source: rtems/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042.c @ d55af6d

4.104.114.84.95
Last change on this file since d55af6d was d55af6d, checked in by Joel Sherrill <joel.sherrill@…>, on 11/09/99 at 15:38:47

Now using libchip instead of local precursor to libchip. Untested.

  • Property mode set to 100644
File size: 17.0 KB
Line 
1/*
2 *  This file contains the PS2 keyboard driver for the i8042
3 *
4 *  Note that this driver will only handle a single i8042 device
5 *
6 *  COPYRIGHT (c) 1998 by Radstone Technology
7 *
8 *
9 * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
10 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
11 * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
12 * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
13 *
14 * You are hereby granted permission to use, copy, modify, and distribute
15 * this file, provided that this notice, plus the above copyright notice
16 * and disclaimer, appears in all copies. Radstone Technology will provide
17 * no support for this code.
18 *
19 *  This driver uses the termios pseudo driver.
20 *
21 *  $Id$
22 */
23
24#include <rtems.h>
25#include <bsp.h>
26#include <rtems/libio.h>
27#include <libchip/serial.h>
28#include <ringbuf.h>
29
30#include "console.h"
31#include "i8042_p.h"
32#include "vga_p.h"
33
34/*
35 * UK style keyboard
36 */
37char pcUKNormalLookup[] = "1234567890-=\b\tqwertyuiop[]\n\0asdfghjkl;\'"
38                          "`\0#zxcvbnm,./\0*\0 \0\0\0\0\0\0\0\0\0\0\0\0"
39                          "\000789-456+1230.\0\0\\";
40char pcUKShiftedLookup[]= "!\"£$%^&*()_+\b\tQWERTYUIOP{}\n\0ASDFGHJKL:"
41                          "@\0\0~ZXCVBNM<>?\0*\0 \0\0\0\0\0\0\0\0\0\0\0"
42                          "\0\000789-456+1230.\0\0|";
43/*
44 * US style keyboard
45 */
46char pcUSNormalLookup[] = "1234567890-=\b\tqwertyuiop[]\n\0asdfghjkl;\'"
47                          "`\0\\zxcvbnm,./\0*\0 \0\0\0\0\0\0\0\0\0\0\0"
48                          "\0\000789-456+1230.\0\0\\";
49char pcUSShiftedLookup[]= "!@#$%^&*()_+\b\tQWERTYUIOP{}\n\0ASDFGHJKL:@~"
50                          "\0|ZXCVBNM<>?\0*\0 \0\0\0\0\0\0\0\0\0\0\0\0"
51                          "\000789-456+1230.\0\0|";
52
53static char *pcNormalLookup;
54static char *pcShiftedLookup;
55
56/*
57 * This is exported to vga.c to provide flow control
58 */
59volatile boolean bScrollLock=FALSE;
60
61/*
62 * If multiple devices are to be supported then a private copy of
63 * the following will be required for each instance
64 */
65static boolean bCtrlPressed=FALSE;
66static boolean bAltPressed=FALSE;
67static boolean bAltGrPressed=FALSE;
68static boolean bLShiftPressed=FALSE;
69static boolean bRShiftPressed=FALSE;
70static boolean bCapsLock=FALSE;
71static boolean bNumLock=FALSE;
72static boolean bTwoCode=FALSE;
73
74#if CONSOLE_USE_INTERRUPTS
75static volatile Ring_buffer_t KbdOutputBuffer;
76static volatile boolean bProcessInterruptInput=FALSE;
77static boolean bInterruptsEnabled=FALSE;
78static volatile boolean bReceivedAck=TRUE;
79
80static void i8042_process(
81        int minor
82);
83
84static void i8042_scan_code(
85        int minor,
86        unsigned8   ucScan
87);
88#endif
89
90static volatile Ring_buffer_t KbdInputBuffer;
91
92/*
93 * The following routines enable an interrupt driver to switch
94 * to polled mode as required for command processing
95 */
96void i8042_polled_on(
97        int minor
98)
99{
100#if CONSOLE_USE_INTERRUPTS
101        bProcessInterruptInput=FALSE;
102#endif
103}
104
105void i8042_polled_off(
106        int minor
107)
108{
109#if CONSOLE_USE_INTERRUPTS
110        unsigned32      Irql;
111        unsigned8       ucScan;
112
113        /*
114         * Make sure we have processed everything outstanding
115         */
116        rtems_interrupt_disable(Irql);
117        while(!Ring_buffer_Is_empty(&KbdInputBuffer))
118        {
119                rtems_interrupt_enable(Irql);
120                Ring_buffer_Remove_character(&KbdInputBuffer,
121                                             ucScan);
122                i8042_scan_code(minor, ucScan);
123                rtems_interrupt_disable(Irql);
124        }
125        bProcessInterruptInput=TRUE;
126        rtems_interrupt_enable(Irql);
127#endif
128}
129
130/*
131 * Send data to the keyboard
132 */
133static rtems_status_code
134i8042_outbyte_raw(
135        int minor,
136        unsigned8 ucData
137)
138{
139        unsigned32 i;
140        unsigned8 Status;
141
142#if CONSOLE_USE_INTERRUPTS
143        unsigned32      Irql;
144
145        if(bInterruptsEnabled)
146        {
147                Ring_buffer_Add_character(&KbdOutputBuffer,
148                                          ucData);
149                if(!Console_Port_Data[minor].bActive)
150                {
151                        /*
152                         * Wake up the device
153                         */
154                        rtems_interrupt_disable(Irql);
155                        Console_Port_Data[minor].bActive=TRUE;
156                        i8042_process(minor);
157                        rtems_interrupt_enable(Irql);
158
159                }
160                return RTEMS_SUCCESSFUL;
161        }
162#endif
163        for (i=0; i<KBD_TIMEOUT; i++)
164        {
165                inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status);
166                if((Status & KBD_IBF_MASK)==0)
167                {
168                        outport_byte(Console_Port_Tbl[minor].ulDataPort,
169                                     ucData);
170                        return RTEMS_SUCCESSFUL;
171                }
172        }
173        return RTEMS_TIMEOUT;
174}
175
176/*
177 * Read data from the keyboard
178 */
179static rtems_status_code
180i8042_inbyte_polled(
181        int minor,
182        unsigned8 *pucData
183)
184{
185        unsigned8 Status;
186
187        inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status);
188        if(Status & KBD_OBF_MASK)
189        {
190                inport_byte(Console_Port_Tbl[minor].ulDataPort,
191                            *pucData);
192                return RTEMS_SUCCESSFUL;
193        }
194        return RTEMS_TIMEOUT;
195}
196
197/*
198 * Blocking read data from the keyboard
199 */
200static rtems_status_code
201i8042_inbyte_raw(
202        int minor,
203        unsigned8 *pucData
204)
205{
206        int i;
207
208#if CONSOLE_USE_INTERRUPTS
209        if(bInterruptsEnabled)
210        {
211                i=0;
212                while(Ring_buffer_Is_empty(&KbdInputBuffer))
213                {
214                        rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
215                        if(i++==KBD_TIMEOUT)
216                        {
217                                return RTEMS_TIMEOUT;
218                        }
219                }
220                Ring_buffer_Remove_character(&KbdInputBuffer,
221                                             *pucData);
222        }
223        else
224#endif
225        {
226                for (i=0; i<KBD_TIMEOUT; i++)
227                {
228                        if(i8042_inbyte_polled(minor, pucData)==
229                              RTEMS_SUCCESSFUL)
230                        {
231                                return RTEMS_SUCCESSFUL;
232                        }
233                        /*
234                         * Wait for a character to be recieved
235                         */
236                }
237
238                return RTEMS_TIMEOUT;
239        }
240
241        return RTEMS_SUCCESSFUL;
242}
243
244/*
245 * Send a command to the keyboard controller
246 */
247static rtems_status_code
248i8042_outbyte_cmd_polled(
249        int minor,
250        unsigned8 ucCommand
251)
252{
253        unsigned32 i;
254        unsigned8 Status;
255
256        /*
257         * This routine may be called when no clock driver is available
258         * so the timeout is dependant on the ISA bus timing used to access
259         * the i8042 which will not vary (much) across platforms.
260         */
261        for (i=0; i<KBD_TIMEOUT; i++)
262        {
263                inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status);
264                if((Status & KBD_IBF_MASK)==0)
265                {
266                        outport_byte(Console_Port_Tbl[minor].ulCtrlPort1,
267                                     ucCommand);
268                        return RTEMS_SUCCESSFUL;
269                }
270        }
271        return RTEMS_TIMEOUT;
272}
273
274void EnqueueKbdChar(
275        int minor,
276        char cChar
277)
278{
279#if CONSOLE_USE_INTERRUPTS
280        rtems_termios_enqueue_raw_characters(
281                Console_Port_Data[minor].termios_data,
282                &cChar,
283                1);
284#else
285        Ring_buffer_Add_character(&KbdInputBuffer, cChar);
286#endif
287}
288/*
289 * Process second code in a two code sequence
290 */
291static void i8042_process_two_code(
292        int minor,
293        unsigned8 ucScan,
294        boolean bMakenBreak
295)
296{
297        char cASCIICtrlCode;
298        char cASCIICode;
299
300        cASCIICtrlCode='\0';
301        cASCIICode='\0';
302
303        switch(ucScan)
304        {
305                case KEY_ALT:
306                {
307                        bAltGrPressed=bMakenBreak;
308                        break;
309                }
310
311                case KEY_CONTROL:
312                {
313                        bCtrlPressed=bMakenBreak;
314                        break;
315                }
316
317                case KEY_INSERT:
318                {
319                        cASCIICtrlCode='@';
320                        break;
321                }
322
323                case KEY_DELETE:
324                {
325                        cASCIICode=ASCII_DEL;
326                        break;
327                }
328
329                case KEY_LEFT_ARROW:
330                {
331                        cASCIICtrlCode='D';
332                        break;
333                }
334
335                case KEY_HOME:
336                {
337                        cASCIICtrlCode='H';
338                        break;
339                }
340
341                case KEY_END:
342                {
343                        cASCIICtrlCode='K';
344                        break;
345                }
346
347                case KEY_UP_ARROW:
348                {
349                        cASCIICtrlCode='A';
350                        break;
351                }
352
353                case KEY_DOWN_ARROW:
354                {
355                        cASCIICtrlCode='B';
356                        break;
357                }
358
359                case KEY_PAGE_UP:
360                {
361                        cASCIICtrlCode='?';
362                        break;
363                }
364
365                case KEY_PAGE_DOWN:
366                {
367                        cASCIICtrlCode='/';
368                        break;
369                }
370
371                case KEY_RIGHT_ARROW:
372                {
373                        cASCIICtrlCode='C';
374                        break;
375                }
376
377                case KEY_KEYPAD_SLASH:
378                {
379                        cASCIICode='/';
380                        break;
381                }
382
383                case KEY_KEYPAD_ENTER:
384                {
385                        cASCIICode=ASCII_CR;
386                        break;
387                }
388
389                case KEY_PRINT_SCREEN:
390                {
391                        cASCIICode=ASCII_SYSRQ;
392                        break;
393                }
394
395                default:
396                {
397                        /*
398                         * Ignore this code
399                         */
400                        break;
401                }
402        }
403
404        if(bMakenBreak && cASCIICode)
405        {
406                EnqueueKbdChar(minor, cASCIICode);
407        }
408        else if(bMakenBreak && cASCIICtrlCode)
409        {
410                EnqueueKbdChar(minor, ASCII_CSI);
411                EnqueueKbdChar(minor, cASCIICtrlCode);
412        }
413}
414
415static boolean i8042_process_qualifiers(
416        unsigned8 ucScan,
417        boolean bMakenBreak
418)
419{
420        boolean bProcessed;
421
422        /*
423         * Check for scan codes for shift, control, or alt keys.
424         */
425        bProcessed=TRUE;
426
427        switch (ucScan)
428        {
429                case KEY_LEFT_SHIFT:
430                {
431                        bLShiftPressed=bMakenBreak;
432                        break;
433                }
434
435                case KEY_RIGHT_SHIFT:
436                {
437                        bRShiftPressed=bMakenBreak;
438                        break;
439                }
440
441                case KEY_CONTROL:
442                {
443                        bCtrlPressed=bMakenBreak;
444                        break;
445                }
446
447                case KEY_ALT:
448                {
449                        bAltPressed=bMakenBreak;
450                        break;
451                }
452
453                default:
454                {
455                        /*
456                         * Something else needs to process this code
457                         */
458                        bProcessed=FALSE;
459                        break;
460                }
461        }
462
463        return(bProcessed);
464}
465
466static boolean i8042_process_top_row(
467        int             minor,
468        unsigned8       ucScan
469)
470{
471        boolean bProcessed;
472        char    cASCIIFnCode;
473#if CONSOLE_USE_INTERRUPTS==0
474        unsigned8       ucKeyboardAck;
475#endif
476
477        /*
478         * Check for keys on the top row
479         */
480        bProcessed=TRUE;
481        cASCIIFnCode='\0';
482
483        switch (ucScan)
484        {
485                case KEY_ESC:
486                {
487                        EnqueueKbdChar(minor, ASCII_ESC);
488                        break;
489                }
490
491                case KEY_F1:
492                {
493                        cASCIIFnCode='P';
494                        break;
495                }
496
497                case KEY_F2:
498                {
499                        cASCIIFnCode='Q';
500                        break;
501                }
502
503                case KEY_F3:
504                {
505                        cASCIIFnCode='w';
506                        break;
507                }
508
509                case KEY_F4:
510                {
511                        cASCIIFnCode='x';
512                        break;
513                }
514
515                case KEY_F5:
516                {
517                        cASCIIFnCode='t';
518                        break;
519                }
520
521                case KEY_F6:
522                {
523                        cASCIIFnCode='u';
524                        break;
525                }
526
527                case KEY_F7:
528                {
529                        cASCIIFnCode='q';
530                        break;
531                }
532
533                case KEY_F8:
534                {
535                        cASCIIFnCode='r';
536                        break;
537                }
538
539                case KEY_F9:
540                {
541                        cASCIIFnCode='p';
542                        break;
543                }
544
545                case KEY_F10:
546                {
547                        cASCIIFnCode='M';
548                        break;
549                }
550
551                case KEY_F11:
552                {
553                        cASCIIFnCode='A';
554                        break;
555                }
556
557                case KEY_F12:
558                {
559                        cASCIIFnCode='B';
560                        break;
561                }
562
563                case KEY_SYS_REQUEST:
564                {
565                        EnqueueKbdChar(minor, ASCII_SYSRQ);
566                        break;
567                }
568
569                case KEY_CAPS_LOCK:
570                case KEY_NUM_LOCK:
571                case KEY_SCROLL_LOCK:
572                {
573                        switch(ucScan)
574                        {
575                                case KEY_CAPS_LOCK:
576                                {
577                                        bCapsLock=!bCapsLock;
578                                        break;
579                                }
580
581                                case KEY_NUM_LOCK:
582                                {
583                                        bNumLock=!bNumLock;
584                                        break;
585                                }
586
587                                case KEY_SCROLL_LOCK:
588                                {
589#if CONSOLE_USE_INTERRUPTS
590                                        bScrollLock=!bScrollLock;
591#endif
592                                        break;
593                                }
594                        }
595
596                        i8042_outbyte_raw(minor, KBD_CMD_SET_LEDS);
597#if CONSOLE_USE_INTERRUPTS==0
598                        i8042_inbyte_raw(minor, &ucKeyboardAck);
599#endif
600                        i8042_outbyte_raw(minor,
601                                          (bCapsLock ? KBD_LED_CAPS : 0) |
602                                          (bNumLock ? KBD_LED_NUM : 0) |
603                                          (bScrollLock ? KBD_LED_SCROLL : 0));
604#if CONSOLE_USE_INTERRUPTS==0
605                        i8042_inbyte_raw(minor, &ucKeyboardAck);
606#endif
607
608                        break;
609                }
610
611                default:
612                {
613                        /*
614                         * Something else needs to process this code
615                         */
616                        bProcessed=FALSE;
617                        break;
618                }
619        }
620
621        if(cASCIIFnCode)
622        {
623                EnqueueKbdChar(minor, ASCII_CSI);
624                EnqueueKbdChar(minor, 'O');
625                EnqueueKbdChar(minor, cASCIIFnCode);
626        }
627
628        return(bProcessed);
629}
630
631static boolean i8042_process_keypad(
632        int     minor,
633        unsigned8 ucScan
634)
635{
636        char cASCIICtrlCode;
637
638        /*
639         * Process keys on the keypad
640         */
641        cASCIICtrlCode='\0';
642
643        switch(ucScan)
644        {
645                case KEY_UP_ARROW:
646                {
647                        cASCIICtrlCode='A';
648                        break;
649                }
650
651                case KEY_DOWN_ARROW:
652                {
653                        cASCIICtrlCode='B';
654                        break;
655                }
656
657                case KEY_RIGHT_ARROW:
658                {
659                        cASCIICtrlCode='C';
660                        break;
661                }
662
663                case KEY_LEFT_ARROW:
664                {
665                        cASCIICtrlCode='D';
666                        break;
667                }
668
669                case KEY_HOME:
670                {
671                        cASCIICtrlCode='H';
672                        break;
673                }
674
675                case KEY_END:
676                {
677                        cASCIICtrlCode='K';
678                        break;
679                }
680
681                case KEY_PAGE_UP:
682                {
683                        cASCIICtrlCode='?';
684                        break;
685                }
686
687                case KEY_PAGE_DOWN:
688                {
689                        cASCIICtrlCode='/';
690                        break;
691                }
692
693                case KEY_INSERT:
694                {
695                        cASCIICtrlCode='@';
696                        break;
697                }
698
699                case KEY_DELETE:
700                {
701                        /*
702                         * This is a special case not requiring an ASCII_CSI
703                         */
704                        EnqueueKbdChar(minor, ASCII_DEL);
705                        return(TRUE);
706                }
707
708                default:
709                {
710                        /*
711                         * Something else needs to process this code
712                         */
713                        break;
714                }
715        }
716
717        if(cASCIICtrlCode)
718        {
719                EnqueueKbdChar(minor, ASCII_CSI);
720                EnqueueKbdChar(minor, cASCIICtrlCode);
721                return(TRUE);
722        }
723        else
724        {
725                return(FALSE);
726        }
727}
728
729/*
730 * This routine translates the keyboard scan code into an
731 * ASCII character (or sequence) and queues it
732 */
733static void i8042_scan_code(
734        int minor,
735        unsigned8   ucScan
736)
737{
738        char cChar;
739        boolean bMakenBreak;
740
741        /*
742         * Check for code 0xe0, which introduces a two key sequence.
743         */
744
745        if(ucScan==KEY_TWO_KEY)
746        {
747                bTwoCode=TRUE;
748                return;
749        }
750
751        /*
752         * Bit 7 of scan code indicates make or break
753         */
754        if(ucScan & 0x80)
755        {
756                bMakenBreak=FALSE;
757                ucScan&=0x7f;
758        }
759        else
760        {
761                bMakenBreak=TRUE;
762        }
763
764        /*
765         * If we are in a multikey sequence then process the second keypress
766         */
767        if(bTwoCode)
768        {
769                i8042_process_two_code(minor, ucScan, bMakenBreak);
770
771                /*
772                 * Revert to prcessing single key sequences
773                 */
774                bTwoCode=FALSE;
775                return;
776        }
777
778        if(i8042_process_qualifiers(ucScan, bMakenBreak))
779        {
780                /*
781                 * We are all done
782                 */
783                return;
784        }
785
786        /*
787         * The remaining keys are only processed for make
788         */
789        if(!bMakenBreak)
790        {
791                return;
792        }
793
794        if(i8042_process_top_row(minor, ucScan))
795        {
796                /*
797                 * We are all done
798                 */
799                return;
800        }
801
802        if(!bNumLock && i8042_process_keypad(minor, ucScan))
803        {
804                /*
805                 * We are all done
806                 */
807                return;
808        }
809
810        /*
811         * Process "normal" keys
812         */
813
814        cChar=0;
815
816        /*
817         * Check to see if the scan code corresponds to an ASCII
818         * character.
819         */
820        if(((ucScan >= 16) && (ucScan <= 25)) ||
821           ((ucScan >= 30) && (ucScan <= 38)) ||
822           ((ucScan >= 44) && (ucScan <= 50)))
823        {
824                if(bCtrlPressed)
825                {
826                        cChar=pcNormalLookup[ucScan - 2]-'a'+1;
827                }
828                else
829                {
830                        if(((bLShiftPressed || bRShiftPressed) && !bCapsLock) ||
831                           (!(bLShiftPressed || bRShiftPressed) && bCapsLock))
832                        {
833                                cChar=pcShiftedLookup[ucScan - 2];
834                        }
835                        else
836                        {
837                                cChar=pcNormalLookup[ucScan - 2];
838                        }
839                }
840        }
841        else if((ucScan > 1) && (ucScan <= 0x56))
842        {
843                /*
844                 * Its ASCII but not alpha, so don't shift on CapsLock.
845                 */
846                if(bLShiftPressed || bRShiftPressed)
847                {
848                        cChar=pcShiftedLookup[ucScan - 2];
849                }
850                else
851                {
852                        cChar=pcNormalLookup[ucScan - 2];
853                }
854        }
855
856        /*
857         * If we got a character then queue it
858         */
859        if(cChar)
860        {
861                EnqueueKbdChar(minor, cChar);
862        }
863}
864
865/*
866 *  Console Device Driver Entry Points
867 */
868boolean i8042_probe(int minor)
869{
870        unsigned8 ucKeyboardAck;
871        unsigned8 ucKeyboardID1, ucKeyboardID2;
872
873        if(!vga_probe(minor))
874        {
875                /*
876                 * There is no VGA adaptor so fail probe
877                 */
878                return(FALSE);
879        }
880
881        Ring_buffer_Initialize(&KbdInputBuffer);
882#if CONSOLE_USE_INTERRUPTS
883        Ring_buffer_Initialize(&KbdOutputBuffer);
884#endif
885
886        i8042_polled_on(minor);
887        /*
888         * Determine keyboard type
889         */
890        i8042_outbyte_raw(minor, KBD_CMD_READ_ID);
891        ucKeyboardAck=0;
892        if((i8042_inbyte_raw(minor, &ucKeyboardAck)==RTEMS_TIMEOUT) ||
893           (ucKeyboardAck==KBD_CMD_RESEND))
894        {
895                /*
896                 * No or incorrect keyboard response so fail probe
897                 */
898                return(FALSE);
899        }
900
901        i8042_inbyte_raw(minor, &ucKeyboardID1);
902        i8042_inbyte_raw(minor, &ucKeyboardID2);
903        if((ucKeyboardID1==0xab) && (ucKeyboardID2==0x41))
904        {
905                pcNormalLookup=&pcUKNormalLookup[0];
906                pcShiftedLookup=&pcUKShiftedLookup[0];
907        }
908        else
909        {
910                pcNormalLookup=&pcUSNormalLookup[0];
911                pcShiftedLookup=&pcUSShiftedLookup[0];
912        }
913        i8042_polled_off(minor);
914
915        return(TRUE);
916}
917
918void i8042_init(int minor)
919{
920        unsigned8 ucKeyboardAck;
921
922        vga_init(minor);
923
924        i8042_polled_on(minor);
925        /*
926         * Switch all LEDs off
927         */
928        i8042_outbyte_raw(minor, KBD_CMD_SET_LEDS);
929        i8042_inbyte_raw(minor, &ucKeyboardAck);
930        i8042_outbyte_raw(minor, 0);
931        i8042_inbyte_raw(minor, &ucKeyboardAck);
932        /*
933         * Select scan code set 1
934         */
935        i8042_outbyte_raw(minor, KBD_CMD_SEL_SCAN_CODE);
936        i8042_inbyte_raw(minor, &ucKeyboardAck);
937        i8042_outbyte_raw(minor, 1);
938        i8042_inbyte_raw(minor, &ucKeyboardAck);
939        i8042_polled_off(minor);
940}
941
942/* PAGE
943 *
944 *  i8042_inbyte_nonblocking_polled
945 *
946 *  Console Termios polling input entry point.
947 */
948
949int i8042_inbyte_nonblocking_polled(
950        int minor
951)
952{
953        unsigned8       ucScan;
954        char    ucData;
955
956        if(i8042_inbyte_polled(minor, &ucScan)==RTEMS_SUCCESSFUL)
957        {
958                i8042_scan_code(minor, ucScan);
959        }
960
961        if(!Ring_buffer_Is_empty(&KbdInputBuffer))
962        {
963                Ring_buffer_Remove_character(&KbdInputBuffer,
964                                             ucData);
965                return(ucData);
966        }
967
968        return(-1);
969}
970
971#if CONSOLE_USE_INTERRUPTS
972/*
973 *  i8042_isr
974 *
975 *  This routine is the console interrupt handler for the keyboard
976 *
977 *  Input parameters:
978 *    vector - vector number
979 *
980 *  Output parameters: NONE
981 *
982 *  Return values:     NONE
983 */
984static void i8042_process(
985        int     minor
986)
987{
988        unsigned8       Status;
989        unsigned8       ucData;
990
991        inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status);
992
993        if(Status & KBD_OBF_MASK)
994        {
995                inport_byte(Console_Port_Tbl[minor].ulDataPort, ucData);
996
997                if(bProcessInterruptInput)
998                {
999                        /*
1000                         * Every byte written to the keyboard should be followed
1001                         * by an acknowledge
1002                         */
1003                        if(ucData==KBD_CMD_ACK)
1004                        {
1005                                bReceivedAck=TRUE;
1006                        }
1007                        else
1008                        {
1009                                i8042_scan_code(minor, ucData);
1010                        }
1011                }
1012                else
1013                {
1014                        /*
1015                         * Store the scan code into the ring buffer where it
1016                         * can be read using i8042_inbyte_raw()
1017                         */
1018                        Ring_buffer_Add_character(&KbdInputBuffer, ucData);
1019                }
1020        }
1021
1022        if(((Status & KBD_IBF_MASK)==0) &&
1023           bReceivedAck)
1024        {
1025                if(Ring_buffer_Is_empty(&KbdOutputBuffer))
1026                {
1027                        Console_Port_Data[minor].bActive=FALSE;
1028                }
1029                else
1030                {
1031                        Ring_buffer_Remove_character(&KbdOutputBuffer,
1032                                                     ucData);
1033                        outport_byte(Console_Port_Tbl[minor].ulDataPort,
1034                                     ucData);
1035                        bReceivedAck=FALSE;
1036                }
1037        }
1038}
1039
1040static rtems_isr i8042_isr(
1041  rtems_vector_number vector
1042)
1043{
1044        int     minor;
1045
1046        for(minor=0;minor<Console_Port_Count;minor++)
1047        {
1048                if(vector==Console_Port_Tbl[minor].ulIntVector)
1049                {
1050                        i8042_process(minor);
1051                }
1052        }
1053}
1054
1055void i8042_initialize_interrupts(int minor)
1056{
1057        i8042_init(minor);
1058
1059        Console_Port_Data[minor].bActive=FALSE;
1060
1061        set_vector(i8042_isr,
1062                   Console_Port_Tbl[minor].ulIntVector,
1063                   1);
1064
1065        i8042_outbyte_cmd_polled(minor, KBD_CTR_WRITE_COMMAND);
1066        i8042_outbyte_raw(minor, KBD_CMD_ENABLE_KBD_INT);
1067
1068        /*
1069         * At this point interrupts should spring into life
1070         */
1071        bInterruptsEnabled=TRUE;
1072}
1073
1074#endif /* CONSOLE_USE_INTERRUPTS */
Note: See TracBrowser for help on using the repository browser.