ps2kbd.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. /*
  2. * (C) Copyright 2002
  3. * John W. Linville, linville@tuxdriver.com
  4. *
  5. * Modified from code for support of MIP405 and PIP405 boards. Previous
  6. * copyright follows.
  7. *
  8. * (C) Copyright 2001
  9. * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
  10. *
  11. * See file CREDITS for list of people who contributed to this
  12. * project.
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License as
  16. * published by the Free Software Foundation; either version 2 of
  17. * the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  27. * MA 02111-1307 USA
  28. *
  29. *
  30. * Source partly derived from:
  31. * linux/drivers/char/pc_keyb.c
  32. *
  33. *
  34. */
  35. #include <common.h>
  36. #include <asm/processor.h>
  37. #include <devices.h>
  38. #include "ps2kbd.h"
  39. unsigned char kbd_read_status(void);
  40. unsigned char kbd_read_input(void);
  41. void kbd_send_data(unsigned char data);
  42. void i8259_mask_irq(unsigned int irq);
  43. void i8259_unmask_irq(unsigned int irq);
  44. /* used only by send_data - set by keyboard_interrupt */
  45. #undef KBG_DEBUG
  46. #ifdef KBG_DEBUG
  47. #define PRINTF(fmt,args...) printf (fmt ,##args)
  48. #else
  49. #define PRINTF(fmt,args...)
  50. #endif
  51. #define KBD_STAT_KOBF 0x01
  52. #define KBD_STAT_IBF 0x02
  53. #define KBD_STAT_SYS 0x04
  54. #define KBD_STAT_CD 0x08
  55. #define KBD_STAT_LOCK 0x10
  56. #define KBD_STAT_MOBF 0x20
  57. #define KBD_STAT_TI_OUT 0x40
  58. #define KBD_STAT_PARERR 0x80
  59. #define KBD_INIT_TIMEOUT 2000 /* Timeout in ms for initializing the keyboard */
  60. #define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */
  61. #define KBD_TIMEOUT 2000 /* Timeout in ms for keyboard command acknowledge */
  62. /*
  63. * Keyboard Controller Commands
  64. */
  65. #define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
  66. #define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */
  67. #define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */
  68. #define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */
  69. #define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */
  70. #define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */
  71. #define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */
  72. #define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
  73. #define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
  74. #define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
  75. #define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if
  76. initiated by the auxiliary device */
  77. #define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
  78. /*
  79. * Keyboard Commands
  80. */
  81. #define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
  82. #define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
  83. #define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
  84. #define KBD_CMD_DISABLE 0xF5 /* Disable scanning */
  85. #define KBD_CMD_RESET 0xFF /* Reset */
  86. /*
  87. * Keyboard Replies
  88. */
  89. #define KBD_REPLY_POR 0xAA /* Power on reset */
  90. #define KBD_REPLY_ACK 0xFA /* Command ACK */
  91. #define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
  92. /*
  93. * Status Register Bits
  94. */
  95. #define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
  96. #define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
  97. #define KBD_STAT_SELFTEST 0x04 /* Self test successful */
  98. #define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
  99. #define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
  100. #define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
  101. #define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
  102. #define KBD_STAT_PERR 0x80 /* Parity error */
  103. #define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
  104. /*
  105. * Controller Mode Register Bits
  106. */
  107. #define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */
  108. #define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */
  109. #define KBD_MODE_SYS 0x04 /* The system flag (?) */
  110. #define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */
  111. #define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */
  112. #define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */
  113. #define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
  114. #define KBD_MODE_RFU 0x80
  115. #define KDB_DATA_PORT 0x60
  116. #define KDB_COMMAND_PORT 0x64
  117. #define LED_SCR 0x01 /* scroll lock led */
  118. #define LED_CAP 0x04 /* caps lock led */
  119. #define LED_NUM 0x02 /* num lock led */
  120. #define KBD_BUFFER_LEN 0x20 /* size of the keyboardbuffer */
  121. static volatile char kbd_buffer[KBD_BUFFER_LEN];
  122. static volatile int in_pointer = 0;
  123. static volatile int out_pointer = 0;
  124. static unsigned char num_lock = 0;
  125. static unsigned char caps_lock = 0;
  126. static unsigned char scroll_lock = 0;
  127. static unsigned char shift = 0;
  128. static unsigned char ctrl = 0;
  129. static unsigned char alt = 0;
  130. static unsigned char e0 = 0;
  131. static unsigned char leds = 0;
  132. #define DEVNAME "ps2kbd"
  133. /* Simple translation table for the keys */
  134. static unsigned char kbd_plain_xlate[] = {
  135. 0xff,0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t', /* 0x00 - 0x0f */
  136. 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',0xff, 'a', 's', /* 0x10 - 0x1f */
  137. 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',0xff,'\\', 'z', 'x', 'c', 'v', /* 0x20 - 0x2f */
  138. 'b', 'n', 'm', ',', '.', '/',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */
  139. 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
  140. '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */
  141. '\r',0xff,0xff
  142. };
  143. static unsigned char kbd_shift_xlate[] = {
  144. 0xff,0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t', /* 0x00 - 0x0f */
  145. 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',0xff, 'A', 'S', /* 0x10 - 0x1f */
  146. 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',0xff, '|', 'Z', 'X', 'C', 'V', /* 0x20 - 0x2f */
  147. 'B', 'N', 'M', '<', '>', '?',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */
  148. 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
  149. '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */
  150. '\r',0xff,0xff
  151. };
  152. static unsigned char kbd_ctrl_xlate[] = {
  153. 0xff,0x1b, '1',0x00, '3', '4', '5',0x1E, '7', '8', '9', '0',0x1F, '=','\b','\t', /* 0x00 - 0x0f */
  154. 0x11,0x17,0x05,0x12,0x14,0x18,0x15,0x09,0x0f,0x10,0x1b,0x1d,'\n',0xff,0x01,0x13, /* 0x10 - 0x1f */
  155. 0x04,0x06,0x08,0x09,0x0a,0x0b,0x0c, ';','\'', '~',0x00,0x1c,0x1a,0x18,0x03,0x16, /* 0x20 - 0x2f */
  156. 0x02,0x0e,0x0d, '<', '>', '?',0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x30 - 0x3f */
  157. 0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1', /* 0x40 - 0x4f */
  158. '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x50 - 0x5F */
  159. '\r',0xff,0xff
  160. };
  161. /******************************************************************
  162. * Init
  163. ******************************************************************/
  164. int isa_kbd_init (void)
  165. {
  166. char *result;
  167. result = kbd_initialize ();
  168. if (result != NULL) {
  169. result = kbd_initialize ();
  170. }
  171. if (result == NULL) {
  172. printf ("AT Keyboard initialized\n");
  173. irq_install_handler (KBD_INTERRUPT,
  174. (interrupt_handler_t *) kbd_interrupt,
  175. NULL);
  176. return (1);
  177. } else {
  178. printf ("%s\n", result);
  179. return (-1);
  180. }
  181. }
  182. #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE
  183. extern int overwrite_console (void);
  184. #else
  185. int overwrite_console (void)
  186. {
  187. return (0);
  188. }
  189. #endif
  190. int drv_isa_kbd_init (void)
  191. {
  192. int error;
  193. device_t kbddev ;
  194. char *stdinname = getenv ("stdin");
  195. if(isa_kbd_init() == -1)
  196. return -1;
  197. memset (&kbddev, 0, sizeof(kbddev));
  198. strcpy(kbddev.name, DEVNAME);
  199. kbddev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
  200. kbddev.putc = NULL ;
  201. kbddev.puts = NULL ;
  202. kbddev.getc = kbd_getc ;
  203. kbddev.tstc = kbd_testc ;
  204. error = device_register (&kbddev);
  205. if(error==0) {
  206. /* check if this is the standard input device */
  207. if(strcmp(stdinname,DEVNAME)==0) {
  208. /* reassign the console */
  209. if(overwrite_console()) {
  210. return 1;
  211. }
  212. error=console_assign(stdin,DEVNAME);
  213. if(error==0)
  214. return 1;
  215. else
  216. return error;
  217. }
  218. return 1;
  219. }
  220. return error;
  221. }
  222. /******************************************************************
  223. * Queue handling
  224. ******************************************************************/
  225. /* puts character in the queue and sets up the in and out pointer */
  226. void kbd_put_queue(char data)
  227. {
  228. if((in_pointer+1)==KBD_BUFFER_LEN) {
  229. if(out_pointer==0) {
  230. return; /* buffer full */
  231. } else{
  232. in_pointer=0;
  233. }
  234. } else {
  235. if((in_pointer+1)==out_pointer)
  236. return; /* buffer full */
  237. in_pointer++;
  238. }
  239. kbd_buffer[in_pointer]=data;
  240. return;
  241. }
  242. /* test if a character is in the queue */
  243. int kbd_testc(void)
  244. {
  245. if(in_pointer==out_pointer)
  246. return(0); /* no data */
  247. else
  248. return(1);
  249. }
  250. /* gets the character from the queue */
  251. int kbd_getc(void)
  252. {
  253. char c;
  254. while(in_pointer==out_pointer);
  255. if((out_pointer+1)==KBD_BUFFER_LEN)
  256. out_pointer=0;
  257. else
  258. out_pointer++;
  259. c=kbd_buffer[out_pointer];
  260. return (int)c;
  261. }
  262. /* set LEDs */
  263. void kbd_set_leds(void)
  264. {
  265. if(caps_lock==0)
  266. leds&=~LED_CAP; /* switch caps_lock off */
  267. else
  268. leds|=LED_CAP; /* switch on LED */
  269. if(num_lock==0)
  270. leds&=~LED_NUM; /* switch LED off */
  271. else
  272. leds|=LED_NUM; /* switch on LED */
  273. if(scroll_lock==0)
  274. leds&=~LED_SCR; /* switch LED off */
  275. else
  276. leds|=LED_SCR; /* switch on LED */
  277. kbd_send_data(KBD_CMD_SET_LEDS);
  278. kbd_send_data(leds);
  279. }
  280. void handle_keyboard_event (unsigned char scancode)
  281. {
  282. unsigned char keycode;
  283. /* Convert scancode to keycode */
  284. PRINTF ("scancode %x\n", scancode);
  285. if (scancode == 0xe0) {
  286. e0 = 1; /* special charakters */
  287. return;
  288. }
  289. if (e0 == 1) {
  290. e0 = 0; /* delete flag */
  291. if (!(((scancode & 0x7F) == 0x38) || /* the right ctrl key */
  292. ((scancode & 0x7F) == 0x1D) || /* the right alt key */
  293. ((scancode & 0x7F) == 0x35) || /* the right '/' key */
  294. ((scancode & 0x7F) == 0x1C) || /* the right enter key */
  295. ((scancode) == 0x48) || /* arrow up */
  296. ((scancode) == 0x50) || /* arrow down */
  297. ((scancode) == 0x4b) || /* arrow left */
  298. ((scancode) == 0x4d)))
  299. /* arrow right */
  300. /* we swallow unknown e0 codes */
  301. return;
  302. }
  303. /* special cntrl keys */
  304. switch (scancode) {
  305. case 0x48:
  306. kbd_put_queue (27);
  307. kbd_put_queue (91);
  308. kbd_put_queue ('A');
  309. return;
  310. case 0x50:
  311. kbd_put_queue (27);
  312. kbd_put_queue (91);
  313. kbd_put_queue ('B');
  314. return;
  315. case 0x4b:
  316. kbd_put_queue (27);
  317. kbd_put_queue (91);
  318. kbd_put_queue ('D');
  319. return;
  320. case 0x4D:
  321. kbd_put_queue (27);
  322. kbd_put_queue (91);
  323. kbd_put_queue ('C');
  324. return;
  325. case 0x58: /* F12 key */
  326. if (ctrl == 1) {
  327. extern int console_changed;
  328. setenv ("stdin", DEVNAME);
  329. setenv ("stdout", "vga");
  330. console_changed = 1;
  331. }
  332. return;
  333. case 0x2A:
  334. case 0x36: /* shift pressed */
  335. shift = 1;
  336. return; /* do nothing else */
  337. case 0xAA:
  338. case 0xB6: /* shift released */
  339. shift = 0;
  340. return; /* do nothing else */
  341. case 0x38: /* alt pressed */
  342. alt = 1;
  343. return; /* do nothing else */
  344. case 0xB8: /* alt released */
  345. alt = 0;
  346. return; /* do nothing else */
  347. case 0x1d: /* ctrl pressed */
  348. ctrl = 1;
  349. return; /* do nothing else */
  350. case 0x9d: /* ctrl released */
  351. ctrl = 0;
  352. return; /* do nothing else */
  353. case 0x46: /* scrollock pressed */
  354. scroll_lock = ~scroll_lock;
  355. kbd_set_leds ();
  356. return; /* do nothing else */
  357. case 0x3A: /* capslock pressed */
  358. caps_lock = ~caps_lock;
  359. kbd_set_leds ();
  360. return;
  361. case 0x45: /* numlock pressed */
  362. num_lock = ~num_lock;
  363. kbd_set_leds ();
  364. return;
  365. case 0xC6: /* scroll lock released */
  366. case 0xC5: /* num lock released */
  367. case 0xBA: /* caps lock released */
  368. return; /* just swallow */
  369. }
  370. if ((scancode & 0x80) == 0x80) /* key released */
  371. return;
  372. /* now, decide which table we need */
  373. if (scancode > (sizeof (kbd_plain_xlate) / sizeof (kbd_plain_xlate[0]))) { /* scancode not in list */
  374. PRINTF ("unkown scancode %X\n", scancode);
  375. return; /* swallow it */
  376. }
  377. /* setup plain code first */
  378. keycode = kbd_plain_xlate[scancode];
  379. if (caps_lock == 1) { /* caps_lock is pressed, overwrite plain code */
  380. if (scancode > (sizeof (kbd_shift_xlate) / sizeof (kbd_shift_xlate[0]))) { /* scancode not in list */
  381. PRINTF ("unkown caps-locked scancode %X\n", scancode);
  382. return; /* swallow it */
  383. }
  384. keycode = kbd_shift_xlate[scancode];
  385. if (keycode < 'A') { /* we only want the alphas capital */
  386. keycode = kbd_plain_xlate[scancode];
  387. }
  388. }
  389. if (shift == 1) { /* shift overwrites caps_lock */
  390. if (scancode > (sizeof (kbd_shift_xlate) / sizeof (kbd_shift_xlate[0]))) { /* scancode not in list */
  391. PRINTF ("unkown shifted scancode %X\n", scancode);
  392. return; /* swallow it */
  393. }
  394. keycode = kbd_shift_xlate[scancode];
  395. }
  396. if (ctrl == 1) { /* ctrl overwrites caps_lock and shift */
  397. if (scancode > (sizeof (kbd_ctrl_xlate) / sizeof (kbd_ctrl_xlate[0]))) { /* scancode not in list */
  398. PRINTF ("unkown ctrl scancode %X\n", scancode);
  399. return; /* swallow it */
  400. }
  401. keycode = kbd_ctrl_xlate[scancode];
  402. }
  403. /* check if valid keycode */
  404. if (keycode == 0xff) {
  405. PRINTF ("unkown scancode %X\n", scancode);
  406. return; /* swallow unknown codes */
  407. }
  408. kbd_put_queue (keycode);
  409. PRINTF ("%x\n", keycode);
  410. }
  411. /*
  412. * This reads the keyboard status port, and does the
  413. * appropriate action.
  414. *
  415. */
  416. unsigned char handle_kbd_event (void)
  417. {
  418. unsigned char status = kbd_read_status ();
  419. unsigned int work = 10000;
  420. while ((--work > 0) && (status & KBD_STAT_OBF)) {
  421. unsigned char scancode;
  422. scancode = kbd_read_input ();
  423. /* Error bytes must be ignored to make the
  424. Synaptics touchpads compaq use work */
  425. /* Ignore error bytes */
  426. if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR))) {
  427. if (status & KBD_STAT_MOUSE_OBF); /* not supported: handle_mouse_event(scancode); */
  428. else
  429. handle_keyboard_event (scancode);
  430. }
  431. status = kbd_read_status ();
  432. }
  433. if (!work)
  434. PRINTF ("pc_keyb: controller jammed (0x%02X).\n", status);
  435. return status;
  436. }
  437. /******************************************************************************
  438. * Lowlevel Part of keyboard section
  439. */
  440. unsigned char kbd_read_status(void)
  441. {
  442. return(in8(CONFIG_SYS_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT));
  443. }
  444. unsigned char kbd_read_input(void)
  445. {
  446. return(in8(CONFIG_SYS_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT));
  447. }
  448. void kbd_write_command(unsigned char cmd)
  449. {
  450. out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT,cmd);
  451. }
  452. void kbd_write_output(unsigned char data)
  453. {
  454. out8(CONFIG_SYS_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT, data);
  455. }
  456. int kbd_read_data(void)
  457. {
  458. int val;
  459. unsigned char status;
  460. val = -1;
  461. status = kbd_read_status();
  462. if (status & KBD_STAT_OBF) {
  463. val = kbd_read_input();
  464. if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
  465. val = -2;
  466. }
  467. return val;
  468. }
  469. int kbd_wait_for_input (void)
  470. {
  471. unsigned long timeout;
  472. int val;
  473. timeout = KBD_TIMEOUT;
  474. val = kbd_read_data ();
  475. while (val < 0) {
  476. if (timeout-- == 0)
  477. return -1;
  478. udelay (1000);
  479. val = kbd_read_data ();
  480. }
  481. return val;
  482. }
  483. int kb_wait (void)
  484. {
  485. unsigned long timeout = KBC_TIMEOUT * 10;
  486. do {
  487. unsigned char status = handle_kbd_event ();
  488. if (!(status & KBD_STAT_IBF))
  489. return 0; /* ok */
  490. udelay (1000);
  491. timeout--;
  492. } while (timeout);
  493. return 1;
  494. }
  495. void kbd_write_command_w (int data)
  496. {
  497. if (kb_wait ())
  498. PRINTF ("timeout in kbd_write_command_w\n");
  499. kbd_write_command (data);
  500. }
  501. void kbd_write_output_w (int data)
  502. {
  503. if (kb_wait ())
  504. PRINTF ("timeout in kbd_write_output_w\n");
  505. kbd_write_output (data);
  506. }
  507. void kbd_send_data (unsigned char data)
  508. {
  509. unsigned char status;
  510. i8259_mask_irq (KBD_INTERRUPT); /* disable interrupt */
  511. kbd_write_output_w (data);
  512. status = kbd_wait_for_input ();
  513. if (status == KBD_REPLY_ACK)
  514. i8259_unmask_irq (KBD_INTERRUPT); /* enable interrupt */
  515. }
  516. char *kbd_initialize (void)
  517. {
  518. int status;
  519. in_pointer = 0; /* delete in Buffer */
  520. out_pointer = 0;
  521. /*
  522. * Test the keyboard interface.
  523. * This seems to be the only way to get it going.
  524. * If the test is successful a x55 is placed in the input buffer.
  525. */
  526. kbd_write_command_w (KBD_CCMD_SELF_TEST);
  527. if (kbd_wait_for_input () != 0x55)
  528. return "Kbd: failed self test";
  529. /*
  530. * Perform a keyboard interface test. This causes the controller
  531. * to test the keyboard clock and data lines. The results of the
  532. * test are placed in the input buffer.
  533. */
  534. kbd_write_command_w (KBD_CCMD_KBD_TEST);
  535. if (kbd_wait_for_input () != 0x00)
  536. return "Kbd: interface failed self test";
  537. /*
  538. * Enable the keyboard by allowing the keyboard clock to run.
  539. */
  540. kbd_write_command_w (KBD_CCMD_KBD_ENABLE);
  541. status = kbd_wait_for_input ();
  542. /*
  543. * Reset keyboard. If the read times out
  544. * then the assumption is that no keyboard is
  545. * plugged into the machine.
  546. * This defaults the keyboard to scan-code set 2.
  547. *
  548. * Set up to try again if the keyboard asks for RESEND.
  549. */
  550. do {
  551. kbd_write_output_w (KBD_CMD_RESET);
  552. status = kbd_wait_for_input ();
  553. if (status == KBD_REPLY_ACK)
  554. break;
  555. if (status != KBD_REPLY_RESEND) {
  556. PRINTF ("status: %X\n", status);
  557. return "Kbd: reset failed, no ACK";
  558. }
  559. } while (1);
  560. if (kbd_wait_for_input () != KBD_REPLY_POR)
  561. return "Kbd: reset failed, no POR";
  562. /*
  563. * Set keyboard controller mode. During this, the keyboard should be
  564. * in the disabled state.
  565. *
  566. * Set up to try again if the keyboard asks for RESEND.
  567. */
  568. do {
  569. kbd_write_output_w (KBD_CMD_DISABLE);
  570. status = kbd_wait_for_input ();
  571. if (status == KBD_REPLY_ACK)
  572. break;
  573. if (status != KBD_REPLY_RESEND)
  574. return "Kbd: disable keyboard: no ACK";
  575. } while (1);
  576. kbd_write_command_w (KBD_CCMD_WRITE_MODE);
  577. kbd_write_output_w (KBD_MODE_KBD_INT
  578. | KBD_MODE_SYS
  579. | KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC);
  580. /* AMCC powerpc portables need this to use scan-code set 1 -- Cort */
  581. kbd_write_command_w (KBD_CCMD_READ_MODE);
  582. if (!(kbd_wait_for_input () & KBD_MODE_KCC)) {
  583. /*
  584. * If the controller does not support conversion,
  585. * Set the keyboard to scan-code set 1.
  586. */
  587. kbd_write_output_w (0xF0);
  588. kbd_wait_for_input ();
  589. kbd_write_output_w (0x01);
  590. kbd_wait_for_input ();
  591. }
  592. kbd_write_output_w (KBD_CMD_ENABLE);
  593. if (kbd_wait_for_input () != KBD_REPLY_ACK)
  594. return "Kbd: enable keyboard: no ACK";
  595. /*
  596. * Finally, set the typematic rate to maximum.
  597. */
  598. kbd_write_output_w (KBD_CMD_SET_RATE);
  599. if (kbd_wait_for_input () != KBD_REPLY_ACK)
  600. return "Kbd: Set rate: no ACK";
  601. kbd_write_output_w (0x00);
  602. if (kbd_wait_for_input () != KBD_REPLY_ACK)
  603. return "Kbd: Set rate: no ACK";
  604. return NULL;
  605. }
  606. void kbd_interrupt(void)
  607. {
  608. handle_kbd_event();
  609. }