static int sunkbd_configure(int flags) { struct sunkbd_softc *sc; /* * We are only prepared to be used for the high-level console * when the keyboard is both configured and attached. */ if (!(flags & KB_CONF_PROBE_ONLY)) { if (KBD_IS_INITIALIZED(&sunkbd_softc.sc_kbd)) goto found; else return (0); } if (uart_cpu_getdev(UART_DEV_KEYBOARD, &uart_keyboard)) return (0); if (uart_probe(&uart_keyboard)) return (0); uart_init(&uart_keyboard); uart_keyboard.type = UART_DEV_KEYBOARD; uart_keyboard.attach = sunkbd_attach; uart_add_sysdev(&uart_keyboard); if (sunkbd_probe_keyboard(&uart_keyboard) != KB_SUN4) return (0); sc = &sunkbd_softc; callout_init(&sc->sc_repeat_callout, 0); sunkbd_clear_state(&sc->sc_kbd); #if defined(SUNKBD_EMULATE_ATKBD) kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_101, 0, 0, 0, 0); kbd_set_maps(&sc->sc_kbd, &key_map, &accent_map, fkey_tab, sizeof(fkey_tab) / sizeof(fkey_tab[0])); #else kbd_init_struct(&sc->sc_kbd, SUNKBD_DRIVER_NAME, KB_OTHER, 0, 0, 0, 0); kbd_set_maps(&sc->sc_kbd, &keymap_sun_us_unix_kbd, &accentmap_sun_us_unix_kbd, fkey_tab, sizeof(fkey_tab) / sizeof(fkey_tab[0])); #endif sc->sc_mode = K_XLATE; kbd_register(&sc->sc_kbd); sc->sc_sysdev = &uart_keyboard; found: /* Return number of found keyboards. */ return (1); }
/* * Reset and initialize the device. Note that unit 0 (UKBD_DEFAULT) is an * always-connected device once it has been initially detected. We do not * deregister it if the usb keyboard is unplugged to avoid losing the * connection to the console. This feature also handles the USB bus reset * which detaches and reattaches USB devices during boot. */ static int ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) { keyboard_t *kbd; ukbd_state_t *state; keymap_t *keymap; accentmap_t *accmap; fkeytab_t *fkeymap; int fkeymap_size; void **data = (void **)arg; struct usb_attach_arg *uaa = (struct usb_attach_arg *)data[0]; if (unit == UKBD_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 = NELEM(default_fkeytab); } else if (*kbdp == NULL) { *kbdp = kbd = kmalloc(sizeof(*kbd), M_DEVBUF, M_INTWAIT | M_ZERO); state = kmalloc(sizeof(*state), M_DEVBUF, M_INTWAIT); keymap = kmalloc(sizeof(key_map), M_DEVBUF, M_INTWAIT); accmap = kmalloc(sizeof(accent_map), M_DEVBUF, M_INTWAIT); fkeymap = kmalloc(sizeof(fkey_tab), M_DEVBUF, M_INTWAIT); fkeymap_size = NELEM(fkey_tab); if ((state == NULL) || (keymap == NULL) || (accmap == NULL) || (fkeymap == NULL)) { if (state != NULL) kfree(state, M_DEVBUF); if (keymap != NULL) kfree(keymap, M_DEVBUF); if (accmap != NULL) kfree(accmap, M_DEVBUF); if (fkeymap != NULL) kfree(fkeymap, M_DEVBUF); kfree(kbd, M_DEVBUF); return ENOMEM; } } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { return 0; } else { kbd = *kbdp; state = (ukbd_state_t *)kbd->kb_data; keymap = kbd->kb_keymap; accmap = kbd->kb_accentmap; fkeymap = kbd->kb_fkeytab; fkeymap_size = kbd->kb_fkeytab_size; } if (!KBD_IS_PROBED(kbd)) { kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, KB_PRI_USB, 0, 0); bzero(state, sizeof(*state)); 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(uaa, flags)) { return ENXIO; } else { KBD_FOUND_DEVICE(kbd); } ukbd_clear_state(kbd); /* * If reattatching to an already open keyboard (e.g. console), * try to restore the translation mode. Otherwise set the * translation mode to, well, translation mode so we don't * get garbage. */ state->ks_mode = K_XLATE; state->ks_iface = uaa->iface; state->ks_uaa = uaa; state->ks_ifstate = 0; callout_init_mp(&state->ks_timeout); /* * 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)) { if (KBD_HAS_DEVICE(kbd) && init_keyboard((ukbd_state_t *)kbd->kb_data, &kbd->kb_type, kbd->kb_flags)) { return ENXIO; } ukbd_ioctl(kbd, KDSETLED, (caddr_t)&(state->ks_state)); } if (!KBD_IS_CONFIGURED(kbd)) { if (kbd_register(kbd) < 0) { kbd->kb_flags = 0; /* XXX: Missing free()'s */ return ENXIO; } if (ukbd_enable_intr(kbd, TRUE, (usbd_intr_t *)data[1]) == 0) ukbd_timeout((void *)kbd); KBD_CONFIG_DONE(kbd); } return 0; }
/* reset and initialize the device */ static int pckbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) { keyboard_t *kbd; pckbd_state_t *state; keymap_t *keymap; accentmap_t *accmap; fkeytab_t *fkeymap; int fkeymap_size; int *data = (int *)arg; if (unit != PC98KBD_DEFAULT) /* shouldn't happen */ return ENXIO; *kbdp = kbd = &default_kbd; state = &default_kbd_state; if (!KBD_IS_PROBED(kbd)) { keymap = &default_keymap; accmap = &default_accentmap; fkeymap = default_fkeytab; fkeymap_size = sizeof(default_fkeytab)/sizeof(default_fkeytab[0]); state->kbdc = kbdc_open(data[0]); if (state->kbdc == NULL) return ENXIO; kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, data[0], IO_KBDSIZE); 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) return ENXIO; } else { KBD_FOUND_DEVICE(kbd); } pckbd_clear_state(kbd); state->ks_mode = K_XLATE; KBD_PROBE_DONE(kbd); } if (!KBD_IS_INITIALIZED(kbd) && !(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)) return ENXIO; pckbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); KBD_INIT_DONE(kbd); } if (!KBD_IS_CONFIGURED(kbd)) { if (kbd_register(kbd) < 0) return ENXIO; KBD_CONFIG_DONE(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 */ /* 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 = NELEM(default_fkeytab); } else if (*kbdp == NULL) { *kbdp = kbd = kmalloc(sizeof(*kbd), M_DEVBUF, M_WAITOK|M_ZERO); state = kmalloc(sizeof(*state), M_DEVBUF, M_WAITOK|M_ZERO); keymap = kmalloc(sizeof(key_map), M_DEVBUF, M_WAITOK); accmap = kmalloc(sizeof(accent_map), M_DEVBUF, M_WAITOK); fkeymap = kmalloc(sizeof(fkey_tab), M_DEVBUF, M_WAITOK); fkeymap_size = NELEM(fkey_tab); } 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; } if (!KBD_IS_PROBED(kbd)) { state->kbdc = atkbdc_open(data[0]); if (state->kbdc == NULL) { return ENXIO; } kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags, KB_PRI_ATKBD, 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) { return ENXIO; } } 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)) { return ENXIO; } 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_FOUND_DEVICE(kbd); KBD_INIT_DONE(kbd); } if (!KBD_IS_CONFIGURED(kbd)) { if (kbd_register(kbd) < 0) { return ENXIO; } KBD_CONFIG_DONE(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 *data = (int *)arg; /* 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]); } else if (*kbdp == NULL) { *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT); if (kbd == NULL) return ENOMEM; bzero(kbd, sizeof(*kbd)); state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT); 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]); if ((state == NULL) || (keymap == NULL) || (accmap == NULL) || (fkeymap == NULL)) { 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); free(kbd, M_DEVBUF); return ENOMEM; } bzero(state, sizeof(*state)); } 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; } if (!KBD_IS_PROBED(kbd)) { state->kbdc = kbdc_open(data[0]); if (state->kbdc == NULL) return ENXIO; kbd_init_struct(kbd, ATKBD_DRIVER_NAME, KB_OTHER, unit, flags, data[0], IO_KBDSIZE); 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) return ENXIO; } 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)) { if (KBD_HAS_DEVICE(kbd) && init_keyboard(state->kbdc, &kbd->kb_type, kbd->kb_config) && (kbd->kb_config & KB_CONF_FAIL_IF_NO_KBD)) return ENXIO; atkbd_ioctl(kbd, KDSETLED, (caddr_t)&state->ks_state); KBD_INIT_DONE(kbd); } if (!KBD_IS_CONFIGURED(kbd)) { if (kbd_register(kbd) < 0) return ENXIO; KBD_CONFIG_DONE(kbd); } return 0; }
/* reset and initialize the device */ static int ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) { keyboard_t *kbd; ukbd_state_t *state; keymap_t *keymap; accentmap_t *accmap; fkeytab_t *fkeymap; int fkeymap_size; void **data = (void **)arg; struct usb_attach_arg *uaa = (struct usb_attach_arg *)data[0]; /* XXX */ if (unit == UKBD_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]); } else if (*kbdp == NULL) { *kbdp = kbd = malloc(sizeof(*kbd), M_DEVBUF, M_NOWAIT); if (kbd == NULL) return ENOMEM; bzero(kbd, sizeof(*kbd)); state = malloc(sizeof(*state), M_DEVBUF, M_NOWAIT); 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]); if ((state == NULL) || (keymap == NULL) || (accmap == NULL) || (fkeymap == NULL)) { 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); free(kbd, M_DEVBUF); return ENOMEM; } } else if (KBD_IS_INITIALIZED(*kbdp) && KBD_IS_CONFIGURED(*kbdp)) { return 0; } else { kbd = *kbdp; state = (ukbd_state_t *)kbd->kb_data; keymap = kbd->kb_keymap; accmap = kbd->kb_accentmap; fkeymap = kbd->kb_fkeytab; fkeymap_size = kbd->kb_fkeytab_size; } if (!KBD_IS_PROBED(kbd)) { kbd_init_struct(kbd, DRIVER_NAME, KB_OTHER, unit, flags, 0, 0); bzero(state, sizeof(*state)); 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(uaa, flags)) return ENXIO; else KBD_FOUND_DEVICE(kbd); ukbd_clear_state(kbd); state->ks_mode = K_XLATE; state->ks_iface = uaa->iface; state->ks_uaa = uaa; state->ks_ifstate = 0; callout_handle_init(&state->ks_timeout_handle); /* * 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)) { if (KBD_HAS_DEVICE(kbd) && init_keyboard((ukbd_state_t *)kbd->kb_data, &kbd->kb_type, kbd->kb_flags)) return ENXIO; ukbd_ioctl(kbd, KDSETLED, (caddr_t)&(state->ks_state)); KBD_INIT_DONE(kbd); } if (!KBD_IS_CONFIGURED(kbd)) { if (kbd_register(kbd) < 0) return ENXIO; if (ukbd_enable_intr(kbd, TRUE, (usbd_intr_t *)data[1]) == 0) ukbd_timeout((void *)kbd); KBD_CONFIG_DONE(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; #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; }