xref: /inferno-os/os/boot/puma/kbd.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
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