kbd.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:5k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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