[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     ! 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