Subversion Repositories shark

Rev

Rev 56 | Details | Compare with Previous | Last modification | View Log | RSS feed

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