Date: Sun, 15 Dec 2002 16:27:39 -0800 (PST) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 22362 for review Message-ID: <200212160027.gBG0Rd7V041052@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=22362 Change 22362 by marcel@marcel_nfs on 2002/12/15 16:27:12 This too starts to look like a NextGen project: o Remove inclusion of <machine/sio_pio.h>, o Reorganize struct com_s so that I can see what I've touched and/or used in new or modified code, o Introduce regshft to allow interleaved multi-IO cards. Shamelessly taken from Linux. Not used ATM, o Remove inclusion of <dev/ic/ns16550.h>. The register names are inconsistent and the comments are wrong. Instead, add register names to sioreg.h, o Add sioprobe1() to do some non-destructive checking to make sure we have something at the given address and that it has a high chance of actually being an UART. Used by siocnprobe() and can (should) be used by sioprobe() as well. o Flesh-out struct consdata to include regshft, data, stop and parity. We get that from the HCDP table so we'd better use it. This will probably grow in the future, o Rewrite sio_machdep.c so that it's easier to add alternatives to the HCDP table. We can use the ACPI defined SPCR table and even plain old hints. Fix a bug where we were testing if the HCDP table address was non-NULL after making the address virtual. The latter makes it a tautology. We now have a serial console on the HP box. This was mostly not working because of the inclusion of bus_pio.h, but we had (and have) some nasty TR mapping issues as well. The removal of the pio include also helped the probed Diva (multi-IO board), but I haven't tried it actually... There's one gotcha: We never find the UART we use as the console, so we never have a device_t for it. Currently cp->cn_dev is explicitly set to NULL so that we segfault when we try to go multi-user. There are a couple of ways to approach this problem: o Allow cn_dev to be NULL and ignore the consdev when we try to open /dev/console, but this may cause the situation when there's no consdev left, o Fake a device_t, like we do for syscons. This seems to be the safest solution. More on this subject later... Affected files ... .. //depot/projects/ia64/sys/dev/sio/sio.c#21 edit .. //depot/projects/ia64/sys/dev/sio/sio_cons.c#3 edit .. //depot/projects/ia64/sys/dev/sio/sioreg.h#5 edit .. //depot/projects/ia64/sys/dev/sio/siovar.h#7 edit .. //depot/projects/ia64/sys/ia64/ia64/sio_machdep.c#3 edit Differences ... ==== //depot/projects/ia64/sys/dev/sio/sio.c#21 (text+ko) ==== @@ -64,7 +64,6 @@ #include <sys/sysctl.h> #include <sys/syslog.h> #include <sys/tty.h> -#include <machine/bus_pio.h> #include <machine/bus.h> #include <sys/rman.h> #include <sys/timepps.h> @@ -81,7 +80,6 @@ #ifdef COM_ESP #include <dev/ic/esp.h> #endif -#include <dev/ic/ns16550.h> #define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ @@ -216,13 +214,15 @@ /* kqfilter */ ttykqfilter, }; -int comconsole = -1; -static volatile speed_t comdefaultrate = CONSPEED; -static u_long comdefaultrclk = DEFAULT_RCLK; +volatile speed_t comdefaultrate = CONSPEED; + +u_long comdefaultrclk = DEFAULT_RCLK; SYSCTL_ULONG(_machdep, OID_AUTO, conrclk, CTLFLAG_RW, &comdefaultrclk, 0, ""); -static speed_t gdbdefaultrate = GDBSPEED; -SYSCTL_UINT(_machdep, OID_AUTO, gdbspeed, CTLFLAG_RW, - &gdbdefaultrate, GDBSPEED, ""); + +static speed_t gdbdefaultrate = GDBSPEED; +SYSCTL_ULONG(_machdep, OID_AUTO, gdbspeed, CTLFLAG_RW, &gdbdefaultrate, + GDBSPEED, ""); + static u_int com_events; /* input chars + weighted output completions */ static void *sio_slow_ih; static void *sio_fast_ih; @@ -265,13 +265,10 @@ comdefaultrate = newspeed; - if (comconsole < 0) /* serial console not selected? */ + com = &sio_console; + if (com->consdev == NULL) return (0); - com = com_addr(comconsole); - if (com == NULL) - return (ENXIO); - /* * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX * (note, the lock rates really are boolean -- if non-zero, disallow @@ -300,8 +297,66 @@ 0, 0, sysctl_machdep_comdefaultrate, "I", ""); /* TUNABLE_INT("machdep.conspeed", &comdefaultrate); */ -#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit)) -#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit)) +u_int +siodivisor(u_long rclk, u_long speed) +{ + long actual_speed; + u_int divisor; + int error; + + if (speed == 0 || speed > (ULONG_MAX - 1) / 8) + return (0); + divisor = (rclk / (8UL * speed) + 1) / 2; + if (divisor == 0 || divisor >= 65536) + return (0); + actual_speed = rclk / (16UL * divisor); + + /* 10 times error in percent: */ + error = ((actual_speed - (long)speed) * 2000 / (long)speed + 1) / 2; + + /* 3.0% maximum error tolerance: */ + if (error < -30 || error > 30) + return (0); + + return (divisor); +} + +/* + * Do some non-destructive (for this device that is) tests + * to make sure we have something that looks like an UART. + * + */ +int sioprobe1(struct com_s *sc) +{ + u_char lcr, val; + + lcr = sio_getreg(sc, com_lcr); + sio_setreg(sc, com_lcr, lcr & ~LCR_DLAB); + + /* Check known 0 bits that don't depend on DLAB. */ + val = sio_getreg(sc, com_iir); + if (val & 0x30) + goto fail; + val = sio_getreg(sc, com_mcr); + if (val & 0xe0) + goto fail; + + /* Check known 0 bits that depend on ~DLAB. */ + val = sio_getreg(sc, com_ier); + if (val & 0xf0) + goto fail; + + /* XXX we can do more. */ + + sio_setreg(sc, com_lcr, lcr); + /* XXX barrier */ + return (0); + + fail: + sio_setreg(sc, com_lcr, lcr); + /* XXX barrier */ + return (ENXIO); +} /* * Unload the driver and clear the table. @@ -379,25 +434,35 @@ if (!port) return (ENXIO); - /* XXX - Grab static struct setup by siocnprobe. */ - com = malloc(sizeof(*com), M_DEVBUF, M_NOWAIT | M_ZERO); - if (com == NULL) - return (ENOMEM); + if (rman_get_bustag(port) != sio_console.bst || + rman_get_bushandle(port) != sio_console.bsh) { + com = malloc(sizeof(*com), M_DEVBUF, M_NOWAIT | M_ZERO); + if (com == NULL) + return (ENOMEM); + bzero(com, sizeof *com); + com->bst = rman_get_bustag(port); + com->bsh = rman_get_bushandle(port); + if (rclk == 0) + rclk = DEFAULT_RCLK; + com->rclk = rclk; + } else + com = &sio_console; + device_set_softc(dev, com); - com->bst = rman_get_bustag(port); - com->bsh = rman_get_bushandle(port); - if (rclk == 0) - rclk = DEFAULT_RCLK; - com->rclk = rclk; while (sio_inited != 2) if (atomic_cmpset_int(&sio_inited, 0, 1)) { mtx_init(&sio_lock, sio_driver_name, NULL, - (comconsole != -1) ? + (sio_console.consdev != NULL) ? MTX_SPIN | MTX_QUIET : MTX_SPIN); atomic_store_rel_int(&sio_inited, 2); } + if (com->consdev != NULL) { + bus_release_resource(dev, space, rid, port); + return (0); + } + if (COM_LLCONSOLE(flags)) { printf("sio%d: reserved for low-level i/o\n", device_get_unit(dev)); @@ -464,14 +529,12 @@ * XXX what about the UART bug avoided by waiting in comparam()? * We don't want to to wait long enough to drain at 2 bps. */ - if (!com->is_console) { - sio_setreg(com, com_cfcr, CFCR_DLAB | CFCR_8BITS); - divisor = siodivisor(rclk, SIO_TEST_SPEED); - sio_setreg(com, com_dlbl, divisor & 0xff); - sio_setreg(com, com_dlbh, divisor >> 8); - sio_setreg(com, com_cfcr, CFCR_8BITS); - DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); - } + sio_setreg(com, com_lcr, LCR_DLAB | LCR_8BITS); + divisor = siodivisor(rclk, SIO_TEST_SPEED); + sio_setreg(com, com_dlbl, divisor & 0xff); + sio_setreg(com, com_dlbh, divisor >> 8); + sio_setreg(com, com_lcr, LCR_8BITS); + DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10)); /* * Enable the interrupt gate and disable device interupts. This @@ -518,13 +581,13 @@ */ /* EXTRA DELAY? */ sio_setreg(com, com_mcr, mcr_image); - + /* * It seems my Xircom CBEM56G Cardbus modem wants to be reset * to 8 bits *again*, or else probe test 0 will fail. * gwk@sgi.com, 4/19/2001 */ - sio_setreg(com, com_cfcr, CFCR_8BITS); + sio_setreg(com, com_lcr, LCR_8BITS); /* * Some pcmcia cards have the "TXRDY bug", so we check everyone @@ -554,11 +617,9 @@ CLR_FLAG(dev, COM_C_IIR_TXRDYBUG); } sio_setreg(com, com_ier, 0); - sio_setreg(com, com_cfcr, CFCR_8BITS); + sio_setreg(com, com_lcr, LCR_8BITS); mtx_unlock_spin(&sio_lock); bus_release_resource(dev, space, rid, port); - if (com->is_console) - result = 0; if (result != 0) { device_set_softc(dev, NULL); free(com, M_DEVBUF); @@ -575,7 +636,7 @@ * o the interrupt goes away when the IIR in the UART is read. */ /* EXTRA DELAY? */ - failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS; + failures[0] = sio_getreg(com, com_lcr) - LCR_8BITS; failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY; failures[2] = sio_getreg(com, com_mcr) - mcr_image; DELAY(10000); /* Some internal modems need this time */ @@ -593,7 +654,7 @@ * and gives a (masked) interrupt as soon as the gate is closed.) */ sio_setreg(com, com_ier, 0); - sio_setreg(com, com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */ + sio_setreg(com, com_lcr, LCR_8BITS); /* dummy to avoid bus echo */ failures[7] = sio_getreg(com, com_ier); DELAY(1000); /* XXX */ failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND; @@ -615,9 +676,8 @@ } break; } + bus_release_resource(dev, space, rid, port); - if (com->is_console) - result = 0; if (result != 0) { device_set_softc(dev, NULL); free(com, M_DEVBUF); @@ -722,8 +782,8 @@ sio_numunits = unit + 1; /* * sioprobe() has initialized the device registers as follows: - * o cfcr = CFCR_8BITS. - * It is most important that CFCR_DLAB is off, so that the + * o cfcr = LCR_8BITS. + * It is most important that LCR_DLAB is off, so that the * data port is not hidden when we enable interrupts. * o ier = 0. * Interrupts are only enabled when the line is open. @@ -732,13 +792,12 @@ * Keeping MCR_DTR and MCR_RTS off might stop the external * device from sending before we are ready. */ - bzero(com, sizeof *com); com->unit = unit; com->ioportres = port; com->ioportspace = space; com->bst = rman_get_bustag(port); com->bsh = rman_get_bushandle(port); - com->cfcr_image = CFCR_8BITS; + com->cfcr_image = LCR_8BITS; com->dtr_wait = 3 * hz; com->loses_outints = COM_LOSESOUTINTS(flags) != 0; com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0; @@ -762,7 +821,7 @@ com->it_in.c_oflag = 0; com->it_in.c_cflag = TTYDEF_CFLAG; com->it_in.c_lflag = 0; - if (unit == comconsole) { + if (com->consdev != NULL) { com->it_in.c_iflag = TTYDEF_IFLAG; com->it_in.c_oflag = TTYDEF_OFLAG; com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; @@ -779,7 +838,7 @@ * Leave i/o resources allocated if this is a `cn'-level * console, so that other devices can't snarf them. */ - if (!com->is_console) + if (com->consdev == NULL) bus_release_resource(dev, space, rid, port); return (ENOMEM); } @@ -790,7 +849,6 @@ /* attempt to determine UART type */ printf("sio%d: type", unit); - if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags) && !COM_NOSCR(flags)) { u_char scr; @@ -808,20 +866,20 @@ goto determined_type; } } - sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); + sio_setreg(com, com_fcr, FCR_ENABLE | FCR_RX_HIGH); DELAY(100); com->st16650a = 0; switch (sio_getreg(com, com_iir) & IIR_FIFO_MASK) { - case FIFO_RX_LOW: + case FCR_RX_LOW: printf(" 16450"); break; - case FIFO_RX_MEDL: + case FCR_RX_MEDL: printf(" 16450?"); break; - case FIFO_RX_MEDH: + case FCR_RX_MEDH: printf(" 16550?"); break; - case FIFO_RX_HIGH: + case FCR_RX_HIGH: if (COM_NOFIFO(flags)) { printf(" 16550A fifo disabled"); } else { @@ -878,7 +936,7 @@ outb(com->esp_port + ESP_CMD2, LOBYTE(512)); } #endif /* COM_ESP */ - sio_setreg(com, com_fifo, 0); + sio_setreg(com, com_fcr, 0); determined_type: ; #ifdef COM_MULTIPORT @@ -896,7 +954,7 @@ SYS_RES_IRQ, 0, NULL, NULL) != 0); } #endif /* COM_MULTIPORT */ - if (unit == comconsole) + if (com->consdev != NULL) printf(", console"); if (COM_IIR_TXRDYBUG(flags)) printf(" with a bogus IIR_TXRDY register"); @@ -949,7 +1007,7 @@ * Enable interrupts for early break-to-debugger support * on the console. */ - if (ret == 0 && unit == comconsole) + if (ret == 0 && com->consdev != NULL) sio_setreg(com, com_ier, IER_ERXRDY | IER_ERLS | IER_EMSC); #endif @@ -1063,9 +1121,9 @@ * input. */ for (i = 0; i < 500; i++) { - sio_setreg(com, com_fifo, - FIFO_RCV_RST | FIFO_XMT_RST - | com->fifo_image); + sio_setreg(com, com_fcr, + FCR_RCV_RST | FCR_XMT_RST + | com->reg_fcr); /* * XXX the delays are for superstitious * historical reasons. It must be less than @@ -1080,7 +1138,7 @@ DELAY(50); if (!(sio_getreg(com, com_lsr) & LSR_RXRDY)) break; - sio_setreg(com, com_fifo, 0); + sio_setreg(com, com_fcr, 0); DELAY(50); (void) sio_getreg(com, com_data); } @@ -1198,7 +1256,7 @@ com->do_timestamp = FALSE; com->do_dcd_timestamp = FALSE; com->pps.ppsparam.mode = 0; - sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); + sio_setreg(com, com_lcr, com->cfcr_image &= ~LCR_SBREAK); tp = com->tp; #if defined(DDB) && (defined(BREAK_TO_DEBUGGER) || \ @@ -1208,7 +1266,7 @@ * console. This allows us to detect break-to-debugger events * while the console device is closed. */ - if (com->unit != comconsole) + if (com->consdev == NULL) #endif { sio_setreg(com, com_ier, 0); @@ -1237,7 +1295,7 @@ * reboots. Some BIOSes fail to detect 16550s when the * fifos are enabled. */ - sio_setreg(com, com_fifo, 0); + sio_setreg(com, com_fcr, 0); } com->active_out = FALSE; wakeup(&com->active_out); @@ -1287,7 +1345,7 @@ * is not the console. In that situation we don't need/want the X * server taking over the console. */ - if (constty != NULL && unit == comconsole) + if (constty != NULL && com->consdev != NULL) constty = NULL; return ((*linesw[com->tp->t_line].l_write)(com->tp, uio, flag)); } @@ -1322,30 +1380,6 @@ splx(s); } -u_int -siodivisor(u_long rclk, u_long speed) -{ - long actual_speed; - u_int divisor; - int error; - - if (speed == 0 || speed > (ULONG_MAX - 1) / 8) - return (0); - divisor = (rclk / (8UL * speed) + 1) / 2; - if (divisor == 0 || divisor >= 65536) - return (0); - actual_speed = rclk / (16UL * divisor); - - /* 10 times error in percent: */ - error = ((actual_speed - (long)speed) * 2000 / (long)speed + 1) / 2; - - /* 3.0% maximum error tolerance: */ - if (error < -30 || error > 30) - return (0); - - return (divisor); -} - static void siodtrwakeup(chan) void *chan; @@ -1575,7 +1609,7 @@ #define KEY_CR 13 /* CR '\r' */ #define KEY_TILDE 126 /* ~ */ - if (com->unit == comconsole) { + if (com->consdev != NULL) { static int brk_state1 = 0, brk_state2 = 0; if (recv_data == KEY_CR) { brk_state1 = recv_data; @@ -1612,7 +1646,7 @@ */ if (line_status & LSR_BI) { #if defined(DDB) && defined(BREAK_TO_DEBUGGER) - if (com->unit == comconsole) { + if (com->consdev != NULL) { breakpoint(); goto cont; } @@ -1856,10 +1890,10 @@ } switch (cmd) { case TIOCSBRK: - sio_setreg(com, com_cfcr, com->cfcr_image |= CFCR_SBREAK); + sio_setreg(com, com_lcr, com->cfcr_image |= LCR_SBREAK); break; case TIOCCBRK: - sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); + sio_setreg(com, com_lcr, com->cfcr_image &= ~LCR_SBREAK); break; case TIOCSDTR: (void)commctl(com, TIOCM_DTR, DMBIS); @@ -2029,25 +2063,25 @@ cflag = t->c_cflag; switch (cflag & CSIZE) { case CS5: - cfcr = CFCR_5BITS; + cfcr = LCR_5BITS; break; case CS6: - cfcr = CFCR_6BITS; + cfcr = LCR_6BITS; break; case CS7: - cfcr = CFCR_7BITS; + cfcr = LCR_7BITS; break; default: - cfcr = CFCR_8BITS; + cfcr = LCR_8BITS; break; } if (cflag & PARENB) { - cfcr |= CFCR_PENAB; + cfcr |= LCR_PENAB; if (!(cflag & PARODD)) - cfcr |= CFCR_PEVEN; + cfcr |= LCR_PEVEN; } if (cflag & CSTOPB) - cfcr |= CFCR_STOPB; + cfcr |= LCR_STOPB; if (com->hasfifo && divisor != 0) { /* @@ -2063,9 +2097,9 @@ * interrupt disablement times in other parts of the system, * without producing silo overflow errors. */ - com->fifo_image = com->unit == siotsunit ? 0 + com->reg_fcr = com->unit == siotsunit ? 0 : t->c_ospeed <= 4800 - ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH; + ? FCR_ENABLE : FCR_ENABLE | FCR_RX_MEDH; #ifdef COM_ESP /* * The Hayes ESP card needs the fifo DMA mode bit set @@ -2073,9 +2107,9 @@ * for each character received. */ if (com->esp) - com->fifo_image |= FIFO_DMA_MODE; + com->reg_fcr |= FCR_DMA_MODE; #endif - sio_setreg(com, com_fifo, com->fifo_image); + sio_setreg(com, com_fcr, com->reg_fcr); } /* @@ -2086,7 +2120,7 @@ (void) siosetwater(com, t->c_ispeed); if (divisor != 0) { - sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB); + sio_setreg(com, com_lcr, cfcr | LCR_DLAB); /* * Only set the divisor registers if they would change, * since on some 16550 incompatibles (UMC8669F), setting @@ -2101,16 +2135,16 @@ sio_setreg(com, com_dlbh, dlbh); } - sio_setreg(com, com_cfcr, com->cfcr_image = cfcr); + sio_setreg(com, com_lcr, com->cfcr_image = cfcr); if (!(tp->t_state & TS_TTSTOP)) com->state |= CS_TTGO; if (cflag & CRTS_IFLOW) { if (com->st16650a) { - sio_setreg(com, com_cfcr, 0xbf); - sio_setreg(com, com_fifo, - sio_getreg(com, com_fifo) | 0x40); + sio_setreg(com, com_lcr, 0xbf); + sio_setreg(com, com_fcr, + sio_getreg(com, com_fcr) | 0x40); } com->state |= CS_RTS_IFLOW; /* @@ -2127,9 +2161,9 @@ */ sio_setreg(com, com_mcr, com->mcr_image |= MCR_RTS); if (com->st16650a) { - sio_setreg(com, com_cfcr, 0xbf); - sio_setreg(com, com_fifo, - sio_getreg(com, com_fifo) & ~0x40); + sio_setreg(com, com_lcr, 0xbf); + sio_setreg(com, com_fcr, + sio_getreg(com, com_fcr) & ~0x40); } } @@ -2146,19 +2180,19 @@ if (!(com->last_modem_status & MSR_CTS)) com->state &= ~CS_ODEVREADY; if (com->st16650a) { - sio_setreg(com, com_cfcr, 0xbf); - sio_setreg(com, com_fifo, - sio_getreg(com, com_fifo) | 0x80); + sio_setreg(com, com_lcr, 0xbf); + sio_setreg(com, com_fcr, + sio_getreg(com, com_fcr) | 0x80); } } else { if (com->st16650a) { - sio_setreg(com, com_cfcr, 0xbf); - sio_setreg(com, com_fifo, - sio_getreg(com, com_fifo) & ~0x80); + sio_setreg(com, com_lcr, 0xbf); + sio_setreg(com, com_fcr, + sio_getreg(com, com_fcr) & ~0x80); } } - sio_setreg(com, com_cfcr, com->cfcr_image); + sio_setreg(com, com_lcr, com->cfcr_image); /* XXX shouldn't call functions while intrs are disabled. */ disc_optim(tp, t, com); @@ -2357,8 +2391,8 @@ /* XXX avoid h/w bug. */ if (!com->esp) #endif - sio_setreg(com, com_fifo, - FIFO_XMT_RST | com->fifo_image); + sio_setreg(com, com_fcr, + FCR_XMT_RST | com->reg_fcr); com->obufs[0].l_queued = FALSE; com->obufs[1].l_queued = FALSE; if (com->state & CS_ODONE) @@ -2372,8 +2406,8 @@ /* XXX avoid h/w bug. */ if (!com->esp) #endif - sio_setreg(com, com_fifo, - FIFO_RCV_RST | com->fifo_image); + sio_setreg(com, com_fcr, + FCR_RCV_RST | com->reg_fcr); com_events -= (com->iptr - com->ibuf); com->iptr = com->ibuf; } ==== //depot/projects/ia64/sys/dev/sio/sio_cons.c#3 (text+ko) ==== @@ -54,7 +54,6 @@ #include <sys/sysctl.h> #include <sys/syslog.h> #include <sys/tty.h> -#include <machine/bus_pio.h> #include <machine/bus.h> #include <sys/rman.h> #include <sys/timepps.h> @@ -68,8 +67,6 @@ #include <dev/sio/sioreg.h> #include <dev/sio/siovar.h> -#include <dev/ic/ns16550.h> - #include <sys/cons.h> /* @@ -84,81 +81,137 @@ static cn_term_t siocnterm; static cn_getc_t siocngetc; static cn_checkc_t siocncheckc; -static cn_putc_t siocnputc; +cn_putc_t siocnputc; CONS_DRIVER(sio, siocnprobe, siocninit, siocnterm, siocngetc, siocncheckc, siocnputc, NULL); +/* Sloppily translate databits, stopbits and parity to LCR register bits. */ +static u_char +siocnlcr(struct sio_consdata *cd) +{ + u_char lcr; + + lcr = 0; + + if (cd->databits >= 8) + lcr |= LCR_8BITS; + else if (cd->databits == 7) + lcr |= LCR_7BITS; + else if (cd->databits == 6) + lcr |= LCR_6BITS; + else + lcr |= LCR_5BITS; + + if (cd->stopbits > 1) + lcr |= LCR_STOPB; + + /* XXX set parity */ + + return (lcr); +} + static void siocnprobe(struct consdev *cp) { struct sio_consdata cd; u_int divisor; - u_char cfcr; + u_char lcr; bzero(&sio_console, sizeof(sio_console)); + cp->cn_dev = NULL; /* How do we know. */ cp->cn_pri = CN_DEAD; if (sio_get_console(&cd) != 0) return; - sio_console.bst = cd.type; - sio_console.bsh = cd.addr; - sio_console.rclk = cd.rclk; + /* Minimum fields needed for rudimentary checks. */ + sio_console.bst = cd.bst; + sio_console.bsh = cd.bsh; + sio_console.regshft = cd.regshft; + + if (sioprobe1(&sio_console)) + return; + + sio_console.rclk = (cd.rclk != 0) ? cd.rclk : DEFAULT_RCLK; - cfcr = sio_getreg(&sio_console, com_cfcr); - sio_setreg(&sio_console, com_cfcr, CFCR_DLAB | cfcr); + /* Set DL and LCR. */ + lcr = siocnlcr(&cd); + sio_setreg(&sio_console, com_lcr, lcr | LCR_DLAB); + /* XXX barrier */ if (cd.baud != 0) { divisor = siodivisor(cd.rclk, cd.baud); - sio_setreg(&sio_console, com_dlbl, divisor & 0xff); - sio_setreg(&sio_console, com_dlbh, divisor >> 8); - } else { - divisor = sio_getreg(&sio_console, com_dlbh); - divisor = (divisor << 8) | sio_getreg(&sio_console, com_dlbl); - /* XXX there should be more sanity checking. */ - cd.baud = (divisor != 0) - ? cd.rclk / (16UL * divisor) : CONSPEED; - } - sio_setreg(&sio_console, com_cfcr, cfcr); + sio_setdreg(&sio_console, com_dl, divisor); + } else + divisor = sio_getdreg(&sio_console, com_dl); + /* XXX barrier */ + sio_setreg(&sio_console, com_lcr, lcr); + /* XXX barrier */ - cp->cn_dev = makedev(28, 0); cp->cn_pri = (boothowto & RB_SERIAL) ? CN_REMOTE : CN_NORMAL; } static void siocninit(struct consdev *cp) { - u_char mcr; + u_char fcr, iir; + /* Disable all interrupt sources. */ sio_setreg(&sio_console, com_ier, 0); - sio_setreg(&sio_console, com_cfcr, CFCR_8BITS); - mcr = sio_getreg(&sio_console, com_mcr); - sio_setreg(&sio_console, com_mcr, - (mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); - (void)sio_getreg(&sio_console, com_iir); - sio_console.is_console = 1; + /* XXX barrier */ + + /* Set FCR. */ + fcr = FCR_RX_MEDH | FCR_ENABLE; + sio_setreg(&sio_console, com_fcr, fcr); + /* XXX barrier */ + sio_setreg(&sio_console, com_fcr, fcr | FCR_RCV_RST | FCR_XMT_RST); + /* XXX barrier */ + sio_console.reg_fcr = fcr; + + /* Set MCR. */ + sio_setreg(&sio_console, com_mcr, MCR_IENABLE | MCR_DTR); + /* XXX barrier */ + + /* + * Clear pending interrupts. THRE is cleared by reading IIR. Data + * that may have been received gets lost here. + */ + iir = sio_getreg(&sio_console, com_iir); + while ((iir & IIR_NOPEND) == 0) { + iir &= IIR_IMASK; + if (iir == IIR_RLS) + sio_getreg(&sio_console, com_lsr); + else if (iir == IIR_RXRDY || iir == IIR_RXTOUT) + sio_getreg(&sio_console, com_rbr); + else if (iir == IIR_MLSC) + sio_getreg(&sio_console, com_msr); + /* XXX barrier */ + iir = sio_getreg(&sio_console, com_iir); + } + /* XXX barrier */ + + /* It's official... */ + sio_console.consdev = cp; } static void siocnterm(struct consdev *cp) { - sio_console.is_console = 0; + /* XXX - What to do here? */ } -static void +void siocnputc(dev_t dev, int c) { int s, to; s = spltty(); to = 100000; - while ((sio_getreg(&sio_console, com_lsr) & (LSR_TSRE | LSR_TXRDY)) - != (LSR_TSRE | LSR_TXRDY) && --to != 0) + while ((sio_getreg(&sio_console, com_lsr) & LSR_TSRE) == 0 && --to) ; sio_setreg(&sio_console, com_data, c); - /* XXX bus_space_barrier */ splx(s); } ==== //depot/projects/ia64/sys/dev/sio/sioreg.h#5 (text+ko) ==== @@ -37,6 +37,22 @@ /* Receiver clock frequency for "standard" pc serial ports. */ #define DEFAULT_RCLK 1843200 +/* Register names. */ +#define com_data 0 /* Data. */ +#define com_rbr com_data /* Receiver Buffer Reg. (R). */ +#define com_thr com_data /* Transmitter Holding Reg. (W). */ +#define com_dlbl 0 /* Divisor Latch (LSB). */ +#define com_dlbh 1 /* Divisor Latch (MSB). */ +#define com_dl com_dlbl /* Divisor Latch (16-bit I/O). */ +#define com_ier 1 /* Interrupt Enable Reg. */ +#define com_iir 2 /* Interrupt Identification Reg. (R) */ +#define com_fcr 2 /* FIFO Control Reg. (W) */ +#define com_lcr 3 /* Line Control Reg. */ +#define com_mcr 4 /* MODEM Control Reg. */ +#define com_lsr 5 /* Line Status Reg. */ +#define com_msr 6 /* MODEM Status Reg. */ +#define com_scr 7 /* Scratch Reg. (16450 and up). */ + /* interrupt enable register */ #define IER_ERXRDY 0x1 #define IER_ETXRDY 0x2 @@ -54,28 +70,28 @@ #define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ /* fifo control register */ -#define FIFO_ENABLE 0x01 -#define FIFO_RCV_RST 0x02 -#define FIFO_XMT_RST 0x04 -#define FIFO_DMA_MODE 0x08 -#define FIFO_RX_LOW 0x00 -#define FIFO_RX_MEDL 0x40 -#define FIFO_RX_MEDH 0x80 -#define FIFO_RX_HIGH 0xc0 +#define FCR_ENABLE 0x01 +#define FCR_RCV_RST 0x02 +#define FCR_XMT_RST 0x04 +#define FCR_DMA_MODE 0x08 +#define FCR_RX_LOW 0x00 +#define FCR_RX_MEDL 0x40 +#define FCR_RX_MEDH 0x80 +#define FCR_RX_HIGH 0xc0 /* character format control register */ -#define CFCR_DLAB 0x80 -#define CFCR_SBREAK 0x40 -#define CFCR_PZERO 0x30 -#define CFCR_PONE 0x20 -#define CFCR_PEVEN 0x10 -#define CFCR_PODD 0x00 -#define CFCR_PENAB 0x08 -#define CFCR_STOPB 0x04 -#define CFCR_8BITS 0x03 -#define CFCR_7BITS 0x02 -#define CFCR_6BITS 0x01 -#define CFCR_5BITS 0x00 +#define LCR_DLAB 0x80 +#define LCR_SBREAK 0x40 +#define LCR_PZERO 0x30 +#define LCR_PONE 0x20 +#define LCR_PEVEN 0x10 +#define LCR_PODD 0x00 +#define LCR_PENAB 0x08 +#define LCR_STOPB 0x04 +#define LCR_8BITS 0x03 +#define LCR_7BITS 0x02 +#define LCR_6BITS 0x01 +#define LCR_5BITS 0x00 /* modem control register */ #define MCR_LOOPBACK 0x10 @@ -117,16 +133,16 @@ #endif /* speed to initialize to during chip tests */ -#define SIO_TEST_SPEED 9600 +#define SIO_TEST_SPEED 9600 /* default serial console speed if not set with sysctl or probed from boot */ #ifndef CONSPEED -#define CONSPEED 9600 +#define CONSPEED 9600 #endif /* default serial gdb speed if not set with sysctl or probed from boot */ #ifndef GDBSPEED -#define GDBSPEED CONSPEED +#define GDBSPEED CONSPEED #endif #define IO_COMSIZE 8 /* 8250, 16x50 com controllers */ ==== //depot/projects/ia64/sys/dev/sio/siovar.h#7 (text+ko) ==== @@ -58,12 +58,9 @@ #define GET_IFTYPE(type) (((type) >> 24) & 0x1f) #define SET_IFTYPE(type) ((type) << 24) - -#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit)) -#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit)) #endif /* PC98 */ -#define CE_NTYPES 3 +#define CE_NTYPES 3 typedef u_char bool_t; /* boolean */ @@ -77,6 +74,16 @@ /* com device structure */ struct com_s { + /* SIO/ng blessed. */ + struct consdev *consdev; /* Set for SIO console. */ + int unit; + bus_space_tag_t bst; + bus_space_handle_t bsh; + u_long rclk; /* Receiver clock (bin 9) */ + u_int regshft; /* Interleaved multi-port. */ + u_char reg_fcr; /* Copy of FCR. */ + + /* Old SIO fields. Need auditing. */ u_int flags; /* Copy isa device flags */ u_char state; /* miscellaneous flag bits */ bool_t active_out; /* nonzero if the callout device is open */ @@ -85,11 +92,9 @@ bool_t esp; /* is this unit a hayes esp board? */ #endif u_char extra_state; /* more flag bits, separate for order trick */ - u_char fifo_image; /* copy of value written to FIFO */ bool_t hasfifo; /* nonzero for 16550 UARTs */ >>> TRUNCATED FOR MAIL (1000 lines) <<< To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200212160027.gBG0Rd7V041052>