[BACK]Return to com_subr.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/com_subr.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: com_subr.c,v 1.10 2007/03/20 17:37:34 deraadt Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 1997 - 1999, Jason Downs.  All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     18:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
                     19:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     20:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     21:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
                     22:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  */
                     27: /*-
                     28:  * Copyright (c) 1993, 1994, 1995, 1996
                     29:  *     Charles M. Hannum.  All rights reserved.
                     30:  * Copyright (c) 1991 The Regents of the University of California.
                     31:  * All rights reserved.
                     32:  *
                     33:  * Redistribution and use in source and binary forms, with or without
                     34:  * modification, are permitted provided that the following conditions
                     35:  * are met:
                     36:  * 1. Redistributions of source code must retain the above copyright
                     37:  *    notice, this list of conditions and the following disclaimer.
                     38:  * 2. Redistributions in binary form must reproduce the above copyright
                     39:  *    notice, this list of conditions and the following disclaimer in the
                     40:  *    documentation and/or other materials provided with the distribution.
                     41:  * 3. Neither the name of the University nor the names of its contributors
                     42:  *    may be used to endorse or promote products derived from this software
                     43:  *    without specific prior written permission.
                     44:  *
                     45:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     46:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     47:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     48:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     49:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     50:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     51:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     52:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     53:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     54:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     55:  * SUCH DAMAGE.
                     56:  *
                     57:  *     @(#)com.c       7.5 (Berkeley) 5/16/91
                     58:  */
                     59:
                     60: /*
                     61:  * COM driver, based on HP dca driver
                     62:  * uses National Semiconductor NS16450/NS16550AF UART
                     63:  */
                     64: #include <sys/param.h>
                     65: #include <sys/systm.h>
                     66: #include <sys/kernel.h>
                     67: #include <sys/device.h>
                     68: #include <sys/tty.h>
                     69:
                     70: #include "com.h"
                     71: #ifdef i386
                     72: #include "pccom.h"
                     73: #else
                     74: #define        NPCCOM  0
                     75: #endif
                     76:
                     77: #include <machine/bus.h>
                     78: #if defined(__sparc64__) || !defined(__sparc__)
                     79: #include <machine/intr.h>
                     80: #endif
                     81:
                     82: #if !defined(__sparc__) || defined(__sparc64__)
                     83: #define        COM_CONSOLE
                     84: #include <dev/cons.h>
                     85: #endif
                     86:
                     87: #include <dev/ic/comreg.h>
                     88: #include <dev/ic/ns16550reg.h>
                     89: #define        com_lcr com_cfcr
                     90:
                     91: #if NCOM > 0
                     92: #include <dev/ic/comvar.h>
                     93: #endif
                     94: #if NPCCOM > 0
                     95: #include <i386/isa/pccomvar.h>
                     96: #endif
                     97:
                     98: #ifdef COM_PXA2X0
                     99: #define com_isr 8
                    100: #define ISR_SEND       (ISR_RXPL | ISR_XMODE | ISR_XMITIR)
                    101: #define ISR_RECV       (ISR_RXPL | ISR_XMODE | ISR_RCVEIR)
                    102: #endif
                    103:
                    104: #ifdef COM_CONSOLE
                    105: #include <sys/conf.h>
                    106: cdev_decl(com);
                    107: #endif
                    108:
                    109: void   com_enable_debugport(struct com_softc *);
                    110: void   com_fifo_probe(struct com_softc *);
                    111:
                    112: #if defined(COM_CONSOLE) || defined(KGDB)
                    113: void
                    114: com_enable_debugport(sc)
                    115:        struct com_softc *sc;
                    116: {
                    117:        int s;
                    118:
                    119:        /* Turn on line break interrupt, set carrier. */
                    120:        s = splhigh();
                    121: #ifdef KGDB
                    122:        SET(sc->sc_ier, IER_ERXRDY);
                    123: #ifdef COM_PXA2X0
                    124:        if (sc->sc_uarttype == COM_UART_PXA2X0)
                    125:                sc->sc_ier |= IER_EUART | IER_ERXTOUT;
                    126: #endif
                    127:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
                    128: #endif
                    129:        SET(sc->sc_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);
                    130:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
                    131:
                    132:        splx(s);
                    133: }
                    134: #endif /* COM_CONSOLED || KGDB */
                    135:
                    136: void
                    137: com_attach_subr(sc)
                    138:        struct com_softc *sc;
                    139: {
                    140:        bus_space_tag_t iot = sc->sc_iot;
                    141:        bus_space_handle_t ioh = sc->sc_ioh;
                    142:        u_int8_t lcr;
                    143:
                    144:        sc->sc_ier = 0;
                    145: #ifdef COM_PXA2X0
                    146:        if (sc->sc_uarttype == COM_UART_PXA2X0)
                    147:                sc->sc_ier |= IER_EUART;
                    148: #endif
                    149:
                    150:        /* disable interrupts */
                    151:        bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
                    152:
                    153: #ifdef COM_CONSOLE
                    154:        if (sc->sc_iobase == comconsaddr) {
                    155:                comconsattached = 1;
                    156:                delay(10000);                   /* wait for output to finish */
                    157:                SET(sc->sc_hwflags, COM_HW_CONSOLE);
                    158:                SET(sc->sc_swflags, COM_SW_SOFTCAR);
                    159:        }
                    160: #endif
                    161:
                    162:        /*
                    163:         * Probe for all known forms of UART.
                    164:         */
                    165:        lcr = bus_space_read_1(iot, ioh, com_lcr);
                    166:        bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
                    167:        bus_space_write_1(iot, ioh, com_efr, 0);
                    168:        bus_space_write_1(iot, ioh, com_lcr, 0);
                    169:
                    170:        bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE);
                    171:        delay(100);
                    172:
                    173:        /*
                    174:         * Skip specific probes if attachment code knows it already.
                    175:         */
                    176:        if (sc->sc_uarttype == COM_UART_UNKNOWN)
                    177:                switch (bus_space_read_1(iot, ioh, com_iir) >> 6) {
                    178:                case 0:
                    179:                        sc->sc_uarttype = COM_UART_16450;
                    180:                        break;
                    181:                case 2:
                    182:                        sc->sc_uarttype = COM_UART_16550;
                    183:                        break;
                    184:                case 3:
                    185:                        sc->sc_uarttype = COM_UART_16550A;
                    186:                        break;
                    187:                default:
                    188:                        sc->sc_uarttype = COM_UART_UNKNOWN;
                    189:                        break;
                    190:                }
                    191:
                    192:        if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for ST16650s */
                    193:                bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
                    194:                if (bus_space_read_1(iot, ioh, com_efr) == 0) {
                    195:                        sc->sc_uarttype = COM_UART_ST16650;
                    196:                } else {
                    197:                        bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
                    198:                        if (bus_space_read_1(iot, ioh, com_efr) == 0)
                    199:                                sc->sc_uarttype = COM_UART_ST16650V2;
                    200:                }
                    201:        }
                    202:
                    203: #if NPCCOM > 0 /* until com works with large FIFOs */
                    204:        if (sc->sc_uarttype == COM_UART_ST16650V2) { /* Probe for XR16850s */
                    205:                u_int8_t dlbl, dlbh;
                    206:
                    207:                /* Enable latch access and get the current values. */
                    208:                bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
                    209:                dlbl = bus_space_read_1(iot, ioh, com_dlbl);
                    210:                dlbh = bus_space_read_1(iot, ioh, com_dlbh);
                    211:
                    212:                /* Zero out the latch divisors */
                    213:                bus_space_write_1(iot, ioh, com_dlbl, 0);
                    214:                bus_space_write_1(iot, ioh, com_dlbh, 0);
                    215:
                    216:                if (bus_space_read_1(iot, ioh, com_dlbh) == 0x10) {
                    217:                        sc->sc_uarttype = COM_UART_XR16850;
                    218:                        sc->sc_uartrev = bus_space_read_1(iot, ioh, com_dlbl);
                    219:                }
                    220:
                    221:                /* Reset to original. */
                    222:                bus_space_write_1(iot, ioh, com_dlbl, dlbl);
                    223:                bus_space_write_1(iot, ioh, com_dlbh, dlbh);
                    224:        }
                    225: #endif
                    226:
                    227:        if (sc->sc_uarttype == COM_UART_16550A) { /* Probe for TI16750s */
                    228:                bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
                    229:                bus_space_write_1(iot, ioh, com_fifo,
                    230:                    FIFO_ENABLE | FIFO_ENABLE_64BYTE);
                    231:                if ((bus_space_read_1(iot, ioh, com_iir) >> 5) == 7) {
                    232: #if 0
                    233:                        bus_space_write_1(iot, ioh, com_lcr, 0);
                    234:                        if ((bus_space_read_1(iot, ioh, com_iir) >> 5) == 6)
                    235: #endif
                    236:                                sc->sc_uarttype = COM_UART_TI16750;
                    237:                }
                    238:                bus_space_write_1(iot, ioh, com_fifo, FIFO_ENABLE);
                    239:        }
                    240:
                    241:        /* Reset the LCR (latch access is probably enabled). */
                    242:        bus_space_write_1(iot, ioh, com_lcr, lcr);
                    243:        if (sc->sc_uarttype == COM_UART_16450) { /* Probe for 8250 */
                    244:                u_int8_t scr0, scr1, scr2;
                    245:
                    246:                scr0 = bus_space_read_1(iot, ioh, com_scratch);
                    247:                bus_space_write_1(iot, ioh, com_scratch, 0xa5);
                    248:                scr1 = bus_space_read_1(iot, ioh, com_scratch);
                    249:                bus_space_write_1(iot, ioh, com_scratch, 0x5a);
                    250:                scr2 = bus_space_read_1(iot, ioh, com_scratch);
                    251:                bus_space_write_1(iot, ioh, com_scratch, scr0);
                    252:
                    253:                if ((scr1 != 0xa5) || (scr2 != 0x5a))
                    254:                        sc->sc_uarttype = COM_UART_8250;
                    255:        }
                    256:
                    257:        /*
                    258:         * Print UART type and initialize ourself.
                    259:         */
                    260:        switch (sc->sc_uarttype) {
                    261:        case COM_UART_UNKNOWN:
                    262:                printf(": unknown uart\n");
                    263:                break;
                    264:        case COM_UART_8250:
                    265:                printf(": ns8250, no fifo\n");
                    266:                break;
                    267:        case COM_UART_16450:
                    268:                printf(": ns16450, no fifo\n");
                    269:                break;
                    270:        case COM_UART_16550:
                    271:                printf(": ns16550, no working fifo\n");
                    272:                break;
                    273:        case COM_UART_16550A:
                    274:                if (sc->sc_fifolen == 0)
                    275:                        sc->sc_fifolen = 16;
                    276:                printf(": ns16550a, %d byte fifo\n", sc->sc_fifolen);
                    277:                SET(sc->sc_hwflags, COM_HW_FIFO);
                    278:                break;
                    279: #ifdef COM_PXA2X0
                    280:        case COM_UART_PXA2X0:
                    281:                printf(": pxa2x0, 32 byte fifo");
                    282:                SET(sc->sc_hwflags, COM_HW_FIFO);
                    283:                sc->sc_fifolen = 32;
                    284:                if (sc->sc_iobase == comsiraddr) {
                    285:                        SET(sc->sc_hwflags, COM_HW_SIR);
                    286:                        printf(" (SIR)");
                    287:                }
                    288:                printf("\n");
                    289:                break;
                    290: #endif
                    291:        case COM_UART_ST16650:
                    292:                printf(": st16650, no working fifo\n");
                    293:                break;
                    294:        case COM_UART_ST16650V2:
                    295:                if (sc->sc_fifolen == 0)
                    296:                        sc->sc_fifolen = 32;
                    297:                printf(": st16650, %d byte fifo\n", sc->sc_fifolen);
                    298:                SET(sc->sc_hwflags, COM_HW_FIFO);
                    299:                break;
                    300:        case COM_UART_ST16C654:
                    301:                printf(": st16c654, 64 byte fifo\n");
                    302:                SET(sc->sc_hwflags, COM_HW_FIFO);
                    303:                sc->sc_fifolen = 64;
                    304:                break;
                    305:        case COM_UART_TI16750:
                    306:                printf(": ti16750, 64 byte fifo\n");
                    307:                SET(sc->sc_hwflags, COM_HW_FIFO);
                    308:                sc->sc_fifolen = 64;
                    309:                break;
                    310: #if NPCCOM > 0
                    311:        case COM_UART_XR16850:
                    312:                printf(": xr16850 (rev %d), 128 byte fifo\n", sc->sc_uartrev);
                    313:                SET(sc->sc_hwflags, COM_HW_FIFO);
                    314:                sc->sc_fifolen = 128;
                    315:                break;
                    316: #ifdef COM_UART_OX16C950
                    317:        case COM_UART_OX16C950:
                    318:                printf(": ox16c950 (rev %d), 128 byte fifo\n", sc->sc_uartrev);
                    319:                SET(sc->sc_hwflags, COM_HW_FIFO);
                    320:                sc->sc_fifolen = 128;
                    321:                break;
                    322: #endif
                    323: #endif
                    324:        default:
                    325:                panic("comattach: bad fifo type");
                    326:        }
                    327:
                    328: #ifdef notyet
                    329:        com_fifo_probe(sc);
                    330: #endif
                    331:
                    332:        if (sc->sc_fifolen == 0) {
                    333:                CLR(sc->sc_hwflags, COM_HW_FIFO);
                    334:                sc->sc_fifolen = 1;
                    335:        }
                    336:
                    337:        /* clear and disable fifo */
                    338:        bus_space_write_1(iot, ioh, com_fifo, FIFO_RCV_RST | FIFO_XMT_RST);
                    339:        (void)bus_space_read_1(iot, ioh, com_data);
                    340:        bus_space_write_1(iot, ioh, com_fifo, 0);
                    341:
                    342:        sc->sc_mcr = 0;
                    343:        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    344:
                    345: #ifdef KGDB
                    346:        /*
                    347:         * Allow kgdb to "take over" this port.  If this is
                    348:         * the kgdb device, it has exclusive use.
                    349:         */
                    350:
                    351:        if (iot == com_kgdb_iot && sc->sc_iobase == com_kgdb_addr &&
                    352:            !ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                    353:                printf("%s: kgdb\n", sc->sc_dev.dv_xname);
                    354:                SET(sc->sc_hwflags, COM_HW_KGDB);
                    355:        }
                    356: #endif /* KGDB */
                    357:
                    358: #ifdef COM_CONSOLE
                    359:        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                    360:                int maj;
                    361:
                    362:                /* locate the major number */
                    363:                for (maj = 0; maj < nchrdev; maj++)
                    364:                        if (cdevsw[maj].d_open == comopen)
                    365:                                break;
                    366:
                    367:                if (maj < nchrdev && cn_tab->cn_dev == NODEV)
                    368:                        cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
                    369:
                    370:                printf("%s: console\n", sc->sc_dev.dv_xname);
                    371:        }
                    372: #endif
                    373:
                    374:        timeout_set(&sc->sc_diag_tmo, comdiag, sc);
                    375:        timeout_set(&sc->sc_dtr_tmo, com_raisedtr, sc);
                    376: #if NCOM > 0
                    377: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
                    378:        sc->sc_si = softintr_establish(IPL_TTY, comsoft, sc);
                    379:        if (sc->sc_si == NULL)
                    380:                panic("%s: can't establish soft interrupt",
                    381:                    sc->sc_dev.dv_xname);
                    382: #else
                    383:        timeout_set(&sc->sc_comsoft_tmo, comsoft, sc);
                    384: #endif
                    385: #endif /* NCOM */
                    386:
                    387:        /*
                    388:         * If there are no enable/disable functions, assume the device
                    389:         * is always enabled.
                    390:         */
                    391:        if (!sc->enable)
                    392:                sc->enabled = 1;
                    393:
                    394: #if defined(COM_CONSOLE) || defined(KGDB)
                    395:        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE|COM_HW_KGDB))
                    396:                com_enable_debugport(sc);
                    397: #endif
                    398: }
                    399:
                    400: void
                    401: com_fifo_probe(struct com_softc *sc)
                    402: {
                    403:        bus_space_handle_t ioh = sc->sc_ioh;
                    404:        bus_space_tag_t iot = sc->sc_iot;
                    405:        u_int8_t fifo, ier;
                    406:        int timo, len;
                    407:
                    408:        if (!ISSET(sc->sc_hwflags, COM_HW_FIFO))
                    409:                return;
                    410:
                    411:        ier = 0;
                    412: #ifdef COM_PXA2X0
                    413:        if (sc->sc_uarttype == COM_UART_PXA2X0)
                    414:                ier |= IER_EUART;
                    415: #endif
                    416:        bus_space_write_1(iot, ioh, com_ier, ier);
                    417:        bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
                    418:        bus_space_write_1(iot, ioh, com_dlbl, 3);
                    419:        bus_space_write_1(iot, ioh, com_dlbh, 0);
                    420:        bus_space_write_1(iot, ioh, com_lcr, LCR_PNONE | LCR_8BITS);
                    421:        bus_space_write_1(iot, ioh, com_mcr, MCR_LOOPBACK);
                    422:
                    423:        fifo = FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST;
                    424:        if (sc->sc_uarttype == COM_UART_TI16750)
                    425:                fifo |= FIFO_ENABLE_64BYTE;
                    426:
                    427:        bus_space_write_1(iot, ioh, com_fifo, fifo);
                    428:
                    429:        for (len = 0; len < 256; len++) {
                    430:                bus_space_write_1(iot, ioh, com_data, (len + 1));
                    431:                timo = 2000;
                    432:                while (!ISSET(bus_space_read_1(iot, ioh, com_lsr),
                    433:                    LSR_TXRDY) && --timo)
                    434:                        delay(1);
                    435:                if (!timo)
                    436:                        break;
                    437:        }
                    438:
                    439:        delay(100);
                    440:
                    441:        for (len = 0; len < 256; len++) {
                    442:                timo = 2000;
                    443:                while (!ISSET(bus_space_read_1(iot, ioh, com_lsr),
                    444:                    LSR_RXRDY) && --timo)
                    445:                        delay(1);
                    446:                if (!timo || bus_space_read_1(iot, ioh, com_data) != (len + 1))
                    447:                        break;
                    448:        }
                    449:
                    450:        /* For safety, always use the smaller value. */
                    451:        if (sc->sc_fifolen > len) {
                    452:                printf("%s: probed fifo depth: %d bytes\n",
                    453:                    sc->sc_dev.dv_xname, len);
                    454:                sc->sc_fifolen = len;
                    455:        }
                    456: }

CVSweb