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

1.1       root        1: /* 
                      2:  * Mach Operating System
                      3:  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
                      5:  * 
                      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.
                     11:  * 
                     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.
                     15:  * 
                     16:  * Carnegie Mellon requests users of this software to return to
                     17:  * 
                     18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
                     22:  * 
                     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>
                     62: #else  MACH_KERNEL
                     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>
                     71: #endif MACH_KERNEL
                     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 };
                     90: #else  MACH_KERNEL
                     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 */
                     98: #endif MACH_KERNEL
                     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();
                    105: #endif MACH_KERNEL
                    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();
                    117:        
                    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
                    139: #else  MACH_KERNEL
                    140:        if (flags & FWRITE)
                    141:                return(ENODEV);
                    142:        
                    143:        if (kbdpgrp == 0)
                    144:                kbdpgrp = u.u_procp->p_pgrp;
                    145: #endif MACH_KERNEL
                    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
                    164: #else  MACH_KERNEL
                    165:        kbdpgrp = 0;
                    166:        kbdflag = 0;
                    167:        kbd_sel = 0;
                    168: #endif MACH_KERNEL
                    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;
                    188:            default:
                    189:                return (D_INVALID_OPERATION);
                    190:        }
                    191:        return (D_SUCCESS);
                    192: }
                    193: 
                    194: io_return_t kbdsetstat(dev, flavor, data, count)
                    195:        dev_t           dev;
                    196:        int             flavor;
                    197:        int *           data;
                    198:        unsigned int    count;
                    199: {
                    200:        io_return_t     result;
                    201: 
                    202:        switch (flavor) {
                    203:            case KDSKBDMODE:
                    204:                kb_mode = *data;
                    205:                /* XXX - what to do about unread events? */
                    206:                /* XXX - should check that 'data' contains an OK valud */
                    207:                break;
                    208:            case K_X_KDB_ENTER:
                    209:                return X_kdb_enter_init(data, count);
                    210:            case K_X_KDB_EXIT:
                    211:                return X_kdb_exit_init(data, count);
                    212:            default:
                    213:                return (D_INVALID_OPERATION);
                    214:        }
                    215:        return (D_SUCCESS);
                    216: }
                    217: 
                    218: #else  MACH_KERNEL
                    219: /*
                    220:  * kbdioctl - handling for asynch & non-blocking I/O.
                    221:  */
                    222: 
                    223: /*ARGSUSED*/
                    224: kbdioctl(dev, cmd, data, flag)
                    225:        dev_t dev;
                    226:        int cmd;
                    227:        caddr_t data;
                    228:        int flag;
                    229: {
                    230:        spl_t s = SPLKD();
                    231:        int err = 0;
                    232: 
                    233:        switch (cmd) {
                    234:        case KDSKBDMODE:
                    235:                kb_mode = *(int *)data;
                    236:                /* XXX - what to do about unread events? */
                    237:                /* XXX - should check that "data" contains an OK value */
                    238:                break;
                    239:        case KDGKBDTYPE:
                    240:                *(int *)data = KB_VANILLAKB;
                    241:                break;
                    242:        case K_X_KDB_ENTER:
                    243:                X_kdb_enter_init((struct X_kdb *) data);
                    244:                break;
                    245:        case K_X_KDB_EXIT:
                    246:                X_kdb_exit_init( (struct X_kdb *) data);
                    247:                break;
                    248:        case FIONBIO:
                    249:                if (*(int *)data)
                    250:                        kbdflag |= KBD_NBIO;
                    251:                else
                    252:                        kbdflag &= ~KBD_NBIO;
                    253:                break;
                    254:        case FIOASYNC:
                    255:                if (*(int *)data)
                    256:                        kbdflag |= KBD_ASYNC;
                    257:                else
                    258:                        kbdflag &= ~KBD_ASYNC;
                    259:                break;
                    260:        default:
                    261:                err = ENOTTY;
                    262:                break;
                    263:        }
                    264: 
                    265:        splx(s);
                    266:        return(err);
                    267: }
                    268: 
                    269: 
                    270: /*
                    271:  * kbdselect
                    272:  */
                    273: 
                    274: /*ARGSUSED*/
                    275: kbdselect(dev, rw)
                    276: {
                    277:        spl_t s = SPLKD();
                    278: 
                    279:        if (!kdq_empty(&kbd_queue)) {
                    280:                splx(s);
                    281:                return(1);
                    282:        }
                    283: 
                    284:        if (kbd_sel)
                    285:                kbdflag |= KBD_COLL;
                    286:        else
                    287:                kbd_sel = (struct proc *)current_thread();
                    288:                                        /* eeeyuck */
                    289:        
                    290:        splx(s);
                    291:        return(0);
                    292: }
                    293: #endif MACH_KERNEL
                    294: 
                    295: 
                    296: /*
                    297:  * kbdread - dequeue and return any queued events.
                    298:  */
                    299: 
                    300: #ifdef MACH_KERNEL
                    301: boolean_t      kbd_read_done();        /* forward */
                    302: 
                    303: kbdread(dev, ior)
                    304:        dev_t   dev;
                    305:        register io_req_t       ior;
                    306: {
                    307:        register int    err, count;
                    308:        register spl_t  s;
                    309: 
                    310:        err = device_read_alloc(ior, (vm_size_t)ior->io_count);
                    311:        if (err != KERN_SUCCESS)
                    312:            return (err);
                    313: 
                    314:        s = SPLKD();
                    315:        if (kdq_empty(&kbd_queue)) {
                    316:            if (ior->io_mode & D_NOWAIT) {
                    317:                splx(s);
                    318:                return (D_WOULD_BLOCK);
                    319:            }
                    320:            ior->io_done = kbd_read_done;
                    321:            enqueue_tail(&kbd_read_queue, (queue_entry_t) ior);
                    322:            splx(s);
                    323:            return (D_IO_QUEUED);
                    324:        }
                    325:        count = 0;
                    326:        while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
                    327:            register kd_event *ev;
                    328: 
                    329:            ev = kdq_get(&kbd_queue);
                    330:            *(kd_event *)(&ior->io_data[count]) = *ev;
                    331:            count += sizeof(kd_event);
                    332:        }
                    333:        splx(s);
                    334:        ior->io_residual = ior->io_count - count;
                    335:        return (D_SUCCESS);
                    336: }
                    337: 
                    338: boolean_t kbd_read_done(ior)
                    339:        register io_req_t       ior;
                    340: {
                    341:        register int    count;
                    342:        register spl_t  s;
                    343: 
                    344:        s = SPLKD();
                    345:        if (kdq_empty(&kbd_queue)) {
                    346:            ior->io_done = kbd_read_done;
                    347:            enqueue_tail(&kbd_read_queue, (queue_entry_t)ior);
                    348:            splx(s);
                    349:            return (FALSE);
                    350:        }
                    351: 
                    352:        count = 0;
                    353:        while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
                    354:            register kd_event *ev;
                    355: 
                    356:            ev = kdq_get(&kbd_queue);
                    357:            *(kd_event *)(&ior->io_data[count]) = *ev;
                    358:            count += sizeof(kd_event);
                    359:        }
                    360:        splx(s);
                    361: 
                    362:        ior->io_residual = ior->io_count - count;
                    363:        ds_read_done(ior);
                    364: 
                    365:        return (TRUE);
                    366: }
                    367: 
                    368: #else  MACH_KERNEL
                    369: /*ARGSUSED*/
                    370: kbdread(dev, uio)
                    371:        dev_t dev;
                    372:        struct uio *uio;
                    373: {
                    374:        int s = SPLKD();
                    375:        int err = 0;
                    376:        kd_event *ev;
                    377:        int i;
                    378:        char *cp;
                    379: 
                    380:        if (kdq_empty(&kbd_queue))
                    381:                if (kbdflag & KBD_NBIO) {
                    382:                        err = EWOULDBLOCK;
                    383:                        goto done;
                    384:                } else 
                    385:                        while (kdq_empty(&kbd_queue)) {
                    386:                                splx(s);
                    387:                                sleep((caddr_t)&kbd_queue, TTIPRI);
                    388:                                s = SPLKD();
                    389:                        }
                    390: 
                    391:        while (!kdq_empty(&kbd_queue) && uio->uio_resid >= sizeof(kd_event)) {
                    392:                ev = kdq_get(&kbd_queue);
                    393:                for (cp = (char *)ev, i = 0; i < sizeof(kd_event);
                    394:                     ++i, ++cp) {
                    395:                        err = ureadc(*cp, uio);
                    396:                        if (err)
                    397:                                goto done;
                    398:                }
                    399:        }
                    400: 
                    401: done:
                    402:        splx(s);
                    403:        return(err);
                    404: }
                    405: #endif MACH_KERNEL
                    406: 
                    407: 
                    408: /*
                    409:  * kd_enqsc - enqueue a scancode.  Should be called at SPLKD.
                    410:  */
                    411: 
                    412: void
                    413: kd_enqsc(sc)
                    414:        Scancode sc;
                    415: {
                    416:        kd_event ev;
                    417: 
                    418:        ev.type = KEYBD_EVENT;
                    419:        ev.time = time;
                    420:        ev.value.sc = sc;
                    421:        kbd_enqueue(&ev);
                    422: }
                    423: 
                    424: 
                    425: /*
                    426:  * kbd_enqueue - enqueue an event and wake up selecting processes, if
                    427:  * any.  Should be called at SPLKD.
                    428:  */
                    429: 
                    430: void
                    431: kbd_enqueue(ev)
                    432:        kd_event *ev;
                    433: {
                    434:        if (kdq_full(&kbd_queue))
                    435:                printf("kbd: queue full\n");
                    436:        else
                    437:                kdq_put(&kbd_queue, ev);
                    438: 
                    439: #ifdef MACH_KERNEL
                    440:        {
                    441:            register io_req_t   ior;
                    442:            while ((ior = (io_req_t)dequeue_head(&kbd_read_queue)) != 0)
                    443:                iodone(ior);
                    444:        }
                    445: #else  MACH_KERNEL
                    446:        if (kbd_sel) {
                    447:                selwakeup(kbd_sel, kbdflag & KBD_COLL);
                    448:                kbd_sel = 0;
                    449:                kbdflag &= ~KBD_COLL;
                    450:        }
                    451:        if (kbdflag & KBD_ASYNC)
                    452:                gsignal(kbdpgrp, SIGIO);
                    453:        wakeup((caddr_t)&kbd_queue);
                    454: #endif MACH_KERNEL
                    455: }
                    456: 
                    457: u_int X_kdb_enter_str[512], X_kdb_exit_str[512];
                    458: int   X_kdb_enter_len = 0,  X_kdb_exit_len = 0;
                    459: 
                    460: kdb_in_out(p)
                    461: u_int *p;
                    462: {
                    463: register int t = p[0];
                    464: 
                    465:        switch (t & K_X_TYPE) {
                    466:                case K_X_IN|K_X_BYTE:
                    467:                        inb(t & K_X_PORT);
                    468:                        break;
                    469: 
                    470:                case K_X_IN|K_X_WORD:
                    471:                        inw(t & K_X_PORT);
                    472:                        break;
                    473: 
                    474:                case K_X_IN|K_X_LONG:
                    475:                        inl(t & K_X_PORT);
                    476:                        break;
                    477: 
                    478:                case K_X_OUT|K_X_BYTE:
                    479:                        outb(t & K_X_PORT, p[1]);
                    480:                        break;
                    481: 
                    482:                case K_X_OUT|K_X_WORD:
                    483:                        outw(t & K_X_PORT, p[1]);
                    484:                        break;
                    485: 
                    486:                case K_X_OUT|K_X_LONG:
                    487:                        outl(t & K_X_PORT, p[1]);
                    488:                        break;
                    489:        }
                    490: }
                    491: 
                    492: X_kdb_enter()
                    493: {
                    494: register u_int *u_ip, *endp;
                    495: 
                    496:        for (u_ip = X_kdb_enter_str, endp = &X_kdb_enter_str[X_kdb_enter_len];
                    497:             u_ip < endp;
                    498:             u_ip += 2)
                    499:            kdb_in_out(u_ip);
                    500: }
                    501: 
                    502: X_kdb_exit()
                    503: {
                    504: register u_int *u_ip, *endp;
                    505: 
                    506:        for (u_ip = X_kdb_exit_str, endp = &X_kdb_exit_str[X_kdb_exit_len];
                    507:             u_ip < endp;
                    508:             u_ip += 2)
                    509:           kdb_in_out(u_ip);
                    510: }
                    511: 
                    512: #ifdef MACH_KERNEL
                    513: io_return_t
                    514: X_kdb_enter_init(data, count)
                    515:     u_int *data;
                    516:     u_int count;
                    517: {
                    518:     if (count * sizeof X_kdb_enter_str[0] > sizeof X_kdb_enter_str)
                    519:        return D_INVALID_OPERATION;
                    520: 
                    521:     bcopy(data, X_kdb_enter_str, count * sizeof X_kdb_enter_str[0]);
                    522:     X_kdb_enter_len = count;
                    523:     return D_SUCCESS;
                    524: }
                    525: 
                    526: io_return_t
                    527: X_kdb_exit_init(data, count)
                    528:     u_int *data;
                    529:     u_int count;
                    530: {
                    531:     if (count * sizeof X_kdb_exit_str[0] > sizeof X_kdb_exit_str)
                    532:        return D_INVALID_OPERATION;
                    533: 
                    534:     bcopy(data, X_kdb_exit_str, count * sizeof X_kdb_exit_str[0]);
                    535:     X_kdb_exit_len = count;
                    536:     return D_SUCCESS;
                    537: }
                    538: #else  MACH_KERNEL
                    539: X_kdb_enter_init(kp)
                    540: struct X_kdb *kp;
                    541: {
                    542:        if (kp->size > sizeof X_kdb_enter_str)
                    543:                u.u_error = ENOENT;
                    544:        else if(copyin(kp->ptr, X_kdb_enter_str, kp->size) == EFAULT)
                    545:                u.u_error = EFAULT;
                    546: 
                    547:        X_kdb_enter_len = kp->size>>2;
                    548: }
                    549: 
                    550: X_kdb_exit_init(kp)
                    551: struct X_kdb *kp;
                    552: {
                    553:        if (kp->size > sizeof X_kdb_exit_str)
                    554:                u.u_error = ENOENT;
                    555:        else if(copyin(kp->ptr, X_kdb_exit_str, kp->size) == EFAULT)
                    556:                u.u_error = EFAULT;
                    557: 
                    558:        X_kdb_exit_len = kp->size>>2;
                    559: }
                    560: #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.