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

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

1.1       nbrk        1: /*     $OpenBSD: com.c,v 1.117 2007/07/15 19:25:49 kettenis Exp $      */
                      2: /*     $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 1997 - 1999, Jason Downs.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
                     17:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     19:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
                     20:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     21:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     22:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
                     23:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     26:  * SUCH DAMAGE.
                     27:  */
                     28: /*-
                     29:  * Copyright (c) 1993, 1994, 1995, 1996
                     30:  *     Charles M. Hannum.  All rights reserved.
                     31:  * Copyright (c) 1991 The Regents of the University of California.
                     32:  * All rights reserved.
                     33:  *
                     34:  * Redistribution and use in source and binary forms, with or without
                     35:  * modification, are permitted provided that the following conditions
                     36:  * are met:
                     37:  * 1. Redistributions of source code must retain the above copyright
                     38:  *    notice, this list of conditions and the following disclaimer.
                     39:  * 2. Redistributions in binary form must reproduce the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer in the
                     41:  *    documentation and/or other materials provided with the distribution.
                     42:  * 3. Neither the name of the University nor the names of its contributors
                     43:  *    may be used to endorse or promote products derived from this software
                     44:  *    without specific prior written permission.
                     45:  *
                     46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     56:  * SUCH DAMAGE.
                     57:  *
                     58:  *     @(#)com.c       7.5 (Berkeley) 5/16/91
                     59:  */
                     60:
                     61: /*
                     62:  * COM driver, based on HP dca driver
                     63:  * uses National Semiconductor NS16450/NS16550AF UART
                     64:  */
                     65: #include <sys/param.h>
                     66: #include <sys/systm.h>
                     67: #include <sys/ioctl.h>
                     68: #include <sys/selinfo.h>
                     69: #include <sys/tty.h>
                     70: #include <sys/proc.h>
                     71: #include <sys/user.h>
                     72: #include <sys/conf.h>
                     73: #include <sys/file.h>
                     74: #include <sys/uio.h>
                     75: #include <sys/kernel.h>
                     76: #include <sys/syslog.h>
                     77: #include <sys/device.h>
                     78: #include <sys/vnode.h>
                     79: #ifdef DDB
                     80: #include <ddb/db_var.h>
                     81: #endif
                     82:
                     83: #include <machine/bus.h>
                     84: #if defined(__sparc64__) || !defined(__sparc__)
                     85: #include <machine/intr.h>
                     86: #endif
                     87:
                     88: #if !defined(__sparc__) || defined(__sparc64__)
                     89: #define        COM_CONSOLE
                     90: #include <dev/cons.h>
                     91: #endif
                     92:
                     93: #include <dev/ic/comreg.h>
                     94: #include <dev/ic/comvar.h>
                     95: #include <dev/ic/ns16550reg.h>
                     96: #define        com_lcr com_cfcr
                     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 __zaurus__
                    105: #include <arch/zaurus/dev/zaurus_scoopvar.h>
                    106: #endif
                    107:
                    108: /* XXX: These belong elsewhere */
                    109: cdev_decl(com);
                    110:
                    111: static u_char tiocm_xxx2mcr(int);
                    112:
                    113: void   compwroff(struct com_softc *);
                    114: void   cominit(bus_space_tag_t, bus_space_handle_t, int, int);
                    115: int    com_is_console(bus_space_tag_t, bus_addr_t);
                    116:
                    117: struct cfdriver com_cd = {
                    118:        NULL, "com", DV_TTY
                    119: };
                    120:
                    121: int    comdefaultrate = TTYDEF_SPEED;
                    122: #ifdef COM_PXA2X0
                    123: bus_addr_t comsiraddr;
                    124: #endif
                    125: #ifdef COM_CONSOLE
                    126: int    comconsfreq;
                    127: int    comconsinit;
                    128: bus_addr_t comconsaddr;
                    129: int    comconsattached;
                    130: bus_space_tag_t comconsiot;
                    131: bus_space_handle_t comconsioh;
                    132: tcflag_t comconscflag = TTYDEF_CFLAG;
                    133: #endif
                    134:
                    135: int    commajor;
                    136:
                    137: #ifdef KGDB
                    138: #include <sys/kgdb.h>
                    139:
                    140: bus_addr_t com_kgdb_addr;
                    141: bus_space_tag_t com_kgdb_iot;
                    142: bus_space_handle_t com_kgdb_ioh;
                    143:
                    144: int    com_kgdb_getc(void *);
                    145: void   com_kgdb_putc(void *, int);
                    146: #endif /* KGDB */
                    147:
                    148: #define        DEVUNIT(x)      (minor(x) & 0x7f)
                    149: #define        DEVCUA(x)       (minor(x) & 0x80)
                    150:
                    151: int
                    152: comspeed(long freq, long speed)
                    153: {
                    154: #define        divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
                    155:
                    156:        int x, err;
                    157:
                    158:        if (speed == 0)
                    159:                return 0;
                    160:        if (speed < 0)
                    161:                return -1;
                    162:        x = divrnd((freq / 16), speed);
                    163:        if (x <= 0)
                    164:                return -1;
                    165:        err = divrnd((quad_t)freq * 1000 / 16, speed * x) - 1000;
                    166:        if (err < 0)
                    167:                err = -err;
                    168:        if (err > COM_TOLERANCE)
                    169:                return -1;
                    170:        return x;
                    171:
                    172: #undef divrnd
                    173: }
                    174:
                    175: #ifdef COM_CONSOLE
                    176: int
                    177: comprobe1(bus_space_tag_t iot, bus_space_handle_t ioh)
                    178: {
                    179:        int i, k;
                    180:
                    181:        /* force access to id reg */
                    182:        bus_space_write_1(iot, ioh, com_lcr, 0);
                    183:        bus_space_write_1(iot, ioh, com_iir, 0);
                    184:        for (i = 0; i < 32; i++) {
                    185:                k = bus_space_read_1(iot, ioh, com_iir);
                    186:                if (k & 0x38) {
                    187:                        bus_space_read_1(iot, ioh, com_data); /* cleanup */
                    188:                } else
                    189:                        break;
                    190:        }
                    191:        if (i >= 32)
                    192:                return 0;
                    193:
                    194:        return 1;
                    195: }
                    196: #endif
                    197:
                    198: int
                    199: com_detach(struct device *self, int flags)
                    200: {
                    201:        struct com_softc *sc = (struct com_softc *)self;
                    202:        int maj, mn;
                    203:
                    204:        sc->sc_swflags |= COM_SW_DEAD;
                    205:
                    206:        /* locate the major number */
                    207:        for (maj = 0; maj < nchrdev; maj++)
                    208:                if (cdevsw[maj].d_open == comopen)
                    209:                        break;
                    210:
                    211:        /* Nuke the vnodes for any open instances. */
                    212:        mn = self->dv_unit;
                    213:        vdevgone(maj, mn, mn, VCHR);
                    214:
                    215:        /* XXX a symbolic constant for the cua bit would be nicer. */
                    216:        mn |= 0x80;
                    217:        vdevgone(maj, mn, mn, VCHR);
                    218:
                    219:        /* Detach and free the tty. */
                    220:        if (sc->sc_tty) {
                    221:                ttyfree(sc->sc_tty);
                    222:        }
                    223:
                    224:        timeout_del(&sc->sc_dtr_tmo);
                    225:        timeout_del(&sc->sc_diag_tmo);
                    226: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
                    227:        softintr_disestablish(sc->sc_si);
                    228: #else
                    229:        timeout_del(&sc->sc_comsoft_tmo);
                    230: #endif
                    231:
                    232:        return (0);
                    233: }
                    234:
                    235: int
                    236: com_activate(struct device *self, enum devact act)
                    237: {
                    238:        struct com_softc *sc = (struct com_softc *)self;
                    239:        int s, rv = 0;
                    240:
                    241:        s = spltty();
                    242:        switch (act) {
                    243:        case DVACT_ACTIVATE:
                    244:                break;
                    245:
                    246:        case DVACT_DEACTIVATE:
                    247: #ifdef KGDB
                    248:                if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) {
                    249: #else
                    250:                if (sc->sc_hwflags & COM_HW_CONSOLE) {
                    251: #endif /* KGDB */
                    252:                        rv = EBUSY;
                    253:                        break;
                    254:                }
                    255:
                    256:                if (sc->disable != NULL && sc->enabled != 0) {
                    257:                        (*sc->disable)(sc);
                    258:                        sc->enabled = 0;
                    259:                }
                    260:                break;
                    261:        }
                    262:        splx(s);
                    263:        return (rv);
                    264: }
                    265:
                    266: int
                    267: comopen(dev_t dev, int flag, int mode, struct proc *p)
                    268: {
                    269:        int unit = DEVUNIT(dev);
                    270:        struct com_softc *sc;
                    271:        bus_space_tag_t iot;
                    272:        bus_space_handle_t ioh;
                    273:        struct tty *tp;
                    274:        int s;
                    275:        int error = 0;
                    276:
                    277:        if (unit >= com_cd.cd_ndevs)
                    278:                return ENXIO;
                    279:        sc = com_cd.cd_devs[unit];
                    280:        if (!sc)
                    281:                return ENXIO;
                    282:
                    283: #ifdef KGDB
                    284:        /*
                    285:         * If this is the kgdb port, no other use is permitted.
                    286:         */
                    287:        if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
                    288:                return (EBUSY);
                    289: #endif /* KGDB */
                    290:
                    291:        s = spltty();
                    292:        if (!sc->sc_tty) {
                    293:                tp = sc->sc_tty = ttymalloc();
                    294:        } else
                    295:                tp = sc->sc_tty;
                    296:        splx(s);
                    297:
                    298:        tp->t_oproc = comstart;
                    299:        tp->t_param = comparam;
                    300:        tp->t_dev = dev;
                    301:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
                    302:                SET(tp->t_state, TS_WOPEN);
                    303:                ttychars(tp);
                    304:                tp->t_iflag = TTYDEF_IFLAG;
                    305:                tp->t_oflag = TTYDEF_OFLAG;
                    306: #ifdef COM_CONSOLE
                    307:                if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
                    308:                        tp->t_cflag = comconscflag;
                    309:                else
                    310: #endif
                    311:                        tp->t_cflag = TTYDEF_CFLAG;
                    312:                if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
                    313:                        SET(tp->t_cflag, CLOCAL);
                    314:                if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
                    315:                        SET(tp->t_cflag, CRTSCTS);
                    316:                if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
                    317:                        SET(tp->t_cflag, MDMBUF);
                    318:                tp->t_lflag = TTYDEF_LFLAG;
                    319:                tp->t_ispeed = tp->t_ospeed = comdefaultrate;
                    320:
                    321:                s = spltty();
                    322:
                    323:                sc->sc_initialize = 1;
                    324:                comparam(tp, &tp->t_termios);
                    325:                ttsetwater(tp);
                    326:
                    327: #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
                    328:                timeout_add(&sc->sc_comsoft_tmo, 1);
                    329: #endif
                    330:
                    331:                sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
                    332:                sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
                    333:                sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
                    334:
                    335:                iot = sc->sc_iot;
                    336:                ioh = sc->sc_ioh;
                    337:
                    338:                /*
                    339:                 * Wake up the sleepy heads.
                    340:                 */
                    341:                switch (sc->sc_uarttype) {
                    342:                case COM_UART_ST16650:
                    343:                case COM_UART_ST16650V2:
                    344:                        bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
                    345:                        bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
                    346:                        bus_space_write_1(iot, ioh, com_ier, 0);
                    347:                        bus_space_write_1(iot, ioh, com_efr, 0);
                    348:                        bus_space_write_1(iot, ioh, com_lcr, 0);
                    349:                        break;
                    350:                case COM_UART_TI16750:
                    351:                        bus_space_write_1(iot, ioh, com_ier, 0);
                    352:                        break;
                    353:                case COM_UART_PXA2X0:
                    354:                        bus_space_write_1(iot, ioh, com_ier, IER_EUART);
                    355:                        break;
                    356:                }
                    357:
                    358:                if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
                    359:                        u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
                    360:                        u_int8_t lcr;
                    361:
                    362:                        if (tp->t_ispeed <= 1200)
                    363:                                fifo |= FIFO_TRIGGER_1;
                    364:                        else
                    365:                                fifo |= FIFO_TRIGGER_8;
                    366:                        if (sc->sc_uarttype == COM_UART_TI16750) {
                    367:                                fifo |= FIFO_ENABLE_64BYTE;
                    368:                                lcr = bus_space_read_1(iot, ioh, com_lcr);
                    369:                                bus_space_write_1(iot, ioh, com_lcr,
                    370:                                    lcr | LCR_DLAB);
                    371:                        }
                    372:
                    373:                        /*
                    374:                         * (Re)enable and drain FIFOs.
                    375:                         *
                    376:                         * Certain SMC chips cause problems if the FIFOs are
                    377:                         * enabled while input is ready. Turn off the FIFO
                    378:                         * if necessary to clear the input. Test the input
                    379:                         * ready bit after enabling the FIFOs to handle races
                    380:                         * between enabling and fresh input.
                    381:                         *
                    382:                         * Set the FIFO threshold based on the receive speed.
                    383:                         */
                    384:                        for (;;) {
                    385:                                bus_space_write_1(iot, ioh, com_fifo, 0);
                    386:                                delay(100);
                    387:                                (void) bus_space_read_1(iot, ioh, com_data);
                    388:                                bus_space_write_1(iot, ioh, com_fifo, fifo |
                    389:                                    FIFO_RCV_RST | FIFO_XMT_RST);
                    390:                                delay(100);
                    391:                                if(!ISSET(bus_space_read_1(iot, ioh,
                    392:                                    com_lsr), LSR_RXRDY))
                    393:                                        break;
                    394:                        }
                    395:                        if (sc->sc_uarttype == COM_UART_TI16750)
                    396:                                bus_space_write_1(iot, ioh, com_lcr, lcr);
                    397:                }
                    398:
                    399:                /* flush any pending I/O */
                    400:                while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
                    401:                        (void) bus_space_read_1(iot, ioh, com_data);
                    402:                /* you turn me on, baby */
                    403:                sc->sc_mcr = MCR_DTR | MCR_RTS;
                    404:                if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
                    405:                        SET(sc->sc_mcr, MCR_IENABLE);
                    406:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    407:                sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
                    408: #ifdef COM_PXA2X0
                    409:                if (sc->sc_uarttype == COM_UART_PXA2X0)
                    410:                        sc->sc_ier |= IER_EUART | IER_ERXTOUT;
                    411: #endif
                    412:                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
                    413:
                    414:                sc->sc_msr = bus_space_read_1(iot, ioh, com_msr);
                    415:                if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) ||
                    416:                    ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
                    417:                        SET(tp->t_state, TS_CARR_ON);
                    418:                else
                    419:                        CLR(tp->t_state, TS_CARR_ON);
                    420: #ifdef COM_PXA2X0
                    421:                if (sc->sc_uarttype == COM_UART_PXA2X0 &&
                    422:                    ISSET(sc->sc_hwflags, COM_HW_SIR)) {
                    423:                        bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
                    424: #ifdef __zaurus__
                    425:                        scoop_set_irled(1);
                    426: #endif
                    427:                }
                    428: #endif
                    429:        } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
                    430:                return EBUSY;
                    431:        else
                    432:                s = spltty();
                    433:
                    434:        if (DEVCUA(dev)) {
                    435:                if (ISSET(tp->t_state, TS_ISOPEN)) {
                    436:                        /* Ah, but someone already is dialed in... */
                    437:                        splx(s);
                    438:                        return EBUSY;
                    439:                }
                    440:                sc->sc_cua = 1;         /* We go into CUA mode */
                    441:        } else {
                    442:                /* tty (not cua) device; wait for carrier if necessary */
                    443:                if (ISSET(flag, O_NONBLOCK)) {
                    444:                        if (sc->sc_cua) {
                    445:                                /* Opening TTY non-blocking... but the CUA is busy */
                    446:                                splx(s);
                    447:                                return EBUSY;
                    448:                        }
                    449:                } else {
                    450:                        while (sc->sc_cua ||
                    451:                            (!ISSET(tp->t_cflag, CLOCAL) &&
                    452:                                !ISSET(tp->t_state, TS_CARR_ON))) {
                    453:                                SET(tp->t_state, TS_WOPEN);
                    454:                                error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0);
                    455:                                /*
                    456:                                 * If TS_WOPEN has been reset, that means the cua device
                    457:                                 * has been closed.  We don't want to fail in that case,
                    458:                                 * so just go around again.
                    459:                                 */
                    460:                                if (error && ISSET(tp->t_state, TS_WOPEN)) {
                    461:                                        CLR(tp->t_state, TS_WOPEN);
                    462:                                        if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN))
                    463:                                                compwroff(sc);
                    464:                                        splx(s);
                    465:                                        return error;
                    466:                                }
                    467:                        }
                    468:                }
                    469:        }
                    470:        splx(s);
                    471:
                    472:        return (*linesw[tp->t_line].l_open)(dev, tp);
                    473: }
                    474:
                    475: int
                    476: comclose(dev_t dev, int flag, int mode, struct proc *p)
                    477: {
                    478:        int unit = DEVUNIT(dev);
                    479:        struct com_softc *sc = com_cd.cd_devs[unit];
                    480:        bus_space_tag_t iot = sc->sc_iot;
                    481:        bus_space_handle_t ioh = sc->sc_ioh;
                    482:        struct tty *tp = sc->sc_tty;
                    483:        int s;
                    484:
                    485: #ifdef COM_CONSOLE
                    486:        /* XXX This is for cons.c. */
                    487:        if (!ISSET(tp->t_state, TS_ISOPEN))
                    488:                return 0;
                    489: #endif
                    490:
                    491:        if(sc->sc_swflags & COM_SW_DEAD)
                    492:                return 0;
                    493:
                    494:        (*linesw[tp->t_line].l_close)(tp, flag);
                    495:        s = spltty();
                    496:        if (ISSET(tp->t_state, TS_WOPEN)) {
                    497:                /* tty device is waiting for carrier; drop dtr then re-raise */
                    498:                CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
                    499:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    500:                timeout_add(&sc->sc_dtr_tmo, hz * 2);
                    501:        } else {
                    502:                /* no one else waiting; turn off the uart */
                    503:                compwroff(sc);
                    504:        }
                    505:        CLR(tp->t_state, TS_BUSY | TS_FLUSH);
                    506: #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
                    507:        timeout_del(&sc->sc_comsoft_tmo);
                    508: #endif
                    509:        sc->sc_cua = 0;
                    510:        splx(s);
                    511:        ttyclose(tp);
                    512:
                    513: #ifdef COM_CONSOLE
                    514: #ifdef notyet /* XXXX */
                    515:        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                    516:                ttyfree(tp);
                    517:                sc->sc_tty = 0;
                    518:        }
                    519: #endif
                    520: #endif
                    521:        return 0;
                    522: }
                    523:
                    524: void
                    525: compwroff(struct com_softc *sc)
                    526: {
                    527:        bus_space_tag_t iot = sc->sc_iot;
                    528:        bus_space_handle_t ioh = sc->sc_ioh;
                    529:        struct tty *tp = sc->sc_tty;
                    530:
                    531:        CLR(sc->sc_lcr, LCR_SBREAK);
                    532:        bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
                    533:        bus_space_write_1(iot, ioh, com_ier, 0);
                    534:        if (ISSET(tp->t_cflag, HUPCL) &&
                    535:            !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
                    536:                /* XXX perhaps only clear DTR */
                    537:                sc->sc_mcr = 0;
                    538:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    539:        }
                    540:
                    541:        /*
                    542:         * Turn FIFO off; enter sleep mode if possible.
                    543:         */
                    544:        bus_space_write_1(iot, ioh, com_fifo, 0);
                    545:        delay(100);
                    546:        (void) bus_space_read_1(iot, ioh, com_data);
                    547:        delay(100);
                    548:        bus_space_write_1(iot, ioh, com_fifo,
                    549:                          FIFO_RCV_RST | FIFO_XMT_RST);
                    550:
                    551:        switch (sc->sc_uarttype) {
                    552:        case COM_UART_ST16650:
                    553:        case COM_UART_ST16650V2:
                    554:                bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
                    555:                bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
                    556:                bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
                    557:                bus_space_write_1(iot, ioh, com_lcr, 0);
                    558:                break;
                    559:        case COM_UART_TI16750:
                    560:                bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
                    561:                break;
                    562: #ifdef COM_PXA2X0
                    563:        case COM_UART_PXA2X0:
                    564:                bus_space_write_1(iot, ioh, com_ier, 0);
                    565: #ifdef __zaurus__
                    566:                if (ISSET(sc->sc_hwflags, COM_HW_SIR))
                    567:                        scoop_set_irled(0);
                    568: #endif
                    569:                break;
                    570: #endif
                    571:        }
                    572: }
                    573:
                    574: void
                    575: com_raisedtr(void *arg)
                    576: {
                    577:        struct com_softc *sc = arg;
                    578:
                    579:        SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
                    580:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
                    581: }
                    582:
                    583: int
                    584: comread(dev_t dev, struct uio *uio, int flag)
                    585: {
                    586:        struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
                    587:        struct tty *tp = sc->sc_tty;
                    588:
                    589:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
                    590: }
                    591:
                    592: int
                    593: comwrite(dev_t dev, struct uio *uio, int flag)
                    594: {
                    595:        struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
                    596:        struct tty *tp = sc->sc_tty;
                    597:
                    598:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
                    599: }
                    600:
                    601: struct tty *
                    602: comtty(dev_t dev)
                    603: {
                    604:        struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
                    605:        struct tty *tp = sc->sc_tty;
                    606:
                    607:        return (tp);
                    608: }
                    609:
                    610: static u_char
                    611: tiocm_xxx2mcr(int data)
                    612: {
                    613:        u_char m = 0;
                    614:
                    615:        if (ISSET(data, TIOCM_DTR))
                    616:                SET(m, MCR_DTR);
                    617:        if (ISSET(data, TIOCM_RTS))
                    618:                SET(m, MCR_RTS);
                    619:        return m;
                    620: }
                    621:
                    622: int
                    623: comioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                    624: {
                    625:        int unit = DEVUNIT(dev);
                    626:        struct com_softc *sc = com_cd.cd_devs[unit];
                    627:        struct tty *tp = sc->sc_tty;
                    628:        bus_space_tag_t iot = sc->sc_iot;
                    629:        bus_space_handle_t ioh = sc->sc_ioh;
                    630:        int error;
                    631:
                    632:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
                    633:        if (error >= 0)
                    634:                return error;
                    635:        error = ttioctl(tp, cmd, data, flag, p);
                    636:        if (error >= 0)
                    637:                return error;
                    638:
                    639:        switch (cmd) {
                    640:        case TIOCSBRK:
                    641:                SET(sc->sc_lcr, LCR_SBREAK);
                    642:                bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
                    643:                break;
                    644:        case TIOCCBRK:
                    645:                CLR(sc->sc_lcr, LCR_SBREAK);
                    646:                bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
                    647:                break;
                    648:        case TIOCSDTR:
                    649:                SET(sc->sc_mcr, sc->sc_dtr);
                    650:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    651:                break;
                    652:        case TIOCCDTR:
                    653:                CLR(sc->sc_mcr, sc->sc_dtr);
                    654:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    655:                break;
                    656:        case TIOCMSET:
                    657:                CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
                    658:        case TIOCMBIS:
                    659:                SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
                    660:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    661:                break;
                    662:        case TIOCMBIC:
                    663:                CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
                    664:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    665:                break;
                    666:        case TIOCMGET: {
                    667:                u_char m;
                    668:                int bits = 0;
                    669:
                    670:                m = sc->sc_mcr;
                    671:                if (ISSET(m, MCR_DTR))
                    672:                        SET(bits, TIOCM_DTR);
                    673:                if (ISSET(m, MCR_RTS))
                    674:                        SET(bits, TIOCM_RTS);
                    675:                m = sc->sc_msr;
                    676:                if (ISSET(m, MSR_DCD))
                    677:                        SET(bits, TIOCM_CD);
                    678:                if (ISSET(m, MSR_CTS))
                    679:                        SET(bits, TIOCM_CTS);
                    680:                if (ISSET(m, MSR_DSR))
                    681:                        SET(bits, TIOCM_DSR);
                    682:                if (ISSET(m, MSR_RI | MSR_TERI))
                    683:                        SET(bits, TIOCM_RI);
                    684:                if (bus_space_read_1(iot, ioh, com_ier))
                    685:                        SET(bits, TIOCM_LE);
                    686:                *(int *)data = bits;
                    687:                break;
                    688:        }
                    689:        case TIOCGFLAGS: {
                    690:                int driverbits, userbits = 0;
                    691:
                    692:                driverbits = sc->sc_swflags;
                    693:                if (ISSET(driverbits, COM_SW_SOFTCAR))
                    694:                        SET(userbits, TIOCFLAG_SOFTCAR);
                    695:                if (ISSET(driverbits, COM_SW_CLOCAL))
                    696:                        SET(userbits, TIOCFLAG_CLOCAL);
                    697:                if (ISSET(driverbits, COM_SW_CRTSCTS))
                    698:                        SET(userbits, TIOCFLAG_CRTSCTS);
                    699:                if (ISSET(driverbits, COM_SW_MDMBUF))
                    700:                        SET(userbits, TIOCFLAG_MDMBUF);
                    701:                if (ISSET(driverbits, COM_SW_PPS))
                    702:                        SET(userbits, TIOCFLAG_PPS);
                    703:
                    704:                *(int *)data = userbits;
                    705:                break;
                    706:        }
                    707:        case TIOCSFLAGS: {
                    708:                int userbits, driverbits = 0;
                    709:
                    710:                error = suser(p, 0);
                    711:                if (error != 0)
                    712:                        return(EPERM);
                    713:
                    714:                userbits = *(int *)data;
                    715:                if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
                    716:                    ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
                    717:                        SET(driverbits, COM_SW_SOFTCAR);
                    718:                if (ISSET(userbits, TIOCFLAG_CLOCAL))
                    719:                        SET(driverbits, COM_SW_CLOCAL);
                    720:                if (ISSET(userbits, TIOCFLAG_CRTSCTS))
                    721:                        SET(driverbits, COM_SW_CRTSCTS);
                    722:                if (ISSET(userbits, TIOCFLAG_MDMBUF))
                    723:                        SET(driverbits, COM_SW_MDMBUF);
                    724:                if (ISSET(userbits, TIOCFLAG_PPS))
                    725:                        SET(driverbits, COM_SW_PPS);
                    726:
                    727:                sc->sc_swflags = driverbits;
                    728:                break;
                    729:        }
                    730:        default:
                    731:                return ENOTTY;
                    732:        }
                    733:
                    734:        return 0;
                    735: }
                    736:
                    737: /* already called at spltty */
                    738: int
                    739: comparam(struct tty *tp, struct termios *t)
                    740: {
                    741:        struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
                    742:        bus_space_tag_t iot = sc->sc_iot;
                    743:        bus_space_handle_t ioh = sc->sc_ioh;
                    744:        int ospeed = comspeed(sc->sc_frequency, t->c_ospeed);
                    745:        u_char lcr;
                    746:        tcflag_t oldcflag;
                    747:
                    748:        /* check requested parameters */
                    749:        if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
                    750:                return EINVAL;
                    751:
                    752:        lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
                    753:
                    754:        switch (ISSET(t->c_cflag, CSIZE)) {
                    755:        case CS5:
                    756:                SET(lcr, LCR_5BITS);
                    757:                break;
                    758:        case CS6:
                    759:                SET(lcr, LCR_6BITS);
                    760:                break;
                    761:        case CS7:
                    762:                SET(lcr, LCR_7BITS);
                    763:                break;
                    764:        case CS8:
                    765:                SET(lcr, LCR_8BITS);
                    766:                break;
                    767:        }
                    768:        if (ISSET(t->c_cflag, PARENB)) {
                    769:                SET(lcr, LCR_PENAB);
                    770:                if (!ISSET(t->c_cflag, PARODD))
                    771:                        SET(lcr, LCR_PEVEN);
                    772:        }
                    773:        if (ISSET(t->c_cflag, CSTOPB))
                    774:                SET(lcr, LCR_STOPB);
                    775:
                    776:        sc->sc_lcr = lcr;
                    777:
                    778:        if (ospeed == 0) {
                    779:                CLR(sc->sc_mcr, MCR_DTR);
                    780:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    781:        }
                    782:
                    783:        /*
                    784:         * Set the FIFO threshold based on the receive speed, if we are
                    785:         * changing it.
                    786:         */
                    787:        if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) {
                    788:                sc->sc_initialize = 0;
                    789:
                    790:                if (ospeed != 0) {
                    791:                        /*
                    792:                         * Make sure the transmit FIFO is empty before
                    793:                         * proceeding.  If we don't do this, some revisions
                    794:                         * of the UART will hang.  Interestingly enough,
                    795:                         * even if we do this while the last character is
                    796:                         * still being pushed out, they don't hang.  This
                    797:                         * seems good enough.
                    798:                         */
                    799:                        while (ISSET(tp->t_state, TS_BUSY)) {
                    800:                                int error;
                    801:
                    802:                                ++sc->sc_halt;
                    803:                                error = ttysleep(tp, &tp->t_outq,
                    804:                                    TTOPRI | PCATCH, "comprm", 0);
                    805:                                --sc->sc_halt;
                    806:                                if (error) {
                    807:                                        comstart(tp);
                    808:                                        return (error);
                    809:                                }
                    810:                        }
                    811:
                    812:                        bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
                    813:                        bus_space_write_1(iot, ioh, com_dlbl, ospeed);
                    814:                        bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8);
                    815:                        bus_space_write_1(iot, ioh, com_lcr, lcr);
                    816:                        SET(sc->sc_mcr, MCR_DTR);
                    817:                        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    818:                } else
                    819:                        bus_space_write_1(iot, ioh, com_lcr, lcr);
                    820:
                    821:                if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
                    822:                        if (sc->sc_uarttype == COM_UART_TI16750) {
                    823:                                bus_space_write_1(iot, ioh, com_lcr,
                    824:                                    lcr | LCR_DLAB);
                    825:                                bus_space_write_1(iot, ioh, com_fifo,
                    826:                                    FIFO_ENABLE | FIFO_ENABLE_64BYTE |
                    827:                                    (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
                    828:                                bus_space_write_1(iot, ioh, com_lcr, lcr);
                    829:                        } else
                    830:                                bus_space_write_1(iot, ioh, com_fifo,
                    831:                                    FIFO_ENABLE |
                    832:                                    (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
                    833:                }
                    834:        } else
                    835:                bus_space_write_1(iot, ioh, com_lcr, lcr);
                    836:
                    837:        /* When not using CRTSCTS, RTS follows DTR. */
                    838:        if (!ISSET(t->c_cflag, CRTSCTS)) {
                    839:                if (ISSET(sc->sc_mcr, MCR_DTR)) {
                    840:                        if (!ISSET(sc->sc_mcr, MCR_RTS)) {
                    841:                                SET(sc->sc_mcr, MCR_RTS);
                    842:                                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    843:                        }
                    844:                } else {
                    845:                        if (ISSET(sc->sc_mcr, MCR_RTS)) {
                    846:                                CLR(sc->sc_mcr, MCR_RTS);
                    847:                                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    848:                        }
                    849:                }
                    850:                sc->sc_dtr = MCR_DTR | MCR_RTS;
                    851:        } else
                    852:                sc->sc_dtr = MCR_DTR;
                    853:
                    854:        /* and copy to tty */
                    855:        tp->t_ispeed = t->c_ispeed;
                    856:        tp->t_ospeed = t->c_ospeed;
                    857:        oldcflag = tp->t_cflag;
                    858:        tp->t_cflag = t->c_cflag;
                    859:
                    860:        /*
                    861:         * If DCD is off and MDMBUF is changed, ask the tty layer if we should
                    862:         * stop the device.
                    863:         */
                    864:        if (!ISSET(sc->sc_msr, MSR_DCD) &&
                    865:            !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
                    866:            ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
                    867:            (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
                    868:                CLR(sc->sc_mcr, sc->sc_dtr);
                    869:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                    870:        }
                    871:
                    872:        /* Just to be sure... */
                    873:        comstart(tp);
                    874:        return 0;
                    875: }
                    876:
                    877: void
                    878: comstart(struct tty *tp)
                    879: {
                    880:        struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
                    881:        bus_space_tag_t iot = sc->sc_iot;
                    882:        bus_space_handle_t ioh = sc->sc_ioh;
                    883:        int s;
                    884:
                    885:        s = spltty();
                    886:        if (ISSET(tp->t_state, TS_BUSY))
                    887:                goto out;
                    888:        if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0)
                    889:                goto stopped;
                    890:        if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
                    891:                goto stopped;
                    892:        if (tp->t_outq.c_cc <= tp->t_lowat) {
                    893:                if (ISSET(tp->t_state, TS_ASLEEP)) {
                    894:                        CLR(tp->t_state, TS_ASLEEP);
                    895:                        wakeup(&tp->t_outq);
                    896:                }
                    897:                if (tp->t_outq.c_cc == 0)
                    898:                        goto stopped;
                    899:                selwakeup(&tp->t_wsel);
                    900:        }
                    901:        SET(tp->t_state, TS_BUSY);
                    902:
                    903: #ifdef COM_PXA2X0
                    904:        /* Enable transmitter slow infrared mode. */
                    905:        if (sc->sc_uarttype == COM_UART_PXA2X0 &&
                    906:            ISSET(sc->sc_hwflags, COM_HW_SIR))
                    907:                bus_space_write_1(iot, ioh, com_isr, ISR_SEND);
                    908: #endif
                    909:
                    910:        /* Enable transmit completion interrupts. */
                    911:        if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
                    912:                SET(sc->sc_ier, IER_ETXRDY);
                    913:                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
                    914:        }
                    915:
                    916:        if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
                    917:                u_char buffer[64];      /* XXX: largest fifo */
                    918:
                    919:                int n = q_to_b(&tp->t_outq, buffer, sc->sc_fifolen);
                    920:                int i;
                    921:
                    922:                for (i = 0; i < n; i++) {
                    923:                        bus_space_write_1(iot, ioh, com_data, buffer[i]);
                    924:                }
                    925:        } else if (tp->t_outq.c_cc != 0)
                    926:                bus_space_write_1(iot, ioh, com_data, getc(&tp->t_outq));
                    927: out:
                    928:        splx(s);
                    929:        return;
                    930: stopped:
                    931:        if (ISSET(sc->sc_ier, IER_ETXRDY)) {
                    932:                CLR(sc->sc_ier, IER_ETXRDY);
                    933:                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
                    934: #ifdef COM_PXA2X0
                    935:                if (sc->sc_uarttype == COM_UART_PXA2X0 &&
                    936:                    ISSET(sc->sc_hwflags, COM_HW_SIR)) {
                    937:                        int timo;
                    938:
                    939:                        /* Wait for empty transmit shift register. */
                    940:                        timo = 20000;
                    941:                        while (!ISSET(bus_space_read_1(iot, ioh, com_lsr),
                    942:                            LSR_TSRE) && --timo)
                    943:                                delay(1);
                    944:
                    945:                        /* Enable receiver slow infrared mode. */
                    946:                        bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
                    947:                }
                    948: #endif
                    949:        }
                    950:        splx(s);
                    951: }
                    952:
                    953: /*
                    954:  * Stop output on a line.
                    955:  */
                    956: int
                    957: comstop(struct tty *tp, int flag)
                    958: {
                    959:        int s;
                    960:
                    961:        s = spltty();
                    962:        if (ISSET(tp->t_state, TS_BUSY))
                    963:                if (!ISSET(tp->t_state, TS_TTSTOP))
                    964:                        SET(tp->t_state, TS_FLUSH);
                    965:        splx(s);
                    966:        return 0;
                    967: }
                    968:
                    969: void
                    970: comdiag(void *arg)
                    971: {
                    972:        struct com_softc *sc = arg;
                    973:        int overflows, floods;
                    974:        int s;
                    975:
                    976:        s = spltty();
                    977:        sc->sc_errors = 0;
                    978:        overflows = sc->sc_overflows;
                    979:        sc->sc_overflows = 0;
                    980:        floods = sc->sc_floods;
                    981:        sc->sc_floods = 0;
                    982:        splx(s);
                    983:        log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
                    984:            sc->sc_dev.dv_xname,
                    985:            overflows, overflows == 1 ? "" : "s",
                    986:            floods, floods == 1 ? "" : "s");
                    987: }
                    988:
                    989: void
                    990: comsoft(void *arg)
                    991: {
                    992:        struct com_softc *sc = (struct com_softc *)arg;
                    993:        struct tty *tp;
                    994:        u_char *ibufp;
                    995:        u_char *ibufend;
                    996:        int c;
                    997:        int s;
                    998:        static int lsrmap[8] = {
                    999:                0,      TTY_PE,
                   1000:                TTY_FE, TTY_PE|TTY_FE,
                   1001:                TTY_FE, TTY_PE|TTY_FE,
                   1002:                TTY_FE, TTY_PE|TTY_FE
                   1003:        };
                   1004:
                   1005:        if (sc == NULL || sc->sc_ibufp == sc->sc_ibuf)
                   1006:                goto out;
                   1007:
                   1008:        tp = sc->sc_tty;
                   1009:
                   1010:        s = spltty();
                   1011:
                   1012:        ibufp = sc->sc_ibuf;
                   1013:        ibufend = sc->sc_ibufp;
                   1014:
                   1015:        if (ibufp == ibufend) {
                   1016:                splx(s);
                   1017:                goto out;
                   1018:        }
                   1019:
                   1020:        sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
                   1021:                                     sc->sc_ibufs[1] : sc->sc_ibufs[0];
                   1022:        sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
                   1023:        sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
                   1024:
                   1025:        if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN)) {
                   1026:                splx(s);
                   1027:                goto out;
                   1028:        }
                   1029:
                   1030:        if (ISSET(tp->t_cflag, CRTSCTS) &&
                   1031:            !ISSET(sc->sc_mcr, MCR_RTS)) {
                   1032:                /* XXX */
                   1033:                SET(sc->sc_mcr, MCR_RTS);
                   1034:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr,
                   1035:                    sc->sc_mcr);
                   1036:        }
                   1037:
                   1038:        splx(s);
                   1039:
                   1040:        while (ibufp < ibufend) {
                   1041:                c = *ibufp++;
                   1042:                if (ISSET(*ibufp, LSR_OE)) {
                   1043:                        sc->sc_overflows++;
                   1044:                        if (sc->sc_errors++ == 0)
                   1045:                                timeout_add(&sc->sc_diag_tmo, 60 * hz);
                   1046:                }
                   1047:                /* This is ugly, but fast. */
                   1048:                c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
                   1049:                (*linesw[tp->t_line].l_rint)(c, tp);
                   1050:        }
                   1051:
                   1052: out:
                   1053: #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
                   1054:        timeout_add(&sc->sc_comsoft_tmo, 1);
                   1055: #else
                   1056:        ;
                   1057: #endif
                   1058: }
                   1059:
                   1060: #ifdef KGDB
                   1061:
                   1062: /*
                   1063:  * If a line break is set, or data matches one of the characters
                   1064:  * gdb uses to signal a connection, then start up kgdb. Just gobble
                   1065:  * any other data. Done in a stand alone function because comintr
                   1066:  * does tty stuff and we don't have one.
                   1067:  */
                   1068:
                   1069: int
                   1070: kgdbintr(void *arg)
                   1071: {
                   1072:        struct com_softc *sc = arg;
                   1073:        bus_space_tag_t iot = sc->sc_iot;
                   1074:        bus_space_handle_t ioh = sc->sc_ioh;
                   1075:        u_char lsr, data, msr, delta;
                   1076:
                   1077:        if (!ISSET(sc->sc_hwflags, COM_HW_KGDB))
                   1078:                return(0);
                   1079:
                   1080:        for (;;) {
                   1081:                lsr = bus_space_read_1(iot, ioh, com_lsr);
                   1082:                if (ISSET(lsr, LSR_RXRDY)) {
                   1083:                        do {
                   1084:                                data = bus_space_read_1(iot, ioh, com_data);
                   1085:                                if (data == 3 || data == '$' || data == '+' ||
                   1086:                                    ISSET(lsr, LSR_BI)) {
                   1087:                                        kgdb_connect(1);
                   1088:                                        data = 0;
                   1089:                                }
                   1090:                                lsr = bus_space_read_1(iot, ioh, com_lsr);
                   1091:                        } while (ISSET(lsr, LSR_RXRDY));
                   1092:
                   1093:                }
                   1094:                if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
                   1095:                        printf("weird lsr %02x\n", lsr);
                   1096:
                   1097:                msr = bus_space_read_1(iot, ioh, com_msr);
                   1098:
                   1099:                if (msr != sc->sc_msr) {
                   1100:                        delta = msr ^ sc->sc_msr;
                   1101:                        sc->sc_msr = msr;
                   1102:                        if (ISSET(delta, MSR_DCD)) {
                   1103:                                if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
                   1104:                                        CLR(sc->sc_mcr, sc->sc_dtr);
                   1105:                                        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                   1106:                                }
                   1107:                        }
                   1108:                }
                   1109:                if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
                   1110:                        return (1);
                   1111:        }
                   1112: }
                   1113: #endif /* KGDB */
                   1114:
                   1115: int
                   1116: comintr(void *arg)
                   1117: {
                   1118:        struct com_softc *sc = arg;
                   1119:        bus_space_tag_t iot = sc->sc_iot;
                   1120:        bus_space_handle_t ioh = sc->sc_ioh;
                   1121:        struct tty *tp;
                   1122:        u_char lsr, data, msr, delta;
                   1123:
                   1124:        if (!sc->sc_tty)
                   1125:                return (0);             /* can't do squat. */
                   1126:
                   1127:        if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
                   1128:                return (0);
                   1129:
                   1130:        tp = sc->sc_tty;
                   1131:
                   1132:        for (;;) {
                   1133:                lsr = bus_space_read_1(iot, ioh, com_lsr);
                   1134:
                   1135:                if (ISSET(lsr, LSR_RXRDY)) {
                   1136:                        u_char *p = sc->sc_ibufp;
                   1137:
                   1138: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
                   1139:                        softintr_schedule(sc->sc_si);
                   1140: #endif
                   1141:                        do {
                   1142:                                data = bus_space_read_1(iot, ioh, com_data);
                   1143:                                if (ISSET(lsr, LSR_BI)) {
                   1144: #if defined(COM_CONSOLE) && defined(DDB)
                   1145:                                        if (ISSET(sc->sc_hwflags,
                   1146:                                            COM_HW_CONSOLE)) {
                   1147:                                                if (db_console)
                   1148:                                                        Debugger();
                   1149:                                                goto next;
                   1150:                                        }
                   1151: #endif
                   1152:                                        data = 0;
                   1153:                                }
                   1154:                                if (p >= sc->sc_ibufend) {
                   1155:                                        sc->sc_floods++;
                   1156:                                        if (sc->sc_errors++ == 0)
                   1157:                                                timeout_add(&sc->sc_diag_tmo, 60 * hz);
                   1158:                                } else {
                   1159:                                        *p++ = data;
                   1160:                                        *p++ = lsr;
                   1161:                                        if (p == sc->sc_ibufhigh &&
                   1162:                                            ISSET(tp->t_cflag, CRTSCTS)) {
                   1163:                                                /* XXX */
                   1164:                                                CLR(sc->sc_mcr, MCR_RTS);
                   1165:                                                bus_space_write_1(iot, ioh, com_mcr,
                   1166:                                                    sc->sc_mcr);
                   1167:                                        }
                   1168:                                }
                   1169: #if defined(COM_CONSOLE) && defined(DDB)
                   1170:                        next:
                   1171: #endif
                   1172:                                lsr = bus_space_read_1(iot, ioh, com_lsr);
                   1173:                        } while (ISSET(lsr, LSR_RXRDY));
                   1174:
                   1175:                        sc->sc_ibufp = p;
                   1176:                }
                   1177:                msr = bus_space_read_1(iot, ioh, com_msr);
                   1178:
                   1179:                if (msr != sc->sc_msr) {
                   1180:                        delta = msr ^ sc->sc_msr;
                   1181:
                   1182:                        ttytstamp(tp, sc->sc_msr & MSR_CTS, msr & MSR_CTS,
                   1183:                            sc->sc_msr & MSR_DCD, msr & MSR_DCD);
                   1184:
                   1185:                        sc->sc_msr = msr;
                   1186:                        if (ISSET(delta, MSR_DCD)) {
                   1187:                                if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
                   1188:                                    (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
                   1189:                                        CLR(sc->sc_mcr, sc->sc_dtr);
                   1190:                                        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
                   1191:                                }
                   1192:                        }
                   1193:                        if (ISSET(delta & msr, MSR_CTS) &&
                   1194:                            ISSET(tp->t_cflag, CRTSCTS)) {
                   1195:                                /* the line is up and we want to do rts/cts flow control */
                   1196:                                (*linesw[tp->t_line].l_start)(tp);
                   1197:                        }
                   1198:                }
                   1199:
                   1200:                if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
                   1201:                        CLR(tp->t_state, TS_BUSY | TS_FLUSH);
                   1202:                        if (sc->sc_halt > 0)
                   1203:                                wakeup(&tp->t_outq);
                   1204:                        (*linesw[tp->t_line].l_start)(tp);
                   1205:                }
                   1206:
                   1207: #ifdef COM_PXA2X0
                   1208:                if (sc->sc_uarttype == COM_UART_PXA2X0 &&
                   1209:                    ISSET(sc->sc_hwflags, COM_HW_SIR) &&
                   1210:                    ISSET(lsr, LSR_TXRDY) && ISSET(lsr, LSR_TSRE))
                   1211:                        bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
                   1212: #endif
                   1213:
                   1214:                if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
                   1215:                        return (1);
                   1216:        }
                   1217: }
                   1218:
                   1219: /*
                   1220:  * Following are all routines needed for COM to act as console
                   1221:  */
                   1222:
                   1223: #if defined(__sgi__)
                   1224: #undef CONADDR
                   1225: #undef COM_FREQ
                   1226: #include <machine/autoconf.h>
                   1227: #endif
                   1228:
                   1229: /*
                   1230:  * The following functions are polled getc and putc routines, shared
                   1231:  * by the console and kgdb glue.
                   1232:  */
                   1233:
                   1234: int
                   1235: com_common_getc(bus_space_tag_t iot, bus_space_handle_t ioh)
                   1236: {
                   1237:        int s = splhigh();
                   1238:        u_char stat, c;
                   1239:
                   1240: #ifdef COM_PXA2X0
                   1241:        if (com_is_console(iot, comsiraddr))
                   1242:                bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
                   1243: #endif
                   1244:
                   1245:        /* block until a character becomes available */
                   1246:        while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
                   1247:                continue;
                   1248:
                   1249:        c = bus_space_read_1(iot, ioh, com_data);
                   1250:        /* clear any interrupts generated by this transmission */
                   1251:        stat = bus_space_read_1(iot, ioh, com_iir);
                   1252:        splx(s);
                   1253:        return (c);
                   1254: }
                   1255:
                   1256: void
                   1257: com_common_putc(bus_space_tag_t iot, bus_space_handle_t ioh, int c)
                   1258: {
                   1259:        int s = spltty();
                   1260:        int timo;
                   1261:
                   1262:        printf("com_common_putc: enter\n");
                   1263:
                   1264:        /* wait for any pending transmission to finish */
                   1265:        timo = 2000;
                   1266:        while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
                   1267:                delay(1);
                   1268:
                   1269: #ifdef COM_PXA2X0
                   1270:        if (com_is_console(iot, comsiraddr))
                   1271:                bus_space_write_1(iot, ioh, com_isr, ISR_SEND);
                   1272: #endif
                   1273:        bus_space_write_1(iot, ioh, com_data, (u_int8_t)(c & 0xff));
                   1274:        bus_space_barrier(iot, ioh, 0, COM_NPORTS,
                   1275:            (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE));
                   1276:
                   1277:        printf("com_common_putc: wait for TXRDY\n");
                   1278:        /* wait for this transmission to complete */
                   1279:        timo = 2000;
                   1280:        while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
                   1281:                delay(1);
                   1282:
                   1283: #ifdef COM_PXA2X0
                   1284:        if (com_is_console(iot, comsiraddr)) {
                   1285:                /* wait for transmit shift register to become empty */
                   1286:                timo = 20000;
                   1287:                while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TSRE)
                   1288:                    && --timo)
                   1289:                        delay(1);
                   1290:
                   1291:                bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
                   1292:        }
                   1293: #endif
                   1294:
                   1295:        splx(s);
                   1296: }
                   1297:
                   1298: void
                   1299: cominit(bus_space_tag_t iot, bus_space_handle_t ioh, int rate, int frequency)
                   1300: {
                   1301:        int s = splhigh();
                   1302:        u_char stat;
                   1303:
                   1304:        bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
                   1305:        rate = comspeed(frequency, rate); /* XXX not comdefaultrate? */
                   1306:        bus_space_write_1(iot, ioh, com_dlbl, rate);
                   1307:        bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
                   1308:        bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
                   1309:        bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS);
                   1310: #ifdef COM_PXA2X0
                   1311:        /* XXX */
                   1312:        bus_space_write_1(iot, ioh, com_ier, IER_EUART);  /* Make sure they are off */
                   1313: #else
                   1314:        bus_space_write_1(iot, ioh, com_ier, 0);  /* Make sure they are off */
                   1315: #endif
                   1316:        bus_space_write_1(iot, ioh, com_fifo,
                   1317:            FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
                   1318:        stat = bus_space_read_1(iot, ioh, com_iir);
                   1319:        splx(s);
                   1320: }
                   1321:
                   1322: #ifdef COM_CONSOLE
                   1323: void
                   1324: comcnprobe(struct consdev *cp)
                   1325: {
                   1326:        /* XXX NEEDS TO BE FIXED XXX */
                   1327: #ifdef MD_ISA_IOT
                   1328:        bus_space_tag_t iot = MD_ISA_IOT;
                   1329: #elif defined(__sgi__)
                   1330:        bus_space_tag_t iot = sys_config.cons_iot;
                   1331: #else
                   1332:        bus_space_tag_t iot = 0;
                   1333: #endif
                   1334:        bus_space_handle_t ioh;
                   1335:        int found;
                   1336:
                   1337:        if (CONADDR == 0)
                   1338:                return;
                   1339:
                   1340:        comconsiot = iot;
                   1341:        if (bus_space_map(iot, CONADDR, COM_NPORTS, 0, &ioh))
                   1342:                return;
                   1343:        found = comprobe1(iot, ioh);
                   1344:        bus_space_unmap(iot, ioh, COM_NPORTS);
                   1345:        if (!found)
                   1346:                return;
                   1347:
                   1348:        /* locate the major number */
                   1349:        for (commajor = 0; commajor < nchrdev; commajor++)
                   1350:                if (cdevsw[commajor].d_open == comopen)
                   1351:                        break;
                   1352:
                   1353:        /* initialize required fields */
                   1354:        cp->cn_dev = makedev(commajor, CONUNIT);
                   1355: #if defined(COMCONSOLE) || defined(PCCOMCONSOLE) || !defined(__amd64__)
                   1356:        cp->cn_pri = CN_REMOTE;
                   1357: #else
                   1358:        cp->cn_pri = CN_NORMAL;
                   1359: #endif
                   1360: }
                   1361:
                   1362: void
                   1363: comcninit(struct consdev *cp)
                   1364: {
                   1365:        comconsaddr = CONADDR;
                   1366:
                   1367:        if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &comconsioh))
                   1368:                panic("comcninit: mapping failed");
                   1369:
                   1370:        if (comconsfreq == 0)
                   1371:                comconsfreq = COM_FREQ;
                   1372:
                   1373:        cominit(comconsiot, comconsioh, comdefaultrate, comconsfreq);
                   1374:        comconsinit = 0;
                   1375: }
                   1376:
                   1377:
                   1378: int
                   1379: comcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency, tcflag_t cflag)
                   1380: {
                   1381:        static struct consdev comcons = {
                   1382:                NULL, NULL, comcngetc, comcnputc, comcnpollc, NULL,
                   1383:                NODEV, CN_NORMAL
                   1384:        };
                   1385:
                   1386: #ifndef __sparc64__
                   1387:        if (bus_space_map(iot, iobase, COM_NPORTS, 0, &comconsioh))
                   1388:                return ENOMEM;
                   1389: #endif
                   1390:
                   1391:        cominit(iot, comconsioh, rate, frequency);
                   1392:
                   1393:        cn_tab = &comcons;
                   1394:
                   1395:        comconsiot = iot;
                   1396:        comconsaddr = iobase;
                   1397:        comconscflag = cflag;
                   1398:        comconsfreq = frequency;
                   1399:
                   1400:        return (0);
                   1401: }
                   1402:
                   1403: int
                   1404: comcngetc(dev_t dev)
                   1405: {
                   1406:        return (com_common_getc(comconsiot, comconsioh));
                   1407: }
                   1408:
                   1409: /*
                   1410:  * Console kernel output character routine.
                   1411:  */
                   1412: void
                   1413: comcnputc(dev_t dev, int c)
                   1414: {
                   1415:        com_common_putc(comconsiot, comconsioh, c);
                   1416: }
                   1417:
                   1418: void
                   1419: comcnpollc(dev_t dev, int on)
                   1420: {
                   1421:
                   1422: }
                   1423: #endif /* COM_CONSOLE */
                   1424:
                   1425: #ifdef KGDB
                   1426: int
                   1427: com_kgdb_attach(bus_space_tag_t iot, bus_addr_t iobase, int rate,
                   1428:     int frequency,tcflag_t cflag)
                   1429:        bus_space_tag_t iot;
                   1430:        bus_addr_t iobase;
                   1431:        int rate, frequency;
                   1432:        tcflag_t cflag;
                   1433: {
                   1434: #ifdef COM_CONSOLE
                   1435:        if (iot == comconsiot && iobase == comconsaddr) {
                   1436:                return (EBUSY); /* cannot share with console */
                   1437:        }
                   1438: #endif
                   1439:
                   1440:        com_kgdb_iot = iot;
                   1441:        com_kgdb_addr = iobase;
                   1442:
                   1443:        if (bus_space_map(com_kgdb_iot, com_kgdb_addr, COM_NPORTS, 0,
                   1444:            &com_kgdb_ioh))
                   1445:                panic("com_kgdb_attach: mapping failed");
                   1446:
                   1447:        /* XXX We currently don't respect KGDBMODE? */
                   1448:        cominit(com_kgdb_iot, com_kgdb_ioh, rate, frequency);
                   1449:
                   1450:        kgdb_attach(com_kgdb_getc, com_kgdb_putc, NULL);
                   1451:        kgdb_dev = 123; /* unneeded, only to satisfy some tests */
                   1452:
                   1453:        return (0);
                   1454: }
                   1455:
                   1456: /* ARGSUSED */
                   1457: int
                   1458: com_kgdb_getc(void *arg)
                   1459: {
                   1460:
                   1461:        return (com_common_getc(com_kgdb_iot, com_kgdb_ioh));
                   1462: }
                   1463:
                   1464: /* ARGSUSED */
                   1465: void
                   1466: com_kgdb_putc(void *arg, int c)
                   1467: {
                   1468:
                   1469:        return (com_common_putc(com_kgdb_iot, com_kgdb_ioh, c));
                   1470: }
                   1471: #endif /* KGDB */
                   1472:
                   1473: #ifdef COM_PXA2X0
                   1474: int
                   1475: com_is_console(bus_space_tag_t iot, bus_addr_t iobase)
                   1476: {
                   1477:
                   1478:        if (comconsiot == iot && comconsaddr == iobase)
                   1479:                return (1);
                   1480: #ifdef KGDB
                   1481:        else if (com_kgdb_iot == iot && com_kgdb_addr == iobase)
                   1482:                return (1);
                   1483: #endif
                   1484:        return (0);
                   1485: }
                   1486: #endif

CVSweb