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

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

1.1       nbrk        1: /*     $OpenBSD: comkbd_ebus.c,v 1.18 2005/11/11 16:44:51 miod Exp $   */
                      2:
                      3: /*
                      4:  * Copyright (c) 2002 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: #include <sys/param.h>
                     35: #include <sys/systm.h>
                     36: #include <sys/proc.h>
                     37: #include <sys/device.h>
                     38: #include <sys/conf.h>
                     39: #include <sys/file.h>
                     40: #include <sys/ioctl.h>
                     41: #include <sys/malloc.h>
                     42: #include <sys/tty.h>
                     43: #include <sys/time.h>
                     44: #include <sys/kernel.h>
                     45: #include <sys/syslog.h>
                     46:
                     47: #include <machine/bus.h>
                     48: #include <machine/autoconf.h>
                     49: #include <machine/openfirm.h>
                     50:
                     51: #include <sparc64/dev/ebusreg.h>
                     52: #include <sparc64/dev/ebusvar.h>
                     53:
                     54: #include <dev/wscons/wsconsio.h>
                     55: #include <dev/wscons/wskbdvar.h>
                     56:
                     57: #include <dev/sun/sunkbdreg.h>
                     58: #include <dev/sun/sunkbdvar.h>
                     59:
                     60: #include <dev/ic/comreg.h>
                     61: #include <dev/ic/comvar.h>
                     62: #include <dev/ic/ns16550reg.h>
                     63:
                     64: #include <dev/cons.h>
                     65:
                     66: #define        COMK_RX_RING    64
                     67: #define        COMK_TX_RING    64
                     68:
                     69: struct comkbd_softc {
                     70:        struct sunkbd_softc     sc_base;
                     71:
                     72:        bus_space_tag_t sc_iot;         /* bus tag */
                     73:        bus_space_handle_t sc_ioh;      /* bus handle */
                     74:        void *sc_ih, *sc_si;            /* interrupt vectors */
                     75:
                     76:        u_int sc_rxcnt;
                     77:        u_int8_t sc_rxbuf[COMK_RX_RING];
                     78:        u_int8_t *sc_rxbeg, *sc_rxend, *sc_rxget, *sc_rxput;
                     79:
                     80:        u_int sc_txcnt;
                     81:        u_int8_t sc_txbuf[COMK_TX_RING];
                     82:        u_int8_t *sc_txbeg, *sc_txend, *sc_txget, *sc_txput;
                     83:
                     84:        u_int8_t sc_ier;
                     85: };
                     86:
                     87: #define        COM_WRITE(sc,r,v) \
                     88:     bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (r), (v))
                     89: #define        COM_READ(sc,r) \
                     90:     bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (r))
                     91:
                     92: int comkbd_match(struct device *, void *, void *);
                     93: void comkbd_attach(struct device *, struct device *, void *);
                     94: int comkbd_iskbd(int);
                     95:
                     96: /* wskbd glue */
                     97: void comkbd_cnpollc(void *, int);
                     98: void comkbd_cngetc(void *, u_int *, int *);
                     99:
                    100: /* internals */
                    101: int comkbd_enqueue(void *, u_int8_t *, u_int);
                    102: int comkbd_init(struct comkbd_softc *);
                    103: void comkbd_putc(struct comkbd_softc *, u_int8_t);
                    104: int comkbd_intr(void *);
                    105: void comkbd_soft(void *);
                    106:
                    107: struct cfattach comkbd_ca = {
                    108:        sizeof(struct comkbd_softc), comkbd_match, comkbd_attach
                    109: };
                    110:
                    111: struct cfdriver comkbd_cd = {
                    112:        NULL, "comkbd", DV_DULL
                    113: };
                    114:
                    115: const char *comkbd_names[] = {
                    116:        "su",
                    117:        "su_pnp",
                    118:        NULL
                    119: };
                    120:
                    121: struct wskbd_consops comkbd_consops = {
                    122:        comkbd_cngetc,
                    123:        comkbd_cnpollc
                    124: };
                    125:
                    126: int
                    127: comkbd_iskbd(node)
                    128:        int node;
                    129: {
                    130:        if (OF_getproplen(node, "keyboard") == 0)
                    131:                return (10);
                    132:        return (0);
                    133: }
                    134:
                    135: int
                    136: comkbd_match(parent, match, aux)
                    137:        struct device *parent;
                    138:        void *match;
                    139:        void *aux;
                    140: {
                    141:        struct ebus_attach_args *ea = aux;
                    142:        int i;
                    143:
                    144:        for (i = 0; comkbd_names[i]; i++)
                    145:                if (strcmp(ea->ea_name, comkbd_names[i]) == 0)
                    146:                        return (comkbd_iskbd(ea->ea_node));
                    147:
                    148:        if (strcmp(ea->ea_name, "serial") == 0) {
                    149:                char compat[80];
                    150:
                    151:                if ((i = OF_getproplen(ea->ea_node, "compatible")) &&
                    152:                    OF_getprop(ea->ea_node, "compatible", compat,
                    153:                        sizeof(compat)) == i) {
                    154:                        if (strcmp(compat, "su16550") == 0 ||
                    155:                            strcmp(compat, "su") == 0)
                    156:                                return (comkbd_iskbd(ea->ea_node));
                    157:                }
                    158:        }
                    159:        return (0);
                    160: }
                    161:
                    162: void
                    163: comkbd_attach(parent, self, aux)
                    164:        struct device *parent, *self;
                    165:        void *aux;
                    166: {
                    167:        struct comkbd_softc *sc = (void *)self;
                    168:        struct sunkbd_softc *ss = (void *)sc;
                    169:        struct ebus_attach_args *ea = aux;
                    170:        struct wskbddev_attach_args a;
                    171:        int console;
                    172:
                    173:        ss->sc_sendcmd = comkbd_enqueue;
                    174:        timeout_set(&ss->sc_bellto, sunkbd_bellstop, sc);
                    175:
                    176:        sc->sc_iot = ea->ea_memtag;
                    177:
                    178:        sc->sc_rxget = sc->sc_rxput = sc->sc_rxbeg = sc->sc_rxbuf;
                    179:        sc->sc_rxend = sc->sc_rxbuf + COMK_RX_RING;
                    180:        sc->sc_rxcnt = 0;
                    181:
                    182:        sc->sc_txget = sc->sc_txput = sc->sc_txbeg = sc->sc_txbuf;
                    183:        sc->sc_txend = sc->sc_txbuf + COMK_TX_RING;
                    184:        sc->sc_txcnt = 0;
                    185:
                    186:        console = (ea->ea_node == OF_instance_to_package(OF_stdin()));
                    187:
                    188:        sc->sc_si = softintr_establish(IPL_TTY, comkbd_soft, sc);
                    189:        if (sc->sc_si == NULL) {
                    190:                printf(": can't get soft intr\n");
                    191:                return;
                    192:        }
                    193:
                    194:        /* Use prom address if available, otherwise map it. */
                    195:        if (ea->ea_nvaddrs && bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0,
                    196:            BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh) == 0) {
                    197:                sc->sc_iot = ea->ea_memtag;
                    198:        } else if (ebus_bus_map(ea->ea_memtag, 0,
                    199:            EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
                    200:            ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
                    201:                sc->sc_iot = ea->ea_memtag;
                    202:        } else if (ebus_bus_map(ea->ea_iotag, 0,
                    203:            EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
                    204:            ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
                    205:                sc->sc_iot = ea->ea_iotag;
                    206:        } else {
                    207:                printf(": can't map register space\n");
                    208:                 return;
                    209:        }
                    210:
                    211:        sc->sc_ih = bus_intr_establish(sc->sc_iot,
                    212:            ea->ea_intrs[0], IPL_TTY, 0, comkbd_intr, sc, self->dv_xname);
                    213:        if (sc->sc_ih == NULL) {
                    214:                printf(": can't get hard intr\n");
                    215:                return;
                    216:        }
                    217:
                    218:        if (comkbd_init(sc) == 0) {
                    219:                return;
                    220:        }
                    221:
                    222:        ss->sc_click =
                    223:            strcmp(getpropstring(optionsnode, "keyboard-click?"), "true") == 0;
                    224:        sunkbd_setclick(ss, ss->sc_click);
                    225:
                    226:        a.console = console;
                    227:        if (ISTYPE5(ss->sc_layout)) {
                    228:                a.keymap = &sunkbd5_keymapdata;
                    229: #ifndef SUNKBD5_LAYOUT
                    230:                if (ss->sc_layout < MAXSUNLAYOUT &&
                    231:                    sunkbd_layouts[ss->sc_layout] != -1)
                    232:                        sunkbd5_keymapdata.layout =
                    233:                            sunkbd_layouts[ss->sc_layout];
                    234: #endif
                    235:        } else {
                    236:                a.keymap = &sunkbd_keymapdata;
                    237: #ifndef SUNKBD_LAYOUT
                    238:                if (ss->sc_layout < MAXSUNLAYOUT &&
                    239:                    sunkbd_layouts[ss->sc_layout] != -1)
                    240:                        sunkbd_keymapdata.layout =
                    241:                            sunkbd_layouts[ss->sc_layout];
                    242: #endif
                    243:        }
                    244:        a.accessops = &sunkbd_accessops;
                    245:        a.accesscookie = sc;
                    246:
                    247:        if (console) {
                    248:                cn_tab->cn_dev = makedev(77, ss->sc_dev.dv_unit); /* XXX */
                    249:                cn_tab->cn_pollc = wskbd_cnpollc;
                    250:                cn_tab->cn_getc = wskbd_cngetc;
                    251:                wskbd_cnattach(&comkbd_consops, sc, a.keymap);
                    252:                sc->sc_ier = IER_ETXRDY | IER_ERXRDY;
                    253:                COM_WRITE(sc, com_ier, sc->sc_ier);
                    254:                COM_READ(sc, com_iir);
                    255:                COM_WRITE(sc, com_mcr, MCR_IENABLE | MCR_DTR | MCR_RTS);
                    256:        }
                    257:
                    258:        ss->sc_wskbddev = config_found(self, &a, wskbddevprint);
                    259: }
                    260:
                    261: void
                    262: comkbd_cnpollc(vsc, on)
                    263:        void *vsc;
                    264:        int on;
                    265: {
                    266: }
                    267:
                    268: void
                    269: comkbd_cngetc(v, type, data)
                    270:        void *v;
                    271:        u_int *type;
                    272:        int *data;
                    273: {
                    274:        struct comkbd_softc *sc = v;
                    275:        int s;
                    276:        u_int8_t c;
                    277:
                    278:        s = splhigh();
                    279:        while (1) {
                    280:                if (COM_READ(sc, com_lsr) & LSR_RXRDY)
                    281:                        break;
                    282:        }
                    283:        c = COM_READ(sc, com_data);
                    284:        COM_READ(sc, com_iir);
                    285:        splx(s);
                    286:
                    287:        sunkbd_decode(c, type, data);
                    288: }
                    289:
                    290: void
                    291: comkbd_putc(sc, c)
                    292:        struct comkbd_softc *sc;
                    293:        u_int8_t c;
                    294: {
                    295:        int s, timo;
                    296:
                    297:        s = splhigh();
                    298:
                    299:        timo = 150000;
                    300:        while (--timo) {
                    301:                if (COM_READ(sc, com_lsr) & LSR_TXRDY)
                    302:                        break;
                    303:        }
                    304:
                    305:        COM_WRITE(sc, com_data, c);
                    306:        bus_space_barrier(sc->sc_iot, sc->sc_ioh, 0, COM_NPORTS,
                    307:            BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
                    308:
                    309:        timo = 150000;
                    310:        while (--timo) {
                    311:                if (COM_READ(sc, com_lsr) & LSR_TXRDY)
                    312:                        break;
                    313:        }
                    314:
                    315:        splx(s);
                    316: }
                    317:
                    318: int
                    319: comkbd_enqueue(v, buf, buflen)
                    320:        void *v;
                    321:        u_int8_t *buf;
                    322:        u_int buflen;
                    323: {
                    324:        struct comkbd_softc *sc = v;
                    325:        int s;
                    326:        u_int i;
                    327:
                    328:        s = spltty();
                    329:
                    330:        /* See if there is room... */
                    331:        if ((sc->sc_txcnt + buflen) > COMK_TX_RING) {
                    332:                splx(s);
                    333:                return (-1);
                    334:        }
                    335:
                    336:        for (i = 0; i < buflen; i++) {
                    337:                *sc->sc_txget = *buf;
                    338:                buf++;
                    339:                sc->sc_txcnt++;
                    340:                sc->sc_txget++;
                    341:                if (sc->sc_txget == sc->sc_txend)
                    342:                        sc->sc_txget = sc->sc_txbeg;
                    343:        }
                    344:
                    345:        comkbd_soft(sc);
                    346:
                    347:        splx(s);
                    348:        return (0);
                    349: }
                    350:
                    351: void
                    352: comkbd_soft(vsc)
                    353:        void *vsc;
                    354: {
                    355:        struct comkbd_softc *sc = vsc;
                    356:        struct sunkbd_softc *ss = (void *)sc;
                    357:        u_int type;
                    358:        int value;
                    359:        u_int8_t c;
                    360:
                    361:        while (sc->sc_rxcnt) {
                    362:                c = *sc->sc_rxget;
                    363:                if (++sc->sc_rxget == sc->sc_rxend)
                    364:                        sc->sc_rxget = sc->sc_rxbeg;
                    365:                sc->sc_rxcnt--;
                    366:                sunkbd_decode(c, &type, &value);
                    367:                wskbd_input(ss->sc_wskbddev, type, value);
                    368:        }
                    369:
                    370:        if (sc->sc_txcnt) {
                    371:                c = sc->sc_ier | IER_ETXRDY;
                    372:                if (c != sc->sc_ier) {
                    373:                        COM_WRITE(sc, com_ier, c);
                    374:                        sc->sc_ier = c;
                    375:                }
                    376:                if (COM_READ(sc, com_lsr) & LSR_TXRDY) {
                    377:                        sc->sc_txcnt--;
                    378:                        COM_WRITE(sc, com_data, *sc->sc_txput);
                    379:                        if (++sc->sc_txput == sc->sc_txend)
                    380:                                sc->sc_txput = sc->sc_txbeg;
                    381:                }
                    382:        }
                    383: }
                    384:
                    385: int
                    386: comkbd_intr(vsc)
                    387:        void *vsc;
                    388: {
                    389:        struct comkbd_softc *sc = vsc;
                    390:        u_int8_t iir, lsr, data;
                    391:        int needsoft = 0;
                    392:
                    393:        /* Nothing to do */
                    394:        iir = COM_READ(sc, com_iir);
                    395:        if (iir & IIR_NOPEND)
                    396:                return (0);
                    397:
                    398:        for (;;) {
                    399:                lsr = COM_READ(sc, com_lsr);
                    400:                if (lsr & LSR_RXRDY) {
                    401:                        needsoft = 1;
                    402:
                    403:                        do {
                    404:                                data = COM_READ(sc, com_data);
                    405:                                if (sc->sc_rxcnt != COMK_RX_RING) {
                    406:                                        *sc->sc_rxput = data;
                    407:                                        if (++sc->sc_rxput == sc->sc_rxend)
                    408:                                                sc->sc_rxput = sc->sc_rxbeg;
                    409:                                        sc->sc_rxcnt++;
                    410:                                }
                    411:                                lsr = COM_READ(sc, com_lsr);
                    412:                        } while (lsr & LSR_RXRDY);
                    413:                }
                    414:
                    415:                if (lsr & LSR_TXRDY) {
                    416:                        if (sc->sc_txcnt == 0) {
                    417:                                /* Nothing further to send */
                    418:                                sc->sc_ier &= ~IER_ETXRDY;
                    419:                                COM_WRITE(sc, com_ier, sc->sc_ier);
                    420:                        } else
                    421:                                needsoft = 1;
                    422:                }
                    423:
                    424:                iir = COM_READ(sc, com_iir);
                    425:                if (iir & IIR_NOPEND)
                    426:                        break;
                    427:        }
                    428:
                    429:        if (needsoft)
                    430:                softintr_schedule(sc->sc_si);
                    431:
                    432:        return (1);
                    433: }
                    434:
                    435: int
                    436: comkbd_init(sc)
                    437:        struct comkbd_softc *sc;
                    438: {
                    439:        struct sunkbd_softc *ss = (void *)sc;
                    440:        u_int8_t stat, c;
                    441:        int tries;
                    442:
                    443:        for (tries = 5; tries != 0; tries--) {
                    444:                int ltries;
                    445:
                    446:                ss->sc_leds = 0;
                    447:                ss->sc_layout = -1;
                    448:
                    449:                /* Send reset request */
                    450:                comkbd_putc(sc, SKBD_CMD_RESET);
                    451:
                    452:                ltries = 1000;
                    453:                while (--ltries > 0) {
                    454:                        stat = COM_READ(sc,com_lsr);
                    455:                        if (stat & LSR_RXRDY) {
                    456:                                c = COM_READ(sc, com_data);
                    457:
                    458:                                sunkbd_raw(ss, c);
                    459:                                if (ss->sc_kbdstate == SKBD_STATE_RESET)
                    460:                                        break;
                    461:                        }
                    462:                        DELAY(1000);
                    463:                }
                    464:                if (ltries == 0)
                    465:                        continue;
                    466:
                    467:                /* Wait for reset to finish. */
                    468:                ltries = 1000;
                    469:                while (--ltries > 0) {
                    470:                        stat = COM_READ(sc, com_lsr);
                    471:                        if (stat & LSR_RXRDY) {
                    472:                                c = COM_READ(sc, com_data);
                    473:                                sunkbd_raw(ss, c);
                    474:                                if (ss->sc_kbdstate == SKBD_STATE_GETKEY)
                    475:                                        break;
                    476:                        }
                    477:                        DELAY(1000);
                    478:                }
                    479:                if (ltries == 0)
                    480:                        continue;
                    481:
                    482:
                    483:                /* Send layout request */
                    484:                comkbd_putc(sc, SKBD_CMD_LAYOUT);
                    485:
                    486:                ltries = 1000;
                    487:                while (--ltries > 0) {
                    488:                        stat = COM_READ(sc, com_lsr);
                    489:                        if (stat & LSR_RXRDY) {
                    490:                                c = COM_READ(sc, com_data);
                    491:                                sunkbd_raw(ss, c);
                    492:                                if (ss->sc_layout != -1)
                    493:                                        break;
                    494:                        }
                    495:                        DELAY(1000);
                    496:                }
                    497:                if (ltries != 0)
                    498:                        break;
                    499:        }
                    500:        if (tries == 0)
                    501:                printf(": no keyboard\n");
                    502:        else
                    503:                printf(": layout %d\n", ss->sc_layout);
                    504:
                    505:        return tries;
                    506: }

CVSweb