Clone of mesa.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

pc_keyb.c 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. /*
  2. * PC/HW routine collection v1.3 for DOS/DJGPP
  3. *
  4. * Copyright (C) 2002 - Daniel Borca
  5. * Email : dborca@yahoo.com
  6. * Web : http://www.geocities.com/dborca
  7. */
  8. #include <pc.h>
  9. #include <sys/exceptn.h>
  10. #include <sys/farptr.h>
  11. #include "pc_hw.h"
  12. #define KEYB_IRQ 1
  13. #define KEY_BUFFER_SIZE 64
  14. #define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG)
  15. #define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG)
  16. static int keyboard_installed;
  17. static volatile struct {
  18. volatile int start, end;
  19. volatile int key[KEY_BUFFER_SIZE];
  20. } key_buffer;
  21. static volatile int key_enhanced, key_pause_loop, key_shifts;
  22. static int leds_ok = TRUE;
  23. static int in_a_terrupt = FALSE;
  24. static volatile char pc_key[KEY_MAX];
  25. /* convert Allegro format scancodes into key_shifts flag bits */
  26. static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] = {
  27. KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG,
  28. KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG,
  29. KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG,
  30. KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG
  31. };
  32. /* lookup table for converting hardware scancodes into Allegro format */
  33. static unsigned char hw_to_mycode[128] = {
  34. /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
  35. /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
  36. /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
  37. /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
  38. /* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R,
  39. /* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I,
  40. /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
  41. /* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S,
  42. /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
  43. /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
  44. /* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH,
  45. /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
  46. /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
  47. /* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK,
  48. /* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
  49. /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
  50. /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
  51. /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD,
  52. /* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD,
  53. /* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD,
  54. /* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD,
  55. /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
  56. /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
  57. /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
  58. /* 0x60 */ 0, 0, 0, 0,
  59. /* 0x64 */ 0, 0, 0, 0,
  60. /* 0x68 */ 0, 0, 0, 0,
  61. /* 0x6C */ 0, 0, 0, 0,
  62. /* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1,
  63. /* 0x74 */ 0, 0, 0, 0,
  64. /* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT,
  65. /* 0x7C */ 0, KEY_YEN, 0, 0
  66. };
  67. /* lookup table for converting extended hardware codes into Allegro format */
  68. static unsigned char hw_to_mycode_ex[128] = {
  69. /* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
  70. /* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
  71. /* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
  72. /* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
  73. /* 0x10 */ KEY_CIRCUMFLEX, KEY_AT, KEY_COLON2, KEY_R,
  74. /* 0x14 */ KEY_KANJI, KEY_Y, KEY_U, KEY_I,
  75. /* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
  76. /* 0x1C */ KEY_ENTER_PAD, KEY_RCONTROL, KEY_A, KEY_S,
  77. /* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
  78. /* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
  79. /* 0x28 */ KEY_QUOTE, KEY_TILDE, 0, KEY_BACKSLASH,
  80. /* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
  81. /* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
  82. /* 0x34 */ KEY_STOP, KEY_SLASH_PAD, 0, KEY_PRTSCR,
  83. /* 0x38 */ KEY_ALTGR, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
  84. /* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
  85. /* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
  86. /* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_PAUSE, KEY_HOME,
  87. /* 0x48 */ KEY_UP, KEY_PGUP, KEY_MINUS_PAD, KEY_LEFT,
  88. /* 0x4C */ KEY_5_PAD, KEY_RIGHT, KEY_PLUS_PAD, KEY_END,
  89. /* 0x50 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL,
  90. /* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
  91. /* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
  92. /* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
  93. /* 0x60 */ 0, 0, 0, 0,
  94. /* 0x64 */ 0, 0, 0, 0,
  95. /* 0x68 */ 0, 0, 0, 0,
  96. /* 0x6C */ 0, 0, 0, 0,
  97. /* 0x70 */ 0, 0, 0, 0,
  98. /* 0x74 */ 0, 0, 0, 0,
  99. /* 0x78 */ 0, 0, 0, 0,
  100. /* 0x7C */ 0, 0, 0, 0
  101. };
  102. /* default mapping table for the US keyboard layout */
  103. static unsigned short standard_key_ascii_table[KEY_MAX] = {
  104. /* start */ 0,
  105. /* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
  106. /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  107. /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  108. /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  109. /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
  110. /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  111. /* numpad */ '/', '*', '-', '+', '.', 13,
  112. /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  113. };
  114. /* capslock mapping table for the US keyboard layout */
  115. static unsigned short standard_key_capslock_table[KEY_MAX] = {
  116. /* start */ 0,
  117. /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  118. /* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  119. /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  120. /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  121. /* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
  122. /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  123. /* numpad */ '/', '*', '-', '+', '.', 13,
  124. /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  125. };
  126. /* shifted mapping table for the US keyboard layout */
  127. static unsigned short standard_key_shift_table[KEY_MAX] = {
  128. /* start */ 0,
  129. /* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
  130. /* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(',
  131. /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  132. /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  133. /* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ',
  134. /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  135. /* numpad */ '/', '*', '-', '+', '.', 13,
  136. /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  137. };
  138. /* ctrl+key mapping table for the US keyboard layout */
  139. static unsigned short standard_key_control_table[KEY_MAX] = {
  140. /* start */ 0,
  141. /* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
  142. /* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  143. /* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  144. /* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  145. /* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2,
  146. /* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
  147. /* numpad */ 2, 2, 2, 2, 2, 10,
  148. /* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  149. };
  150. /* convert numeric pad scancodes into arrow codes */
  151. static unsigned char numlock_table[10] = {
  152. KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT,
  153. KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP
  154. };
  155. /* kb_wait_for_write_ready:
  156. * Wait for the keyboard controller to set the ready-for-write bit.
  157. */
  158. static __inline int
  159. kb_wait_for_write_ready (void)
  160. {
  161. int timeout = 4096;
  162. while ((timeout > 0) && (inportb(0x64) & 2)) timeout--;
  163. return (timeout > 0);
  164. }
  165. /* kb_wait_for_read_ready:
  166. * Wait for the keyboard controller to set the ready-for-read bit.
  167. */
  168. static __inline int
  169. kb_wait_for_read_ready (void)
  170. {
  171. int timeout = 16384;
  172. while ((timeout > 0) && (!(inportb(0x64) & 1))) timeout--;
  173. return (timeout > 0);
  174. }
  175. /* kb_send_data:
  176. * Sends a byte to the keyboard controller. Returns 1 if all OK.
  177. */
  178. static __inline int
  179. kb_send_data (unsigned char data)
  180. {
  181. int resends = 4;
  182. int timeout, temp;
  183. do {
  184. if (!kb_wait_for_write_ready())
  185. return 0;
  186. outportb(0x60, data);
  187. timeout = 4096;
  188. while (--timeout > 0) {
  189. if (!kb_wait_for_read_ready())
  190. return 0;
  191. temp = inportb(0x60);
  192. if (temp == 0xFA)
  193. return 1;
  194. if (temp == 0xFE)
  195. break;
  196. }
  197. } while ((resends-- > 0) && (timeout > 0));
  198. return 0;
  199. }
  200. static void
  201. update_leds (int leds)
  202. {
  203. if (leds_ok) {
  204. if (!in_a_terrupt)
  205. DISABLE();
  206. if (!kb_send_data(0xED)) {
  207. kb_send_data(0xF4);
  208. leds_ok = FALSE;
  209. } else if (!kb_send_data((leds >> 8) & 7)) {
  210. kb_send_data(0xF4);
  211. leds_ok = FALSE;
  212. }
  213. if (!in_a_terrupt)
  214. ENABLE();
  215. }
  216. } ENDOFUNC(update_leds)
  217. static void
  218. inject_key (int scancode)
  219. {
  220. unsigned short *table;
  221. if ((scancode >= KEY_0_PAD) && (scancode <= KEY_9_PAD)) {
  222. if (((key_shifts & KB_NUMLOCK_FLAG) != 0) == ((key_shifts & KB_SHIFT_FLAG) != 0)) {
  223. scancode = numlock_table[scancode - KEY_0_PAD];
  224. }
  225. table = standard_key_ascii_table;
  226. } else if (key_shifts & KB_CTRL_FLAG) {
  227. table = standard_key_control_table;
  228. } else if (key_shifts & KB_SHIFT_FLAG) {
  229. if (key_shifts & KB_CAPSLOCK_FLAG) {
  230. if (standard_key_ascii_table[scancode] == standard_key_capslock_table[scancode]) {
  231. table = standard_key_shift_table;
  232. } else {
  233. table = standard_key_ascii_table;
  234. }
  235. } else {
  236. table = standard_key_shift_table;
  237. }
  238. } else if (key_shifts & KB_CAPSLOCK_FLAG) {
  239. table = standard_key_capslock_table;
  240. } else {
  241. table = standard_key_ascii_table;
  242. }
  243. key_buffer.key[key_buffer.end++] = (scancode << 16) | table[scancode];
  244. if (key_buffer.end >= KEY_BUFFER_SIZE)
  245. key_buffer.end = 0;
  246. if (key_buffer.end == key_buffer.start) {
  247. key_buffer.start++;
  248. if (key_buffer.start >= KEY_BUFFER_SIZE)
  249. key_buffer.start = 0;
  250. }
  251. } ENDOFUNC(inject_key)
  252. static void
  253. handle_code (int scancode, int keycode)
  254. {
  255. in_a_terrupt++;
  256. if (keycode == 0) { /* pause */
  257. inject_key(scancode);
  258. pc_key[KEY_PAUSE] ^= TRUE;
  259. } else if (scancode) {
  260. int flag;
  261. if (scancode >= KEY_MODIFIERS) {
  262. flag = modifier_table[scancode - KEY_MODIFIERS];
  263. } else {
  264. flag = 0;
  265. }
  266. if ((char)keycode < 0) { /* release */
  267. pc_key[scancode] = FALSE;
  268. if (flag & KB_MODIFIERS) {
  269. key_shifts &= ~flag;
  270. }
  271. } else { /* keypress */
  272. pc_key[scancode] = TRUE;
  273. if (flag & KB_MODIFIERS) {
  274. key_shifts |= flag;
  275. }
  276. if (flag & KB_LED_FLAGS) {
  277. key_shifts ^= flag;
  278. update_leds(key_shifts);
  279. }
  280. if (scancode < KEY_MODIFIERS) {
  281. inject_key(scancode);
  282. }
  283. }
  284. }
  285. in_a_terrupt--;
  286. } ENDOFUNC(handle_code)
  287. static int
  288. keyboard ()
  289. {
  290. unsigned char temp, scancode;
  291. temp = inportb(0x60);
  292. if (temp <= 0xe1) {
  293. if (key_pause_loop) {
  294. if (!--key_pause_loop) handle_code(KEY_PAUSE, 0);
  295. } else
  296. switch (temp) {
  297. case 0xe0:
  298. key_enhanced = TRUE;
  299. break;
  300. case 0xe1:
  301. key_pause_loop = 5;
  302. break;
  303. default:
  304. if (key_enhanced) {
  305. key_enhanced = FALSE;
  306. scancode = hw_to_mycode_ex[temp & 0x7f];
  307. } else {
  308. scancode = hw_to_mycode[temp & 0x7f];
  309. }
  310. handle_code(scancode, temp);
  311. }
  312. }
  313. if (((temp==0x4F)||(temp==0x53))&&(key_shifts&KB_CTRL_FLAG)&&(key_shifts&KB_ALT_FLAG)) {
  314. /* Hack alert:
  315. * only SIGINT (but not Ctrl-Break)
  316. * calls the destructors and will safely clean up
  317. */
  318. __asm("\n\
  319. movb $0x79, %%al \n\
  320. call ___djgpp_hw_exception \n\
  321. ":::"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
  322. }
  323. __asm("\n\
  324. inb $0x61, %%al \n\
  325. movb %%al, %%ah \n\
  326. orb $0x80, %%al \n\
  327. outb %%al, $0x61 \n\
  328. xchgb %%al, %%ah \n\
  329. outb %%al, $0x61 \n\
  330. movb $0x20, %%al \n\
  331. outb %%al, $0x20 \n\
  332. ":::"%eax");
  333. return 0;
  334. } ENDOFUNC(keyboard)
  335. int
  336. pc_keypressed (void)
  337. {
  338. return (key_buffer.start!=key_buffer.end);
  339. }
  340. int
  341. pc_readkey (void)
  342. {
  343. if (keyboard_installed) {
  344. int key;
  345. while (key_buffer.start == key_buffer.end) {
  346. __dpmi_yield();
  347. }
  348. DISABLE();
  349. key = key_buffer.key[key_buffer.start++];
  350. if (key_buffer.start >= KEY_BUFFER_SIZE)
  351. key_buffer.start = 0;
  352. ENABLE();
  353. return key;
  354. } else {
  355. return 0;
  356. }
  357. }
  358. int
  359. pc_keydown (int code)
  360. {
  361. return pc_key[code];
  362. }
  363. int
  364. pc_keyshifts (void)
  365. {
  366. return key_shifts;
  367. }
  368. void
  369. pc_remove_keyb (void)
  370. {
  371. if (keyboard_installed) {
  372. int s1, s2, s3;
  373. keyboard_installed = FALSE;
  374. pc_clexit(pc_remove_keyb);
  375. DISABLE();
  376. _farsetsel(__djgpp_dos_sel);
  377. _farnspokew(0x41c, _farnspeekw(0x41a));
  378. s1 = _farnspeekb(0x417) & 0x80;
  379. s2 = _farnspeekb(0x418) & 0xFC;
  380. s3 = _farnspeekb(0x496) & 0xF3;
  381. if (pc_key[KEY_RSHIFT]) { s1 |= 1; }
  382. if (pc_key[KEY_LSHIFT]) { s1 |= 2; }
  383. if (pc_key[KEY_LCONTROL]) { s2 |= 1; s1 |= 4; }
  384. if (pc_key[KEY_ALT]) { s1 |= 8; s2 |= 2; }
  385. if (pc_key[KEY_RCONTROL]) { s1 |= 4; s3 |= 4; }
  386. if (pc_key[KEY_ALTGR]) { s1 |= 8; s3 |= 8; }
  387. if (key_shifts & KB_SCROLOCK_FLAG) s1 |= 16;
  388. if (key_shifts & KB_NUMLOCK_FLAG) s1 |= 32;
  389. if (key_shifts & KB_CAPSLOCK_FLAG) s1 |= 64;
  390. _farnspokeb(0x417, s1);
  391. _farnspokeb(0x418, s2);
  392. _farnspokeb(0x496, s3);
  393. update_leds(key_shifts);
  394. ENABLE();
  395. pc_remove_irq(KEYB_IRQ);
  396. }
  397. }
  398. int
  399. pc_install_keyb (void)
  400. {
  401. if (keyboard_installed || pc_install_irq(KEYB_IRQ, keyboard)) {
  402. return -1;
  403. } else {
  404. int s1, s2, s3;
  405. LOCKDATA(key_buffer);
  406. LOCKDATA(key_enhanced);
  407. LOCKDATA(key_pause_loop);
  408. LOCKDATA(key_shifts);
  409. LOCKDATA(leds_ok);
  410. LOCKDATA(in_a_terrupt);
  411. LOCKDATA(pc_key);
  412. LOCKDATA(modifier_table);
  413. LOCKDATA(hw_to_mycode);
  414. LOCKDATA(hw_to_mycode_ex);
  415. LOCKDATA(standard_key_ascii_table);
  416. LOCKDATA(standard_key_capslock_table);
  417. LOCKDATA(standard_key_shift_table);
  418. LOCKDATA(standard_key_control_table);
  419. LOCKDATA(numlock_table);
  420. LOCKFUNC(update_leds);
  421. LOCKFUNC(inject_key);
  422. LOCKFUNC(handle_code);
  423. LOCKFUNC(keyboard);
  424. DISABLE();
  425. _farsetsel(__djgpp_dos_sel);
  426. _farnspokew(0x41c, _farnspeekw(0x41a));
  427. key_shifts = 0;
  428. s1 = _farnspeekb(0x417);
  429. s2 = _farnspeekb(0x418);
  430. s3 = _farnspeekb(0x496);
  431. if (s1 & 1) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_RSHIFT] = TRUE; }
  432. if (s1 & 2) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_LSHIFT] = TRUE; }
  433. if (s2 & 1) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_LCONTROL] = TRUE; }
  434. if (s2 & 2) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALT] = TRUE; }
  435. if (s3 & 4) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_RCONTROL] = TRUE; }
  436. if (s3 & 8) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALTGR] = TRUE; }
  437. if (s1 & 16) key_shifts |= KB_SCROLOCK_FLAG;
  438. if (s1 & 32) key_shifts |= KB_NUMLOCK_FLAG;
  439. if (s1 & 64) key_shifts |= KB_CAPSLOCK_FLAG;
  440. update_leds(key_shifts);
  441. key_enhanced = key_pause_loop = 0;
  442. key_buffer.start = key_buffer.end = 0;
  443. ENABLE();
  444. pc_atexit(pc_remove_keyb);
  445. keyboard_installed = TRUE;
  446. return 0;
  447. }
  448. }