⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 com.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	$OpenBSD: com.c,v 1.50 1999/08/08 16:28:17 niklas Exp $	*//*	$NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $	*//*- * Copyright (c) 1993, 1994, 1995, 1996 *	Charles M. Hannum.  All rights reserved. * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)com.c	7.5 (Berkeley) 5/16/91 *//* * COM driver, based on HP dca driver * uses National Semiconductor NS16450/NS16550AF UART */#include <sys/param.h>/*#include <sys/systm.h>#include <sys/ioctl.h>*/#include <sys/tty.h>/*#include <sys/proc.h>#include <sys/user.h>*/#include <sys/conf.h>/*#include <sys/file.h>#include <sys/uio.h>#include <sys/kernel.h>#include <sys/syslog.h> */#include <sys/types.h>#include <sys/device.h>/*#include <sys/vnode.h>*/#include <machine/bus.h>#include <machine/intr.h>#include <dev/ic/comreg.h>#include <dev/ic/comvar.h>#include <dev/ic/ns16550reg.h>#define	com_lcr	com_cfcr#ifndef NULL#define NULL	0#endif/* XXX: These belong elsewhere */cdev_decl(com);bdev_decl(com);static u_char tiocm_xxx2mcr __P((int));/* * XXX the following two cfattach structs should be different, and possibly * XXX elsewhere. */int	comprobe __P((struct device *, void *, void *));void	comattach __P((struct device *, struct device *, void *));void	compwroff __P((struct com_softc *));void	com_raisedtr __P((void *));#if NCOM_ISAstruct cfattach com_isa_ca = {	sizeof(struct com_softc), comprobe, comattach};#endif#if NCOM_ISAPNPstruct cfattach com_isapnp_ca = {	sizeof(struct com_softc), comprobe, comattach};#endifstruct cfdriver com_cd = {	NULL, "com", DV_TTY};#ifndef CONSPEED#define	CONSPEED B9600#endif#ifdef COMCONSOLEint	comdefaultrate = CONSPEED;		/* XXX why set default? */#elseint	comdefaultrate = TTYDEF_SPEED;#endifint	comconsaddr;int	comconsinit;int	comconsattached;bus_space_tag_t comconsiot;bus_space_handle_t comconsioh;tcflag_t comconscflag = TTYDEF_CFLAG;int	commajor;int	comsopen = 0;int	comevents = 0;#ifdef KGDB#include <machine/remote-sl.h>extern int kgdb_dev;extern int kgdb_rate;extern int kgdb_debug_init;#endif#define	DEVUNIT(x)	(minor(x) & 0x7f)#define	DEVCUA(x)	(minor(x) & 0x80)/* Macros to clear/set/test flags. */#define	SET(t, f)	(t) |= (f)#define	CLR(t, f)	(t) &= ~(f)#define	ISSET(t, f)	((t) & (f))/* Macros for determining bus type. */#if NCOM_ISA#define IS_ISA(parent) \    (strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa") == 0)#else#define IS_ISA(parent) 0#endif#if NCOM_ISAPNP#define IS_ISAPNP(parent) \    (strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isapnp") == 0)#else#define IS_ISAPNP(parent) 0#endifintcomspeed(speed)	long speed;{#define	divrnd(n, q)	(((n)*2/(q)+1)/2)	/* divide and round off */	int x, err;	if (speed == 0)		return 0;	if (speed < 0)		return -1;	x = divrnd((COM_FREQ / 16), speed);	if (x <= 0)		return -1;	err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;	if (err < 0)		err = -err;	if (err > COM_TOLERANCE)		return -1;	return x;#undef	divrnd(n, q)}intcomprobe1(iot, ioh)	bus_space_tag_t iot;	bus_space_handle_t ioh;{	int i, k;	/* force access to id reg */	bus_space_write_1(iot, ioh, com_lcr, 0);	bus_space_write_1(iot, ioh, com_iir, 0);	for (i = 0; i < 32; i++) {	    k = bus_space_read_1(iot, ioh, com_iir);	    if (k & 0x38) {		bus_space_read_1(iot, ioh, com_data); /* cleanup */	    } else		break;	}	if (i >= 32) 	    return 0;	return 1;}intcomprobe(parent, match, aux)	struct device *parent;	void *match, *aux;{	bus_space_tag_t iot;	bus_space_handle_t ioh;	int iobase, needioh;	int rv = 1;	/*	 * XXX should be broken out into functions for isa probe and	 * XXX for commulti probe, with a helper function that contains	 * XXX most of the interesting stuff.	 */#if NCOM_ISA || NCOM_ISAPNP	if (IS_ISA(parent) || IS_ISAPNP(parent)) {		struct isa_attach_args *ia = aux;		iot = ia->ia_iot;		iobase = ia->ia_iobase;		if (IS_ISAPNP(parent)) {			ioh = ia->ia_ioh;			needioh = 0;		} else			needioh = 1;	} else#endif		return(0);			/* This cannot happen */	/* if it's in use as console, it's there. */	if (iobase == comconsaddr && !comconsattached)		goto out;	if (needioh && bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {		rv = 0;		goto out;	}	rv = comprobe1(iot, ioh);	if (needioh)		bus_space_unmap(iot, ioh, COM_NPORTS);out:#if NCOM_ISA	if (rv && IS_ISA(parent)) {		struct isa_attach_args *ia = aux;		ia->ia_iosize = COM_NPORTS;		ia->ia_msize = 0;	}#endif	return (rv);}voidcomattach(parent, self, aux)	struct device *parent, *self;	void *aux;{	struct com_softc *sc = (void *)self;	int iobase, irq;	bus_space_tag_t iot;	bus_space_handle_t ioh;	u_int8_t lcr;	/*	 * XXX should be broken out into functions for isa attach and	 * XXX for commulti attach, with a helper function that contains	 * XXX most of the interesting stuff.	 */	sc->sc_hwflags = 0;	sc->sc_swflags = 0;#if NCOM_ISA || NCOM_ISAPNP	if (IS_ISA(parent) || IS_ISAPNP(parent)) {		struct isa_attach_args *ia = aux;		/*		 * We're living on an isa.		 */		iobase = ia->ia_iobase;		iot = ia->ia_iot;		if (IS_ISAPNP(parent)) {			/* No console support! */			ioh = ia->ia_ioh;		} else {	       		if (iobase != comconsaddr) {				if (bus_space_map(iot, iobase, COM_NPORTS, 0,				    &ioh))					panic("comattach: io mapping failed");			} else				ioh = comconsioh;		}		irq = ia->ia_irq;	} else#endif		panic("comattach: impossible");	sc->sc_iot = iot;	sc->sc_ioh = ioh;	sc->sc_iobase = iobase;	if (iobase == comconsaddr) {		comconsattached = 1;		/* 		 * Need to reset baud rate, etc. of next print so reset		 * comconsinit.  Also make sure console is always "hardwired".		 */		delay(1000);			/* wait for output to finish */		comconsinit = 0;		SET(sc->sc_hwflags, COM_HW_CONSOLE);		SET(sc->sc_swflags, COM_SW_SOFTCAR);	}	/*	 * Probe for all known forms of UART.	 */	lcr = bus_space_read_1(iot, ioh, com_lcr);	bus_space_write_1(iot, ioh, com_lcr, 0xbf);	bus_space_write_1(iot, ioh, com_efr, 0);	bus_space_write_1(iot, ioh, com_lcr, 0);	bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE);	delay(100);	switch(bus_space_read_1(iot, ioh, com_iir) >> 6) {	case 0:		sc->sc_uarttype = COM_UART_16450;		break;	case 2:		sc->sc_uarttype = COM_UART_16550;		break;	case 3:		sc->sc_uarttype = COM_UART_16550A;		break;	default:		sc->sc_uarttype = COM_UART_UNKNOWN;		break;	}	if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for ST16650s */		bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);		if (bus_space_read_1(iot, ioh, com_efr) == 0) {			sc->sc_uarttype = COM_UART_ST16650;		} else {			bus_space_write_1(iot, ioh, com_lcr, 0xbf);			if (bus_space_read_1(iot, ioh, com_efr) == 0)				sc->sc_uarttype = COM_UART_ST16650V2;		}	}	bus_space_write_1(iot, ioh, com_lcr, lcr);	if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */		u_int8_t scr0, scr1, scr2;		scr0 = bus_space_read_1(iot, ioh, com_scratch);		bus_space_write_1(iot, ioh, com_scratch, 0xa5);		scr1 = bus_space_read_1(iot, ioh, com_scratch);		bus_space_write_1(iot, ioh, com_scratch, 0x5a);		scr2 = bus_space_read_1(iot, ioh, com_scratch);		bus_space_write_1(iot, ioh, com_scratch, scr0);		if ((scr1 != 0xa5) || (scr2 != 0x5a))			sc->sc_uarttype = COM_UART_8250;	}	/*	 * Print UART type and initialize ourself.	 */	sc->sc_fifolen = 1;	/* default */	switch (sc->sc_uarttype) {	case COM_UART_UNKNOWN:		printf(": unknown uart\n");		break;	case COM_UART_8250:		printf(": ns8250, no fifo\n");		break;	case COM_UART_16450:		printf(": ns16450, no fifo\n");		break;	case COM_UART_16550:		printf(": ns16550, no working fifo\n");		break;	case COM_UART_16550A:		printf(": ns16550a, 16 byte fifo\n");		SET(sc->sc_hwflags, COM_HW_FIFO);		sc->sc_fifolen = 16;		break;	case COM_UART_ST16650:		printf(": st16650, no working fifo\n");		break;	case COM_UART_ST16650V2:		printf(": st16650, 32 byte fifo\n");		SET(sc->sc_hwflags, COM_HW_FIFO);		sc->sc_fifolen = 32;		break;	case COM_UART_TI16750:		printf(": ti16750, 64 byte fifo\n");		SET(sc->sc_hwflags, COM_HW_FIFO);		sc->sc_fifolen = 64;		break;	default:		panic("comattach: bad fifo type");	}	/* clear and disable fifo */	bus_space_write_1(iot, ioh, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST);	(void)bus_space_read_1(iot, ioh, com_data);	bus_space_write_1(iot, ioh, com_fifo, 0);	/* disable interrupts */	bus_space_write_1(iot, ioh, com_ier, 0);	bus_space_write_1(iot, ioh, com_mcr, 0);	/* XXX maybe move up some? */	if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))		printf("%s: console\n", sc->sc_dev.dv_xname);	/*	 * If there are no enable/disable functions, assume the device	 * is always enabled.	 */	if (!sc->enable)		sc->enabled = 1;}intcom_detach(self, flags)	struct device *self;	int flags;{	struct com_softc *sc = (struct com_softc *)self;	int maj, mn;	/* locate the major number */	for (maj = 0; maj < nchrdev; maj++)		if (cdevsw[maj].d_open == comopen)			break;	/* Nuke the vnodes for any open instances. */	mn = self->dv_unit;	vdevgone(maj, mn, mn, VCHR);	/* XXX a symbolic constant for the cua bit would be nicer. */	mn |= 0x80;	vdevgone(maj, mn, mn, VCHR);	/* Detach and free the tty. */	if (sc->sc_tty) {		tty_detach(sc->sc_tty);		ttyfree(sc->sc_tty);	}	untimeout(compoll, NULL);	untimeout(com_raisedtr, sc);	untimeout(comdiag, sc);	return (0);}intcom_activate(self, act)	struct device *self;	enum devact act;{	struct com_softc *sc = (struct com_softc *)self;	int s, rv = 0;	s = spltty();	switch (act) {	case DVACT_ACTIVATE:		rv = EOPNOTSUPP;		break;	case DVACT_DEACTIVATE:		if (sc->sc_hwflags & COM_HW_CONSOLE) {			rv = EBUSY;			break;		}		if (sc->disable != NULL && sc->enabled != 0) {			(*sc->disable)(sc);			sc->enabled = 0;		}		break;	}	splx(s);	return (rv);}intcomopen(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	int unit = DEVUNIT(dev);	struct com_softc *sc;	bus_space_tag_t iot;	bus_space_handle_t ioh;	struct tty *tp;	int s;	int error = 0; 	if (unit >= com_cd.cd_ndevs)		return ENXIO;	sc = com_cd.cd_devs[unit];	if (!sc)		return ENXIO;	s = spltty();	if (!sc->sc_tty) {		tp = sc->sc_tty = ttymalloc();		tty_attach(tp);	} else		tp = sc->sc_tty;	splx(s);	tp->t_oproc = comstart;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -