Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / obp / obp / dev / usb-devices / kbd / usbkeyin.fth
CommitLineData
920dae64
AT
1\ ========== Copyright Header Begin ==========================================
2\
3\ Hypervisor Software File: usbkeyin.fth
4\
5\ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6\
7\ - Do no alter or remove copyright notices
8\
9\ - Redistribution and use of this software in source and binary forms, with
10\ or without modification, are permitted provided that the following
11\ conditions are met:
12\
13\ - Redistribution of source code must retain the above copyright notice,
14\ this list of conditions and the following disclaimer.
15\
16\ - Redistribution in binary form must reproduce the above copyright notice,
17\ this list of conditions and the following disclaimer in the
18\ documentation and/or other materials provided with the distribution.
19\
20\ Neither the name of Sun Microsystems, Inc. or the names of contributors
21\ may be used to endorse or promote products derived from this software
22\ without specific prior written permission.
23\
24\ This software is provided "AS IS," without a warranty of any kind.
25\ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
26\ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
27\ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
28\ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
29\ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
30\ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN
31\ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
32\ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
33\ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
34\ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
35\ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
36\
37\ You acknowledge that this software is not designed, licensed or
38\ intended for use in the design, construction, operation or maintenance of
39\ any nuclear facility.
40\
41\ ========== Copyright Header End ============================================
42\ id: @(#)usbkeyin.fth 1.19 06/12/15
43\ purpose:
44\ copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved
45
46
47\ headers \ XXX for debugging
48external
49
501 instance value ha-toggle
51: our-toggle ( -- new-toggle )
52 ha-toggle if
53 0 dup to ha-toggle ( 0-toggle )
54 else
55 1 dup to ha-toggle ( 1-toggle )
56 then
57;
58
59
60: get-keynumber ( index -- key# )
61 curr-byte1-bfaddr + c@
62;
63
64
65\ Once the current down keys have been evaluated and dealt with, they
66\ become the previous report's keys, so copy all relevant data.
67\
68: copy-curr-to-prev ( -- )
69
70 /key-info-buff 0 do
71 keybuff-curr^v i + c@ keybuff-prev i + c!
72 loop
73
74 shiftflag to pr-shiftflag stopflag to pr-stopflag
75 ctrlflag to pr-ctrlflag altgflag to pr-altgflag
76 powerflag to pr-powerflag monflag to pr-monflag
77;
78
79
80
81\ Increment the variable (that's kept in the key input buffer) which
82\ keeps track of how many nonspecial keys are down in the current report.
83\
84: count-curr-as-nonspcl ( -- )
85 keybuff-curr^v >#regl-keys-dn ( regkey-cnt-adr )
86 dup c@ 1+ swap c!
87;
88
89
90\ If the keynumber matches for a special key ( Control, Shift - including
91\ capslock, Altg, Power, Mon or Stop ) then set the index from the 1st
92\ keybyte buff location into its "flag".
93\ At the same time keep a count of the non-special keys.
94\
95\ Note that in a way this is cheating because we haven't used the
96\ keymap to get the "intent" of the key# - we've explicitly associated
97\ some of the key#s with their known actions. This will be OK for two
98\ reasons; 1) We won't take action on the special keys (except Stop)
99\ until later when we're applying the "rules", and 2) regardless of
100\ country layout, the key#/action for each of these keys will always
101\ remain constant. So, for example, if we get a key# of 102 (power
102\ key), it will only matter to us later if a shift key is also present.
103\
104: chk-n-set-spcl|regl ( -- )
105 0 keybuff-curr^v >#regl-keys-dn c! \ init count to 0
106 curr-#ksdn-bfaddr c@ ( #downkeys )
107 0 do
108 true i get-keynumber ( yes-spcl-flag key# )
109
110 case
111 \ Note that the case doesn't contain values for rt shift or rt
112 \ control since we explicitly convert the modifier byte's bits
113 \ to be left shift and left control (in "add-key-to-array").
114 d# 225 of i to shiftflag endof \ left shift
115 d# 224 of i to ctrlflag endof \ left control
116 d# 230 of i to altgflag endof \ right alt == Altgraph
117 d# 57 of i to shiftflag endof \ capslock
118 d# 102 of i to powerflag endof \ power key
119 d# 127 of i to monflag endof \ mute(nonshift)
120 \ mon-off-on(shift)
121 d# 120 of i to stopflag endof \ stop (L1) key down
122
123 nip false swap ( no-spcl-flag key# )
124 endcase ( spcl-flag? )
125
126 \ Now use the index and flag to mark the key as special or regular.
127 false = if ( )
128 count-curr-as-nonspcl ( )
129 then
130 loop
131;
132
133
134\ If the control key is down and it is in effect (it is the highest
135\ priority control key down) then apply the control offset to the
136\ keyvalue.
137\
138: chk&adjust4ctrl ( keyvalue' -- keyvalue )
139
140 ctrl-in-effect if
141 ctrlflag -1 > if
142 h# 1f and ( keyvalue )
143 then
144 then
145;
146
147
148\ Take the key# (prior to conversion to the ascii char) and see if it was
149\ in the previous report.
150\
151: in-last-rep? ( key# -- flag )
152 false swap ( flag' key# )
153 keybuff-prev >#keys-down c@ dup if ( flag' key# #prev-kys-dn )
154 0 do ( flag' key# )
155 dup prev-byte1-bfaddr i + c@ = if ( flag' key# )
156 nip true swap ( true-flag key# )
157 then ( flag' key# )
158 loop 1 ( flag' key# dropjunk )
159 then ( flag' key# something )
160 2drop ( flag )
161;
162
163
164: set-repeating-flag \ ( prpt|-1 rpting? newk|-1 key# keyval --
165 \ -- prpt|-1 rpting?' newk|-1 )
166\ drop rot true or -rot
167 2drop >r true or r>
168;
169
170
171: chknset-potential-rpt \ ( prpt|-1 rpting? newk|-1 k# keyval --
172 \ -- prpt rpting? newk|-1 )
173 >r drop ( prpt|-1 rpting? newk|-1 ) ( R: keyval )
174 rot dup -1 = if ( rpting? newk|-1 prpt|-1 ) ( R: keyval )
175 drop r> ( rpting? newk|-1 prpt )
176 else
177 r> drop ( rpting? newk|-1 prpt )
178 then
179 -rot ( prpt rpting? newk|-1 )
180;
181
182
183\ Set the keval as the newkey, but only if another keyval from the current
184\ report hasn't already been set. (The first "new" key found is used.)
185\
186: chknset-new-keyval-rcvd \ ( prpt|-1 rpting? newk|-1 keyval --
187 \ -- prpt|-1 rpting? newkey' )
188 swap dup -1 = if ( prpt|-1 rpting? keyval newk|-1 )
189 drop ( prpt|-1 rpting? newkey )
190 else
191 nip ( prpt|-1 rpting? prev-newkey )
192 then
193;
194
195
196: queue?-adjust-flags \ ( prpt|-1 rpting? newkey|-1 key# keyval --
197 \ -- prpt|-1' rpting?' newkey|-1' )
198 dup curr-repeat-key = if ( prpt|-1 rpting? nwkey|-1 k# keyval )
199 set-repeating-flag ( prpt|-1 rpting! newkey|-1 )
200 exit
201 then ( prpt|-1 rpting? nwkey|-1 k# keyval )
202
203 over in-last-rep? if ( prpt|-1 rpting? nwkey|-1 k# keyval )
204 chknset-potential-rpt ( prpt' rpting? newkey|-1 )
205 exit
206 then nip ( prpt|-1 rpting? newkey|-1 keyval )
207
208 dup bput ( prpt|-1 rpting? newkey|-1 keyval )
209 chknset-new-keyval-rcvd ( prpt|-1 rpting? newkey' )
210;
211
212
213\ Go through the list of keys which are down, queuing any new keys after
214\ they've been converted to ascii chars. Three items are returned;
215\ 1) The first key in the current report which was also seen in the
216\ last report - but which is not the repeat key, or -1 if those
217\ criteria are not met.
218\ 2) A true/false flag which indicates if the repeat key was found in
219\ in this latest report.
220\ 3) The first "new" key in the report, or a -1 if there were no new
221\ keys seen.
222\
223defer convert ' noop is convert
224
2250 instance value shift-map?
2260 instance value altg-map?
227
228: setup-flags ( -- altg? shift? )
229 altg-map? shift-map?
230;
231
232: queue-new-keys ( -- potrptkey|-1 repeating? newkey|-1 )
233 -1 false -1 ( prpt|-1 rpting? newk|-1 )
234
235 curr-#ksdn-bfaddr c@ ( prpt|-1 rpting? newk|-1 #dnkeys )
236 0 do ( prpt|-1 rpting? newk|-1 )
237 i get-keynumber dup ( prpt|-1 rpting? newk|-1 k# k# )
238 setup-flags ( prpt|-1 rpting? newk|-1 k# k# altg? shift? )
239 convert ( prpt|-1 rpting? newk|-1 k# keyval )
240 chk&adjust4ctrl ( prpt|-1 rpting? newk|-1 k# keyval' )
241 queue?-adjust-flags ( prpt|-1' rpting?' newk|-1' )
242 loop
243;
244
245
246\ There's a new key, so mark it and add in the initial delay time
247\ for the repeat timer mechanism.
248\
249: new-repeat-key ( keyvalue -- )
250 to curr-repeat-key ( )
251 get-msecs d# 700 + to key-repeat-time
252;
253
254
255\ Using the specified keymap, have the regular keys queued and then
256\ set the repeat key. The algorithm for determining the repeat key is
257\ as follows;
258\ 1) If a new keyvalue is found that was not in the last report then
259\ set it as the new repeat key.
260\ 2) If no new keyvalue was found, see if the currently repeating
261\ keyvalue was seen - if so take no action so that the timers will
262\ be continuous.
263\ 3) If there's no new key, and the currently repeating key was not
264\ seen, it's still possible that a keyvalue that was found in the
265\ last report is still in the current report, and if so then that
266\ keyvalue becomes the repeat key. (This would occur if the user
267\ pressed two or more keys simultaneously, but then released one
268\ or more keys - including the repeat key, but still kept one or
269\ more keys pressed.)
270\
271: process-dn-keys ( -- )
272 queue-new-keys ( potrptkey|-1 repeating? newkey|-1 )
273
274 dup -1 > if ( potrptkey|-1 repeating? newkey|-1 )
275 new-repeat-key ( potrptkey|-1 repeating? )
276 2drop exit
277 then drop ( potrptkey|-1 repeating? )
278
279 if ( potrptkey|-1 )
280 drop exit \ The "old" repeat key continues...
281 then ( potrptkey|-1 )
282
283 dup -1 = if ( potrptkey|-1 )
284 drop ( )
285 nokey to curr-repeat-key
286 else
287 new-repeat-key ( )
288 then
289;
290
291
292\ The only special key down is Stop, and at least 1 regular key is down.
293\ Stop-a was taken care of elsewhere. Not yet certain if we're going
294\ to attempt to put in Stop-d, Stop-n or Stop-f, so ignore for now.
295\
296: eval-stop+keys ( table-offset -- )
297 process-dn-keys ( )
298;
299
300: stop-&-regl-dn ( -- )
301 false to shift-map? false to altg-map? eval-stop+keys
302;
303
304
305: shift-&-regl-dn ( -- )
306 true to shift-map? false to altg-map? process-dn-keys
307;
308
309
310: altg-&-regl-dn ( -- )
311 false to shift-map? true to altg-map? process-dn-keys
312;
313
314
315\ Find out if each of the xspecial keys (don't bother with the monitor or
316\ power keys) that are currently down were also down in the last report
317\ - if so return a true flag.
318\
319: all-spcl-prev-dn? ( -- flag )
320 true ( flag' )
321 stopflag -1 <> if
322 pr-stopflag -1 <> and ( flag' )
323 then
324 shiftflag -1 <> if
325 pr-shiftflag -1 <> and ( flag' )
326 then
327 ctrlflag -1 <> if
328 pr-ctrlflag -1 <> and ( flag' )
329 then
330 altgflag -1 <> if
331 pr-altgflag -1 <> and ( flag )
332 then
333;
334
335
336: check-shift-power&mon ( -- )
337
338 powerflag -1 > if turn-me-off then
339 monflag -1 > if toggle-mon then
340;
341
342
343: do-shift-&-regl-dn ( -- )
344 check-shift-power&mon shift-&-regl-dn
345;
346
347
348\ Determine the highest priority spcecial key that is down so that only
349\ it will be considered when we evaluate the "normal" keys that will go
350\ into the queue.
351\
352: use-hipri-spcl ( -- )
353 stopflag -1 > if
354 stop-&-regl-dn ( )
355 exit
356 then
357
358 shiftflag -1 > if
359 do-shift-&-regl-dn ( )
360 exit
361 then
362
363 ctrlflag -1 > if
364 -1 to ctrl-in-effect ( )
365 shift-&-regl-dn ( )
366 0 to ctrl-in-effect ( )
367 exit
368 then
369
370 altgflag -1 > if
371 altg-&-regl-dn ( )
372 exit
373 then
374;
375
376
377
378\ Return true if the current flag is set and the previous flag is not set.
379\
380: only-curr-set? ( curr-flag-val|-1 prev-flag-val|-1 -- flag )
381 -1 = ( curr-flag-val flag' )
382 swap -1 > and
383;
384
385
386\ One or more special keys down. If only one is new then ignore the
387\ rest and use the new. If more than one special key is new then use
388\ the one with the highest priority. Note that checking of Stop-a was
389\ done prior to arriving here.
390\
391: spcl-keys-dn ( -- )
392
393 all-spcl-prev-dn? if ( )
394 \ Since there are no new special keys, we're going to select the
395 \ highest priority key as the one to use.
396 use-hipri-spcl ( )
397 else
398 \ Find out which of the special keys are "new" and select the
399 \ highest priority key from that one.
400
401 stopflag pr-stopflag only-curr-set? if
402 stop-&-regl-dn ( )
403 exit
404 then
405
406 shiftflag pr-shiftflag only-curr-set? if
407 do-shift-&-regl-dn ( )
408 exit
409 then
410
411 ctrlflag pr-ctrlflag only-curr-set? if
412 -1 to ctrl-in-effect ( )
413 shift-&-regl-dn ( )
414 0 to ctrl-in-effect ( )
415 exit
416 then
417
418 \ If none of the above-three are the new down special then it must
419 \ be the AltGraph key.
420 altg-&-regl-dn ( )
421 then
422;
423
424
425\ Determine if special keys are present and will be used, or if there
426\ are only std keys.
427\ Note that checking of Stop-a was done prior to arriving here.
428\
429: due-process ( #spclkeys-dn -- )
430 dup curr-#ksdn-bfaddr c@ swap ( #spclkeys-dn #keys-dn #spclkeys-dn )
431 - 0= if ( #spclkeys-dn )
432 \ Only spcl keys down.
433 shiftflag -1 = if ( #spclkeys-dn )
434 \ If one of the spcl keys wasn't the shift key (indicating that a
435 \ shift-power or shift-mon could be possible) then no keys from
436 \ the current report will go into the queue.
437 nokey to curr-repeat-key ( )
438 drop exit ( )
439 then
440 then ( #spclkeys-dn )
441
442 if
443 spcl-keys-dn ( )
444 else
445 false to shift-map? false to altg-map? process-dn-keys
446 then
447;
448
449
450\ The Stop key is known to be down, so cycle through all down keys to
451\ see if the 'a' key is down.
452\
453: stopA-active? ( -- StopA? )
454 false curr-#ksdn-bfaddr c@ ( StopA?' #down-keys )
455 0 do
456 i get-keynumber ( StopA?' key# )
457 4 = if ( StopA?' )
458 true or leave ( yes-StopA )
459 then
460 loop ( StopA? )
461;
462
463\ Check to see if alternate break chord is pressed - shift-pause
464
465: shift-pause? ( -- SPause? )
466 false curr-#ksdn-bfaddr c@ ( false #down-keys )
467 0 do
468 i get-keynumber ( false key# )
469 d# 72 = if ( false )
470 true or leave ( true-SPause? )
471 then
472 loop ( SPause? )
473;
474
475
476
477\ If more than 1 key is down then we'll need to apply a set of "rules"
478\ that will let us know the precedence of the pressed keys. For example,
479\ there might just be several normal keys down, or there may be special
480\ keys down as well. In the case where multiple keys are reported, we'll
481\ look at the down keys in the previous report (if any) to see if it can
482\ be determined which of the current down keys are "new".
483\
484: start-key-processing ( -- Abort-of-some-kind-requested? )
485 chk-n-set-spcl|regl ( )
486
487 shiftflag -1 > if
488 shift-pause? dup if ( SPause? )
489 exit
490 then
491 else
492 stopflag -1 > if
493 stopA-active? dup if ( StopA? )
494 exit ( yes-StopA )
495 then
496 else
497 false ( no-stopA )
498 then
499 then
500
501 curr-#ksdn-bfaddr c@ ( no-StopA #down-keys )
502 keybuff-curr^v >#regl-keys-dn c@ - ( no-StopA #spclkeys-dn )
503 due-process ( no-StopA )
504;
505
506
507\ Sets the global offset into the current and previous report's key-down
508\ buffer to point to the 1st (of 9) key-down bytes. A pointer to the
509\ # of keys down in the current buffer is also set since it's used
510\ frequently.
511\
512: set-oftused-buf-offsets ( -- )
513 keybuff-curr^v >kbd-in-byte1 to curr-byte1-bfaddr
514 keybuff-curr^v >#keys-down to curr-#ksdn-bfaddr
515
516 keybuff-prev >kbd-in-byte1 to prev-byte1-bfaddr
517;
518
519
520\ Receive a keyvalue which represents a special key, and place it
521\ into the 1st available array position in the input key array.
522\
523: add-key-to-array ( #dn-keys modbyte byte-to-add -- #dn-keys' modbyte )
524 swap >r ( #down-keys' byte-2-add )
525 over keybuff-curr^v >kbd-in-byte1 + ( #dn-keys' byte-2-add byteN-addr)
526 c! 1+ r> ( #dn-keys' modbyte )
527;
528
529
530\ 1 indicates a keyboard rollover - indicating too many keys pressed or
531\ kbd is confused; 2 indicates kbd diag failure; 3 is undefined error;
532\ The rollover error seems to be cleared on next understandable keypress,
533\ but don't know about the other two.
534\
535: kbd-err? ( key-value -- flag )
536 4 < if true else false then
537;
538
539
540\ The "down" keys from the latest key report are placed into one of the
541\ buffers by the HA by specifying its address in the enable-interrupts
542\ call to the HA; We then use pointers to the buffers to get at the
543\ key information.
544\ USB keyboards automatically sets individual key bytes to 0 if no key
545\ is down.
546\ Note that we'll "copy" any shift, cntrl or AltGraph keys into the
547\ 1st open slot in the array (based on the info in the modifier byte). This
548\ is being done since the code was originally written to expect those
549\ three special keys to be returned in the array rather than the modifier
550\ byte. The buffer definition was extended 3 bytes just for this purpose.
551\
552: set-#down-keys ( -- #down-keys )
553 0 ( #down-keys' )
554 6 0 do
555 i get-keynumber ?dup if ( #down-keys' key-value )
556 kbd-err? if ( #down-keys' )
557 drop 0 leave ( 0-down-keys )
558 else
559 1+ ( #down-keys' )
560 then
561 then
562 loop ( #down-keys' )
563
564 dup 0= if
565 exit ( #down-keys )
566 then ( #down-keys' )
567
568 keybuff-curr^v >kbd-in-modkeys c@ ( #down-keys' modbyte )
569
570 dup h# 11 and if \ either left or rt cntrl
571 d# 224 add-key-to-array ( #down-keys' modbyte )
572 \ put the byte representing a Cntrl into
573 \ the 1st available key array locn
574 then
575 dup h# 22 and if \ either left or rt shift
576 d# 225 add-key-to-array
577 \ put the byte representing a Shift into
578 \ the 1st available key array locn
579 then
580 dup h# 40 and if \ rt alt = AltGraph
581 d# 230 add-key-to-array ( #down-keys' modbyte )
582 \ put the byte representing an AltGraph
583 \ into the 1st available key array locn
584 then
585 drop ( #down-keys )
586 dup curr-#ksdn-bfaddr c! ( #down-keys )
587;
588
589
590\ In the buffer that holds the key information for the previous key
591\ report, zero the bytes that hold the # of down keys and # of "regular"
592\ down keys, and clear the special key flags.
593\
594: clear-all-prev-keys ( -- )
595 0 keybuff-prev >#keys-down c!
596 0 keybuff-prev >#regl-keys-dn c!
597 -1 to pr-shiftflag -1 to pr-ctrlflag -1 to pr-altgflag
598 -1 to pr-powerflag -1 to pr-monflag -1 to pr-stopflag
599;
600
601
602\ In the buffer that holds the key information for the current key
603\ report, zero the bytes that hold the # of down keys and # of "regular"
604\ down keys, and clear the special key flags. Don't need to zero the
605\ individual key data bytes because they are set for each report by the
606\ hid kbd device.
607\
608: clear-all-curr-keys ( -- )
609 0 curr-#ksdn-bfaddr c!
610 0 keybuff-curr^v >#regl-keys-dn c!
611 -1 to shiftflag -1 to ctrlflag -1 to altgflag
612 -1 to powerflag -1 to monflag -1 to stopflag
613;
614
615
616\ An "ack" was received from the keyboard, so we can now go and evaluate
617\ the keycodes that were received in the current report.
618\
619: eval-key-data ( -- Stop-a? )
620
621 0 to unstall-cnt
622 set-#down-keys if ( )
623 \ If *any* key was pressed - std or "special", i.e. cntrl.
624 start-key-processing ( Stop-a? )
625 copy-curr-to-prev ( Stop-a? )
626 clear-all-curr-keys ( Stop-a? )
627 else
628 clear-all-prev-keys false ( no-Stop-a )
629 nokey to curr-repeat-key ( no-Stop-a )
630 then
631;
632
633\ Clear the software state associated with the keyboard. This is called
634\ when the PROM is entered from an unknown state.
635\
636: clear-keyboard ( -- )
637 initkeybuf \ clear the keyboard circular queue
638 clear-all-curr-keys
639 clear-all-prev-keys
640 nokey to curr-repeat-key
641;