kbd.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. enum {
  8. Data= 0x60, /* data port */
  9. Status= 0x64, /* status port */
  10. Inready= 0x01, /* input character ready */
  11. Outbusy= 0x02, /* output busy */
  12. Sysflag= 0x04, /* system flag */
  13. Cmddata= 0x08, /* cmd==0, data==1 */
  14. Inhibit= 0x10, /* keyboard/mouse inhibited */
  15. Minready= 0x20, /* mouse character ready */
  16. Rtimeout= 0x40, /* general timeout */
  17. Parity= 0x80,
  18. Cmd= 0x64, /* command port (write only) */
  19. Spec= 0x80,
  20. PF= Spec|0x20, /* num pad function key */
  21. View= Spec|0x00, /* view (shift window up) */
  22. KF= Spec|0x40, /* function key */
  23. Shift= Spec|0x60,
  24. Break= Spec|0x61,
  25. Ctrl= Spec|0x62,
  26. Latin= Spec|0x63,
  27. Caps= Spec|0x64,
  28. Num= Spec|0x65,
  29. No= Spec|0x7F, /* no mapping */
  30. Home= KF|13,
  31. Up= KF|14,
  32. Pgup= KF|15,
  33. Print= KF|16,
  34. Left= View,
  35. Right= View,
  36. End= '\r',
  37. Down= View,
  38. Pgdown= View,
  39. Ins= KF|20,
  40. Del= 0x7F,
  41. };
  42. uchar kbtab[] =
  43. {
  44. [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
  45. [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
  46. [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
  47. [0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
  48. [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
  49. [0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
  50. [0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,
  51. [0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
  52. [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
  53. [0x48] No, No, No, No, No, No, No, No,
  54. [0x50] No, No, No, No, No, No, No, KF|11,
  55. [0x58] KF|12, No, No, No, No, No, No, No,
  56. };
  57. uchar kbtabshift[] =
  58. {
  59. [0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
  60. [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
  61. [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
  62. [0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
  63. [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
  64. [0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
  65. [0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,
  66. [0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
  67. [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
  68. [0x48] No, No, No, No, No, No, No, No,
  69. [0x50] No, No, No, No, No, No, No, KF|11,
  70. [0x58] KF|12, No, No, No, No, No, No, No,
  71. };
  72. uchar kbtabesc1[] =
  73. {
  74. [0x00] No, No, No, No, No, No, No, No,
  75. [0x08] No, No, No, No, No, No, No, No,
  76. [0x10] No, No, No, No, No, No, No, No,
  77. [0x18] No, No, No, No, No, Ctrl, No, No,
  78. [0x20] No, No, No, No, No, No, No, No,
  79. [0x28] No, No, No, No, No, No, No, No,
  80. [0x30] No, No, No, No, No, No, No, Print,
  81. [0x38] Latin, No, No, No, No, No, No, No,
  82. [0x40] No, No, No, No, No, No, Break, Home,
  83. [0x48] Up, Pgup, No, Down, No, Right, No, End,
  84. [0x50] Left, Pgdown, Ins, Del, No, No, No, No,
  85. [0x58] No, No, No, No, No, No, No, No,
  86. };
  87. struct latin
  88. {
  89. uchar l;
  90. char c[2];
  91. }latintab[] = {
  92. L'¡', "!!", /* spanish initial ! */
  93. L'¢', "c|", /* cent */
  94. L'¢', "c$", /* cent */
  95. L'£', "l$", /* pound sterling */
  96. L'¤', "g$", /* general currency */
  97. L'¥', "y$", /* yen */
  98. L'¥', "j$", /* yen */
  99. L'¦', "||", /* broken vertical bar */
  100. L'§', "SS", /* section symbol */
  101. L'¨', "\"\"", /* dieresis */
  102. L'©', "cr", /* copyright */
  103. L'©', "cO", /* copyright */
  104. L'ª', "sa", /* super a, feminine ordinal */
  105. L'«', "<<", /* left angle quotation */
  106. L'¬', "no", /* not sign, hooked overbar */
  107. L'­', "--", /* soft hyphen */
  108. L'®', "rg", /* registered trademark */
  109. L'¯', "__", /* macron */
  110. L'°', "s0", /* degree (sup o) */
  111. L'±', "+-", /* plus-minus */
  112. L'²', "s2", /* sup 2 */
  113. L'³', "s3", /* sup 3 */
  114. L'´', "''", /* grave accent */
  115. L'µ', "mu", /* mu */
  116. L'¶', "pg", /* paragraph (pilcrow) */
  117. L'·', "..", /* centered . */
  118. L'¸', ",,", /* cedilla */
  119. L'¹', "s1", /* sup 1 */
  120. L'º', "so", /* sup o */
  121. L'»', ">>", /* right angle quotation */
  122. L'¼', "14", /* 1/4 */
  123. L'½', "12", /* 1/2 */
  124. L'¾', "34", /* 3/4 */
  125. L'¿', "??", /* spanish initial ? */
  126. L'À', "A`", /* A grave */
  127. L'Á', "A'", /* A acute */
  128. L'Â', "A^", /* A circumflex */
  129. L'Ã', "A~", /* A tilde */
  130. L'Ä', "A\"", /* A dieresis */
  131. L'Ä', "A:", /* A dieresis */
  132. L'Å', "Ao", /* A circle */
  133. L'Å', "AO", /* A circle */
  134. L'Æ', "Ae", /* AE ligature */
  135. L'Æ', "AE", /* AE ligature */
  136. L'Ç', "C,", /* C cedilla */
  137. L'È', "E`", /* E grave */
  138. L'É', "E'", /* E acute */
  139. L'Ê', "E^", /* E circumflex */
  140. L'Ë', "E\"", /* E dieresis */
  141. L'Ë', "E:", /* E dieresis */
  142. L'Ì', "I`", /* I grave */
  143. L'Í', "I'", /* I acute */
  144. L'Î', "I^", /* I circumflex */
  145. L'Ï', "I\"", /* I dieresis */
  146. L'Ï', "I:", /* I dieresis */
  147. L'Ð', "D-", /* Eth */
  148. L'Ñ', "N~", /* N tilde */
  149. L'Ò', "O`", /* O grave */
  150. L'Ó', "O'", /* O acute */
  151. L'Ô', "O^", /* O circumflex */
  152. L'Õ', "O~", /* O tilde */
  153. L'Ö', "O\"", /* O dieresis */
  154. L'Ö', "O:", /* O dieresis */
  155. L'Ö', "OE", /* O dieresis */
  156. L'Ö', "Oe", /* O dieresis */
  157. L'×', "xx", /* times sign */
  158. L'Ø', "O/", /* O slash */
  159. L'Ù', "U`", /* U grave */
  160. L'Ú', "U'", /* U acute */
  161. L'Û', "U^", /* U circumflex */
  162. L'Ü', "U\"", /* U dieresis */
  163. L'Ü', "U:", /* U dieresis */
  164. L'Ü', "UE", /* U dieresis */
  165. L'Ü', "Ue", /* U dieresis */
  166. L'Ý', "Y'", /* Y acute */
  167. L'Þ', "P|", /* Thorn */
  168. L'Þ', "Th", /* Thorn */
  169. L'Þ', "TH", /* Thorn */
  170. L'ß', "ss", /* sharp s */
  171. L'à', "a`", /* a grave */
  172. L'á', "a'", /* a acute */
  173. L'â', "a^", /* a circumflex */
  174. L'ã', "a~", /* a tilde */
  175. L'ä', "a\"", /* a dieresis */
  176. L'ä', "a:", /* a dieresis */
  177. L'å', "ao", /* a circle */
  178. L'æ', "ae", /* ae ligature */
  179. L'ç', "c,", /* c cedilla */
  180. L'è', "e`", /* e grave */
  181. L'é', "e'", /* e acute */
  182. L'ê', "e^", /* e circumflex */
  183. L'ë', "e\"", /* e dieresis */
  184. L'ë', "e:", /* e dieresis */
  185. L'ì', "i`", /* i grave */
  186. L'í', "i'", /* i acute */
  187. L'î', "i^", /* i circumflex */
  188. L'ï', "i\"", /* i dieresis */
  189. L'ï', "i:", /* i dieresis */
  190. L'ð', "d-", /* eth */
  191. L'ñ', "n~", /* n tilde */
  192. L'ò', "o`", /* o grave */
  193. L'ó', "o'", /* o acute */
  194. L'ô', "o^", /* o circumflex */
  195. L'õ', "o~", /* o tilde */
  196. L'ö', "o\"", /* o dieresis */
  197. L'ö', "o:", /* o dieresis */
  198. L'ö', "oe", /* o dieresis */
  199. L'÷', "-:", /* divide sign */
  200. L'ø', "o/", /* o slash */
  201. L'ù', "u`", /* u grave */
  202. L'ú', "u'", /* u acute */
  203. L'û', "u^", /* u circumflex */
  204. L'ü', "u\"", /* u dieresis */
  205. L'ü', "u:", /* u dieresis */
  206. L'ü', "ue", /* u dieresis */
  207. L'ý', "y'", /* y acute */
  208. L'þ', "th", /* thorn */
  209. L'þ', "p|", /* thorn */
  210. L'ÿ', "y\"", /* y dieresis */
  211. L'ÿ', "y:", /* y dieresis */
  212. 0, 0,
  213. };
  214. enum
  215. {
  216. /* controller command byte */
  217. Cscs1= (1<<6), /* scan code set 1 */
  218. Cmousedis= (1<<5), /* mouse disable */
  219. Ckbddis= (1<<4), /* kbd disable */
  220. Csf= (1<<2), /* system flag */
  221. Cmouseint= (1<<1), /* mouse interrupt enable */
  222. Ckbdint= (1<<0), /* kbd interrupt enable */
  223. };
  224. static uchar ccc;
  225. int
  226. latin1(int k1, int k2)
  227. {
  228. struct latin *l;
  229. for(l=latintab; l->l; l++)
  230. if(k1==l->c[0] && k2==l->c[1])
  231. return l->l;
  232. return 0;
  233. }
  234. /*
  235. * wait for output no longer busy
  236. */
  237. static int
  238. outready(void)
  239. {
  240. int tries;
  241. for(tries = 0; (inb(Status) & Outbusy); tries++){
  242. if(tries > 500)
  243. return -1;
  244. delay(2);
  245. }
  246. return 0;
  247. }
  248. /*
  249. * wait for input
  250. */
  251. static int
  252. inready(void)
  253. {
  254. int tries;
  255. for(tries = 0; !(inb(Status) & Inready); tries++){
  256. if(tries > 500)
  257. return -1;
  258. delay(2);
  259. }
  260. return 0;
  261. }
  262. /*
  263. * ask 8042 to enable the use of address bit 20
  264. */
  265. void
  266. i8042a20(void)
  267. {
  268. outready();
  269. outb(Cmd, 0xD1);
  270. outready();
  271. outb(Data, 0xDF);
  272. outready();
  273. }
  274. /*
  275. * ask 8042 to reset the machine
  276. */
  277. void
  278. i8042reset(void)
  279. {
  280. int i, x;
  281. #ifdef notdef
  282. ushort *s = (ushort*)(KZERO|0x472);
  283. *s = 0x1234; /* BIOS warm-boot flag */
  284. #endif /* notdef */
  285. outready();
  286. outb(Cmd, 0xFE); /* pulse reset line (means resend on AT&T machines) */
  287. outready();
  288. /*
  289. * Pulse it by hand (old somewhat reliable)
  290. */
  291. x = 0xDF;
  292. for(i = 0; i < 5; i++){
  293. x ^= 1;
  294. outready();
  295. outb(Cmd, 0xD1);
  296. outready();
  297. outb(Data, x); /* toggle reset */
  298. delay(100);
  299. }
  300. }
  301. /*
  302. * keyboard interrupt
  303. */
  304. static void
  305. i8042intr(Ureg*, void*)
  306. {
  307. int s, c;
  308. static int esc1, esc2;
  309. static int alt, caps, ctl, num, shift;
  310. static int lstate, k1, k2;
  311. int keyup;
  312. /*
  313. * get status
  314. */
  315. s = inb(Status);
  316. if(!(s&Inready))
  317. return;
  318. /*
  319. * get the character
  320. */
  321. c = inb(Data);
  322. /*
  323. * if it's the aux port...
  324. */
  325. if(s & Minready)
  326. return;
  327. /*
  328. * e0's is the first of a 2 character sequence
  329. */
  330. if(c == 0xe0){
  331. esc1 = 1;
  332. return;
  333. } else if(c == 0xe1){
  334. esc2 = 2;
  335. return;
  336. }
  337. keyup = c&0x80;
  338. c &= 0x7f;
  339. if(c > sizeof kbtab){
  340. c |= keyup;
  341. if(c != 0xFF) /* these come fairly often: CAPSLOCK U Y */
  342. print("unknown key %ux\n", c);
  343. return;
  344. }
  345. if(esc1){
  346. c = kbtabesc1[c];
  347. esc1 = 0;
  348. } else if(esc2){
  349. esc2--;
  350. return;
  351. } else if(shift)
  352. c = kbtabshift[c];
  353. else
  354. c = kbtab[c];
  355. if(caps && c<='z' && c>='a')
  356. c += 'A' - 'a';
  357. /*
  358. * keyup only important for shifts
  359. */
  360. if(keyup){
  361. switch(c){
  362. case Latin:
  363. alt = 0;
  364. break;
  365. case Shift:
  366. shift = 0;
  367. break;
  368. case Ctrl:
  369. ctl = 0;
  370. break;
  371. }
  372. return;
  373. }
  374. /*
  375. * normal character
  376. */
  377. if(!(c & Spec)){
  378. if(ctl){
  379. if(alt && c == Del)
  380. warp86("\nCtrl-Alt-Del\n", 0);
  381. c &= 0x1f;
  382. }
  383. switch(lstate){
  384. case 1:
  385. k1 = c;
  386. lstate = 2;
  387. return;
  388. case 2:
  389. k2 = c;
  390. lstate = 0;
  391. c = latin1(k1, k2);
  392. if(c == 0){
  393. kbdchar(k1);
  394. c = k2;
  395. }
  396. /* fall through */
  397. default:
  398. break;
  399. }
  400. } else {
  401. switch(c){
  402. case Caps:
  403. caps ^= 1;
  404. return;
  405. case Num:
  406. num ^= 1;
  407. return;
  408. case Shift:
  409. shift = 1;
  410. return;
  411. case Latin:
  412. alt = 1;
  413. lstate = 1;
  414. return;
  415. case Ctrl:
  416. ctl = 1;
  417. return;
  418. }
  419. }
  420. kbdchar(c);
  421. }
  422. static char *initfailed = "kbd init failed\n";
  423. static int
  424. outbyte(int port, int c)
  425. {
  426. outb(port, c);
  427. if(outready() < 0) {
  428. vga = 0;
  429. print(initfailed);
  430. return -1;
  431. }
  432. return 0;
  433. }
  434. void
  435. i8042init(void)
  436. {
  437. int c, try;
  438. /* wait for a quiescent controller */
  439. try = 1000;
  440. while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) {
  441. if(c & Inready)
  442. inb(Data);
  443. delay(1);
  444. }
  445. if (try <= 0) {
  446. vga = 0;
  447. print(initfailed);
  448. return;
  449. }
  450. /* get current controller command byte */
  451. outb(Cmd, 0x20);
  452. if(inready() < 0){
  453. print("kbdinit: can't read ccc\n");
  454. ccc = 0;
  455. } else
  456. ccc = inb(Data);
  457. /* enable kbd xfers and interrupts */
  458. ccc &= ~Ckbddis;
  459. ccc |= Csf | Ckbdint | Cscs1;
  460. if(outready() < 0) {
  461. vga = 0;
  462. print(initfailed);
  463. return;
  464. }
  465. if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0)
  466. return;
  467. setvec(VectorKBD, i8042intr, 0);
  468. }