Пример #1
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 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;
}
Пример #2
0
/* 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;
}
Пример #3
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;
}
Пример #4
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 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;
}
Пример #5
0
/* 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;
}
Пример #6
0
/* 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;
}
Пример #7
0
/* finish using this keyboard */
static int
pckbd_term(keyboard_t *kbd)
{
	kbd_unregister(kbd);
	return 0;
}
Пример #8
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;
}
Пример #9
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;
}