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/drivers/tty/keyboard.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 /* Keyboard driver for PC's and AT's.
    2  *
    3  * Changes: 
    4  *   Jul 13, 2004   processes can observe function keys  (Jorrit N. Herder)
    5  *   Jun 15, 2004   removed wreboot(), except panic dumps (Jorrit N. Herder)
    6  *   Feb 04, 1994   loadable keymaps  (Marcus Hampel)
    7  */
    8 
    9 #include "../drivers.h"
   10 #include <sys/time.h>
   11 #include <sys/select.h>
   12 #include <termios.h>
   13 #include <signal.h>
   14 #include <unistd.h>
   15 #include <minix/callnr.h>
   16 #include <minix/com.h>
   17 #include <minix/keymap.h>
   18 #include "tty.h"
   19 #include "keymaps/us-std.src"
   20 #include "../../kernel/const.h"
   21 #include "../../kernel/config.h"
   22 #include "../../kernel/type.h"
   23 #include "../../kernel/proc.h"
   24 
   25 int irq_hook_id = -1;
   26 
   27 /* Standard and AT keyboard.  (PS/2 MCA implies AT throughout.) */
   28 #define KEYBD           0x60    /* I/O port for keyboard data */
   29 
   30 /* AT keyboard. */
   31 #define KB_COMMAND      0x64    /* I/O port for commands on AT */
   32 #define KB_STATUS       0x64    /* I/O port for status on AT */
   33 #define KB_ACK          0xFA    /* keyboard ack response */
   34 #define KB_OUT_FULL     0x01    /* status bit set when keypress char pending */
   35 #define KB_IN_FULL      0x02    /* status bit set when not ready to receive */
   36 #define LED_CODE        0xED    /* command to keyboard to set LEDs */
   37 #define MAX_KB_ACK_RETRIES 0x1000       /* max #times to wait for kb ack */
   38 #define MAX_KB_BUSY_RETRIES 0x1000      /* max #times to loop while kb busy */
   39 #define KBIT            0x80    /* bit used to ack characters to keyboard */
   40 
   41 /* Miscellaneous. */
   42 #define ESC_SCAN        0x01    /* reboot key when panicking */
   43 #define SLASH_SCAN      0x35    /* to recognize numeric slash */
   44 #define RSHIFT_SCAN     0x36    /* to distinguish left and right shift */
   45 #define HOME_SCAN       0x47    /* first key on the numeric keypad */
   46 #define INS_SCAN        0x52    /* INS for use in CTRL-ALT-INS reboot */
   47 #define DEL_SCAN        0x53    /* DEL for use in CTRL-ALT-DEL reboot */
   48 
   49 #define CONSOLE            0    /* line number for console */
   50 #define KB_IN_BYTES       32    /* size of keyboard input buffer */
   51 PRIVATE char ibuf[KB_IN_BYTES]; /* input buffer */
   52 PRIVATE char *ihead = ibuf;     /* next free spot in input buffer */
   53 PRIVATE char *itail = ibuf;     /* scan code to return to TTY */
   54 PRIVATE int icount;             /* # codes in buffer */
   55 
   56 PRIVATE int esc;                /* escape scan code detected? */
   57 PRIVATE int alt_l;              /* left alt key state */
   58 PRIVATE int alt_r;              /* right alt key state */
   59 PRIVATE int alt;                /* either alt key */
   60 PRIVATE int ctrl_l;             /* left control key state */
   61 PRIVATE int ctrl_r;             /* right control key state */
   62 PRIVATE int ctrl;               /* either control key */
   63 PRIVATE int shift_l;            /* left shift key state */
   64 PRIVATE int shift_r;            /* right shift key state */
   65 PRIVATE int shift;              /* either shift key */
   66 PRIVATE int num_down;           /* num lock key depressed */
   67 PRIVATE int caps_down;          /* caps lock key depressed */
   68 PRIVATE int scroll_down;        /* scroll lock key depressed */
   69 PRIVATE int locks[NR_CONS];     /* per console lock keys state */
   70 
   71 /* Lock key active bits.  Chosen to be equal to the keyboard LED bits. */
   72 #define SCROLL_LOCK     0x01
   73 #define NUM_LOCK        0x02
   74 #define CAPS_LOCK       0x04
   75 
   76 PRIVATE char numpad_map[] =
   77                 {'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};
   78 
   79 /* Variables and definition for observed function keys. */
   80 typedef struct observer { int proc_nr; int events; } obs_t;
   81 PRIVATE obs_t  fkey_obs[12];    /* observers for F1-F12 */
   82 PRIVATE obs_t sfkey_obs[12];    /* observers for SHIFT F1-F12 */
   83 
   84 FORWARD _PROTOTYPE( int kb_ack, (void)                                  );
   85 FORWARD _PROTOTYPE( int kb_wait, (void)                                 );
   86 FORWARD _PROTOTYPE( int func_key, (int scode)                           );
   87 FORWARD _PROTOTYPE( int scan_keyboard, (void)                           );
   88 FORWARD _PROTOTYPE( unsigned make_break, (int scode)                    );
   89 FORWARD _PROTOTYPE( void set_leds, (void)                               );
   90 FORWARD _PROTOTYPE( void show_key_mappings, (void)                      );
   91 FORWARD _PROTOTYPE( int kb_read, (struct tty *tp, int try)              );
   92 FORWARD _PROTOTYPE( unsigned map_key, (int scode)                       );
   93 
   94 /*===========================================================================*
   95  *                              map_key0                                     *
   96  *===========================================================================*/
   97 /* Map a scan code to an ASCII code ignoring modifiers. */
   98 #define map_key0(scode)  \
   99         ((unsigned) keymap[(scode) * MAP_COLS])
  100 
  101 /*===========================================================================*
  102  *                              map_key                                      *
  103  *===========================================================================*/
  104 PRIVATE unsigned map_key(scode)
  105 int scode;
  106 {
  107 /* Map a scan code to an ASCII code. */
  108 
  109   int caps, column, lk;
  110   u16_t *keyrow;
  111 
  112   if (scode == SLASH_SCAN && esc) return '/';   /* don't map numeric slash */
  113 
  114   keyrow = &keymap[scode * MAP_COLS];
  115 
  116   caps = shift;
  117   lk = locks[ccurrent];
  118   if ((lk & NUM_LOCK) && HOME_SCAN <= scode && scode <= DEL_SCAN) caps = !caps;
  119   if ((lk & CAPS_LOCK) && (keyrow[0] & HASCAPS)) caps = !caps;
  120 
  121   if (alt) {
  122         column = 2;
  123         if (ctrl || alt_r) column = 3;  /* Ctrl + Alt == AltGr */
  124         if (caps) column = 4;
  125   } else {
  126         column = 0;
  127         if (caps) column = 1;
  128         if (ctrl) column = 5;
  129   }
  130   return keyrow[column] & ~HASCAPS;
  131 }
  132 
  133 /*===========================================================================*
  134  *                              kbd_interrupt                                *
  135  *===========================================================================*/
  136 PUBLIC void kbd_interrupt(m_ptr)
  137 message *m_ptr;
  138 {
  139 /* A keyboard interrupt has occurred.  Process it. */
  140   int scode;
  141   static timer_t timer;         /* timer must be static! */
  142 
  143   /* Fetch the character from the keyboard hardware and acknowledge it. */
  144   scode = scan_keyboard();
  145 
  146   /* Store the scancode in memory so the task can get at it later. */
  147   if (icount < KB_IN_BYTES) {
  148         *ihead++ = scode;
  149         if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;
  150         icount++;
  151         tty_table[ccurrent].tty_events = 1;
  152         if (tty_table[ccurrent].tty_select_ops & SEL_RD) {
  153                 select_retry(&tty_table[ccurrent]);
  154         }
  155   }
  156 }
  157 
  158 /*===========================================================================*
  159  *                              kb_read                                      *
  160  *===========================================================================*/
  161 PRIVATE int kb_read(tp, try)
  162 tty_t *tp;
  163 int try;
  164 {
  165 /* Process characters from the circular keyboard buffer. */
  166   char buf[3];
  167   int scode;
  168   unsigned ch;
  169 
  170   tp = &tty_table[ccurrent];            /* always use the current console */
  171 
  172   if (try) {
  173         if (icount > 0) return 1;
  174         return 0;
  175   }
  176 
  177   while (icount > 0) {
  178         scode = *itail++;                       /* take one key scan code */
  179         if (itail == ibuf + KB_IN_BYTES) itail = ibuf;
  180         icount--;
  181 
  182         /* Function keys are being used for debug dumps. */
  183         if (func_key(scode)) continue;
  184 
  185         /* Perform make/break processing. */
  186         ch = make_break(scode);
  187 
  188         if (ch <= 0xFF) {
  189                 /* A normal character. */
  190                 buf[0] = ch;
  191                 (void) in_process(tp, buf, 1);
  192         } else
  193         if (HOME <= ch && ch <= INSRT) {
  194                 /* An ASCII escape sequence generated by the numeric pad. */
  195                 buf[0] = ESC;
  196                 buf[1] = '[';
  197                 buf[2] = numpad_map[ch - HOME];
  198                 (void) in_process(tp, buf, 3);
  199         } else
  200         if (ch == ALEFT) {
  201                 /* Choose lower numbered console as current console. */
  202                 select_console(ccurrent - 1);
  203                 set_leds();
  204         } else
  205         if (ch == ARIGHT) {
  206                 /* Choose higher numbered console as current console. */
  207                 select_console(ccurrent + 1);
  208                 set_leds();
  209         } else
  210         if (AF1 <= ch && ch <= AF12) {
  211                 /* Alt-F1 is console, Alt-F2 is ttyc1, etc. */
  212                 select_console(ch - AF1);
  213                 set_leds();
  214         } else
  215         if (CF1 <= ch && ch <= CF12) {
  216             switch(ch) {
  217                 case CF1: show_key_mappings(); break; 
  218                 case CF3: toggle_scroll(); break; /* hardware <-> software */   
  219                 case CF7: sigchar(&tty_table[CONSOLE], SIGQUIT); break;
  220                 case CF8: sigchar(&tty_table[CONSOLE], SIGINT); break;
  221                 case CF9: sigchar(&tty_table[CONSOLE], SIGKILL); break;
  222             }
  223         }
  224   }
  225 
  226   return 1;
  227 }
  228 
  229 /*===========================================================================*
  230  *                              make_break                                   *
  231  *===========================================================================*/
  232 PRIVATE unsigned make_break(scode)
  233 int scode;                      /* scan code of key just struck or released */
  234 {
  235 /* This routine can handle keyboards that interrupt only on key depression,
  236  * as well as keyboards that interrupt on key depression and key release.
  237  * For efficiency, the interrupt routine filters out most key releases.
  238  */
  239   int ch, make, escape;
  240   static int CAD_count = 0;
  241 
  242   /* Check for CTRL-ALT-DEL, and if found, halt the computer. This would
  243    * be better done in keyboard() in case TTY is hung, except control and
  244    * alt are set in the high level code.
  245    */
  246   if (ctrl && alt && (scode == DEL_SCAN || scode == INS_SCAN))
  247   {
  248         if (++CAD_count == 3) sys_abort(RBT_HALT);
  249         sys_kill(INIT_PROC_NR, SIGABRT);
  250         return -1;
  251   }
  252 
  253   /* High-order bit set on key release. */
  254   make = (scode & KEY_RELEASE) == 0;            /* true if pressed */
  255 
  256   ch = map_key(scode &= ASCII_MASK);            /* map to ASCII */
  257 
  258   escape = esc;         /* Key is escaped?  (true if added since the XT) */
  259   esc = 0;
  260 
  261   switch (ch) {
  262         case CTRL:              /* Left or right control key */
  263                 *(escape ? &ctrl_r : &ctrl_l) = make;
  264                 ctrl = ctrl_l | ctrl_r;
  265                 break;
  266         case SHIFT:             /* Left or right shift key */
  267                 *(scode == RSHIFT_SCAN ? &shift_r : &shift_l) = make;
  268                 shift = shift_l | shift_r;
  269                 break;
  270         case ALT:               /* Left or right alt key */
  271                 *(escape ? &alt_r : &alt_l) = make;
  272                 alt = alt_l | alt_r;
  273                 break;
  274         case CALOCK:            /* Caps lock - toggle on 0 -> 1 transition */
  275                 if (caps_down < make) {
  276                         locks[ccurrent] ^= CAPS_LOCK;
  277                         set_leds();
  278                 }
  279                 caps_down = make;
  280                 break;
  281         case NLOCK:             /* Num lock */
  282                 if (num_down < make) {
  283                         locks[ccurrent] ^= NUM_LOCK;
  284                         set_leds();
  285                 }
  286                 num_down = make;
  287                 break;
  288         case SLOCK:             /* Scroll lock */
  289                 if (scroll_down < make) {
  290                         locks[ccurrent] ^= SCROLL_LOCK;
  291                         set_leds();
  292                 }
  293                 scroll_down = make;
  294                 break;
  295         case EXTKEY:            /* Escape keycode */
  296                 esc = 1;                /* Next key is escaped */
  297                 return(-1);
  298         default:                /* A normal key */
  299                 if (make) return(ch);
  300   }
  301 
  302   /* Key release, or a shift type key. */
  303   return(-1);
  304 }
  305 
  306 /*===========================================================================*
  307  *                              set_leds                                     *
  308  *===========================================================================*/
  309 PRIVATE void set_leds()
  310 {
  311 /* Set the LEDs on the caps, num, and scroll lock keys */
  312   int s;
  313   if (! machine.pc_at) return;  /* PC/XT doesn't have LEDs */
  314 
  315   kb_wait();                    /* wait for buffer empty  */
  316   if ((s=sys_outb(KEYBD, LED_CODE)) != OK)
  317       printf("Warning, sys_outb couldn't prepare for LED values: %d\n", s);
  318                                 /* prepare keyboard to accept LED values */
  319   kb_ack();                     /* wait for ack response  */
  320 
  321   kb_wait();                    /* wait for buffer empty  */
  322   if ((s=sys_outb(KEYBD, locks[ccurrent])) != OK)
  323       printf("Warning, sys_outb couldn't give LED values: %d\n", s);
  324                                 /* give keyboard LED values */
  325   kb_ack();                     /* wait for ack response  */
  326 }
  327 
  328 /*===========================================================================*
  329  *                              kb_wait                                      *
  330  *===========================================================================*/
  331 PRIVATE int kb_wait()
  332 {
  333 /* Wait until the controller is ready; return zero if this times out. */
  334 
  335   int retries, status, temp;
  336   int s;
  337 
  338   retries = MAX_KB_BUSY_RETRIES + 1;    /* wait until not busy */
  339   do {
  340       s = sys_inb(KB_STATUS, &status);
  341       if (status & KB_OUT_FULL) {
  342           s = sys_inb(KEYBD, &temp);    /* discard value */
  343       }
  344       if (! (status & (KB_IN_FULL|KB_OUT_FULL)) )
  345           break;                        /* wait until ready */
  346   } while (--retries != 0);             /* continue unless timeout */ 
  347   return(retries);              /* zero on timeout, positive if ready */
  348 }
  349 
  350 /*===========================================================================*
  351  *                              kb_ack                                       *
  352  *===========================================================================*/
  353 PRIVATE int kb_ack()
  354 {
  355 /* Wait until kbd acknowledges last command; return zero if this times out. */
  356 
  357   int retries, s;
  358   u8_t u8val;
  359 
  360   retries = MAX_KB_ACK_RETRIES + 1;
  361   do {
  362       s = sys_inb(KEYBD, &u8val);
  363       if (u8val == KB_ACK)      
  364           break;                /* wait for ack */
  365   } while(--retries != 0);      /* continue unless timeout */
  366 
  367   return(retries);              /* nonzero if ack received */
  368 }
  369 
  370 /*===========================================================================*
  371  *                              kb_init                                      *
  372  *===========================================================================*/
  373 PUBLIC void kb_init(tp)
  374 tty_t *tp;
  375 {
  376 /* Initialize the keyboard driver. */
  377 
  378   tp->tty_devread = kb_read;    /* input function */
  379 }
  380 
  381 /*===========================================================================*
  382  *                              kb_init_once                                 *
  383  *===========================================================================*/
  384 PUBLIC void kb_init_once(void)
  385 {
  386   int i;
  387 
  388   set_leds();                   /* turn off numlock led */
  389   scan_keyboard();              /* discard leftover keystroke */
  390 
  391       /* Clear the function key observers array. Also see func_key(). */
  392       for (i=0; i<12; i++) {
  393           fkey_obs[i].proc_nr = NONE;   /* F1-F12 observers */
  394           fkey_obs[i].events = 0;       /* F1-F12 observers */
  395           sfkey_obs[i].proc_nr = NONE;  /* Shift F1-F12 observers */
  396           sfkey_obs[i].events = 0;      /* Shift F1-F12 observers */
  397       }
  398 
  399       /* Set interrupt handler and enable keyboard IRQ. */
  400       irq_hook_id = KEYBOARD_IRQ;       /* id to be returned on interrupt */
  401       if ((i=sys_irqsetpolicy(KEYBOARD_IRQ, IRQ_REENABLE, &irq_hook_id)) != OK)
  402           panic("TTY",  "Couldn't set keyboard IRQ policy", i);
  403       if ((i=sys_irqenable(&irq_hook_id)) != OK)
  404           panic("TTY", "Couldn't enable keyboard IRQs", i);
  405       kbd_irq_set |= (1 << KEYBOARD_IRQ);
  406 }
  407 
  408 /*===========================================================================*
  409  *                              kbd_loadmap                                  *
  410  *===========================================================================*/
  411 PUBLIC int kbd_loadmap(m)
  412 message *m;
  413 {
  414 /* Load a new keymap. */
  415   int result;
  416   result = sys_vircopy(m->PROC_NR, D, (vir_bytes) m->ADDRESS,
  417         SELF, D, (vir_bytes) keymap, 
  418         (vir_bytes) sizeof(keymap));
  419   return(result);
  420 }
  421 
  422 /*===========================================================================*
  423  *                              do_fkey_ctl                                  *
  424  *===========================================================================*/
  425 PUBLIC void do_fkey_ctl(m_ptr)
  426 message *m_ptr;                 /* pointer to the request message */
  427 {
  428 /* This procedure allows processes to register a function key to receive
  429  * notifications if it is pressed. At most one binding per key can exist.
  430  */
  431   int i; 
  432   int result;
  433 
  434   switch (m_ptr->FKEY_REQUEST) {        /* see what we must do */
  435   case FKEY_MAP:                        /* request for new mapping */
  436       result = OK;                      /* assume everything will be ok*/
  437       for (i=0; i < 12; i++) {          /* check F1-F12 keys */
  438           if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {
  439 #if DEAD_CODE
  440         /* Currently, we don't check if the slot is in use, so that IS
  441          * can recover after a crash by overtaking its existing mappings.
  442          * In future, a better solution will be implemented.
  443          */
  444               if (fkey_obs[i].proc_nr == NONE) { 
  445 #endif
  446                   fkey_obs[i].proc_nr = m_ptr->m_source;
  447                   fkey_obs[i].events = 0;
  448                   bit_unset(m_ptr->FKEY_FKEYS, i+1);
  449 #if DEAD_CODE
  450               } else {
  451                   printf("WARNING, fkey_map failed F%d\n", i+1);
  452                   result = EBUSY;       /* report failure, but try rest */
  453               }
  454 #endif
  455           }
  456       }
  457       for (i=0; i < 12; i++) {          /* check Shift+F1-F12 keys */
  458           if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
  459 #if DEAD_CODE
  460               if (sfkey_obs[i].proc_nr == NONE) { 
  461 #endif
  462                   sfkey_obs[i].proc_nr = m_ptr->m_source;
  463                   sfkey_obs[i].events = 0;
  464                   bit_unset(m_ptr->FKEY_SFKEYS, i+1);
  465 #if DEAD_CODE
  466               } else {
  467                   printf("WARNING, fkey_map failed Shift F%d\n", i+1);
  468                   result = EBUSY;       /* report failure but try rest */
  469               }
  470 #endif
  471           }
  472       }
  473       break;
  474   case FKEY_UNMAP:
  475       result = OK;                      /* assume everything will be ok*/
  476       for (i=0; i < 12; i++) {          /* check F1-F12 keys */
  477           if (bit_isset(m_ptr->FKEY_FKEYS, i+1) ) {
  478               if (fkey_obs[i].proc_nr == m_ptr->m_source) { 
  479                   fkey_obs[i].proc_nr = NONE;
  480                   fkey_obs[i].events = 0;
  481                   bit_unset(m_ptr->FKEY_FKEYS, i+1);
  482               } else {
  483                   result = EPERM;       /* report failure, but try rest */
  484               }
  485           }
  486       }
  487       for (i=0; i < 12; i++) {          /* check Shift+F1-F12 keys */
  488           if (bit_isset(m_ptr->FKEY_SFKEYS, i+1) ) {
  489               if (sfkey_obs[i].proc_nr == m_ptr->m_source) { 
  490                   sfkey_obs[i].proc_nr = NONE;
  491                   sfkey_obs[i].events = 0;
  492                   bit_unset(m_ptr->FKEY_SFKEYS, i+1);
  493               } else {
  494                   result = EPERM;       /* report failure, but try rest */
  495               }
  496           }
  497       }
  498       break;
  499   case FKEY_EVENTS:
  500       m_ptr->FKEY_FKEYS = m_ptr->FKEY_SFKEYS = 0;
  501       for (i=0; i < 12; i++) {          /* check (Shift+) F1-F12 keys */
  502           if (fkey_obs[i].proc_nr == m_ptr->m_source) {
  503               if (fkey_obs[i].events) { 
  504                   bit_set(m_ptr->FKEY_FKEYS, i+1);
  505                   fkey_obs[i].events = 0;
  506               }
  507           }
  508           if (sfkey_obs[i].proc_nr == m_ptr->m_source) {
  509               if (sfkey_obs[i].events) { 
  510                   bit_set(m_ptr->FKEY_SFKEYS, i+1);
  511                   sfkey_obs[i].events = 0;
  512               }
  513           }
  514       }
  515       break;
  516   default:
  517           result =  EINVAL;             /* key cannot be observed */
  518   }
  519 
  520   /* Almost done, return result to caller. */
  521   m_ptr->m_type = result;
  522   send(m_ptr->m_source, m_ptr);
  523 }
  524 
  525 /*===========================================================================*
  526  *                              func_key                                     *
  527  *===========================================================================*/
  528 PRIVATE int func_key(scode)
  529 int scode;                      /* scan code for a function key */
  530 {
  531 /* This procedure traps function keys for debugging purposes. Observers of 
  532  * function keys are kept in a global array. If a subject (a key) is pressed
  533  * the observer is notified of the event. Initialization of the arrays is done
  534  * in kb_init, where NONE is set to indicate there is no interest in the key.
  535  * Returns FALSE on a key release or if the key is not observable.
  536  */
  537   message m;
  538   int key;
  539   int proc_nr;
  540   int i,s;
  541 
  542   /* Ignore key releases. If this is a key press, get full key code. */
  543   if (scode & KEY_RELEASE) return(FALSE);       /* key release */
  544   key = map_key(scode);                         /* include modifiers */
  545 
  546   /* Key pressed, now see if there is an observer for the pressed key.
  547    *           F1-F12   observers are in fkey_obs array. 
  548    *    SHIFT  F1-F12   observers are in sfkey_req array. 
  549    *    CTRL   F1-F12   reserved (see kb_read)
  550    *    ALT    F1-F12   reserved (see kb_read)
  551    * Other combinations are not in use. Note that Alt+Shift+F1-F12 is yet
  552    * defined in <minix/keymap.h>, and thus is easy for future extensions.
  553    */
  554   if (F1 <= key && key <= F12) {                /* F1-F12 */
  555       proc_nr = fkey_obs[key - F1].proc_nr;     
  556       fkey_obs[key - F1].events ++ ;    
  557   } else if (SF1 <= key && key <= SF12) {       /* Shift F2-F12 */
  558       proc_nr = sfkey_obs[key - SF1].proc_nr;   
  559       sfkey_obs[key - SF1].events ++;   
  560   }
  561   else {
  562       return(FALSE);                            /* not observable */
  563   }
  564 
  565   /* See if an observer is registered and send it a message. */
  566   if (proc_nr != NONE) { 
  567       m.NOTIFY_TYPE = FKEY_PRESSED;
  568       notify(proc_nr);
  569   }
  570   return(TRUE);
  571 }
  572 
  573 /*===========================================================================*
  574  *                              show_key_mappings                            *
  575  *===========================================================================*/
  576 PRIVATE void show_key_mappings()
  577 {
  578     int i,s;
  579     struct proc proc;
  580 
  581     printf("\n");
  582     printf("System information.   Known function key mappings to request debug dumps:\n");
  583     printf("-------------------------------------------------------------------------\n");
  584     for (i=0; i<12; i++) {
  585 
  586       printf(" %sF%d: ", i+1<10? " ":"", i+1);
  587       if (fkey_obs[i].proc_nr != NONE) {
  588           if ((s=sys_getproc(&proc, fkey_obs[i].proc_nr))!=OK)
  589               printf("sys_getproc: %d\n", s);
  590           printf("%-14.14s", proc.p_name);
  591       } else {
  592           printf("%-14.14s", "<none>");
  593       }
  594 
  595       printf("    %sShift-F%d: ", i+1<10? " ":"", i+1);
  596       if (sfkey_obs[i].proc_nr != NONE) {
  597           if ((s=sys_getproc(&proc, sfkey_obs[i].proc_nr))!=OK)
  598               printf("sys_getproc: %d\n", s);
  599           printf("%-14.14s", proc.p_name);
  600       } else {
  601           printf("%-14.14s", "<none>");
  602       }
  603       printf("\n");
  604     }
  605     printf("\n");
  606     printf("Press one of the registered function keys to trigger a debug dump.\n");
  607     printf("\n");
  608 }
  609 
  610 /*===========================================================================*
  611  *                              scan_keyboard                                *
  612  *===========================================================================*/
  613 PRIVATE int scan_keyboard()
  614 {
  615 /* Fetch the character from the keyboard hardware and acknowledge it. */
  616   pvb_pair_t byte_in[2], byte_out[2];
  617   
  618   byte_in[0].port = KEYBD;      /* get the scan code for the key struck */
  619   byte_in[1].port = PORT_B;     /* strobe the keyboard to ack the char */
  620   sys_vinb(byte_in, 2);         /* request actual input */
  621 
  622   pv_set(byte_out[0], PORT_B, byte_in[1].value | KBIT); /* strobe bit high */
  623   pv_set(byte_out[1], PORT_B, byte_in[1].value);        /* then strobe low */
  624   sys_voutb(byte_out, 2);       /* request actual output */
  625 
  626   return(byte_in[0].value);             /* return scan code */
  627 }
  628 
  629 /*===========================================================================*
  630  *                              do_panic_dumps                               *
  631  *===========================================================================*/
  632 PUBLIC void do_panic_dumps(m)
  633 message *m;                     /* request message to TTY */
  634 {
  635 /* Wait for keystrokes for printing debugging info and reboot. */
  636   int quiet, code;
  637 
  638   /* A panic! Allow debug dumps until user wants to shutdown. */
  639   printf("\nHit ESC to reboot, DEL to shutdown, F-keys for debug dumps\n");
  640 
  641   (void) scan_keyboard();       /* ack any old input */
  642   quiet = scan_keyboard();/* quiescent value (0 on PC, last code on AT)*/
  643   for (;;) {
  644         tickdelay(10);
  645         /* See if there are pending request for output, but don't block. 
  646          * Diagnostics can span multiple printf()s, so do it in a loop.
  647          */
  648         while (nb_receive(ANY, m) == OK) {
  649                 switch(m->m_type) {
  650                 case FKEY_CONTROL: do_fkey_ctl(m);      break;
  651                 case SYS_SIG:      do_new_kmess(m);     break;
  652                 case DIAGNOSTICS:  do_diagnostics(m);   break;
  653                 default:        ;       /* do nothing */ 
  654                 }
  655                 tickdelay(1);           /* allow more */
  656         }
  657         code = scan_keyboard();
  658         if (code != quiet) {
  659                 /* A key has been pressed. */
  660                 switch (code) {                 /* possibly abort MINIX */
  661                 case ESC_SCAN:  sys_abort(RBT_REBOOT);  return; 
  662                 case DEL_SCAN:  sys_abort(RBT_HALT);    return; 
  663                 }
  664                 (void) func_key(code);          /* check for function key */
  665                 quiet = scan_keyboard();
  666         }
  667   }
  668 }
  669 

Cache object: cb98324fff17ab087487fbb50420d93b


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