5 #include "../port/lib.h"
10 #include "../port/error.h"
13 Data= 0x40+3, /* data port */
14 Cmd= 0x44+3, /* command port (write) */
15 Status= 0x44+3, /* status port (read) */
16 Inready= 0x01, /* input character ready */
17 Outbusy= 0x02, /* output busy */
18 Sysflag= 0x04, /* system flag */
19 Cmddata= 0x08, /* cmd==0, data==1 */
20 Inhibit= 0x10, /* keyboard/mouse inhibited */
21 Minready= 0x20, /* mouse character ready */
22 Rtimeout= 0x40, /* general timeout */
28 /* controller command byte */
29 Cscs1= (1<<6), /* scan code set 1 */
30 Cauxdis= (1<<5), /* mouse disable */
31 Ckbddis= (1<<4), /* kbd disable */
32 Csf= (1<<2), /* system flag */
33 Cauxint= (1<<1), /* mouse interrupt enable */
34 Ckbdint= (1<<0), /* kbd interrupt enable */
43 static Dirtab kbdtab[] = {
44 ".", {Qdir, 0, QTDIR}, 0, 0555,
45 "scancode", {Qscancode, 0}, 0, 0440,
46 "leds", {Qleds, 0}, 0, 0220,
49 static Lock i8042lock;
50 static uchar ccc, dummy;
59 #define inb(r) (dummy=kbd.io[r])
60 #define outb(r,b) (kbd.io[r]=b)
63 * wait for output no longer busy
70 for(tries = 0; (inb(Status) & Outbusy); tries++){
86 for(tries = 0; !(inb(Status) & Inready); tries++){
95 * set keyboard's leds for lock states (scroll, numeric, caps).
97 * at least one keyboard (from Qtronics) also sets its numeric-lock
98 * behaviour to match the led state, though it has no numeric keypad,
99 * and some BIOSes bring the system up with numeric-lock set and no
100 * setting to change that. this combination steals the keys for these
101 * characters and makes it impossible to generate them: uiolkjm&*().
102 * thus we'd like to be able to force the numeric-lock led (and behaviour) off.
109 if(!conf.keyboard || leds == old)
116 outb(Data, 0xed); /* `reset keyboard lock states' */
132 i8042intr(Ureg*, void*)
134 extern void sgimouseputc(int);
158 * if it's the aux port...
165 qproduce(kbd.q, &b, 1);
175 kbdattach(char *spec)
177 return devattach(L'b', spec);
181 kbdwalk(Chan *c, Chan *nc, char **name, int nname)
183 return devwalk(c, nc, name, nname, kbdtab, nelem(kbdtab), devgen);
187 kbdstat(Chan *c, uchar *dp, int n)
189 return devstat(c, dp, n, kbdtab, nelem(kbdtab), devgen);
193 kbdopen(Chan *c, int omode)
197 if(c->qid.path == Qscancode){
202 if(incref(&kbd.ref) != 1)
204 c = devopen(c, omode, kbdtab, nelem(kbdtab), devgen);
208 return devopen(c, omode, kbdtab, nelem(kbdtab), devgen);
214 if((c->flag & COPEN) && c->qid.path == Qscancode)
219 kbdbread(Chan *c, long n, ulong off)
221 if(c->qid.path == Qscancode)
222 return qbread(kbd.q, n);
224 return devbread(c, n, off);
228 kbdread(Chan *c, void *a, long n, vlong)
230 if(c->qid.path == Qscancode)
231 return qread(kbd.q, a, n);
232 if(c->qid.path == Qdir)
233 return devdirread(c, a, n, kbdtab, nelem(kbdtab), devgen);
240 kbdwrite(Chan *c, void *a, long n, vlong)
244 if(c->qid.path != Qleds)
249 p = tmp + sizeof(tmp)-1;
250 memmove(tmp, a, p - tmp);
259 static char *initfailed = "i8042: kbdinit failed\n";
262 outbyte(int port, int c)
277 kbd.io = IO(uchar, HPC3_KBDMS);
278 kbd.q = qopen(1024, Qcoalesce, 0, 0);
280 panic("kbdinit: qopen");
283 /* wait for a quiescent controller */
285 while(try-- > 0 && (c = inb(Status)) & (Outbusy | Inready)) {
295 /* get current controller command byte */
298 print("i8042: kbdinit can't read ccc\n");
303 /* enable kbd xfers and interrupts */
305 ccc |= Csf | Ckbdint | Cscs1;
311 if (outbyte(Cmd, 0x60) < 0 || outbyte(Data, ccc) < 0){
312 print("i8042: kbdinit mouse disable failed\n");
317 addclock0link(pollintr, 5);