xref: /plan9-contrib/sys/src/9/loongson/kbd.c (revision a81c3ea0c7f009a3088ab7fe55ea9013d9d77a74)
1*a81c3ea0SDavid du Colombier /*
2*a81c3ea0SDavid du Colombier  * keyboard input
3*a81c3ea0SDavid du Colombier  */
4*a81c3ea0SDavid du Colombier #include	"u.h"
5*a81c3ea0SDavid du Colombier #include	"../port/lib.h"
6*a81c3ea0SDavid du Colombier #include	"mem.h"
7*a81c3ea0SDavid du Colombier #include	"dat.h"
8*a81c3ea0SDavid du Colombier #include	"fns.h"
9*a81c3ea0SDavid du Colombier #include	"io.h"
10*a81c3ea0SDavid du Colombier #include	"../port/error.h"
11*a81c3ea0SDavid du Colombier 
12*a81c3ea0SDavid du Colombier enum {
13*a81c3ea0SDavid du Colombier 	Data=		0x60,		/* data port */
14*a81c3ea0SDavid du Colombier 
15*a81c3ea0SDavid du Colombier 	Status=		0x64,		/* status port */
16*a81c3ea0SDavid du Colombier 	 Inready=	0x01,		/*  input character ready */
17*a81c3ea0SDavid du Colombier 	 Outbusy=	0x02,		/*  output busy */
18*a81c3ea0SDavid du Colombier 	 Sysflag=	0x04,		/*  system flag */
19*a81c3ea0SDavid du Colombier 	 Cmddata=	0x08,		/*  cmd==0, data==1 */
20*a81c3ea0SDavid du Colombier 	 Inhibit=	0x10,		/*  keyboard/mouse inhibited */
21*a81c3ea0SDavid du Colombier 	 Minready=	0x20,		/*  mouse character ready */
22*a81c3ea0SDavid du Colombier 	 Rtimeout=	0x40,		/*  general timeout */
23*a81c3ea0SDavid du Colombier 	 Parity=	0x80,
24*a81c3ea0SDavid du Colombier 
25*a81c3ea0SDavid du Colombier 	Cmd=		0x64,		/* command port (write only) */
26*a81c3ea0SDavid du Colombier 
27*a81c3ea0SDavid du Colombier 	Spec=		0xF800,		/* Unicode private space */
28*a81c3ea0SDavid du Colombier 	PF=		Spec|0x20,	/* num pad function key */
29*a81c3ea0SDavid du Colombier 	View=		Spec|0x00,	/* view (shift window up) */
30*a81c3ea0SDavid du Colombier 	KF=		0xF000,		/* function key (begin Unicode private space) */
31*a81c3ea0SDavid du Colombier 	Shift=		Spec|0x60,
32*a81c3ea0SDavid du Colombier 	Break=		Spec|0x61,
33*a81c3ea0SDavid du Colombier 	Ctrl=		Spec|0x62,
34*a81c3ea0SDavid du Colombier 	Latin=		Spec|0x63,
35*a81c3ea0SDavid du Colombier 	Caps=		Spec|0x64,
36*a81c3ea0SDavid du Colombier 	Num=		Spec|0x65,
37*a81c3ea0SDavid du Colombier 	Middle=		Spec|0x66,
38*a81c3ea0SDavid du Colombier 	Altgr=		Spec|0x67,
39*a81c3ea0SDavid du Colombier 	Kmouse=		Spec|0x100,
40*a81c3ea0SDavid du Colombier 	No=		0x00,		/* peter */
41*a81c3ea0SDavid du Colombier 
42*a81c3ea0SDavid du Colombier 	Home=		KF|13,
43*a81c3ea0SDavid du Colombier 	Up=		KF|14,
44*a81c3ea0SDavid du Colombier 	Pgup=		KF|15,
45*a81c3ea0SDavid du Colombier 	Print=		KF|16,
46*a81c3ea0SDavid du Colombier 	Left=		KF|17,
47*a81c3ea0SDavid du Colombier 	Right=		KF|18,
48*a81c3ea0SDavid du Colombier 	End=		KF|24,
49*a81c3ea0SDavid du Colombier 	Down=		View,
50*a81c3ea0SDavid du Colombier 	Pgdown=		KF|19,
51*a81c3ea0SDavid du Colombier 	Ins=		KF|20,
52*a81c3ea0SDavid du Colombier 	Del=		0x7F,
53*a81c3ea0SDavid du Colombier 	Scroll=		KF|21,
54*a81c3ea0SDavid du Colombier 
55*a81c3ea0SDavid du Colombier 	Nscan=	128,
56*a81c3ea0SDavid du Colombier 
57*a81c3ea0SDavid du Colombier 	Int=	0,			/* kbscans indices */
58*a81c3ea0SDavid du Colombier 	Ext,
59*a81c3ea0SDavid du Colombier 	Nscans,
60*a81c3ea0SDavid du Colombier };
61*a81c3ea0SDavid du Colombier 
62*a81c3ea0SDavid du Colombier /*
63*a81c3ea0SDavid du Colombier  * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
64*a81c3ea0SDavid du Colombier  * A 'standard' keyboard doesn't produce anything above 0x58.
65*a81c3ea0SDavid du Colombier  */
66*a81c3ea0SDavid du Colombier Rune kbtab[Nscan] =
67*a81c3ea0SDavid du Colombier {
68*a81c3ea0SDavid du Colombier [0x00]	No,	0x1b,	'1',	'2',	'3',	'4',	'5',	'6',
69*a81c3ea0SDavid du Colombier [0x08]	'7',	'8',	'9',	'0',	'-',	'=',	'\b',	'\t',
70*a81c3ea0SDavid du Colombier [0x10]	'q',	'w',	'e',	'r',	't',	'y',	'u',	'i',
71*a81c3ea0SDavid du Colombier [0x18]	'o',	'p',	'[',	']',	'\n',	Ctrl,	'a',	's',
72*a81c3ea0SDavid du Colombier [0x20]	'd',	'f',	'g',	'h',	'j',	'k',	'l',	';',
73*a81c3ea0SDavid du Colombier [0x28]	'\'',	'`',	Shift,	'\\',	'z',	'x',	'c',	'v',
74*a81c3ea0SDavid du Colombier [0x30]	'b',	'n',	'm',	',',	'.',	'/',	Shift,	'*',
75*a81c3ea0SDavid du Colombier [0x38]	Latin,	' ',	Ctrl,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
76*a81c3ea0SDavid du Colombier [0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	Scroll,	'7',
77*a81c3ea0SDavid du Colombier [0x48]	'8',	'9',	'-',	'4',	'5',	'6',	'+',	'1',
78*a81c3ea0SDavid du Colombier [0x50]	'2',	'3',	'0',	'.',	No,	No,	No,	KF|11,
79*a81c3ea0SDavid du Colombier [0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
80*a81c3ea0SDavid du Colombier [0x60]	No,	No,	No,	No,	No,	No,	No,	No,
81*a81c3ea0SDavid du Colombier [0x68]	No,	No,	No,	No,	No,	No,	No,	No,
82*a81c3ea0SDavid du Colombier [0x70]	No,	No,	No,	No,	No,	No,	No,	No,
83*a81c3ea0SDavid du Colombier [0x78]	No,	View,	No,	Up,	No,	No,	No,	No,
84*a81c3ea0SDavid du Colombier };
85*a81c3ea0SDavid du Colombier 
86*a81c3ea0SDavid du Colombier Rune kbtabshift[Nscan] =
87*a81c3ea0SDavid du Colombier {
88*a81c3ea0SDavid du Colombier [0x00]	No,	0x1b,	'!',	'@',	'#',	'$',	'%',	'^',
89*a81c3ea0SDavid du Colombier [0x08]	'&',	'*',	'(',	')',	'_',	'+',	'\b',	'\t',
90*a81c3ea0SDavid du Colombier [0x10]	'Q',	'W',	'E',	'R',	'T',	'Y',	'U',	'I',
91*a81c3ea0SDavid du Colombier [0x18]	'O',	'P',	'{',	'}',	'\n',	Ctrl,	'A',	'S',
92*a81c3ea0SDavid du Colombier [0x20]	'D',	'F',	'G',	'H',	'J',	'K',	'L',	':',
93*a81c3ea0SDavid du Colombier [0x28]	'"',	'~',	Shift,	'|',	'Z',	'X',	'C',	'V',
94*a81c3ea0SDavid du Colombier [0x30]	'B',	'N',	'M',	'<',	'>',	'?',	Shift,	'*',
95*a81c3ea0SDavid du Colombier [0x38]	Latin,	' ',	Ctrl,	KF|1,	KF|2,	KF|3,	KF|4,	KF|5,
96*a81c3ea0SDavid du Colombier [0x40]	KF|6,	KF|7,	KF|8,	KF|9,	KF|10,	Num,	Scroll,	'7',
97*a81c3ea0SDavid du Colombier [0x48]	'8',	'9',	'-',	'4',	'5',	'6',	'+',	'1',
98*a81c3ea0SDavid du Colombier [0x50]	'2',	'3',	'0',	'.',	No,	No,	No,	KF|11,
99*a81c3ea0SDavid du Colombier [0x58]	KF|12,	No,	No,	No,	No,	No,	No,	No,
100*a81c3ea0SDavid du Colombier [0x60]	No,	No,	No,	No,	No,	No,	No,	No,
101*a81c3ea0SDavid du Colombier [0x68]	No,	No,	No,	No,	No,	No,	No,	No,
102*a81c3ea0SDavid du Colombier [0x70]	No,	No,	No,	No,	No,	No,	No,	No,
103*a81c3ea0SDavid du Colombier [0x78]	No,	Up,	No,	Up,	No,	No,	No,	No,
104*a81c3ea0SDavid du Colombier };
105*a81c3ea0SDavid du Colombier 
106*a81c3ea0SDavid du Colombier Rune kbtabesc1[Nscan] =
107*a81c3ea0SDavid du Colombier {
108*a81c3ea0SDavid du Colombier [0x00]	No,	No,	No,	No,	No,	No,	No,	No,
109*a81c3ea0SDavid du Colombier [0x08]	No,	No,	No,	No,	No,	No,	No,	No,
110*a81c3ea0SDavid du Colombier [0x10]	No,	No,	No,	No,	No,	No,	No,	No,
111*a81c3ea0SDavid du Colombier [0x18]	No,	No,	No,	No,	'\n',	Ctrl,	No,	No,
112*a81c3ea0SDavid du Colombier [0x20]	No,	No,	No,	No,	No,	No,	No,	No,
113*a81c3ea0SDavid du Colombier [0x28]	No,	No,	Shift,	No,	No,	No,	No,	No,
114*a81c3ea0SDavid du Colombier [0x30]	No,	No,	No,	No,	No,	'/',	No,	Print,
115*a81c3ea0SDavid du Colombier [0x38]	Altgr,	No,	No,	No,	No,	No,	No,	No,
116*a81c3ea0SDavid du Colombier [0x40]	No,	No,	No,	No,	No,	No,	Break,	Home,
117*a81c3ea0SDavid du Colombier [0x48]	Up,	Pgup,	No,	Left,	No,	Right,	No,	End,
118*a81c3ea0SDavid du Colombier [0x50]	Down,	Pgdown,	Ins,	Del,	No,	No,	No,	No,
119*a81c3ea0SDavid du Colombier [0x58]	No,	No,	No,	No,	No,	No,	No,	No,
120*a81c3ea0SDavid du Colombier [0x60]	No,	No,	No,	No,	No,	No,	No,	No,
121*a81c3ea0SDavid du Colombier [0x68]	No,	No,	No,	No,	No,	No,	No,	No,
122*a81c3ea0SDavid du Colombier [0x70]	No,	No,	No,	No,	No,	No,	No,	No,
123*a81c3ea0SDavid du Colombier [0x78]	No,	Up,	No,	No,	No,	No,	No,	No,
124*a81c3ea0SDavid du Colombier };
125*a81c3ea0SDavid du Colombier 
126*a81c3ea0SDavid du Colombier Rune kbtabaltgr[Nscan] =
127*a81c3ea0SDavid du Colombier {
128*a81c3ea0SDavid du Colombier [0x00]	No,	No,	No,	No,	No,	No,	No,	No,
129*a81c3ea0SDavid du Colombier [0x08]	No,	No,	No,	No,	No,	No,	No,	No,
130*a81c3ea0SDavid du Colombier [0x10]	No,	No,	No,	No,	No,	No,	No,	No,
131*a81c3ea0SDavid du Colombier [0x18]	No,	No,	No,	No,	'\n',	Ctrl,	No,	No,
132*a81c3ea0SDavid du Colombier [0x20]	No,	No,	No,	No,	No,	No,	No,	No,
133*a81c3ea0SDavid du Colombier [0x28]	No,	No,	Shift,	No,	No,	No,	No,	No,
134*a81c3ea0SDavid du Colombier [0x30]	No,	No,	No,	No,	No,	'/',	No,	Print,
135*a81c3ea0SDavid du Colombier [0x38]	Altgr,	No,	No,	No,	No,	No,	No,	No,
136*a81c3ea0SDavid du Colombier [0x40]	No,	No,	No,	No,	No,	No,	Break,	Home,
137*a81c3ea0SDavid du Colombier [0x48]	Up,	Pgup,	No,	Left,	No,	Right,	No,	End,
138*a81c3ea0SDavid du Colombier [0x50]	Down,	Pgdown,	Ins,	Del,	No,	No,	No,	No,
139*a81c3ea0SDavid du Colombier [0x58]	No,	No,	No,	No,	No,	No,	No,	No,
140*a81c3ea0SDavid du Colombier [0x60]	No,	No,	No,	No,	No,	No,	No,	No,
141*a81c3ea0SDavid du Colombier [0x68]	No,	No,	No,	No,	No,	No,	No,	No,
142*a81c3ea0SDavid du Colombier [0x70]	No,	No,	No,	No,	No,	No,	No,	No,
143*a81c3ea0SDavid du Colombier [0x78]	No,	Up,	No,	No,	No,	No,	No,	No,
144*a81c3ea0SDavid du Colombier };
145*a81c3ea0SDavid du Colombier 
146*a81c3ea0SDavid du Colombier Rune kbtabctrl[Nscan] =
147*a81c3ea0SDavid du Colombier {
148*a81c3ea0SDavid du Colombier [0x00]	No,	'', 	'', 	'', 	'', 	'', 	'', 	'',
149*a81c3ea0SDavid du Colombier [0x08]	'', 	'', 	'', 	'', 	'
150*a81c3ea0SDavid du Colombier ', 	'', 	'\b',	'\t',
151*a81c3ea0SDavid du Colombier [0x10]	'', 	'', 	'', 	'', 	'', 	'', 	'', 	'\t',
152*a81c3ea0SDavid du Colombier [0x18]	'', 	'', 	'', 	'', 	'\n',	Ctrl,	'', 	'',
153*a81c3ea0SDavid du Colombier [0x20]	'', 	'', 	'', 	'\b',	'\n',	'', 	'', 	'',
154*a81c3ea0SDavid du Colombier [0x28]	'', 	No, 	Shift,	'', 	'', 	'', 	'', 	'',
155*a81c3ea0SDavid du Colombier [0x30]	'', 	'', 	'
156*a81c3ea0SDavid du Colombier ', 	'', 	'', 	'', 	Shift,	'\n',
157*a81c3ea0SDavid du Colombier [0x38]	Latin,	No, 	Ctrl,	'', 	'', 	'', 	'', 	'',
158*a81c3ea0SDavid du Colombier [0x40]	'', 	'', 	'', 	'
159*a81c3ea0SDavid du Colombier ', 	'', 	'', 	'', 	'',
160*a81c3ea0SDavid du Colombier [0x48]	'', 	'', 	'
161*a81c3ea0SDavid du Colombier ', 	'', 	'', 	'', 	'', 	'',
162*a81c3ea0SDavid du Colombier [0x50]	'', 	'', 	'', 	'', 	No,	No,	No,	'',
163*a81c3ea0SDavid du Colombier [0x58]	'', 	No,	No,	No,	No,	No,	No,	No,
164*a81c3ea0SDavid du Colombier [0x60]	No,	No,	No,	No,	No,	No,	No,	No,
165*a81c3ea0SDavid du Colombier [0x68]	No,	No,	No,	No,	No,	No,	No,	No,
166*a81c3ea0SDavid du Colombier [0x70]	No,	No,	No,	No,	No,	No,	No,	No,
167*a81c3ea0SDavid du Colombier [0x78]	No,	'', 	No,	'\b',	No,	No,	No,	No,
168*a81c3ea0SDavid du Colombier };
169*a81c3ea0SDavid du Colombier 
170*a81c3ea0SDavid du Colombier enum
171*a81c3ea0SDavid du Colombier {
172*a81c3ea0SDavid du Colombier 	/* controller command byte */
173*a81c3ea0SDavid du Colombier 	Cscs1=		(1<<6),		/* scan code set 1 */
174*a81c3ea0SDavid du Colombier 	Cauxdis=	(1<<5),		/* mouse disable */
175*a81c3ea0SDavid du Colombier 	Ckbddis=	(1<<4),		/* kbd disable */
176*a81c3ea0SDavid du Colombier 	Csf=		(1<<2),		/* system flag */
177*a81c3ea0SDavid du Colombier 	Cauxint=	(1<<1),		/* mouse interrupt enable */
178*a81c3ea0SDavid du Colombier 	Ckbdint=	(1<<0),		/* kbd interrupt enable */
179*a81c3ea0SDavid du Colombier };
180*a81c3ea0SDavid du Colombier 
181*a81c3ea0SDavid du Colombier int mouseshifted;
182*a81c3ea0SDavid du Colombier void (*kbdmouse)(int);
183*a81c3ea0SDavid du Colombier 
184*a81c3ea0SDavid du Colombier static Lock i8042lock;
185*a81c3ea0SDavid du Colombier static uchar ccc;
186*a81c3ea0SDavid du Colombier static void (*auxputc)(int, int);
187*a81c3ea0SDavid du Colombier static int nokbd = 1;			/* flag: no PS/2 keyboard */
188*a81c3ea0SDavid du Colombier 
outready(void)189*a81c3ea0SDavid du Colombier /*
190*a81c3ea0SDavid du Colombier  *  wait for output no longer busy
191*a81c3ea0SDavid du Colombier  */
192*a81c3ea0SDavid du Colombier static int
193*a81c3ea0SDavid du Colombier outready(void)
194*a81c3ea0SDavid du Colombier {
195*a81c3ea0SDavid du Colombier 	int tries;
196*a81c3ea0SDavid du Colombier 
197*a81c3ea0SDavid du Colombier 	for(tries = 0; (inb(Status) & Outbusy); tries++){
198*a81c3ea0SDavid du Colombier 		if(tries > 500)
199*a81c3ea0SDavid du Colombier 			return -1;
200*a81c3ea0SDavid du Colombier 		delay(2);
201*a81c3ea0SDavid du Colombier 	}
202*a81c3ea0SDavid du Colombier 	return 0;
203*a81c3ea0SDavid du Colombier }
204*a81c3ea0SDavid du Colombier 
inready(void)205*a81c3ea0SDavid du Colombier /*
206*a81c3ea0SDavid du Colombier  *  wait for input
207*a81c3ea0SDavid du Colombier  */
208*a81c3ea0SDavid du Colombier static int
209*a81c3ea0SDavid du Colombier inready(void)
210*a81c3ea0SDavid du Colombier {
211*a81c3ea0SDavid du Colombier 	int tries;
212*a81c3ea0SDavid du Colombier 
213*a81c3ea0SDavid du Colombier 	for(tries = 0; !(inb(Status) & Inready); tries++){
214*a81c3ea0SDavid du Colombier 		if(tries > 500)
215*a81c3ea0SDavid du Colombier 			return -1;
216*a81c3ea0SDavid du Colombier 		delay(2);
217*a81c3ea0SDavid du Colombier 	}
218*a81c3ea0SDavid du Colombier 	return 0;
219*a81c3ea0SDavid du Colombier }
220*a81c3ea0SDavid du Colombier 
221*a81c3ea0SDavid du Colombier int
222*a81c3ea0SDavid du Colombier i8042auxcmd(int cmd)
223*a81c3ea0SDavid du Colombier {
224*a81c3ea0SDavid du Colombier 	unsigned int c;
225*a81c3ea0SDavid du Colombier 	int tries;
226*a81c3ea0SDavid du Colombier 	static int badkbd;
227*a81c3ea0SDavid du Colombier 
228*a81c3ea0SDavid du Colombier 	if(badkbd)
229*a81c3ea0SDavid du Colombier 		return -1;
230*a81c3ea0SDavid du Colombier 	c = 0;
231*a81c3ea0SDavid du Colombier 	tries = 0;
232*a81c3ea0SDavid du Colombier 
233*a81c3ea0SDavid du Colombier 	ilock(&i8042lock);
234*a81c3ea0SDavid du Colombier 	do{
235*a81c3ea0SDavid du Colombier 		if(tries++ > 2)
236*a81c3ea0SDavid du Colombier 			break;
237*a81c3ea0SDavid du Colombier 		if(outready() < 0)
238*a81c3ea0SDavid du Colombier 			break;
239*a81c3ea0SDavid du Colombier 		outb(Cmd, 0xD4);
240*a81c3ea0SDavid du Colombier 		if(outready() < 0)
241*a81c3ea0SDavid du Colombier 			break;
242*a81c3ea0SDavid du Colombier 		outb(Data, cmd);
243*a81c3ea0SDavid du Colombier 		if(outready() < 0)
244*a81c3ea0SDavid du Colombier 			break;
245*a81c3ea0SDavid du Colombier 		if(inready() < 0)
246*a81c3ea0SDavid du Colombier 			break;
247*a81c3ea0SDavid du Colombier 		c = inb(Data);
248*a81c3ea0SDavid du Colombier 	} while(c == 0xFE || c == 0);
249*a81c3ea0SDavid du Colombier 	iunlock(&i8042lock);
250*a81c3ea0SDavid du Colombier 
251*a81c3ea0SDavid du Colombier 	if(c != 0xFA){
252*a81c3ea0SDavid du Colombier 		print("i8042: %2.2ux returned to the %2.2ux command\n", c, cmd);
253*a81c3ea0SDavid du Colombier 		badkbd = 1;	/* don't keep trying; there might not be one */
254*a81c3ea0SDavid du Colombier 		return -1;
255*a81c3ea0SDavid du Colombier 	}
i8042auxcmds(uchar * cmd,int ncmd)256*a81c3ea0SDavid du Colombier 	return 0;
257*a81c3ea0SDavid du Colombier }
258*a81c3ea0SDavid du Colombier 
259*a81c3ea0SDavid du Colombier int
260*a81c3ea0SDavid du Colombier i8042auxcmds(uchar *cmd, int ncmd)
261*a81c3ea0SDavid du Colombier {
262*a81c3ea0SDavid du Colombier 	int i;
263*a81c3ea0SDavid du Colombier 
264*a81c3ea0SDavid du Colombier 	ilock(&i8042lock);
265*a81c3ea0SDavid du Colombier 	for(i=0; i<ncmd; i++){
266*a81c3ea0SDavid du Colombier 		if(outready() < 0)
267*a81c3ea0SDavid du Colombier 			break;
268*a81c3ea0SDavid du Colombier 		outb(Cmd, 0xD4);
269*a81c3ea0SDavid du Colombier 		if(outready() < 0)
270*a81c3ea0SDavid du Colombier 			break;
271*a81c3ea0SDavid du Colombier 		outb(Data, cmd[i]);
272*a81c3ea0SDavid du Colombier 	}
273*a81c3ea0SDavid du Colombier 	iunlock(&i8042lock);
274*a81c3ea0SDavid du Colombier 	return i;
275*a81c3ea0SDavid du Colombier }
276*a81c3ea0SDavid du Colombier 
277*a81c3ea0SDavid du Colombier typedef struct Kbscan Kbscan;
278*a81c3ea0SDavid du Colombier struct Kbscan {
279*a81c3ea0SDavid du Colombier 	int	esc1;
280*a81c3ea0SDavid du Colombier 	int	esc2;
281*a81c3ea0SDavid du Colombier 	int	alt;
282*a81c3ea0SDavid du Colombier 	int	altgr;
283*a81c3ea0SDavid du Colombier 	int	caps;
284*a81c3ea0SDavid du Colombier 	int	ctl;
285*a81c3ea0SDavid du Colombier 	int	num;
286*a81c3ea0SDavid du Colombier 	int	shift;
287*a81c3ea0SDavid du Colombier 	int	collecting;
288*a81c3ea0SDavid du Colombier 	int	nk;
289*a81c3ea0SDavid du Colombier 	Rune	kc[5];
290*a81c3ea0SDavid du Colombier 	int	buttons;
291*a81c3ea0SDavid du Colombier };
292*a81c3ea0SDavid du Colombier 
293*a81c3ea0SDavid du Colombier Kbscan kbscans[Nscans];	/* kernel and external scan code state */
294*a81c3ea0SDavid du Colombier 
295*a81c3ea0SDavid du Colombier static int kdebug;
296*a81c3ea0SDavid du Colombier 
297*a81c3ea0SDavid du Colombier /*
298*a81c3ea0SDavid du Colombier  * set keyboard's leds for lock states (scroll, numeric, caps).
299*a81c3ea0SDavid du Colombier  *
300*a81c3ea0SDavid du Colombier  * at least one keyboard (from Qtronics) also sets its numeric-lock
301*a81c3ea0SDavid du Colombier  * behaviour to match the led state, though it has no numeric keypad,
302*a81c3ea0SDavid du Colombier  * and some BIOSes bring the system up with numeric-lock set and no
303*a81c3ea0SDavid du Colombier  * setting to change that.  this combination steals the keys for these
setleds(Kbscan * kbscan)304*a81c3ea0SDavid du Colombier  * characters and makes it impossible to generate them: uiolkjm&*().
305*a81c3ea0SDavid du Colombier  * thus we'd like to be able to force the numeric-lock led (and behaviour) off.
306*a81c3ea0SDavid du Colombier  */
307*a81c3ea0SDavid du Colombier static void
308*a81c3ea0SDavid du Colombier setleds(Kbscan *kbscan)
309*a81c3ea0SDavid du Colombier {
310*a81c3ea0SDavid du Colombier 	int leds;
311*a81c3ea0SDavid du Colombier 	uchar dummy;
312*a81c3ea0SDavid du Colombier 
313*a81c3ea0SDavid du Colombier 	SET(dummy);
314*a81c3ea0SDavid du Colombier 	if(nokbd || kbscan != &kbscans[Int])
315*a81c3ea0SDavid du Colombier 		return;
316*a81c3ea0SDavid du Colombier 	leds = 0;
317*a81c3ea0SDavid du Colombier 	if(kbscan->num)
318*a81c3ea0SDavid du Colombier 		leds |= 1<<1;
319*a81c3ea0SDavid du Colombier 	if(0 && kbscan->caps)		/* we don't implement caps lock */
320*a81c3ea0SDavid du Colombier 		leds |= 1<<2;
321*a81c3ea0SDavid du Colombier 
322*a81c3ea0SDavid du Colombier 	ilock(&i8042lock);
323*a81c3ea0SDavid du Colombier 	outready();
324*a81c3ea0SDavid du Colombier 	outb(Data, 0xed);		/* `reset keyboard lock states' */
325*a81c3ea0SDavid du Colombier 	if(inready() == 0)
326*a81c3ea0SDavid du Colombier 		dummy = inb(Data);
327*a81c3ea0SDavid du Colombier 
328*a81c3ea0SDavid du Colombier 	outready();
329*a81c3ea0SDavid du Colombier 	outb(Data, leds);
330*a81c3ea0SDavid du Colombier 	if(inready() == 0)
331*a81c3ea0SDavid du Colombier 		dummy = inb(Data);
332*a81c3ea0SDavid du Colombier 
333*a81c3ea0SDavid du Colombier 	outready();
334*a81c3ea0SDavid du Colombier 	iunlock(&i8042lock);
335*a81c3ea0SDavid du Colombier 	USED(dummy);
336*a81c3ea0SDavid du Colombier }
337*a81c3ea0SDavid du Colombier 
kbdputsc(int c,int external)338*a81c3ea0SDavid du Colombier /*
339*a81c3ea0SDavid du Colombier  * Scan code processing
340*a81c3ea0SDavid du Colombier  */
341*a81c3ea0SDavid du Colombier void
342*a81c3ea0SDavid du Colombier kbdputsc(int c, int external)
343*a81c3ea0SDavid du Colombier {
344*a81c3ea0SDavid du Colombier 	int i, keyup;
345*a81c3ea0SDavid du Colombier 	Kbscan *kbscan;
346*a81c3ea0SDavid du Colombier 
347*a81c3ea0SDavid du Colombier 	if(external)
348*a81c3ea0SDavid du Colombier 		kbscan = &kbscans[Ext];
349*a81c3ea0SDavid du Colombier 	else
350*a81c3ea0SDavid du Colombier 		kbscan = &kbscans[Int];
351*a81c3ea0SDavid du Colombier 
352*a81c3ea0SDavid du Colombier 	if(kdebug)
353*a81c3ea0SDavid du Colombier 		print("sc %x ms %d\n", c, mouseshifted);
354*a81c3ea0SDavid du Colombier 	/*
355*a81c3ea0SDavid du Colombier 	 *  e0's is the first of a 2 character sequence, e1 the first
356*a81c3ea0SDavid du Colombier 	 *  of a 3 character sequence (on the safari)
357*a81c3ea0SDavid du Colombier 	 */
358*a81c3ea0SDavid du Colombier 	if(c == 0xe0){
359*a81c3ea0SDavid du Colombier 		kbscan->esc1 = 1;
360*a81c3ea0SDavid du Colombier 		return;
361*a81c3ea0SDavid du Colombier 	} else if(c == 0xe1){
362*a81c3ea0SDavid du Colombier 		kbscan->esc2 = 2;
363*a81c3ea0SDavid du Colombier 		return;
364*a81c3ea0SDavid du Colombier 	}
365*a81c3ea0SDavid du Colombier 
366*a81c3ea0SDavid du Colombier 	keyup = c & 0x80;
367*a81c3ea0SDavid du Colombier 	c &= 0x7f;
368*a81c3ea0SDavid du Colombier 	if(c > sizeof kbtab){
369*a81c3ea0SDavid du Colombier 		c |= keyup;
370*a81c3ea0SDavid du Colombier 		if(c != 0xFF)	/* these come fairly often: CAPSLOCK U Y */
371*a81c3ea0SDavid du Colombier 			print("unknown key %ux\n", c);
372*a81c3ea0SDavid du Colombier 		return;
373*a81c3ea0SDavid du Colombier 	}
374*a81c3ea0SDavid du Colombier 
375*a81c3ea0SDavid du Colombier 	if(kbscan->esc1){
376*a81c3ea0SDavid du Colombier 		c = kbtabesc1[c];
377*a81c3ea0SDavid du Colombier 		kbscan->esc1 = 0;
378*a81c3ea0SDavid du Colombier 	} else if(kbscan->esc2){
379*a81c3ea0SDavid du Colombier 		kbscan->esc2--;
380*a81c3ea0SDavid du Colombier 		return;
381*a81c3ea0SDavid du Colombier 	} else if(kbscan->shift)
382*a81c3ea0SDavid du Colombier 		c = kbtabshift[c];
383*a81c3ea0SDavid du Colombier 	else if(kbscan->altgr)
384*a81c3ea0SDavid du Colombier 		c = kbtabaltgr[c];
385*a81c3ea0SDavid du Colombier 	else if(kbscan->ctl)
386*a81c3ea0SDavid du Colombier 		c = kbtabctrl[c];
387*a81c3ea0SDavid du Colombier 	else
388*a81c3ea0SDavid du Colombier 		c = kbtab[c];
389*a81c3ea0SDavid du Colombier 
390*a81c3ea0SDavid du Colombier 	if(kbscan->caps && c<='z' && c>='a')
391*a81c3ea0SDavid du Colombier 		c += 'A' - 'a';
392*a81c3ea0SDavid du Colombier 
393*a81c3ea0SDavid du Colombier 	/*
394*a81c3ea0SDavid du Colombier 	 *  keyup only important for shifts
395*a81c3ea0SDavid du Colombier 	 */
396*a81c3ea0SDavid du Colombier 	if(keyup){
397*a81c3ea0SDavid du Colombier 		switch(c){
398*a81c3ea0SDavid du Colombier 		case Latin:
399*a81c3ea0SDavid du Colombier 			kbscan->alt = 0;
400*a81c3ea0SDavid du Colombier 			break;
401*a81c3ea0SDavid du Colombier 		case Shift:
402*a81c3ea0SDavid du Colombier 			kbscan->shift = 0;
403*a81c3ea0SDavid du Colombier 			mouseshifted = 0;
404*a81c3ea0SDavid du Colombier 			if(kdebug)
405*a81c3ea0SDavid du Colombier 				print("shiftclr\n");
406*a81c3ea0SDavid du Colombier 			break;
407*a81c3ea0SDavid du Colombier 		case Ctrl:
408*a81c3ea0SDavid du Colombier 			kbscan->ctl = 0;
409*a81c3ea0SDavid du Colombier 			break;
410*a81c3ea0SDavid du Colombier 		case Altgr:
411*a81c3ea0SDavid du Colombier 			kbscan->altgr = 0;
412*a81c3ea0SDavid du Colombier 			break;
413*a81c3ea0SDavid du Colombier 		case Kmouse|1:
414*a81c3ea0SDavid du Colombier 		case Kmouse|2:
415*a81c3ea0SDavid du Colombier 		case Kmouse|3:
416*a81c3ea0SDavid du Colombier 		case Kmouse|4:
417*a81c3ea0SDavid du Colombier 		case Kmouse|5:
418*a81c3ea0SDavid du Colombier 			kbscan->buttons &= ~(1<<(c-Kmouse-1));
419*a81c3ea0SDavid du Colombier 			if(kbdmouse)
420*a81c3ea0SDavid du Colombier 				kbdmouse(kbscan->buttons);
421*a81c3ea0SDavid du Colombier 			break;
422*a81c3ea0SDavid du Colombier 		}
423*a81c3ea0SDavid du Colombier 		return;
424*a81c3ea0SDavid du Colombier 	}
425*a81c3ea0SDavid du Colombier 
426*a81c3ea0SDavid du Colombier 	/*
427*a81c3ea0SDavid du Colombier 	 *  normal character
428*a81c3ea0SDavid du Colombier 	 */
429*a81c3ea0SDavid du Colombier 	if(!(c & (Spec|KF))){
430*a81c3ea0SDavid du Colombier 		if(kbscan->ctl)
431*a81c3ea0SDavid du Colombier 			if(kbscan->alt && c == Del)
432*a81c3ea0SDavid du Colombier 				exit(0);
433*a81c3ea0SDavid du Colombier 		if(!kbscan->collecting){
434*a81c3ea0SDavid du Colombier 			kbdputc(kbdq, c);
435*a81c3ea0SDavid du Colombier 			return;
436*a81c3ea0SDavid du Colombier 		}
437*a81c3ea0SDavid du Colombier 		kbscan->kc[kbscan->nk++] = c;
438*a81c3ea0SDavid du Colombier 		c = latin1(kbscan->kc, kbscan->nk);
439*a81c3ea0SDavid du Colombier 		if(c < -1)	/* need more keystrokes */
440*a81c3ea0SDavid du Colombier 			return;
441*a81c3ea0SDavid du Colombier 		if(c != -1)	/* valid sequence */
442*a81c3ea0SDavid du Colombier 			kbdputc(kbdq, c);
443*a81c3ea0SDavid du Colombier 		else	/* dump characters */
444*a81c3ea0SDavid du Colombier 			for(i=0; i<kbscan->nk; i++)
445*a81c3ea0SDavid du Colombier 				kbdputc(kbdq, kbscan->kc[i]);
446*a81c3ea0SDavid du Colombier 		kbscan->nk = 0;
447*a81c3ea0SDavid du Colombier 		kbscan->collecting = 0;
448*a81c3ea0SDavid du Colombier 		return;
449*a81c3ea0SDavid du Colombier 	} else {
450*a81c3ea0SDavid du Colombier 		switch(c){
451*a81c3ea0SDavid du Colombier 		case Caps:
452*a81c3ea0SDavid du Colombier 			kbscan->caps ^= 1;
453*a81c3ea0SDavid du Colombier 			return;
454*a81c3ea0SDavid du Colombier 		case Num:
455*a81c3ea0SDavid du Colombier 			kbscan->num ^= 1;
456*a81c3ea0SDavid du Colombier 			if(!external)
457*a81c3ea0SDavid du Colombier 				setleds(kbscan);
458*a81c3ea0SDavid du Colombier 			return;
459*a81c3ea0SDavid du Colombier 		case Shift:
460*a81c3ea0SDavid du Colombier 			kbscan->shift = 1;
461*a81c3ea0SDavid du Colombier 			if(kdebug)
462*a81c3ea0SDavid du Colombier 				print("shift\n");
463*a81c3ea0SDavid du Colombier 			mouseshifted = 1;
464*a81c3ea0SDavid du Colombier 			return;
465*a81c3ea0SDavid du Colombier 		case Latin:
466*a81c3ea0SDavid du Colombier 			kbscan->alt = 1;
467*a81c3ea0SDavid du Colombier 			/*
468*a81c3ea0SDavid du Colombier 			 * VMware and Qemu use Ctl-Alt as the key combination
469*a81c3ea0SDavid du Colombier 			 * to make the VM give up keyboard and mouse focus.
470*a81c3ea0SDavid du Colombier 			 * This has the unfortunate side effect that when you
471*a81c3ea0SDavid du Colombier 			 * come back into focus, Plan 9 thinks you want to type
472*a81c3ea0SDavid du Colombier 			 * a compose sequence (you just typed alt).
473*a81c3ea0SDavid du Colombier 			 *
474*a81c3ea0SDavid du Colombier 			 * As a clumsy hack around this, we look for ctl-alt
475*a81c3ea0SDavid du Colombier 			 * and don't treat it as the start of a compose sequence.
476*a81c3ea0SDavid du Colombier 			 */
477*a81c3ea0SDavid du Colombier 			if(!kbscan->ctl){
478*a81c3ea0SDavid du Colombier 				kbscan->collecting = 1;
479*a81c3ea0SDavid du Colombier 				kbscan->nk = 0;
480*a81c3ea0SDavid du Colombier 			}
481*a81c3ea0SDavid du Colombier 			return;
482*a81c3ea0SDavid du Colombier 		case Ctrl:
483*a81c3ea0SDavid du Colombier 			kbscan->ctl = 1;
484*a81c3ea0SDavid du Colombier 			return;
485*a81c3ea0SDavid du Colombier 		case Altgr:
486*a81c3ea0SDavid du Colombier 			kbscan->altgr = 1;
487*a81c3ea0SDavid du Colombier 			return;
488*a81c3ea0SDavid du Colombier 		case Kmouse|1:
489*a81c3ea0SDavid du Colombier 		case Kmouse|2:
490*a81c3ea0SDavid du Colombier 		case Kmouse|3:
491*a81c3ea0SDavid du Colombier 		case Kmouse|4:
492*a81c3ea0SDavid du Colombier 		case Kmouse|5:
493*a81c3ea0SDavid du Colombier 			kbscan->buttons |= 1<<(c-Kmouse-1);
494*a81c3ea0SDavid du Colombier 			if(kbdmouse)
495*a81c3ea0SDavid du Colombier 				kbdmouse(kbscan->buttons);
496*a81c3ea0SDavid du Colombier 			return;
497*a81c3ea0SDavid du Colombier 		case KF|11:
498*a81c3ea0SDavid du Colombier 			print("kbd debug on, F12 turns it off\n");
499*a81c3ea0SDavid du Colombier 			kdebug = 1;
500*a81c3ea0SDavid du Colombier 			break;
501*a81c3ea0SDavid du Colombier 		case KF|12:
502*a81c3ea0SDavid du Colombier 			kdebug = 0;
503*a81c3ea0SDavid du Colombier 			break;
504*a81c3ea0SDavid du Colombier 		}
505*a81c3ea0SDavid du Colombier 	}
506*a81c3ea0SDavid du Colombier 	kbdputc(kbdq, c);
507*a81c3ea0SDavid du Colombier }
508*a81c3ea0SDavid du Colombier 
i8042intr(Ureg *,void *)509*a81c3ea0SDavid du Colombier /*
510*a81c3ea0SDavid du Colombier  *  keyboard interrupt
511*a81c3ea0SDavid du Colombier  */
512*a81c3ea0SDavid du Colombier static void
513*a81c3ea0SDavid du Colombier i8042intr(Ureg*, void*)
514*a81c3ea0SDavid du Colombier {
515*a81c3ea0SDavid du Colombier 	int s, c;
516*a81c3ea0SDavid du Colombier 
517*a81c3ea0SDavid du Colombier 	/*
518*a81c3ea0SDavid du Colombier 	 *  get status
519*a81c3ea0SDavid du Colombier 	 */
520*a81c3ea0SDavid du Colombier 	ilock(&i8042lock);
521*a81c3ea0SDavid du Colombier 	s = inb(Status);
522*a81c3ea0SDavid du Colombier 	if(!(s&Inready)){
523*a81c3ea0SDavid du Colombier 		iunlock(&i8042lock);
524*a81c3ea0SDavid du Colombier 		return;
525*a81c3ea0SDavid du Colombier 	}
526*a81c3ea0SDavid du Colombier 
527*a81c3ea0SDavid du Colombier 	/*
528*a81c3ea0SDavid du Colombier 	 *  get the character
529*a81c3ea0SDavid du Colombier 	 */
530*a81c3ea0SDavid du Colombier 	c = inb(Data);
531*a81c3ea0SDavid du Colombier 	iunlock(&i8042lock);
532*a81c3ea0SDavid du Colombier 
533*a81c3ea0SDavid du Colombier 	/*
534*a81c3ea0SDavid du Colombier 	 *  if it's the aux port...
535*a81c3ea0SDavid du Colombier 	 */
536*a81c3ea0SDavid du Colombier 	if(s & Minready){
537*a81c3ea0SDavid du Colombier 		if(auxputc != nil)
538*a81c3ea0SDavid du Colombier 			auxputc(c, kbscans[Int].shift);
539*a81c3ea0SDavid du Colombier 		return;
540*a81c3ea0SDavid du Colombier 	}
541*a81c3ea0SDavid du Colombier 
542*a81c3ea0SDavid du Colombier 	kbdputsc(c, Int);
543*a81c3ea0SDavid du Colombier }
544*a81c3ea0SDavid du Colombier 
545*a81c3ea0SDavid du Colombier void
546*a81c3ea0SDavid du Colombier i8042auxenable(void (*putc)(int, int))
547*a81c3ea0SDavid du Colombier {
548*a81c3ea0SDavid du Colombier 	char *err = "i8042: aux init failed\n";
549*a81c3ea0SDavid du Colombier 
550*a81c3ea0SDavid du Colombier 	/* enable kbd/aux xfers and interrupts */
551*a81c3ea0SDavid du Colombier 	ccc &= ~Cauxdis;
552*a81c3ea0SDavid du Colombier 	ccc |= Cauxint;
553*a81c3ea0SDavid du Colombier 
554*a81c3ea0SDavid du Colombier 	ilock(&i8042lock);
555*a81c3ea0SDavid du Colombier 	if(outready() < 0)
556*a81c3ea0SDavid du Colombier 		print(err);
557*a81c3ea0SDavid du Colombier 	outb(Cmd, 0x60);			/* write control register */
558*a81c3ea0SDavid du Colombier 	if(outready() < 0)
559*a81c3ea0SDavid du Colombier 		print(err);
560*a81c3ea0SDavid du Colombier 	outb(Data, ccc);
561*a81c3ea0SDavid du Colombier 	if(outready() < 0)
562*a81c3ea0SDavid du Colombier 		print(err);
563*a81c3ea0SDavid du Colombier 	outb(Cmd, 0xA8);			/* auxiliary device enable */
564*a81c3ea0SDavid du Colombier 	if(outready() < 0){
565*a81c3ea0SDavid du Colombier 		iunlock(&i8042lock);
566*a81c3ea0SDavid du Colombier 		return;
567*a81c3ea0SDavid du Colombier 	}
568*a81c3ea0SDavid du Colombier 	auxputc = putc;
569*a81c3ea0SDavid du Colombier 	intrenable(IL8259, i8042intr, 0, IrqAUX);
570*a81c3ea0SDavid du Colombier 	iunlock(&i8042lock);
571*a81c3ea0SDavid du Colombier }
outbyte(int port,int c)572*a81c3ea0SDavid du Colombier 
573*a81c3ea0SDavid du Colombier static char *initfailed = "i8042: kbdinit failed\n";
574*a81c3ea0SDavid du Colombier 
575*a81c3ea0SDavid du Colombier static int
576*a81c3ea0SDavid du Colombier outbyte(int port, int c)
577*a81c3ea0SDavid du Colombier {
578*a81c3ea0SDavid du Colombier 	outb(port, c);
579*a81c3ea0SDavid du Colombier 	if(outready() < 0) {
580*a81c3ea0SDavid du Colombier 		print(initfailed);
581*a81c3ea0SDavid du Colombier 		return -1;
582*a81c3ea0SDavid du Colombier 	}
kbdinit(void)583*a81c3ea0SDavid du Colombier 	return 0;
584*a81c3ea0SDavid du Colombier }
585*a81c3ea0SDavid du Colombier 
586*a81c3ea0SDavid du Colombier void
587*a81c3ea0SDavid du Colombier kbdinit(void)
588*a81c3ea0SDavid du Colombier {
589*a81c3ea0SDavid du Colombier 	int c, try;
590*a81c3ea0SDavid du Colombier 	uchar dummy;
591*a81c3ea0SDavid du Colombier 
592*a81c3ea0SDavid du Colombier 	SET(dummy);
593*a81c3ea0SDavid du Colombier 	kbdq = qopen(4*1024, 0, 0, 0);
594*a81c3ea0SDavid du Colombier 	if(kbdq == nil)
595*a81c3ea0SDavid du Colombier 		panic("kbdinit");
596*a81c3ea0SDavid du Colombier 	qnoblock(kbdq, 1);
597*a81c3ea0SDavid du Colombier 
598*a81c3ea0SDavid du Colombier 	/* wait for a quiescent controller */
599*a81c3ea0SDavid du Colombier 	try = 500;
600*a81c3ea0SDavid du Colombier 	while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) {
601*a81c3ea0SDavid du Colombier 		if(c & Inready)
602*a81c3ea0SDavid du Colombier 			dummy = inb(Data);
603*a81c3ea0SDavid du Colombier 		delay(1);
604*a81c3ea0SDavid du Colombier 	}
605*a81c3ea0SDavid du Colombier 	if (try <= 0) {
606*a81c3ea0SDavid du Colombier 		print(initfailed);
607*a81c3ea0SDavid du Colombier 		return;
608*a81c3ea0SDavid du Colombier 	}
609*a81c3ea0SDavid du Colombier 
610*a81c3ea0SDavid du Colombier 	/* get current controller command byte */
611*a81c3ea0SDavid du Colombier 	outb(Cmd, 0x20);
612*a81c3ea0SDavid du Colombier 	if(inready() < 0){
613*a81c3ea0SDavid du Colombier 		print("i8042: kbdinit can't read ccc\n");
614*a81c3ea0SDavid du Colombier 		ccc = 0;
615*a81c3ea0SDavid du Colombier 	} else
616*a81c3ea0SDavid du Colombier 		ccc = inb(Data);
617*a81c3ea0SDavid du Colombier 
618*a81c3ea0SDavid du Colombier 	/* enable kbd xfers and interrupts */
619*a81c3ea0SDavid du Colombier 	ccc &= ~Ckbddis;
620*a81c3ea0SDavid du Colombier 	ccc |= Csf | Ckbdint | Cscs1;
621*a81c3ea0SDavid du Colombier 	if(outready() < 0) {
622*a81c3ea0SDavid du Colombier 		print(initfailed);
623*a81c3ea0SDavid du Colombier 		return;
624*a81c3ea0SDavid du Colombier 	}
625*a81c3ea0SDavid du Colombier 
626*a81c3ea0SDavid du Colombier 	nokbd = 0;
627*a81c3ea0SDavid du Colombier 
628*a81c3ea0SDavid du Colombier 	/* disable mouse */
629*a81c3ea0SDavid du Colombier 	if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0)
630*a81c3ea0SDavid du Colombier 		print("i8042: kbdinit mouse disable failed\n");
631*a81c3ea0SDavid du Colombier 
632*a81c3ea0SDavid du Colombier 	/* see http://www.computer-engineering.org/ps2keyboard for codes */
633*a81c3ea0SDavid du Colombier 	if(getconf("*typematic") != nil)
634*a81c3ea0SDavid du Colombier 		/* set typematic rate/delay (0 -> delay=250ms & rate=30cps) */
635*a81c3ea0SDavid du Colombier 		if(outbyte(Data, 0xf3) < 0 || outbyte(Data, 0) < 0)
636*a81c3ea0SDavid du Colombier 			print("i8042: kbdinit set typematic rate failed\n");
637*a81c3ea0SDavid du Colombier 
638*a81c3ea0SDavid du Colombier 	intrenable(IL8259, i8042intr, 0, IrqKBD);
639*a81c3ea0SDavid du Colombier 
640*a81c3ea0SDavid du Colombier 	kbscans[Int].num = 0;
641*a81c3ea0SDavid du Colombier 	setleds(&kbscans[Int]);
kbdputmap(ushort m,ushort scanc,Rune r)642*a81c3ea0SDavid du Colombier 	USED(dummy);
643*a81c3ea0SDavid du Colombier }
644*a81c3ea0SDavid du Colombier 
645*a81c3ea0SDavid du Colombier void
646*a81c3ea0SDavid du Colombier kbdputmap(ushort m, ushort scanc, Rune r)
647*a81c3ea0SDavid du Colombier {
648*a81c3ea0SDavid du Colombier 	if(scanc >= Nscan)
649*a81c3ea0SDavid du Colombier 		error(Ebadarg);
650*a81c3ea0SDavid du Colombier 	switch(m) {
651*a81c3ea0SDavid du Colombier 	default:
652*a81c3ea0SDavid du Colombier 		error(Ebadarg);
653*a81c3ea0SDavid du Colombier 	case 0:
654*a81c3ea0SDavid du Colombier 		kbtab[scanc] = r;
655*a81c3ea0SDavid du Colombier 		break;
656*a81c3ea0SDavid du Colombier 	case 1:
657*a81c3ea0SDavid du Colombier 		kbtabshift[scanc] = r;
658*a81c3ea0SDavid du Colombier 		break;
659*a81c3ea0SDavid du Colombier 	case 2:
660*a81c3ea0SDavid du Colombier 		kbtabesc1[scanc] = r;
661*a81c3ea0SDavid du Colombier 		break;
662*a81c3ea0SDavid du Colombier 	case 3:
663*a81c3ea0SDavid du Colombier 		kbtabaltgr[scanc] = r;
664*a81c3ea0SDavid du Colombier 		break;
665*a81c3ea0SDavid du Colombier 	case 4:
666*a81c3ea0SDavid du Colombier 		kbtabctrl[scanc] = r;
667*a81c3ea0SDavid du Colombier 		break;
kbdgetmap(uint offset,int * t,int * sc,Rune * r)668*a81c3ea0SDavid du Colombier 	}
669*a81c3ea0SDavid du Colombier }
670*a81c3ea0SDavid du Colombier 
671*a81c3ea0SDavid du Colombier int
672*a81c3ea0SDavid du Colombier kbdgetmap(uint offset, int *t, int *sc, Rune *r)
673*a81c3ea0SDavid du Colombier {
674*a81c3ea0SDavid du Colombier 	if ((int)offset < 0)
675*a81c3ea0SDavid du Colombier 		error(Ebadarg);
676*a81c3ea0SDavid du Colombier 	*t = offset/Nscan;
677*a81c3ea0SDavid du Colombier 	*sc = offset%Nscan;
678*a81c3ea0SDavid du Colombier 	switch(*t) {
679*a81c3ea0SDavid du Colombier 	default:
680*a81c3ea0SDavid du Colombier 		return 0;
681*a81c3ea0SDavid du Colombier 	case 0:
682*a81c3ea0SDavid du Colombier 		*r = kbtab[*sc];
683*a81c3ea0SDavid du Colombier 		return 1;
684*a81c3ea0SDavid du Colombier 	case 1:
685*a81c3ea0SDavid du Colombier 		*r = kbtabshift[*sc];
686*a81c3ea0SDavid du Colombier 		return 1;
687*a81c3ea0SDavid du Colombier 	case 2:
688*a81c3ea0SDavid du Colombier 		*r = kbtabesc1[*sc];
689*a81c3ea0SDavid du Colombier 		return 1;
690*a81c3ea0SDavid du Colombier 	case 3:
691*a81c3ea0SDavid du Colombier 		*r = kbtabaltgr[*sc];
692*a81c3ea0SDavid du Colombier 		return 1;
693*a81c3ea0SDavid du Colombier 	case 4:
694 		*r = kbtabctrl[*sc];
695 		return 1;
696 	}
697 }
698