The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386at/kd_event.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 9aab75fd7a61eeb09baae504b4749bff


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.