]> pd.if.org Git - mmurtl/blob - ossource/keyboard.asm
autocommit for file dated 2003-12-29 17:36:54
[mmurtl] / ossource / keyboard.asm
1 ;   MMURTL Operating System Source Code\r
2 ;   Copyright 1991,1992,1993,1994,1995 Richard A. Burgess\r
3 ;   ALL RIGHTS RESERVED\r
4 ;   Version 1.0\r
5 ;\r
6 .DATA                                   ;Begin Keyboard Data\r
7 .INCLUDE MOSEDF.INC\r
8 .INCLUDE RQB.INC\r
9 .INCLUDE TSS.INC\r
10 .ALIGN DWORD\r
11 \r
12 EXTRN ddVidOwner        DD\r
13 \r
14 ;The keyboard service is designed to return the complete status\r
15 ;of the keyboard shift, control, alt, and lock keys as well as\r
16 ;the key in the buffer that the state applies to.\r
17 ;\r
18 ;This is done by using two buffers. The first is a "RAW" key buffer\r
19 ;that holds keys from the interrupt service routine which contains\r
20 ;all raw keystrokes including shift keys going up and down.\r
21 ;This information is needed to build coherent keystroke information\r
22 ; for an application.  This buffer is 32 bytes long.\r
23 ;\r
24 ;The second buffer is 256 bytes and contains the translated information\r
25 ;in the form of DWords (a 4 byte quantity times 64).  This DWord contains the\r
26 ;following information:\r
27 ;\r
28 ;Low byte  (bits 0-7)   Partially translated application keystroke\r
29 ;Next byte (bits 8-15)  Shift State (Ctrl, Shift, Alt)\r
30 ;Next byte (bits 16-23) Lock State (CAPS, Num, Scroll)\r
31 ;Hi Byte   (bits 24-31) Key Source (Bit 1 Set = Key From Numeric Pad)\r
32 ;\r
33 KBDSvcName      DB 'KEYBOARD'\r
34 \r
35 KbdMainExch     DD 0                    ;Used by the Kbd Process\r
36 KbdHoldExch DD 0                        ;Used for requestors that don't own the keyboard\r
37 KbdGlobExch DD 0                        ;Used to hold Global CTRL-ALT requests\r
38 KbdWaitExch DD 0                        ;Used for Kbd Wait-For-Key requests\r
39 KbdTempExch DD 0                        ;Used to rifle thru requests\r
40 \r
41 dGlobalKey      DD 0                    ;Global Key Found, else 0\r
42 dfPrefix        DD 0\r
43 \r
44 KbdMsgBuf1L     DD 0                    ;Message buffers for Kbd Service\r
45 KbdMsgBuf1H     DD 0\r
46 \r
47 KbdMsgBuf2L DD 0\r
48 KbdMsgBuf2H DD 0\r
49 \r
50 KbdOwner                DD 1            ;Current owner of Kbd (Mon is default)\r
51 KbdAbortJob             DD 0            ;Job that is aborting\r
52 KbdCancelJob    DD 0            ;Job that is cancelling global request\r
53 \r
54 rgbKbdBuf   DB 20h DUP (0) ;32 byte RAW buffer\r
55 dKbdCnt     DD 0\r
56 pKbdIn      DD OFFSET rgbKbdBuf         ;ptr to next char going in\r
57 pKbdOut     DD OFFSET rgbKbdBuf         ;ptr to next char going out\r
58 ;\r
59 bKbdMode    DB 0                ;ZERO for Cooked, 1 for RAW (testing)\r
60 fKBDInitDone DB 0                       ;Set true when KBD Service is up and running\r
61 ;\r
62 KbdState    DB 0                ;(See State Masks below)\r
63 KbdLock     DB 0                ;(See Lock Masks below)\r
64 ;\r
65 rgdKBBuf        DD 40h DUP (0)  ;64 Dwords for translated key buffer\r
66 dKBCnt          DD 0\r
67 pKBIn           DD OFFSET rgdKBBuf      ;ptr to codes comming in\r
68 pKBOut      DD OFFSET rgdKBBuf  ;ptr to codes going out\r
69 ;\r
70 ; These "masks" are for keyboard states that change with special keys:\r
71 ; They are BIT OFFSETS and NOT MASKS for logical operations!!!!!\r
72 \r
73 CtrlLeftBit    EQU 0\r
74 CtrlRiteBit    EQU 1\r
75 ShftLeftBit    EQU 2\r
76 ShftRiteBit    EQU 3\r
77 AltLeftBit     EQU 4\r
78 AltRiteBit     EQU 5\r
79 ;\r
80 ; Mask to tell if one of the 3 states exist (Ctrl, Shift, Alt)\r
81 CtrlDownMask    EQU 00000011b\r
82 ShftDownMask    EQU 00001100b\r
83 AltDownMask             EQU 00110000b\r
84 ;\r
85 ; BIT OFFSETS\r
86 CpLockBit      EQU 2\r
87 NmLockBit      EQU 1\r
88 ScLockBit      EQU 0\r
89 ; MASKS\r
90 CpLockMask     DB 00000100b\r
91 NmLockMask     DB 00000010b\r
92 ScLockMask     DB 00000001b\r
93 \r
94 ;\r
95 ; The following special keys are processed by the Keyboard Task and handled\r
96 ; as follows:\r
97 ; NUMLOCK  - Lights NumLock LED and processes keys accordingly\r
98 ; SHIFT    - Sets shift flag and processes keys accordingly\r
99 ; CTRL     - Sets Ctrl flag\r
100 ; CAPSLOCK - Lights CapsLock LED and processes keys accordingly\r
101 ; ALT      - Sets Alt flag.\r
102 ; SCRLLOCK - Lights ScrollLock LED and flag\r
103 ;\r
104 ; This table is used to translate all active editing keys from\r
105 ; the raw value provided by the hardware.\r
106 ;\r
107 ;                                                               SHIFT\r
108 ;                                                               Value\r
109 KbdTable DB 0;                  00\r
110 DB      01Bh     ;  Esc         01\r
111 DB      031h     ;  1           02              21h  !\r
112 DB      032h     ;  2           03              40h  @\r
113 DB      033h     ;  3           04              23h  #\r
114 DB      034h     ;  4           05              24h  $\r
115 DB      035h     ;  5           06              25h  %\r
116 DB      036h     ;  6           07              5Eh  ^\r
117 DB      037h     ;  7           08              26h  &\r
118 DB      038h     ;  8           09              2Ah  *\r
119 DB      039h     ;  9           0A              28h  (\r
120 DB      030h     ;  0           0B              29h  )\r
121 DB      02Dh     ;  -           0C              5Fh  _\r
122 DB      03Dh     ;  =           0D              2Bh  +\r
123 DB      008h     ;  BkSpc       0E\r
124 DB      009h     ;  TAB         0F\r
125 DB      071h     ;  q           10              51h\r
126 DB      077h     ;  w           11              57h\r
127 DB      065h     ;  e           12              45h\r
128 DB      072h     ;  r           13              52h\r
129 DB      074h     ;  t           14              54h\r
130 DB      079h     ;  y           15              59h\r
131 DB      075h     ;  u           16              55h\r
132 DB      069h     ;  i           17              49h\r
133 DB      06Fh     ;  o           18              4Fh\r
134 DB      070h     ;  p           19              50h\r
135 DB      05Bh     ;  [           1A              7Bh\r
136 DB      05Dh     ;  ]           1B              7Dh\r
137 DB      00Dh     ;  CR          1C\r
138 DB      0h               ;  LCtrl       1D    Special handling\r
139 DB      061h     ;  a           1E              41h\r
140 DB      073h     ;  s           1F              53h\r
141 DB      064h     ;  d           20              44h\r
142 DB      066h     ;  f           21              46h\r
143 DB      067h     ;  g           22              47h\r
144 DB      068h     ;  h           23              48h\r
145 DB      06Ah     ;  j           24              4Ah\r
146 DB      06Bh     ;  k           25              4Bh\r
147 DB      06Ch     ;  l (L)       26              4Ch\r
148 DB      03Bh     ;  ;           27              3Ah\r
149 DB      027h     ;  '           28              22h\r
150 DB      060h     ;  `           29              7Eh\r
151 DB      0h               ;  LfShf       2A    Special handling\r
152 DB      05Ch     ;  \           2B              7Ch\r
153 DB      07Ah     ;  z           2C              5Ah\r
154 DB      078h     ;  x           2D              58h\r
155 DB      063h     ;  c           2E              43h\r
156 DB      076h     ;  v           2F              56h\r
157 DB      062h     ;  b           30              42h\r
158 DB      06Eh     ;  n           31              4Eh\r
159 DB      06Dh     ;  m           32              4Dh\r
160 DB      02Ch     ;  ,           33              3Ch\r
161 DB      02Eh     ;  .           34              3Eh\r
162 DB      02Fh     ;  /           35              3Fh\r
163 DB      0h               ;  RtShf       36    Special handling\r
164 DB      02Ah     ;  Num *       37              Num pad\r
165 DB      0h               ;  LAlt        38    Special handling\r
166 DB      020h     ;  Space       39\r
167 DB      0h               ;  CpsLk       3A    Special handling\r
168 DB      00Fh     ;  F1          3B\r
169 DB      010h     ;  F2          3C\r
170 DB      011h     ;  F3          3D\r
171 DB      012h     ;  F4          3E\r
172 DB      013h     ;  F5          3F\r
173 DB      014h     ;  F6          40\r
174 DB      015h     ;  F7          41\r
175 DB      016h     ;  F8          42\r
176 DB      017h     ;  F9          43\r
177 DB      018h     ;  F10         44\r
178 DB      0h               ;  NumLk       45   Special handling\r
179 DB      0h               ;  ScrLk       46   Special handling\r
180 DB      086h     ;  Num 7       47              37h             Num Home\r
181 DB      081h     ;  Num 8       48              38h             Num Up\r
182 DB      085h     ;  Num 9       49              39h             Num Pg Up\r
183 DB      0ADh     ;  Num -       4A                              Num Pad\r
184 DB      083h     ;  Num 4       4B              34h             Num Left\r
185 DB      09Fh     ;  Num 5       4C              35h             Num (Extra code)\r
186 DB      084h     ;  Num 6       4D              36h             Num Right\r
187 DB      0ABh     ;  Num +       4E                              Num Pad\r
188 DB      08Bh     ;  Num 1       4F              31h             Num End\r
189 DB      082h     ;  Num 2       50              32h             Num Down\r
190 DB      08Ch     ;  Num 3       51              33h             Num Pg Dn\r
191 DB      08Eh     ;  Num 0       52              30h             Num Insert\r
192 DB      0FFh     ;  Num .       53              2Eh             Num Del\r
193 DB      01Ch     ;  Pr Scr      54                      SYS REQUEST\r
194 DB      000h     ;              55\r
195 DB      000h     ;              56\r
196 DB      019h     ;  F11         57\r
197 DB      01Ah     ;  F12         58\r
198 DB      000h     ;                      59\r
199 DB      000h     ;                      5A\r
200 DB      000h     ;                      5B\r
201 DB      000h     ;                      5C\r
202 DB      000h     ;                      5D\r
203 DB      000h     ;                      5E\r
204 DB      000h     ;                      5F   ;The following chars are subs from table2\r
205 DB      00Eh     ;  Ins         60      Cursor pad\r
206 DB      00Bh     ;  End         61      Cursor pad\r
207 DB      002h     ;  Down        62      Cursor pad\r
208 DB      00Ch     ;  PgDn        63      Cursor pad\r
209 DB      003h     ;  Left        64      Cursor pad\r
210 DB      000h     ;              65\r
211 DB      004h     ;  Right       66      Cursor pad\r
212 DB      006h     ;  Home        67      Cursor pad\r
213 DB      001h     ;  Up          68      Cursor pad\r
214 DB      005h     ;  PgUp        69      Cursor pad\r
215 DB      07Fh     ;  Delete  6A  Cursor pad\r
216 DB      0AFh     ;  /           6B  Num Pad\r
217 DB      08Dh     ;  ENTER       6C  Num Pad\r
218 DB      0h               ;                      6D\r
219 DB  0h           ;              6E\r
220 DB  0h           ;                      6F\r
221 DB  0h           ;                      70\r
222 DB  0h           ;                      71\r
223 DB  0h           ;                      72\r
224 DB  0h           ;                      73\r
225 DB  0h           ;                      74\r
226 DB  0h           ;                      75\r
227 DB  0h           ;                      76\r
228 DB  0h           ;                      77\r
229 DB  0h           ;                      78\r
230 DB  0h           ;                      79\r
231 DB  0h           ;                      7A\r
232 DB  0h           ;                      7B\r
233 DB  0h           ;                      7C\r
234 DB  0h           ;                      7D\r
235 DB  0h           ;                      7E\r
236 DB  0h           ;                      7F\r
237 ;\r
238 ;This table does an initial character translation from the characters\r
239 ;provided by the keyboard.  The Kbd translates incoming keystrokes\r
240 ;from the original scan set 2 for the IBM PC.  All PCs are are set to this\r
241 ;by default.  Keys on the 101 keyboard that were common to the numeric\r
242 ;keypad use a two character escape sequence begining with E0 hex.\r
243 ;If we see an E0 hex we scan this table and provide the translation\r
244 ;to another unique character which is looked up in the primary\r
245 ;table above.  This gives us unique single characters for every key.\r
246 ;\r
247 nKbdTable2 EQU 16\r
248 ;\r
249 KbdTable2 DB 052h,  060h    ;Insert\r
250                   DB 04Fh,  061h    ;End\r
251                   DB 050h,  062h    ;Down\r
252                   DB 051h,  063h    ;Pg Down\r
253                   DB 04Bh,  064h    ;Left\r
254                   DB 04Dh,  066h    ;Rite\r
255                   DB 047h,  067h    ;Home\r
256                   DB 048h,  068h    ;Up\r
257                   DB 049h,  069h    ;Pg Up\r
258                   DB 053h,  06Ah    ;Delete\r
259 \r
260                   DB 037h,  06Bh    ;Num /\r
261                   DB 01Ch,  06Ch    ;Num ENTER\r
262 \r
263                   DB 038h,  070h    ;Right ALT DOWN         These are special cause we\r
264                   DB 01Dh,  071h    ;Right Ctrl DOWN    track UP & DOWN!!!\r
265                   DB 0B8h,  0F0h    ;Right ALT UP\r
266                   DB 09Dh,  0F1h    ;Right Ctrl UP\r
267 \r
268 \r
269 ;This table provides shift level values for codes from the primary KbdTable.\r
270 ;In Shift-ON state, keycodes 21 - 7E hex are translated through this table.\r
271 ;In CAPS LOCK state, codes 61h to 7Ah are translated through this table\r
272 ;In NUM LOCK state, codes with High Bit set are translated\r
273 ;\r
274 \r
275 KbdTableS DB 0; 00\r
276 DB      38h             ;       01  Up   8  Numeric pad\r
277 DB      32h             ;       02  Dn   2  Numeric pad\r
278 DB      34h             ;       03  Left 4  Numeric pad\r
279 DB      36h             ;       04  Rite 6  Numeric pad\r
280 DB      39h             ;       05  PgUp 9  Numeric pad\r
281 DB      37h             ;       06  Home 7  Numeric pad\r
282 DB      07h             ;       07\r
283 DB      08h             ;       08\r
284 DB      09h             ;       09\r
285 DB      0Ah             ;       0A\r
286 DB      31h             ;       0B  End  1  Numeric Pad\r
287 DB      33h             ;       0C  PgDn 3  Numeric pad\r
288 DB      0Dh             ;       0D\r
289 DB      30h             ;       0E  Ins  0  Numeric pad\r
290 DB      0Fh             ;       0F\r
291 DB      10h             ;       10\r
292 DB      11h             ;       11\r
293 DB      12h             ;       12\r
294 DB      13h             ;       13\r
295 DB      14h             ;       14\r
296 DB      15h             ;       15\r
297 DB      16h             ;       16\r
298 DB      17h             ;       17\r
299 DB      18h             ;       18\r
300 DB      18h             ;       19\r
301 DB      1Ah             ;       1A\r
302 DB      1Bh             ;       1B\r
303 DB      1Ch             ;       1C\r
304 DB      1Dh             ;       1D\r
305 DB      1Eh             ;       1E\r
306 DB      35h             ;       1F      Blnk 5  Numeric pad\r
307 DB      20h             ;       20\r
308 DB      21h             ;       21\r
309 DB      22h             ;       22\r
310 DB      23h             ;       23\r
311 DB      24h             ;       24\r
312 DB      25h             ;       25\r
313 DB      26h             ;       26\r
314 DB      22h             ;       27  '  "\r
315 DB      28h             ;       28\r
316 DB      29h             ;       29\r
317 DB      2Ah             ;       2A\r
318 DB      2Bh             ;       2B\r
319 DB      3Ch             ;       2C  ,  <\r
320 DB      5Fh             ;       2D  -  _\r
321 DB      3Eh             ;       2E  .  >\r
322 DB      3Fh             ;       2F  /  ?\r
323 DB      29h             ;       30  0  )\r
324 DB      21h             ;       31  1  !\r
325 DB      40h             ;       32  2  @\r
326 DB      23h             ;       33  3  #\r
327 DB      24h             ;       34  4  $\r
328 DB      25h             ;       35  5  %\r
329 DB      5Eh             ;       36  6  ^\r
330 DB      26h             ;       37  7  &\r
331 DB      2Ah             ;       38  8  *\r
332 DB      28h             ;       39  9  (\r
333 DB      3Ah             ;       3A\r
334 DB      3Ah             ;       3B  ;  :\r
335 DB      3Ch             ;       3C\r
336 DB      2Bh             ;       3D  =  +\r
337 DB      3Eh             ;       3E\r
338 DB      3Fh             ;       3F\r
339 DB      40h             ;       40\r
340 DB      41h             ;       41\r
341 DB      42h             ;       42\r
342 DB      43h             ;       43\r
343 DB      44h             ;       44\r
344 DB      45h             ;       45\r
345 DB      46h             ;       46\r
346 DB      47h             ;       47\r
347 DB      48h             ;       48\r
348 DB      49h             ;       49\r
349 DB      4Ah             ;       4A\r
350 DB      4Bh             ;       4B\r
351 DB      4Ch             ;       4C\r
352 DB      4Dh             ;       4D\r
353 DB      4Eh             ;       4E\r
354 DB      4Fh             ;       4F\r
355 DB      50h             ;       50\r
356 DB      51h             ;       51\r
357 DB      52h             ;       52\r
358 DB      53h             ;       53\r
359 DB      54h             ;       54\r
360 DB      55h             ;       55\r
361 DB      56h             ;       56\r
362 DB      57h             ;       57\r
363 DB      58h             ;       58\r
364 DB      59h             ;       59\r
365 DB      5Ah             ;       5A\r
366 DB      7Bh             ;       5B  [  {\r
367 DB      7Ch             ;       5C  \  |\r
368 DB      7Dh             ;       5D  ]  }\r
369 DB      5Eh             ;       5E\r
370 DB      5Fh             ;       5F\r
371 DB      7Eh             ;       60  `  ~\r
372 DB      41h             ;       61  a  A\r
373 DB      42h             ;       62      b  B\r
374 DB      43h             ;       63      c  C\r
375 DB      44h             ;       64      d  D\r
376 DB      45h             ;       65      e  E\r
377 DB      46h             ;       66      f  F\r
378 DB      47h             ;       67      g  G\r
379 DB      48h             ;       68      h  H\r
380 DB      49h             ;       69      i  I\r
381 DB      4Ah             ;       6A      j  J\r
382 DB      4Bh             ;       6B      k  K\r
383 DB      4Ch             ;       6C      l  L\r
384 DB      4Dh             ;       6D      m  M\r
385 DB      4Eh             ;       6E      n  N\r
386 DB      4Fh             ;       6F      o  O\r
387 DB      50h             ;       70      p  P\r
388 DB      51h             ;       71      q  Q\r
389 DB      52h             ;       72      r  R\r
390 DB      53h             ;       73      s  S\r
391 DB      54h             ;       74      t  T\r
392 DB      55h             ;       75      u  U\r
393 DB      56h             ;       76      v  V\r
394 DB      57h             ;       77  w  W\r
395 DB      58h             ;       78  x  X\r
396 DB      59h             ;       79  y  Y\r
397 DB      5Ah             ;       7A  z  Z\r
398 DB      7Bh             ;       7B\r
399 DB      7Ch             ;       7C\r
400 DB      7Dh             ;       7D\r
401 DB      7Eh             ;       7E\r
402 DB      2Eh             ;       7F      Del  .  Numeric Pad\r
403 \r
404 \r
405 KbdSvcStack     DD 255 DUP(0)   ;1024 byte stack for KbsSvc\r
406 KbdSvcStackTop  DD 0\r
407 \r
408 ;=============================================================================\r
409 ;The following equates are for the hardware handling code.\r
410 ;8042 Status Byte, Port Hex 0064 Read\r
411 ;=============================================================================\r
412 \r
413 STATUSPORT              EQU 64h\r
414 COMMANDPORT             EQU 64h\r
415 DATAPORT                EQU 60h\r
416 \r
417 PARITYERROR             EQU 10000000b\r
418 GENERALTIMEOUT  EQU 01000000b\r
419 AUXOUTBUFFFULL  EQU 00100000b\r
420 INHIBITSWITCH   EQU 00010000b\r
421 COMMANDDATA             EQU 00001000b\r
422 SYSTEMFLAG              EQU 00000100b\r
423 INPUTBUFFFULL   EQU 00000010b\r
424 OUTPUTBUFFFULL  EQU 00000001b\r
425 \r
426 \r
427 ;==================Begin Keyboard Code ===================\r
428 \r
429 .CODE\r
430 ;\r
431 ;\r
432 ;ISR for the keyboard.  This is vectored to by the processor whenever\r
433 ;INT 21 fires off.  This puts the single byte from the 8042\r
434 ;KBD processor into the buffer.  Short and sweet the way all ISRs\r
435 ;should be... (most are not this easy though).  This also sends\r
436 ;a message to the KBD Task (using ISend) when the buffer is almost\r
437 ;full so it will be forced to process some of the raw keys even\r
438 ;if no keyboard requests are waiting.\r
439 \r
440 PUBLIC IntKeyBrd:                                       ;Key Board (KB) INT 21\r
441             PUSHAD                                              ;Save all registers\r
442             MOV ESI, pKbdIn                             ;Set up pointer\r
443             XOR EAX,EAX\r
444             IN  AL, 60h                                 ;Read byte\r
445             MOV EBX, dKbdCnt                    ;See if buffer full\r
446             CMP EBX, 20h                                ;Buffer size\r
447             JE KbdEnd                           ;Buffer is full - Don't save it\r
448             MOV BYTE PTR [ESI], AL                      ;Move into buf\r
449             INC dKbdCnt                                         ;One more in the buf\r
450             INC ESI                                                     ;Next byte in\r
451             CMP ESI, OFFSET rgbKbdBuf+20h       ;past end yet?\r
452             JB KbdEnd\r
453             MOV ESI, OFFSET rgbKbdBuf   ;Back to beginning of buffer\r
454 KbdEnd:\r
455             MOV pKbdIn, ESI                             ;Set up pointer for next time\r
456 \r
457                 CMP BYTE PTR fKBDInitDone, 0  ;Service isn't ready for messages yet\r
458                 JE KbdExit\r
459 \r
460                 ;ISend a msg to Keyboard task\r
461                 MOV EBX, KbdMainExch            ;Yes - ISend Message to KbdTask\r
462                 PUSH EBX                    ;exchange to send to\r
463                 PUSH 0FFFFFFFFh             ;bogus msg\r
464                 PUSH 0FFFFFFFFh             ;bogus msg\r
465                 CALL FWORD PTR _ISendMsg                ;tell him to come and get it...\r
466 KbdExit:\r
467                 PUSH 1\r
468                 CALL FWORD PTR _EndOfIRQ\r
469             POPAD\r
470             IRETD\r
471 \r
472 ;===============================================\r
473 ;This gets one byte from the Kbd Buffer and returns it in AL\r
474 ;Zero is returned if no key exists.\r
475 ;\r
476 ReadKBDBuf:\r
477                 CLI\r
478             MOV ESI, pKbdOut            ;Get ptr to next char to come out\r
479             MOV EAX, dKbdCnt            ;See if there are any bytes\r
480             CMP EAX, 0\r
481             JE RdKBDone                         ;No - Leave 0 in EAX\r
482             DEC dKbdCnt                         ;Yes - make cnt right\r
483             XOR EAX,EAX\r
484             MOV AL, BYTE PTR [ESI]                      ;Put byte in AL\r
485             INC ESI\r
486             CMP ESI, OFFSET rgbKbdBuf+20h       ;past end yet?\r
487             JB RdKBDone\r
488             MOV ESI, OFFSET rgbKbdBuf   ;Back to beginning of buffer\r
489 RdKBDone:\r
490             MOV pKbdOut, ESI                    ;Save ptr to next char to come out\r
491             STI\r
492                 RETN\r
493 ;\r
494 ;========================================================\r
495 ;\r
496 ; Reads and processes all bytes from the RAW keyboard buffer\r
497 ; and places them and their proper state bytes and into the next DWord\r
498 ; in the translated buffer if it is an edit key.\r
499 \r
500 XLateRawKBD:\r
501             CALL ReadKbdBuf\r
502             CMP EAX, 0\r
503             JE XLateDone                        ;No\r
504 \r
505             MOV BL, bKbdMode            ;See if we are RAW... (for testing ONLY)\r
506             CMP BL, 1\r
507             JNE KB001                           ;NO - keep going\r
508             JMP KB029A                          ;Yes, leave the key in AL for buffer\r
509 \r
510                 ;Now we check to see if the byte is 0Eh which tells us\r
511                 ;this is a two key code that needs to be translated from\r
512                 ;our special table before processing.  This turns the\r
513                 ;two key code into a single code and sets a state\r
514                 ;bit to indicate this.\r
515 \r
516 KB001:\r
517                 CMP dfPrefix, 1\r
518                 JE KB003\r
519             CMP AL, 0E0h                        ;Key PREFIX???\r
520                 JNE KB006                               ;No\r
521         MOV dfPrefix, 1                 ;Yes, We got an E0\r
522             JMP XLateDone                       ;\r
523 \r
524 KB003:\r
525         MOV dfPrefix, 0                 ;No prefix\r
526             MOV ESI, OFFSET KbdTable2\r
527             MOV ECX, nKbdTable2\r
528 KB004:\r
529             CMP BYTE PTR [ESI], AL\r
530             JE  KB005\r
531             INC ESI                                     ;Two byte further into table 2\r
532             INC ESI\r
533             DEC ECX\r
534             JNZ KB004                           ;Go to next table entry\r
535             JMP XLateDone                       ;No translation - ignore it\r
536 \r
537 KB005:\r
538             INC ESI                                     ;One byte further over to get Xlate byte\r
539             XOR EAX,EAX\r
540             MOV AL, [ESI]                       ;Fall thru to check on char...\r
541 \r
542       ;This next section checks for special keys (shift, alt, etc.)\r
543       ;BL has SHIFT state, CL has LOCK State, AL has byte from buffer.\r
544 \r
545 KB006:\r
546         MOV dfPrefix, 0                 ;No prefix\r
547             XOR EBX, EBX\r
548             XOR ECX, ECX\r
549             MOV BL, KbdState            ;BL has Shift, Alt, Ctrl states\r
550             MOV CL, KbdLock                     ;BH has Num, Caps, & Scroll Lock\r
551 \r
552             CMP AL, 45h                         ;Key = NumLock ?\r
553             JNE KB007                           ;NO...\r
554             BTC ECX, NmLockBit          ;Compliment bit\r
555             JMP KB022\r
556 KB007:\r
557             CMP AL, 3Ah                         ;Caps Lock?\r
558             JNE KB008\r
559             BTC ECX, CpLockBit          ;Compliment bit in BH\r
560             JMP KB022\r
561 KB008:\r
562             CMP AL, 46h                         ;Scroll Lock?\r
563             JNE KB009\r
564             BTC ECX, ScLockBit          ;Compliment bit in BH\r
565             JMP KB022\r
566 KB009:\r
567             CMP AL, 2Ah                         ;Char Left Shift On?\r
568             JNE KB010\r
569             BTS EBX, ShftLeftBit\r
570             JMP KB021\r
571 KB010:\r
572             CMP AL, 36h                         ;Right Shift On?\r
573             JNE KB011\r
574             BTS EBX, ShftRiteBit\r
575             JMP KB021\r
576 KB011:\r
577             CMP AL, 0AAh                        ;Left Shift Off?\r
578             JNE KB012\r
579             BTR EBX, ShftLeftBit\r
580             JMP KB021\r
581 \r
582 KB012:\r
583             CMP AL, 0B6h                        ;Right Shift Off?\r
584             JNE KB013\r
585             BTR EBX, ShftRiteBit\r
586             JMP KB021\r
587 \r
588 KB013:\r
589             CMP AL, 1Dh                         ;Left Ctrl On?\r
590             JNE KB014\r
591             BTS EBX, CtrlLeftBit\r
592             JMP KB021\r
593 \r
594 KB014:\r
595             CMP AL, 71h                         ;Right Ctrl On?\r
596             JNE KB015\r
597             BTS EBX, CtrlRiteBit\r
598             JMP KB021\r
599 \r
600 KB015:\r
601             CMP AL, 09Dh                        ;Left Ctrl Off?\r
602             JNE KB016\r
603             BTR EBX, CtrlLeftBit\r
604             JMP KB021\r
605 \r
606 KB016:\r
607             CMP AL, 0F1h                        ;Right Ctrl Off?\r
608             JNE KB017\r
609             BTR EBX, CtrlRiteBit\r
610             JMP KB021\r
611 KB017:\r
612             CMP AL, 38h                         ;Left Alt On?\r
613             JNE KB018\r
614             BTS EBX, AltLeftBit\r
615             JMP KB021\r
616 KB018:\r
617             CMP AL, 70h                         ;Right Alt On?\r
618             JNE KB019\r
619             BTS EBX, AltRiteBit\r
620             JMP KB021\r
621 KB019:\r
622             CMP AL, 0B8h                        ;Left Alt Off?\r
623             JNE KB020\r
624             BTR EBX, AltLeftBit\r
625             JMP KB021\r
626 KB020:\r
627             CMP AL, 0F0h                        ;Right Alt Off?\r
628             JNE KB023\r
629             BTR EBX, AltRiteBit\r
630 KB021:\r
631             MOV KbdState, BL            ;Put Kbd Shift State back\r
632             JMP XLateDone                       ;\r
633 KB022:\r
634             MOV KbdLock, CL                     ;Put Kbd Lock State back\r
635             CALL SetKbdLEDS                     ;Set LEDs on keyboard\r
636             JMP XLateRawKBD                     ;\r
637 \r
638                 ;We jumped here if it wasn't a key that is specially handled\r
639 \r
640 KB023:\r
641             TEST AL,  80h                       ;Check for high bit (key-up code)\r
642             JNZ  XLateDone                      ;Go back, else fall through\r
643 \r
644             OR AL,AL                            ;Zero not a valid code\r
645             JZ XLateDone                        ;Go back, else fall through\r
646 \r
647        ;If we got here, IT'S AN EDIT KEY DOWN!\r
648        ;Now we lookup the code and do a single translation.\r
649 \r
650             AND EAX, 07Fh                               ;Chop off any upper bit junk\r
651             MOV ESI, OFFSET KbdTable    ;Set up to index table\r
652             MOV DL, BYTE PTR [ESI+EAX]  ;Save in DL\r
653             OR AL,AL                                    ;Zero not a valid code\r
654             JZ XLateDone                                ;Go back, else fall through\r
655 \r
656             MOV CL, KbdState                    ;Get Shift state\r
657             MOV CH, KbdLock                             ;Get lock state\r
658 \r
659                 ;TO let the user know if the key came from the Numeric\r
660                 ;keypad we set the high bits in the first translation\r
661                 ;table for these keys.  This next piece of code tests for it\r
662                 ;and sets the low bit in DH if it its. DH is later moved\r
663                 ;into the high byte of the returned key code.\r
664 \r
665                 MOV DH, 0\r
666                 TEST DL, 80h                            ;High bit set?\r
667                 JZ SHORT KB024\r
668                 MOV DH, 1                                       ;Indicates key came numeric pad\r
669 \r
670                 ;See if shift key is down and shift all keys it is is\r
671 KB024:\r
672                 TEST CL, ShftDownMask           ;Either shift key down?\r
673                 JZ KB025                                        ;No, go look for locks\r
674                 CMP DL, 21h                                     ;Is key < ' '\r
675                 JB KB025                                        ;Yes, look for locks\r
676                 CMP DL, 7Eh                                     ;Is key > '~'\r
677                 JA KB025                                        ;Yes, look for locks\r
678                 JMP SHORT KB027                         ;In-range, go do the translation\r
679 \r
680 KB025:  ;See if key is from Numerc Keypad (high bit will be set)\r
681 \r
682                 TEST DL, 80h                            ;High bit set?\r
683                 JZ KB026                                        ;No\r
684                 AND CH, NmLockMask                      ;Yes, is NumLock ON\r
685                 JZ KB026                                        ;No\r
686                 CMP DL, 0ADh                            ;Yes, but don't shift DASH (-) Special Case\r
687                 JE KB026\r
688                 JMP SHORT KB027                         ;Do the shift Xlation\r
689 \r
690 KB026:  ;See if Caps Lock is on and if key is between 61h and 7Ah\r
691                 ;do the translation\r
692 \r
693                 TEST CH, CpLockMask                     ;Is CpLock ON\r
694                 JZ KB029                                        ;No\r
695                 CMP DL, 61h                                     ;Is key >= 'a'\r
696                 JB KB029                                        ;No\r
697                 CMP DL, 7Ah                                     ;Is key <= 'z'\r
698                 JA KB029                                        ;No\r
699                 ;Fall through to do the translation\r
700 \r
701 KB027:  ;Do the shift translation and leave in DL\r
702                 MOV     AL, DL                                  ;Put in AL\r
703                 AND EAX, 07Fh                           ;Chop all above 7 bits\r
704             MOV ESI, OFFSET KbdTableS   ;Set up to index table\r
705             MOV DL, BYTE PTR [ESI+EAX]  ;Save in DL\r
706                 ;Fall though to put key in final buffer\r
707 \r
708        ;Place DL in the LOW byte of the DWord to go into the\r
709        ;final buffer (the data the user will get)\r
710        ;If the high bit is set coming from the primary\r
711        ;translation table, this means the key was from the\r
712        ;numeric keypad so we set the numpad bit in status\r
713        ;which should already be in DH\r
714 KB029:\r
715                 MOV AH, DH\r
716                 SHL EAX, 8                              ;Num Pad indicator\r
717             MOV AL, KbdState            ;Get Shift state\r
718             MOV AH, KbdLock                     ;Get lock state\r
719             SHL EAX, 8\r
720                 AND DL, 7Fh                             ;Lop of high bit (if there)\r
721             MOV AL, DL\r
722 \r
723                 ;EAX now has the buffered info for the user (Key, Shifts & Locks)\r
724                 ;Now we put it in the DWord buffer if it is NOT a GLOBAL.\r
725                 ;If global, we put it in dGlobalKey.\r
726 \r
727                 TEST AH, CtrlDownMask           ;Either Ctrl Down?\r
728                 JZ KB029A                                       ;No\r
729                 TEST AH, AltDownMask            ;Either Alt Down?\r
730                 JZ KB029A                                       ;No\r
731 \r
732                 ;It IS a global key request!\r
733                 MOV dGlobalKey, EAX                     ;Save it\r
734             JMP  XLateRawKBD                    ;Back for more (if there is any)\r
735 \r
736 KB029A:\r
737             MOV  EBX, dKBCnt                    ;See if buffer full\r
738             CMP  EBX, 64                                ;number of DWords in final buffer\r
739             JE   XLateDone                              ;Buffer is FULL..\r
740             MOV  ESI, pKBIn                             ;Get ptr to next IN to final buffer\r
741             MOV  [ESI], EAX                             ;Move into buf\r
742             INC  dKBCnt                                 ;One more DWord in the buf\r
743                 ADD  ESI, 4\r
744             CMP  ESI, OFFSET rgdKBBuf+100h ;40h * 4\r
745             JB   KB030\r
746             MOV  ESI, OFFSET rgdKBBuf   ;Reset to buf beginning\r
747 KB030:\r
748             MOV  pKBIn, ESI                     ;Save ptr to next in\r
749             JMP  XLateRawKBD\r
750 XlateDone:\r
751                 XOR EAX, EAX\r
752             RETN\r
753 \r
754 ;========================================================\r
755 ;\r
756 ; Returns a keyboard code from FINAL keyboard buffer.\r
757 ; Returns zero in EAX if buffer is empty.\r
758 ;\r
759 ; IN :  Nothing\r
760 ; OUT:  EAX has Key or 0 if none\r
761 ; USED: EAX, ESI\r
762 ; MODIFIES: dKBCnt, pKBOut\r
763 ;\r
764 ReadKBFinal:\r
765                 MOV EAX, dKBCnt\r
766                 CMP EAX, 0\r
767                 JE KBFDone                                      ;Nothing final buffer\r
768             DEC dKBCnt                                  ;One more DWord in the buf\r
769                 MOV ESI, pKBOut                         ;ptr to next code out\r
770                 MOV EAX, [ESI]                          ;Put it in EAX\r
771                 ADD ESI, 4                                      ;Next code please...\r
772             CMP ESI, OFFSET rgdKBBuf+100h       ;Past end of buff?\r
773             JB  KBF02                                   ;No\r
774             MOV ESI, OFFSET rgdKBBuf    ;Yes, Reset to beginning\r
775 KBF02:\r
776             MOV pKBOut, ESI                             ;Update pKBOut\r
777 KBFDone:\r
778             RETN\r
779 \r
780 ;========================================================\r
781 ;\r
782 ; This is the keyboard Service task. It is an infinite loop\r
783 ; that services requests from users of the keyboard.  It\r
784 ; calls XLateRawKBD to process raw keyboard buffer data,\r
785 ; and waits at the KeyBoard Service Main Exchange for users.\r
786 ; When it gets a request it checks the service code and handles\r
787 ; it accordingly.\r
788 \r
789 KBDServiceTask:\r
790                 CALL XLateRawKBD                        ;Processes RAW buffer if not empty\r
791 \r
792                 CMP DWORD PTR dGlobalKey, 0\r
793                 JE  KST01                                       ;No global key came in\r
794 KBDGlobal1:\r
795                 PUSH KbdGlobExch\r
796                 PUSH OFFSET KbdMsgBuf1L         ;Where to return pRqBlk\r
797                 CALL FWORD PTR _CheckMsg        ;Check to see if RqWaiting\r
798                 OR EAX, EAX                                     ;Yes if ZERO\r
799                 JZ KBDGlobal2                           ;Rq waiting for global\r
800                 MOV DWORD PTR dGlobalKey, 0     ;Wipe out global key (no one wants it)\r
801                 JMP KBDServiceTask                      ;Start over again\r
802 \r
803 KBDGlobal2:\r
804                 MOV EBX, KbdMsgBuf1L            ;pRqBlk into EBX\r
805                 MOV ESI, [EBX+pData1]           ;Ptr where to return key\r
806                 OR ESI, ESI                                     ;Is it null?? (Bad news if so)\r
807                 JNZ KBDGlobal3                          ;No, probably good ptr\r
808                 PUSH EBX                                        ;Yes, BAD PTR. Push pRqBlk\r
809                 PUSH ErcNullPtr                         ;Push error\r
810                 CALL FWORD PTR _Respond\r
811                 JMP KBDServiceTask                      ;Go back to the top\r
812 KBDGlobal3:\r
813                 MOV EDX, dGlobalKey\r
814                 MOV [ESI], EDX                          ;Give em the key!\r
815                 PUSH EBX                                        ;Push pRqBlk\r
816                 PUSH 0                                          ;Push NO ERROR\r
817                 CALL FWORD PTR _Respond\r
818                 JMP KBDGlobal1                          ;Go back to see if others want it\r
819 \r
820 KST01:\r
821                 CMP DWORD PTR ddVidOwner, 2     ;Debugger has video\r
822                 JNE     KST01ND                                 ;NOT in Debugger\r
823                 PUSH 20\r
824                 CALL FWORD PTR _Sleep           ;\r
825                 CALL XLateRawKBD                        ;Processes RAW buffer\r
826                 JMP KBDServiceTask                      ;Go back to the top\r
827 \r
828 KST01ND:\r
829                 PUSH KbdMainExch                        ;See if someones "Requesting"\r
830                 PUSH OFFSET KbdMsgBuf1L         ;\r
831                 CALL FWORD PTR _WaitMsg         ;Wait for the message\r
832 \r
833                 ;If we got here, we have a Request or a Msg the from ISR\r
834 \r
835                 CMP DWORD PTR KbdMsgBuf1L, 0FFFFFFFFh   ;Is it a msg from the KBD ISR?\r
836                 JNE KST02                                       ;No, jump to handle Request\r
837 \r
838                 ;If we got here, ISR sent msg to us (something in the buffer)\r
839 \r
840                 CALL XLateRawKBD                        ;Processes RAW buffer\r
841 \r
842                 CMP DWORD PTR dGlobalKey, 0\r
843                 JNE KBDGlobal1                          ;A global key came in\r
844 \r
845                 PUSH KbdWaitExch                        ;See if owner is waiting for a key\r
846                 PUSH OFFSET KbdMsgBuf1L         ;Where to return Request or msg\r
847                 CALL FWORD PTR _CheckMsg        ;\r
848                 OR EAX, EAX\r
849                 JNZ KBDServiceTask                      ;No Rq/Msg waiting, Go back to the top,\r
850                                                                         ;or fall thru to check the request\r
851 \r
852 KST02:\r
853                 ;If we got here we've got a Request from Main or Wait Exch\r
854                 MOV EBX, KbdMsgBuf1L            ;pRqBlk into EBX\r
855                 MOV CX, [EBX+ServiceCode]       ;Save in CX\r
856 \r
857                 CMP CX, 0                                       ;Job Abort Notify\r
858                 JE KSTAbort                                     ;\r
859                 CMP CX, 1                                       ;ReadKbd\r
860                 JE KSTRead                                      ;\r
861                 CMP CX, 2                                       ;ReadKbdGlobal\r
862                 JE KSTReadGlobal                        ;\r
863                 CMP CX, 3                                       ;CancelGlobal\r
864                 JE KSTCancelGlobal                      ;\r
865                 CMP CX, 4                                       ;AssignKBD\r
866                 JE KSTAssignKbd                         ;\r
867                 PUSH EBX                                        ;HOMEY DON'T SERVICE THAT!\r
868                 PUSH ErcBadSvcCode                      ;Bad service code\r
869                 CALL FWORD PTR _Respond\r
870                 JMP KBDServiceTask                      ;Go back to the top\r
871 \r
872 ;-------------------------------------------------------\r
873 KSTRead:\r
874                 MOV EAX, [EBX+RqOwnerJob]       ;Whose Request is it?\r
875                 CMP EAX, KbdOwner\r
876                 JE KSTRead00                            ;This guy owns it!\r
877                 PUSH EBX                                        ;Not the owner, so send to Hold Exch\r
878                 PUSH KbdHoldExch                        ;\r
879                 CALL FWORD PTR _MoveRequest\r
880                 JMP KBDServiceTask                      ;Go back to the top\r
881 KSTRead00:\r
882                 CALL ReadKBFinal                        ;Get Code from Buf (Uses EAX, ESI)\r
883                 CMP EAX, 0                                      ;No Key in Final Buffer\r
884                 JE KSTRead02                            ;Go see if they asked to wait\r
885                 MOV ESI, [EBX+pData1]           ;Ptr where to return key\r
886                 CMP ESI, 0                                      ;Is it null?? (Bad news if so)\r
887                 JNE KSTRead01                           ;No, probably good ptr\r
888                 PUSH EBX                                        ;Yes, BAD PTR. Push pRqBlk\r
889                 PUSH ErcNullPtr                         ;Push error\r
890                 CALL FWORD PTR _Respond\r
891                 JMP KBDServiceTask                      ;Go back to the top\r
892 KSTRead01:\r
893                 MOV [ESI], EAX                          ;Give them the key code\r
894                 PUSH EBX                                        ;RqHandle\r
895                 PUSH 0                                          ;NO Error\r
896                 CALL FWORD PTR _Respond\r
897                 JMP KBDServiceTask                      ;Go back to the top\r
898 \r
899 KSTRead02:\r
900                 CMP DWORD PTR [EBX+dData0], 0   ;Wait for key?  0 in dData0 = Don't wait\r
901                 JNE KSTRead04                           ;Yes\r
902                 PUSH EBX\r
903                 PUSH ErcNoKeyAvail                      ;Error Code (No key to give you)\r
904                 CALL FWORD PTR _Respond\r
905                 JMP KBDServiceTask                      ;Go back to the top\r
906 \r
907 KSTRead04:\r
908                 PUSH EBX                                        ;They opted to wait for a key\r
909                 PUSH KbdWaitExch                        ;Send em to the wait exch\r
910                 CALL FWORD PTR _MoveRequest\r
911                 JMP KBDServiceTask                      ;Go back to the top\r
912 ;--------------------------------------------------------\r
913 \r
914 KSTAbort:\r
915                 ;Respond to all requests we are holding for Job in dData0\r
916                 ;with Erc with ErcOwnerAbort. Then respond to Abort\r
917                 ;request last. Requests can be at the HoldExch, the WaitExch,\r
918                 ;or the GlobalKeyExch. We must chack all 3!\r
919                 ;Save abort job for comparison\r
920 \r
921                 MOV EAX, [EBX+dData0]           ;Get aborting job number\r
922                 MOV KbdAbortJob, EAX        ;this is aborting job\r
923 \r
924 KSTAbort10:                                                     ;Check the WaitExch\r
925                 PUSH KbdWaitExch                        ;See if he was "waiting" for a key\r
926                 PUSH OFFSET KbdMsgBuf2L         ;Where to return Request\r
927                 CALL FWORD PTR _CheckMsg        ;\r
928                 OR EAX, EAX                                     ;Yes (someone's waiting) if ZERO\r
929                 JNZ     KSTAbort20                              ;No more waiters\r
930                 MOV EDX, KbdMsgBuf2L            ;pRq of holding job into EDX\r
931                 MOV     EBX, [EDX+RqOwnerJob]\r
932                 CMP     EBX, KbdAbortJob\r
933                 JE KSTAbort11                           ;Go to respond with Erc\r
934                 PUSH EDX                                        ;Else move Request to MainKbd Exch\r
935                 PUSH KbdMainExch                        ; to be reevaluated\r
936                 CALL FWORD PTR _MoveRequest\r
937                 JMP KSTAbort10                          ;Go back to look for more waiters\r
938 KSTAbort11:                                                     ;\r
939                 PUSH EDX                                        ;Respond to this request\r
940                 PUSH ErcOwnerAbort                      ;cause he's dead\r
941                 CALL FWORD PTR _Respond\r
942                 JMP SHORT KSTAbort10\r
943 \r
944 KSTAbort20:                                                     ;Check HoldExch for dead job\r
945                 PUSH KbdHoldExch                        ;See if anyone is on hold\r
946                 PUSH OFFSET KbdMsgBuf2L         ;Where to return Request\r
947                 CALL FWORD PTR _CheckMsg        ;\r
948                 OR EAX, EAX                                     ;Yes (someones holding) if ZERO\r
949                 JNZ     KSTAbort30                              ;No more holders\r
950                 MOV EDX, KbdMsgBuf2L            ;pRq of holding job into EDX\r
951                 MOV     EBX, [EDX+RqOwnerJob]\r
952                 CMP     EBX, KbdAbortJob\r
953                 JE KSTAbort21                           ;Go to respond with Erc\r
954                 PUSH EDX                                        ;Else move Request to MainKbd Exch\r
955                 PUSH KbdMainExch                        ; to be reevaluated. It's not him.\r
956                 CALL FWORD PTR _MoveRequest\r
957                 JMP KSTAbort20                          ;Go back to look for more holders\r
958 KSTAbort21:                                                     ;\r
959                 PUSH EDX                                        ;Respond to this request\r
960                 PUSH ErcOwnerAbort                      ;cause he's dead\r
961                 CALL FWORD PTR _Respond\r
962                 JMP SHORT KSTAbort20            ;Go back to look for more holders\r
963 \r
964 KSTAbort30:                                                     ;Check GlobalExch for dead job\r
965                 PUSH KbdGlobExch                        ;See if anyone is at global\r
966                 PUSH OFFSET KbdMsgBuf2L         ;Where to return Request\r
967                 CALL FWORD PTR _CheckMsg        ;\r
968                 OR EAX, EAX                                     ;Yes (someones holding) if ZERO\r
969                 JNZ     KSTAbort40                              ;No more holders\r
970                 MOV EDX, KbdMsgBuf2L            ;pRq of holding job into EDX\r
971                 MOV     EBX, [EDX+RqOwnerJob]\r
972                 CMP     EBX, KbdAbortJob\r
973                 JE KSTAbort31                           ;Go to respond with Erc\r
974                 PUSH EDX                                        ;Else move Request to MainKbd Exch\r
975                 PUSH KbdMainExch                        ; to be reevaluated\r
976                 CALL FWORD PTR _MoveRequest\r
977                 JMP KSTAbort30                          ;Go back to look for more globals\r
978 KSTAbort31:                                                     ;\r
979                 PUSH EDX                                        ;Respond to this request\r
980                 PUSH ErcOwnerAbort                      ;cause he's dead\r
981                 CALL FWORD PTR _Respond\r
982                 JMP SHORT KSTAbort30\r
983 \r
984 KSTAbort40:                                                     ;Respond to original abort Req\r
985                 MOV EBX, KbdMsgBuf1L            ;pRqBlk of original Abort Request\r
986                 PUSH EBX                                        ;\r
987                 PUSH 0                                          ;Error Code (OK)\r
988                 CALL FWORD PTR _Respond\r
989                 JMP KBDServiceTask                      ;Go back to the top\r
990 ;----------------------------------------------------------\r
991 \r
992 KSTReadGlobal:\r
993                 PUSH EBX                                        ;They want a global key\r
994                 PUSH KbdGlobExch                        ;Send em to the Global exch\r
995                 CALL FWORD PTR _MoveRequest\r
996                 JMP KBDServiceTask                      ;Go back to the top\r
997 ;-----------------------------------------------------------\r
998 ;Assign a new owner for the keyboard. We must check to see\r
999 ;if the new owner had any keyboard requests on hold.\r
1000 ;We do this by sending all the requests that were on hold\r
1001 ;back to the main exchange to be reevaluated.\r
1002 ;Then we respond to the original request.\r
1003 \r
1004 KSTAssignKBD:\r
1005                 ;Change owner of Kbd\r
1006                 MOV EAX, [EBX+dData0]           ;Get new owner\r
1007                 CMP EAX, KbdOwner\r
1008                 JNE KSTAssign01                         ;New Owner!\r
1009 \r
1010                 PUSH EBX                                        ;Same owner\r
1011                 PUSH 0                                          ;Error Code (OK)\r
1012                 CALL FWORD PTR _Respond\r
1013                 JMP KBDServiceTask                      ;Go back to the top\r
1014 KSTAssign01:\r
1015                 MOV KbdOwner, EAX                       ;Set new owner\r
1016 \r
1017 KSTAssign02:                                            ;Move all waiters to main exch\r
1018                 PUSH KbdWaitExch                        ;See if anyone is "waiting" for a key\r
1019                 PUSH OFFSET KbdMsgBuf2L         ;Where to return Request\r
1020                 CALL FWORD PTR _CheckMsg        ;\r
1021                 OR EAX, EAX                                     ;Yes (someones waiting) if ZERO\r
1022                 JNZ     KSTAssign03                             ;No more waiters\r
1023                 MOV EDX, KbdMsgBuf2L            ;pRq into EDX\r
1024                 PUSH EDX                                        ;Move Request to MainKbd Exch\r
1025                 PUSH KbdMainExch                        ; to be reevaluated\r
1026                 CALL FWORD PTR _MoveRequest\r
1027                 JMP KSTAssign02                         ;Go back to look for more waiters\r
1028 KSTAssign03:                                            ;Waiter have been moved, Respond to Req\r
1029                 PUSH KbdHoldExch                        ;See if anyone is on hold\r
1030                 PUSH OFFSET KbdMsgBuf2L         ;Where to return Request\r
1031                 CALL FWORD PTR _CheckMsg                ;\r
1032                 OR EAX, EAX                                     ;Yes if ZERO\r
1033                 JNZ     KSTAssign04                             ;No more holders\r
1034                 MOV EDX, KbdMsgBuf2L            ;pRq into EDX\r
1035                 PUSH EDX                                        ;Move Request to MainKbd Exch\r
1036                 PUSH KbdMainExch                        ; to be reevaluated\r
1037                 CALL FWORD PTR _MoveRequest\r
1038                 JMP KSTAssign03                         ;Go back to look for more holders\r
1039 KSTAssign04:                                            ;Holders have been moved, Respond to Req\r
1040                 MOV EBX, KbdMsgBuf1L            ;pRqBlk of original Assign Request\r
1041                 PUSH EBX                                        ;\r
1042                 PUSH 0                                          ;Error Code (OK)\r
1043                 CALL FWORD PTR _Respond\r
1044                 JMP KBDServiceTask                      ;Go back to the top\r
1045 ;-------------------------------------------------------\r
1046 \r
1047 KSTCancelGlobal:\r
1048                 ;Rifle thru Global Exch and respond with ErcNoKeyAvail\r
1049                 ;to those with the same JobNum as dData0\r
1050                 MOV EAX, [EBX+dData0]   ;Save Job that is cancelling global request\r
1051                 MOV KbdCancelJob, EAX   ;\r
1052 \r
1053 KSTCancel10:                                            ;Check GlobalExch for canceled job\r
1054                 PUSH KbdGlobExch                        ;See if anyone is at global\r
1055                 PUSH OFFSET KbdMsgBuf2L         ;Where to return Request\r
1056                 CALL FWORD PTR _CheckMsg        ;\r
1057                 OR EAX, EAX                                     ;Yes (someones holding) if ZERO\r
1058                 JNZ     KSTCancel20                             ;No more globals\r
1059                 MOV EDX, KbdMsgBuf2L            ;pRq of holding job into EDX\r
1060                 MOV     EBX, [EDX+RqOwnerJob]\r
1061                 CMP     EBX, KbdCancelJob\r
1062                 JE KSTCancel11                          ;Go to respond with Erc\r
1063                 PUSH EDX                                        ;Else move Request to MainKbd Exch\r
1064                 PUSH KbdMainExch                        ; to be reevaluated\r
1065                 CALL FWORD PTR _MoveRequest\r
1066                 JMP KSTCancel10                         ;Go back to look for more globals\r
1067 KSTCancel11:                                                    ;\r
1068                 PUSH EDX                                        ;Respond to this request\r
1069                 PUSH ErcNoKeyAvail                      ;cause he cancelled it!\r
1070                 CALL FWORD PTR _Respond\r
1071                 JMP SHORT KSTCancel10           ;Back to check for more\r
1072 \r
1073 KSTCancel20:                                            ;Respond to original cancel Req\r
1074                 MOV EBX, KbdMsgBuf1L            ;pRqBlk of original Request\r
1075                 PUSH EBX                                        ;\r
1076                 PUSH 0                                          ;Error Code (OK)\r
1077                 CALL FWORD PTR _Respond\r
1078                 JMP KBDServiceTask                      ;Go back to the top\r
1079 \r
1080 ;=============================================================\r
1081 ;PUBLIC blocking call to read the keyboard. This uses the\r
1082 ;Default TSS exchange and the stack to make the request to\r
1083 ;the keyboard service for the caller.  The request is a standard\r
1084 ;service code one (Wait On Key) request.\r
1085 ;If fWait is NON-ZERO, this will not return without a key unless\r
1086 ;a kernel/fatal error occurs.\r
1087 ;\r
1088 ;The call is fully reentrant (it has to be...).\r
1089 ;\r
1090 ; Procedural interface:\r
1091 ;\r
1092 ;       ReadKbd(pKeyCodeRet, fWait): dError\r
1093 ;\r
1094 ;   pKeyCodeRet is a pointer to a DWORD where the keycode is returned.\r
1095 ;     [EBP+16]\r
1096 ;       fWait is NON-ZERO to wait for a key.\r
1097 ;         [EBP+12]\r
1098 ;\r
1099 ; Stack Variables:\r
1100 ;   Hndl    [EBP-4]\r
1101 ;\r
1102 PUBLIC __ReadKBD:\r
1103                 PUSH EBP                                        ; Save the Previous FramePtr\r
1104                 MOV EBP,ESP                                     ; Set up New FramePtr\r
1105                 SUB ESP, 4                                      ; One DWORD local var\r
1106 \r
1107                 MOV EAX, OFFSET KBDSvcName      ;'KEYBOARD '\r
1108                 PUSH EAX\r
1109 \r
1110                 PUSH 1                                          ;Service Code (Read Keyboard)\r
1111 \r
1112                 MOV ECX,pRunTSS             ;Get TSS_Exch for our use\r
1113                 MOV EBX,[ECX+TSS_Exch]      ;Exchange (TSS Exch)\r
1114                 PUSH EBX                    ;\r
1115 \r
1116                 LEA EAX, [EBP-4]                        ;Rq Handle (Local Var)\r
1117                 PUSH EAX\r
1118 \r
1119                 PUSH 0                                          ;npSend\r
1120                 MOV EAX, [EBP+16]                       ;Key Code return (Their Ptr)\r
1121                 PUSH EAX                                        ;pData1\r
1122                 PUSH 4                                          ;Size of key code\r
1123                 PUSH 0                                          ;pData2\r
1124                 PUSH 0                                          ;cbData2\r
1125 \r
1126                 XOR EAX, EAX\r
1127                 CMP DWORD PTR [EBP+12], 0       ;Don't wait for Key?\r
1128                 JE ReadKbd1                                     ;No wait\r
1129                 MOV EAX, 1                                      ;Set up to wait!\r
1130 ReadKbd1:\r
1131                 PUSH EAX                                        ;Wait value (dData0)\r
1132 \r
1133                 PUSH 0\r
1134                 PUSH 0\r
1135 \r
1136                 CALL FWORD PTR _Request         ;make the Request\r
1137 \r
1138                 ;The request is made. Now we call Wait!\r
1139 \r
1140                 MOV ECX,pRunTSS             ;Get TSS_Exch for our use\r
1141                 MOV EBX,[ECX+TSS_Exch]      ;\r
1142                 PUSH EBX                    ;Pass exchange (for WaitMsg)\r
1143                 ADD ECX,TSS_Msg             ;Offset of TSS msg area\r
1144                 PUSH ECX\r
1145                 CALL FWORD PTR _WaitMsg         ;Wait on it\r
1146 \r
1147                 ;When we get here the caller should have the key code\r
1148                 ;HOWEVER, we want to pass any errors back via EAX\r
1149 \r
1150                 OR EAX, EAX                                     ;Was there a kernel error?\r
1151                 JNZ ReadKbdEnd                          ;YES.... bummer\r
1152                 MOV ECX,pRunTSS             ;Get TSS_Msg area so we can get error\r
1153                 ADD ECX,TSS_Msg             ;Offset of TSS msg area\r
1154                 MOV EBX, [ECX]                          ;pRqBlk\r
1155                 MOV EAX, [ECX+4]                        ;Service error in second DWord\r
1156 ReadKbdEnd:\r
1157                 MOV ESP,EBP                             ;\r
1158                 POP EBP                                 ;\r
1159                 RETF 8                                  ; Rtn to Caller & Remove Params from stack\r
1160 \r
1161 ;=============================================================\r
1162 ;Special Call for Debugger so it doesn't have to pass thru\r
1163 ;the kernel Request mechanism for a keystroke.\r
1164 ;It acts like ReadKbd with fWait set to true.\r
1165 ;It sucks keys directly from the Final Keyboard buffer.\r
1166 ;\r
1167 ; Procedural interface:\r
1168 ;\r
1169 ;       ReadDbgKbd(pKeyCodeRet)\r
1170 ;\r
1171 ;   pKeyCodeRet is a pointer to a DWORD where the keycode is returned.\r
1172 ;     [EBP+8]\r
1173 ;\r
1174 PUBLIC ReadDbgKBD:\r
1175                 PUSH EBP                                        ; Save the Previous FramePtr\r
1176                 MOV EBP,ESP                                     ; Set up New FramePtr\r
1177 RDKB0:\r
1178                 CALL ReadKBFinal                        ;Get Code from Buf (Uses EAX, ESI)\r
1179                 OR EAX, EAX                                     ;Got a key?? (non zero)\r
1180                 JNZ RDKB1                                       ;No. Loop back again\r
1181                 PUSH 2                                          ;Sleep for 20 ms\r
1182                 CALL FWORD PTR _Sleep\r
1183                 JMP RDKB0                                       ;Check again\r
1184 RDKB1:\r
1185                 MOV ESI, [EBP+8]                        ;Ptr where to return key\r
1186                 MOV [ESI], EAX\r
1187                 XOR EAX, EAX\r
1188                 MOV ESP,EBP                             ;\r
1189                 POP EBP                                 ;\r
1190                 RETN 4                                  ; Rtn to Caller & Remove Params from stack\r
1191 \r
1192 ;=================================================\r
1193 ;This sets the Keyboard Scan Set to #2 with 8042 interpretation ON\r
1194 ;\r
1195 PUBLIC InitKBD:\r
1196 \r
1197                 PUSH 1                                  ;KBD IRQ\r
1198                 CALL FWORD PTR _MaskIRQ\r
1199 \r
1200                 CALL InBuffEmpty    ;Wait for Input Buffer to Empty\r
1201                 MOV AL,0FAh             ;Set ALL keys typematic/make/break\r
1202                 OUT DataPort,AL     ;Send Command to KBD (not 8042)\r
1203 \r
1204                 CALL OutBuffFull        ;Eat response\r
1205                 IN AL, DATAPORT\r
1206 \r
1207                 CALL InBuffEmpty    ;Wait for Input Buffer to Empty\r
1208                 MOV AL,0F0h             ;Set Scan code set\r
1209                 OUT DataPort,AL     ;Send Command to KBD (not 8042)\r
1210 \r
1211                 CALL OutBuffFull        ;Eat response\r
1212                 IN AL, DATAPORT\r
1213 \r
1214 \r
1215                 CALL InBuffEmpty    ;Wait for Input Buffer to Empty\r
1216                 MOV AL,02h              ;Scan set 2\r
1217                 OUT DataPort,AL     ;Send Command\r
1218 \r
1219                 CALL OutBuffFull        ;Eat response\r
1220                 IN AL, DATAPORT\r
1221 \r
1222                 CALL InBuffEmpty    ;Wait for Input Buffer to Empty\r
1223                 MOV AL,060h             ;Set up to write 8042 command byte\r
1224                 OUT COMMANDPORT,AL  ;Send Command\r
1225                 CALL InBuffEmpty    ;Wait for Input Buffer to Empty\r
1226                 MOV AL,45h              ;Enable IBM Xlate\r
1227                 OUT DataPort,AL     ;Send Command\r
1228 \r
1229                 PUSH 1                          ;KBD IRQ\r
1230                 CALL FWORD PTR _UnMaskIRQ\r
1231 \r
1232                 CALL SetKbdLEDs\r
1233 \r
1234                 RETN\r
1235 \r
1236 ;=============================================================================\r
1237 ;This creates the Keyboard Task and Service.\r
1238 ;\r
1239 PUBLIC _InitKBDService:\r
1240 \r
1241                 ;All initial requests and messages from the ISR come to\r
1242                 ;this exchange\r
1243 \r
1244                 MOV EAX, OFFSET KbdMainExch     ;Alloc Main Kbd exch for service\r
1245                 PUSH EAX\r
1246                 CALL FWORD PTR _AllocExch\r
1247                 OR EAX, EAX                                     ;Check for error on AllocExch\r
1248                 JNZ InitKBDSvcEnd                       ;YUP, we got bad problems\r
1249 \r
1250                 ;TempExch for testing\r
1251 \r
1252                 MOV EAX, OFFSET KbdTempExch     ;Alloc Hold Kbd exch for Kbd service\r
1253                 PUSH EAX\r
1254                 CALL FWORD PTR _AllocExch\r
1255                 OR EAX, EAX                                     ;Check for error on AllocExch\r
1256                 JNZ InitKBDSvcEnd                       ;YUP, we got bad problems\r
1257 \r
1258                 ;Requests for ReadkeyBoard (ScvCode #1) that are from job\r
1259                 ;that currently owns the keyboard waits here if it wants\r
1260                 ;to wait for a key.\r
1261 \r
1262                 MOV EAX, OFFSET KbdWaitExch     ;Alloc Hold Kbd exch for Kbd service\r
1263                 PUSH EAX\r
1264                 CALL FWORD PTR _AllocExch\r
1265                 OR EAX, EAX                                     ;Check for error on AllocExch\r
1266                 JNZ InitKBDSvcEnd                       ;YUP, we got bad problems\r
1267 \r
1268                 ;Requests for ReadkeyBoard (ScvCode #1) that are from jobs\r
1269                 ;that do NOT currently own the keyboard get sent here using\r
1270                 ;MoveRequest.\r
1271 \r
1272                 MOV EAX, OFFSET KbdHoldExch     ;Alloc Hold Kbd exch for Kbd service\r
1273                 PUSH EAX\r
1274                 CALL FWORD PTR _AllocExch\r
1275                 OR EAX, EAX                                     ;Check for error on AllocExch\r
1276                 JNZ InitKBDSvcEnd                       ;YUP, we got bad problems\r
1277 \r
1278                 ;Requests for ReadkeyGlobal (SvcCode #3) wait here until we\r
1279                 ;get a global key from the keyboard.\r
1280                 ;\r
1281                 MOV EAX, OFFSET KbdGlobExch     ;Alloc Global Wait exch for Kbd service\r
1282                 PUSH EAX\r
1283                 CALL FWORD PTR _AllocExch\r
1284                 OR EAX, EAX                                     ;Check for error on AllocExch\r
1285                 JNZ InitKBDSvcEnd                       ;YUP, we got bad problems\r
1286 \r
1287                 ;Spawn the Keyboard Service task\r
1288 \r
1289                 MOV EAX, OFFSET KBDServiceTask\r
1290                 PUSH EAX\r
1291                 PUSH 7                                          ;Priority\r
1292                 PUSH 0                                          ;fDebug\r
1293                 MOV EAX, OFFSET KbdSvcStackTop\r
1294                 PUSH EAX\r
1295                 PUSH 1                                          ;OS Job task\r
1296                 CALL FWORD PTR _SpawnTask\r
1297                 OR EAX, EAX                                     ;Check for error on AllocExch\r
1298                 JNZ InitKBDSvcEnd                       ;YUP, we got bad problems\r
1299 \r
1300                 MOV EAX, OFFSET KBDSvcName\r
1301                 PUSH EAX\r
1302                 PUSH KbdMainExch\r
1303                 CALL FWORD PTR _RegisterSvc\r
1304 InitKBDSvcEnd:\r
1305                 MOV BYTE PTR fKBDInitDone, 1    ;We're UP!\r
1306                 RETN\r
1307 ;\r
1308 ;=============================================================================\r
1309 ;This tells the 8042 Controller to Disable the Keyboard device.\r
1310 ;=============================================================================\r
1311 \r
1312 KbdDisable:\r
1313                 PUSH EAX\r
1314                 CALL InBuffEmpty        ;Wait for Input Buffer to Empty\r
1315                 MOV AL,0ADh             ;Set Command to "Write the 8042 Command Byte"\r
1316                 OUT COMMANDPORT,AL      ;Send Command\r
1317                 CALL InBuffEmpty        ;Wait for Input Buffer to Empty\r
1318                 POP EAX\r
1319                 RETN\r
1320 \r
1321 ;=============================================================================\r
1322 ; This tells the 8042 Controller to Enable the Keyboard Device.\r
1323 ;=============================================================================\r
1324 \r
1325 KbdEnable:\r
1326                 CALL InBuffEmpty        ;Wait for Input Buffer to Empty\r
1327                 MOV AL,0AEh                     ;Set Command to "Write the 8042 Command Byte"\r
1328                 OUT COMMANDPORT,AL      ;Send Command\r
1329                 CALL InBuffEmpty        ;Wait for Input Buffer to Empty\r
1330                 RETN\r
1331 ;\r
1332 ;=============================================================================\r
1333 ; Waits until the 8042 Input Buffer is EMPTY\r
1334 ;=============================================================================\r
1335 \r
1336 InBuffEmpty:\r
1337                 PUSH EAX\r
1338                 PUSH ECX\r
1339                 MOV ECX,2FFFFh                  ;check 128k times\r
1340 IBE:\r
1341                 JMP IBE1\r
1342 IBE1:\r
1343                 JMP IBE2\r
1344 IBE2:\r
1345                 IN AL,STATUSPORT                ;Read Status Byte into AL\r
1346                 TEST AL,INPUTBUFFFULL   ;Test The Input Buffer Full Bit\r
1347                 LOOPNZ IBE\r
1348                 POP ECX\r
1349                 POP EAX\r
1350                 RETN\r
1351 \r
1352 ;=============================================================================\r
1353 ; Waits until the 8042 Output Buffer is FULL so we can read it\r
1354 ;=============================================================================\r
1355 ;\r
1356 ; Before calling this makes sure that the Keyboard interrupts have been\r
1357 ; masked so the keyboard interrupt doesn't eat the byte you're\r
1358 ; looking for!!\r
1359 ;\r
1360 OutBuffFull:\r
1361                 PUSH EAX\r
1362                 PUSH ECX\r
1363                 MOV ECX,2FFFFh\r
1364 OBF:\r
1365                 JMP OBF1:\r
1366 OBF1:\r
1367                 JMP OBF2:\r
1368 OBF2:\r
1369                 IN AL,STATUSPORT        ;Read Status Byte into AL\r
1370                 TEST AL,OUTPUTBUFFFULL  ;Test The Output Buffer Full Bit\r
1371                 LOOPZ OBF\r
1372                 POP ECX\r
1373                 POP EAX\r
1374                 RETN\r
1375 \r
1376 ;=============================================================================\r
1377 ; This sets the indicators on the keyboard based on data in KbdState\r
1378 ;=============================================================================\r
1379 \r
1380 SetKbdLEDs:\r
1381                 PUSH EAX\r
1382 \r
1383                 PUSH 1                                  ;KBD IRQ\r
1384                 CALL FWORD PTR _MaskIRQ\r
1385 \r
1386                 CALL InBuffEmpty                ;Wait for Input Buffer to Empty\r
1387                 MOV AL,0EDh                             ;Set/Reset Status Indicators\r
1388                 OUT DATAPORT,AL                 ;Send KBD Command\r
1389 \r
1390                 CALL OutBuffFull                ;Eat response\r
1391                 IN AL, DATAPORT\r
1392 \r
1393                 CALL InBuffEmpty                ;Wait for Input Buffer to Empty\r
1394                 MOV AL,KbdLock                  ;Get Current Lock Status Byte\r
1395                 AND AL,00000111b                ;Mask all but low order 3 bits\r
1396                 OUT DATAPORT,AL                 ;Send KBD Command\r
1397 \r
1398                 CALL OutBuffFull                ;Eat response\r
1399                 IN AL, DATAPORT\r
1400 \r
1401                 PUSH 1                                  ;KBD IRQ\r
1402                 CALL FWORD PTR _UnMaskIRQ\r
1403                 POP EAX\r
1404                 RETN\r
1405 \r
1406 ;================= END OF MODULE ==================\r