From owner-p4-projects Tue Dec 24 1:13:10 2002 Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id C99CC37B405; Tue, 24 Dec 2002 01:13:01 -0800 (PST) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 770AE37B401 for ; Tue, 24 Dec 2002 01:13:01 -0800 (PST) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0414843EDC for ; Tue, 24 Dec 2002 01:13:01 -0800 (PST) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.12.6/8.12.6) with ESMTP id gBO9D0fh023346 for ; Tue, 24 Dec 2002 01:13:00 -0800 (PST) (envelope-from marcel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.12.6/8.12.6/Submit) id gBO9D0up023337 for perforce@freebsd.org; Tue, 24 Dec 2002 01:13:00 -0800 (PST) Date: Tue, 24 Dec 2002 01:13:00 -0800 (PST) Message-Id: <200212240913.gBO9D0up023337@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to marcel@freebsd.org using -f From: Marcel Moolenaar Subject: PERFORCE change 22700 for review To: Perforce Change Reviews Sender: owner-p4-projects@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG http://perforce.freebsd.org/chv.cgi?CH=22700 Change 22700 by marcel@marcel_nfs on 2002/12/24 01:12:53 o Initialize the FIFOs at the end of sioprobe. Set loopback prior to enabling the FIFOs so that we don't send garbage and clear the RHR after resetting the FIFOs. With loopback enabled we should be able to determine the size of the FIFO. This we don't do yet. We assume a regular 16 byte FIFO for now. o Move UART identification after FIFO initialization in sioprobe. Only set the device description if it hasn't been set yet. This allows bus specific front-end code to give a more detailed or a more relevant description. A generic ACPI defined UART will now yield: sio0: <16550 or compatible> port 0x3f8-0x3ff irq 4 on acpi0 Recognize the newer 16650 and 16750 based on the FIFO size. We avoid fiddling with the SPR when we know we have a FIFO. This avoids potential problems with multi-port cards. The fiddling is only needed to differentiate between the INS8250 and the NS16450 and both are not current devices. o Don't reinitialize the FIFOs when we open the device. The code appears to be broken and unnecessary and was probably added to work around some weirdness. Keep it, but wrap it inside #if 0 / #endif. Affected files ... .. //depot/projects/ia64/sys/dev/sio/sio.c#26 edit .. //depot/projects/ia64/sys/dev/sio/siovar.h#12 edit Differences ... ==== //depot/projects/ia64/sys/dev/sio/sio.c#26 (text+ko) ==== @@ -263,6 +263,104 @@ 0, 0, sysctl_machdep_comdefaultrate, "I", ""); /* TUNABLE_INT("machdep.conspeed", &comdefaultrate); */ +/* + * Initialize FIFOs. We cannot simple enable the FIFOs because that may cause + * garbage to appear on the wire (non-empty transmit FIFO) or garbage to be + * received (non-empty receive FIFO). The former is prevented by enabling + * loopback prior to enabling the FIFOs. The latter is prevented by ignoring + * any data in the RHR after we have reset the FIFOs. + */ +static void +sioinitfifo(struct com_s *sc) +{ + + sio_setreg(sc, com_mcr, sc->reg_mcr | MCR_LOOPBACK); + /* XXX barrier */ + sio_setreg(sc, com_fcr, FCR_ENABLE); + /* XXX barrier */ + sio_setreg(sc, com_fcr, FCR_ENABLE | FCR_RCV_RST | FCR_XMT_RST); + /* XXX barrier */ + DELAY(100); + sc->reg_fcr = 0; + sc->hasfifo = (sio_getreg(sc, com_iir) & IIR_FIFO_MASK) ? 1 : 0; + if (sc->hasfifo) { + while (sio_getreg(sc, com_lsr) & LSR_RXRDY) { + (void)sio_getreg(sc, com_data); + /* XXX barrier */ + } + sc->reg_fcr = FCR_ENABLE | FCR_RX_HIGH; + sio_setreg(sc, com_mcr, sc->reg_fcr); + /* XXX barrier */ + + sc->fifosize = 16; /* Minimal FIFO size. */ + /* + * XXX count the number of characters we can send before + * we have a receive interrupt. This tells us how large + * the FIFOs are. + */ + } + sio_setreg(sc, com_mcr, sc->reg_mcr); + /* XXX barrier */ +} + +static void +siodescribe(device_t dev, struct com_s *sc) +{ + int has_spr; + u_char spr; + + if (sc->hasfifo) { + /* + * NS16550 or higher. The minimum FIFO size is 16 bytes for + * the NS16550. The ST16C650 has 32 bytes FIFOs and the + * NS16750 has 64 bytes FIFOs. + */ + switch (sc->fifosize) { + case 16: + /* + * XXX Should we try to see if we have a broken + * 16550 or a fixed 16550A? + */ + device_set_desc(dev, "16550 or compatible"); + break; + case 32: + /* + * XXX Should we check that features like automatic + * flow control exist? + */ + device_set_desc(dev, "16650 or compatible"); + break; + case 64: + /* + * XXX Should we check that features like automatic + * flow control exist? + */ + device_set_desc(dev, "16750 or compatible"); + break; + default: + /* XXX Probably not right. */ + device_set_desc(dev, "16550 with non-standard FIFO"); + break; + } + } else { + /* + * NS16450 or lower. Use the Scratch Pad Register (SPR) to + * differentiate the NS16450 from the INS8250. + */ + spr = sio_getreg(sc, com_scr); + sio_setreg(sc, com_scr, ~spr); + /* XXX barrier */ + has_spr = (sio_getreg(sc, com_scr) == ~spr) ? 1 : 0; + /* XXX barrier */ + sio_setreg(sc, com_scr, spr); + /* XXX barrier */ + if (!has_spr) + device_set_desc(dev, "8250 or compatible"); + else + device_set_desc(dev, "16450 or compatible"); + } +} + u_int siodivisor(u_long rclk, u_long speed) { @@ -313,6 +411,8 @@ /* XXX we can do more. */ + sio_setreg(sc, com_ier, 0); + /* XXX barrier */ sio_setreg(sc, com_lcr, lcr); /* XXX barrier */ return (0); @@ -377,13 +477,27 @@ com = (struct com_s *)device_get_softc(dev); - /* Check if we're probing the console. */ + /* Check if we're probing what could be the console. */ if (com->bst == sio_console.bst && com->bsh == sio_console.bsh) { com = &sio_console; device_set_softc(dev, com); - return (0); + } + + if (com->consdev == NULL) { + /* Perform rudimentary sanity checking. */ + if (sioprobe1(com)) + return (ENXIO); + + if (com->rclk == 0) + com->rclk = DEFAULT_RCLK; } + /* Initialize the FIFOs. */ + sioinitfifo(com); + + if (device_get_desc(dev) == NULL) + siodescribe(dev, com); + flags = device_get_flags(dev); if (COM_LLCONSOLE(flags)) { @@ -391,16 +505,6 @@ return (ENXIO); } - /* Perform rudimentary sanity checking. */ - if (sioprobe1(com)) - return (ENXIO); - - if (com->rclk == 0) - com->rclk = DEFAULT_RCLK; - - sio_setreg(com, com_ier, 0); - /* XXX barrier */ - return (0); } @@ -440,7 +544,6 @@ 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; - com->tx_fifo_size = 1; com->obufs[0].l_head = com->obuf1; com->obufs[1].l_head = com->obuf2; @@ -478,80 +581,8 @@ termioschars(&com->it_in); com->it_out = com->it_in; - /* attempt to determine UART type */ - device_printf(dev, "type "); - - if (!COM_IIR_TXRDYBUG(flags) && !COM_NOSCR(flags)) { - u_char scr; - u_char scr1; - u_char scr2; - - scr = sio_getreg(com, com_scr); - /* XXX barrier */ - sio_setreg(com, com_scr, 0xa5); - /* XXX barrier */ - scr1 = sio_getreg(com, com_scr); - /* XXX barrier */ - sio_setreg(com, com_scr, 0x5a); - /* XXX barrier */ - scr2 = sio_getreg(com, com_scr); - /* XXX barrier */ - sio_setreg(com, com_scr, scr); - /* XXX barrier */ - if (scr1 != 0xa5 || scr2 != 0x5a) { - printf("8250"); - goto determined_type; - } - } - - sio_setreg(com, com_fcr, FCR_ENABLE | FCR_RX_HIGH); - /* XXX barrier with SYNC semantics */ - DELAY(100); - - com->st16650a = 0; - switch (sio_getreg(com, com_iir) & IIR_FIFO_MASK) { - case FCR_RX_LOW: - printf("16450"); - break; - case FCR_RX_MEDL: - printf("16450?"); - break; - case FCR_RX_MEDH: - printf("16550?"); - break; - case FCR_RX_HIGH: - if (COM_NOFIFO(flags)) { - printf("16550A fifo disabled"); - } else { - com->hasfifo = TRUE; - if (COM_ST16650A(flags)) { - com->st16650a = 1; - com->tx_fifo_size = 32; - printf("ST16650A"); - } else { - com->tx_fifo_size = COM_FIFOSIZE(flags); - printf("16550A"); - } - } - if (!com->st16650a) { - if (!com->tx_fifo_size) - com->tx_fifo_size = 16; - else - printf("lookalike with %d bytes FIFO", - com->tx_fifo_size); - } - - break; - } - - sio_setreg(com, com_fcr, 0); -determined_type: ; - if (com->consdev != NULL) - printf(", console"); - if (COM_IIR_TXRDYBUG(flags)) - printf(" with a bogus IIR_TXRDY register"); - printf("\n"); + device_printf(dev, "console\n"); if (sio_fast_ih == NULL) { swi_add(&tty_ithd, "tty:sio", siopoll, NULL, SWI_TTY, 0, @@ -697,6 +728,7 @@ --com->wopeners; if (error != 0) goto out; +#if 0 /* * XXX we should goto open_top if comparam() slept. */ @@ -740,6 +772,7 @@ goto out; } } +#endif mtx_lock_spin(&sio_lock); (void) sio_getreg(com, com_lsr); @@ -1291,12 +1324,12 @@ if (line_status & LSR_TXRDY && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { ioptr = com->obufq.l_head; - if (com->tx_fifo_size > 1 && com->unit != siotsunit) { + if (com->hasfifo && com->unit != siotsunit) { u_int ocount; ocount = com->obufq.l_tail - ioptr; - if (ocount > com->tx_fifo_size) - ocount = com->tx_fifo_size; + if (ocount > com->fifosize) + ocount = com->fifosize; com->bytes_out += ocount; do sio_setreg(com, com_data, *ioptr++); ==== //depot/projects/ia64/sys/dev/sio/siovar.h#12 (text+ko) ==== @@ -83,6 +83,8 @@ bus_space_handle_t bsh; u_long rclk; /* Receiver clock (bin 9) */ u_int regshft; /* Interleaved multi-port. */ + u_int hasfifo:1; + u_int fifosize; u_short reg_dl; /* Copy of DL. */ u_char reg_fcr; /* Copy of FCR. */ u_char reg_lcr; /* Copy of LCR. */ @@ -93,7 +95,6 @@ u_char state; /* miscellaneous flag bits */ bool_t active_out; /* nonzero if the callout device is open */ u_char extra_state; /* more flag bits, separate for order trick */ - bool_t hasfifo; /* nonzero for 16550 UARTs */ bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */ bool_t loses_outints; /* nonzero if device loses output interrupts */ bool_t no_irq; /* nonzero if irq is not attached */ @@ -101,7 +102,6 @@ bool_t poll; /* nonzero if polling is required */ bool_t poll_output; /* nonzero if polling for output is required */ int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ - u_int tx_fifo_size; u_int wopeners; /* # processes waiting for DCD in open() */ /* To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message