Пример #1
0
static int
write_kbd(KBDC kbdc, int command, int data)
{
    /* prevent the timeout routine from polling the keyboard */
    if (!kbdc_lock(kbdc, TRUE)) 
	return EBUSY;

    /* disable the keyboard and mouse interrupt */
    crit_enter();

#if 0
    /*
     * XXX NOTE: We can't just disable the KBD port any more, even
     * 	         temporarily, without blowing up some BIOS emulations
     *		 if not followed by a full reset.
     */
    c = get_controller_command_byte(kbdc);
    if ((c == -1) ||
	!set_controller_command_byte(kbdc,
		KBD_KBD_CONTROL_BITS,
		KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT)) {
	/* CONTROLLER ERROR */
        kbdc_lock(kbdc, FALSE);
	crit_exit();
	return EIO;
    }
    /* 
     * Now that the keyboard controller is told not to generate 
     * the keyboard and mouse interrupts, call `splx()' to allow 
     * the other tty interrupts. The clock interrupt may also occur, 
     * but the timeout routine (`scrn_timer()') will be blocked 
     * by the lock flag set via `kbdc_lock()'
     */
    crit_exit();
#endif

    if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK)
        send_kbd_command(kbdc, KBDC_ENABLE_KBD);

#if 0
    /* restore the interrupts */
    if (!set_controller_command_byte(kbdc, KBD_KBD_CONTROL_BITS, c)) {
	/* CONTROLLER ERROR */
    }
#else
    crit_exit();
#endif
    kbdc_lock(kbdc, FALSE);

    return 0;
}
Пример #2
0
static int
write_kbd(KBDC kbdc, int command, int data)
{
    int s;

    /* prevent the timeout routine from polling the keyboard */
    if (!kbdc_lock(kbdc, TRUE))
        return EBUSY;

    /* disable the keyboard and mouse interrupt */
    s = spltty();
#if 0
    c = get_controller_command_byte(kbdc);
    if ((c == -1)
            || !set_controller_command_byte(kbdc,
                                            kbdc_get_device_mask(kbdc),
                                            KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
                                            | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
        /* CONTROLLER ERROR */
        kbdc_lock(kbdc, FALSE);
        splx(s);
        return EIO;
    }
    /*
     * Now that the keyboard controller is told not to generate
     * the keyboard and mouse interrupts, call `splx()' to allow
     * the other tty interrupts. The clock interrupt may also occur,
     * but the timeout routine (`scrn_timer()') will be blocked
     * by the lock flag set via `kbdc_lock()'
     */
    splx(s);
#endif

    if (send_kbd_command_and_data(kbdc, command, data) != KBD_ACK)
        send_kbd_command(kbdc, KBDC_ENABLE_KBD);

#if 0
    /* restore the interrupts */
    if (!set_controller_command_byte(kbdc,
                                     kbdc_get_device_mask(kbdc),
                                     c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
        /* CONTROLLER ERROR */
    }
#else
    splx(s);
#endif
    kbdc_lock(kbdc, FALSE);

    return 0;
}
Пример #3
0
static int
atkbd_reset(KBDC kbdc, int flags, int c)
{
	/* reset keyboard hardware */
	if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) {
		/*
		 * KEYBOARD ERROR
		 * Keyboard reset may fail either because the keyboard
		 * doen't exist, or because the keyboard doesn't pass
		 * the self-test, or the keyboard controller on the
		 * motherboard and the keyboard somehow fail to shake hands.
		 * It is just possible, particularly in the last case,
		 * that the keyboard controller may be left in a hung state.
		 * test_controller() and test_kbd_port() appear to bring
		 * the keyboard controller back (I don't know why and how,
		 * though.)
		 */
		empty_both_buffers(kbdc, 10);
		test_controller(kbdc);
		test_kbd_port(kbdc);
		/*
		 * We could disable the keyboard port and interrupt... but, 
		 * the keyboard may still exist (see above). 
		 */
		set_controller_command_byte(kbdc,
		    ALLOW_DISABLE_KBD(kbdc) ? 0xff : KBD_KBD_CONTROL_BITS, c);
		if (bootverbose)
			printf("atkbd: failed to reset the keyboard.\n");
		return (EIO);
	}
	return (0);
}
Пример #4
0
static int
setup_kbd_port(KBDC kbdc, int port, int intr)
{
    if (!set_controller_command_byte(kbdc,
                                     KBD_KBD_CONTROL_BITS,
                                     ((port) ? KBD_ENABLE_KBD_PORT : KBD_DISABLE_KBD_PORT)
                                     | ((intr) ? KBD_ENABLE_KBD_INT : KBD_DISABLE_KBD_INT)))
        return 1;
    return 0;
}
Пример #5
0
static int
probe_keyboard(KBDC kbdc, int flags)
{
	/*
	 * Don't try to print anything in this function.  The low-level 
	 * console may not have been initialized yet...
	 */
	int err;
	int c;
	int m;

	if (!kbdc_lock(kbdc, TRUE)) {
		/* driver error? */
		return ENXIO;
	}

	/* flush any noise in the buffer */
	empty_both_buffers(kbdc, 10);

	/* save the current keyboard controller command byte */
	m = kbdc_get_device_mask(kbdc) & ~KBD_KBD_CONTROL_BITS;
	c = get_controller_command_byte(kbdc);
	if (c == -1) {
		/* CONTROLLER ERROR */
		kbdc_set_device_mask(kbdc, m);
		kbdc_lock(kbdc, FALSE);
		return ENXIO;
	}

	/* 
	 * The keyboard may have been screwed up by the boot block.
	 * We may just be able to recover from error by testing the controller
	 * and the keyboard port. The controller command byte needs to be
	 * saved before this recovery operation, as some controllers seem 
	 * to set the command byte to particular values.
	 */
	test_controller(kbdc);
	test_kbd_port(kbdc);

	err = get_kbd_echo(kbdc);
	if (err == 0) {
		kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS);
	} else {
		if (c != -1)
			/* try to restore the command byte as before */
			set_controller_command_byte(kbdc, 0xff, c);
		kbdc_set_device_mask(kbdc, m);
	}

	kbdc_lock(kbdc, FALSE);
	return err;
}
Пример #6
0
static void
atkbd_shutdown_final(void *v)
{
#ifdef __sparc64__
    keyboard_t *kbd = v;
    KBDC kbdc = ((atkbd_state_t *)kbd->kb_data)->kbdc;

    /*
     * Turn off the translation in preparation for handing the keyboard
     * over to the OFW as the OBP driver doesn't use translation and
     * also doesn't disable it itself resulting in a broken keymap at
     * the boot prompt. Also disable the aux port and the interrupts as
     * the OBP driver doesn't use them, i.e. polls the keyboard. Not
     * disabling the interrupts doesn't cause real problems but the
     * responsiveness is a bit better when they are turned off.
     */
    send_kbd_command(kbdc, KBDC_DISABLE_KBD);
    set_controller_command_byte(kbdc,
                                KBD_AUX_CONTROL_BITS | KBD_KBD_CONTROL_BITS | KBD_TRANSLATION,
                                KBD_DISABLE_AUX_PORT | KBD_DISABLE_KBD_INT | KBD_ENABLE_KBD_PORT);
    send_kbd_command(kbdc, KBDC_ENABLE_KBD);
#endif
}
Пример #7
0
static int
init_keyboard(KBDC kbdc, int *type, int flags)
{
    int codeset;
    int id;
    int c;

    if (!kbdc_lock(kbdc, TRUE)) {
        /* driver error? */
        return EIO;
    }

    /* temporarily block data transmission from the keyboard */
    write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT);

    /* save the current controller command byte */
    empty_both_buffers(kbdc, 200);
    c = get_controller_command_byte(kbdc);
    if (c == -1) {
        /* CONTROLLER ERROR */
        kbdc_lock(kbdc, FALSE);
        printf("atkbd: unable to get the current command byte value.\n");
        return EIO;
    }
    if (bootverbose)
        printf("atkbd: the current kbd controller command byte %04x\n",
               c);
#if 0
    /* override the keyboard lock switch */
    c |= KBD_OVERRIDE_KBD_LOCK;
#endif

    /* enable the keyboard port, but disable the keyboard intr. */
    if (setup_kbd_port(kbdc, TRUE, FALSE)) {
        /* CONTROLLER ERROR: there is very little we can do... */
        printf("atkbd: unable to set the command byte.\n");
        kbdc_lock(kbdc, FALSE);
        return EIO;
    }

    /*
     * Check if we have an XT keyboard before we attempt to reset it.
     * The procedure assumes that the keyboard and the controller have
     * been set up properly by BIOS and have not been messed up
     * during the boot process.
     */
    codeset = -1;
    if (flags & KB_CONF_ALT_SCANCODESET)
        /* the user says there is a XT keyboard */
        codeset = 1;
#ifdef KBD_DETECT_XT_KEYBOARD
    else if ((c & KBD_TRANSLATION) == 0) {
        /* SET_SCANCODE_SET is not always supported; ignore error */
        if (send_kbd_command_and_data(kbdc, KBDC_SET_SCANCODE_SET, 0)
                == KBD_ACK)
            codeset = read_kbd_data(kbdc);
    }
    if (bootverbose)
        printf("atkbd: scancode set %d\n", codeset);
#endif /* KBD_DETECT_XT_KEYBOARD */

    *type = KB_OTHER;
    id = get_kbd_id(kbdc);
    switch(id) {
    case 0x41ab:	/* 101/102/... Enhanced */
    case 0x83ab:	/* ditto */
    case 0x54ab:	/* SpaceSaver */
    case 0x84ab:	/* ditto */
#if 0
    case 0x90ab:	/* 'G' */
    case 0x91ab:	/* 'P' */
    case 0x92ab:	/* 'A' */
#endif
        *type = KB_101;
        break;
    case -1:	/* AT 84 keyboard doesn't return ID */
        *type = KB_84;
        break;
    default:
        break;
    }
    if (bootverbose)
        printf("atkbd: keyboard ID 0x%x (%d)\n", id, *type);

    /* reset keyboard hardware */
    if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) {
        /*
         * KEYBOARD ERROR
         * Keyboard reset may fail either because the keyboard
         * doen't exist, or because the keyboard doesn't pass
         * the self-test, or the keyboard controller on the
         * motherboard and the keyboard somehow fail to shake hands.
         * It is just possible, particularly in the last case,
         * that the keyboard controller may be left in a hung state.
         * test_controller() and test_kbd_port() appear to bring
         * the keyboard controller back (I don't know why and how,
         * though.)
         */
        empty_both_buffers(kbdc, 10);
        test_controller(kbdc);
        test_kbd_port(kbdc);
        /*
         * We could disable the keyboard port and interrupt... but,
         * the keyboard may still exist (see above).
         */
        set_controller_command_byte(kbdc, 0xff, c);
        kbdc_lock(kbdc, FALSE);
        if (bootverbose)
            printf("atkbd: failed to reset the keyboard.\n");
        return EIO;
    }

    /*
     * Allow us to set the XT_KEYBD flag so that keyboards
     * such as those on the IBM ThinkPad laptop computers can be used
     * with the standard console driver.
     */
    if (codeset == 1) {
        if (send_kbd_command_and_data(kbdc,
                                      KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) {
            /* XT kbd doesn't need scan code translation */
            c &= ~KBD_TRANSLATION;
        } else {
            /*
             * KEYBOARD ERROR
             * The XT kbd isn't usable unless the proper scan
             * code set is selected.
             */
            set_controller_command_byte(kbdc, 0xff, c);
            kbdc_lock(kbdc, FALSE);
            printf("atkbd: unable to set the XT keyboard mode.\n");
            return EIO;
        }
    }

#if defined(__sparc64__)
    if (send_kbd_command_and_data(
                kbdc, KBDC_SET_SCANCODE_SET, 2) != KBD_ACK) {
        printf("atkbd: can't set translation.\n");
    }
    c |= KBD_TRANSLATION;
#endif

    /* enable the keyboard port and intr. */
    if (!set_controller_command_byte(kbdc,
                                     KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
                                     (c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK))
                                     | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) {
        /*
         * CONTROLLER ERROR
         * This is serious; we are left with the disabled
         * keyboard intr.
         */
        set_controller_command_byte(kbdc, 0xff, c);
        kbdc_lock(kbdc, FALSE);
        printf("atkbd: unable to enable the keyboard port and intr.\n");
        return EIO;
    }

    kbdc_lock(kbdc, FALSE);
    return 0;
}
Пример #8
0
static int
probe_keyboard(KBDC kbdc, int flags)
{
    /*
     * Don't try to print anything in this function.  The low-level
     * console may not have been initialized yet...
     */
    int err;
    int c;
    int m;

    if (!kbdc_lock(kbdc, TRUE)) {
        /* driver error? */
        return ENXIO;
    }

    /* temporarily block data transmission from the keyboard */
    write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT);

    /* flush any noise in the buffer */
    empty_both_buffers(kbdc, 100);

    /* save the current keyboard controller command byte */
    m = kbdc_get_device_mask(kbdc) & ~KBD_KBD_CONTROL_BITS;
    c = get_controller_command_byte(kbdc);
    if (c == -1) {
        /* CONTROLLER ERROR */
        kbdc_set_device_mask(kbdc, m);
        kbdc_lock(kbdc, FALSE);
        return ENXIO;
    }

    /*
     * The keyboard may have been screwed up by the boot block.
     * We may just be able to recover from error by testing the controller
     * and the keyboard port. The controller command byte needs to be
     * saved before this recovery operation, as some controllers seem
     * to set the command byte to particular values.
     */
    test_controller(kbdc);
    if (!(flags & KB_CONF_NO_PROBE_TEST))
        test_kbd_port(kbdc);

    err = get_kbd_echo(kbdc);

    /*
     * Even if the keyboard doesn't seem to be present (err != 0),
     * we shall enable the keyboard port and interrupt so that
     * the driver will be operable when the keyboard is attached
     * to the system later.  It is NOT recommended to hot-plug
     * the AT keyboard, but many people do so...
     */
    kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS);
    setup_kbd_port(kbdc, TRUE, TRUE);
#if 0
    if (err == 0) {
        kbdc_set_device_mask(kbdc, m | KBD_KBD_CONTROL_BITS);
    } else {
        /* try to restore the command byte as before */
        set_controller_command_byte(kbdc, 0xff, c);
        kbdc_set_device_mask(kbdc, m);
    }
#endif

    kbdc_lock(kbdc, FALSE);
    return err;
}
Пример #9
0
static int
init_keyboard(KBDC kbdc, int *type, int flags)
{
	int codeset;
	int id;
	int c;
	int mux_version;
	int mux_mask;
	int mux_val;

	if (!kbdc_lock(kbdc, TRUE)) {
		/* driver error? */
		return EIO;
	}

	/*
	 * XXX block data transmission from the keyboard.  This can cause
	 * the keyboard to stop sending keystrokes even when re-enabled
	 * under certain circumstances if not followed by a full reset.
	 */
	write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT);

#if 0
	if (atkbd_setmuxmode(kbdc, 1, &mux_version)) {
		kprintf("atkbd: no mux\n");
		mux_version = -1;
	} else {
		kprintf("atkbd: mux present version %d\n", mux_version);
	}
#else
	mux_version = -1;
#endif

	/* save the current controller command byte */
	empty_both_buffers(kbdc, 200);
	c = get_controller_command_byte(kbdc);
	if (c == -1) {
		/* CONTROLLER ERROR */
		kbdc_lock(kbdc, FALSE);
		kprintf("atkbd: unable to get the current command byte value.\n");
		return EIO;
	}
	if (bootverbose)
		kprintf("atkbd: the current kbd controller command byte %04x\n",
		       c);
#if 0
	/* override the keyboard lock switch */
	c |= KBD_OVERRIDE_KBD_LOCK;
#endif

	/* enable the keyboard port, but disable the keyboard intr. */
	if (setup_kbd_port(kbdc, TRUE, FALSE)) {
		/* CONTROLLER ERROR: there is very little we can do... */
		kprintf("atkbd: unable to set the command byte.\n");
		kbdc_lock(kbdc, FALSE);
		return EIO;
	}

	/* default codeset */
	codeset = -1;

	/* reset keyboard hardware */
	if (!(flags & KB_CONF_NO_RESET) && !reset_kbd(kbdc)) {
		/*
		 * KEYBOARD ERROR
		 * Keyboard reset may fail either because the keyboard
		 * doen't exist, or because the keyboard doesn't pass
		 * the self-test, or the keyboard controller on the
		 * motherboard and the keyboard somehow fail to shake hands.
		 * It is just possible, particularly in the last case,
		 * that the keyoard controller may be left in a hung state.
		 * test_controller() and test_kbd_port() appear to bring
		 * the keyboard controller back (I don't know why and how,
		 * though.)
		 */
		empty_both_buffers(kbdc, 10);
		test_controller(kbdc);
		test_kbd_port(kbdc);
		/*
		 * We could disable the keyboard port and interrupt... but,
		 * the keyboard may still exist (see above).
		 */
		set_controller_command_byte(kbdc, KBD_KBD_CONTROL_BITS, c);
		kbdc_lock(kbdc, FALSE);
		if (bootverbose)
			kprintf("atkbd: failed to reset the keyboard.\n");
		return EIO;
	}

	/* 
	 * Check if we have an XT keyboard before we attempt to reset it. 
	 * The procedure assumes that the keyboard and the controller have 
	 * been set up properly by BIOS and have not been messed up 
	 * during the boot process.
	 */
	codeset = -1;
	if (flags & KB_CONF_ALT_SCANCODESET)
		/* the user says there is a XT keyboard */
		codeset = 1;
#ifdef KBD_DETECT_XT_KEYBOARD
	else if ((c & KBD_TRANSLATION) == 0) {
		/* SET_SCANCODE_SET is not always supported; ignore error */
		if (send_kbd_command_and_data(kbdc, KBDC_SET_SCANCODE_SET, 0)
			== KBD_ACK) 
			codeset = read_kbd_data(kbdc);
	}
#endif /* KBD_DETECT_XT_KEYBOARD */
	if (bootverbose)
		kprintf("atkbd: scancode set %d\n", codeset);
 
	/*
	 * Get the keyboard id.
	 */
	*type = KB_OTHER;
	id = get_kbd_id(kbdc, ATKBD_CMD_GETID);
	switch(id) {
	case 0x41ab:	/* 101/102/... Enhanced */
	case 0x83ab:	/* ditto */
	case 0x54ab:	/* SpaceSaver */
	case 0x84ab:	/* ditto */
#if 0
	case 0x90ab:	/* 'G' */
	case 0x91ab:	/* 'P' */
	case 0x92ab:	/* 'A' */
#endif
		*type = KB_101;
		break;
	case -1:	/* AT 84 keyboard doesn't return ID */
		*type = KB_84;
		break;
	default:
		break;
	}
	if (bootverbose)
		kprintf("atkbd: keyboard ID 0x%x (%d)\n", id, *type);

	/*
	 * Allow us to set the XT_KEYBD flag in UserConfig so that keyboards
	 * such as those on the IBM ThinkPad laptop computers can be used
	 * with the standard console driver.
	 */
	if (codeset == 1) {
		if (send_kbd_command_and_data(kbdc,
			KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) {
			/* XT kbd doesn't need scan code translation */
			c &= ~KBD_TRANSLATION;
		} else {
			/*
			 * KEYBOARD ERROR 
			 * The XT kbd isn't usable unless the proper scan
			 * code set is selected. 
			 */
			set_controller_command_byte(kbdc,
						    KBD_KBD_CONTROL_BITS, c);
			kbdc_lock(kbdc, FALSE);
			kprintf("atkbd: unable to set the XT keyboard mode.\n");
			return EIO;
		}
	}

#if 0
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_EX_ENABLE, 0x71) != KBD_ACK)
		kprintf("atkbd: can't CMD_EX_ENABLE\n");

	if (send_kbd_command(kbdc, ATKBD_CMD_SETALL_MB) != KBD_ACK)
		kprintf("atkbd: can't SETALL_MB\n");
	if (send_kbd_command(kbdc, ATKBD_CMD_SETALL_MBR) != KBD_ACK)
		kprintf("atkbd: can't SETALL_MBR\n");
#endif
#if 0
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_SSCANSET, 2) != KBD_ACK)
		kprintf("atkbd: can't SSCANSET\n");
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_GSCANSET, 0) != KBD_ACK)
		kprintf("atkbd: can't SSCANSET\n");
	else
		kprintf("atkbd: scanset %d\n", read_kbd_data(kbdc));
#endif
#if 0
	kprintf("atkbd: id %04x\n", get_kbd_id(kbdc, ATKBD_CMD_OK_GETID));
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_SETLEDS, 0) != KBD_ACK)
		kprintf("atkbd: setleds failed\n");
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_SETREP, 255) != KBD_ACK)
		kprintf("atkbd: setrep failed\n");
	if (send_kbd_command(kbdc, ATKBD_CMD_RESEND) != KBD_ACK)
		kprintf("atkbd: resend failed\n");
#endif
	/*
	 * Some keyboards require a SETLEDS command to be sent after
	 * the reset command before they will send keystrokes to us
	 * (Acer C720).
	 */
	if (send_kbd_command_and_data(kbdc, ATKBD_CMD_SETLEDS, 0) != KBD_ACK)
		kprintf("atkbd: setleds failed\n");
	send_kbd_command(kbdc, ATKBD_CMD_ENABLE);

#if 0
	/* DEBUGGING */
	{
		int retry;
		int c;
		kprintf("atkbd: waiting for keypress");
		for (retry = 0; retry < 10; ++retry) {
			c = read_kbd_data_no_wait(kbdc);
			kprintf(" %d", c);
			tsleep(&c, 0, "wait", hz);
		}
		kprintf("\n");
	}
#endif

	if (mux_version == -1) {
		mux_mask = 0;
		mux_val = 0;
	} else {
		mux_mask = KBD_AUX_CONTROL_BITS;
		mux_val = 0;
		kprintf("atkbd: setaux for multiplexer\n");
	}

	/* enable the keyboard port and intr. */
	if (!set_controller_command_byte(kbdc, 
		KBD_KBD_CONTROL_BITS | KBD_TRANSLATION |
		KBD_OVERRIDE_KBD_LOCK | mux_mask,
		(c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK))
		    | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT | mux_val)) {
		/*
		 * CONTROLLER ERROR 
		 * This is serious; we are left with the disabled
		 * keyboard intr. 
		 */
		set_controller_command_byte(kbdc,
				KBD_KBD_CONTROL_BITS | KBD_TRANSLATION |
				KBD_OVERRIDE_KBD_LOCK | mux_mask,
				c);
		kbdc_lock(kbdc, FALSE);
		kprintf("atkbd: unable to enable the keyboard port and intr.\n");
		return EIO;
	}

	kbdc_lock(kbdc, FALSE);
	return 0;
}
Пример #10
0
static int
probe_keyboard(KBDC kbdc, int flags)
{
	/*
	 * Don't try to print anything in this function.  The low-level 
	 * console may not have been initialized yet...
	 */
	int err;
	int c;

	if (!kbdc_lock(kbdc, TRUE)) {
		/* driver error? */
		return ENXIO;
	}

	/*
	 * XXX block data transmission from the keyboard.  This can cause
	 * the keyboard to stop sending keystrokes even when re-enabled
	 * under certain circumstances if not followed by a full reset.
	 */
	write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT);

	/* flush any noise in the buffer */
	empty_both_buffers(kbdc, 100);

	/* save the current keyboard controller command byte */
	c = get_controller_command_byte(kbdc);
	if (c == -1) {
		/* CONTROLLER ERROR */
		kbdc_lock(kbdc, FALSE);
		return ENXIO;
	}

	/* 
	 * The keyboard may have been screwed up by the boot block.
	 * We may just be able to recover from error by testing the controller
	 * and the keyboard port. The controller command byte needs to be
	 * saved before this recovery operation, as some controllers seem 
	 * to set the command byte to particular values.
	 */
	test_controller(kbdc);
	test_kbd_port(kbdc);

	err = get_kbd_echo(kbdc);

	/*
	 * Even if the keyboard doesn't seem to be present (err != 0),
	 * we shall enable the keyboard port and interrupt so that
	 * the driver will be operable when the keyboard is attached
	 * to the system later.  It is NOT recommended to hot-plug
	 * the AT keyboard, but many people do so...
	 */
	setup_kbd_port(kbdc, TRUE, TRUE);
#if 0
	if (err) {
		/* try to restore the command byte as before */
		set_controller_command_byte(kbdc, KBD_KBD_CONTROL_BITS, c);
	}
#endif

	kbdc_lock(kbdc, FALSE);
	return err;
}
Пример #11
0
static int
init_keyboard(KBDC kbdc, int *type, int flags)
{
	int codeset;
	int id;
	int c;

	if (!kbdc_lock(kbdc, TRUE)) {
		/* driver error? */
		return EIO;
	}

	/* temporarily block data transmission from the keyboard */
	write_controller_command(kbdc, KBDC_DISABLE_KBD_PORT);

	/* save the current controller command byte */
	empty_both_buffers(kbdc, 200);
	c = get_controller_command_byte(kbdc);
	if (c == -1) {
		/* CONTROLLER ERROR */
		kbdc_lock(kbdc, FALSE);
		printf("atkbd: unable to get the current command byte value.\n");
		return EIO;
	}
	if (bootverbose)
		printf("atkbd: the current kbd controller command byte %04x\n",
		   c);
#if 0
	/* override the keyboard lock switch */
	c |= KBD_OVERRIDE_KBD_LOCK;
#endif

	/* enable the keyboard port, but disable the keyboard intr. */
	if (setup_kbd_port(kbdc, TRUE, FALSE)) {
		/* CONTROLLER ERROR: there is very little we can do... */
		printf("atkbd: unable to set the command byte.\n");
		kbdc_lock(kbdc, FALSE);
		return EIO;
	}

	if (HAS_QUIRK(kbdc, KBDC_QUIRK_RESET_AFTER_PROBE) &&
	    atkbd_reset(kbdc, flags, c)) {
		kbdc_lock(kbdc, FALSE);
		return EIO;
	}

	/* 
	 * Check if we have an XT keyboard before we attempt to reset it. 
	 * The procedure assumes that the keyboard and the controller have 
	 * been set up properly by BIOS and have not been messed up 
	 * during the boot process.
	 */
	codeset = -1;
	if (flags & KB_CONF_ALT_SCANCODESET)
		/* the user says there is a XT keyboard */
		codeset = 1;
#ifdef KBD_DETECT_XT_KEYBOARD
	else if ((c & KBD_TRANSLATION) == 0) {
		/* SET_SCANCODE_SET is not always supported; ignore error */
		if (send_kbd_command_and_data(kbdc, KBDC_SET_SCANCODE_SET, 0)
			== KBD_ACK) 
			codeset = read_kbd_data(kbdc);
	}
	if (bootverbose)
		printf("atkbd: scancode set %d\n", codeset);
#endif /* KBD_DETECT_XT_KEYBOARD */
 
	*type = KB_OTHER;
	id = get_kbd_id(kbdc);
	switch(id) {
	case 0x41ab:	/* 101/102/... Enhanced */
	case 0x83ab:	/* ditto */
	case 0x54ab:	/* SpaceSaver */
	case 0x84ab:	/* ditto */
#if 0
	case 0x90ab:	/* 'G' */
	case 0x91ab:	/* 'P' */
	case 0x92ab:	/* 'A' */
#endif
		*type = KB_101;
		break;
	case -1:	/* AT 84 keyboard doesn't return ID */
		*type = KB_84;
		break;
	default:
		break;
	}
	if (bootverbose)
		printf("atkbd: keyboard ID 0x%x (%d)\n", id, *type);

	if (!HAS_QUIRK(kbdc, KBDC_QUIRK_RESET_AFTER_PROBE) &&
	    atkbd_reset(kbdc, flags, c)) {
		kbdc_lock(kbdc, FALSE);
		return EIO;
	}

	/*
	 * Allow us to set the XT_KEYBD flag so that keyboards
	 * such as those on the IBM ThinkPad laptop computers can be used
	 * with the standard console driver.
	 */
	if (codeset == 1) {
		if (send_kbd_command_and_data(kbdc,
			KBDC_SET_SCANCODE_SET, codeset) == KBD_ACK) {
			/* XT kbd doesn't need scan code translation */
			c &= ~KBD_TRANSLATION;
		} else {
			/*
			 * KEYBOARD ERROR 
			 * The XT kbd isn't usable unless the proper scan
			 * code set is selected. 
			 */
			set_controller_command_byte(kbdc, ALLOW_DISABLE_KBD(kbdc)
			    ? 0xff : KBD_KBD_CONTROL_BITS, c);
			kbdc_lock(kbdc, FALSE);
			printf("atkbd: unable to set the XT keyboard mode.\n");
			return EIO;
		}
	}

#if defined(__sparc64__)
	if (send_kbd_command_and_data(
		kbdc, KBDC_SET_SCANCODE_SET, 2) != KBD_ACK) {
		printf("atkbd: can't set translation.\n");
	}
	c |= KBD_TRANSLATION;
#endif

	/*
	 * Some keyboards require a SETLEDS command to be sent after
	 * the reset command before they will send keystrokes to us
	 */
	if (HAS_QUIRK(kbdc, KBDC_QUIRK_SETLEDS_ON_INIT) &&
	    send_kbd_command_and_data(kbdc, KBDC_SET_LEDS, 0) != KBD_ACK) {
		printf("atkbd: setleds failed\n");
	}
	if (!ALLOW_DISABLE_KBD(kbdc))
	    send_kbd_command(kbdc, KBDC_ENABLE_KBD);

	/* enable the keyboard port and intr. */
	if (!set_controller_command_byte(kbdc, 
		KBD_KBD_CONTROL_BITS | KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK,
		(c & (KBD_TRANSLATION | KBD_OVERRIDE_KBD_LOCK))
		    | KBD_ENABLE_KBD_PORT | KBD_ENABLE_KBD_INT)) {
		/*
		 * CONTROLLER ERROR 
		 * This is serious; we are left with the disabled
		 * keyboard intr. 
		 */
		set_controller_command_byte(kbdc, ALLOW_DISABLE_KBD(kbdc)
		    ? 0xff : (KBD_KBD_CONTROL_BITS | KBD_TRANSLATION |
			KBD_OVERRIDE_KBD_LOCK), c);
		kbdc_lock(kbdc, FALSE);
		printf("atkbd: unable to enable the keyboard port and intr.\n");
		return EIO;
	}

	kbdc_lock(kbdc, FALSE);
	return 0;
}