[BACK]Return to qsc.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / vxt

Annotation of sys/arch/vax/vxt/qsc.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: qsc.c,v 1.1 2006/08/27 16:55:41 miod Exp $    */
                      2: /*
                      3:  * Copyright (c) 2006 Miodrag Vallat.
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice, this permission notice, and the disclaimer below
                      8:  * appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18: /*
                     19:  * Mach Operating System
                     20:  * Copyright (c) 1993-1991 Carnegie Mellon University
                     21:  * All Rights Reserved.
                     22:  *
                     23:  * Permission to use, copy, modify and distribute this software and its
                     24:  * documentation is hereby granted, provided that both the copyright
                     25:  * notice and this permission notice appear in all copies of the
                     26:  * software, derivative works or modified versions, and any portions
                     27:  * thereof, and that both notices appear in supporting documentation.
                     28:  *
                     29:  * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     30:  * CONDITION.  CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
                     31:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     32:  *
                     33:  * Carnegie Mellon requests users of this software to return to
                     34:  *
                     35:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     36:  *  School of Computer Science
                     37:  *  Carnegie Mellon University
                     38:  *  Pittsburgh PA 15213-3890
                     39:  *
                     40:  * any improvements or extensions that they make and grant Carnegie the
                     41:  * rights to redistribute these changes.
                     42:  */
                     43:
                     44: #include <sys/param.h>
                     45: #include <sys/ioctl.h>
                     46: #include <sys/proc.h>
                     47: #include <sys/tty.h>
                     48: #include <sys/systm.h>
                     49: #include <sys/device.h>
                     50: #include <sys/syslog.h>
                     51: #include <sys/conf.h>
                     52:
                     53: #include <machine/bus.h>
                     54: #include <machine/nexus.h>
                     55: #include <machine/sid.h>
                     56:
                     57: #include <dev/cons.h>
                     58:
                     59: #include <vax/vxt/vxtbusvar.h>
                     60:
                     61: #include <vax/vxt/qscreg.h>
                     62: #include <vax/vxt/qscvar.h>
                     63:
                     64: #ifdef DDB
                     65: #include <machine/cpu.h>
                     66: #include <ddb/db_var.h>
                     67: #endif
                     68:
                     69: #include "qsckbd.h"
                     70: #include "qscms.h"
                     71:
                     72: struct cfdriver qsc_cd = {
                     73:        NULL, "qsc", DV_TTY
                     74: };
                     75:
                     76: /* console storage */
                     77: struct qsc_sv_reg qsccn_sv;
                     78:
                     79: /* prototypes */
                     80: cdev_decl(qsc);
                     81: cons_decl(qsc);
                     82: int    qscintr(void *);
                     83: int    qscparam(struct tty *, struct termios *);
                     84: void   qscrint(struct qscsoftc *, u_int);
                     85: int    qscspeed(int);
                     86: void   qscstart(struct tty *);
                     87: struct tty *qsctty(dev_t);
                     88: void   qscxint(struct qscsoftc *, u_int);
                     89:
                     90: /*
                     91:  * Registers are mapped as the least-significant byte of 32-bit
                     92:  * addresses. The following macros hide this.
                     93:  */
                     94:
                     95: #define        qsc_readp(sc, reg) \
                     96:        bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, 4 * (reg))
                     97: #define        qsc_read(sc, line, reg) \
                     98:        bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, \
                     99:            (sc)->sc_regaddr[line][reg])
                    100: #define        qsc_writep(sc, reg, val) \
                    101:        bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, 4 * (reg), (val))
                    102: #define        qsc_write(sc, line, reg, val) \
                    103:        bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, \
                    104:            (sc)->sc_regaddr[line][reg], (val))
                    105:
                    106: #define SC_LINE(dev)   (minor(dev))
                    107:
                    108: /*
                    109:  * Attachment glue.
                    110:  */
                    111:
                    112: int    qsc_match(struct device *parent, void *self, void *aux);
                    113: void   qsc_attach(struct device *parent, struct device *self, void *aux);
                    114: int    qsc_print(void *, const char *);
                    115:
                    116: struct cfattach qsc_ca = {
                    117:        sizeof(struct qscsoftc), qsc_match, qsc_attach
                    118: };
                    119:
                    120: int
                    121: qsc_match(struct device *parent, void *cf, void *aux)
                    122: {
                    123:        struct bp_conf *bp = aux;
                    124:
                    125:        if (strcmp(bp->type, qsc_cd.cd_name) == 0)
                    126:                return (1);
                    127:        return (0);
                    128: }
                    129:
                    130: void
                    131: qsc_attach(struct device *parent, struct device *self, void *aux)
                    132: {
                    133:        extern struct vax_bus_space vax_mem_bus_space;
                    134:        struct qscsoftc *sc = (struct qscsoftc *)self;
                    135:        bus_space_handle_t ioh;
                    136:        u_int line, pair, reg;
                    137: #if NQSCKBD > 0 || NQSCMS > 0
                    138:        struct qsc_attach_args qa;
                    139: #endif
                    140:
                    141:        sc->sc_iot = &vax_mem_bus_space;
                    142:        if (bus_space_map(sc->sc_iot, QSCADDR, VAX_NBPG, 0, &ioh) != 0) {
                    143:                printf(": can't map registers!\n");
                    144:                return;
                    145:        }
                    146:        sc->sc_ioh = ioh;
                    147:
                    148:        if (cn_tab->cn_putc == qsccnputc) {
                    149:                sc->sc_console = 1;
                    150:                printf(": console");
                    151:        }
                    152:
                    153:        /*
                    154:         * Initialize line-specific data (register addresses)
                    155:         */
                    156:
                    157:        for (line = 0; line < SC_NLINES; line++) {
                    158:                sc->sc_regaddr[line][SC_MR] = line * 8 + SC_MRA;
                    159:                sc->sc_regaddr[line][SC_CSR] = line * 8 + SC_CSRA;
                    160:                sc->sc_regaddr[line][SC_CR] = line * 8 + SC_CRA;
                    161:                sc->sc_regaddr[line][SC_TXFIFO] = line * 8 + SC_TXFIFOA;
                    162:
                    163:                sc->sc_regaddr[line][SC_IOPCR] = (line < 2 ? 0 : 0x10) +
                    164:                    (line & 1) + SC_IOPCRA;
                    165:
                    166:                sc->sc_regaddr[line][SC_ACR] = (line < 2 ? 0 : 0x10) + SC_ACRAB;
                    167:                sc->sc_regaddr[line][SC_IMR] = (line < 2 ? 0 : 0x10) + SC_IMRAB;
                    168:                sc->sc_regaddr[line][SC_OPR] = (line < 2 ? 0 : 0x10) + SC_OPRAB;
                    169:        }
                    170:        for (line = 0; line < SC_NLINES; line++)
                    171:                for (reg = 0; reg < SC_LOGICAL; reg++)
                    172:                        sc->sc_regaddr[line][reg] =
                    173:                            0 + 4 * sc->sc_regaddr[line][reg];
                    174:
                    175:        /*
                    176:         * Initialize all lines.
                    177:         */
                    178:        sc->sc_sv_reg = sc->sc_console ? &qsccn_sv : &sc->sc_sv_reg_storage;
                    179:        for (line = 0; line < SC_NLINES; line++) {
                    180:                /* do not reinitialize the console line... */
                    181:                if (sc->sc_console && line == QSC_LINE_SERIAL)
                    182:                        continue;
                    183:
                    184:                sc->sc_sv_reg->sv_mr1[line] =
                    185:                    (line == 3 ? ODDPAR | PAREN : PARDIS) | RXRTS | CL8;
                    186:                sc->sc_sv_reg->sv_mr2[line] = /* TXCTS | */ SB1;
                    187:                sc->sc_sv_reg->sv_csr[line] = line < 2 ? BD9600 : BD4800;
                    188:                sc->sc_sv_reg->sv_cr[line]  = TXEN | RXEN;
                    189:
                    190:                pair = line >> 1;
                    191:
                    192:                if (sc->sc_console && pair == (QSC_LINE_SERIAL >> 1))
                    193:                        continue;
                    194:
                    195:                /* Start out with Tx and RX interrupts disabled */
                    196:                sc->sc_sv_reg->sv_imr[pair] = 0;
                    197:        }
                    198:
                    199:        for (line = 0; line < SC_NLINES; line++) {
                    200:                /* do not reset the console line... */
                    201:                if (sc->sc_console && line == QSC_LINE_SERIAL)
                    202:                        continue;
                    203:
                    204:                qsc_write(sc, line, SC_CR, RXRESET | TXDIS | RXDIS);
                    205:                DELAY(1);
                    206:                qsc_write(sc, line, SC_CR, TXRESET | TXDIS | RXDIS);
                    207:                DELAY(1);
                    208:                qsc_write(sc, line, SC_CR, ERRRESET | TXDIS | RXDIS);
                    209:                DELAY(1);
                    210:                qsc_write(sc, line, SC_CR, BRKINTRESET | TXDIS | RXDIS);
                    211:                DELAY(1);
                    212:                qsc_write(sc, line, SC_CR, MRZERO | TXDIS | RXDIS);
                    213:                DELAY(1);
                    214:
                    215:                qsc_write(sc, line, SC_MR, 0);
                    216:                qsc_write(sc, line, SC_MR, sc->sc_sv_reg->sv_mr1[line]);
                    217:                qsc_write(sc, line, SC_MR, sc->sc_sv_reg->sv_mr2[line]);
                    218:                qsc_write(sc, line, SC_CSR, sc->sc_sv_reg->sv_csr[line]);
                    219:                qsc_write(sc, line, SC_CR, sc->sc_sv_reg->sv_cr[line]);
                    220:                DELAY(1);
                    221:        }
                    222:
                    223:        for (pair = 0; pair < SC_NLINES / 2; pair++)
                    224:                qsc_write(sc, pair << 1, SC_IMR,
                    225:                    sc->sc_sv_reg->sv_imr[pair]);
                    226:
                    227:        for (line = 0; line < SC_NLINES; line++) {
                    228:                sc->sc_tty[line] = NULL;
                    229:                sc->sc_swflags[line] = 0;
                    230:        }
                    231:        if (sc->sc_console)
                    232:                sc->sc_swflags[QSC_LINE_SERIAL] |= TIOCFLAG_SOFTCAR;
                    233:
                    234:        printf("\n");
                    235:
                    236:        /*
                    237:         * Configure interrupts. We are bidding in 2681 mode for now.
                    238:         */
                    239:
                    240:        qsc_writep(sc, SC_ICR, 0x00);
                    241:        for (line = SC_BIDCRA; line <= SC_BIDCRD; line++)
                    242:                qsc_writep(sc, line, 0x00);
                    243:        qsc_writep(sc, SC_IVR, VXT_INTRVEC >> 2);
                    244:
                    245:        vxtbus_intr_establish(self->dv_xname, IPL_TTY, qscintr, sc);
                    246:
                    247:        /*
                    248:         * Attach subdevices, and enable RX and TX interrupts on their lines
                    249:         * if successful.
                    250:         */
                    251: #if NQSCKBD > 0
                    252:        /* keyboard */
                    253:        qa.qa_line = QSC_LINE_KEYBOARD;
                    254:        qa.qa_console = !sc->sc_console;
                    255:        qa.qa_hook = &sc->sc_hook[QSC_LINE_KEYBOARD];
                    256:        if (config_found(self, &qa, qsc_print) != NULL)
                    257:                sc->sc_sv_reg->sv_imr[QSC_LINE_KEYBOARD >> 1] |= IRXRDYA;
                    258: #endif
                    259: #if NQSCMS > 0
                    260:        /* mouse */
                    261:        qa.qa_line = QSC_LINE_MOUSE;
                    262:        qa.qa_console = 0;
                    263:        qa.qa_hook = &sc->sc_hook[QSC_LINE_MOUSE];
                    264:        if (config_found(self, &qa, qsc_print) != NULL)
                    265:                sc->sc_sv_reg->sv_imr[QSC_LINE_MOUSE >> 1] |= IRXRDYB;
                    266: #endif
                    267:
                    268:        for (pair = 0; pair < SC_NLINES / 2; pair++)
                    269:                qsc_write(sc, pair << 1, SC_IMR,
                    270:                    sc->sc_sv_reg->sv_imr[pair]);
                    271:
                    272:        sc->sc_rdy = 1;
                    273: }
                    274:
                    275: /* speed tables */
                    276: const struct qsc_s {
                    277:        int kspeed;
                    278:        int dspeed;
                    279: } qsc_speeds[] = {
                    280:        { B0,           0       },      /* 0 baud, special HUP condition */
                    281:         { B50,         NOBAUD  },      /* 50 baud, not implemented */
                    282:        { B75,          BD75    },      /* 75 baud */
                    283:        { B110,         BD110   },      /* 110 baud */
                    284:        { B134,         BD134   },      /* 134.5 baud */
                    285:        { B150,         BD150   },      /* 150 baud */
                    286:        { B200,         NOBAUD  },      /* 200 baud, not implemented */
                    287:        { B300,         BD300   },      /* 300 baud */
                    288:        { B600,         BD600   },      /* 600 baud */
                    289:        { B1200,        BD1200  },      /* 1200 baud */
                    290:        { B1800,        BD1800  },      /* 1800 baud */
                    291:        { B2400,        BD2400  },      /* 2400 baud */
                    292:        { B4800,        BD4800  },      /* 4800 baud */
                    293:        { B9600,        BD9600  },      /* 9600 baud */
                    294:        { B19200,       BD19200 },      /* 19200 baud */
                    295:        { -1,           NOBAUD  },      /* anything more is uncivilized */
                    296: };
                    297:
                    298: int
                    299: qscspeed(int speed)
                    300: {
                    301:        const struct qsc_s *ds;
                    302:
                    303:        for (ds = qsc_speeds; ds->kspeed != -1; ds++)
                    304:                if (ds->kspeed == speed)
                    305:                        return ds->dspeed;
                    306:
                    307:        return NOBAUD;
                    308: }
                    309:
                    310: struct tty *
                    311: qsctty(dev_t dev)
                    312: {
                    313:        u_int line;
                    314:        struct qscsoftc *sc;
                    315:
                    316:        line = SC_LINE(dev);
                    317:        if (qsc_cd.cd_ndevs == 0 || line >= SC_NLINES)
                    318:                return (NULL);
                    319:
                    320:        sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
                    321:        if (sc == NULL)
                    322:                return (NULL);
                    323:
                    324:        return sc->sc_tty[line];
                    325: }
                    326:
                    327: void
                    328: qscstart(struct tty *tp)
                    329: {
                    330:        struct qscsoftc *sc;
                    331:        dev_t dev;
                    332:        int s;
                    333:        u_int line;
                    334:        int c, tries;
                    335:
                    336:        if ((tp->t_state & TS_ISOPEN) == 0)
                    337:                return;
                    338:
                    339:        dev = tp->t_dev;
                    340:        line = SC_LINE(dev);
                    341:        sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
                    342:
                    343:        s = spltty();
                    344:
                    345:        if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
                    346:                goto bail;
                    347:
                    348:        if (tp->t_outq.c_cc <= tp->t_lowat) {
                    349:                if (tp->t_state & TS_ASLEEP) {
                    350:                        tp->t_state &= ~TS_ASLEEP;
                    351:                        wakeup((caddr_t)&tp->t_outq);
                    352:                }
                    353:                selwakeup(&tp->t_wsel);
                    354:                if (tp->t_outq.c_cc == 0)
                    355:                        goto bail;
                    356:        }
                    357:
                    358:        tp->t_state |= TS_BUSY;
                    359:        while (tp->t_outq.c_cc != 0) {
                    360:
                    361:                /* load transmitter until it is full */
                    362:                for (tries = 10000; tries != 0; tries --)
                    363:                        if (qsc_read(sc, line, SC_SR) & TXRDY)
                    364:                                break;
                    365:
                    366:                if (tries == 0) {
                    367:                        timeout_add(&tp->t_rstrt_to, 1);
                    368:                        tp->t_state |= TS_TIMEOUT;
                    369:                        break;
                    370:                } else {
                    371:                        c = getc(&tp->t_outq);
                    372:
                    373:                        qsc_write(sc, line, SC_TXFIFO, c & 0xff);
                    374:
                    375:                        sc->sc_sv_reg->sv_imr[line >> 1] |=
                    376:                            line & 1 ? ITXRDYB : ITXRDYA;
                    377:                        qsc_write(sc, line, SC_IMR,
                    378:                            sc->sc_sv_reg->sv_imr[line >> 1]);
                    379:                }
                    380:        }
                    381:        tp->t_state &= ~TS_BUSY;
                    382:
                    383: bail:
                    384:        splx(s);
                    385: }
                    386:
                    387: int
                    388: qscstop(struct tty *tp, int flag)
                    389: {
                    390:        int s;
                    391:
                    392:        s = spltty();
                    393:        if (tp->t_state & TS_BUSY) {
                    394:                if ((tp->t_state & TS_TTSTOP) == 0)
                    395:                        tp->t_state |= TS_FLUSH;
                    396:        }
                    397:        splx(s);
                    398:
                    399:        return 0;
                    400: }
                    401:
                    402: int
                    403: qscioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                    404: {
                    405:        int error;
                    406:        u_int line;
                    407:        struct tty *tp;
                    408:        struct qscsoftc *sc;
                    409:
                    410:        line = SC_LINE(dev);
                    411:        sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
                    412:
                    413:        tp = sc->sc_tty[line];
                    414:        if (tp == NULL)
                    415:                return (ENXIO);
                    416:
                    417:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
                    418:        if (error >= 0)
                    419:                return(error);
                    420:
                    421:        error = ttioctl(tp, cmd, data, flag, p);
                    422:        if (error >= 0)
                    423:                return(error);
                    424:
                    425:        switch (cmd) {
                    426:        case TIOCGFLAGS:
                    427:                *(int *)data = sc->sc_swflags[line];
                    428:                break;
                    429:        case TIOCSFLAGS:
                    430:                error = suser(p, 0);
                    431:                if (error != 0)
                    432:                        return (EPERM);
                    433:
                    434:                sc->sc_swflags[line] = *(int *)data &
                    435:                    /* only allow valid flags */
                    436:                    (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
                    437:                break;
                    438:        default:
                    439:                return (ENOTTY);
                    440:        }
                    441:
                    442:        return (0);
                    443: }
                    444:
                    445: int
                    446: qscparam(struct tty *tp, struct termios *t)
                    447: {
                    448:        int flags;
                    449:        u_int line, pair;
                    450:        int speeds;
                    451:        u_int8_t mr1, mr2;
                    452:        struct qscsoftc *sc;
                    453:        dev_t dev;
                    454:
                    455:        dev = tp->t_dev;
                    456:        line = SC_LINE(dev);
                    457:        pair = line >> 1;
                    458:        sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
                    459:
                    460:        tp->t_ispeed = t->c_ispeed;
                    461:        tp->t_ospeed = t->c_ospeed;
                    462:        tp->t_cflag = t->c_cflag;
                    463:
                    464:        flags = tp->t_flags;
                    465:
                    466:        /* disable Tx and Rx */
                    467:        if (sc->sc_console == 0 || line != QSC_LINE_SERIAL) {
                    468:                if (line & 1)
                    469:                        sc->sc_sv_reg->sv_imr[pair] &= ~(ITXRDYB | IRXRDYB);
                    470:                else
                    471:                        sc->sc_sv_reg->sv_imr[pair] &= ~(ITXRDYA | IRXRDYA);
                    472:                qsc_write(sc, line, SC_IMR, sc->sc_sv_reg->sv_imr[pair]);
                    473:
                    474:                /* set baudrate */
                    475:                speeds = qscspeed(tp->t_ispeed);
                    476:                if (speeds == NOBAUD)
                    477:                        speeds = DEFBAUD;
                    478:                qsc_write(sc, line, SC_CSR, speeds);
                    479:                sc->sc_sv_reg->sv_csr[line] = speeds;
                    480:
                    481:                /* get saved mode registers and clear set up parameters */
                    482:                mr1 = sc->sc_sv_reg->sv_mr1[line];
                    483:                mr1 &= ~(CLMASK | PARTYPEMASK | PARMODEMASK);
                    484:
                    485:                mr2 = sc->sc_sv_reg->sv_mr2[line];
                    486:                mr2 &= ~SBMASK;
                    487:
                    488:                /* set up character size */
                    489:                switch (t->c_cflag & CSIZE) {
                    490:                case CL8:
                    491:                        mr1 |= CL8;
                    492:                        break;
                    493:                case CL7:
                    494:                        mr1 |= CL7;
                    495:                        break;
                    496:                case CL6:
                    497:                        mr1 |= CL6;
                    498:                        break;
                    499:                case CL5:
                    500:                        mr1 |= CL5;
                    501:                        break;
                    502:                }
                    503:
                    504:                /* set up stop bits */
                    505:                if (tp->t_ospeed == B110)
                    506:                        mr2 |= SB2;
                    507:                else
                    508:                        mr2 |= SB1;
                    509:
                    510:                /* set up parity */
                    511:                if (t->c_cflag & PARENB) {
                    512:                        mr1 |= PAREN;
                    513:                        if (t->c_cflag & PARODD)
                    514:                                mr1 |= ODDPAR;
                    515:                        else
                    516:                                mr1 |= EVENPAR;
                    517:                } else
                    518:                        mr1 |= PARDIS;
                    519:
                    520:                if (sc->sc_sv_reg->sv_mr1[line] != mr1 ||
                    521:                    sc->sc_sv_reg->sv_mr2[line] != mr2) {
                    522:                        /* write mode registers to duart */
                    523:                        qsc_write(sc, line, SC_CR, MRONE);
                    524:                        DELAY(1);
                    525:                        qsc_write(sc, line, SC_MR, mr1);
                    526:                        qsc_write(sc, line, SC_MR, mr2);
                    527:
                    528:                        /* save changed mode registers */
                    529:                        sc->sc_sv_reg->sv_mr1[line] = mr1;
                    530:                        sc->sc_sv_reg->sv_mr2[line] = mr2;
                    531:                }
                    532:        }
                    533:
                    534:        /* enable transmitter? */
                    535:        if (tp->t_state & TS_BUSY) {
                    536:                sc->sc_sv_reg->sv_imr[pair] |= line & 1 ? ITXRDYB : ITXRDYA;
                    537:        }
                    538:
                    539:        /* re-enable the receiver */
                    540:        sc->sc_sv_reg->sv_imr[pair] |= line & 1 ? IRXRDYB : IRXRDYA;
                    541:        qsc_write(sc, line, SC_IMR, sc->sc_sv_reg->sv_imr[pair]);
                    542:
                    543:        return (0);
                    544: }
                    545:
                    546: int
                    547: qscopen(dev_t dev, int flag, int mode, struct proc *p)
                    548: {
                    549:        int s;
                    550:        u_int line;
                    551:        struct qscsoftc *sc;
                    552:        struct tty *tp;
                    553:
                    554:        line = SC_LINE(dev);
                    555:        if (qsc_cd.cd_ndevs == 0 || line >= SC_NLINES)
                    556:                return (ENXIO);
                    557:        /* Line B is not wired... */
                    558:        if (line == QSC_LINE_DEAD)
                    559:                return (ENXIO);
                    560:        sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
                    561:        if (sc == NULL)
                    562:                return (ENXIO);
                    563:
                    564:        /* if some other device is using the line, it's not available */
                    565:        if (sc->sc_hook[line].fn != NULL)
                    566:                return (ENXIO);
                    567:
                    568:        s = spltty();
                    569:        if (sc->sc_tty[line] != NULL)
                    570:                tp = sc->sc_tty[line];
                    571:        else
                    572:                tp = sc->sc_tty[line] = ttymalloc();
                    573:
                    574:        tp->t_oproc = qscstart;
                    575:        tp->t_param = qscparam;
                    576:        tp->t_dev = dev;
                    577:
                    578:        if ((tp->t_state & TS_ISOPEN) == 0) {
                    579:                ttychars(tp);
                    580:
                    581:                if (tp->t_ispeed == 0) {
                    582:                        tp->t_iflag = TTYDEF_IFLAG;
                    583:                        tp->t_oflag = TTYDEF_OFLAG;
                    584:                        tp->t_lflag = TTYDEF_LFLAG;
                    585:                        tp->t_ispeed = tp->t_ospeed = B9600;
                    586:                        if (sc->sc_console && line == QSC_LINE_SERIAL) {
                    587:                                /* console is 8N1 */
                    588:                                tp->t_cflag = (CREAD | CS8 | HUPCL);
                    589:                        } else {
                    590:                                tp->t_cflag = TTYDEF_CFLAG;
                    591:                        }
                    592:                }
                    593:
                    594:                if (sc->sc_swflags[line] & TIOCFLAG_CLOCAL)
                    595:                        tp->t_cflag |= CLOCAL;
                    596:                if (sc->sc_swflags[line] & TIOCFLAG_CRTSCTS)
                    597:                        tp->t_cflag |= CRTSCTS;
                    598:                if (sc->sc_swflags[line] & TIOCFLAG_MDMBUF)
                    599:                        tp->t_cflag |= MDMBUF;
                    600:
                    601:                qscparam(tp, &tp->t_termios);
                    602:                ttsetwater(tp);
                    603:
                    604:                tp->t_state |= TS_CARR_ON;
                    605:        } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
                    606:                splx(s);
                    607:                return (EBUSY);
                    608:        }
                    609:
                    610:        /*
                    611:         * Reset the tty pointer, as there could have been a dialout
                    612:         * use of the tty with a dialin open waiting.
                    613:         */
                    614:        tp->t_dev = dev;
                    615:        splx(s);
                    616:        return ((*linesw[tp->t_line].l_open)(dev, tp));
                    617: }
                    618:
                    619: int
                    620: qscclose(dev_t dev, int flag, int mode, struct proc *p)
                    621: {
                    622:        struct tty *tp;
                    623:        struct qscsoftc *sc;
                    624:        u_int line;
                    625:
                    626:        line = SC_LINE(dev);
                    627:        sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
                    628:
                    629:        tp = sc->sc_tty[line];
                    630:        (*linesw[tp->t_line].l_close)(tp, flag);
                    631:        ttyclose(tp);
                    632:
                    633:        return (0);
                    634: }
                    635:
                    636: int
                    637: qscread(dev_t dev, struct uio *uio, int flag)
                    638: {
                    639:        u_int line;
                    640:        struct tty *tp;
                    641:        struct qscsoftc *sc;
                    642:
                    643:        line = SC_LINE(dev);
                    644:        sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
                    645:
                    646:        tp = sc->sc_tty[line];
                    647:        if (tp == NULL)
                    648:                return (ENXIO);
                    649:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
                    650: }
                    651:
                    652: int
                    653: qscwrite(dev_t dev, struct uio *uio, int flag)
                    654: {
                    655:        u_int line;
                    656:        struct tty *tp;
                    657:        struct qscsoftc *sc;
                    658:
                    659:        line = SC_LINE(dev);
                    660:        sc = (struct qscsoftc *)qsc_cd.cd_devs[0];
                    661:
                    662:        tp = sc->sc_tty[line];
                    663:        if (tp == NULL)
                    664:                return (ENXIO);
                    665:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
                    666: }
                    667:
                    668: void
                    669: qscrint(struct qscsoftc *sc, u_int line)
                    670: {
                    671:        struct tty *tp;
                    672:        int data;
                    673:        unsigned char sr;
                    674:        int overrun = 0;
                    675:
                    676:        tp = sc->sc_tty[line];
                    677:
                    678:        /* read status reg */
                    679:        while ((sr = qsc_read(sc, line, SC_SR)) & RXRDY) {
                    680:                /* read data and reset receiver */
                    681:                data = qsc_read(sc, line, SC_RXFIFO);
                    682:
                    683:                if (sr & RBRK) {
                    684:                        /* clear break state */
                    685:                        qsc_write(sc, line, SC_CR, BRKINTRESET);
                    686:                        DELAY(1);
                    687:                        qsc_write(sc, line, SC_CR, ERRRESET);
                    688:                        DELAY(1);
                    689:                        continue;
                    690:                }
                    691:
                    692:                if ((sr & ROVRN) && cold == 0 && overrun == 0) {
                    693:                        log(LOG_WARNING, "%s line %d: receiver overrun\n",
                    694:                            sc->sc_dev.dv_xname, line);
                    695:                        overrun = 1;
                    696:                }
                    697:
                    698:                if (sr & FRERR)
                    699:                        data |= TTY_FE;
                    700:                if (sr & PERR)
                    701:                        data |= TTY_PE;
                    702:
                    703:                /* clear error state */
                    704:                if (sr & (ROVRN | FRERR | PERR)) {
                    705:                        qsc_write(sc, line, SC_CR, ERRRESET);
                    706:                        DELAY(1);
                    707:                }
                    708:
                    709:                if (sc->sc_hook[line].fn != NULL) {
                    710:                        if ((data & TTY_ERRORMASK) != 0 ||
                    711:                           (*sc->sc_hook[line].fn)(sc->sc_hook[line].arg, data))
                    712:                        continue;
                    713:                }
                    714:
                    715:                if ((tp->t_state & (TS_ISOPEN|TS_WOPEN)) == 0 &&
                    716:                    (sc->sc_console == 0 || line != QSC_LINE_SERIAL)) {
                    717:                        continue;
                    718:                }
                    719:
                    720:                /* no errors */
                    721: #if defined(DDB)
                    722:                if (tp->t_dev == cn_tab->cn_dev) {
                    723:                        int j = kdbrint(data);
                    724:
                    725:                        if (j == 1)
                    726:                                continue;
                    727:
                    728:                        if (j == 2)
                    729:                                (*linesw[tp->t_line].l_rint)(27, tp);
                    730:                }
                    731: #endif
                    732:                (*linesw[tp->t_line].l_rint)(data, tp);
                    733:        }
                    734: }
                    735:
                    736: void
                    737: qscxint(struct qscsoftc *sc, u_int line)
                    738: {
                    739:        struct tty *tp;
                    740:        u_int pair;
                    741:
                    742:        tp = sc->sc_tty[line];
                    743:
                    744:        if ((tp->t_state & (TS_ISOPEN|TS_WOPEN))==0)
                    745:                goto out;
                    746:
                    747:        if (tp->t_state & TS_BUSY) {
                    748:                tp->t_state &= ~(TS_BUSY | TS_FLUSH);
                    749:                qscstart(tp);
                    750:                if (tp->t_state & TS_BUSY) {
                    751:                        /* do not disable transmitter, yet */
                    752:                        return;
                    753:                }
                    754:        }
                    755: out:
                    756:
                    757:        /* disable transmitter */
                    758:        pair = line >> 1;
                    759:        sc->sc_sv_reg->sv_imr[pair] &= line & 1 ? ~ITXRDYB : ~ITXRDYA;
                    760:        qsc_write(sc, line, SC_IMR, sc->sc_sv_reg->sv_imr[pair]);
                    761: }
                    762:
                    763: int
                    764: qscintr(void *arg)
                    765: {
                    766:        struct qscsoftc *sc = arg;
                    767:        u_int8_t isr[SC_NLINES >> 1], curisr;
                    768:        u_int pair, line;
                    769:        int rc = 0;
                    770:
                    771:        for (pair = 0; pair < SC_NLINES >> 1; pair++) {
                    772:                line = pair << 1;
                    773:
                    774:                /* read interrupt status register and mask with imr */
                    775:                isr[pair] = curisr = qsc_read(sc, line, SC_ISR);
                    776:                curisr &= sc->sc_sv_reg->sv_imr[pair];
                    777:                if (curisr == 0)
                    778:                        continue;
                    779:
                    780:                rc = 1;
                    781:
                    782:                if (curisr & IRXRDYA)
                    783:                        qscrint(sc, line);
                    784:                if (curisr & ITXRDYA)
                    785:                        qscxint(sc, line);
                    786:                if (curisr & IBRKA) {
                    787:                        qsc_write(sc, line, SC_CR, BRKINTRESET);
                    788:                        DELAY(1);
                    789:                }
                    790:
                    791:                if (curisr & IRXRDYB)
                    792:                        qscrint(sc, line + 1);
                    793:                if (curisr & ITXRDYB)
                    794:                        qscxint(sc, line + 1);
                    795:                if (curisr & IBRKB) {
                    796:                        qsc_write(sc, line + 1, SC_CR, BRKINTRESET);
                    797:                        DELAY(1);
                    798:                }
                    799:        }
                    800:
                    801:        return (rc);
                    802: }
                    803:
                    804: /*
                    805:  * Console interface routines.
                    806:  */
                    807:
                    808: vaddr_t qsc_cnregs;
                    809: #define        qsc_cnread(reg) \
                    810:        *(volatile u_int8_t *)(qsc_cnregs + 4 * (reg))
                    811: #define        qsc_cnwrite(reg, val) \
                    812:        *(volatile u_int8_t *)(qsc_cnregs + 4 * (reg)) = (val)
                    813:
                    814: void
                    815: qsccnprobe(struct consdev *cp)
                    816: {
                    817:        int maj;
                    818:        extern int getmajor(void *);
                    819:        extern vaddr_t iospace;
                    820:
                    821:        if (vax_boardtype != VAX_BTYP_VXT)
                    822:                return;
                    823:
                    824:        /* locate the major number */
                    825:        if ((maj = getmajor(qscopen)) < 0)
                    826:                return;
                    827:
                    828:        qsc_cnregs = iospace;
                    829:        ioaccess(iospace, QSCADDR, 1);
                    830:
                    831:        cp->cn_dev = makedev(maj, QSC_LINE_SERIAL);
                    832:        cp->cn_pri = vax_confdata & 2 ? CN_NORMAL : CN_REMOTE;
                    833: }
                    834:
                    835: void
                    836: qsccninit(cp)
                    837:        struct consdev *cp;
                    838: {
                    839:        qsccn_sv.sv_mr1[QSC_LINE_SERIAL] = PARDIS | RXRTS | CL8;
                    840:        qsccn_sv.sv_mr2[QSC_LINE_SERIAL] = /* TXCTS | */ SB1;
                    841:        qsccn_sv.sv_csr[QSC_LINE_SERIAL] = BD9600;
                    842:        qsccn_sv.sv_cr[QSC_LINE_SERIAL]  = TXEN | RXEN;
                    843:        qsccn_sv.sv_imr[QSC_LINE_SERIAL] = 0;
                    844:
                    845:        qsc_cnwrite(SC_CRA, RXRESET | TXDIS | RXDIS);
                    846:        DELAY(1);
                    847:        qsc_cnwrite(SC_CRA, TXRESET | TXDIS | RXDIS);
                    848:        DELAY(1);
                    849:        qsc_cnwrite(SC_CRA, ERRRESET | TXDIS | RXDIS);
                    850:        DELAY(1);
                    851:        qsc_cnwrite(SC_CRA, BRKINTRESET | TXDIS | RXDIS);
                    852:        DELAY(1);
                    853:        qsc_cnwrite(SC_CRA, MRZERO | TXDIS | RXDIS);
                    854:        DELAY(1);
                    855:
                    856:        qsc_cnwrite(SC_MRA, 0);
                    857:        qsc_cnwrite(SC_MRA, qsccn_sv.sv_mr1[QSC_LINE_SERIAL]);
                    858:        qsc_cnwrite(SC_MRA, qsccn_sv.sv_mr2[QSC_LINE_SERIAL]);
                    859:        qsc_cnwrite(SC_CSRA, qsccn_sv.sv_csr[QSC_LINE_SERIAL]);
                    860:        qsc_cnwrite(SC_CRA, qsccn_sv.sv_cr[QSC_LINE_SERIAL]);
                    861:        DELAY(1);
                    862:
                    863:        qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL]);
                    864:        qsc_cnwrite(SC_IMRCD, 0);
                    865: }
                    866:
                    867: int
                    868: qsccngetc(dev_t dev)
                    869: {
                    870:        unsigned char sr;       /* status reg of line a/b */
                    871:        u_char c;               /* received character */
                    872:        int s;
                    873:
                    874:        s = spltty();
                    875:
                    876:        /* disable interrupts for this line and enable receiver */
                    877:        qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL] & ~ITXRDYA);
                    878:        qsc_cnwrite(SC_CRA, RXEN);
                    879:        DELAY(1);
                    880:
                    881:        for (;;) {
                    882:                /* read status reg */
                    883:                sr = qsc_cnread(SC_SRA);
                    884:
                    885:                /* receiver interrupt handler*/
                    886:                if (sr & RXRDY) {
                    887:                        /* read character from line */
                    888:                        c = qsc_cnread(SC_RXFIFOA);
                    889:
                    890:                        /* check break condition */
                    891:                        if (sr & RBRK) {
                    892:                                /* clear break state */
                    893:                                qsc_cnwrite(SC_CRA, BRKINTRESET);
                    894:                                DELAY(1);
                    895:                                qsc_cnwrite(SC_CRA, ERRRESET);
                    896:                                DELAY(1);
                    897:                                break;
                    898:                        }
                    899:
                    900:                        if (sr & (FRERR | PERR | ROVRN)) {
                    901:                                /* clear error state */
                    902:                                qsc_cnwrite(SC_CRA, ERRRESET);
                    903:                                DELAY(1);
                    904:                        } else {
                    905:                                break;
                    906:                        }
                    907:                }
                    908:        }
                    909:
                    910:        /* restore the previous state */
                    911:        qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL]);
                    912:        qsc_cnwrite(SC_CRA, qsccn_sv.sv_cr[QSC_LINE_SERIAL]);
                    913:
                    914:        splx(s);
                    915:
                    916:        return ((int)c);
                    917: }
                    918:
                    919: void
                    920: qsccnputc(dev_t dev, int c)
                    921: {
                    922:        int s;
                    923:
                    924:        if (mfpr(PR_MAPEN) == 0)
                    925:                return;
                    926:
                    927:        s = spltty();
                    928:
                    929:        /* disable interrupts for this line and enable transmitter */
                    930:        qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL] & ~ITXRDYA);
                    931:        qsc_cnwrite(SC_CRA, TXEN);
                    932:        DELAY(1);
                    933:
                    934:        while ((qsc_cnread(SC_SRA) & TXRDY) == 0)
                    935:                ;
                    936:        qsc_cnwrite(SC_TXFIFOA, c);
                    937:
                    938:        /* wait for transmitter to empty */
                    939:        while ((qsc_cnread(SC_SRA) & TXEMT) == 0)
                    940:                ;
                    941:
                    942:        /* restore the previous state */
                    943:        qsc_cnwrite(SC_IMRAB, qsccn_sv.sv_imr[QSC_LINE_SERIAL]);
                    944:        qsc_cnwrite(SC_CRA, qsccn_sv.sv_cr[QSC_LINE_SERIAL]);
                    945:        DELAY(1);
                    946:
                    947:        splx(s);
                    948: }
                    949:
                    950: void
                    951: qsccnpollc(dev, pollflag)
                    952:        dev_t dev;
                    953:        int pollflag;
                    954: {
                    955: }
                    956:
                    957: /*
                    958:  * Keyboard and mouse helper routines
                    959:  */
                    960:
                    961: #if NQSCKBD > 0 || NQSCMS > 0
                    962: int
                    963: qsc_print(void *aux, const char *name)
                    964: {
                    965:        struct qsc_attach_args *qa = aux;
                    966:
                    967:        if (name != NULL)
                    968:                printf(qa->qa_line == QSC_LINE_KEYBOARD ?
                    969:                    "lkkbd at %s" : "lkms at %s", name);
                    970:        else
                    971:                printf(" line %d", qa->qa_line);
                    972:
                    973:        return (UNCONF);
                    974: }
                    975:
                    976: int
                    977: qscgetc(u_int line)
                    978: {
                    979:        bus_addr_t craddr;
                    980:        struct qscsoftc *sc = NULL;
                    981:        int s;
                    982:        u_int8_t sr, imr, imrmask, cr, c;
                    983:
                    984:        s = spltty();
                    985:
                    986:        craddr = line == QSC_LINE_KEYBOARD ? SC_CRC : SC_CRD;
                    987:        imrmask = line & 1 ? ~IRXRDYB : ~IRXRDYA;
                    988:        imr = sc != NULL ? sc->sc_sv_reg->sv_imr[line / 2] : 0;
                    989:        cr = sc != NULL ? sc->sc_sv_reg->sv_cr[line] : 0;
                    990:
                    991:        /* disable interrupts for this line and enable receiver */
                    992:        qsc_cnwrite(SC_IMRCD, imr & imrmask);
                    993:        qsc_cnwrite(craddr, RXEN);
                    994:        DELAY(1);
                    995:
                    996:        for (;;) {
                    997:                /* read status reg */
                    998:                sr = qsc_cnread(line == QSC_LINE_KEYBOARD ? SC_SRC : SC_SRD);
                    999:
                   1000:                /* receiver interrupt handler*/
                   1001:                if (sr & RXRDY) {
                   1002:                        /* read character from line */
                   1003:                        c = qsc_cnread(line == QSC_LINE_KEYBOARD ?
                   1004:                            SC_RXFIFOC : SC_RXFIFOD);
                   1005:
                   1006:                        /* check break condition */
                   1007:                        if (sr & RBRK) {
                   1008:                                /* clear break state */
                   1009:                                qsc_cnwrite(craddr, BRKINTRESET);
                   1010:                                DELAY(1);
                   1011:                                qsc_cnwrite(craddr, ERRRESET);
                   1012:                                DELAY(1);
                   1013:                                break;
                   1014:                        }
                   1015:
                   1016:                        if (sr & (FRERR | PERR | ROVRN)) {
                   1017:                                /* clear error state */
                   1018:                                qsc_cnwrite(craddr, ERRRESET);
                   1019:                                DELAY(1);
                   1020:                        } else {
                   1021:                                break;
                   1022:                        }
                   1023:                }
                   1024:        }
                   1025:
                   1026:        /* restore the previous state */
                   1027:        qsc_cnwrite(SC_IMRCD, imr);
                   1028:        qsc_cnwrite(craddr, cr);
                   1029:        DELAY(1);
                   1030:
                   1031:        splx(s);
                   1032:
                   1033:        return ((int)c);
                   1034: }
                   1035:
                   1036: void
                   1037: qscputc(u_int line, int c)
                   1038: {
                   1039:        bus_addr_t craddr;
                   1040:        struct qscsoftc *sc = NULL;
                   1041:        int s;
                   1042:        u_int8_t imr, imrmask, cr;
                   1043:
                   1044:        s = spltty();
                   1045:
                   1046:        if (qsc_cd.cd_ndevs != 0 &&
                   1047:            (sc = (struct qscsoftc *)qsc_cd.cd_devs[0]) != NULL)
                   1048:                if (sc->sc_rdy == 0)
                   1049:                        sc = NULL;
                   1050:
                   1051:        craddr = line == QSC_LINE_KEYBOARD ? SC_CRC : SC_CRD;
                   1052:        imrmask = line & 1 ? ~ITXRDYB : ~ITXRDYA;
                   1053:        imr = sc != NULL ? sc->sc_sv_reg->sv_imr[line / 2] : 0;
                   1054:        cr = sc != NULL ? sc->sc_sv_reg->sv_cr[line] : 0;
                   1055:
                   1056:        /* disable interrupts for this line and enable transmitter */
                   1057:        qsc_cnwrite(SC_IMRCD, imr & imrmask);
                   1058:        qsc_cnwrite(craddr, TXEN);
                   1059:        DELAY(1);
                   1060:
                   1061:        while ((qsc_cnread(line == QSC_LINE_KEYBOARD ? SC_SRC : SC_SRD) &
                   1062:            TXRDY) == 0)
                   1063:                ;
                   1064:        qsc_cnwrite(line == QSC_LINE_KEYBOARD ? SC_TXFIFOC : SC_TXFIFOD, c);
                   1065:
                   1066:        /* wait for transmitter to empty */
                   1067:        while ((qsc_cnread(line == QSC_LINE_KEYBOARD ? SC_SRC : SC_SRD) &
                   1068:            TXEMT) == 0)
                   1069:                ;
                   1070:
                   1071:        /* restore the previous state */
                   1072:        qsc_cnwrite(SC_IMRCD, imr);
                   1073:        qsc_cnwrite(craddr, cr);
                   1074:        DELAY(1);
                   1075:
                   1076:        splx(s);
                   1077: }
                   1078: #endif

CVSweb