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) 1993,1992,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.10  93/11/17  16:51:04  dbg
   30  *      Use sys_clock instead of 'time'.  Remove non-MACH_KERNEL code.
   31  *      ANSI-fy.
   32  *      [93/06/10            dbg]
   33  * 
   34  * Revision 2.9  93/05/15  19:32:16  mrt
   35  *      machparam.h -> machspl.h
   36  * 
   37  * Revision 2.8  93/01/14  17:31:23  danner
   38  *      Proper spl typing.
   39  *      [92/11/30            af]
   40  * 
   41  * Revision 2.7  91/05/14  16:27:12  mrt
   42  *      Correcting copyright
   43  * 
   44  * Revision 2.6  91/02/05  17:19:10  mrt
   45  *      Changed to new Mach copyright
   46  *      [91/02/01  17:45:36  mrt]
   47  * 
   48  * Revision 2.5  90/11/26  14:50:31  rvb
   49  *      jsb beat me to XMK34, sigh ...
   50  *      [90/11/26            rvb]
   51  *      Synched 2.5 & 3.0 at I386q (r1.5.1.4) & XMK35 (r2.5)
   52  *      [90/11/15            rvb]
   53  * 
   54  * Revision 2.4  90/08/09  16:32:32  rpd
   55  *      Added kdb/X support from rvb.
   56  *      [90/08/08            rpd]
   57  *
   58  * Revision 2.3  90/05/21  13:27:21  dbg
   59  *      Replace stub with real file, converted for pure kernel.
   60  * 
   61  * Revision 1.5.1.3  90/05/14  13:21:36  rvb
   62  *      Support for entering kdb from X;
   63  *      [90/04/30            rvb]
   64  * 
   65  * Revision 1.5.1.2  90/02/28  15:50:22  rvb
   66  *      Fix numerous typo's in Olivetti disclaimer.
   67  *      [90/02/28            rvb]
   68  * 
   69  * Revision 1.5.1.1  90/01/08  13:30:51  rvb
   70  *      Add Olivetti copyright.
   71  *      [90/01/08            rvb]
   72  * 
   73  * Revision 1.5  89/07/17  10:41:17  rvb
   74  *      Olivetti Changes to X79 upto 5/9/89:
   75  *      [89/07/11            rvb]
   76  * 
   77  * Revision 1.4.1.1  89/04/27  12:21:11  kupfer
   78  * Merge X79 with our latest and greatest.
   79  * 
   80  * Revision 1.1.1.1  89/04/27  11:53:53  kupfer
   81  * X79 from CMU.
   82  * 
   83  * Revision 1.4  89/03/09  20:06:41  rpd
   84  *      More cleanup.
   85  * 
   86  * Revision 1.3  89/02/26  12:42:31  gm0w
   87  *      Changes for cleanup.
   88  * 
   89  */
   90  
   91 /* **********************************************************************
   92  File:         kd_event.c
   93  Description:  Driver for event interface to keyboard.
   94 
   95  $ Header: $
   96 
   97  Copyright Ing. C. Olivetti & C. S.p.A. 1989.  All rights reserved.
   98 ********************************************************************** */
   99 /*
  100   Copyright 1988, 1989 by Olivetti Advanced Technology Center, Inc.,
  101 Cupertino, California.
  102 
  103                 All Rights Reserved
  104 
  105   Permission to use, copy, modify, and distribute this software and
  106 its documentation for any purpose and without fee is hereby
  107 granted, provided that the above copyright notice appears in all
  108 copies and that both the copyright notice and this permission notice
  109 appear in supporting documentation, and that the name of Olivetti
  110 not be used in advertising or publicity pertaining to distribution
  111 of the software without specific, written prior permission.
  112 
  113   OLIVETTI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
  114 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  115 IN NO EVENT SHALL OLIVETTI BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
  116 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  117 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
  118 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUR OF OR IN CONNECTION
  119 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  120 */
  121 
  122 #include <mach/boolean.h>
  123 #include <kern/clock.h>
  124 #include <kern/kern_io.h>
  125 #include <kern/memory.h>
  126 #include <sys/types.h>
  127 #include <device/errno.h>
  128 #include <device/ds_routines.h>
  129 #include <device/io_req.h>
  130 #include <i386/machspl.h>
  131 #include <i386/pio.h>
  132 #include <i386at/kd.h>
  133 #include <i386at/kd_queue.h>
  134 
  135 /*
  136  * Code for /dev/kbd.   The interrupt processing is done in kd.c,
  137  * which calls into this module to enqueue scancode events when
  138  * the keyboard is in Event mode.
  139  */
  140 
  141 /*
  142  * Note: These globals are protected by raising the interrupt level
  143  * via SPLKD.
  144  */
  145 
  146 kd_event_queue kbd_queue;               /* queue of keyboard events */
  147 queue_head_t    kbd_read_queue = { &kbd_read_queue, &kbd_read_queue };
  148 
  149 void kbd_enqueue(kd_event *);
  150 
  151 io_return_t X_kdb_enter_init();
  152 io_return_t X_kdb_exit_init();
  153 
  154 static boolean_t initialized = FALSE;
  155 
  156 
  157 /*
  158  * kbdinit - set up event queue.
  159  */
  160 
  161 void kbdinit(void)
  162 {
  163         spl_t s = SPLKD();
  164         
  165         if (!initialized) {
  166                 kdq_reset(&kbd_queue);
  167                 initialized = TRUE;
  168         }
  169         splx(s);
  170 }
  171 
  172 
  173 /*
  174  * kbdopen - Verify that open is read-only and remember process
  175  * group leader.
  176  */
  177 
  178 /*ARGSUSED*/
  179 io_return_t kbdopen(
  180         int     dev)
  181 {
  182         if (dev != 0)
  183             return D_NO_SUCH_DEVICE;
  184 
  185         kbdinit();
  186         return D_SUCCESS;
  187 }
  188 
  189 
  190 /*
  191  * kbdclose - Make sure that the kd driver is in Ascii mode and
  192  * reset various flags.
  193  */
  194 
  195 /*ARGSUSED*/
  196 io_return_t kbdclose(
  197         int     dev)
  198 {
  199         spl_t s = SPLKD();
  200 
  201         kb_mode = KB_ASCII;
  202         kdq_reset(&kbd_queue);
  203         splx(s);
  204 
  205         return D_SUCCESS;
  206 }
  207 
  208 
  209 io_return_t kbdgetstat(
  210         int             dev,
  211         int             flavor,
  212         dev_status_t    *data,          /* pointer to OUT array */
  213         natural_t       *count)         /* OUT */
  214 {
  215         switch (flavor) {
  216             case KDGKBDTYPE:
  217                 *data = KB_VANILLAKB;
  218                 *count = 1;
  219                 break;
  220             default:
  221                 return D_INVALID_OPERATION;
  222         }
  223         return D_SUCCESS;
  224 }
  225 
  226 io_return_t kbdsetstat(
  227         int             dev,
  228         int             flavor,
  229         dev_status_t    data,
  230         natural_t       count)
  231 {
  232         switch (flavor) {
  233             case KDSKBDMODE:
  234                 kb_mode = *data;
  235                 /* XXX - what to do about unread events? */
  236                 /* XXX - should check that 'data' contains an OK valud */
  237                 break;
  238             case K_X_KDB_ENTER:
  239                 return X_kdb_enter_init(data, count);
  240             case K_X_KDB_EXIT:
  241                 return X_kdb_exit_init(data, count);
  242             default:
  243                 return D_INVALID_OPERATION;
  244         }
  245         return D_SUCCESS;
  246 }
  247 
  248 /*
  249  * kbdread - dequeue and return any queued events.
  250  */
  251 
  252 boolean_t kbd_read_done(io_req_t);      /* forward */
  253 
  254 io_return_t kbdread(
  255         int     dev,
  256         register io_req_t ior)
  257 {
  258         register int    err, count;
  259         register spl_t  s;
  260 
  261         err = device_read_alloc(ior, (vm_size_t)ior->io_count);
  262         if (err != KERN_SUCCESS)
  263             return err;
  264 
  265         s = SPLKD();
  266         if (kdq_empty(&kbd_queue)) {
  267             if (ior->io_mode & D_NOWAIT) {
  268                 splx(s);
  269                 return D_WOULD_BLOCK;
  270             }
  271             ior->io_done = kbd_read_done;
  272             enqueue_tail(&kbd_read_queue, (queue_entry_t) ior);
  273             splx(s);
  274             return D_IO_QUEUED;
  275         }
  276         count = 0;
  277         while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
  278             register kd_event *ev;
  279 
  280             ev = kdq_get(&kbd_queue);
  281             *(kd_event *)(&ior->io_data[count]) = *ev;
  282             count += sizeof(kd_event);
  283         }
  284         splx(s);
  285         ior->io_residual = ior->io_count - count;
  286         return D_SUCCESS;
  287 }
  288 
  289 boolean_t kbd_read_done(
  290         register io_req_t ior)
  291 {
  292         register int    count;
  293         register spl_t  s;
  294 
  295         s = SPLKD();
  296         if (kdq_empty(&kbd_queue)) {
  297             ior->io_done = kbd_read_done;
  298             enqueue_tail(&kbd_read_queue, (queue_entry_t)ior);
  299             splx(s);
  300             return FALSE;
  301         }
  302 
  303         count = 0;
  304         while (!kdq_empty(&kbd_queue) && count < ior->io_count) {
  305             register kd_event *ev;
  306 
  307             ev = kdq_get(&kbd_queue);
  308             *(kd_event *)(&ior->io_data[count]) = *ev;
  309             count += sizeof(kd_event);
  310         }
  311         splx(s);
  312 
  313         ior->io_residual = ior->io_count - count;
  314         ds_read_done(ior);
  315 
  316         return TRUE;
  317 }
  318 
  319 
  320 /*
  321  * kd_enqsc - enqueue a scancode.  Should be called at SPLKD.
  322  */
  323 
  324 void
  325 kd_enqsc(
  326         Scancode sc)
  327 {
  328         kd_event ev;
  329         time_spec_t cur_time;
  330 
  331         clock_read(cur_time, sys_clock);
  332 
  333         ev.type = KEYBD_EVENT;
  334         ev.time.seconds = cur_time.seconds;
  335         ev.time.microseconds = cur_time.nanoseconds / 1000;
  336         ev.value.sc = sc;
  337         kbd_enqueue(&ev);
  338 }
  339 
  340 
  341 /*
  342  * kbd_enqueue - enqueue an event and wake up selecting processes, if
  343  * any.  Should be called at SPLKD.
  344  */
  345 
  346 void
  347 kbd_enqueue(
  348         kd_event *ev)
  349 {
  350         register io_req_t       ior;
  351 
  352         if (kdq_full(&kbd_queue))
  353                 printf("kbd: queue full\n");
  354         else
  355                 kdq_put(&kbd_queue, ev);
  356 
  357         while ((ior = (io_req_t)dequeue_head(&kbd_read_queue)) != 0)
  358             iodone(ior);
  359 }
  360 
  361 unsigned int X_kdb_enter_str[512], X_kdb_exit_str[512];
  362 int     X_kdb_enter_len = 0,  X_kdb_exit_len = 0;
  363 
  364 void kdb_in_out(
  365         unsigned int *p)
  366 {
  367         register int t = p[0];
  368 
  369         switch (t & K_X_TYPE) {
  370                 case K_X_IN|K_X_BYTE:
  371                         inb(t & K_X_PORT);
  372                         break;
  373 
  374                 case K_X_IN|K_X_WORD:
  375                         inw(t & K_X_PORT);
  376                         break;
  377 
  378                 case K_X_IN|K_X_LONG:
  379                         inl(t & K_X_PORT);
  380                         break;
  381 
  382                 case K_X_OUT|K_X_BYTE:
  383                         outb(t & K_X_PORT, p[1]);
  384                         break;
  385 
  386                 case K_X_OUT|K_X_WORD:
  387                         outw(t & K_X_PORT, p[1]);
  388                         break;
  389 
  390                 case K_X_OUT|K_X_LONG:
  391                         outl(t & K_X_PORT, p[1]);
  392                         break;
  393         }
  394 }
  395 
  396 void X_kdb_enter()
  397 {
  398         register unsigned int *u_ip, *endp;
  399 
  400         for (u_ip = X_kdb_enter_str, endp = &X_kdb_enter_str[X_kdb_enter_len];
  401              u_ip < endp;
  402              u_ip += 2)
  403             kdb_in_out(u_ip);
  404 }
  405 
  406 void X_kdb_exit()
  407 {
  408         register unsigned int *u_ip, *endp;
  409 
  410         for (u_ip = X_kdb_exit_str, endp = &X_kdb_exit_str[X_kdb_exit_len];
  411              u_ip < endp;
  412              u_ip += 2)
  413            kdb_in_out(u_ip);
  414 }
  415 
  416 io_return_t
  417 X_kdb_enter_init(
  418     unsigned int *data,
  419     natural_t count)
  420 {
  421     if (count * sizeof X_kdb_enter_str[0] > sizeof X_kdb_enter_str)
  422         return D_INVALID_OPERATION;
  423 
  424     bcopy(data, X_kdb_enter_str, count * sizeof X_kdb_enter_str[0]);
  425     X_kdb_enter_len = count;
  426     return D_SUCCESS;
  427 }
  428 
  429 io_return_t
  430 X_kdb_exit_init(
  431     unsigned int *data,
  432     natural_t count)
  433 {
  434     if (count * sizeof X_kdb_exit_str[0] > sizeof X_kdb_exit_str)
  435         return D_INVALID_OPERATION;
  436 
  437     bcopy(data, X_kdb_exit_str, count * sizeof X_kdb_exit_str[0]);
  438     X_kdb_exit_len = count;
  439     return D_SUCCESS;
  440 }

Cache object: b9699a2d5b44e894240b35f75ed3a59e


[ 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.