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; }
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; }
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; }
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; }
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; }