1*74a4d8c2SCharles.Forsyth #include "boot.h"
2*74a4d8c2SCharles.Forsyth
3*74a4d8c2SCharles.Forsyth
4*74a4d8c2SCharles.Forsyth enum {
5*74a4d8c2SCharles.Forsyth Data= 0x60, /* data port */
6*74a4d8c2SCharles.Forsyth
7*74a4d8c2SCharles.Forsyth Status= 0x64, /* status port */
8*74a4d8c2SCharles.Forsyth Inready= 0x01, /* input character ready */
9*74a4d8c2SCharles.Forsyth Outbusy= 0x02, /* output busy */
10*74a4d8c2SCharles.Forsyth Sysflag= 0x04, /* system flag */
11*74a4d8c2SCharles.Forsyth Cmddata= 0x08, /* cmd==0, data==1 */
12*74a4d8c2SCharles.Forsyth Inhibit= 0x10, /* keyboard/mouse inhibited */
13*74a4d8c2SCharles.Forsyth Minready= 0x20, /* mouse character ready */
14*74a4d8c2SCharles.Forsyth Rtimeout= 0x40, /* general timeout */
15*74a4d8c2SCharles.Forsyth Parity= 0x80,
16*74a4d8c2SCharles.Forsyth
17*74a4d8c2SCharles.Forsyth Cmd= 0x64, /* command port (write only) */
18*74a4d8c2SCharles.Forsyth
19*74a4d8c2SCharles.Forsyth Spec= 0x80,
20*74a4d8c2SCharles.Forsyth
21*74a4d8c2SCharles.Forsyth PF= Spec|0x20, /* num pad function key */
22*74a4d8c2SCharles.Forsyth View= Spec|0x00, /* view (shift window up) */
23*74a4d8c2SCharles.Forsyth KF= Spec|0x40, /* function key */
24*74a4d8c2SCharles.Forsyth Shift= Spec|0x60,
25*74a4d8c2SCharles.Forsyth Break= Spec|0x61,
26*74a4d8c2SCharles.Forsyth Ctrl= Spec|0x62,
27*74a4d8c2SCharles.Forsyth Latin= Spec|0x63,
28*74a4d8c2SCharles.Forsyth Caps= Spec|0x64,
29*74a4d8c2SCharles.Forsyth Num= Spec|0x65,
30*74a4d8c2SCharles.Forsyth No= Spec|0x7F, /* no mapping */
31*74a4d8c2SCharles.Forsyth
32*74a4d8c2SCharles.Forsyth Home= KF|13,
33*74a4d8c2SCharles.Forsyth Up= KF|14,
34*74a4d8c2SCharles.Forsyth Pgup= KF|15,
35*74a4d8c2SCharles.Forsyth Print= KF|16,
36*74a4d8c2SCharles.Forsyth Left= View,
37*74a4d8c2SCharles.Forsyth Right= View,
38*74a4d8c2SCharles.Forsyth End= '\r',
39*74a4d8c2SCharles.Forsyth Down= View,
40*74a4d8c2SCharles.Forsyth Pgdown= View,
41*74a4d8c2SCharles.Forsyth Ins= KF|20,
42*74a4d8c2SCharles.Forsyth Del= 0x7F,
43*74a4d8c2SCharles.Forsyth };
44*74a4d8c2SCharles.Forsyth
45*74a4d8c2SCharles.Forsyth uchar kbtab[] =
46*74a4d8c2SCharles.Forsyth {
47*74a4d8c2SCharles.Forsyth [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',
48*74a4d8c2SCharles.Forsyth [0x08] '7', '8', '9', '0', '-', '=', '\b', '\t',
49*74a4d8c2SCharles.Forsyth [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
50*74a4d8c2SCharles.Forsyth [0x18] 'o', 'p', '[', ']', '\n', Ctrl, 'a', 's',
51*74a4d8c2SCharles.Forsyth [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
52*74a4d8c2SCharles.Forsyth [0x28] '\'', '`', Shift, '\\', 'z', 'x', 'c', 'v',
53*74a4d8c2SCharles.Forsyth [0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,
54*74a4d8c2SCharles.Forsyth [0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
55*74a4d8c2SCharles.Forsyth [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
56*74a4d8c2SCharles.Forsyth [0x48] No, No, No, No, No, No, No, No,
57*74a4d8c2SCharles.Forsyth [0x50] No, No, No, No, No, No, No, KF|11,
58*74a4d8c2SCharles.Forsyth [0x58] KF|12, No, No, No, No, No, No, No,
59*74a4d8c2SCharles.Forsyth };
60*74a4d8c2SCharles.Forsyth
61*74a4d8c2SCharles.Forsyth uchar kbtabshift[] =
62*74a4d8c2SCharles.Forsyth {
63*74a4d8c2SCharles.Forsyth [0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',
64*74a4d8c2SCharles.Forsyth [0x08] '&', '*', '(', ')', '_', '+', '\b', '\t',
65*74a4d8c2SCharles.Forsyth [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
66*74a4d8c2SCharles.Forsyth [0x18] 'O', 'P', '{', '}', '\n', Ctrl, 'A', 'S',
67*74a4d8c2SCharles.Forsyth [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
68*74a4d8c2SCharles.Forsyth [0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',
69*74a4d8c2SCharles.Forsyth [0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,
70*74a4d8c2SCharles.Forsyth [0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,
71*74a4d8c2SCharles.Forsyth [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,
72*74a4d8c2SCharles.Forsyth [0x48] No, No, No, No, No, No, No, No,
73*74a4d8c2SCharles.Forsyth [0x50] No, No, No, No, No, No, No, KF|11,
74*74a4d8c2SCharles.Forsyth [0x58] KF|12, No, No, No, No, No, No, No,
75*74a4d8c2SCharles.Forsyth };
76*74a4d8c2SCharles.Forsyth
77*74a4d8c2SCharles.Forsyth uchar kbtabesc1[] =
78*74a4d8c2SCharles.Forsyth {
79*74a4d8c2SCharles.Forsyth [0x00] No, No, No, No, No, No, No, No,
80*74a4d8c2SCharles.Forsyth [0x08] No, No, No, No, No, No, No, No,
81*74a4d8c2SCharles.Forsyth [0x10] No, No, No, No, No, No, No, No,
82*74a4d8c2SCharles.Forsyth [0x18] No, No, No, No, No, Ctrl, No, No,
83*74a4d8c2SCharles.Forsyth [0x20] No, No, No, No, No, No, No, No,
84*74a4d8c2SCharles.Forsyth [0x28] No, No, No, No, No, No, No, No,
85*74a4d8c2SCharles.Forsyth [0x30] No, No, No, No, No, No, No, Print,
86*74a4d8c2SCharles.Forsyth [0x38] Latin, No, No, No, No, No, No, No,
87*74a4d8c2SCharles.Forsyth [0x40] No, No, No, No, No, No, Break, Home,
88*74a4d8c2SCharles.Forsyth [0x48] Up, Pgup, No, Down, No, Right, No, End,
89*74a4d8c2SCharles.Forsyth [0x50] Left, Pgdown, Ins, Del, No, No, No, No,
90*74a4d8c2SCharles.Forsyth [0x58] No, No, No, No, No, No, No, No,
91*74a4d8c2SCharles.Forsyth };
92*74a4d8c2SCharles.Forsyth
93*74a4d8c2SCharles.Forsyth struct latin
94*74a4d8c2SCharles.Forsyth {
95*74a4d8c2SCharles.Forsyth uchar l;
96*74a4d8c2SCharles.Forsyth char c[2];
97*74a4d8c2SCharles.Forsyth }latintab[] = {
98*74a4d8c2SCharles.Forsyth L'¡', "!!", /* spanish initial ! */
99*74a4d8c2SCharles.Forsyth L'¢', "c|", /* cent */
100*74a4d8c2SCharles.Forsyth L'¢', "c$", /* cent */
101*74a4d8c2SCharles.Forsyth L'£', "l$", /* pound sterling */
102*74a4d8c2SCharles.Forsyth L'¤', "g$", /* general currency */
103*74a4d8c2SCharles.Forsyth L'¥', "y$", /* yen */
104*74a4d8c2SCharles.Forsyth L'¥', "j$", /* yen */
105*74a4d8c2SCharles.Forsyth L'¦', "||", /* broken vertical bar */
106*74a4d8c2SCharles.Forsyth L'§', "SS", /* section symbol */
107*74a4d8c2SCharles.Forsyth L'¨', "\"\"", /* dieresis */
108*74a4d8c2SCharles.Forsyth L'©', "cr", /* copyright */
109*74a4d8c2SCharles.Forsyth L'©', "cO", /* copyright */
110*74a4d8c2SCharles.Forsyth L'ª', "sa", /* super a, feminine ordinal */
111*74a4d8c2SCharles.Forsyth L'«', "<<", /* left angle quotation */
112*74a4d8c2SCharles.Forsyth L'¬', "no", /* not sign, hooked overbar */
113*74a4d8c2SCharles.Forsyth L'', "--", /* soft hyphen */
114*74a4d8c2SCharles.Forsyth L'®', "rg", /* registered trademark */
115*74a4d8c2SCharles.Forsyth L'¯', "__", /* macron */
116*74a4d8c2SCharles.Forsyth L'°', "s0", /* degree (sup o) */
117*74a4d8c2SCharles.Forsyth L'±', "+-", /* plus-minus */
118*74a4d8c2SCharles.Forsyth L'²', "s2", /* sup 2 */
119*74a4d8c2SCharles.Forsyth L'³', "s3", /* sup 3 */
120*74a4d8c2SCharles.Forsyth L'´', "''", /* grave accent */
121*74a4d8c2SCharles.Forsyth L'µ', "mu", /* mu */
122*74a4d8c2SCharles.Forsyth L'¶', "pg", /* paragraph (pilcrow) */
123*74a4d8c2SCharles.Forsyth L'·', "..", /* centered . */
124*74a4d8c2SCharles.Forsyth L'¸', ",,", /* cedilla */
125*74a4d8c2SCharles.Forsyth L'¹', "s1", /* sup 1 */
126*74a4d8c2SCharles.Forsyth L'º', "so", /* sup o */
127*74a4d8c2SCharles.Forsyth L'»', ">>", /* right angle quotation */
128*74a4d8c2SCharles.Forsyth L'¼', "14", /* 1/4 */
129*74a4d8c2SCharles.Forsyth L'½', "12", /* 1/2 */
130*74a4d8c2SCharles.Forsyth L'¾', "34", /* 3/4 */
131*74a4d8c2SCharles.Forsyth L'¿', "??", /* spanish initial ? */
132*74a4d8c2SCharles.Forsyth L'À', "A`", /* A grave */
133*74a4d8c2SCharles.Forsyth L'Á', "A'", /* A acute */
134*74a4d8c2SCharles.Forsyth L'Â', "A^", /* A circumflex */
135*74a4d8c2SCharles.Forsyth L'Ã', "A~", /* A tilde */
136*74a4d8c2SCharles.Forsyth L'Ä', "A\"", /* A dieresis */
137*74a4d8c2SCharles.Forsyth L'Ä', "A:", /* A dieresis */
138*74a4d8c2SCharles.Forsyth L'Å', "Ao", /* A circle */
139*74a4d8c2SCharles.Forsyth L'Å', "AO", /* A circle */
140*74a4d8c2SCharles.Forsyth L'Æ', "Ae", /* AE ligature */
141*74a4d8c2SCharles.Forsyth L'Æ', "AE", /* AE ligature */
142*74a4d8c2SCharles.Forsyth L'Ç', "C,", /* C cedilla */
143*74a4d8c2SCharles.Forsyth L'È', "E`", /* E grave */
144*74a4d8c2SCharles.Forsyth L'É', "E'", /* E acute */
145*74a4d8c2SCharles.Forsyth L'Ê', "E^", /* E circumflex */
146*74a4d8c2SCharles.Forsyth L'Ë', "E\"", /* E dieresis */
147*74a4d8c2SCharles.Forsyth L'Ë', "E:", /* E dieresis */
148*74a4d8c2SCharles.Forsyth L'Ì', "I`", /* I grave */
149*74a4d8c2SCharles.Forsyth L'Í', "I'", /* I acute */
150*74a4d8c2SCharles.Forsyth L'Î', "I^", /* I circumflex */
151*74a4d8c2SCharles.Forsyth L'Ï', "I\"", /* I dieresis */
152*74a4d8c2SCharles.Forsyth L'Ï', "I:", /* I dieresis */
153*74a4d8c2SCharles.Forsyth L'Ð', "D-", /* Eth */
154*74a4d8c2SCharles.Forsyth L'Ñ', "N~", /* N tilde */
155*74a4d8c2SCharles.Forsyth L'Ò', "O`", /* O grave */
156*74a4d8c2SCharles.Forsyth L'Ó', "O'", /* O acute */
157*74a4d8c2SCharles.Forsyth L'Ô', "O^", /* O circumflex */
158*74a4d8c2SCharles.Forsyth L'Õ', "O~", /* O tilde */
159*74a4d8c2SCharles.Forsyth L'Ö', "O\"", /* O dieresis */
160*74a4d8c2SCharles.Forsyth L'Ö', "O:", /* O dieresis */
161*74a4d8c2SCharles.Forsyth L'Ö', "OE", /* O dieresis */
162*74a4d8c2SCharles.Forsyth L'Ö', "Oe", /* O dieresis */
163*74a4d8c2SCharles.Forsyth L'×', "xx", /* times sign */
164*74a4d8c2SCharles.Forsyth L'Ø', "O/", /* O slash */
165*74a4d8c2SCharles.Forsyth L'Ù', "U`", /* U grave */
166*74a4d8c2SCharles.Forsyth L'Ú', "U'", /* U acute */
167*74a4d8c2SCharles.Forsyth L'Û', "U^", /* U circumflex */
168*74a4d8c2SCharles.Forsyth L'Ü', "U\"", /* U dieresis */
169*74a4d8c2SCharles.Forsyth L'Ü', "U:", /* U dieresis */
170*74a4d8c2SCharles.Forsyth L'Ü', "UE", /* U dieresis */
171*74a4d8c2SCharles.Forsyth L'Ü', "Ue", /* U dieresis */
172*74a4d8c2SCharles.Forsyth L'Ý', "Y'", /* Y acute */
173*74a4d8c2SCharles.Forsyth L'Þ', "P|", /* Thorn */
174*74a4d8c2SCharles.Forsyth L'Þ', "Th", /* Thorn */
175*74a4d8c2SCharles.Forsyth L'Þ', "TH", /* Thorn */
176*74a4d8c2SCharles.Forsyth L'ß', "ss", /* sharp s */
177*74a4d8c2SCharles.Forsyth L'à', "a`", /* a grave */
178*74a4d8c2SCharles.Forsyth L'á', "a'", /* a acute */
179*74a4d8c2SCharles.Forsyth L'â', "a^", /* a circumflex */
180*74a4d8c2SCharles.Forsyth L'ã', "a~", /* a tilde */
181*74a4d8c2SCharles.Forsyth L'ä', "a\"", /* a dieresis */
182*74a4d8c2SCharles.Forsyth L'ä', "a:", /* a dieresis */
183*74a4d8c2SCharles.Forsyth L'å', "ao", /* a circle */
184*74a4d8c2SCharles.Forsyth L'æ', "ae", /* ae ligature */
185*74a4d8c2SCharles.Forsyth L'ç', "c,", /* c cedilla */
186*74a4d8c2SCharles.Forsyth L'è', "e`", /* e grave */
187*74a4d8c2SCharles.Forsyth L'é', "e'", /* e acute */
188*74a4d8c2SCharles.Forsyth L'ê', "e^", /* e circumflex */
189*74a4d8c2SCharles.Forsyth L'ë', "e\"", /* e dieresis */
190*74a4d8c2SCharles.Forsyth L'ë', "e:", /* e dieresis */
191*74a4d8c2SCharles.Forsyth L'ì', "i`", /* i grave */
192*74a4d8c2SCharles.Forsyth L'í', "i'", /* i acute */
193*74a4d8c2SCharles.Forsyth L'î', "i^", /* i circumflex */
194*74a4d8c2SCharles.Forsyth L'ï', "i\"", /* i dieresis */
195*74a4d8c2SCharles.Forsyth L'ï', "i:", /* i dieresis */
196*74a4d8c2SCharles.Forsyth L'ð', "d-", /* eth */
197*74a4d8c2SCharles.Forsyth L'ñ', "n~", /* n tilde */
198*74a4d8c2SCharles.Forsyth L'ò', "o`", /* o grave */
199*74a4d8c2SCharles.Forsyth L'ó', "o'", /* o acute */
200*74a4d8c2SCharles.Forsyth L'ô', "o^", /* o circumflex */
201*74a4d8c2SCharles.Forsyth L'õ', "o~", /* o tilde */
202*74a4d8c2SCharles.Forsyth L'ö', "o\"", /* o dieresis */
203*74a4d8c2SCharles.Forsyth L'ö', "o:", /* o dieresis */
204*74a4d8c2SCharles.Forsyth L'ö', "oe", /* o dieresis */
205*74a4d8c2SCharles.Forsyth L'÷', "-:", /* divide sign */
206*74a4d8c2SCharles.Forsyth L'ø', "o/", /* o slash */
207*74a4d8c2SCharles.Forsyth L'ù', "u`", /* u grave */
208*74a4d8c2SCharles.Forsyth L'ú', "u'", /* u acute */
209*74a4d8c2SCharles.Forsyth L'û', "u^", /* u circumflex */
210*74a4d8c2SCharles.Forsyth L'ü', "u\"", /* u dieresis */
211*74a4d8c2SCharles.Forsyth L'ü', "u:", /* u dieresis */
212*74a4d8c2SCharles.Forsyth L'ü', "ue", /* u dieresis */
213*74a4d8c2SCharles.Forsyth L'ý', "y'", /* y acute */
214*74a4d8c2SCharles.Forsyth L'þ', "th", /* thorn */
215*74a4d8c2SCharles.Forsyth L'þ', "p|", /* thorn */
216*74a4d8c2SCharles.Forsyth L'ÿ', "y\"", /* y dieresis */
217*74a4d8c2SCharles.Forsyth L'ÿ', "y:", /* y dieresis */
218*74a4d8c2SCharles.Forsyth 0, 0,
219*74a4d8c2SCharles.Forsyth };
220*74a4d8c2SCharles.Forsyth
221*74a4d8c2SCharles.Forsyth enum
222*74a4d8c2SCharles.Forsyth {
223*74a4d8c2SCharles.Forsyth /* controller command byte */
224*74a4d8c2SCharles.Forsyth Cscs1= (1<<6), /* scan code set 1 */
225*74a4d8c2SCharles.Forsyth Cmousedis= (1<<5), /* mouse disable */
226*74a4d8c2SCharles.Forsyth Ckbddis= (1<<4), /* kbd disable */
227*74a4d8c2SCharles.Forsyth Csf= (1<<2), /* system flag */
228*74a4d8c2SCharles.Forsyth Cmouseint= (1<<1), /* mouse interrupt enable */
229*74a4d8c2SCharles.Forsyth Ckbdint= (1<<0), /* kbd interrupt enable */
230*74a4d8c2SCharles.Forsyth };
231*74a4d8c2SCharles.Forsyth
232*74a4d8c2SCharles.Forsyth static uchar ccc;
233*74a4d8c2SCharles.Forsyth
234*74a4d8c2SCharles.Forsyth int
latin1(int k1,int k2)235*74a4d8c2SCharles.Forsyth latin1(int k1, int k2)
236*74a4d8c2SCharles.Forsyth {
237*74a4d8c2SCharles.Forsyth struct latin *l;
238*74a4d8c2SCharles.Forsyth
239*74a4d8c2SCharles.Forsyth for(l=latintab; l->l; l++)
240*74a4d8c2SCharles.Forsyth if(k1==l->c[0] && k2==l->c[1])
241*74a4d8c2SCharles.Forsyth return l->l;
242*74a4d8c2SCharles.Forsyth return 0;
243*74a4d8c2SCharles.Forsyth }
244*74a4d8c2SCharles.Forsyth
245*74a4d8c2SCharles.Forsyth /*
246*74a4d8c2SCharles.Forsyth * wait for output no longer busy
247*74a4d8c2SCharles.Forsyth */
248*74a4d8c2SCharles.Forsyth static int
outready(void)249*74a4d8c2SCharles.Forsyth outready(void)
250*74a4d8c2SCharles.Forsyth {
251*74a4d8c2SCharles.Forsyth int tries;
252*74a4d8c2SCharles.Forsyth
253*74a4d8c2SCharles.Forsyth for(tries = 0; (inb(Status) & Outbusy); tries++){
254*74a4d8c2SCharles.Forsyth if(tries > 500)
255*74a4d8c2SCharles.Forsyth return -1;
256*74a4d8c2SCharles.Forsyth delay(2);
257*74a4d8c2SCharles.Forsyth }
258*74a4d8c2SCharles.Forsyth return 0;
259*74a4d8c2SCharles.Forsyth }
260*74a4d8c2SCharles.Forsyth
261*74a4d8c2SCharles.Forsyth /*
262*74a4d8c2SCharles.Forsyth * wait for input
263*74a4d8c2SCharles.Forsyth */
264*74a4d8c2SCharles.Forsyth static int
inready(void)265*74a4d8c2SCharles.Forsyth inready(void)
266*74a4d8c2SCharles.Forsyth {
267*74a4d8c2SCharles.Forsyth int tries;
268*74a4d8c2SCharles.Forsyth
269*74a4d8c2SCharles.Forsyth for(tries = 0; !(inb(Status) & Inready); tries++){
270*74a4d8c2SCharles.Forsyth if(tries > 500)
271*74a4d8c2SCharles.Forsyth return -1;
272*74a4d8c2SCharles.Forsyth delay(2);
273*74a4d8c2SCharles.Forsyth }
274*74a4d8c2SCharles.Forsyth return 0;
275*74a4d8c2SCharles.Forsyth }
276*74a4d8c2SCharles.Forsyth
277*74a4d8c2SCharles.Forsyth /*
278*74a4d8c2SCharles.Forsyth * ask 8042 to enable the use of address bit 20
279*74a4d8c2SCharles.Forsyth */
280*74a4d8c2SCharles.Forsyth void
i8042a20(void)281*74a4d8c2SCharles.Forsyth i8042a20(void)
282*74a4d8c2SCharles.Forsyth {
283*74a4d8c2SCharles.Forsyth outready();
284*74a4d8c2SCharles.Forsyth outb(Cmd, 0xD1);
285*74a4d8c2SCharles.Forsyth outready();
286*74a4d8c2SCharles.Forsyth outb(Data, 0xDF);
287*74a4d8c2SCharles.Forsyth outready();
288*74a4d8c2SCharles.Forsyth }
289*74a4d8c2SCharles.Forsyth
290*74a4d8c2SCharles.Forsyth /*
291*74a4d8c2SCharles.Forsyth * ask 8042 to reset the machine
292*74a4d8c2SCharles.Forsyth */
293*74a4d8c2SCharles.Forsyth void
i8042reset(void)294*74a4d8c2SCharles.Forsyth i8042reset(void)
295*74a4d8c2SCharles.Forsyth {
296*74a4d8c2SCharles.Forsyth ushort *s = (ushort*)(KZERO|0x472);
297*74a4d8c2SCharles.Forsyth int i, x;
298*74a4d8c2SCharles.Forsyth
299*74a4d8c2SCharles.Forsyth *s = 0x1234; /* BIOS warm-boot flag */
300*74a4d8c2SCharles.Forsyth
301*74a4d8c2SCharles.Forsyth outready();
302*74a4d8c2SCharles.Forsyth outb(Cmd, 0xFE); /* pulse reset line (means resend on AT&T machines) */
303*74a4d8c2SCharles.Forsyth outready();
304*74a4d8c2SCharles.Forsyth
305*74a4d8c2SCharles.Forsyth /*
306*74a4d8c2SCharles.Forsyth * Pulse it by hand (old somewhat reliable)
307*74a4d8c2SCharles.Forsyth */
308*74a4d8c2SCharles.Forsyth x = 0xDF;
309*74a4d8c2SCharles.Forsyth for(i = 0; i < 5; i++){
310*74a4d8c2SCharles.Forsyth x ^= 1;
311*74a4d8c2SCharles.Forsyth outready();
312*74a4d8c2SCharles.Forsyth outb(Cmd, 0xD1);
313*74a4d8c2SCharles.Forsyth outready();
314*74a4d8c2SCharles.Forsyth outb(Data, x); /* toggle reset */
315*74a4d8c2SCharles.Forsyth delay(100);
316*74a4d8c2SCharles.Forsyth }
317*74a4d8c2SCharles.Forsyth }
318*74a4d8c2SCharles.Forsyth
319*74a4d8c2SCharles.Forsyth /*
320*74a4d8c2SCharles.Forsyth * keyboard interrupt
321*74a4d8c2SCharles.Forsyth */
322*74a4d8c2SCharles.Forsyth int
kbdintr0(void)323*74a4d8c2SCharles.Forsyth kbdintr0(void)
324*74a4d8c2SCharles.Forsyth {
325*74a4d8c2SCharles.Forsyth int s, c;
326*74a4d8c2SCharles.Forsyth static int esc1, esc2;
327*74a4d8c2SCharles.Forsyth static int shift;
328*74a4d8c2SCharles.Forsyth static int caps;
329*74a4d8c2SCharles.Forsyth static int ctl;
330*74a4d8c2SCharles.Forsyth static int num;
331*74a4d8c2SCharles.Forsyth static int lstate, k1, k2;
332*74a4d8c2SCharles.Forsyth int keyup;
333*74a4d8c2SCharles.Forsyth
334*74a4d8c2SCharles.Forsyth /*
335*74a4d8c2SCharles.Forsyth * get status
336*74a4d8c2SCharles.Forsyth */
337*74a4d8c2SCharles.Forsyth s = inb(Status);
338*74a4d8c2SCharles.Forsyth if(!(s&Inready))
339*74a4d8c2SCharles.Forsyth return -1;
340*74a4d8c2SCharles.Forsyth
341*74a4d8c2SCharles.Forsyth /*
342*74a4d8c2SCharles.Forsyth * get the character
343*74a4d8c2SCharles.Forsyth */
344*74a4d8c2SCharles.Forsyth c = inb(Data);
345*74a4d8c2SCharles.Forsyth
346*74a4d8c2SCharles.Forsyth /*
347*74a4d8c2SCharles.Forsyth * e0's is the first of a 2 character sequence
348*74a4d8c2SCharles.Forsyth */
349*74a4d8c2SCharles.Forsyth if(c == 0xe0){
350*74a4d8c2SCharles.Forsyth esc1 = 1;
351*74a4d8c2SCharles.Forsyth return 0;
352*74a4d8c2SCharles.Forsyth } else if(c == 0xe1){
353*74a4d8c2SCharles.Forsyth esc2 = 2;
354*74a4d8c2SCharles.Forsyth return 0;
355*74a4d8c2SCharles.Forsyth }
356*74a4d8c2SCharles.Forsyth
357*74a4d8c2SCharles.Forsyth keyup = c&0x80;
358*74a4d8c2SCharles.Forsyth c &= 0x7f;
359*74a4d8c2SCharles.Forsyth if(c > sizeof kbtab){
360*74a4d8c2SCharles.Forsyth print("unknown key %ux\n", c|keyup);
361*74a4d8c2SCharles.Forsyth kbdchar(0, k1);
362*74a4d8c2SCharles.Forsyth return 0;
363*74a4d8c2SCharles.Forsyth }
364*74a4d8c2SCharles.Forsyth
365*74a4d8c2SCharles.Forsyth if(esc1){
366*74a4d8c2SCharles.Forsyth c = kbtabesc1[c];
367*74a4d8c2SCharles.Forsyth esc1 = 0;
368*74a4d8c2SCharles.Forsyth kbdchar(0, c);
369*74a4d8c2SCharles.Forsyth return 0;
370*74a4d8c2SCharles.Forsyth } else if(esc2){
371*74a4d8c2SCharles.Forsyth esc2--;
372*74a4d8c2SCharles.Forsyth return 0;
373*74a4d8c2SCharles.Forsyth } else if(shift)
374*74a4d8c2SCharles.Forsyth c = kbtabshift[c];
375*74a4d8c2SCharles.Forsyth else
376*74a4d8c2SCharles.Forsyth c = kbtab[c];
377*74a4d8c2SCharles.Forsyth
378*74a4d8c2SCharles.Forsyth if(caps && c<='z' && c>='a')
379*74a4d8c2SCharles.Forsyth c += 'A' - 'a';
380*74a4d8c2SCharles.Forsyth
381*74a4d8c2SCharles.Forsyth /*
382*74a4d8c2SCharles.Forsyth * keyup only important for shifts
383*74a4d8c2SCharles.Forsyth */
384*74a4d8c2SCharles.Forsyth if(keyup){
385*74a4d8c2SCharles.Forsyth switch(c){
386*74a4d8c2SCharles.Forsyth case Shift:
387*74a4d8c2SCharles.Forsyth shift = 0;
388*74a4d8c2SCharles.Forsyth break;
389*74a4d8c2SCharles.Forsyth case Ctrl:
390*74a4d8c2SCharles.Forsyth ctl = 0;
391*74a4d8c2SCharles.Forsyth break;
392*74a4d8c2SCharles.Forsyth }
393*74a4d8c2SCharles.Forsyth return 0;
394*74a4d8c2SCharles.Forsyth }
395*74a4d8c2SCharles.Forsyth
396*74a4d8c2SCharles.Forsyth /*
397*74a4d8c2SCharles.Forsyth * normal character
398*74a4d8c2SCharles.Forsyth */
399*74a4d8c2SCharles.Forsyth if(!(c & Spec)){
400*74a4d8c2SCharles.Forsyth if(ctl)
401*74a4d8c2SCharles.Forsyth c &= 0x1f;
402*74a4d8c2SCharles.Forsyth switch(lstate){
403*74a4d8c2SCharles.Forsyth case 1:
404*74a4d8c2SCharles.Forsyth k1 = c;
405*74a4d8c2SCharles.Forsyth lstate = 2;
406*74a4d8c2SCharles.Forsyth return 0;
407*74a4d8c2SCharles.Forsyth case 2:
408*74a4d8c2SCharles.Forsyth k2 = c;
409*74a4d8c2SCharles.Forsyth lstate = 0;
410*74a4d8c2SCharles.Forsyth c = latin1(k1, k2);
411*74a4d8c2SCharles.Forsyth if(c == 0){
412*74a4d8c2SCharles.Forsyth kbdchar(0, k1);
413*74a4d8c2SCharles.Forsyth c = k2;
414*74a4d8c2SCharles.Forsyth }
415*74a4d8c2SCharles.Forsyth /* fall through */
416*74a4d8c2SCharles.Forsyth default:
417*74a4d8c2SCharles.Forsyth break;
418*74a4d8c2SCharles.Forsyth }
419*74a4d8c2SCharles.Forsyth } else {
420*74a4d8c2SCharles.Forsyth switch(c){
421*74a4d8c2SCharles.Forsyth case Caps:
422*74a4d8c2SCharles.Forsyth caps ^= 1;
423*74a4d8c2SCharles.Forsyth return 0;
424*74a4d8c2SCharles.Forsyth case Num:
425*74a4d8c2SCharles.Forsyth num ^= 1;
426*74a4d8c2SCharles.Forsyth return 0;
427*74a4d8c2SCharles.Forsyth case Shift:
428*74a4d8c2SCharles.Forsyth shift = 1;
429*74a4d8c2SCharles.Forsyth return 0;
430*74a4d8c2SCharles.Forsyth case Latin:
431*74a4d8c2SCharles.Forsyth lstate = 1;
432*74a4d8c2SCharles.Forsyth return 0;
433*74a4d8c2SCharles.Forsyth case Ctrl:
434*74a4d8c2SCharles.Forsyth ctl = 1;
435*74a4d8c2SCharles.Forsyth return 0;
436*74a4d8c2SCharles.Forsyth }
437*74a4d8c2SCharles.Forsyth }
438*74a4d8c2SCharles.Forsyth kbdchar(0, c);
439*74a4d8c2SCharles.Forsyth return 0;
440*74a4d8c2SCharles.Forsyth }
441*74a4d8c2SCharles.Forsyth
442*74a4d8c2SCharles.Forsyth static void
kbdintr(Ureg *,void *)443*74a4d8c2SCharles.Forsyth kbdintr(Ureg*, void*)
444*74a4d8c2SCharles.Forsyth {
445*74a4d8c2SCharles.Forsyth while(kbdintr0() == 0)
446*74a4d8c2SCharles.Forsyth ;
447*74a4d8c2SCharles.Forsyth }
448*74a4d8c2SCharles.Forsyth
449*74a4d8c2SCharles.Forsyth static char *initfailed = "kbd init failed\n";
450*74a4d8c2SCharles.Forsyth
451*74a4d8c2SCharles.Forsyth void
kbdinit(void)452*74a4d8c2SCharles.Forsyth kbdinit(void)
453*74a4d8c2SCharles.Forsyth {
454*74a4d8c2SCharles.Forsyth int c;
455*74a4d8c2SCharles.Forsyth
456*74a4d8c2SCharles.Forsyth /* wait for a quiescent controller */
457*74a4d8c2SCharles.Forsyth while((c = inb(Status)) & (Outbusy | Inready))
458*74a4d8c2SCharles.Forsyth if(c & Inready)
459*74a4d8c2SCharles.Forsyth inb(Data);
460*74a4d8c2SCharles.Forsyth
461*74a4d8c2SCharles.Forsyth /* get current controller command byte */
462*74a4d8c2SCharles.Forsyth outb(Cmd, 0x20);
463*74a4d8c2SCharles.Forsyth if(inready() < 0){
464*74a4d8c2SCharles.Forsyth print("kbdinit: can't read ccc\n");
465*74a4d8c2SCharles.Forsyth ccc = 0;
466*74a4d8c2SCharles.Forsyth } else
467*74a4d8c2SCharles.Forsyth ccc = inb(Data);
468*74a4d8c2SCharles.Forsyth
469*74a4d8c2SCharles.Forsyth /* enable kbd xfers and interrupts */
470*74a4d8c2SCharles.Forsyth ccc &= ~Ckbddis;
471*74a4d8c2SCharles.Forsyth ccc |= Csf | Ckbdint | Cscs1;
472*74a4d8c2SCharles.Forsyth if(outready() < 0)
473*74a4d8c2SCharles.Forsyth print(initfailed);
474*74a4d8c2SCharles.Forsyth outb(Cmd, 0x60);
475*74a4d8c2SCharles.Forsyth if(outready() < 0)
476*74a4d8c2SCharles.Forsyth print(initfailed);
477*74a4d8c2SCharles.Forsyth outb(Data, ccc);
478*74a4d8c2SCharles.Forsyth if(outready() < 0)
479*74a4d8c2SCharles.Forsyth print(initfailed);
480*74a4d8c2SCharles.Forsyth
481*74a4d8c2SCharles.Forsyth setvec(V_KEYBOARD, kbdintr, 0);
482*74a4d8c2SCharles.Forsyth }
483