and NEW_SCHED_Q definitions. Some minor problems are being traced at the moment. This commit is meant to backup my files. --- Jorrit
		
			
				
	
	
		
			613 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			613 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* Keyboard driver for PC's and AT's.
 | 
						|
 *
 | 
						|
 * Changes: 
 | 
						|
 *   Jul 13, 2004   processes can observe function keys  (Jorrit N. Herder)
 | 
						|
 *   Jun 15, 2004   removed wreboot(), except panic dumps (Jorrit N. Herder)
 | 
						|
 *   Feb 04, 1994   loadable keymaps  (Marcus Hampel)
 | 
						|
 */
 | 
						|
 | 
						|
#include "../drivers.h"
 | 
						|
#include <termios.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <minix/callnr.h>
 | 
						|
#include <minix/com.h>
 | 
						|
#include <minix/keymap.h>
 | 
						|
#include "tty.h"
 | 
						|
#include "keymaps/us-std.src"
 | 
						|
#include "../../kernel/kernel.h"
 | 
						|
#include "../../kernel/proc.h"
 | 
						|
 | 
						|
int irq_hook_id = -1;
 | 
						|
 | 
						|
/* Standard and AT keyboard.  (PS/2 MCA implies AT throughout.) */
 | 
						|
#define KEYBD		0x60	/* I/O port for keyboard data */
 | 
						|
 | 
						|
/* AT keyboard. */
 | 
						|
#define KB_COMMAND	0x64	/* I/O port for commands on AT */
 | 
						|
#define KB_STATUS	0x64	/* I/O port for status on AT */
 | 
						|
#define KB_ACK		0xFA	/* keyboard ack response */
 | 
						|
#define KB_OUT_FULL	0x01	/* status bit set when keypress char pending */
 | 
						|
#define KB_IN_FULL	0x02	/* status bit set when not ready to receive */
 | 
						|
#define LED_CODE	0xED	/* command to keyboard to set LEDs */
 | 
						|
#define MAX_KB_ACK_RETRIES 0x1000	/* max #times to wait for kb ack */
 | 
						|
#define MAX_KB_BUSY_RETRIES 0x1000	/* max #times to loop while kb busy */
 | 
						|
#define KBIT		0x80	/* bit used to ack characters to keyboard */
 | 
						|
 | 
						|
/* Miscellaneous. */
 | 
						|
#define ESC_SCAN	0x01	/* reboot key when panicking */
 | 
						|
#define SLASH_SCAN	0x35	/* to recognize numeric slash */
 | 
						|
#define RSHIFT_SCAN	0x36	/* to distinguish left and right shift */
 | 
						|
#define HOME_SCAN	0x47	/* first key on the numeric keypad */
 | 
						|
#define INS_SCAN	0x52	/* INS for use in CTRL-ALT-INS reboot */
 | 
						|
#define DEL_SCAN	0x53	/* DEL for use in CTRL-ALT-DEL reboot */
 | 
						|
 | 
						|
#define CONSOLE		   0	/* line number for console */
 | 
						|
#define KB_IN_BYTES	  32	/* size of keyboard input buffer */
 | 
						|
PRIVATE char ibuf[KB_IN_BYTES];	/* input buffer */
 | 
						|
PRIVATE char *ihead = ibuf;	/* next free spot in input buffer */
 | 
						|
PRIVATE char *itail = ibuf;	/* scan code to return to TTY */
 | 
						|
PRIVATE int icount;		/* # codes in buffer */
 | 
						|
 | 
						|
PRIVATE int esc;		/* escape scan code detected? */
 | 
						|
PRIVATE int alt_l;		/* left alt key state */
 | 
						|
PRIVATE int alt_r;		/* right alt key state */
 | 
						|
PRIVATE int alt;		/* either alt key */
 | 
						|
PRIVATE int ctrl_l;		/* left control key state */
 | 
						|
PRIVATE int ctrl_r;		/* right control key state */
 | 
						|
PRIVATE int ctrl;		/* either control key */
 | 
						|
PRIVATE int shift_l;		/* left shift key state */
 | 
						|
PRIVATE int shift_r;		/* right shift key state */
 | 
						|
PRIVATE int shift;		/* either shift key */
 | 
						|
PRIVATE int num_down;		/* num lock key depressed */
 | 
						|
PRIVATE int caps_down;		/* caps lock key depressed */
 | 
						|
PRIVATE int scroll_down;	/* scroll lock key depressed */
 | 
						|
PRIVATE int locks[NR_CONS];	/* per console lock keys state */
 | 
						|
 | 
						|
/* Lock key active bits.  Chosen to be equal to the keyboard LED bits. */
 | 
						|
#define SCROLL_LOCK	0x01
 | 
						|
#define NUM_LOCK	0x02
 | 
						|
#define CAPS_LOCK	0x04
 | 
						|
 | 
						|
PRIVATE char numpad_map[] =
 | 
						|
		{'H', 'Y', 'A', 'B', 'D', 'C', 'V', 'U', 'G', 'S', 'T', '@'};
 | 
						|
 | 
						|
/* Variables and definition for observed function keys. */
 | 
						|
PRIVATE int  fkey_obs[12];	/* observers for F1-F12 */
 | 
						|
PRIVATE int sfkey_obs[12];	/* observers for SHIFT F1-F12 */
 | 
						|
 | 
						|
FORWARD _PROTOTYPE( int kb_ack, (void) );
 | 
						|
FORWARD _PROTOTYPE( int kb_wait, (void) );
 | 
						|
FORWARD _PROTOTYPE( int func_key, (int scode) );
 | 
						|
FORWARD _PROTOTYPE( int scan_keyboard, (void) );
 | 
						|
FORWARD _PROTOTYPE( unsigned make_break, (int scode) );
 | 
						|
FORWARD _PROTOTYPE( void set_leds, (void) );
 | 
						|
FORWARD _PROTOTYPE( void kb_read, (struct tty *tp) );
 | 
						|
FORWARD _PROTOTYPE( unsigned map_key, (int scode) );
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				map_key0				     *
 | 
						|
 *===========================================================================*/
 | 
						|
/* Map a scan code to an ASCII code ignoring modifiers. */
 | 
						|
#define map_key0(scode)	 \
 | 
						|
	((unsigned) keymap[(scode) * MAP_COLS])
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				map_key					     *
 | 
						|
 *===========================================================================*/
 | 
						|
PRIVATE unsigned map_key(scode)
 | 
						|
int scode;
 | 
						|
{
 | 
						|
/* Map a scan code to an ASCII code. */
 | 
						|
 | 
						|
  int caps, column, lk;
 | 
						|
  u16_t *keyrow;
 | 
						|
 | 
						|
  if (scode == SLASH_SCAN && esc) return '/';	/* don't map numeric slash */
 | 
						|
 | 
						|
  keyrow = &keymap[scode * MAP_COLS];
 | 
						|
 | 
						|
  caps = shift;
 | 
						|
  lk = locks[ccurrent];
 | 
						|
  if ((lk & NUM_LOCK) && HOME_SCAN <= scode && scode <= DEL_SCAN) caps = !caps;
 | 
						|
  if ((lk & CAPS_LOCK) && (keyrow[0] & HASCAPS)) caps = !caps;
 | 
						|
 | 
						|
  if (alt) {
 | 
						|
	column = 2;
 | 
						|
	if (ctrl || alt_r) column = 3;	/* Ctrl + Alt == AltGr */
 | 
						|
	if (caps) column = 4;
 | 
						|
  } else {
 | 
						|
	column = 0;
 | 
						|
	if (caps) column = 1;
 | 
						|
	if (ctrl) column = 5;
 | 
						|
  }
 | 
						|
  return keyrow[column] & ~HASCAPS;
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				kbd_hw_int				     *
 | 
						|
 *===========================================================================*/
 | 
						|
PUBLIC void do_interrupt(m_ptr)
 | 
						|
message *m_ptr;
 | 
						|
{
 | 
						|
/* A keyboard interrupt has occurred.  Process it. */
 | 
						|
  int scode;
 | 
						|
  static timer_t timer;		/* timer must be static! */
 | 
						|
 | 
						|
  /* Fetch the character from the keyboard hardware and acknowledge it. */
 | 
						|
  scode = scan_keyboard();
 | 
						|
 | 
						|
  /* Store the scancode in memory so the task can get at it later. */
 | 
						|
  if (icount < KB_IN_BYTES) {
 | 
						|
	*ihead++ = scode;
 | 
						|
	if (ihead == ibuf + KB_IN_BYTES) ihead = ibuf;
 | 
						|
	icount++;
 | 
						|
	tty_table[ccurrent].tty_events = 1;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*==========================================================================*
 | 
						|
 *				kb_read					    *
 | 
						|
 *==========================================================================*/
 | 
						|
PRIVATE void kb_read(tp)
 | 
						|
tty_t *tp;
 | 
						|
{
 | 
						|
/* Process characters from the circular keyboard buffer. */
 | 
						|
 | 
						|
  char buf[3];
 | 
						|
  int scode;
 | 
						|
  unsigned ch;
 | 
						|
 | 
						|
  tp = &tty_table[ccurrent];		/* always use the current console */
 | 
						|
 | 
						|
  while (icount > 0) {
 | 
						|
	scode = *itail++;			/* take one key scan code */
 | 
						|
	if (itail == ibuf + KB_IN_BYTES) itail = ibuf;
 | 
						|
	icount--;
 | 
						|
 | 
						|
	/* Function keys are being used for debug dumps. */
 | 
						|
	if (func_key(scode)) continue;
 | 
						|
 | 
						|
	/* Perform make/break processing. */
 | 
						|
	ch = make_break(scode);
 | 
						|
 | 
						|
	if (ch <= 0xFF) {
 | 
						|
		/* A normal character. */
 | 
						|
		buf[0] = ch;
 | 
						|
		(void) in_process(tp, buf, 1);
 | 
						|
	} else
 | 
						|
	if (HOME <= ch && ch <= INSRT) {
 | 
						|
		/* An ASCII escape sequence generated by the numeric pad. */
 | 
						|
		buf[0] = ESC;
 | 
						|
		buf[1] = '[';
 | 
						|
		buf[2] = numpad_map[ch - HOME];
 | 
						|
		(void) in_process(tp, buf, 3);
 | 
						|
	} else
 | 
						|
	if (ch == ALEFT) {
 | 
						|
		/* Choose lower numbered console as current console. */
 | 
						|
		select_console(ccurrent - 1);
 | 
						|
		set_leds();
 | 
						|
	} else
 | 
						|
	if (ch == ARIGHT) {
 | 
						|
		/* Choose higher numbered console as current console. */
 | 
						|
		select_console(ccurrent + 1);
 | 
						|
		set_leds();
 | 
						|
	} else
 | 
						|
	if (AF1 <= ch && ch <= AF12) {
 | 
						|
		/* Alt-F1 is console, Alt-F2 is ttyc1, etc. */
 | 
						|
		select_console(ch - AF1);
 | 
						|
		set_leds();
 | 
						|
	} else
 | 
						|
	if (CF1 <= ch && ch <= CF12) {
 | 
						|
	    switch(ch) {
 | 
						|
  		case CF3: toggle_scroll(); break; /* hardware <-> software */	
 | 
						|
  		case CF7: sigchar(&tty_table[CONSOLE], SIGQUIT); break;
 | 
						|
  		case CF8: sigchar(&tty_table[CONSOLE], SIGINT); break;
 | 
						|
  		case CF9: sigchar(&tty_table[CONSOLE], SIGKILL); break;
 | 
						|
  	    }
 | 
						|
	}
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				make_break				     *
 | 
						|
 *===========================================================================*/
 | 
						|
PRIVATE unsigned make_break(scode)
 | 
						|
int scode;			/* scan code of key just struck or released */
 | 
						|
{
 | 
						|
/* This routine can handle keyboards that interrupt only on key depression,
 | 
						|
 * as well as keyboards that interrupt on key depression and key release.
 | 
						|
 * For efficiency, the interrupt routine filters out most key releases.
 | 
						|
 */
 | 
						|
  int ch, make, escape;
 | 
						|
  static int CAD_count = 0;
 | 
						|
 | 
						|
  /* Check for CTRL-ALT-DEL, and if found, halt the computer. This would
 | 
						|
   * be better done in keyboard() in case TTY is hung, except control and
 | 
						|
   * alt are set in the high level code.
 | 
						|
   */
 | 
						|
  if (ctrl && alt && (scode == DEL_SCAN || scode == INS_SCAN))
 | 
						|
  {
 | 
						|
	if (++CAD_count == 3) sys_abort(RBT_HALT);
 | 
						|
	sys_kill(INIT_PROC_NR, SIGABRT);
 | 
						|
	return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  /* High-order bit set on key release. */
 | 
						|
  make = (scode & KEY_RELEASE) == 0;		/* true if pressed */
 | 
						|
 | 
						|
  ch = map_key(scode &= ASCII_MASK);		/* map to ASCII */
 | 
						|
 | 
						|
  escape = esc;		/* Key is escaped?  (true if added since the XT) */
 | 
						|
  esc = 0;
 | 
						|
 | 
						|
  switch (ch) {
 | 
						|
  	case CTRL:		/* Left or right control key */
 | 
						|
		*(escape ? &ctrl_r : &ctrl_l) = make;
 | 
						|
		ctrl = ctrl_l | ctrl_r;
 | 
						|
		break;
 | 
						|
  	case SHIFT:		/* Left or right shift key */
 | 
						|
		*(scode == RSHIFT_SCAN ? &shift_r : &shift_l) = make;
 | 
						|
		shift = shift_l | shift_r;
 | 
						|
		break;
 | 
						|
  	case ALT:		/* Left or right alt key */
 | 
						|
		*(escape ? &alt_r : &alt_l) = make;
 | 
						|
		alt = alt_l | alt_r;
 | 
						|
		break;
 | 
						|
  	case CALOCK:		/* Caps lock - toggle on 0 -> 1 transition */
 | 
						|
		if (caps_down < make) {
 | 
						|
			locks[ccurrent] ^= CAPS_LOCK;
 | 
						|
			set_leds();
 | 
						|
		}
 | 
						|
		caps_down = make;
 | 
						|
		break;
 | 
						|
  	case NLOCK:		/* Num lock */
 | 
						|
		if (num_down < make) {
 | 
						|
			locks[ccurrent] ^= NUM_LOCK;
 | 
						|
			set_leds();
 | 
						|
		}
 | 
						|
		num_down = make;
 | 
						|
		break;
 | 
						|
  	case SLOCK:		/* Scroll lock */
 | 
						|
		if (scroll_down < make) {
 | 
						|
			locks[ccurrent] ^= SCROLL_LOCK;
 | 
						|
			set_leds();
 | 
						|
		}
 | 
						|
		scroll_down = make;
 | 
						|
		break;
 | 
						|
  	case EXTKEY:		/* Escape keycode */
 | 
						|
		esc = 1;		/* Next key is escaped */
 | 
						|
		return(-1);
 | 
						|
  	default:		/* A normal key */
 | 
						|
		if (make) return(ch);
 | 
						|
  }
 | 
						|
 | 
						|
  /* Key release, or a shift type key. */
 | 
						|
  return(-1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				set_leds				     *
 | 
						|
 *===========================================================================*/
 | 
						|
PRIVATE void set_leds()
 | 
						|
{
 | 
						|
/* Set the LEDs on the caps, num, and scroll lock keys */
 | 
						|
  int s;
 | 
						|
  if (! machine.pc_at) return;	/* PC/XT doesn't have LEDs */
 | 
						|
 | 
						|
  kb_wait();			/* wait for buffer empty  */
 | 
						|
  if ((s=sys_outb(KEYBD, LED_CODE)) != OK)
 | 
						|
      printf("Warning, sys_outb couldn't prepare for LED values: %d\n", s);
 | 
						|
   				/* prepare keyboard to accept LED values */
 | 
						|
  kb_ack();			/* wait for ack response  */
 | 
						|
 | 
						|
  kb_wait();			/* wait for buffer empty  */
 | 
						|
  if ((s=sys_outb(KEYBD, locks[ccurrent])) != OK)
 | 
						|
      printf("Warning, sys_outb couldn't give LED values: %d\n", s);
 | 
						|
				/* give keyboard LED values */
 | 
						|
  kb_ack();			/* wait for ack response  */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*==========================================================================*
 | 
						|
 *				kb_wait					    *
 | 
						|
 *==========================================================================*/
 | 
						|
PRIVATE int kb_wait()
 | 
						|
{
 | 
						|
/* Wait until the controller is ready; return zero if this times out. */
 | 
						|
 | 
						|
  int retries, status, temp;
 | 
						|
  int s;
 | 
						|
 | 
						|
  retries = MAX_KB_BUSY_RETRIES + 1;	/* wait until not busy */
 | 
						|
  do {
 | 
						|
      s = sys_inb(KB_STATUS, &status);
 | 
						|
      if (status & KB_OUT_FULL) {
 | 
						|
          s = sys_inb(KEYBD, &temp);	/* discard value */
 | 
						|
      }
 | 
						|
      if (! (status & (KB_IN_FULL|KB_OUT_FULL)) )
 | 
						|
          break;			/* wait until ready */
 | 
						|
  } while (--retries != 0);		/* continue unless timeout */ 
 | 
						|
  return(retries);		/* zero on timeout, positive if ready */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*==========================================================================*
 | 
						|
 *				kb_ack					    *
 | 
						|
 *==========================================================================*/
 | 
						|
PRIVATE int kb_ack()
 | 
						|
{
 | 
						|
/* Wait until kbd acknowledges last command; return zero if this times out. */
 | 
						|
 | 
						|
  int retries, s;
 | 
						|
  u8_t u8val;
 | 
						|
 | 
						|
  retries = MAX_KB_ACK_RETRIES + 1;
 | 
						|
  do {
 | 
						|
      s = sys_inb(KEYBD, &u8val);
 | 
						|
      if (u8val == KB_ACK)	
 | 
						|
          break;		/* wait for ack */
 | 
						|
  } while(--retries != 0);	/* continue unless timeout */
 | 
						|
 | 
						|
  return(retries);		/* nonzero if ack received */
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				kb_init					     *
 | 
						|
 *===========================================================================*/
 | 
						|
PUBLIC void kb_init(tp)
 | 
						|
tty_t *tp;
 | 
						|
{
 | 
						|
/* Initialize the keyboard driver. */
 | 
						|
  static int count = 0;
 | 
						|
  int i;
 | 
						|
 | 
						|
  tp->tty_devread = kb_read;	/* input function */
 | 
						|
  set_leds();			/* turn off numlock led */
 | 
						|
  scan_keyboard();		/* discard leftover keystroke */
 | 
						|
 | 
						|
  /* The following initialization should only run once. */
 | 
						|
  if (! count ++) {
 | 
						|
 | 
						|
      /* Clear the function key observers array. Also see func_key(). */
 | 
						|
      for (i=0; i<12; i++) {
 | 
						|
          fkey_obs[i] = NONE;	/* F1-F12 observers */
 | 
						|
          sfkey_obs[i] = NONE;	/* Shift F1-F12 observers */
 | 
						|
      }
 | 
						|
 | 
						|
      /* Set interrupt handler and enable keyboard IRQ. */
 | 
						|
      if ((i=sys_irqsetpolicy(KEYBOARD_IRQ, IRQ_REENABLE, &irq_hook_id)) != OK)
 | 
						|
          server_panic("TTY",  "Couldn't set keyboard IRQ policy", i);
 | 
						|
      if ((i=sys_irqenable(&irq_hook_id)) != OK)
 | 
						|
          server_panic("TTY", "Couldn't enable keyboard IRQs", i);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				kbd_loadmap				     *
 | 
						|
 *===========================================================================*/
 | 
						|
PUBLIC int kbd_loadmap(m)
 | 
						|
message *m;
 | 
						|
{
 | 
						|
/* Load a new keymap. */
 | 
						|
  int result;
 | 
						|
  result = sys_vircopy(m->PROC_NR, D, (vir_bytes) m->ADDRESS,
 | 
						|
  	SELF, D, (vir_bytes) keymap, 
 | 
						|
  	(vir_bytes) sizeof(keymap));
 | 
						|
  return(result);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				do_fkey_ctl				     *
 | 
						|
 *===========================================================================*/
 | 
						|
PUBLIC void do_fkey_ctl(m_ptr)
 | 
						|
message *m_ptr;			/* pointer to the request message */
 | 
						|
{
 | 
						|
/* This procedure allows processes to register a function key to receive
 | 
						|
 * notifications if it is pressed. At most one binding per key can exist.
 | 
						|
 */
 | 
						|
  int fkey = m_ptr->FKEY_CODE;		/* get function key code */
 | 
						|
  unsigned code;
 | 
						|
  int *observers = NULL;
 | 
						|
  int index = -1;
 | 
						|
  int result;
 | 
						|
 | 
						|
  /* See if this key can be observed; get the observers array and index. */ 
 | 
						|
  if (SF1 == fkey) result = EINVAL;		/* Shift-F1 is TTY reserved */
 | 
						|
  if (F1 <= fkey && fkey <= F12) { 		/* F1-F12 */
 | 
						|
      observers = fkey_obs; 
 | 
						|
      index = fkey - F1;
 | 
						|
  } else if (SF2 <= fkey && fkey <= SF12) {   	/* Shift F1-F12 */
 | 
						|
      observers = sfkey_obs; 
 | 
						|
      index = fkey - SF1;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Handle the request if an observers array was set above. */
 | 
						|
  if (observers) {
 | 
						|
      if (m_ptr->FKEY_ENABLE) {		/* try to register an observer */
 | 
						|
    	  if (observers[index] == NONE) {
 | 
						|
    	      observers[index] = m_ptr->m_source;
 | 
						|
    	      result = OK;		/* done, new observer registered */
 | 
						|
          } else {
 | 
						|
    	      result = EBUSY;		/* function key already bound */
 | 
						|
      	  }
 | 
						|
      } else {				/* unregister an observer */
 | 
						|
          if (observers[index] == m_ptr->m_source) {
 | 
						|
              observers[index] = NONE; 
 | 
						|
    	      result = OK;		/* done, observer unregistered */
 | 
						|
    	  } else {
 | 
						|
    	      result = EPERM;		/* can only remove own binding */
 | 
						|
          }
 | 
						|
      }
 | 
						|
  } else {
 | 
						|
    result =  EINVAL;			/* key cannot be observed */
 | 
						|
  }
 | 
						|
 | 
						|
  /* Almost done, return result to caller. */
 | 
						|
  m_ptr->m_type = result;
 | 
						|
  send(m_ptr->m_source, m_ptr);
 | 
						|
}
 | 
						|
 | 
						|
/*===========================================================================*
 | 
						|
 *				func_key				     *
 | 
						|
 *===========================================================================*/
 | 
						|
PRIVATE int func_key(scode)
 | 
						|
int scode;			/* scan code for a function key */
 | 
						|
{
 | 
						|
/* This procedure traps function keys for debugging purposes. Observers of 
 | 
						|
 * function keys are kept in a global array. If a subject (a key) is pressed
 | 
						|
 * the observer is notified of the event. Initialization of the arrays is done
 | 
						|
 * in kb_init, where NONE is set to indicate there is no interest in the key.
 | 
						|
 * Returns FALSE on a key release or if the key is not observable.
 | 
						|
 */
 | 
						|
  message m;
 | 
						|
  int *observers = NULL;
 | 
						|
  unsigned fkey;
 | 
						|
  int index = -1;
 | 
						|
  int i,s;
 | 
						|
  struct proc proc;
 | 
						|
 | 
						|
  /* Ignore key releases. If this is a key press, get full key code. */
 | 
						|
  if (scode & KEY_RELEASE) return(FALSE);	/* key release */
 | 
						|
  fkey = map_key(scode);		/* include modifiers */
 | 
						|
 | 
						|
  /* Key pressed, now see if there is an observer for the pressed key.
 | 
						|
   *	       F1-F12	observers are in fkey_obs array. 
 | 
						|
   *	SHIFT  F1-F12	observers are in sfkey_req array. 
 | 
						|
   *	CTRL   F1-F12	reserved (see kb_read)
 | 
						|
   *	ALT    F1-F12	reserved (see kb_read)
 | 
						|
   * Other combinations are not in use. Note that Alt+Shift+F1-F12 is yet
 | 
						|
   * defined in <minix/keymap.h>, but other modifier combinations are not. 
 | 
						|
   */
 | 
						|
  if (SF1 == fkey) {
 | 
						|
    printf("\n");
 | 
						|
    printf("System information.   Known function key mappings to request debug dumps:\n");
 | 
						|
    printf("-------------------------------------------------------------------------\n");
 | 
						|
    for (i=0; i<12; i++) {
 | 
						|
 | 
						|
      printf(" %sF%d: ", i+1<10? " ":"", i+1);
 | 
						|
      if (fkey_obs[i] != NONE) {
 | 
						|
          if ((s=sys_getproc(&proc, fkey_obs[i]))!=OK)
 | 
						|
              printf("sys_getproc: %d\n", s);
 | 
						|
          printf("%-14.14s", proc.p_name);
 | 
						|
      } else {
 | 
						|
          printf("%-14.14s", "<none>");
 | 
						|
      }
 | 
						|
 | 
						|
      printf("    %sShift-F%d: ", i+1<10? " ":"", i+1);
 | 
						|
      if (sfkey_obs[i] != NONE) {
 | 
						|
          if ((s=sys_getproc(&proc, sfkey_obs[i]))!=OK)
 | 
						|
              printf("sys_getproc: %d\n", s);
 | 
						|
          printf("%-14.14s", proc.p_name);
 | 
						|
      } else {
 | 
						|
          printf("%-14.14s", "<none>");
 | 
						|
      }
 | 
						|
      printf("\n");
 | 
						|
    }
 | 
						|
    printf("\n");
 | 
						|
    printf("Press one of the registered function keys to trigger a debug dump.\n");
 | 
						|
    printf("\n");
 | 
						|
  }
 | 
						|
  else if (F1 <= fkey && fkey <= F12) {		/* F1-F12 */
 | 
						|
      observers = &fkey_obs[0];	
 | 
						|
      index = fkey - F1;
 | 
						|
  } else if (SF2 <= fkey && fkey <= SF12) {	/* Shift F2-F12 */
 | 
						|
      observers = &sfkey_obs[0];
 | 
						|
      index = fkey - SF1;
 | 
						|
  }
 | 
						|
  if (! observers) return(FALSE);	/* not observable */
 | 
						|
 | 
						|
  /* See if an observer is registered and send it a message. */
 | 
						|
  if (observers[index] != NONE) { 
 | 
						|
#if DEAD_CODE
 | 
						|
      m.m_type = FKEY_PRESSED;
 | 
						|
      m.FKEY_NUM = index+1;
 | 
						|
      m.FKEY_CODE = fkey;
 | 
						|
      if (OK != (s=nb_send(observers[index], &m))) {
 | 
						|
          printf("WARNING: F%d key nb_send to process %d failed: %d.\n",
 | 
						|
          	index+1, observers[index], s);
 | 
						|
      }
 | 
						|
#else
 | 
						|
      m.NOTIFY_TYPE = FKEY_PRESSED;
 | 
						|
      m.NOTIFY_ARG = fkey;
 | 
						|
      m.NOTIFY_FLAGS = index+1;
 | 
						|
      if (OK != (s=notify(observers[index], &m))) {
 | 
						|
          printf("WARNING: F%d key notify to process %d failed: %d.\n",
 | 
						|
          	index+1, observers[index], s);
 | 
						|
      }
 | 
						|
#endif
 | 
						|
  }
 | 
						|
  return(TRUE);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*==========================================================================*
 | 
						|
 *				scan_keyboard				    *
 | 
						|
 *==========================================================================*/
 | 
						|
PRIVATE int scan_keyboard()
 | 
						|
{
 | 
						|
/* Fetch the character from the keyboard hardware and acknowledge it. */
 | 
						|
  pvb_pair_t byte_in[2], byte_out[2];
 | 
						|
  
 | 
						|
  byte_in[0].port = KEYBD;	/* get the scan code for the key struck */
 | 
						|
  byte_in[1].port = PORT_B;	/* strobe the keyboard to ack the char */
 | 
						|
  sys_vinb(byte_in, 2);		/* request actual input */
 | 
						|
 | 
						|
  pv_set(byte_out[0], PORT_B, byte_in[1].value | KBIT); /* strobe bit high */
 | 
						|
  pv_set(byte_out[1], PORT_B, byte_in[1].value);	/* then strobe low */
 | 
						|
  sys_voutb(byte_out, 2);	/* request actual output */
 | 
						|
 | 
						|
  return(byte_in[0].value);		/* return scan code */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*==========================================================================*
 | 
						|
 *				do_panic_dumps 				    *
 | 
						|
 *==========================================================================*/
 | 
						|
PUBLIC void do_panic_dumps(m)
 | 
						|
message *m;			/* request message to TTY */
 | 
						|
{
 | 
						|
/* Wait for keystrokes for printing debugging info and reboot. */
 | 
						|
 | 
						|
  int quiet, code;
 | 
						|
 | 
						|
  /* A panic! Allow debug dumps until user wants to shutdown. */
 | 
						|
  printf("\nHit ESC to reboot, DEL to shutdown, F-keys for debug dumps\n");
 | 
						|
 | 
						|
  (void) scan_keyboard();	/* ack any old input */
 | 
						|
  quiet = scan_keyboard();/* quiescent value (0 on PC, last code on AT)*/
 | 
						|
  for (;;) {
 | 
						|
	tick_delay(10);
 | 
						|
	/* See if there are pending request for output, but don't block. 
 | 
						|
	 * Diagnostics can span multiple printf()s, so do it in a loop.
 | 
						|
	 */
 | 
						|
	while (nb_receive(ANY, m) == OK) {
 | 
						|
		switch(m->m_type) {
 | 
						|
		case NEW_KMESS:	   do_new_kmess(m);	break;
 | 
						|
		case DIAGNOSTICS:  do_diagnostics(m);	break;
 | 
						|
		default:	;	/* do nothing */ 
 | 
						|
		}
 | 
						|
		tick_delay(1);		/* allow more */
 | 
						|
	}
 | 
						|
	code = scan_keyboard();
 | 
						|
	if (code != quiet) {
 | 
						|
		/* A key has been pressed. */
 | 
						|
		switch (code) {			/* possibly abort MINIX */
 | 
						|
		case ESC_SCAN:  sys_abort(RBT_REBOOT); 	return;	
 | 
						|
		case DEL_SCAN:  sys_abort(RBT_HALT); 	return;	
 | 
						|
		}
 | 
						|
		(void) func_key(code);	     	/* check for function key */
 | 
						|
		quiet = scan_keyboard();
 | 
						|
	}
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 |