kbd.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #include <linux/keyboard.h>
  2. #include "defkeymap.c" /* yeah I know it's bad -- Cort */
  3. unsigned char shfts, ctls, alts, caps;
  4. #define KBDATAP 0x60 /* kbd data port */
  5. #define KBSTATUSPORT 0x61 /* kbd status */
  6. #define KBSTATP 0x64 /* kbd status port */
  7. #define KBINRDY 0x01
  8. #define KBOUTRDY 0x02
  9. extern unsigned char inb(int port);
  10. extern void outb(int port, char val);
  11. extern void puts(const char *);
  12. extern void puthex(unsigned long val);
  13. extern void udelay(long x);
  14. static int kbd(int noblock)
  15. {
  16. unsigned char dt, brk, val;
  17. unsigned code;
  18. loop:
  19. if (noblock) {
  20. if ((inb(KBSTATP) & KBINRDY) == 0)
  21. return (-1);
  22. } else while((inb(KBSTATP) & KBINRDY) == 0) ;
  23. dt = inb(KBDATAP);
  24. brk = dt & 0x80; /* brk == 1 on key release */
  25. dt = dt & 0x7f; /* keycode */
  26. if (shfts)
  27. code = shift_map[dt];
  28. else if (ctls)
  29. code = ctrl_map[dt];
  30. else
  31. code = plain_map[dt];
  32. val = KVAL(code);
  33. switch (KTYP(code) & 0x0f) {
  34. case KT_LATIN:
  35. if (brk)
  36. break;
  37. if (alts)
  38. val |= 0x80;
  39. if (val == 0x7f) /* map delete to backspace */
  40. val = '\b';
  41. return val;
  42. case KT_LETTER:
  43. if (brk)
  44. break;
  45. if (caps)
  46. val -= 'a'-'A';
  47. return val;
  48. case KT_SPEC:
  49. if (brk)
  50. break;
  51. if (val == KVAL(K_CAPS))
  52. caps = !caps;
  53. else if (val == KVAL(K_ENTER)) {
  54. enter: /* Wait for key up */
  55. while (1) {
  56. while((inb(KBSTATP) & KBINRDY) == 0) ;
  57. dt = inb(KBDATAP);
  58. if (dt & 0x80) /* key up */ break;
  59. }
  60. return 10;
  61. }
  62. break;
  63. case KT_PAD:
  64. if (brk)
  65. break;
  66. if (val < 10)
  67. return val;
  68. if (val == KVAL(K_PENTER))
  69. goto enter;
  70. break;
  71. case KT_SHIFT:
  72. switch (val) {
  73. case KG_SHIFT:
  74. case KG_SHIFTL:
  75. case KG_SHIFTR:
  76. shfts = brk ? 0 : 1;
  77. break;
  78. case KG_ALT:
  79. case KG_ALTGR:
  80. alts = brk ? 0 : 1;
  81. break;
  82. case KG_CTRL:
  83. case KG_CTRLL:
  84. case KG_CTRLR:
  85. ctls = brk ? 0 : 1;
  86. break;
  87. }
  88. break;
  89. case KT_LOCK:
  90. switch (val) {
  91. case KG_SHIFT:
  92. case KG_SHIFTL:
  93. case KG_SHIFTR:
  94. if (brk)
  95. shfts = !shfts;
  96. break;
  97. case KG_ALT:
  98. case KG_ALTGR:
  99. if (brk)
  100. alts = !alts;
  101. break;
  102. case KG_CTRL:
  103. case KG_CTRLL:
  104. case KG_CTRLR:
  105. if (brk)
  106. ctls = !ctls;
  107. break;
  108. }
  109. break;
  110. }
  111. if (brk) return (-1); /* Ignore initial 'key up' codes */
  112. goto loop;
  113. }
  114. static int __kbdreset(void)
  115. {
  116. unsigned char c;
  117. int i, t;
  118. /* flush input queue */
  119. t = 2000;
  120. while ((inb(KBSTATP) & KBINRDY))
  121. {
  122. (void)inb(KBDATAP);
  123. if (--t == 0)
  124. return 1;
  125. }
  126. /* Send self-test */
  127. t = 20000;
  128. while (inb(KBSTATP) & KBOUTRDY)
  129. if (--t == 0)
  130. return 2;
  131. outb(KBSTATP,0xAA);
  132. t = 200000;
  133. while ((inb(KBSTATP) & KBINRDY) == 0) /* wait input ready */
  134. if (--t == 0)
  135. return 3;
  136. if ((c = inb(KBDATAP)) != 0x55)
  137. {
  138. puts("Keyboard self test failed - result:");
  139. puthex(c);
  140. puts("\n");
  141. }
  142. /* Enable interrupts and keyboard controller */
  143. t = 20000;
  144. while (inb(KBSTATP) & KBOUTRDY)
  145. if (--t == 0) return 4;
  146. outb(KBSTATP,0x60);
  147. t = 20000;
  148. while (inb(KBSTATP) & KBOUTRDY)
  149. if (--t == 0) return 5;
  150. outb(KBDATAP,0x45);
  151. for (i = 0; i < 10000; i++) udelay(1);
  152. t = 20000;
  153. while (inb(KBSTATP) & KBOUTRDY)
  154. if (--t == 0) return 6;
  155. outb(KBSTATP,0x20);
  156. t = 200000;
  157. while ((inb(KBSTATP) & KBINRDY) == 0) /* wait input ready */
  158. if (--t == 0) return 7;
  159. if (! (inb(KBDATAP) & 0x40)) {
  160. /*
  161. * Quote from PS/2 System Reference Manual:
  162. *
  163. * "Address hex 0060 and address hex 0064 should be
  164. * written only when the input-buffer-full bit and
  165. * output-buffer-full bit in the Controller Status
  166. * register are set 0." (KBINRDY and KBOUTRDY)
  167. */
  168. t = 200000;
  169. while (inb(KBSTATP) & (KBINRDY | KBOUTRDY))
  170. if (--t == 0) return 8;
  171. outb(KBDATAP,0xF0);
  172. t = 200000;
  173. while (inb(KBSTATP) & (KBINRDY | KBOUTRDY))
  174. if (--t == 0) return 9;
  175. outb(KBDATAP,0x01);
  176. }
  177. t = 20000;
  178. while (inb(KBSTATP) & KBOUTRDY)
  179. if (--t == 0) return 10;
  180. outb(KBSTATP,0xAE);
  181. return 0;
  182. }
  183. static void kbdreset(void)
  184. {
  185. int ret = __kbdreset();
  186. if (ret) {
  187. puts("__kbdreset failed: ");
  188. puthex(ret);
  189. puts("\n");
  190. }
  191. }
  192. /* We have to actually read the keyboard when CRT_tstc is called,
  193. * since the pending data might be a key release code, and therefore
  194. * not valid data. In this case, kbd() will return -1, even though there's
  195. * data to be read. Of course, we might actually read a valid key press,
  196. * in which case it gets queued into key_pending for use by CRT_getc.
  197. */
  198. static int kbd_reset = 0;
  199. static int key_pending = -1;
  200. int CRT_getc(void)
  201. {
  202. int c;
  203. if (!kbd_reset) {kbdreset(); kbd_reset++; }
  204. if (key_pending != -1) {
  205. c = key_pending;
  206. key_pending = -1;
  207. return c;
  208. } else {
  209. while ((c = kbd(0)) == 0) ;
  210. return c;
  211. }
  212. }
  213. int CRT_tstc(void)
  214. {
  215. if (!kbd_reset) {kbdreset(); kbd_reset++; }
  216. while (key_pending == -1 && ((inb(KBSTATP) & KBINRDY) != 0)) {
  217. key_pending = kbd(1);
  218. }
  219. return (key_pending != -1);
  220. }