[BACK]Return to sab.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc64 / dev

Annotation of sys/arch/sparc64/dev/sab.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: sab.c,v 1.19 2006/05/28 22:41:44 jason Exp $  */
                      2:
                      3: /*
                      4:  * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
                      5:  * 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 ``AS IS'' AND ANY EXPRESS OR
                     17:  * 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 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)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     24:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     25:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  *
                     28:  * Effort sponsored in part by the Defense Advanced Research Projects
                     29:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
                     30:  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
                     31:  *
                     32:  */
                     33:
                     34: /*
                     35:  * SAB82532 Dual UART driver
                     36:  */
                     37:
                     38: #include <sys/types.h>
                     39: #include <sys/param.h>
                     40: #include <sys/systm.h>
                     41: #include <sys/device.h>
                     42: #include <sys/conf.h>
                     43: #include <sys/file.h>
                     44: #include <sys/ioctl.h>
                     45: #include <sys/kernel.h>
                     46: #include <sys/proc.h>
                     47: #include <sys/tty.h>
                     48: #include <sys/time.h>
                     49: #include <sys/syslog.h>
                     50:
                     51: #include <machine/autoconf.h>
                     52: #include <machine/openfirm.h>
                     53: #include <machine/bsd_openprom.h>
                     54: #include <machine/conf.h>
                     55: #include <machine/cpu.h>
                     56: #include <machine/eeprom.h>
                     57: #include <machine/psl.h>
                     58:
                     59: #include <dev/cons.h>
                     60: #include <ddb/db_output.h>
                     61:
                     62: #include <sparc64/dev/ebusreg.h>
                     63: #include <sparc64/dev/ebusvar.h>
                     64: #include <sparc64/dev/cons.h>
                     65: #include <sparc64/dev/sab82532reg.h>
                     66:
                     67: #define        SAB_CARD(x)     ((minor(x) >> 6) & 3)
                     68: #define        SAB_PORT(x)     (minor(x) & 7)
                     69: #define        SAB_DIALOUT(x)  (minor(x) & 0x10)
                     70: #define        SABTTY_RBUF_SIZE        1024    /* must be divisible by 2 */
                     71:
                     72: struct sab_softc {
                     73:        struct device           sc_dv;
                     74:        struct intrhand *       sc_ih;
                     75:        bus_space_tag_t         sc_bt;
                     76:        bus_space_handle_t      sc_bh;
                     77:        struct sabtty_softc *   sc_child[SAB_NCHAN];
                     78:        u_int                   sc_nchild;
                     79:        void *                  sc_softintr;
                     80:        int                     sc_node;
                     81: };
                     82:
                     83: struct sabtty_attach_args {
                     84:        u_int sbt_portno;
                     85: };
                     86:
                     87: struct sabtty_softc {
                     88:        struct device           sc_dv;
                     89:        struct sab_softc *      sc_parent;
                     90:        bus_space_tag_t         sc_bt;
                     91:        bus_space_handle_t      sc_bh;
                     92:        struct tty *            sc_tty;
                     93:        u_int                   sc_portno;
                     94:        u_int8_t                sc_pvr_dtr, sc_pvr_dsr;
                     95:        u_int8_t                sc_imr0, sc_imr1;
                     96:        int                     sc_openflags;
                     97:        u_char *                sc_txp;
                     98:        int                     sc_txc;
                     99:        int                     sc_flags;
                    100: #define SABTTYF_STOP           0x01
                    101: #define        SABTTYF_DONE            0x02
                    102: #define        SABTTYF_RINGOVERFLOW    0x04
                    103: #define        SABTTYF_CDCHG           0x08
                    104: #define        SABTTYF_CONS_IN         0x10
                    105: #define        SABTTYF_CONS_OUT        0x20
                    106: #define        SABTTYF_TXDRAIN         0x40
                    107: #define        SABTTYF_DONTDDB         0x80
                    108:        u_int8_t                sc_rbuf[SABTTY_RBUF_SIZE];
                    109:        u_int8_t                *sc_rend, *sc_rput, *sc_rget;
                    110:        u_int8_t                sc_polling, sc_pollrfc;
                    111: };
                    112:
                    113: struct sabtty_softc *sabtty_cons_input;
                    114: struct sabtty_softc *sabtty_cons_output;
                    115:
                    116: #define        SAB_READ(sc,r)          \
                    117:     bus_space_read_1((sc)->sc_bt, (sc)->sc_bh, (r))
                    118: #define        SAB_WRITE(sc,r,v)       \
                    119:     bus_space_write_1((sc)->sc_bt, (sc)->sc_bh, (r), (v))
                    120: #define        SAB_WRITE_BLOCK(sc,r,p,c)       \
                    121:     bus_space_write_region_1((sc)->sc_bt, (sc)->sc_bh, (r), (p), (c))
                    122:
                    123: int sab_match(struct device *, void *, void *);
                    124: void sab_attach(struct device *, struct device *, void *);
                    125: int sab_print(void *, const char *);
                    126: int sab_intr(void *);
                    127: void sab_softintr(void *);
                    128: void sab_cnputc(dev_t, int);
                    129: int sab_cngetc(dev_t);
                    130: void sab_cnpollc(dev_t, int);
                    131:
                    132: int sabtty_match(struct device *, void *, void *);
                    133: void sabtty_attach(struct device *, struct device *, void *);
                    134: void sabtty_start(struct tty *);
                    135: int sabtty_param(struct tty *, struct termios *);
                    136: int sabtty_intr(struct sabtty_softc *, int *);
                    137: void sabtty_softintr(struct sabtty_softc *);
                    138: int sabtty_mdmctrl(struct sabtty_softc *, int, int);
                    139: int sabtty_cec_wait(struct sabtty_softc *);
                    140: int sabtty_tec_wait(struct sabtty_softc *);
                    141: void sabtty_reset(struct sabtty_softc *);
                    142: void sabtty_flush(struct sabtty_softc *);
                    143: int sabtty_speed(int);
                    144: void sabtty_console_flags(struct sabtty_softc *);
                    145: void sabtty_cnpollc(struct sabtty_softc *, int);
                    146: void sabtty_shutdown(void *);
                    147: int sabttyparam(struct sabtty_softc *, struct tty *, struct termios *);
                    148:
                    149: int sabttyopen(dev_t, int, int, struct proc *);
                    150: int sabttyclose(dev_t, int, int, struct proc *);
                    151: int sabttyread(dev_t, struct uio *, int);
                    152: int sabttywrite(dev_t, struct uio *, int);
                    153: int sabttyioctl(dev_t, u_long, caddr_t, int, struct proc *);
                    154: int sabttystop(struct tty *, int);
                    155: struct tty *sabttytty(dev_t);
                    156: void sabtty_cnputc(struct sabtty_softc *, int);
                    157: int sabtty_cngetc(struct sabtty_softc *);
                    158: void sabtty_abort(struct sabtty_softc *);
                    159:
                    160: struct cfattach sab_ca = {
                    161:        sizeof(struct sab_softc), sab_match, sab_attach
                    162: };
                    163:
                    164: struct cfdriver sab_cd = {
                    165:        NULL, "sab", DV_DULL
                    166: };
                    167:
                    168: struct cfattach sabtty_ca = {
                    169:        sizeof(struct sabtty_softc), sabtty_match, sabtty_attach
                    170: };
                    171:
                    172: struct cfdriver sabtty_cd = {
                    173:        NULL, "sabtty", DV_TTY
                    174: };
                    175:
                    176: struct sabtty_rate {
                    177:        int baud;
                    178:        int n, m;
                    179: };
                    180:
                    181: struct sabtty_rate sabtty_baudtable[] = {
                    182:        {      50,      35,     10 },
                    183:        {      75,      47,     9 },
                    184:        {     110,      32,     9 },
                    185:        {     134,      53,     8 },
                    186:        {     150,      47,     8 },
                    187:        {     200,      35,     8 },
                    188:        {     300,      47,     7 },
                    189:        {     600,      47,     6 },
                    190:        {    1200,      47,     5 },
                    191:        {    1800,      31,     5 },
                    192:        {    2400,      47,     4 },
                    193:        {    4800,      47,     3 },
                    194:        {    9600,      47,     2 },
                    195:        {   19200,      47,     1 },
                    196:        {   38400,      23,     1 },
                    197:        {   57600,      15,     1 },
                    198:        {  115200,       7,     1 },
                    199:        {  230400,       3,     1 },
                    200:        {  460800,       1,     1 },
                    201:        {   76800,      11,     1 },
                    202:        {  153600,       5,     1 },
                    203:        {  307200,       3,     1 },
                    204:        {  614400,       3,     0 },
                    205:        {  921600,       0,     1 },
                    206: };
                    207:
                    208: int
                    209: sab_match(parent, match, aux)
                    210:        struct device *parent;
                    211:        void *match, *aux;
                    212: {
                    213:        struct ebus_attach_args *ea = aux;
                    214:        char *compat;
                    215:
                    216:        if (strcmp(ea->ea_name, "se") == 0)
                    217:                return (1);
                    218:        compat = getpropstring(ea->ea_node, "compatible");
                    219:        if (compat != NULL && !strcmp(compat, "sab82532"))
                    220:                return (1);
                    221:        return (0);
                    222: }
                    223:
                    224: void
                    225: sab_attach(parent, self, aux)
                    226:        struct device *parent;
                    227:        struct device *self;
                    228:        void *aux;
                    229: {
                    230:        struct sab_softc *sc = (struct sab_softc *)self;
                    231:        struct ebus_attach_args *ea = aux;
                    232:        u_int8_t r;
                    233:        u_int i;
                    234:
                    235:        sc->sc_bt = ea->ea_memtag;
                    236:        sc->sc_node = ea->ea_node;
                    237:
                    238:        /* Use prom mapping, if available. */
                    239:        if (ea->ea_nvaddrs) {
                    240:                if (bus_space_map(sc->sc_bt, ea->ea_vaddrs[0],
                    241:                    0, BUS_SPACE_MAP_PROMADDRESS, &sc->sc_bh) != 0) {
                    242:                        printf(": can't map register space\n");
                    243:                        return;
                    244:                }
                    245:        } else if (ebus_bus_map(sc->sc_bt, 0,
                    246:            EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 0, 0,
                    247:            &sc->sc_bh) != 0) {
                    248:                printf(": can't map register space\n");
                    249:                return;
                    250:        }
                    251:
                    252:        BUS_SPACE_SET_FLAGS(sc->sc_bt, sc->sc_bh, BSHDB_NO_ACCESS);
                    253:
                    254:        sc->sc_ih = bus_intr_establish(sc->sc_bt, ea->ea_intrs[0],
                    255:            IPL_TTY, 0, sab_intr, sc, self->dv_xname);
                    256:        if (sc->sc_ih == NULL) {
                    257:                printf(": can't map interrupt\n");
                    258:                return;
                    259:        }
                    260:
                    261:        sc->sc_softintr = softintr_establish(IPL_TTY, sab_softintr, sc);
                    262:        if (sc->sc_softintr == NULL) {
                    263:                printf(": can't get soft intr\n");
                    264:                return;
                    265:        }
                    266:
                    267:        printf(": rev ");
                    268:        r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_VMASK;
                    269:        switch (r) {
                    270:        case SAB_VSTR_V_1:
                    271:                printf("1");
                    272:                break;
                    273:        case SAB_VSTR_V_2:
                    274:                printf("2");
                    275:                break;
                    276:        case SAB_VSTR_V_32:
                    277:                printf("3.2");
                    278:                break;
                    279:        default:
                    280:                printf("unknown(0x%x)", r);
                    281:                break;
                    282:        }
                    283:        printf("\n");
                    284:
                    285:        /* Let current output drain */
                    286:        DELAY(100000);
                    287:
                    288:        /* Set all pins, except DTR pins to be inputs */
                    289:        SAB_WRITE(sc, SAB_PCR, ~(SAB_PVR_DTR_A | SAB_PVR_DTR_B));
                    290:        /* Disable port interrupts */
                    291:        SAB_WRITE(sc, SAB_PIM, 0xff);
                    292:        SAB_WRITE(sc, SAB_PVR, SAB_PVR_DTR_A | SAB_PVR_DTR_B | SAB_PVR_MAGIC);
                    293:        SAB_WRITE(sc, SAB_IPC, SAB_IPC_ICPL);
                    294:
                    295:        for (i = 0; i < SAB_NCHAN; i++) {
                    296:                struct sabtty_attach_args sta;
                    297:
                    298:                sta.sbt_portno = i;
                    299:                sc->sc_child[i] = (struct sabtty_softc *)config_found_sm(self,
                    300:                    &sta, sab_print, sabtty_match);
                    301:                if (sc->sc_child[i] != NULL)
                    302:                        sc->sc_nchild++;
                    303:        }
                    304: }
                    305:
                    306: int
                    307: sab_print(args, name)
                    308:        void *args;
                    309:        const char *name;
                    310: {
                    311:        struct sabtty_attach_args *sa = args;
                    312:
                    313:        if (name)
                    314:                printf("sabtty at %s", name);
                    315:        printf(" port %d", sa->sbt_portno);
                    316:        return (UNCONF);
                    317: }
                    318:
                    319: int
                    320: sab_intr(vsc)
                    321:        void *vsc;
                    322: {
                    323:        struct sab_softc *sc = vsc;
                    324:        int r = 0, needsoft = 0;
                    325:        u_int8_t gis;
                    326:
                    327:        gis = SAB_READ(sc, SAB_GIS);
                    328:
                    329:        /* channel A */
                    330:        if ((gis & (SAB_GIS_ISA1 | SAB_GIS_ISA0)) && sc->sc_child[0] &&
                    331:            sc->sc_child[0]->sc_tty)
                    332:                r |= sabtty_intr(sc->sc_child[0], &needsoft);
                    333:
                    334:        /* channel B */
                    335:        if ((gis & (SAB_GIS_ISB1 | SAB_GIS_ISB0)) && sc->sc_child[1] &&
                    336:            sc->sc_child[1]->sc_tty)
                    337:                r |= sabtty_intr(sc->sc_child[1], &needsoft);
                    338:
                    339:        if (needsoft)
                    340:                softintr_schedule(sc->sc_softintr);
                    341:
                    342:        return (r);
                    343: }
                    344:
                    345: void
                    346: sab_softintr(vsc)
                    347:        void *vsc;
                    348: {
                    349:        struct sab_softc *sc = vsc;
                    350:
                    351:        if (sc->sc_child[0] && sc->sc_child[0]->sc_tty)
                    352:                sabtty_softintr(sc->sc_child[0]);
                    353:        if (sc->sc_child[1] && sc->sc_child[1]->sc_tty)
                    354:                sabtty_softintr(sc->sc_child[1]);
                    355: }
                    356:
                    357: int
                    358: sabtty_match(parent, match, aux)
                    359:        struct device *parent;
                    360:        void *match, *aux;
                    361: {
                    362:        struct sabtty_attach_args *sa = aux;
                    363:
                    364:        if (sa->sbt_portno < SAB_NCHAN)
                    365:                return (1);
                    366:        return (0);
                    367: }
                    368:
                    369: void
                    370: sabtty_attach(parent, self, aux)
                    371:        struct device *parent;
                    372:        struct device *self;
                    373:        void *aux;
                    374: {
                    375:        struct sabtty_softc *sc = (struct sabtty_softc *)self;
                    376:        struct sabtty_attach_args *sa = aux;
                    377:        int r;
                    378:
                    379:        sc->sc_tty = ttymalloc();
                    380:        sc->sc_tty->t_oproc = sabtty_start;
                    381:        sc->sc_tty->t_param = sabtty_param;
                    382:
                    383:        sc->sc_parent = (struct sab_softc *)parent;
                    384:        sc->sc_bt = sc->sc_parent->sc_bt;
                    385:        sc->sc_portno = sa->sbt_portno;
                    386:        sc->sc_rend = sc->sc_rbuf + SABTTY_RBUF_SIZE;
                    387:
                    388:        switch (sa->sbt_portno) {
                    389:        case 0: /* port A */
                    390:                sc->sc_pvr_dtr = SAB_PVR_DTR_A;
                    391:                sc->sc_pvr_dsr = SAB_PVR_DSR_A;
                    392:                r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh,
                    393:                    SAB_CHAN_A, SAB_CHANLEN, &sc->sc_bh);
                    394:                break;
                    395:        case 1: /* port B */
                    396:                sc->sc_pvr_dtr = SAB_PVR_DTR_B;
                    397:                sc->sc_pvr_dsr = SAB_PVR_DSR_B;
                    398:                r = bus_space_subregion(sc->sc_bt, sc->sc_parent->sc_bh,
                    399:                    SAB_CHAN_B, SAB_CHANLEN, &sc->sc_bh);
                    400:                break;
                    401:        default:
                    402:                printf(": invalid channel: %u\n", sa->sbt_portno);
                    403:                return;
                    404:        }
                    405:        if (r != 0) {
                    406:                printf(": failed to allocate register subregion\n");
                    407:                return;
                    408:        }
                    409:
                    410:        sabtty_console_flags(sc);
                    411:
                    412:        if (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) {
                    413:                struct termios t;
                    414:                char *acc;
                    415:
                    416:                switch (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) {
                    417:                case SABTTYF_CONS_IN:
                    418:                        acc = "input";
                    419:                        break;
                    420:                case SABTTYF_CONS_OUT:
                    421:                        acc = "output";
                    422:                        break;
                    423:                case SABTTYF_CONS_IN|SABTTYF_CONS_OUT:
                    424:                default:
                    425:                        acc = "i/o";
                    426:                        break;
                    427:                }
                    428:
                    429:                if (sc->sc_flags & SABTTYF_CONS_OUT) {
                    430:                        /* Let current output drain */
                    431:                        DELAY(100000);
                    432:                }
                    433:
                    434:                t.c_ispeed = 0;
                    435:                t.c_ospeed = 9600;
                    436:                t.c_cflag = CREAD | CS8 | HUPCL;
                    437:                sc->sc_tty->t_ospeed = 0;
                    438:                sabttyparam(sc, sc->sc_tty, &t);
                    439:
                    440:                if (sc->sc_flags & SABTTYF_CONS_IN) {
                    441:                        sabtty_cons_input = sc;
                    442:                        cn_tab->cn_pollc = sab_cnpollc;
                    443:                        cn_tab->cn_getc = sab_cngetc;
                    444:                        cn_tab->cn_dev = makedev(77/*XXX*/, self->dv_unit);
                    445:                        shutdownhook_establish(sabtty_shutdown, sc);
                    446:                }
                    447:
                    448:                if (sc->sc_flags & SABTTYF_CONS_OUT) {
                    449:                        sabtty_cons_output = sc;
                    450:                        cn_tab->cn_putc = sab_cnputc;
                    451:                        cn_tab->cn_dev = makedev(77/*XXX*/, self->dv_unit);
                    452:                }
                    453:                printf(": console %s", acc);
                    454:        } else {
                    455:                /* Not a console... */
                    456:                sabtty_reset(sc);
                    457:        }
                    458:
                    459:        printf("\n");
                    460: }
                    461:
                    462: int
                    463: sabtty_intr(sc, needsoftp)
                    464:        struct sabtty_softc *sc;
                    465:        int *needsoftp;
                    466: {
                    467:        u_int8_t isr0, isr1;
                    468:        int i, len = 0, needsoft = 0, r = 0, clearfifo = 0;
                    469:
                    470:        isr0 = SAB_READ(sc, SAB_ISR0);
                    471:        isr1 = SAB_READ(sc, SAB_ISR1);
                    472:
                    473:        if (isr0 || isr1)
                    474:                r = 1;
                    475:
                    476:        if (isr0 & SAB_ISR0_RPF) {
                    477:                len = 32;
                    478:                clearfifo = 1;
                    479:        }
                    480:        if (isr0 & SAB_ISR0_TCD) {
                    481:                len = (32 - 1) & SAB_READ(sc, SAB_RBCL);
                    482:                clearfifo = 1;
                    483:        }
                    484:        if (isr0 & SAB_ISR0_TIME) {
                    485:                sabtty_cec_wait(sc);
                    486:                SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD);
                    487:        }
                    488:        if (isr0 & SAB_ISR0_RFO) {
                    489:                sc->sc_flags |= SABTTYF_RINGOVERFLOW;
                    490:                clearfifo = 1;
                    491:        }
                    492:        if (len != 0) {
                    493:                u_int8_t *ptr;
                    494:
                    495:                ptr = sc->sc_rput;
                    496:                for (i = 0; i < len; i++) {
                    497:                        *ptr++ = SAB_READ(sc, SAB_RFIFO);
                    498:                        if (ptr == sc->sc_rend)
                    499:                                ptr = sc->sc_rbuf;
                    500:                        if (ptr == sc->sc_rget) {
                    501:                                if (ptr == sc->sc_rbuf)
                    502:                                        ptr = sc->sc_rend;
                    503:                                ptr--;
                    504:                                sc->sc_flags |= SABTTYF_RINGOVERFLOW;
                    505:                        }
                    506:                }
                    507:                sc->sc_rput = ptr;
                    508:                needsoft = 1;
                    509:        }
                    510:
                    511:        if (clearfifo) {
                    512:                sabtty_cec_wait(sc);
                    513:                SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC);
                    514:        }
                    515:
                    516:        if (isr0 & SAB_ISR0_CDSC) {
                    517:                sc->sc_flags |= SABTTYF_CDCHG;
                    518:                needsoft = 1;
                    519:        }
                    520:
                    521:        if (isr1 & SAB_ISR1_BRKT)
                    522:                sabtty_abort(sc);
                    523:
                    524:        if (isr1 & (SAB_ISR1_XPR | SAB_ISR1_ALLS)) {
                    525:                if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_XFW) &&
                    526:                    (sc->sc_flags & SABTTYF_STOP) == 0) {
                    527:                        if (sc->sc_txc < 32)
                    528:                                len = sc->sc_txc;
                    529:                        else
                    530:                                len = 32;
                    531:
                    532:                        if (len > 0) {
                    533:                                SAB_WRITE_BLOCK(sc, SAB_XFIFO, sc->sc_txp, len);
                    534:                                sc->sc_txp += len;
                    535:                                sc->sc_txc -= len;
                    536:
                    537:                                sabtty_cec_wait(sc);
                    538:                                SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XF);
                    539:
                    540:                                /*
                    541:                                 * Prevent the false end of xmit from
                    542:                                 * confusing things below.
                    543:                                 */
                    544:                                isr1 &= ~SAB_ISR1_ALLS;
                    545:                        }
                    546:                }
                    547:
                    548:                if ((sc->sc_txc == 0) || (sc->sc_flags & SABTTYF_STOP)) {
                    549:                        if ((sc->sc_imr1 & SAB_IMR1_XPR) == 0) {
                    550:                                sc->sc_imr1 |= SAB_IMR1_XPR;
                    551:                                sc->sc_imr1 &= ~SAB_IMR1_ALLS;
                    552:                                SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
                    553:                        }
                    554:                }
                    555:        }
                    556:
                    557:        if ((isr1 & SAB_ISR1_ALLS) && ((sc->sc_txc == 0) ||
                    558:            (sc->sc_flags & SABTTYF_STOP))) {
                    559:                if (sc->sc_flags & SABTTYF_TXDRAIN)
                    560:                        wakeup(sc);
                    561:                sc->sc_flags &= ~SABTTYF_STOP;
                    562:                sc->sc_flags |= SABTTYF_DONE;
                    563:                sc->sc_imr1 |= SAB_IMR1_ALLS;
                    564:                SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
                    565:                needsoft = 1;
                    566:        }
                    567:
                    568:        if (needsoft)
                    569:                *needsoftp = needsoft;
                    570:        return (r);
                    571: }
                    572:
                    573: void
                    574: sabtty_softintr(sc)
                    575:        struct sabtty_softc *sc;
                    576: {
                    577:        struct tty *tp = sc->sc_tty;
                    578:        int s, flags;
                    579:        u_int8_t r;
                    580:
                    581:        if (tp == NULL)
                    582:                return;
                    583:
                    584:        if ((tp->t_state & TS_ISOPEN) == 0)
                    585:                return;
                    586:
                    587:        while (sc->sc_rget != sc->sc_rput) {
                    588:                int data;
                    589:                u_int8_t stat;
                    590:
                    591:                data = sc->sc_rget[0];
                    592:                stat = sc->sc_rget[1];
                    593:                sc->sc_rget += 2;
                    594:                if (stat & SAB_RSTAT_PE)
                    595:                        data |= TTY_PE;
                    596:                if (stat & SAB_RSTAT_FE)
                    597:                        data |= TTY_FE;
                    598:                if (sc->sc_rget == sc->sc_rend)
                    599:                        sc->sc_rget = sc->sc_rbuf;
                    600:
                    601:                (*linesw[tp->t_line].l_rint)(data, tp);
                    602:        }
                    603:
                    604:        s = splhigh();
                    605:        flags = sc->sc_flags;
                    606:        sc->sc_flags &= ~(SABTTYF_DONE|SABTTYF_CDCHG|SABTTYF_RINGOVERFLOW);
                    607:        splx(s);
                    608:
                    609:        if (flags & SABTTYF_CDCHG) {
                    610:                s = spltty();
                    611:                r = SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD;
                    612:                splx(s);
                    613:
                    614:                (*linesw[tp->t_line].l_modem)(tp, r);
                    615:        }
                    616:
                    617:        if (flags & SABTTYF_RINGOVERFLOW)
                    618:                log(LOG_WARNING, "%s: ring overflow\n", sc->sc_dv.dv_xname);
                    619:
                    620:        if (flags & SABTTYF_DONE) {
                    621:                ndflush(&tp->t_outq, sc->sc_txp - tp->t_outq.c_cf);
                    622:                tp->t_state &= ~TS_BUSY;
                    623:                (*linesw[tp->t_line].l_start)(tp);
                    624:        }
                    625: }
                    626:
                    627: int
                    628: sabttyopen(dev, flags, mode, p)
                    629:        dev_t dev;
                    630:        int flags, mode;
                    631:        struct proc *p;
                    632: {
                    633:        struct sab_softc *bc;
                    634:        struct sabtty_softc *sc;
                    635:        struct tty *tp;
                    636:        int card = SAB_CARD(dev), port = SAB_PORT(dev), s, s1;
                    637:
                    638:        if (card >= sab_cd.cd_ndevs)
                    639:                return (ENXIO);
                    640:        bc = sab_cd.cd_devs[card];
                    641:        if (bc == NULL)
                    642:                return (ENXIO);
                    643:
                    644:        if (port >= bc->sc_nchild)
                    645:                return (ENXIO);
                    646:        sc = bc->sc_child[port];
                    647:        if (sc == NULL)
                    648:                return (ENXIO);
                    649:
                    650:        tp = sc->sc_tty;
                    651:        tp->t_dev = dev;
                    652:
                    653:        if ((tp->t_state & TS_ISOPEN) == 0) {
                    654:                tp->t_state |= TS_WOPEN;
                    655:
                    656:                ttychars(tp);
                    657:                tp->t_iflag = TTYDEF_IFLAG;
                    658:                tp->t_oflag = TTYDEF_OFLAG;
                    659:                tp->t_cflag = TTYDEF_CFLAG;
                    660:                if (sc->sc_openflags & TIOCFLAG_CLOCAL)
                    661:                        tp->t_cflag |= CLOCAL;
                    662:                if (sc->sc_openflags & TIOCFLAG_CRTSCTS)
                    663:                        tp->t_cflag |= CRTSCTS;
                    664:                if (sc->sc_openflags & TIOCFLAG_MDMBUF)
                    665:                        tp->t_cflag |= MDMBUF;
                    666:                tp->t_lflag = TTYDEF_LFLAG;
                    667:                tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
                    668:
                    669:                sc->sc_rput = sc->sc_rget = sc->sc_rbuf;
                    670:
                    671:                s = spltty();
                    672:
                    673:                ttsetwater(tp);
                    674:
                    675:                s1 = splhigh();
                    676:                sabtty_reset(sc);
                    677:                sabtty_param(tp, &tp->t_termios);
                    678:                sc->sc_imr0 = SAB_IMR0_PERR | SAB_IMR0_FERR | SAB_IMR0_PLLA;
                    679:                SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0);
                    680:                sc->sc_imr1 = SAB_IMR1_BRK | SAB_IMR1_ALLS | SAB_IMR1_XDU |
                    681:                    SAB_IMR1_TIN | SAB_IMR1_CSC | SAB_IMR1_XMR | SAB_IMR1_XPR;
                    682:                SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
                    683:                SAB_WRITE(sc, SAB_CCR0, SAB_READ(sc, SAB_CCR0) | SAB_CCR0_PU);
                    684:                sabtty_cec_wait(sc);
                    685:                SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES);
                    686:                sabtty_cec_wait(sc);
                    687:                SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
                    688:                sabtty_cec_wait(sc);
                    689:                splx(s1);
                    690:
                    691:                sabtty_flush(sc);
                    692:
                    693:                if ((sc->sc_openflags & TIOCFLAG_SOFTCAR) ||
                    694:                    (SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD))
                    695:                        tp->t_state |= TS_CARR_ON;
                    696:                else
                    697:                        tp->t_state &= ~TS_CARR_ON;
                    698:        } else if ((tp->t_state & TS_XCLUDE) &&
                    699:            (!suser(p, 0))) {
                    700:                return (EBUSY);
                    701:        } else {
                    702:                s = spltty();
                    703:        }
                    704:
                    705:        if ((flags & O_NONBLOCK) == 0) {
                    706:                while ((tp->t_cflag & CLOCAL) == 0 &&
                    707:                    (tp->t_state & TS_CARR_ON) == 0) {
                    708:                        int error;
                    709:
                    710:                        tp->t_state |= TS_WOPEN;
                    711:                        error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
                    712:                            "sabttycd", 0);
                    713:                        if (error != 0) {
                    714:                                splx(s);
                    715:                                tp->t_state &= ~TS_WOPEN;
                    716:                                return (error);
                    717:                        }
                    718:                }
                    719:        }
                    720:
                    721:        splx(s);
                    722:
                    723:        s = (*linesw[tp->t_line].l_open)(dev, tp);
                    724:        if (s != 0) {
                    725:                if (tp->t_state & TS_ISOPEN)
                    726:                        return (s);
                    727:
                    728:                if (tp->t_cflag & HUPCL) {
                    729:                        sabtty_mdmctrl(sc, 0, DMSET);
                    730:                        (void)tsleep(sc, TTIPRI, ttclos, hz);
                    731:                }
                    732:
                    733:                if ((sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) == 0) {
                    734:                        /* Flush and power down if we're not the console */
                    735:                        sabtty_flush(sc);
                    736:                        sabtty_reset(sc);
                    737:                }
                    738:        }
                    739:        return (s);
                    740: }
                    741:
                    742: int
                    743: sabttyclose(dev, flags, mode, p)
                    744:        dev_t dev;
                    745:        int flags, mode;
                    746:        struct proc *p;
                    747: {
                    748:        struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)];
                    749:        struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)];
                    750:        struct tty *tp = sc->sc_tty;
                    751:        int s;
                    752:
                    753:        (*linesw[tp->t_line].l_close)(tp, flags);
                    754:
                    755:        s = spltty();
                    756:
                    757:        if ((tp->t_state & TS_ISOPEN) == 0) {
                    758:                /* Wait for output drain */
                    759:                sc->sc_imr1 &= ~SAB_IMR1_ALLS;
                    760:                SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
                    761:                sc->sc_flags |= SABTTYF_TXDRAIN;
                    762:                (void)tsleep(sc, TTIPRI, ttclos, 5 * hz);
                    763:                sc->sc_imr1 |= SAB_IMR1_ALLS;
                    764:                SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
                    765:                sc->sc_flags &= ~SABTTYF_TXDRAIN;
                    766:
                    767:                if (tp->t_cflag & HUPCL) {
                    768:                        sabtty_mdmctrl(sc, 0, DMSET);
                    769:                        (void)tsleep(bc, TTIPRI, ttclos, hz);
                    770:                }
                    771:
                    772:                if ((sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) == 0) {
                    773:                        /* Flush and power down if we're not the console */
                    774:                        sabtty_flush(sc);
                    775:                        sabtty_reset(sc);
                    776:                }
                    777:        }
                    778:
                    779:        ttyclose(tp);
                    780:        splx(s);
                    781:
                    782:        return (0);
                    783: }
                    784:
                    785: int
                    786: sabttyread(dev, uio, flags)
                    787:        dev_t dev;
                    788:        struct uio *uio;
                    789:        int flags;
                    790: {
                    791:        struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)];
                    792:        struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)];
                    793:        struct tty *tp = sc->sc_tty;
                    794:
                    795:        return ((*linesw[tp->t_line].l_read)(tp, uio, flags));
                    796: }
                    797:
                    798: int
                    799: sabttywrite(dev, uio, flags)
                    800:        dev_t dev;
                    801:        struct uio *uio;
                    802:        int flags;
                    803: {
                    804:        struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)];
                    805:        struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)];
                    806:        struct tty *tp = sc->sc_tty;
                    807:
                    808:        return ((*linesw[tp->t_line].l_write)(tp, uio, flags));
                    809: }
                    810:
                    811: int
                    812: sabttyioctl(dev, cmd, data, flags, p)
                    813:        dev_t dev;
                    814:        u_long cmd;
                    815:        caddr_t data;
                    816:        int flags;
                    817:        struct proc *p;
                    818: {
                    819:        struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)];
                    820:        struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)];
                    821:        struct tty *tp = sc->sc_tty;
                    822:        int error;
                    823:
                    824:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flags, p);
                    825:        if (error >= 0)
                    826:                return (error);
                    827:
                    828:        error = ttioctl(tp, cmd, data, flags, p);
                    829:        if (error >= 0)
                    830:                return (error);
                    831:
                    832:        error = 0;
                    833:
                    834:        switch (cmd) {
                    835:        case TIOCSBRK:
                    836:                SAB_WRITE(sc, SAB_DAFO,
                    837:                    SAB_READ(sc, SAB_DAFO) | SAB_DAFO_XBRK);
                    838:                break;
                    839:        case TIOCCBRK:
                    840:                SAB_WRITE(sc, SAB_DAFO,
                    841:                    SAB_READ(sc, SAB_DAFO) & ~SAB_DAFO_XBRK);
                    842:                break;
                    843:        case TIOCSDTR:
                    844:                sabtty_mdmctrl(sc, TIOCM_DTR, DMBIS);
                    845:                break;
                    846:        case TIOCCDTR:
                    847:                sabtty_mdmctrl(sc, TIOCM_DTR, DMBIC);
                    848:                break;
                    849:        case TIOCMBIS:
                    850:                sabtty_mdmctrl(sc, *((int *)data), DMBIS);
                    851:                break;
                    852:        case TIOCMBIC:
                    853:                sabtty_mdmctrl(sc, *((int *)data), DMBIC);
                    854:                break;
                    855:        case TIOCMGET:
                    856:                *((int *)data) = sabtty_mdmctrl(sc, 0, DMGET);
                    857:                break;
                    858:        case TIOCMSET:
                    859:                sabtty_mdmctrl(sc, *((int *)data), DMSET);
                    860:                break;
                    861:        case TIOCGFLAGS:
                    862:                *((int *)data) = sc->sc_openflags;
                    863:                break;
                    864:        case TIOCSFLAGS:
                    865:                if (suser(p, 0))
                    866:                        error = EPERM;
                    867:                else
                    868:                        sc->sc_openflags = *((int *)data) &
                    869:                            (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
                    870:                             TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
                    871:                break;
                    872:        default:
                    873:                error = ENOTTY;
                    874:        }
                    875:
                    876:        return (error);
                    877: }
                    878:
                    879: struct tty *
                    880: sabttytty(dev)
                    881:        dev_t dev;
                    882: {
                    883:        struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(dev)];
                    884:        struct sabtty_softc *sc = bc->sc_child[SAB_PORT(dev)];
                    885:
                    886:        return (sc->sc_tty);
                    887: }
                    888:
                    889: int
                    890: sabttystop(tp, flags)
                    891:        struct tty *tp;
                    892:        int flags;
                    893: {
                    894:        struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(tp->t_dev)];
                    895:        struct sabtty_softc *sc = bc->sc_child[SAB_PORT(tp->t_dev)];
                    896:        int s;
                    897:
                    898:        s = spltty();
                    899:        if (tp->t_state & TS_BUSY) {
                    900:                if ((tp->t_state & TS_TTSTOP) == 0)
                    901:                        tp->t_state |= TS_FLUSH;
                    902:                sc->sc_flags |= SABTTYF_STOP;
                    903:                sc->sc_imr1 &= ~SAB_IMR1_ALLS;
                    904:                SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
                    905:        }
                    906:        splx(s);
                    907:        return (0);
                    908: }
                    909:
                    910: int
                    911: sabtty_mdmctrl(sc, bits, how)
                    912:        struct sabtty_softc *sc;
                    913:        int bits, how;
                    914: {
                    915:        u_int8_t r;
                    916:        int s;
                    917:
                    918:        s = spltty();
                    919:        switch (how) {
                    920:        case DMGET:
                    921:                bits = 0;
                    922:                if (SAB_READ(sc, SAB_STAR) & SAB_STAR_CTS)
                    923:                        bits |= TIOCM_CTS;
                    924:                if ((SAB_READ(sc, SAB_VSTR) & SAB_VSTR_CD) == 0)
                    925:                        bits |= TIOCM_CD;
                    926:
                    927:                r = SAB_READ(sc, SAB_PVR);
                    928:                if ((r & sc->sc_pvr_dtr) == 0)
                    929:                        bits |= TIOCM_DTR;
                    930:                if ((r & sc->sc_pvr_dsr) == 0)
                    931:                        bits |= TIOCM_DSR;
                    932:
                    933:                r = SAB_READ(sc, SAB_MODE);
                    934:                if ((r & (SAB_MODE_RTS|SAB_MODE_FRTS)) == SAB_MODE_RTS)
                    935:                        bits |= TIOCM_RTS;
                    936:                break;
                    937:        case DMSET:
                    938:                r = SAB_READ(sc, SAB_MODE);
                    939:                if (bits & TIOCM_RTS) {
                    940:                        r &= ~SAB_MODE_FRTS;
                    941:                        r |= SAB_MODE_RTS;
                    942:                } else
                    943:                        r |= SAB_MODE_FRTS | SAB_MODE_RTS;
                    944:                SAB_WRITE(sc, SAB_MODE, r);
                    945:
                    946:                r = SAB_READ(sc, SAB_PVR);
                    947:                if (bits & TIOCM_DTR)
                    948:                        r &= ~sc->sc_pvr_dtr;
                    949:                else
                    950:                        r |= sc->sc_pvr_dtr;
                    951:                SAB_WRITE(sc, SAB_PVR, r);
                    952:                break;
                    953:        case DMBIS:
                    954:                if (bits & TIOCM_RTS) {
                    955:                        r = SAB_READ(sc, SAB_MODE);
                    956:                        r &= ~SAB_MODE_FRTS;
                    957:                        r |= SAB_MODE_RTS;
                    958:                        SAB_WRITE(sc, SAB_MODE, r);
                    959:                }
                    960:                if (bits & TIOCM_DTR) {
                    961:                        r = SAB_READ(sc, SAB_PVR);
                    962:                        r &= ~sc->sc_pvr_dtr;
                    963:                        SAB_WRITE(sc, SAB_PVR, r);
                    964:                }
                    965:                break;
                    966:        case DMBIC:
                    967:                if (bits & TIOCM_RTS) {
                    968:                        r = SAB_READ(sc, SAB_MODE);
                    969:                        r |= SAB_MODE_FRTS | SAB_MODE_RTS;
                    970:                        SAB_WRITE(sc, SAB_MODE, r);
                    971:                }
                    972:                if (bits & TIOCM_DTR) {
                    973:                        r = SAB_READ(sc, SAB_PVR);
                    974:                        r |= sc->sc_pvr_dtr;
                    975:                        SAB_WRITE(sc, SAB_PVR, r);
                    976:                }
                    977:                break;
                    978:        }
                    979:        splx(s);
                    980:        return (bits);
                    981: }
                    982:
                    983: int
                    984: sabttyparam(sc, tp, t)
                    985:        struct sabtty_softc *sc;
                    986:        struct tty *tp;
                    987:        struct termios *t;
                    988: {
                    989:        int s, ospeed;
                    990:        tcflag_t cflag;
                    991:        u_int8_t dafo, r;
                    992:
                    993:        ospeed = sabtty_speed(t->c_ospeed);
                    994:        if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
                    995:                return (EINVAL);
                    996:
                    997:        s = spltty();
                    998:
                    999:        /* hang up line if ospeed is zero, otherwise raise dtr */
                   1000:        sabtty_mdmctrl(sc, TIOCM_DTR,
                   1001:            (t->c_ospeed == 0) ? DMBIC : DMBIS);
                   1002:
                   1003:        dafo = SAB_READ(sc, SAB_DAFO);
                   1004:
                   1005:        cflag = t->c_cflag;
                   1006:
                   1007:        if (sc->sc_flags & (SABTTYF_CONS_IN | SABTTYF_CONS_OUT)) {
                   1008:                cflag |= CLOCAL;
                   1009:                cflag &= ~HUPCL;
                   1010:        }
                   1011:
                   1012:        if (cflag & CSTOPB)
                   1013:                dafo |= SAB_DAFO_STOP;
                   1014:        else
                   1015:                dafo &= ~SAB_DAFO_STOP;
                   1016:
                   1017:        dafo &= ~SAB_DAFO_CHL_CSIZE;
                   1018:        switch (cflag & CSIZE) {
                   1019:        case CS5:
                   1020:                dafo |= SAB_DAFO_CHL_CS5;
                   1021:                break;
                   1022:        case CS6:
                   1023:                dafo |= SAB_DAFO_CHL_CS6;
                   1024:                break;
                   1025:        case CS7:
                   1026:                dafo |= SAB_DAFO_CHL_CS7;
                   1027:                break;
                   1028:        default:
                   1029:                dafo |= SAB_DAFO_CHL_CS8;
                   1030:                break;
                   1031:        }
                   1032:
                   1033:        dafo &= ~SAB_DAFO_PARMASK;
                   1034:        if (cflag & PARENB) {
                   1035:                if (cflag & PARODD)
                   1036:                        dafo |= SAB_DAFO_PAR_ODD;
                   1037:                else
                   1038:                        dafo |= SAB_DAFO_PAR_EVEN;
                   1039:        } else
                   1040:                dafo |= SAB_DAFO_PAR_NONE;
                   1041:
                   1042:        if (ospeed != 0) {
                   1043:                SAB_WRITE(sc, SAB_BGR, ospeed & 0xff);
                   1044:                r = SAB_READ(sc, SAB_CCR2);
                   1045:                r &= ~(SAB_CCR2_BR9 | SAB_CCR2_BR8);
                   1046:                r |= (ospeed >> 2) & (SAB_CCR2_BR9 | SAB_CCR2_BR8);
                   1047:                SAB_WRITE(sc, SAB_CCR2, r);
                   1048:        }
                   1049:
                   1050:        r = SAB_READ(sc, SAB_MODE);
                   1051:        r |= SAB_MODE_RAC;
                   1052:        if (cflag & CRTSCTS) {
                   1053:                r &= ~(SAB_MODE_RTS | SAB_MODE_FCTS);
                   1054:                r |= SAB_MODE_FRTS;
                   1055:                sc->sc_imr1 &= ~SAB_IMR1_CSC;
                   1056:        } else {
                   1057:                r |= SAB_MODE_RTS | SAB_MODE_FCTS;
                   1058:                r &= ~SAB_MODE_FRTS;
                   1059:                sc->sc_imr1 |= SAB_IMR1_CSC;
                   1060:        }
                   1061:        SAB_WRITE(sc, SAB_MODE, r);
                   1062:        SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
                   1063:
                   1064:        tp->t_cflag = cflag;
                   1065:
                   1066:        splx(s);
                   1067:        return (0);
                   1068: }
                   1069:
                   1070: int
                   1071: sabtty_param(tp, t)
                   1072:        struct tty *tp;
                   1073:        struct termios *t;
                   1074: {
                   1075:        struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(tp->t_dev)];
                   1076:        struct sabtty_softc *sc = bc->sc_child[SAB_PORT(tp->t_dev)];
                   1077:
                   1078:        return (sabttyparam(sc, tp, t));
                   1079: }
                   1080:
                   1081: void
                   1082: sabtty_start(tp)
                   1083:        struct tty *tp;
                   1084: {
                   1085:        struct sab_softc *bc = sab_cd.cd_devs[SAB_CARD(tp->t_dev)];
                   1086:        struct sabtty_softc *sc = bc->sc_child[SAB_PORT(tp->t_dev)];
                   1087:        int s;
                   1088:
                   1089:        s = spltty();
                   1090:        if ((tp->t_state & (TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) == 0) {
                   1091:                if (tp->t_outq.c_cc <= tp->t_lowat) {
                   1092:                        if (tp->t_state & TS_ASLEEP) {
                   1093:                                tp->t_state &= ~TS_ASLEEP;
                   1094:                                wakeup(&tp->t_outq);
                   1095:                        }
                   1096:                        selwakeup(&tp->t_wsel);
                   1097:                }
                   1098:                if (tp->t_outq.c_cc) {
                   1099:                        sc->sc_txc = ndqb(&tp->t_outq, 0);
                   1100:                        sc->sc_txp = tp->t_outq.c_cf;
                   1101:                        tp->t_state |= TS_BUSY;
                   1102:                        sc->sc_imr1 &= ~(SAB_ISR1_XPR | SAB_ISR1_ALLS);
                   1103:                        SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
                   1104:                }
                   1105:        }
                   1106:        splx(s);
                   1107: }
                   1108:
                   1109: int
                   1110: sabtty_cec_wait(struct sabtty_softc *sc)
                   1111: {
                   1112:        int i = 50000;
                   1113:
                   1114:        for (;;) {
                   1115:                if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_CEC) == 0)
                   1116:                        return (0);
                   1117:                if (--i == 0)
                   1118:                        return (1);
                   1119:                DELAY(1);
                   1120:        }
                   1121: }
                   1122:
                   1123: int
                   1124: sabtty_tec_wait(struct sabtty_softc *sc)
                   1125: {
                   1126:        int i = 200000;
                   1127:
                   1128:        for (;;) {
                   1129:                if ((SAB_READ(sc, SAB_STAR) & SAB_STAR_TEC) == 0)
                   1130:                        return (0);
                   1131:                if (--i == 0)
                   1132:                        return (1);
                   1133:                DELAY(1);
                   1134:        }
                   1135: }
                   1136:
                   1137: void
                   1138: sabtty_reset(sc)
                   1139:        struct sabtty_softc *sc;
                   1140: {
                   1141:        /* power down */
                   1142:        SAB_WRITE(sc, SAB_CCR0, 0);
                   1143:
                   1144:        /* set basic configuration */
                   1145:        SAB_WRITE(sc, SAB_CCR0,
                   1146:            SAB_CCR0_MCE | SAB_CCR0_SC_NRZ | SAB_CCR0_SM_ASYNC);
                   1147:        SAB_WRITE(sc, SAB_CCR1, SAB_CCR1_ODS | SAB_CCR1_BCR | SAB_CCR1_CM_7);
                   1148:        SAB_WRITE(sc, SAB_CCR2, SAB_CCR2_BDF | SAB_CCR2_SSEL | SAB_CCR2_TOE);
                   1149:        SAB_WRITE(sc, SAB_CCR3, 0);
                   1150:        SAB_WRITE(sc, SAB_CCR4, SAB_CCR4_MCK4 | SAB_CCR4_EBRG);
                   1151:        SAB_WRITE(sc, SAB_MODE, SAB_MODE_RTS | SAB_MODE_FCTS | SAB_MODE_RAC);
                   1152:        SAB_WRITE(sc, SAB_RFC,
                   1153:            SAB_RFC_DPS | SAB_RFC_RFDF | SAB_RFC_RFTH_32CHAR);
                   1154:
                   1155:        /* clear interrupts */
                   1156:        sc->sc_imr0 = sc->sc_imr1 = 0xff;
                   1157:        SAB_WRITE(sc, SAB_IMR0, sc->sc_imr0);
                   1158:        SAB_WRITE(sc, SAB_IMR1, sc->sc_imr1);
                   1159:        SAB_READ(sc, SAB_ISR0);
                   1160:        SAB_READ(sc, SAB_ISR1);
                   1161: }
                   1162:
                   1163: void
                   1164: sabtty_flush(sc)
                   1165:        struct sabtty_softc *sc;
                   1166: {
                   1167:        /* clear rx fifo */
                   1168:        sabtty_cec_wait(sc);
                   1169:        SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
                   1170:
                   1171:        /* clear tx fifo */
                   1172:        sabtty_cec_wait(sc);
                   1173:        SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_XRES);
                   1174: }
                   1175:
                   1176: int
                   1177: sabtty_speed(rate)
                   1178:        int rate;
                   1179: {
                   1180:        int i, len, r;
                   1181:
                   1182:        if (rate == 0)
                   1183:                return (0);
                   1184:        len = sizeof(sabtty_baudtable)/sizeof(sabtty_baudtable[0]);
                   1185:        for (i = 0; i < len; i++) {
                   1186:                if (rate == sabtty_baudtable[i].baud) {
                   1187:                        r = sabtty_baudtable[i].n |
                   1188:                            (sabtty_baudtable[i].m << 6);
                   1189:                        return (r);
                   1190:                }
                   1191:        }
                   1192:        return (-1);
                   1193: }
                   1194:
                   1195: void
                   1196: sabtty_cnputc(sc, c)
                   1197:        struct sabtty_softc *sc;
                   1198:        int c;
                   1199: {
                   1200:        sabtty_tec_wait(sc);
                   1201:        SAB_WRITE(sc, SAB_TIC, c);
                   1202:        sabtty_tec_wait(sc);
                   1203: }
                   1204:
                   1205: int
                   1206: sabtty_cngetc(sc)
                   1207:        struct sabtty_softc *sc;
                   1208: {
                   1209:        u_int8_t r, len, ipc;
                   1210:
                   1211:        ipc = SAB_READ(sc, SAB_IPC);
                   1212:        SAB_WRITE(sc, SAB_IPC, ipc | SAB_IPC_VIS);
                   1213:
                   1214: again:
                   1215:        do {
                   1216:                r = SAB_READ(sc, SAB_STAR);
                   1217:        } while ((r & SAB_STAR_RFNE) == 0);
                   1218:
                   1219:        /*
                   1220:         * Ok, at least one byte in RFIFO, ask for permission to access RFIFO
                   1221:         * (I hate this chip... hate hate hate).
                   1222:         */
                   1223:        sabtty_cec_wait(sc);
                   1224:        SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RFRD);
                   1225:
                   1226:        /* Wait for RFIFO to come ready */
                   1227:        do {
                   1228:                r = SAB_READ(sc, SAB_ISR0);
                   1229:        } while ((r & SAB_ISR0_TCD) == 0);
                   1230:
                   1231:        len = SAB_READ(sc, SAB_RBCL) & (32 - 1);
                   1232:        if (len == 0)
                   1233:                goto again;     /* Shouldn't happen... */
                   1234:
                   1235:        r = SAB_READ(sc, SAB_RFIFO);
                   1236:
                   1237:        /*
                   1238:         * Blow away everything left in the FIFO...
                   1239:         */
                   1240:        sabtty_cec_wait(sc);
                   1241:        SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RMC);
                   1242:        SAB_WRITE(sc, SAB_IPC, ipc);
                   1243:        return (r);
                   1244: }
                   1245:
                   1246: void
                   1247: sabtty_cnpollc(sc, on)
                   1248:        struct sabtty_softc *sc;
                   1249:        int on;
                   1250: {
                   1251:        u_int8_t r;
                   1252:
                   1253:        if (on) {
                   1254:                if (sc->sc_polling)
                   1255:                        return;
                   1256:                SAB_WRITE(sc, SAB_IPC, SAB_READ(sc, SAB_IPC) | SAB_IPC_VIS);
                   1257:                r = sc->sc_pollrfc = SAB_READ(sc, SAB_RFC);
                   1258:                r &= ~(SAB_RFC_RFDF);
                   1259:                SAB_WRITE(sc, SAB_RFC, r);
                   1260:                sabtty_cec_wait(sc);
                   1261:                SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
                   1262:                sc->sc_polling = 1;
                   1263:        } else {
                   1264:                if (!sc->sc_polling)
                   1265:                        return;
                   1266:                SAB_WRITE(sc, SAB_IPC, SAB_READ(sc, SAB_IPC) & ~SAB_IPC_VIS);
                   1267:                SAB_WRITE(sc, SAB_RFC, sc->sc_pollrfc);
                   1268:                sabtty_cec_wait(sc);
                   1269:                SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
                   1270:                sc->sc_polling = 0;
                   1271:        }
                   1272: }
                   1273:
                   1274: void
                   1275: sab_cnputc(dev, c)
                   1276:        dev_t dev;
                   1277:        int c;
                   1278: {
                   1279:        struct sabtty_softc *sc = sabtty_cons_output;
                   1280:
                   1281:        if (sc == NULL)
                   1282:                return;
                   1283:        sabtty_cnputc(sc, c);
                   1284: }
                   1285:
                   1286: void
                   1287: sab_cnpollc(dev, on)
                   1288:        dev_t dev;
                   1289:        int on;
                   1290: {
                   1291:        struct sabtty_softc *sc = sabtty_cons_input;
                   1292:
                   1293:        sabtty_cnpollc(sc, on);
                   1294: }
                   1295:
                   1296: int
                   1297: sab_cngetc(dev)
                   1298:        dev_t dev;
                   1299: {
                   1300:        struct sabtty_softc *sc = sabtty_cons_input;
                   1301:
                   1302:        if (sc == NULL)
                   1303:                return (-1);
                   1304:        return (sabtty_cngetc(sc));
                   1305: }
                   1306:
                   1307: void
                   1308: sabtty_console_flags(sc)
                   1309:        struct sabtty_softc *sc;
                   1310: {
                   1311:        int node, channel, cookie;
                   1312:        u_int options;
                   1313:        char buf[255];
                   1314:
                   1315:        node = sc->sc_parent->sc_node;
                   1316:        channel = sc->sc_portno;
                   1317:
                   1318:        options = OF_finddevice("/options");
                   1319:
                   1320:        /* Default to channel 0 if there are no explicit prom args */
                   1321:        cookie = 0;
                   1322:
                   1323:        if (node == OF_instance_to_package(OF_stdin())) {
                   1324:                if (OF_getprop(options, "input-device", buf,
                   1325:                    sizeof(buf)) != -1) {
                   1326:                        if (strncmp("ttyb", buf, strlen("ttyb")) == 0)
                   1327:                                cookie = 1;
                   1328:                }
                   1329:
                   1330:                if (channel == cookie)
                   1331:                        sc->sc_flags |= SABTTYF_CONS_IN;
                   1332:        }
                   1333:
                   1334:        /* Default to same channel if there are no explicit prom args */
                   1335:
                   1336:        if (node == OF_instance_to_package(OF_stdout())) {
                   1337:                if (OF_getprop(options, "output-device", buf,
                   1338:                    sizeof(buf)) != -1) {
                   1339:                        if (strncmp("ttyb", buf, strlen("ttyb")) == 0)
                   1340:                                cookie = 1;
                   1341:                }
                   1342:
                   1343:                if (channel == cookie)
                   1344:                        sc->sc_flags |= SABTTYF_CONS_OUT;
                   1345:        }
                   1346: }
                   1347:
                   1348: void
                   1349: sabtty_abort(sc)
                   1350:        struct sabtty_softc *sc;
                   1351: {
                   1352:
                   1353:        if (sc->sc_flags & SABTTYF_CONS_IN) {
                   1354: #ifdef DDB
                   1355:                extern int db_active, db_console;
                   1356:
                   1357:                if (db_console == 0)
                   1358:                        return;
                   1359:                if (db_active == 0)
                   1360:                        Debugger();
                   1361:                else
                   1362:                        callrom();
                   1363: #else
                   1364:                callrom();
                   1365: #endif
                   1366:        }
                   1367: }
                   1368:
                   1369: void
                   1370: sabtty_shutdown(vsc)
                   1371:        void *vsc;
                   1372: {
                   1373:        struct sabtty_softc *sc = vsc;
                   1374:
                   1375:        /* Have to put the chip back into single char mode */
                   1376:        sc->sc_flags |= SABTTYF_DONTDDB;
                   1377:        SAB_WRITE(sc, SAB_RFC, SAB_READ(sc, SAB_RFC) & ~SAB_RFC_RFDF);
                   1378:        sabtty_cec_wait(sc);
                   1379:        SAB_WRITE(sc, SAB_CMDR, SAB_CMDR_RRES);
                   1380:        sabtty_cec_wait(sc);
                   1381:        SAB_WRITE(sc, SAB_IPC, SAB_READ(sc, SAB_IPC) | SAB_IPC_VIS);
                   1382: }

CVSweb