Date: Sat, 7 Dec 2002 22:03:28 -0800 (PST) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 22057 for review Message-ID: <200212080603.gB863SUB027812@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=22057 Change 22057 by marcel@marcel_nfs on 2002/12/07 22:03:04 Axe my way through sio(4). First of all, split the console specific part from the generic driver part and move it to sio_cons.c. We need to take a different approach if we want to achieve platform independence when probing for the console. We simply rely on MD code (in sio_machdep.c) to provide us with whatever we need to make a console work. We still want to do some trivial checking, but we cannot assume anything. Specificly, we should not mess with the current operational state if we're not damned sure it can not harm. In a more fleshed out implementation we can use flags for it or whetever we like. Secondly, "steal" the sio patch from tmm (pointed out to my by peter) to replace most of the outb with sio_setreg. Nuke any references to anything that smells like ioports. I intend to use the same thick here as I used with the pcivga driver. The console will use a static com_s and we reuse that when we finally discover the device on some bus. Note that it's probably useful if we turn sio_machdep.c into a more generic cn_machdep.c. This would allow us to add whatever cn related MD code to support MI code in the discovery and setup of low-level consoles. The sio driver is very likely in a bad shape now... Affected files ... .. //depot/projects/ia64/sys/conf/files.ia64#24 edit .. //depot/projects/ia64/sys/dev/sio/sio.c#19 edit .. //depot/projects/ia64/sys/dev/sio/sio_cons.c#1 add .. //depot/projects/ia64/sys/dev/sio/siovar.h#5 edit .. //depot/projects/ia64/sys/ia64/ia64/sio_machdep.c#1 add Differences ... ==== //depot/projects/ia64/sys/conf/files.ia64#24 (text+ko) ==== @@ -58,6 +58,7 @@ ia64/ia64/sal.c standard ia64/ia64/sapic.c standard ia64/ia64/setjmp.s standard +ia64/ia64/sio_machdep.c optional sio ia64/ia64/ski.c optional ski ia64/ia64/support.s standard ia64/ia64/ssc.c optional ski @@ -88,6 +89,7 @@ dev/kbd/kbd.c optional sc dev/kbd/kbd.c optional ukbd dev/sio/sio.c optional sio +dev/sio/sio_cons.c optional sio dev/sio/sio_isa.c optional sio isa dev/syscons/schistory.c optional sc dev/syscons/scmouse.c optional sc ==== //depot/projects/ia64/sys/dev/sio/sio.c#19 (text+ko) ==== @@ -35,8 +35,6 @@ * from: i386/isa sio.c,v 1.234 */ -#include "opt_comconsole.h" -#include "opt_compat.h" #include "opt_ddb.h" #include "opt_sio.h" @@ -122,11 +120,6 @@ #define COM_NOSCR(flags) ((flags) & 0x100000) #define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24) -#define sio_getreg(com, off) \ - (bus_space_read_1((com)->bst, (com)->bsh, (off))) -#define sio_setreg(com, off, value) \ - (bus_space_write_1((com)->bst, (com)->bsh, (off), (value))) - /* * com state bits. * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher @@ -162,119 +155,13 @@ "tty-level buffer overflow", }; -#define CE_NTYPES 3 #define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) /* types. XXX - should be elsewhere */ +#ifdef COM_ESP typedef u_int Port_t; /* hardware port */ -typedef u_char bool_t; /* boolean */ - -/* queue of linear buffers */ -struct lbq { - u_char *l_head; /* next char to process */ - u_char *l_tail; /* one past the last char to process */ - struct lbq *l_next; /* next in queue */ - bool_t l_queued; /* nonzero if queued */ -}; - -/* com device structure */ -struct com_s { - u_int flags; /* Copy isa device flags */ - u_char state; /* miscellaneous flag bits */ - bool_t active_out; /* nonzero if the callout device is open */ - u_char cfcr_image; /* copy of value written to CFCR */ -#ifdef COM_ESP - 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 */ - bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */ - bool_t loses_outints; /* nonzero if device loses output interrupts */ - u_char mcr_image; /* copy of value written to MCR */ -#ifdef COM_MULTIPORT - bool_t multiport; /* is this unit part of a multiport device? */ -#endif /* COM_MULTIPORT */ - bool_t no_irq; /* nonzero if irq is not attached */ - bool_t gone; /* hardware disappeared */ - bool_t poll; /* nonzero if polling is required */ - bool_t poll_output; /* nonzero if polling for output is required */ - int unit; /* unit number */ - 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() */ - - /* - * The high level of the driver never reads status registers directly - * because there would be too many side effects to handle conveniently. - * Instead, it reads copies of the registers stored here by the - * interrupt handler. - */ - u_char last_modem_status; /* last MSR read by intr handler */ - u_char prev_modem_status; /* last MSR handled by high level */ - - u_char hotchar; /* ldisc-specific char to be handled ASAP */ - u_char *ibuf; /* start of input buffer */ - u_char *ibufend; /* end of input buffer */ - u_char *ibufold; /* old input buffer, to be freed */ - u_char *ihighwater; /* threshold in input buffer */ - u_char *iptr; /* next free spot in input buffer */ - int ibufsize; /* size of ibuf (not include error bytes) */ - int ierroff; /* offset of error bytes in ibuf */ - - struct lbq obufq; /* head of queue of output buffers */ - struct lbq obufs[2]; /* output buffers */ - - bus_space_tag_t bst; - bus_space_handle_t bsh; - - Port_t data_port; /* i/o ports */ -#ifdef COM_ESP - Port_t esp_port; #endif - Port_t int_id_port; - Port_t modem_ctl_port; - Port_t line_status_port; - Port_t modem_status_port; - Port_t intr_ctl_port; /* Ports of IIR register */ - - struct tty *tp; /* cross reference */ - - /* Initial state. */ - struct termios it_in; /* should be in struct tty */ - struct termios it_out; - - /* Lock state. */ - struct termios lt_in; /* should be in struct tty */ - struct termios lt_out; - - bool_t do_timestamp; - bool_t do_dcd_timestamp; - struct timeval timestamp; - struct timeval dcd_timestamp; - struct pps_state pps; - - u_long bytes_in; /* statistics */ - u_long bytes_out; - u_int delta_error_counts[CE_NTYPES]; - u_long error_counts[CE_NTYPES]; - - u_long rclk; - - struct resource *irqres; - struct resource *ioportres; - int ioportspace; - void *cookie; - dev_t devs[6]; - /* - * Data area for output buffers. Someday we should build the output - * buffer queue without copying data. - */ - u_char obuf1[256]; - u_char obuf2[256]; -}; - #ifdef COM_ESP static int espattach(struct com_s *com, Port_t esp_port); #endif @@ -338,10 +225,6 @@ SYSCTL_UINT(_machdep, OID_AUTO, gdbspeed, CTLFLAG_RW, &gdbdefaultrate, GDBSPEED, ""); static u_int com_events; /* input chars + weighted output completions */ -static Port_t siocniobase; -static int siocnunit = -1; -static Port_t siogdbiobase; -static int siogdbunit = -1; static void *sio_slow_ih; static void *sio_fast_ih; static int sio_timeout; @@ -484,12 +367,8 @@ bool_t failures[10]; int fn; device_t idev; - Port_t iobase; - intrmask_t irqmap[4]; - intrmask_t irqs; u_char mcr_image; int result; - u_long xirq; u_int flags = device_get_flags(dev); int rid, space; struct resource *port; @@ -501,6 +380,7 @@ 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); @@ -519,37 +399,6 @@ atomic_store_rel_int(&sio_inited, 2); } -#if 0 - /* - * XXX this is broken - when we are first called, there are no - * previously configured IO ports. We could hard code - * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse. - * This code has been doing nothing since the conversion since - * "count" is zero the first time around. - */ - if (!already_init) { - /* - * Turn off MCR_IENABLE for all likely serial ports. An unused - * port with its MCR_IENABLE gate open will inhibit interrupts - * from any used port that shares the interrupt vector. - * XXX the gate enable is elsewhere for some multiports. - */ - device_t *devs; - int count, i, xioport; - - devclass_get_devices(sio_devclass, &devs, &count); - for (i = 0; i < count; i++) { - xdev = devs[i]; - if (device_is_enabled(xdev) && - bus_get_resource(xdev, space, 0, &xioport, - NULL) == 0) - outb(xioport + com_mcr, 0); - } - free(devs, M_TEMP); - already_init = TRUE; - } -#endif - if (COM_LLCONSOLE(flags)) { printf("sio%d: reserved for low-level i/o\n", device_get_unit(dev)); @@ -571,9 +420,6 @@ mcr_image = MCR_IENABLE; #ifdef COM_MULTIPORT if (COM_ISMULTIPORT(flags)) { - Port_t xiobase; - u_long io; - idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags)); if (idev == NULL) { printf("sio%d: master device %d not configured\n", @@ -581,14 +427,15 @@ idev = dev; } if (!COM_NOTAST4(flags)) { - if (bus_get_resource(idev, space, 0, &io, - NULL) == 0) { - xiobase = io; + struct com_s icom; + + icom = (struct com_s *) device_get_softc(idev); + if (icom != NULL) { if (bus_get_resource(idev, SYS_RES_IRQ, 0, NULL, NULL) == 0) - outb(xiobase + com_scr, 0x80); + sio_setreg(icom, com_scr, 0x80); else - outb(xiobase + com_scr, 0); + sio_setreg(icom, com_scr, 0); } mcr_image = 0; } @@ -598,7 +445,6 @@ mcr_image = 0; bzero(failures, sizeof failures); - iobase = rman_get_start(port); /* * We don't want to get actual interrupts, just masked ones. @@ -619,9 +465,7 @@ * 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 (iobase == siocniobase) - DELAY((16 + 1) * 1000000 / (comdefaultrate / 10)); - else { + 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); @@ -639,7 +483,6 @@ sio_setreg(com, com_mcr, mcr_image); sio_setreg(com, com_ier, 0); DELAY(1000); /* XXX */ - irqmap[0] = isa_irq_pending(); /* * Attempt to set loopback mode so that we can send a null byte @@ -715,7 +558,7 @@ sio_setreg(com, com_cfcr, CFCR_8BITS); mtx_unlock_spin(&sio_lock); bus_release_resource(dev, space, rid, port); - if (iobase == siocniobase) + if (com->is_console) result = 0; if (result != 0) { device_set_softc(dev, NULL); @@ -737,10 +580,8 @@ 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 */ - irqmap[1] = isa_irq_pending(); failures[4] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_TXRDY; DELAY(1000); /* XXX */ - irqmap[2] = isa_irq_pending(); failures[6] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND; /* @@ -756,26 +597,10 @@ sio_setreg(com, com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */ failures[7] = sio_getreg(com, com_ier); DELAY(1000); /* XXX */ - irqmap[3] = isa_irq_pending(); failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND; mtx_unlock_spin(&sio_lock); - irqs = irqmap[1] & ~irqmap[0]; - if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 && - ((1 << xirq) & irqs) == 0) { - printf( - "sio%d: configured irq %ld not in bitmap of probed irqs %#x\n", - device_get_unit(dev), xirq, irqs); - printf( - "sio%d: port may not be enabled\n", - device_get_unit(dev)); - } - if (bootverbose) - printf("sio%d: irq maps: %#x %#x %#x %#x\n", - device_get_unit(dev), - irqmap[0], irqmap[1], irqmap[2], irqmap[3]); - result = 0; for (fn = 0; fn < sizeof failures; ++fn) if (failures[fn]) { @@ -792,7 +617,7 @@ break; } bus_release_resource(dev, space, rid, port); - if (iobase == siocniobase) + if (com->is_console) result = 0; if (result != 0) { device_set_softc(dev, NULL); @@ -876,7 +701,6 @@ #ifdef COM_ESP Port_t *espp; #endif - Port_t iobase; int minorbase; int unit; u_int flags; @@ -891,7 +715,6 @@ if (!port) return (ENXIO); - iobase = rman_get_start(port); unit = device_get_unit(dev); com = device_get_softc(dev); flags = device_get_flags(dev); @@ -924,13 +747,7 @@ com->obufs[0].l_head = com->obuf1; com->obufs[1].l_head = com->obuf2; - com->data_port = iobase + com_data; - com->int_id_port = iobase + com_iir; - com->modem_ctl_port = iobase + com_mcr; - com->mcr_image = inb(com->modem_ctl_port); - com->line_status_port = iobase + com_lsr; - com->modem_status_port = iobase + com_msr; - com->intr_ctl_port = iobase + com_ier; + com->mcr_image = sio_getreg(com, com_mcr); if (rclk == 0) rclk = DEFAULT_RCLK; @@ -963,7 +780,7 @@ * Leave i/o resources allocated if this is a `cn'-level * console, so that other devices can't snarf them. */ - if (iobase != siocniobase) + if (!com->is_console) bus_release_resource(dev, space, rid, port); return (ENOMEM); } @@ -995,7 +812,7 @@ sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH); DELAY(100); com->st16650a = 0; - switch (inb(com->int_id_port) & IIR_FIFO_MASK) { + switch (sio_getreg(com, com_iir) & IIR_FIFO_MASK) { case FIFO_RX_LOW: printf(" 16450"); break; @@ -1134,7 +951,7 @@ * on the console. */ if (ret == 0 && unit == comconsole) - outb(siocniobase + com_ier, IER_ERXRDY | IER_ERLS | + sio_setreg(com, com_ier, IER_ERXRDY | IER_ERLS | IER_EMSC); #endif } @@ -1262,11 +1079,11 @@ * for about 85 usec instead of 100. */ DELAY(50); - if (!(inb(com->line_status_port) & LSR_RXRDY)) + if (!(sio_getreg(com, com_lsr) & LSR_RXRDY)) break; sio_setreg(com, com_fifo, 0); DELAY(50); - (void) inb(com->data_port); + (void) sio_getreg(com, com_data); } if (i == 500) { error = EIO; @@ -1275,15 +1092,15 @@ } mtx_lock_spin(&sio_lock); - (void) inb(com->line_status_port); - (void) inb(com->data_port); + (void) sio_getreg(com, com_lsr); + (void) sio_getreg(com, com_data); com->prev_modem_status = com->last_modem_status - = inb(com->modem_status_port); + = sio_getreg(com, com_msr); if (COM_IIR_TXRDYBUG(com->flags)) { - outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS + sio_setreg(com, com_ier, IER_ERXRDY | IER_ERLS | IER_EMSC); } else { - outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY + sio_setreg(com, com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC); } mtx_unlock_spin(&sio_lock); @@ -1496,7 +1313,7 @@ s = spltty(); if (com->state & CS_BUSY) com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */ - else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY)) + else if ((sio_getreg(com, com_lsr) & (LSR_TSRE | LSR_TXRDY)) == (LSR_TSRE | LSR_TXRDY)) { com->tp->t_state &= ~TS_BUSY; ttwwakeup(com->tp); @@ -1636,7 +1453,7 @@ */ if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) && !(tp->t_state & TS_TBLOCK)) - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); + sio_setreg(com, com_mcr, com->mcr_image |= MCR_RTS); } static void @@ -1673,7 +1490,7 @@ */ if (com != NULL && !com->gone - && (inb(com->int_id_port) & IIR_IMASK) + && (sio_getreg(com, com_iir) & IIR_IMASK) != IIR_NOPEND) { siointr1(com); possibly_more_intrs = TRUE; @@ -1729,19 +1546,19 @@ u_char int_ctl; u_char int_ctl_new; - int_ctl = inb(com->intr_ctl_port); + int_ctl = sio_getreg(com, com_ier); int_ctl_new = int_ctl; while (!com->gone) { if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) { - modem_status = inb(com->modem_status_port); + modem_status = sio_getreg(com, com_msr); if ((modem_status ^ com->last_modem_status) & MSR_DCD) { pps_capture(&com->pps); pps_event(&com->pps, (modem_status & MSR_DCD) ? PPS_CAPTUREASSERT : PPS_CAPTURECLEAR); } } - line_status = inb(com->line_status_port); + line_status = sio_getreg(com, com_lsr); /* input event? (check first to help avoid overruns) */ while (line_status & LSR_RCV_MASK) { @@ -1749,7 +1566,7 @@ if (!(line_status & LSR_RXRDY)) recv_data = 0; else - recv_data = inb(com->data_port); + recv_data = sio_getreg(com, com_data); #if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER) /* * Solaris implements a new BREAK which is initiated @@ -1836,7 +1653,7 @@ com->iptr = ++ioptr; if (ioptr == com->ihighwater && com->state & CS_RTS_IFLOW) - outb(com->modem_ctl_port, + sio_setreg(com, com_mcr, com->mcr_image &= ~MCR_RTS); if (line_status & LSR_OE) CE_RECORD(com, CE_OVERRUN); @@ -1846,11 +1663,11 @@ * "& 0x7F" is to avoid the gcc-1.40 generating a slow * jump from the top of the loop to here */ - line_status = inb(com->line_status_port) & 0x7F; + line_status = sio_getreg(com, com_lsr) & 0x7F; } /* modem status change? (always check before doing output) */ - modem_status = inb(com->modem_status_port); + modem_status = sio_getreg(com, com_msr); if (modem_status != com->last_modem_status) { if (com->do_dcd_timestamp && !(com->last_modem_status & MSR_DCD) @@ -1891,10 +1708,10 @@ ocount = com->tx_fifo_size; com->bytes_out += ocount; do - outb(com->data_port, *ioptr++); + sio_setreg(com, com_data, *ioptr++); while (--ocount != 0); } else { - outb(com->data_port, *ioptr++); + sio_setreg(com, com_data, *ioptr++); ++com->bytes_out; if (com->unit == siotsunit) { nanouptime(&siots[siotso]); @@ -1931,13 +1748,13 @@ } } if (COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) { - outb(com->intr_ctl_port, int_ctl_new); + sio_setreg(com, com_ier, int_ctl_new); } } /* finished? */ #ifndef COM_MULTIPORT - if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND) + if ((sio_getreg(com, com_iir) & IIR_IMASK) == IIR_NOPEND) #endif /* COM_MULTIPORT */ return; } @@ -2311,7 +2128,7 @@ * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS * on here, since comstart() won't do it later. */ - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); + sio_setreg(com, com_mcr, com->mcr_image |= MCR_RTS); if (com->st16650a) { sio_setreg(com, com_cfcr, 0xbf); sio_setreg(com, com_fifo, @@ -2460,11 +2277,11 @@ com->state |= CS_TTGO; if (tp->t_state & TS_TBLOCK) { if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW) - outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); + sio_setreg(com, com_mcr, com->mcr_image &= ~MCR_RTS); } else { if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater && com->state & CS_RTS_IFLOW) - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); + sio_setreg(com, com_mcr, com->mcr_image |= MCR_RTS); } mtx_unlock_spin(&sio_lock); if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { @@ -2609,14 +2426,14 @@ mtx_lock_spin(&sio_lock); switch (how) { case DMSET: - outb(com->modem_ctl_port, + sio_setreg(com, com_mcr, com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE)); break; case DMBIS: - outb(com->modem_ctl_port, com->mcr_image |= mcr); + sio_setreg(com, com_mcr, com->mcr_image |= mcr); break; case DMBIC: - outb(com->modem_ctl_port, com->mcr_image &= ~mcr); + sio_setreg(com, com_mcr, com->mcr_image &= ~mcr); break; } mtx_unlock_spin(&sio_lock); @@ -2733,536 +2550,3 @@ tp->t_state &= ~TS_CAN_BYPASS_L_RINT; com->hotchar = linesw[tp->t_line].l_hotchar; } - -/* - * Following are all routines needed for SIO to act as console - */ -#include <sys/cons.h> - -struct siocnstate { - u_char dlbl; - u_char dlbh; - u_char ier; - u_char cfcr; - u_char mcr; -}; - -#ifndef __alpha__ -static speed_t siocngetspeed(Port_t, u_long rclk); -#endif -static void siocnclose(struct siocnstate *sp, Port_t iobase); -static void siocnopen(struct siocnstate *sp, Port_t iobase, int speed); -static void siocntxwait(Port_t iobase); - -#ifdef __alpha__ -int siocnattach(int port, int speed); -int siogdbattach(int port, int speed); -int siogdbgetc(void); -void siogdbputc(int c); -#else -static cn_probe_t siocnprobe; -static cn_init_t siocninit; -static cn_term_t siocnterm; -#endif -static cn_checkc_t siocncheckc; -static cn_getc_t siocngetc; -static cn_putc_t siocnputc; - -#ifndef __alpha__ -CONS_DRIVER(sio, siocnprobe, siocninit, siocnterm, siocngetc, siocncheckc, - siocnputc, NULL); -#endif - -/* To get the GDB related variables */ -#if DDB > 0 -#include <ddb/ddb.h> -#endif - -static void -siocntxwait(iobase) - Port_t iobase; -{ - int timo; - - /* - * Wait for any pending transmission to finish. Required to avoid - * the UART lockup bug when the speed is changed, and for normal - * transmits. - */ - timo = 100000; - while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY)) - != (LSR_TSRE | LSR_TXRDY) && --timo != 0) - ; -} - -#ifndef __alpha__ - -/* - * Read the serial port specified and try to figure out what speed - * it's currently running at. We're assuming the serial port has - * been initialized and is basicly idle. This routine is only intended - * to be run at system startup. - * - * If the value read from the serial port doesn't make sense, return 0. - */ - -static speed_t -siocngetspeed(iobase, rclk) - Port_t iobase; - u_long rclk; -{ - u_int divisor; - u_char dlbh; - u_char dlbl; - u_char cfcr; - - cfcr = inb(iobase + com_cfcr); - outb(iobase + com_cfcr, CFCR_DLAB | cfcr); - - dlbl = inb(iobase + com_dlbl); - dlbh = inb(iobase + com_dlbh); - - outb(iobase + com_cfcr, cfcr); - - divisor = dlbh << 8 | dlbl; - - /* XXX there should be more sanity checking. */ - if (divisor == 0) - return (CONSPEED); - return (rclk / (16UL * divisor)); -} - -#endif - -static void -siocnopen(sp, iobase, speed) - struct siocnstate *sp; - Port_t iobase; - int speed; -{ - u_int divisor; - u_char dlbh; - u_char dlbl; - - /* - * Save all the device control registers except the fifo register - * and set our default ones (cs8 -parenb speed=comdefaultrate). - * We can't save the fifo register since it is read-only. - */ - sp->ier = inb(iobase + com_ier); - outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */ - siocntxwait(iobase); - sp->cfcr = inb(iobase + com_cfcr); - outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); - sp->dlbl = inb(iobase + com_dlbl); - sp->dlbh = inb(iobase + com_dlbh); - /* - * Only set the divisor registers if they would change, since on - * some 16550 incompatibles (Startech), setting them clears the - * data input register. This also reduces the effects of the - * UMC8669F bug. - */ - divisor = siodivisor(comdefaultrclk, speed); - dlbl = divisor & 0xFF; - if (sp->dlbl != dlbl) - outb(iobase + com_dlbl, dlbl); - dlbh = divisor >> 8; - if (sp->dlbh != dlbh) - outb(iobase + com_dlbh, dlbh); - outb(iobase + com_cfcr, CFCR_8BITS); - sp->mcr = inb(iobase + com_mcr); - /* - * We don't want interrupts, but must be careful not to "disable" - * them by clearing the MCR_IENABLE bit, since that might cause - * an interrupt by floating the IRQ line. - */ - outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS); -} - -static void -siocnclose(sp, iobase) - struct siocnstate *sp; - Port_t iobase; -{ - /* - * Restore the device control registers. - */ - siocntxwait(iobase); - outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS); - if (sp->dlbl != inb(iobase + com_dlbl)) - outb(iobase + com_dlbl, sp->dlbl); - if (sp->dlbh != inb(iobase + com_dlbh)) - outb(iobase + com_dlbh, sp->dlbh); - outb(iobase + com_cfcr, sp->cfcr); - /* - * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them. - */ - outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS); - outb(iobase + com_ier, sp->ier); -} - -#ifndef __alpha__ - -static void -siocnprobe(cp) - struct consdev *cp; -{ - speed_t boot_speed; - u_char cfcr; - u_int divisor; - int s, unit; - struct siocnstate sp; - - /* - * Find our first enabled console, if any. If it is a high-level - * console device, then initialize it and return successfully. - * If it is a low-level console device, then initialize it and - * return unsuccessfully. It must be initialized in both cases - * for early use by console drivers and debuggers. Initializing - * the hardware is not necessary in all cases, since the i/o - * routines initialize it on the fly, but it is necessary if - * input might arrive while the hardware is switched back to an - * uninitialized state. We can't handle multiple console devices - * yet because our low-level routines don't take a device arg. - * We trust the user to set the console flags properly so that we - * don't need to probe. - */ - cp->cn_pri = CN_DEAD; - - for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */ - int flags; - int disabled; - if (resource_int_value("sio", unit, "disabled", &disabled) == 0) { - if (disabled) - continue; - } - if (resource_int_value("sio", unit, "flags", &flags)) - continue; - if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) { - int port; - Port_t iobase; - - if (resource_int_value("sio", unit, "port", &port)) - continue; - iobase = port; - s = spltty(); - if (boothowto & RB_SERIAL) { - boot_speed = - siocngetspeed(iobase, comdefaultrclk); - if (boot_speed) - comdefaultrate = boot_speed; - } - - /* - * Initialize the divisor latch. We can't rely on - * siocnopen() to do this the first time, since it - * avoids writing to the latch if the latch appears - * to have the correct value. Also, if we didn't - * just read the speed from the hardware, then we - * need to set the speed in hardware so that - * switching it later is null. - */ - cfcr = inb(iobase + com_cfcr); - outb(iobase + com_cfcr, CFCR_DLAB | cfcr); - divisor = siodivisor(comdefaultrclk, comdefaultrate); - outb(iobase + com_dlbl, divisor & 0xff); - outb(iobase + com_dlbh, divisor >> 8); - outb(iobase + com_cfcr, cfcr); - - siocnopen(&sp, iobase, comdefaultrate); - - splx(s); - if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) { - cp->cn_dev = makedev(CDEV_MAJOR, unit); - cp->cn_pri = COM_FORCECONSOLE(flags) - || boothowto & RB_SERIAL - ? CN_REMOTE : CN_NORMAL; - siocniobase = iobase; - siocnunit = unit; - } - if (COM_DEBUGGER(flags)) { - printf("sio%d: gdb debugging port\n", unit); - siogdbiobase = iobase; - siogdbunit = unit; -#if DDB > 0 - gdbdev = makedev(CDEV_MAJOR, unit); - gdb_getc = siocngetc; - gdb_putc = siocnputc; -#endif - } - } - } -#ifdef __i386__ -#if DDB > 0 - /* - * XXX Ugly Compatability. - * If no gdb port has been specified, set it to be the console - * as some configuration files don't specify the gdb port. - */ - if (gdbdev == NODEV && (boothowto & RB_GDB)) { - printf("Warning: no GDB port specified. Defaulting to sio%d.\n", - siocnunit); - printf("Set flag 0x80 on desired GDB port in your\n"); - printf("configuration file (currently sio only).\n"); - siogdbiobase = siocniobase; - siogdbunit = siocnunit; - gdbdev = makedev(CDEV_MAJOR, siocnunit); - gdb_getc = siocngetc; - gdb_putc = siocnputc; - } -#endif -#endif -} - -static void -siocninit(cp) - struct consdev *cp; -{ - comconsole = DEV_TO_UNIT(cp->cn_dev); -} - -static void -siocnterm(cp) - struct consdev *cp; -{ - comconsole = -1; -} - -#endif - -#ifdef __alpha__ - -CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc, NULL); - -int -siocnattach(port, speed) - int port; - int speed; -{ - int s; - u_char cfcr; - u_int divisor; - struct siocnstate sp; - int unit = 0; /* XXX random value! */ - - siocniobase = port; - siocnunit = unit; - comdefaultrate = speed; - sio_consdev.cn_pri = CN_NORMAL; - sio_consdev.cn_dev = makedev(CDEV_MAJOR, unit); - - s = spltty(); - - /* - * Initialize the divisor latch. We can't rely on - * siocnopen() to do this the first time, since it - * avoids writing to the latch if the latch appears - * to have the correct value. Also, if we didn't - * just read the speed from the hardware, then we - * need to set the speed in hardware so that - * switching it later is null. - */ - cfcr = inb(siocniobase + com_cfcr); - outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr); - divisor = siodivisor(comdefaultrclk, comdefaultrate); - outb(siocniobase + com_dlbl, divisor & 0xff); - outb(siocniobase + com_dlbh, divisor >> 8); - outb(siocniobase + com_cfcr, cfcr); - - siocnopen(&sp, siocniobase, comdefaultrate); - splx(s); - - cnadd(&sio_consdev); - return (0); -} - -int -siogdbattach(port, speed) - int port; - int speed; -{ - int s; - u_char cfcr; - u_int divisor; - struct siocnstate sp; - int unit = 1; /* XXX random value! */ - - siogdbiobase = port; - gdbdefaultrate = speed; - - printf("sio%d: gdb debugging port\n", unit); - siogdbunit = unit; -#if DDB > 0 - gdbdev = makedev(CDEV_MAJOR, unit); - gdb_getc = siocngetc; - gdb_putc = siocnputc; -#endif - >>> 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?200212080603.gB863SUB027812>