Annotation of Gnu-Mach/i386/i386at/kd_event.c, revision 1.1.1.3

1.1.1.3 ! root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.3 ! root        5:  *
1.1       root        6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
1.1.1.3 ! root       11:  *
1.1       root       12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.3 ! root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.3 ! root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.3 ! root       22:  *
1.1       root       23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /* **********************************************************************
                     27:  File:         kd_event.c
                     28:  Description:  Driver for event interface to keyboard.
                     29: 
                     30:  $ Header: $
                     31: 
                     32:  Copyright Ing. C. Olivetti & C. S.p.A. 1989.  All rights reserved.
                     33: ********************************************************************** */
                     34: /*
                     35:   Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
                     36: Cupertino, California.
                     37: 
                     38:                All Rights Reserved
                     39: 
                     40:   Permission to use, copy, modify, and distribute this software and
                     41: its documentation for any purpose and without fee is hereby
                     42: granted, provided that the above copyright notice appears in all
                     43: copies and that both the copyright notice and this permission notice
                     44: appear in supporting documentation, and that the name of Olivetti
                     45: not be used in advertising or publicity pertaining to distribution
                     46: of the software without specific, written prior permission.
                     47: 
                     48:   OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
                     49: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
                     50: IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
                     51: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                     52: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
                     53: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
                     54: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     55: */
                     56: 
                     57: #include <mach/boolean.h>
                     58: #include <sys/types.h>
                     59: #ifdef MACH_KERNEL
                     60: #include <device/errno.h>
                     61: #include <device/io_req.h>
1.1.1.3 ! root       62: #else  /* MACH_KERNEL */
1.1       root       63: #include <sys/file.h>
                     64: #include <sys/errno.h>
                     65: #include <kern/thread.h>
                     66: #include <sys/user.h>
                     67: #include <sys/proc.h>
                     68: #include <sys/kernel.h>
                     69: #include <sys/ioctl.h>
                     70: #include <sys/tty.h>
1.1.1.3 ! root       71: #endif /* MACH_KERNEL */
1.1       root       72: #include <i386/machspl.h>
                     73: #include <i386at/kd.h>
                     74: #include <i386at/kd_queue.h>
                     75: 
                     76: /*
                     77:  * Code for /dev/kbd.   The interrupt processing is done in kd.c,
                     78:  * which calls into this module to enqueue scancode events when
                     79:  * the keyboard is in Event mode.
                     80:  */
                     81: 
                     82: /*
                     83:  * Note: These globals are protected by raising the interrupt level
                     84:  * via SPLKD.
                     85:  */
                     86: 
                     87: kd_event_queue kbd_queue;              /* queue of keyboard events */
                     88: #ifdef MACH_KERNEL
                     89: queue_head_t   kbd_read_queue = { &kbd_read_queue, &kbd_read_queue };
1.1.1.3 ! root       90: #else  /* MACH_KERNEL */
1.1       root       91: struct proc *kbd_sel = 0;              /* selecting process, if any */
                     92: short kbdpgrp = 0;             /* process group leader when dev is open */
                     93: 
                     94: int kbdflag = 0;
                     95: #define KBD_COLL       1               /* select collision */
                     96: #define KBD_ASYNC      2               /* user wants asynch notification */
                     97: #define KBD_NBIO       4               /* user wants non-blocking I/O */
1.1.1.3 ! root       98: #endif /* MACH_KERNEL */
1.1       root       99: 
                    100: 
                    101: void kbd_enqueue();
                    102: #ifdef MACH_KERNEL
                    103: io_return_t X_kdb_enter_init();
                    104: io_return_t X_kdb_exit_init();
1.1.1.3 ! root      105: #endif /* MACH_KERNEL */
1.1       root      106: 
                    107: static boolean_t initialized = FALSE;
                    108: 
                    109: 
                    110: /*
                    111:  * kbdinit - set up event queue.
                    112:  */
                    113: 
                    114: kbdinit()
                    115: {
                    116:        spl_t s = SPLKD();
1.1.1.3 ! root      117: 
1.1       root      118:        if (!initialized) {
                    119:                kdq_reset(&kbd_queue);
                    120:                initialized = TRUE;
                    121:        }
                    122:        splx(s);
                    123: }
                    124: 
                    125: 
                    126: /*
                    127:  * kbdopen - Verify that open is read-only and remember process
                    128:  * group leader.
                    129:  */
                    130: 
                    131: /*ARGSUSED*/
                    132: kbdopen(dev, flags)
                    133:        dev_t dev;
                    134:        int flags;
                    135: {
                    136:        kbdinit();
                    137: 
                    138: #ifdef MACH_KERNEL
1.1.1.3 ! root      139: #else  /* MACH_KERNEL */
1.1       root      140:        if (flags & FWRITE)
                    141:                return(ENODEV);
1.1.1.3 ! root      142: 
1.1       root      143:        if (kbdpgrp == 0)
                    144:                kbdpgrp = u.u_procp->p_pgrp;
1.1.1.3 ! root      145: #endif /* MACH_KERNEL */
1.1       root      146:        return(0);
                    147: }
                    148: 
                    149: 
                    150: /*
                    151:  * kbdclose - Make sure that the kd driver is in Ascii mode and
                    152:  * reset various flags.
                    153:  */
                    154: 
                    155: /*ARGSUSED*/
                    156: kbdclose(dev, flags)
                    157:        dev_t dev;
                    158:        int flags;
                    159: {
                    160:        spl_t s = SPLKD();
                    161: 
                    162:        kb_mode = KB_ASCII;
                    163: #ifdef MACH_KERNEL
1.1.1.3 ! root      164: #else  /* MACH_KERNEL */
1.1       root      165:        kbdpgrp = 0;
                    166:        kbdflag = 0;
                    167:        kbd_sel = 0;
1.1.1.3 ! root      168: #endif /* MACH_KERNEL */
1.1       root      169:        kdq_reset(&kbd_queue);
                    170:        splx(s);
                    171: }
                    172: 
                    173: 
                    174: #ifdef MACH_KERNEL
                    175: io_return_t kbdgetstat(dev, flavor, data, count)
                    176:        dev_t           dev;
                    177:        int             flavor;
                    178:        int *           data;           /* pointer to OUT array */
                    179:        unsigned int    *count;         /* OUT */
                    180: {
                    181:        io_return_t     result;
                    182: 
                    183:        switch (flavor) {
                    184:            case KDGKBDTYPE:
                    185:                *data = KB_VANILLAKB;
                    186:                *count = 1;
                    187:                break;
1.1.1.2   root      188:            case DEV_GET_SIZE:
                    189:                data[DEV_GET_SIZE_DEVICE_SIZE] = 0;
                    190:                data[DEV_GET_SIZE_RECORD_SIZE] = sizeof(kd_event);
                    191:                *count = DEV_GET_SIZE_COUNT;
                    192:                break;
1.1       root      193:            default:
                    194:                return (D_INVALID_OPERATION);
                    195:        }
                    196:        return (D_SUCCESS);
                    197: }
                    198: 
                    199: io_return_t kbdsetstat(dev, flavor, data, count)
                    200:        dev_t           dev;
                    201:        int             flavor;
                    202:        int *           data;
                    203:        unsigned int    count;
                    204: {
                    205:        io_return_t     result;
                    206: 
                    207:        switch (flavor) {
                    208:            case KDSKBDMODE:
                    209:                kb_mode = *data;
                    210:                /* XXX - what to do about unread events? */
                    211:                /* XXX - should check that 'data' contains an OK valud */
                    212:                break;
                    213:            case K_X_KDB_ENTER:
                    214:                return X_kdb_enter_init(data, count);
                    215:            case K_X_KDB_EXIT:
                    216:                return X_kdb_exit_init(data, count);
                    217:            default:
                    218:                return (D_INVALID_OPERATION);
                    219:        }
                    220:        return (D_SUCCESS);
                    221: }
                    222: 
1.1.1.3 ! root      223: #else  /* MACH_KERNEL */
1.1       root      224: /*
                    225:  * kbdioctl - handling for asynch & non-blocking I/O.
                    226:  */
                    227: 
                    228: /*ARGSUSED*/
                    229: kbdioctl(dev, cmd, data, flag)
                    230:        dev_t dev;
                    231:        int cmd;
                    232:        caddr_t data;
                    233:        int flag;
                    234: {
                    235:        spl_t s = SPLKD();
                    236:        int err = 0;
                    237: 
                    238:        switch (cmd) {
                    239:        case KDSKBDMODE:
                    240:                kb_mode = *(int *)data;
                    241:                /* XXX - what to do about unread events? */
                    242:                /* XXX - should check that "data" contains an OK value */
                    243:                break;
                    244:        case KDGKBDTYPE:
                    245:                *(int *)data = KB_VANILLAKB;
                    246:                break;
                    247:        case K_X_KDB_ENTER:
                    248:                X_kdb_enter_init((struct X_kdb *) data);
                    249:                break;
                    250:        case K_X_KDB_EXIT:
                    251:                X_kdb_exit_init( (struct X_kdb *) data);
                    252:                break;
                    253:        case FIONBIO:
                    254:                if (*(int *)data)
                    255:                        kbdflag |= KBD_NBIO;
                    256:                else
                    257:                        kbdflag &= ~KBD_NBIO;
                    258:                break;
                    259:        case FIOASYNC:
                    260:                if (*(int *)data)
                    261:                        kbdflag |= KBD_ASYNC;
                    262:                else
                    263:                        kbdflag &= ~KBD_ASYNC;
                    264:                break;
                    265:        default:
                    266:                err = ENOTTY;
                    267:                break;
                    268:        }
                    269: 
                    270:        splx(s);
                    271:        return(err);
                    272: }
                    273: 
                    274: 
                    275: /*
                    276:  * kbdselect
                    277:  */
                    278: 
                    279: /*ARGSUSED*/
                    280: kbdselect(dev, rw)
                    281: {
                    282:        spl_t s = SPLKD();
                    283: 
                    284:        if (!kdq_empty(&kbd_queue)) {
                    285:                splx(s);
                    286:                return(1);
                    287:        }
                    288: 
                    289:        if (kbd_sel)
                    290:                kbdflag |= KBD_COLL;
                    291:        else
                    292:                kbd_sel = (struct proc *)current_thread();
                    293:                                        /* eeeyuck */
1.1.1.3 ! root      294: 
1.1       root      295:        splx(s);
                    296:        return(0);
                    297: }
1.1.1.3 ! root      298: #endif /* MACH_KERNEL */
1.1       root      299: 
                    300: 
                    301: /*
                    302:  * kbdread - dequeue and return any queued events.
                    303:  */
                    304: 
                    305: #ifdef MACH_KERNEL
                    306: boolean_t      kbd_read_done();        /* forward */
                    307: 
                    308: kbdread(dev, ior)
                    309:        dev_t   dev;
                    310:        register io_req_t       ior;
                    311: {
                    312:        register int    err, count;
                    313:        register spl_t  s;
                    314: 
1.1.1.2   root      315:        /* Check if IO_COUNT is a multiple of the record size. */
                    316:        if (ior->io_count % sizeof(kd_event) != 0)
                    317:            return D_INVALID_SIZE;
                    318: 
1.1       root      319:        err = device_read_alloc(ior, (vm_size_t)ior->io_count);
                    320:        if (err != KERN_SUCCESS)
                    321:            return (err);
                    322: 
                    323:        s = SPLKD();
                    324:        if (kdq_empty(&kbd_queue)) {
                    325:            if (ior->io_mode & D_NOWAIT) {
                    326:                splx(s);
                    327:                return (D_WOULD_BLOCK);
                    328:            }
                    329:            ior->io_done = kbd_read_done;
                    330:            enqueue_tail(&kbd_read_queue, (queue_entry_t) ior);
                    331:            splx(s);
                    332:            return (D_IO_QUEUED);
                    333:        }
                    334:        count = 0;
                    335:        while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
                    336:            register kd_event *ev;
                    337: 
                    338:            ev = kdq_get(&kbd_queue);
                    339:            *(kd_event *)(&ior->io_data[count]) = *ev;
                    340:            count += sizeof(kd_event);
                    341:        }
                    342:        splx(s);
                    343:        ior->io_residual = ior->io_count - count;
                    344:        return (D_SUCCESS);
                    345: }
                    346: 
                    347: boolean_t kbd_read_done(ior)
                    348:        register io_req_t       ior;
                    349: {
                    350:        register int    count;
                    351:        register spl_t  s;
                    352: 
                    353:        s = SPLKD();
                    354:        if (kdq_empty(&kbd_queue)) {
                    355:            ior->io_done = kbd_read_done;
                    356:            enqueue_tail(&kbd_read_queue, (queue_entry_t)ior);
                    357:            splx(s);
                    358:            return (FALSE);
                    359:        }
                    360: 
                    361:        count = 0;
                    362:        while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
                    363:            register kd_event *ev;
                    364: 
                    365:            ev = kdq_get(&kbd_queue);
                    366:            *(kd_event *)(&ior->io_data[count]) = *ev;
                    367:            count += sizeof(kd_event);
                    368:        }
                    369:        splx(s);
                    370: 
                    371:        ior->io_residual = ior->io_count - count;
                    372:        ds_read_done(ior);
                    373: 
                    374:        return (TRUE);
                    375: }
                    376: 
1.1.1.3 ! root      377: #else  /* MACH_KERNEL */
1.1       root      378: /*ARGSUSED*/
                    379: kbdread(dev, uio)
                    380:        dev_t dev;
                    381:        struct uio *uio;
                    382: {
                    383:        int s = SPLKD();
                    384:        int err = 0;
                    385:        kd_event *ev;
                    386:        int i;
                    387:        char *cp;
                    388: 
                    389:        if (kdq_empty(&kbd_queue))
                    390:                if (kbdflag & KBD_NBIO) {
                    391:                        err = EWOULDBLOCK;
                    392:                        goto done;
1.1.1.3 ! root      393:                } else
1.1       root      394:                        while (kdq_empty(&kbd_queue)) {
                    395:                                splx(s);
                    396:                                sleep((caddr_t)&kbd_queue, TTIPRI);
                    397:                                s = SPLKD();
                    398:                        }
                    399: 
                    400:        while (!kdq_empty(&kbd_queue) && uio->uio_resid >= sizeof(kd_event)) {
                    401:                ev = kdq_get(&kbd_queue);
                    402:                for (cp = (char *)ev, i = 0; i < sizeof(kd_event);
                    403:                     ++i, ++cp) {
                    404:                        err = ureadc(*cp, uio);
                    405:                        if (err)
                    406:                                goto done;
                    407:                }
                    408:        }
                    409: 
                    410: done:
                    411:        splx(s);
                    412:        return(err);
                    413: }
1.1.1.3 ! root      414: #endif /* MACH_KERNEL */
1.1       root      415: 
                    416: 
                    417: /*
                    418:  * kd_enqsc - enqueue a scancode.  Should be called at SPLKD.
                    419:  */
                    420: 
                    421: void
                    422: kd_enqsc(sc)
                    423:        Scancode sc;
                    424: {
                    425:        kd_event ev;
                    426: 
                    427:        ev.type = KEYBD_EVENT;
                    428:        ev.time = time;
                    429:        ev.value.sc = sc;
                    430:        kbd_enqueue(&ev);
                    431: }
                    432: 
                    433: 
                    434: /*
                    435:  * kbd_enqueue - enqueue an event and wake up selecting processes, if
                    436:  * any.  Should be called at SPLKD.
                    437:  */
                    438: 
                    439: void
                    440: kbd_enqueue(ev)
                    441:        kd_event *ev;
                    442: {
                    443:        if (kdq_full(&kbd_queue))
                    444:                printf("kbd: queue full\n");
                    445:        else
                    446:                kdq_put(&kbd_queue, ev);
                    447: 
                    448: #ifdef MACH_KERNEL
                    449:        {
                    450:            register io_req_t   ior;
                    451:            while ((ior = (io_req_t)dequeue_head(&kbd_read_queue)) != 0)
                    452:                iodone(ior);
                    453:        }
1.1.1.3 ! root      454: #else  /* MACH_KERNEL */
1.1       root      455:        if (kbd_sel) {
                    456:                selwakeup(kbd_sel, kbdflag & KBD_COLL);
                    457:                kbd_sel = 0;
                    458:                kbdflag &= ~KBD_COLL;
                    459:        }
                    460:        if (kbdflag & KBD_ASYNC)
                    461:                gsignal(kbdpgrp, SIGIO);
                    462:        wakeup((caddr_t)&kbd_queue);
1.1.1.3 ! root      463: #endif /* MACH_KERNEL */
1.1       root      464: }
                    465: 
                    466: u_int X_kdb_enter_str[512], X_kdb_exit_str[512];
                    467: int   X_kdb_enter_len = 0,  X_kdb_exit_len = 0;
                    468: 
                    469: kdb_in_out(p)
                    470: u_int *p;
                    471: {
                    472: register int t = p[0];
                    473: 
                    474:        switch (t & K_X_TYPE) {
                    475:                case K_X_IN|K_X_BYTE:
                    476:                        inb(t & K_X_PORT);
                    477:                        break;
                    478: 
                    479:                case K_X_IN|K_X_WORD:
                    480:                        inw(t & K_X_PORT);
                    481:                        break;
                    482: 
                    483:                case K_X_IN|K_X_LONG:
                    484:                        inl(t & K_X_PORT);
                    485:                        break;
                    486: 
                    487:                case K_X_OUT|K_X_BYTE:
                    488:                        outb(t & K_X_PORT, p[1]);
                    489:                        break;
                    490: 
                    491:                case K_X_OUT|K_X_WORD:
                    492:                        outw(t & K_X_PORT, p[1]);
                    493:                        break;
                    494: 
                    495:                case K_X_OUT|K_X_LONG:
                    496:                        outl(t & K_X_PORT, p[1]);
                    497:                        break;
                    498:        }
                    499: }
                    500: 
                    501: X_kdb_enter()
                    502: {
                    503: register u_int *u_ip, *endp;
                    504: 
                    505:        for (u_ip = X_kdb_enter_str, endp = &X_kdb_enter_str[X_kdb_enter_len];
                    506:             u_ip < endp;
                    507:             u_ip += 2)
                    508:            kdb_in_out(u_ip);
                    509: }
                    510: 
                    511: X_kdb_exit()
                    512: {
                    513: register u_int *u_ip, *endp;
                    514: 
                    515:        for (u_ip = X_kdb_exit_str, endp = &X_kdb_exit_str[X_kdb_exit_len];
                    516:             u_ip < endp;
                    517:             u_ip += 2)
                    518:           kdb_in_out(u_ip);
                    519: }
                    520: 
                    521: #ifdef MACH_KERNEL
                    522: io_return_t
                    523: X_kdb_enter_init(data, count)
                    524:     u_int *data;
                    525:     u_int count;
                    526: {
                    527:     if (count * sizeof X_kdb_enter_str[0] > sizeof X_kdb_enter_str)
                    528:        return D_INVALID_OPERATION;
                    529: 
                    530:     bcopy(data, X_kdb_enter_str, count * sizeof X_kdb_enter_str[0]);
                    531:     X_kdb_enter_len = count;
                    532:     return D_SUCCESS;
                    533: }
                    534: 
                    535: io_return_t
                    536: X_kdb_exit_init(data, count)
                    537:     u_int *data;
                    538:     u_int count;
                    539: {
                    540:     if (count * sizeof X_kdb_exit_str[0] > sizeof X_kdb_exit_str)
                    541:        return D_INVALID_OPERATION;
                    542: 
                    543:     bcopy(data, X_kdb_exit_str, count * sizeof X_kdb_exit_str[0]);
                    544:     X_kdb_exit_len = count;
                    545:     return D_SUCCESS;
                    546: }
1.1.1.3 ! root      547: #else  /* MACH_KERNEL */
1.1       root      548: X_kdb_enter_init(kp)
                    549: struct X_kdb *kp;
                    550: {
                    551:        if (kp->size > sizeof X_kdb_enter_str)
                    552:                u.u_error = ENOENT;
                    553:        else if(copyin(kp->ptr, X_kdb_enter_str, kp->size) == EFAULT)
                    554:                u.u_error = EFAULT;
                    555: 
                    556:        X_kdb_enter_len = kp->size>>2;
                    557: }
                    558: 
                    559: X_kdb_exit_init(kp)
                    560: struct X_kdb *kp;
                    561: {
                    562:        if (kp->size > sizeof X_kdb_exit_str)
                    563:                u.u_error = ENOENT;
                    564:        else if(copyin(kp->ptr, X_kdb_exit_str, kp->size) == EFAULT)
                    565:                u.u_error = EFAULT;
                    566: 
                    567:        X_kdb_exit_len = kp->size>>2;
                    568: }
1.1.1.3 ! root      569: #endif /* MACH_KERNEL */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.