static int init_kbd(unsigned ss, unsigned typematic, unsigned xlat) { while(read_kbd() != -1) /* nothing */; /* disable keyboard before programming it */ write_kbd_await_ack(0xF5); /* disable PS/2 mouse, set SYS bit, and Enable Keyboard Interrupt... */ write_kbd(0x64, 0x60); /*jach: enable mouse */ //write_kbd(0x64, 0xA8); /* ...and either disable or enable AT-to-XT keystroke conversion */ write_kbd(0x60, xlat ? 0x65 : 0x25); /* program desired scancode set */ write_kbd_await_ack(0xF0); write_kbd_await_ack(ss); /* we want all keys to return both a make code (when pressed) and a break code (when released -- scancode set 3 only) */ if(ss == 3) { write_kbd_await_ack(0xFA); } /* set typematic delay and rate */ write_kbd_await_ack(0xF3); write_kbd_await_ack(typematic); /* enable keyboard */ write_kbd_await_ack(0xF4); return 0; }
/******************************************************** This identifies the current keyboard as being MF II, then checks the current scancode set and changes it to set 2 if it is not currently set 2. NOTE: work on keyboard driver so that it doesn't require cli/sti, but just mutexes. ********************************************************/ void setup_keyboard() { volatile u_short *keyboard_isr_fired; // first, find out what kinda keyboard we have here k_printf("Detecting type of keyboard...\n"); switch(kbd_get_id()) { case 0: k_printf("Unknown keyboard... Ripple has halted.\n"); asm("cli"); asm("hlt"); case 1: k_printf("AT keyboard found, Ripple requires a newer keyboard... Ripple has halted.\n"); asm("cli"); asm("hlt"); case 2: k_printf("MF II keyboard detected.\n"); break; default: k_printf("No keyboard found, Ripple requires a keyboard... Ripple has halted.\n"); asm("cli"); asm("hlt"); }; asm("cli"); // setup scancode set 2 kbd_set_scancode_set(2); k_printf("Scancode set is: %d\n", kbd_curr_scancode_set()); // disable "IBM PC compatibility mode"(no converting scancode sets to set 1) write_kbd(0x64, 0x60); write_kbd(0x60, 0x07); k_printf("\nWatching IRQ 1... \n"); keyboard_isr_fired = watch_irq(1, 0x12984C00); if(keyboard_isr_fired != 0) { *keyboard_isr_fired = 0; k_printf("success, IRQ has been allocated.\n"); asm("sti"); for(;;) { //putc('x'); if(*keyboard_isr_fired >= 1) { k_printf("%x\n", inportb(0x60)); *keyboard_isr_fired -= 1; }; }; } else { asm("sti"); k_printf("failure\n"); return; }; };
static int write_kbd_await_ack(unsigned val) { int got; write_kbd(0x60, val); got = read_kbd(); if(got != 0xFA) { return -1; } return 0; };
// 1 = succes u_char write_kbd_await_ack(u_char val) { u_char got; write_kbd(0x60, val); got = read_kbd(); if(got != 0xFA) { k_printf("write_kbd_await_ack: expected acknowledge (0xFA), got 0x%x\n", got); return 0; }; return 1; };
static int set_typematic(keyboard_t *kbd) { int val, error; atkbd_state_t *state = kbd->kb_data; val = typematic(DEFAULT_DELAY, DEFAULT_RATE); error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, val); if (error == 0) { kbd->kb_delay1 = typematic_delay(val); kbd->kb_delay2 = typematic_rate(val); } return (error); }
/* some useful control functions */ static int atkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t arg) { /* translate LED_XXX bits into the device specific bits */ static u_char ledmap[8] = { 0, 4, 2, 6, 1, 5, 3, 7, }; atkbd_state_t *state = kbd->kb_data; int error; int s; int i; #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD4) || defined(COMPAT_43) int ival; #endif s = spltty(); switch (cmd) { case KDGKBMODE: /* get keyboard mode */ *(int *)arg = state->ks_mode; break; #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD4) || defined(COMPAT_43) case _IO('K', 7): ival = IOCPARM_IVAL(arg); arg = (caddr_t)&ival; /* FALLTHROUGH */ #endif case KDSKBMODE: /* set keyboard mode */ switch (*(int *)arg) { case K_XLATE: if (state->ks_mode != K_XLATE) { /* make lock key state and LED state match */ state->ks_state &= ~LOCK_MASK; state->ks_state |= KBD_LED_VAL(kbd); } /* FALLTHROUGH */ case K_RAW: case K_CODE: if (state->ks_mode != *(int *)arg) { atkbd_clear_state(kbd); state->ks_mode = *(int *)arg; } break; default: splx(s); return EINVAL; } break; case KDGETLED: /* get keyboard LED */ *(int *)arg = KBD_LED_VAL(kbd); break; #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD4) || defined(COMPAT_43) case _IO('K', 66): ival = IOCPARM_IVAL(arg); arg = (caddr_t)&ival; /* FALLTHROUGH */ #endif case KDSETLED: /* set keyboard LED */ /* NOTE: lock key state in ks_state won't be changed */ if (*(int *)arg & ~LOCK_MASK) { splx(s); return EINVAL; } i = *(int *)arg; /* replace CAPS LED with ALTGR LED for ALTGR keyboards */ if (state->ks_mode == K_XLATE && kbd->kb_keymap->n_keys > ALTGR_OFFSET) { if (i & ALKED) i |= CLKED; else i &= ~CLKED; } if (KBD_HAS_DEVICE(kbd)) { error = write_kbd(state->kbdc, KBDC_SET_LEDS, ledmap[i & LED_MASK]); if (error) { splx(s); return error; } } KBD_LED_VAL(kbd) = *(int *)arg; break; case KDGKBSTATE: /* get lock key state */ *(int *)arg = state->ks_state & LOCK_MASK; break; #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD4) || defined(COMPAT_43) case _IO('K', 20): ival = IOCPARM_IVAL(arg); arg = (caddr_t)&ival; /* FALLTHROUGH */ #endif case KDSKBSTATE: /* set lock key state */ if (*(int *)arg & ~LOCK_MASK) { splx(s); return EINVAL; } state->ks_state &= ~LOCK_MASK; state->ks_state |= *(int *)arg; splx(s); /* set LEDs and quit */ return atkbd_ioctl(kbd, KDSETLED, arg); case KDSETREPEAT: /* set keyboard repeat rate (new interface) */ splx(s); if (!KBD_HAS_DEVICE(kbd)) return 0; i = typematic(((int *)arg)[0], ((int *)arg)[1]); error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, i); if (error == 0) { kbd->kb_delay1 = typematic_delay(i); kbd->kb_delay2 = typematic_rate(i); } return error; #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD4) || defined(COMPAT_43) case _IO('K', 67): ival = IOCPARM_IVAL(arg); arg = (caddr_t)&ival; /* FALLTHROUGH */ #endif case KDSETRAD: /* set keyboard repeat rate (old interface) */ splx(s); if (!KBD_HAS_DEVICE(kbd)) return 0; error = write_kbd(state->kbdc, KBDC_SET_TYPEMATIC, *(int *)arg); if (error == 0) { kbd->kb_delay1 = typematic_delay(*(int *)arg); kbd->kb_delay2 = typematic_rate(*(int *)arg); } return error; case PIO_KEYMAP: /* set keyboard translation table */ case PIO_KEYMAPENT: /* set keyboard translation table entry */ case PIO_DEADKEYMAP: /* set accent key translation table */ state->ks_accents = 0; /* FALLTHROUGH */ default: splx(s); return genkbd_commonioctl(kbd, cmd, arg); } splx(s); return 0; }
void settogglebits(unsigned char b) { write_kbd(0x60,0xED); write_kbd(0x60,b); ;};
static int set1_scancode_to_ascii(unsigned code) { static const unsigned char map[] = { /* 00 */0, 0x1B, '1', '2', '3', '4', '5', '6', /* 08 */'7', '8', '9', '0', '-', '=', '\b', '\t', /* 10 */'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 1Dh is left Ctrl */ /* 18 */'o', 'p', '[', ']', '\n', 0, 'a', 's', /* 20 */'d', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 2Ah is left Shift */ /* 28 */'\'', '`', 0, '\\', 'z', 'x', 'c', 'v', /* 36h is right Shift */ /* 30 */'b', 'n', 'm', ',', '.', '/', 0, 0, /* 38h is left Alt, 3Ah is Caps Lock */ /* 38 */0, ' ', 0, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, /* 45h is Num Lock, 46h is Scroll Lock */ /* 40 */KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,0, 0, KEY_HOME, /* 48 */KEY_UP, KEY_PGUP,'-', KEY_LFT,'5', KEY_RT, '+', KEY_END, /* 50 */KEY_DN, KEY_PGDN,KEY_INS,KEY_DEL,0, 0, 0, KEY_F11, /* 58 */KEY_F12 }; static const unsigned char shift_map[] = { /* 00 */0, 0x1B, '!', '@', '#', '$', '%', '^', /* 08 */'&', '*', '(', ')', '_', '+', '\b', '\t', /* 10 */'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 1Dh is left Ctrl */ /* 18 */'O', 'P', '{', '}', '\n', 0, 'A', 'S', /* 20 */'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 2Ah is left Shift */ /* 28 */'"', '~', 0, '|', 'Z', 'X', 'C', 'V', /* 36h is right Shift */ /* 30 */'B', 'N', 'M', '<', '>', '?', 0, 0, /* 38h is left Alt, 3Ah is Caps Lock */ /* 38 */0, ' ', 0, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, /* 45h is Num Lock, 46h is Scroll Lock */ /* 40 */KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,0, 0, KEY_HOME, /* 48 */KEY_UP, KEY_PGUP,'-', KEY_LFT,'5', KEY_RT, '+', KEY_END, /* 50 */KEY_DN, KEY_PGDN,KEY_INS,KEY_DEL,0, 0, 0, KEY_F11, /* 58 */KEY_F12 }; static unsigned saw_break_code; /**/ unsigned temp; /* check for break code (i.e. a key is released) */ if(code >= 0x80) { saw_break_code = 1; code &= 0x7F; } /* the only break codes we're interested in are Shift, Ctrl, Alt */ if(saw_break_code) { if(code == RAW1_LEFT_ALT || code == RAW1_RIGHT_ALT) kbd_status &= ~KBD_META_ALT; else if(code == RAW1_LEFT_CTRL || code == RAW1_RIGHT_CTRL) kbd_status &= ~KBD_META_CTRL; else if(code == RAW1_LEFT_SHIFT || code == RAW1_RIGHT_SHIFT) kbd_status &= ~KBD_META_SHIFT; saw_break_code = 0; return -1; } /* it's a make code: check the "meta" keys, as above */ if(code == RAW1_LEFT_ALT || code == RAW1_RIGHT_ALT) { kbd_status |= KBD_META_ALT; return -1; } if(code == RAW1_LEFT_CTRL || code == RAW1_RIGHT_CTRL) { kbd_status |= KBD_META_CTRL; return -1; } if(code == RAW1_LEFT_SHIFT || code == RAW1_RIGHT_SHIFT) { kbd_status |= KBD_META_SHIFT; return -1; } /* Scroll Lock, Num Lock, and Caps Lock set the LEDs. These keys have on-off (toggle or XOR) action, instead of momentary action */ if(code == RAW1_SCROLL_LOCK) { kbd_status ^= KBD_META_SCRL; goto LEDS; } if(code == RAW1_NUM_LOCK) { kbd_status ^= KBD_META_NUM; goto LEDS; } if(code == RAW1_CAPS_LOCK) { kbd_status ^= KBD_META_CAPS; LEDS: write_kbd(0x60, 0xED); /* "set LEDs" command */ temp = 0; if(kbd_status & KBD_META_SCRL) temp |= 1; if(kbd_status & KBD_META_NUM) temp |= 2; if(kbd_status & KBD_META_CAPS) temp |= 4; write_kbd(0x60, temp); /* bottom 3 bits set LEDs */ return -1; }; if ( (kbd_status & KBD_META_ALT) && (kbd_status & KBD_META_CTRL)) { if(code >= sizeof(shift_map) / sizeof(shift_map[0])) return -1; temp = shift_map[code]; if (temp == KEY_DEL) return SOFT_RESET; return temp+400; }; /*if(kbd_status & KBD_META_ALT) return code+300;*/ /* convert A-Z[\]^_ to control chars */ if(kbd_status & KBD_META_CTRL) { if(code >= sizeof(map) / sizeof(map[0])) return -1; temp = map[code]; if(temp >= 'a' && temp <= 'z') return temp - 'a'; if(temp >= '[' && temp <= '_') return temp - '[' + 0x1B; return -1; } /* convert raw scancode to ASCII */ if(kbd_status & KBD_META_SHIFT) { /* ignore invalid scan codes */ if(code >= sizeof(shift_map) / sizeof(shift_map[0])) return -1; temp = shift_map[code]; /* defective keyboard? non-US keyboard? more than 104 keys? */ if(temp == 0) return -1; /* caps lock? */ if(kbd_status & KBD_META_CAPS) { if(temp >= 'A' && temp <= 'Z') temp = map[code]; } } else { if(code >= sizeof(map) / sizeof(map[0])) return -1; temp = map[code]; if(temp == 0) return -1; if(kbd_status & KBD_META_CAPS) { if(temp >= 'a' && temp <= 'z') temp = shift_map[code]; } } return temp; };
// returns current scancode set, or 0 upon failer u_char kbd_curr_scancode_set() { write_kbd_await_ack(0xF0); write_kbd(0x60, 0); return(read_kbd()); // return scancode set };