OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [powerpc/] [ppcn_60x/] [console/] [i8042.c] - Blame information for rev 607

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
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: i8042.c,v 1.2 2001-09-27 12:00:49 chris Exp $
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
 */
37
char 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\\";
40
char 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
 */
46
char 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\\";
49
char 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
 
53
static char *pcNormalLookup;
54
static char *pcShiftedLookup;
55
 
56
/*
57
 * This is exported to vga.c to provide flow control
58
 */
59
volatile 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
 */
65
static boolean bCtrlPressed=FALSE;
66
static boolean bAltPressed=FALSE;
67
static boolean bAltGrPressed=FALSE;
68
static boolean bLShiftPressed=FALSE;
69
static boolean bRShiftPressed=FALSE;
70
static boolean bCapsLock=FALSE;
71
static boolean bNumLock=FALSE;
72
static boolean bTwoCode=FALSE;
73
 
74
#if CONSOLE_USE_INTERRUPTS
75
static volatile Ring_buffer_t KbdOutputBuffer;
76
static volatile boolean bProcessInterruptInput=FALSE;
77
static boolean bInterruptsEnabled=FALSE;
78
static volatile boolean bReceivedAck=TRUE;
79
 
80
static void i8042_process(
81
        int minor
82
);
83
 
84
static void i8042_scan_code(
85
        int minor,
86
        unsigned8   ucScan
87
);
88
#endif
89
 
90
static 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
 */
96
void i8042_polled_on(
97
        int minor
98
)
99
{
100
#if CONSOLE_USE_INTERRUPTS
101
        bProcessInterruptInput=FALSE;
102
#endif
103
}
104
 
105
void 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
 */
133
static rtems_status_code
134
i8042_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
 */
179
static rtems_status_code
180
i8042_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
 */
200
static rtems_status_code
201
i8042_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
 */
247
static rtems_status_code
248
i8042_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
 
274
void 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
 */
291
static 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
 
415
static 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
 
466
static 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
 
631
static 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
 */
733
static 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
 */
868
boolean 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
 
918
void 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
 
949
int 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
 */
984
static 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
 
1040
static 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
 
1055
void 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 */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.