/* * The back door to the keyboard driver! * This function is called by the console driver, via the kbdio module, * to tickle keyboard drivers when the low-level console is being initialized. * Almost nothing in the kernel has been initialied yet. Try to probe * keyboards if possible. * NOTE: because of the way the low-level conole is initialized, this routine * may be called more than once!! */ static int pckbd_configure(int flags) { keyboard_t *kbd; int arg[2]; int i; /* XXX: a kludge to obtain the device configuration flags */ if (resource_int_value(DRIVER_NAME, 0, "flags", &i) == 0) { flags |= i; /* if the driver is disabled, unregister the keyboard if any */ if (resource_int_value(DRIVER_NAME, 0, "disabled", &i) == 0 && i != 0) { i = kbd_find_keyboard(DRIVER_NAME, PC98KBD_DEFAULT); if (i >= 0) { kbd = kbd_get_keyboard(i); kbd_unregister(kbd); kbd->kb_flags &= ~KB_REGISTERED; return 0; } } } /* probe the default keyboard */ arg[0] = -1; arg[1] = -1; kbd = NULL; if (pckbd_probe(PC98KBD_DEFAULT, arg, flags)) return 0; if (pckbd_init(PC98KBD_DEFAULT, &kbd, arg, flags)) return 0; /* return the number of found keyboards */ return 1; }
/* finish using this keyboard */ static int pckbd_term(keyboard_t *kbd) { pckbd_state_t *state = (pckbd_state_t *)kbd->kb_data; kbd_unregister(kbd); callout_drain(&state->ks_timer); return 0; }
/* * The back door to the keyboard driver! * This function is called by the console driver, via the kbdio module, * to tickle keyboard drivers when the low-level console is being initialized. * Almost nothing in the kernel has been initialied yet. Try to probe * keyboards if possible. * NOTE: because of the way the low-level console is initialized, this routine * may be called more than once!! */ static int atkbd_configure(int flags) { keyboard_t *kbd; int arg[2]; int i; /* * Probe the keyboard controller, if not present or if the driver * is disabled, unregister the keyboard if any. */ if (atkbdc_configure() != 0 || resource_disabled("atkbd", ATKBD_DEFAULT)) { i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT); if (i >= 0) { kbd = kbd_get_keyboard(i); KBD_ALWAYS_LOCK(kbd); kbd_unregister(kbd); kbd = NULL; /* huh? */ } return 0; } /* XXX: a kludge to obtain the device configuration flags */ if (resource_int_value("atkbd", ATKBD_DEFAULT, "flags", &i) == 0) flags |= i; /* probe the default keyboard */ arg[0] = -1; arg[1] = -1; kbd = NULL; if (atkbd_probe(ATKBD_DEFAULT, arg, flags)) { return 0; } if (atkbd_init(ATKBD_DEFAULT, &kbd, arg, flags)) { return 0; } /* return the number of found keyboards */ return 1; }
/* * The back door to the keyboard driver! * This function is called by the console driver, via the kbdio module, * to tickle keyboard drivers when the low-level console is being initialized. * Almost nothing in the kernel has been initialied yet. Try to probe * keyboards if possible. * NOTE: because of the way the low-level conole is initialized, this routine * may be called more than once!! */ static int atkbd_configure(int flags) { keyboard_t *kbd; int arg[2]; #ifdef __i386__ struct isa_device *dev; int i; /* XXX: a kludge to obtain the device configuration flags */ dev = find_isadev(isa_devtab_tty, &atkbddriver, 0); if (dev != NULL) { flags |= dev->id_flags; /* if the driver is disabled, unregister the keyboard if any */ if (!dev->id_enabled) { i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT); if (i >= 0) { kbd = kbd_get_keyboard(i); kbd_unregister(kbd); kbd->kb_flags &= ~KB_REGISTERED; return 0; } } } #endif /* probe the keyboard controller */ atkbdc_configure(); /* probe the default keyboard */ arg[0] = -1; arg[1] = -1; kbd = NULL; if (atkbd_probe(ATKBD_DEFAULT, arg, flags)) return 0; if (atkbd_init(ATKBD_DEFAULT, &kbd, arg, flags)) return 0; /* return the number of found keyboards */ return 1; }
/* finish using this keyboard */ static int ukbd_term(keyboard_t *kbd) { ukbd_state_t *state; int error; int s; s = splusb(); state = (ukbd_state_t *)kbd->kb_data; DPRINTF(("ukbd_term: ks_ifstate=0x%x\n", state->ks_ifstate)); untimeout(ukbd_timeout, (void *)kbd, state->ks_timeout_handle); callout_handle_init(&state->ks_timeout_handle); if (state->ks_ifstate & INTRENABLED) ukbd_enable_intr(kbd, FALSE, NULL); if (state->ks_ifstate & INTRENABLED) { splx(s); DPRINTF(("ukbd_term: INTRENABLED!\n")); return ENXIO; } error = kbd_unregister(kbd); DPRINTF(("ukbd_term: kbd_unregister() %d\n", error)); if (error == 0) { kbd->kb_flags = 0; if (kbd != &default_kbd) { free(kbd->kb_keymap, M_DEVBUF); free(kbd->kb_accentmap, M_DEVBUF); free(kbd->kb_fkeytab, M_DEVBUF); free(state, M_DEVBUF); free(kbd, M_DEVBUF); } } splx(s); return error; }
/* finish using this keyboard */ static int ukbd_term(keyboard_t *kbd) { ukbd_state_t *state; int error; crit_enter(); state = (ukbd_state_t *)kbd->kb_data; DPRINTF(("ukbd_term: ks_ifstate=0x%x\n", state->ks_ifstate)); callout_stop(&state->ks_timeout); if (state->ks_ifstate & INTRENABLED) ukbd_enable_intr(kbd, FALSE, NULL); if (state->ks_ifstate & INTRENABLED) { crit_exit(); DPRINTF(("ukbd_term: INTRENABLED!\n")); return ENXIO; } error = kbd_unregister(kbd); DPRINTF(("ukbd_term: kbd_unregister() %d\n", error)); if (error == 0) { kbd->kb_flags = 0; if (kbd != &default_kbd) { kfree(kbd->kb_keymap, M_DEVBUF); kfree(kbd->kb_accentmap, M_DEVBUF); kfree(kbd->kb_fkeytab, M_DEVBUF); kfree(state, M_DEVBUF); kfree(kbd, M_DEVBUF); } } crit_exit(); return error; }
/* finish using this keyboard */ static int pckbd_term(keyboard_t *kbd) { kbd_unregister(kbd); return 0; }
/* reset and initialize the device */ static int atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) { keyboard_t *kbd; atkbd_state_t *state; keymap_t *keymap; accentmap_t *accmap; fkeytab_t *fkeymap; int fkeymap_size; int delay[2]; int *data = (int *)arg; /* data[0]: controller, data[1]: irq */ int error, needfree; /* XXX */ if (unit == ATKBD_DEFAULT) { *kbdp = kbd = &default_kbd; if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) return 0; state = &default_kbd_state; keymap = &default_keymap; accmap = &default_accentmap; fkeymap = default_fkeytab; fkeymap_size = sizeof(default_fkeytab)/sizeof(default_fkeytab[0]); needfree = 0; } else if (*kbdp == NULL) { *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT | M_ZERO); state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT | M_ZERO); /* NB: these will always be initialized 'cuz !KBD_IS_PROBED */ keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT); accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT); fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT); fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]); needfree = 1; if ((kbd == NULL) || (state == NULL) || (keymap == NULL) || (accmap == NULL) || (fkeymap == NULL)) { error = ENOMEM; goto bad; } } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { return 0; } else { kbd = *kbdp; state = (atkbd_state_t *)kbd->kb_data; bzero(state, sizeof(*state)); keymap = kbd->kb_keymap; accmap = kbd->kb_accentmap; fkeymap = kbd->kb_fkeytab; fkeymap_size = kbd->kb_fkeytab_size; needfree = 0; } if (!KBD_IS_PROBED(kbd)) { state->kbdc = atkbdc_open(data[0]); if (state->kbdc == NULL) { error = ENXIO; goto bad; } kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags, 0, 0); bcopy(&key_map, keymap, sizeof(key_map)); bcopy(&accent_map, accmap, sizeof(accent_map)); bcopy(fkey_tab, fkeymap, imin(fkeymap_size*sizeof(fkeymap[0]), sizeof(fkey_tab))); kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); kbd->kb_data = (void *)state; if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */ if (flags & KB_CONF_FAIL_IF_NO_KBD) { error = ENXIO; goto bad; } } else { KBD_FOUND_DEVICE(kbd); } atkbd_clear_state(kbd); state->ks_mode = K_XLATE; /* * FIXME: set the initial value for lock keys in ks_state * according to the BIOS data? */ KBD_PROBE_DONE(kbd); } if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY; if (KBD_HAS_DEVICE(kbd) && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) { kbd_unregister(kbd); error = ENXIO; goto bad; } atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); get_typematic(kbd); delay[0] = kbd->kb_delay1; delay[1] = kbd->kb_delay2; atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); KBD_INIT_DONE(kbd); } if (!KBD_IS_CONFIGURED(kbd)) { if (kbd_register(kbd) < 0) { error = ENXIO; goto bad; } KBD_CONFIG_DONE(kbd); } return 0; bad: if (needfree) { if (state != NULL) free(state, M_DEVBUF); if (keymap != NULL) free(keymap, M_DEVBUF); if (accmap != NULL) free(accmap, M_DEVBUF); if (fkeymap != NULL) free(fkeymap, M_DEVBUF); if (kbd != NULL) { free(kbd, M_DEVBUF); *kbdp = NULL; /* insure ref doesn't leak to caller */ } } return error; }
/* reset and initialize the device */ static int atkbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) { keyboard_t *kbd; atkbd_state_t *state; keymap_t *keymap; accentmap_t *accmap; fkeytab_t *fkeymap; int fkeymap_size; int delay[2]; int *data = (int *)arg; /* data[0]: controller, data[1]: irq */ int error, needfree; #ifdef EVDEV_SUPPORT struct evdev_dev *evdev; char phys_loc[8]; #endif /* XXX */ if (unit == ATKBD_DEFAULT) { *kbdp = kbd = &default_kbd; if (KBD_IS_INITIALIZED(kbd) && KBD_IS_CONFIGURED(kbd)) return 0; state = &default_kbd_state; keymap = &default_keymap; accmap = &default_accentmap; fkeymap = default_fkeytab; fkeymap_size = nitems(default_fkeytab); needfree = 0; } else if (*kbdp == NULL) { *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT | M_ZERO); state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT | M_ZERO); /* NB: these will always be initialized 'cuz !KBD_IS_PROBED */ keymap = malloc(sizeof(key_map), M_DEVBUF, M_NOWAIT); accmap = malloc(sizeof(accent_map), M_DEVBUF, M_NOWAIT); fkeymap = malloc(sizeof(fkey_tab), M_DEVBUF, M_NOWAIT); fkeymap_size = sizeof(fkey_tab)/sizeof(fkey_tab[0]); needfree = 1; if ((kbd == NULL) || (state == NULL) || (keymap == NULL) || (accmap == NULL) || (fkeymap == NULL)) { error = ENOMEM; goto bad; } } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { return 0; } else { kbd = *kbdp; state = (atkbd_state_t *)kbd->kb_data; bzero(state, sizeof(*state)); keymap = kbd->kb_keymap; accmap = kbd->kb_accentmap; fkeymap = kbd->kb_fkeytab; fkeymap_size = kbd->kb_fkeytab_size; needfree = 0; } if (!KBD_IS_PROBED(kbd)) { state->kbdc = atkbdc_open(data[0]); if (state->kbdc == NULL) { error = ENXIO; goto bad; } kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags, 0, 0); bcopy(&key_map, keymap, sizeof(key_map)); bcopy(&accent_map, accmap, sizeof(accent_map)); bcopy(fkey_tab, fkeymap, imin(fkeymap_size * sizeof(fkeymap[0]), sizeof(fkey_tab))); kbd_set_maps(kbd, keymap, accmap, fkeymap, fkeymap_size); kbd->kb_data = (void *)state; if (probe_keyboard(state->kbdc, flags)) { /* shouldn't happen */ if (flags & KB_CONF_FAIL_IF_NO_KBD) { error = ENXIO; goto bad; } } else { KBD_FOUND_DEVICE(kbd); } atkbd_clear_state(kbd); state->ks_mode = K_XLATE; /* * FIXME: set the initial value for lock keys in ks_state * according to the BIOS data? */ KBD_PROBE_DONE(kbd); } if (!KBD_IS_INITIALIZED(kbd) && !(flags & KB_CONF_PROBE_ONLY)) { kbd->kb_config = flags & ~KB_CONF_PROBE_ONLY; if (KBD_HAS_DEVICE(kbd) && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) { kbd_unregister(kbd); error = ENXIO; goto bad; } atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); set_typematic(kbd); delay[0] = kbd->kb_delay1; delay[1] = kbd->kb_delay2; atkbd_ioctl(kbd, KDSETREPEAT, (caddr_t)delay); #ifdef EVDEV_SUPPORT /* register as evdev provider on first init */ if (state->ks_evdev == NULL) { snprintf(phys_loc, sizeof(phys_loc), "atkbd%d", unit); evdev = evdev_alloc(); evdev_set_name(evdev, "AT keyboard"); evdev_set_phys(evdev, phys_loc); evdev_set_id(evdev, BUS_I8042, PS2_KEYBOARD_VENDOR, PS2_KEYBOARD_PRODUCT, 0); evdev_set_methods(evdev, kbd, &atkbd_evdev_methods); evdev_support_event(evdev, EV_SYN); evdev_support_event(evdev, EV_KEY); evdev_support_event(evdev, EV_LED); evdev_support_event(evdev, EV_REP); evdev_support_all_known_keys(evdev); evdev_support_led(evdev, LED_NUML); evdev_support_led(evdev, LED_CAPSL); evdev_support_led(evdev, LED_SCROLLL); if (evdev_register_mtx(evdev, &Giant)) evdev_free(evdev); else state->ks_evdev = evdev; state->ks_evdev_state = 0; } #endif KBD_INIT_DONE(kbd); } if (!KBD_IS_CONFIGURED(kbd)) { if (kbd_register(kbd) < 0) { error = ENXIO; goto bad; } KBD_CONFIG_DONE(kbd); } return 0; bad: if (needfree) { if (state != NULL) free(state, M_DEVBUF); if (keymap != NULL) free(keymap, M_DEVBUF); if (accmap != NULL) free(accmap, M_DEVBUF); if (fkeymap != NULL) free(fkeymap, M_DEVBUF); if (kbd != NULL) { free(kbd, M_DEVBUF); *kbdp = NULL; /* insure ref doesn't leak to caller */ } } return error; }