]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/drivers/keyb-pc.cpp
update
[l4.git] / kernel / fiasco / src / drivers / keyb-pc.cpp
1 INTERFACE:
2
3 /**
4  * Implementation for PC keyboards.
5  */
6 EXTENSION class Keyb
7 {
8 private:
9
10   enum {
11     /*
12      * Keyboard I/O ports.
13      */
14     K_RDWR          = 0x60, /* keyboard data & cmds (read/write) */
15     K_STATUS        = 0x64, /* keybd status (read-only) */
16     K_CMD           = 0x64, /* keybd ctlr command (write-only) */
17
18     /*
19      * Bit definitions for K_STATUS port.
20      */
21     K_OBUF_FUL      = 0x01, /* output (from keybd) buffer full */
22     K_IBUF_FUL      = 0x02, /* input (to keybd) buffer full */
23     K_SYSFLAG       = 0x04, /* "System Flag" */
24     K_CMD_DATA      = 0x08, /* 1 = input buf has cmd, 0 = data */
25     K_KBD_INHIBIT   = 0x10, /* 0 if keyboard inhibited */
26     K_AUX_OBUF_FUL  = 0x20, /* 1 = obuf holds aux device data */
27     K_TIMEOUT       = 0x40, /* timout error flag */
28     K_PARITY_ERROR  = 0x80, /* parity error flag */
29
30     /*
31      * Keyboard controller commands (sent to K_CMD port).
32      */
33     KC_CMD_READ     = 0x20, /* read controller command byte */
34     KC_CMD_WRITE    = 0x60, /* write controller command byte */
35     KC_CMD_DIS_AUX  = 0xa7, /* disable auxiliary device */
36     KC_CMD_ENB_AUX  = 0xa8, /* enable auxiliary device */
37     KC_CMD_TEST_AUX = 0xa9, /* test auxiliary device interface */
38     KC_CMD_SELFTEST = 0xaa, /* keyboard controller self-test */
39     KC_CMD_TEST     = 0xab, /* test keyboard interface */
40     KC_CMD_DUMP     = 0xac, /* diagnostic dump */
41     KC_CMD_DISABLE  = 0xad, /* disable keyboard */
42     KC_CMD_ENABLE   = 0xae, /* enable keyboard */
43     KC_CMD_RDKBD    = 0xc4, /* read keyboard ID */
44     KC_CMD_WIN      = 0xd0, /* read  output port */
45     KC_CMD_WOUT     = 0xd1, /* write output port */
46     KC_CMD_ECHO     = 0xee, /* used for diagnostic testing */
47     KC_CMD_PULSE    = 0xff, /* pulse bits 3-0 based on low nybble */
48
49     /*
50      * Keyboard commands (send to K_RDWR).
51      */
52     K_CMD_LEDS      = 0xed, /* set status LEDs (caps lock, etc.) */
53
54     /*
55      * Bit definitions for controller command byte (sent following
56      * K_CMD_WRITE command).
57      */
58     K_CB_ENBLIRQ    = 0x01, /* enable data-ready intrpt */
59     K_CB_SETSYSF    = 0x04, /* Set System Flag */
60     K_CB_INHBOVR    = 0x08, /* Inhibit Override */
61     K_CB_DISBLE     = 0x10, /* disable keyboard */
62
63     /*
64      * Bit definitions for "Indicator Status Byte" (sent after a
65      * K_CMD_LEDS command).  If the bit is on, the LED is on.  Undefined
66      * bit positions must be 0.
67      */
68     K_LED_SCRLLK    = 0x1, /* scroll lock */
69     K_LED_NUMLK     = 0x2, /* num lock */
70     K_LED_CAPSLK    = 0x4, /* caps lock */
71
72     /*
73      * Bit definitions for "Miscellaneous port B" (K_PORTB).
74      */
75     /* read/write */
76     K_ENABLETMR2    = 0x01, /* enable output from timer 2 */
77     K_SPKRDATA      = 0x02, /* direct input to speaker */
78     K_ENABLEPRTB    = 0x04, /* "enable" port B */
79     K_EIOPRTB       = 0x08, /* enable NMI on parity error */
80     /* read-only */
81     K_REFRESHB      = 0x10, /* refresh flag from INLTCONT PAL */
82     K_OUT2B         = 0x20, /* timer 2 output */
83     K_ICKB          = 0x40, /* I/O channel check (parity error) */
84
85     /*
86      * Bit definitions for the keyboard controller's output port.
87      */
88     KO_SYSRESET     = 0x01, /* processor reset */
89     KO_GATE20       = 0x02, /* A20 address line enable */
90     KO_AUX_DATA_OUT = 0x04, /* output data to auxiliary device */
91     KO_AUX_CLOCK    = 0x08, /* auxiliary device clock */
92     KO_OBUF_FUL     = 0x10, /* keyboard output buffer full */
93     KO_AUX_OBUF_FUL = 0x20, /* aux device output buffer full */
94     KO_CLOCK        = 0x40, /* keyboard clock */
95     KO_DATA_OUT     = 0x80, /* output data to keyboard */
96   };
97 };
98
99 IMPLEMENTATION[pc]:
100
101 #include "processor.h"
102 #include "io.h"
103
104 enum {
105   SHIFT = 0xff,
106 };
107
108 static unsigned char keymap[][2] = {
109   {0       },           /* 0 */
110   {27,  27 },           /* 1 - ESC */
111   {'1', '!'},           /* 2 */
112   {'2', '@'},
113   {'3', '#'},
114   {'4', '$'},
115   {'5', '%'},
116   {'6', '^'},
117   {'7', '&'},
118   {'8', '*'},
119   {'9', '('},
120   {'0', ')'},
121   {'-', '_'},
122   {'=', '+'},
123   {8,   8  },           /* 14 - Backspace */
124   {'\t','\t'},          /* 15 */
125   {'q', 'Q'},
126   {'w', 'W'},
127   {'e', 'E'},
128   {'r', 'R'},
129   {'t', 'T'},
130   {'y', 'Y'},
131   {'u', 'U'},
132   {'i', 'I'},
133   {'o', 'O'},
134   {'p', 'P'},
135   {'[', '{'},
136   {']', '}'},           /* 27 */
137   {'\r','\r'},          /* 28 - Enter */
138   {0,   0  },           /* 29 - Ctrl */
139   {'a', 'A'},           /* 30 */
140   {'s', 'S'},
141   {'d', 'D'},
142   {'f', 'F'},
143   {'g', 'G'},
144   {'h', 'H'},
145   {'j', 'J'},
146   {'k', 'K'},
147   {'l', 'L'},
148   {';', ':'},
149   {'\'','"'},           /* 40 */
150   {'`', '~'},           /* 41 */
151   {SHIFT, SHIFT},       /* 42 - Left Shift */
152   {'\\','|'},           /* 43 */
153   {'z', 'Z'},           /* 44 */
154   {'x', 'X'},
155   {'c', 'C'},
156   {'v', 'V'},
157   {'b', 'B'},
158   {'n', 'N'},
159   {'m', 'M'},
160   {',', '<'},
161   {'.', '>'},
162   {'/', '?'},           /* 53 */
163   {SHIFT, SHIFT},       /* 54 - Right Shift */
164   {0,    0},            /* 55 - Print Screen */
165   {0,    0},            /* 56 - Alt */
166   {' ',' '},            /* 57 - Space bar */
167   {0,    0},            /* 58 - Caps Lock */
168   {0,    0},            /* 59 - F1 */
169   {0,    0},            /* 60 - F2 */
170   {0,    0},            /* 61 - F3 */
171   {0,    0},            /* 62 - F4 */
172   {0,    0},            /* 63 - F5 */
173   {0,    0},            /* 64 - F6 */
174   {0,    0},            /* 65 - F7 */
175   {0,    0},            /* 66 - F8 */
176   {0,    0},            /* 67 - F9 */
177   {0,    0},            /* 68 - F10 */
178   {0,    0},            /* 69 - Num Lock */
179   {0,    0},            /* 70 - Scroll Lock */
180   {0xb7,0xb7},          /* 71 - Numeric keypad 7 */
181   {0xb8,0xb8},          /* 72 - Numeric keypad 8 */
182   {0xb9,0xb9},          /* 73 - Numeric keypad 9 */
183   {'-', '-'},           /* 74 - Numeric keypad '-' */
184   {0xb4,0xb4},          /* 75 - Numeric keypad 4 */
185   {0xb5,0xb5},          /* 76 - Numeric keypad 5 */
186   {0xb6,0xb6},          /* 77 - Numeric keypad 6 */
187   {'+', '+'},           /* 78 - Numeric keypad '+' */
188   {0xb1,0xb1},          /* 79 - Numeric keypad 1 */
189   {0xb2,0xb2},          /* 80 - Numeric keypad 2 */
190   {0xb3,0xb3},          /* 81 - Numeric keypad 3 */
191   {0xb0,0xb0},          /* 82 - Numeric keypad 0 */
192   {0xae,0xae},          /* 83 - Numeric keypad '.' */
193 };
194
195 IMPLEMENT
196 void
197 Keyb::set_keymap(Keyb::Keymap km)
198 {
199   // This is a one-time switch over only.
200   if (km == Keymap_de)
201     {
202       // Simple patch to german layout
203       keymap[ 3][1] = '"';
204       keymap[ 7][1] = '&';
205       keymap[ 8][1] = '/';
206       keymap[ 9][1] = '(';
207       keymap[10][1] = ')';
208       keymap[11][1] = '=';
209       keymap[12][1] = '?';
210       keymap[13][1] = '`';
211       keymap[21][0] = 'z';
212       keymap[21][1] = 'Z';
213       keymap[27][0] = '+';
214       keymap[27][1] = '*';
215       keymap[41][0] = '^';
216       keymap[43][0] = '#';
217       keymap[43][1] = '\'';
218       keymap[44][0] = 'y';
219       keymap[44][1] = 'Y';
220       keymap[51][1] = ';';
221       keymap[52][1] = ':';
222       keymap[53][0] = '-';
223       keymap[53][1] = '_';
224     }
225 }
226
227 IMPLEMENT
228 int Keyb::getchar(bool wait)
229 {
230   static unsigned shift_state;
231   unsigned status, scan_code, ch;
232   Proc::Status old_s = Proc::cli_save();
233
234   for (;;)
235     {
236       /* Wait until a scan code is ready and read it. */
237       status = Io::in8(0x64);
238       if ((status & K_OBUF_FUL) == 0)
239         {
240           if (wait)
241             continue;
242           Proc::sti_restore(old_s);
243           return -1;
244         }
245       scan_code = Io::in8(0x60);
246
247       /* Drop mouse events */
248       if ((status & K_AUX_OBUF_FUL) != 0)
249         {
250           if (wait)
251             continue;
252           Proc::sti_restore(old_s);
253           return -1;
254         }
255
256       if ((scan_code & 0x7f) >= sizeof(keymap)/sizeof(keymap[0]))
257         continue;
258
259       /* Handle key releases - only release of SHIFT is important. */
260       if (scan_code & 0x80)
261         {
262           scan_code &= 0x7f;
263           if (keymap[scan_code][0] == SHIFT)
264             shift_state = 0;
265           continue;
266         }
267
268       /* Translate the character through the keymap. */
269       ch = keymap[scan_code][shift_state];
270       if (ch == (unsigned)SHIFT)
271         {
272           shift_state = 1;
273           continue;
274         }
275       if (ch == 0)
276         continue;
277
278       Proc::sti_restore(old_s);
279       return ch;
280     }
281 }