FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/kbdio.c
1 /*-
2 * Copyright (c) 1996 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: src/sys/i386/isa/kbdio.c,v 1.1.2.7 1999/09/05 08:13:07 peter Exp $
30 */
31
32 #include "sc.h"
33 #include "vt.h"
34 #include "psm.h"
35 #include "opt_kbdio.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/syslog.h>
40 #include <machine/clock.h>
41 #ifdef PC98
42 #include <pc98/pc98/pc98.h>
43 #else
44 #include <i386/isa/isa.h>
45 #endif
46 #include <i386/isa/isa_device.h>
47 #include <i386/isa/kbdio.h>
48
49 /*
50 * driver specific options: the following options may be set by
51 * `options' statements in the kernel configuration file.
52 */
53
54 /* retry count */
55 #ifndef KBD_MAXRETRY
56 #define KBD_MAXRETRY 3
57 #endif
58
59 /* timing parameters */
60 #ifndef KBD_RESETDELAY
61 #define KBD_RESETDELAY 200 /* wait 200msec after kbd/mouse reset */
62 #endif
63 #ifndef KBD_MAXWAIT
64 #define KBD_MAXWAIT 5 /* wait 5 times at most after reset */
65 #endif
66
67 /* I/O recovery time */
68 #ifdef PC98
69 #define KBDC_DELAYTIME 37
70 #define KBDD_DELAYTIME 37
71 #else
72 #define KBDC_DELAYTIME 20
73 #define KBDD_DELAYTIME 7
74 #endif
75
76 /* debug option */
77 #ifndef KBDIO_DEBUG
78 #define KBDIO_DEBUG 0
79 #endif
80
81 /* end of driver specific options */
82
83 /* constants */
84
85 #define NKBDC max(max(NSC, NVT), NPSM)
86 #define KBDQ_BUFSIZE 32
87
88 /* macros */
89
90 #ifndef max
91 #define max(x,y) ((x) > (y) ? (x) : (y))
92 #endif
93 #ifndef min
94 #define min(x,y) ((x) < (y) ? (x) : (y))
95 #endif
96
97 #define kbdcp(p) ((struct kbdc_softc *)(p))
98 #define nextq(i) (((i) + 1) % KBDQ_BUFSIZE)
99 #define availq(q) ((q)->head != (q)->tail)
100 #if KBDIO_DEBUG >= 2
101 #define emptyq(q) ((q)->tail = (q)->head = (q)->qcount = 0)
102 #else
103 #define emptyq(q) ((q)->tail = (q)->head = 0)
104 #endif
105
106 /* local variables */
107
108 typedef struct _kqueue {
109 int head;
110 int tail;
111 unsigned char q[KBDQ_BUFSIZE];
112 #if KBDIO_DEBUG >= 2
113 int call_count;
114 int qcount;
115 int max_qcount;
116 #endif
117 } kqueue;
118
119 struct kbdc_softc {
120 int port; /* base port address */
121 int command_byte; /* current command byte value */
122 int command_mask; /* command byte mask bits for kbd/aux devices */
123 int lock; /* FIXME: XXX not quite a semaphore... */
124 kqueue kbd; /* keyboard data queue */
125 kqueue aux; /* auxiliary data queue */
126 };
127
128 static struct kbdc_softc kbdc_softc[NKBDC] = { { 0 }, };
129
130 static int verbose = KBDIO_DEBUG;
131
132 /* function prototypes */
133
134 #ifndef PC98
135 static int addq(kqueue *q, int c);
136 static int removeq(kqueue *q);
137 static int wait_while_controller_busy(struct kbdc_softc *kbdc);
138 static int wait_for_data(struct kbdc_softc *kbdc);
139 #endif
140 static int wait_for_kbd_data(struct kbdc_softc *kbdc);
141 #ifndef PC98
142 static int wait_for_kbd_ack(struct kbdc_softc *kbdc);
143 static int wait_for_aux_data(struct kbdc_softc *kbdc);
144 static int wait_for_aux_ack(struct kbdc_softc *kbdc);
145 #endif
146
147 /* associate a port number with a KBDC */
148
149 KBDC
150 kbdc_open(int port)
151 {
152 #ifdef PC98
153 if (NKBDC) {
154 /* PC-98 has only one keyboard I/F */
155 kbdc_softc[0].port = port;
156 kbdc_softc[0].lock = FALSE;
157 return (KBDC)&kbdc_softc[0];
158 }
159 return NULL; /* You didn't include sc driver in your config file */
160 #else
161 int s;
162 int i;
163
164 s = spltty();
165 for (i = 0; i < NKBDC; ++i) {
166 if (kbdc_softc[i].port == port) {
167 splx(s);
168 return (KBDC) &kbdc_softc[i];
169 }
170 if (kbdc_softc[i].port <= 0) {
171 kbdc_softc[i].port = port;
172 kbdc_softc[i].command_byte = -1;
173 kbdc_softc[i].command_mask = 0;
174 kbdc_softc[i].lock = FALSE;
175 kbdc_softc[i].kbd.head = kbdc_softc[i].kbd.tail = 0;
176 kbdc_softc[i].aux.head = kbdc_softc[i].aux.tail = 0;
177 #if KBDIO_DEBUG >= 2
178 kbdc_softc[i].kbd.call_count = 0;
179 kbdc_softc[i].kbd.qcount = kbdc_softc[i].kbd.max_qcount = 0;
180 kbdc_softc[i].aux.call_count = 0;
181 kbdc_softc[i].aux.qcount = kbdc_softc[i].aux.max_qcount = 0;
182 #endif
183 splx(s);
184 return (KBDC) &kbdc_softc[i];
185 }
186 }
187 splx(s);
188 return NULL;
189 #endif
190 }
191
192 /*
193 * I/O access arbitration in `kbdio'
194 *
195 * The `kbdio' module uses a simplistic convention to arbitrate
196 * I/O access to the controller/keyboard/mouse. The convention requires
197 * close cooperation of the calling device driver.
198 *
199 * The device driver which utilizes the `kbdio' module are assumed to
200 * have the following set of routines.
201 * a. An interrupt handler (the bottom half of the driver).
202 * b. Timeout routines which may briefly polls the keyboard controller.
203 * c. Routines outside interrupt context (the top half of the driver).
204 * They should follow the rules below:
205 * 1. The interrupt handler may assume that it always has full access
206 * to the controller/keyboard/mouse.
207 * 2. The other routines must issue `spltty()' if they wish to
208 * prevent the interrupt handler from accessing
209 * the controller/keyboard/mouse.
210 * 3. The timeout routines and the top half routines of the device driver
211 * arbitrate I/O access by observing the lock flag in `kbdio'.
212 * The flag is manipulated via `kbdc_lock()'; when one wants to
213 * perform I/O, call `kbdc_lock(kbdc, TRUE)' and proceed only if
214 * the call returns with TRUE. Otherwise the caller must back off.
215 * Call `kbdc_lock(kbdc, FALSE)' when necessary I/O operaion
216 * is finished. This mechanism does not prevent the interrupt
217 * handler from being invoked at any time and carrying out I/O.
218 * Therefore, `spltty()' must be strategically placed in the device
219 * driver code. Also note that the timeout routine may interrupt
220 * `kbdc_lock()' called by the top half of the driver, but this
221 * interruption is OK so long as the timeout routine observes the
222 * the rule 4 below.
223 * 4. The interrupt and timeout routines should not extend I/O operation
224 * across more than one interrupt or timeout; they must complete
225 * necessary I/O operation within one invokation of the routine.
226 * This measns that if the timeout routine acquires the lock flag,
227 * it must reset the flag to FALSE before it returns.
228 */
229
230 /* set/reset polling lock */
231 int
232 kbdc_lock(KBDC p, int lock)
233 {
234 int prevlock;
235
236 prevlock = kbdcp(p)->lock;
237 kbdcp(p)->lock = lock;
238
239 return (prevlock != lock);
240 }
241
242 /* check if any data is waiting to be processed */
243 int
244 kbdc_data_ready(KBDC p)
245 {
246 #ifdef PC98
247 return (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL);
248 #else
249 return (availq(&kbdcp(p)->kbd) || availq(&kbdcp(p)->aux)
250 || (inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL));
251 #endif
252 }
253
254 #ifndef PC98
255 /* queuing functions */
256
257 static int
258 addq(kqueue *q, int c)
259 {
260 if (nextq(q->tail) != q->head) {
261 q->q[q->tail] = c;
262 q->tail = nextq(q->tail);
263 #if KBDIO_DEBUG >= 2
264 ++q->call_count;
265 ++q->qcount;
266 if (q->qcount > q->max_qcount)
267 q->max_qcount = q->qcount;
268 #endif
269 return TRUE;
270 }
271 return FALSE;
272 }
273
274 static int
275 removeq(kqueue *q)
276 {
277 int c;
278
279 if (q->tail != q->head) {
280 c = q->q[q->head];
281 q->head = nextq(q->head);
282 #if KBDIO_DEBUG >= 2
283 --q->qcount;
284 #endif
285 return c;
286 }
287 return -1;
288 }
289
290 /*
291 * device I/O routines
292 */
293 static int
294 wait_while_controller_busy(struct kbdc_softc *kbdc)
295 {
296 /* CPU will stay inside the loop for 100msec at most */
297 int retry = 5000;
298 int port = kbdc->port;
299 int f;
300
301 while ((f = inb(port + KBD_STATUS_PORT)) & KBDS_INPUT_BUFFER_FULL) {
302 if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
303 DELAY(KBDD_DELAYTIME);
304 addq(&kbdc->kbd, inb(port + KBD_DATA_PORT));
305 } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
306 DELAY(KBDD_DELAYTIME);
307 addq(&kbdc->aux, inb(port + KBD_DATA_PORT));
308 }
309 DELAY(KBDC_DELAYTIME);
310 if (--retry < 0)
311 return FALSE;
312 }
313 return TRUE;
314 }
315
316 /*
317 * wait for any data; whether it's from the controller,
318 * the keyboard, or the aux device.
319 */
320 static int
321 wait_for_data(struct kbdc_softc *kbdc)
322 {
323 /* CPU will stay inside the loop for 200msec at most */
324 int retry = 10000;
325 int port = kbdc->port;
326 int f;
327
328 while ((f = inb(port + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) == 0) {
329 DELAY(KBDC_DELAYTIME);
330 if (--retry < 0)
331 return 0;
332 }
333 DELAY(KBDD_DELAYTIME);
334 return f;
335 }
336 #endif /* !PC98 */
337
338 /* wait for data from the keyboard */
339 static int
340 wait_for_kbd_data(struct kbdc_softc *kbdc)
341 {
342 /* CPU will stay inside the loop for 200msec at most */
343 int retry = 10000;
344 int port = kbdc->port;
345 int f;
346
347 while ((f = inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)
348 != KBDS_KBD_BUFFER_FULL) {
349 #ifdef PC98
350 DELAY(KBDD_DELAYTIME);
351 #else
352 if (f == KBDS_AUX_BUFFER_FULL) {
353 DELAY(KBDD_DELAYTIME);
354 addq(&kbdc->aux, inb(port + KBD_DATA_PORT));
355 }
356 #endif
357 DELAY(KBDC_DELAYTIME);
358 if (--retry < 0)
359 return 0;
360 }
361 DELAY(KBDD_DELAYTIME);
362 return f;
363 }
364
365 #ifndef PC98
366 /*
367 * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the keyboard.
368 * queue anything else.
369 */
370 static int
371 wait_for_kbd_ack(struct kbdc_softc *kbdc)
372 {
373 /* CPU will stay inside the loop for 200msec at most */
374 int retry = 10000;
375 int port = kbdc->port;
376 int f;
377 int b;
378
379 while (retry-- > 0) {
380 if ((f = inb(port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) {
381 DELAY(KBDD_DELAYTIME);
382 b = inb(port + KBD_DATA_PORT);
383 if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
384 if ((b == KBD_ACK) || (b == KBD_RESEND)
385 || (b == KBD_RESET_FAIL))
386 return b;
387 addq(&kbdc->kbd, b);
388 } else if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
389 addq(&kbdc->aux, b);
390 }
391 }
392 DELAY(KBDC_DELAYTIME);
393 }
394 return -1;
395 }
396
397 /* wait for data from the aux device */
398 static int
399 wait_for_aux_data(struct kbdc_softc *kbdc)
400 {
401 /* CPU will stay inside the loop for 200msec at most */
402 int retry = 10000;
403 int port = kbdc->port;
404 int f;
405
406 while ((f = inb(port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL)
407 != KBDS_AUX_BUFFER_FULL) {
408 if (f == KBDS_KBD_BUFFER_FULL) {
409 DELAY(KBDD_DELAYTIME);
410 addq(&kbdc->kbd, inb(port + KBD_DATA_PORT));
411 }
412 DELAY(KBDC_DELAYTIME);
413 if (--retry < 0)
414 return 0;
415 }
416 DELAY(KBDD_DELAYTIME);
417 return f;
418 }
419
420 /*
421 * wait for an ACK(FAh), RESEND(FEh), or RESET_FAIL(FCh) from the aux device.
422 * queue anything else.
423 */
424 static int
425 wait_for_aux_ack(struct kbdc_softc *kbdc)
426 {
427 /* CPU will stay inside the loop for 200msec at most */
428 int retry = 10000;
429 int port = kbdc->port;
430 int f;
431 int b;
432
433 while (retry-- > 0) {
434 if ((f = inb(port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) {
435 DELAY(KBDD_DELAYTIME);
436 b = inb(port + KBD_DATA_PORT);
437 if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
438 if ((b == PSM_ACK) || (b == PSM_RESEND)
439 || (b == PSM_RESET_FAIL))
440 return b;
441 addq(&kbdc->aux, b);
442 } else if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
443 addq(&kbdc->kbd, b);
444 }
445 }
446 DELAY(KBDC_DELAYTIME);
447 }
448 return -1;
449 }
450
451 /* write a one byte command to the controller */
452 int
453 write_controller_command(KBDC p, int c)
454 {
455 if (!wait_while_controller_busy(kbdcp(p)))
456 return FALSE;
457 outb(kbdcp(p)->port + KBD_COMMAND_PORT, c);
458 return TRUE;
459 }
460
461 /* write a one byte data to the controller */
462 int
463 write_controller_data(KBDC p, int c)
464 {
465 if (!wait_while_controller_busy(kbdcp(p)))
466 return FALSE;
467 outb(kbdcp(p)->port + KBD_DATA_PORT, c);
468 return TRUE;
469 }
470
471 /* write a one byte keyboard command */
472 int
473 write_kbd_command(KBDC p, int c)
474 {
475 if (!wait_while_controller_busy(kbdcp(p)))
476 return FALSE;
477 outb(kbdcp(p)->port + KBD_DATA_PORT, c);
478 return TRUE;
479 }
480
481 /* write a one byte auxiliary device command */
482 int
483 write_aux_command(KBDC p, int c)
484 {
485 if (!write_controller_command(p, KBDC_WRITE_TO_AUX))
486 return FALSE;
487 return write_controller_data(p, c);
488 }
489
490 /* send a command to the keyboard and wait for ACK */
491 int
492 send_kbd_command(KBDC p, int c)
493 {
494 int retry = KBD_MAXRETRY;
495 int res = -1;
496
497 while (retry-- > 0) {
498 if (!write_kbd_command(p, c))
499 continue;
500 res = wait_for_kbd_ack(kbdcp(p));
501 if (res == KBD_ACK)
502 break;
503 }
504 return res;
505 }
506
507 /* send a command to the auxiliary device and wait for ACK */
508 int
509 send_aux_command(KBDC p, int c)
510 {
511 int retry = KBD_MAXRETRY;
512 int res = -1;
513
514 while (retry-- > 0) {
515 if (!write_aux_command(p, c))
516 continue;
517 /*
518 * FIXME: XXX
519 * The aux device may have already sent one or two bytes of
520 * status data, when a command is received. It will immediately
521 * stop data transmission, thus, leaving an incomplete data
522 * packet in our buffer. We have to discard any unprocessed
523 * data in order to remove such packets. Well, we may remove
524 * unprocessed, but necessary data byte as well...
525 */
526 emptyq(&kbdcp(p)->aux);
527 res = wait_for_aux_ack(kbdcp(p));
528 if (res == PSM_ACK)
529 break;
530 }
531 return res;
532 }
533
534 /* send a command and a data to the keyboard, wait for ACKs */
535 int
536 send_kbd_command_and_data(KBDC p, int c, int d)
537 {
538 int retry;
539 int res = -1;
540
541 for (retry = KBD_MAXRETRY; retry > 0; --retry) {
542 if (!write_kbd_command(p, c))
543 continue;
544 res = wait_for_kbd_ack(kbdcp(p));
545 if (res == KBD_ACK)
546 break;
547 else if (res != KBD_RESEND)
548 return res;
549 }
550 if (retry <= 0)
551 return res;
552
553 for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) {
554 if (!write_kbd_command(p, d))
555 continue;
556 res = wait_for_kbd_ack(kbdcp(p));
557 if (res != KBD_RESEND)
558 break;
559 }
560 return res;
561 }
562
563 /* send a command and a data to the auxiliary device, wait for ACKs */
564 int
565 send_aux_command_and_data(KBDC p, int c, int d)
566 {
567 int retry;
568 int res = -1;
569
570 for (retry = KBD_MAXRETRY; retry > 0; --retry) {
571 if (!write_aux_command(p, c))
572 continue;
573 emptyq(&kbdcp(p)->aux);
574 res = wait_for_aux_ack(kbdcp(p));
575 if (res == PSM_ACK)
576 break;
577 else if (res != PSM_RESEND)
578 return res;
579 }
580 if (retry <= 0)
581 return res;
582
583 for (retry = KBD_MAXRETRY, res = -1; retry > 0; --retry) {
584 if (!write_aux_command(p, d))
585 continue;
586 res = wait_for_aux_ack(kbdcp(p));
587 if (res != PSM_RESEND)
588 break;
589 }
590 return res;
591 }
592
593 /*
594 * read one byte from any source; whether from the controller,
595 * the keyboard, or the aux device
596 */
597 int
598 read_controller_data(KBDC p)
599 {
600 if (availq(&kbdcp(p)->kbd))
601 return removeq(&kbdcp(p)->kbd);
602 if (availq(&kbdcp(p)->aux))
603 return removeq(&kbdcp(p)->aux);
604 if (!wait_for_data(kbdcp(p)))
605 return -1; /* timeout */
606 return inb(kbdcp(p)->port + KBD_DATA_PORT);
607 }
608 #endif /* !PC98 */
609
610 #if KBDIO_DEBUG >= 2
611 static int call = 0;
612 #endif
613
614 /* read one byte from the keyboard */
615 int
616 read_kbd_data(KBDC p)
617 {
618 #ifndef PC98
619 #if KBDIO_DEBUG >= 2
620 if (++call > 2000) {
621 call = 0;
622 log(LOG_DEBUG, "KBDIO: kbd q: %d calls, max %d chars, "
623 "aux q: %d calls, max %d chars\n",
624 kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount,
625 kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount);
626 }
627 #endif
628
629 if (availq(&kbdcp(p)->kbd))
630 return removeq(&kbdcp(p)->kbd);
631 #endif /* !PC98 */
632 if (!wait_for_kbd_data(kbdcp(p)))
633 return -1; /* timeout */
634 #ifdef PC98
635 DELAY(KBDC_DELAYTIME);
636 #endif
637 return inb(kbdcp(p)->port + KBD_DATA_PORT);
638 }
639
640 /* read one byte from the keyboard, but return immediately if
641 * no data is waiting
642 */
643 int
644 read_kbd_data_no_wait(KBDC p)
645 {
646 int f;
647
648 #ifdef PC98
649 f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL;
650 #else
651 #if KBDIO_DEBUG >= 2
652 if (++call > 2000) {
653 call = 0;
654 log(LOG_DEBUG, "KBDIO: kbd q: %d calls, max %d chars, "
655 "aux q: %d calls, max %d chars\n",
656 kbdcp(p)->kbd.call_count, kbdcp(p)->kbd.max_qcount,
657 kbdcp(p)->aux.call_count, kbdcp(p)->aux.max_qcount);
658 }
659 #endif
660
661 if (availq(&kbdcp(p)->kbd))
662 return removeq(&kbdcp(p)->kbd);
663 f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL;
664 if (f == KBDS_AUX_BUFFER_FULL) {
665 DELAY(KBDD_DELAYTIME);
666 addq(&kbdcp(p)->aux, inb(kbdcp(p)->port + KBD_DATA_PORT));
667 f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL;
668 }
669 #endif /* PC98 */
670 if (f == KBDS_KBD_BUFFER_FULL) {
671 DELAY(KBDD_DELAYTIME);
672 return inb(kbdcp(p)->port + KBD_DATA_PORT);
673 }
674 return -1; /* no data */
675 }
676
677 #ifndef PC98
678 /* read one byte from the aux device */
679 int
680 read_aux_data(KBDC p)
681 {
682 if (availq(&kbdcp(p)->aux))
683 return removeq(&kbdcp(p)->aux);
684 if (!wait_for_aux_data(kbdcp(p)))
685 return -1; /* timeout */
686 return inb(kbdcp(p)->port + KBD_DATA_PORT);
687 }
688
689 /* read one byte from the aux device, but return immediately if
690 * no data is waiting
691 */
692 int
693 read_aux_data_no_wait(KBDC p)
694 {
695 int f;
696
697 if (availq(&kbdcp(p)->aux))
698 return removeq(&kbdcp(p)->aux);
699 f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL;
700 if (f == KBDS_KBD_BUFFER_FULL) {
701 DELAY(KBDD_DELAYTIME);
702 addq(&kbdcp(p)->kbd, inb(kbdcp(p)->port + KBD_DATA_PORT));
703 f = inb(kbdcp(p)->port + KBD_STATUS_PORT) & KBDS_BUFFER_FULL;
704 }
705 if (f == KBDS_AUX_BUFFER_FULL) {
706 DELAY(KBDD_DELAYTIME);
707 return inb(kbdcp(p)->port + KBD_DATA_PORT);
708 }
709 return -1; /* no data */
710 }
711
712 /* discard data from the keyboard */
713 void
714 empty_kbd_buffer(KBDC p, int wait)
715 {
716 int t;
717 int b;
718 int f;
719 #if KBDIO_DEBUG >= 2
720 int c1 = 0;
721 int c2 = 0;
722 #endif
723 int delta = 2;
724
725 for (t = wait; t > 0; ) {
726 if ((f = inb(kbdcp(p)->port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) {
727 DELAY(KBDD_DELAYTIME);
728 b = inb(kbdcp(p)->port + KBD_DATA_PORT);
729 if ((f & KBDS_BUFFER_FULL) == KBDS_AUX_BUFFER_FULL) {
730 addq(&kbdcp(p)->aux, b);
731 #if KBDIO_DEBUG >= 2
732 ++c2;
733 } else {
734 ++c1;
735 #endif
736 }
737 t = wait;
738 } else {
739 t -= delta;
740 }
741 DELAY(delta*1000);
742 }
743 #if KBDIO_DEBUG >= 2
744 if ((c1 > 0) || (c2 > 0))
745 log(LOG_DEBUG, "kbdio: %d:%d char read (empty_kbd_buffer)\n", c1, c2);
746 #endif
747
748 emptyq(&kbdcp(p)->kbd);
749 }
750
751 /* discard data from the aux device */
752 void
753 empty_aux_buffer(KBDC p, int wait)
754 {
755 int t;
756 int b;
757 int f;
758 #if KBDIO_DEBUG >= 2
759 int c1 = 0;
760 int c2 = 0;
761 #endif
762 int delta = 2;
763
764 for (t = wait; t > 0; ) {
765 if ((f = inb(kbdcp(p)->port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) {
766 DELAY(KBDD_DELAYTIME);
767 b = inb(kbdcp(p)->port + KBD_DATA_PORT);
768 if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) {
769 addq(&kbdcp(p)->kbd, b);
770 #if KBDIO_DEBUG >= 2
771 ++c1;
772 } else {
773 ++c2;
774 #endif
775 }
776 t = wait;
777 } else {
778 t -= delta;
779 }
780 DELAY(delta*1000);
781 }
782 #if KBDIO_DEBUG >= 2
783 if ((c1 > 0) || (c2 > 0))
784 log(LOG_DEBUG, "kbdio: %d:%d char read (empty_aux_buffer)\n", c1, c2);
785 #endif
786
787 emptyq(&kbdcp(p)->aux);
788 }
789
790 /* discard any data from the keyboard or the aux device */
791 void
792 empty_both_buffers(KBDC p, int wait)
793 {
794 int t;
795 int f;
796 #if KBDIO_DEBUG >= 2
797 int c1 = 0;
798 int c2 = 0;
799 #endif
800 int delta = 2;
801
802 for (t = wait; t > 0; ) {
803 if ((f = inb(kbdcp(p)->port + KBD_STATUS_PORT)) & KBDS_ANY_BUFFER_FULL) {
804 DELAY(KBDD_DELAYTIME);
805 (void)inb(kbdcp(p)->port + KBD_DATA_PORT);
806 #if KBDIO_DEBUG >= 2
807 if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL)
808 ++c1;
809 else
810 ++c2;
811 #endif
812 t = wait;
813 } else {
814 t -= delta;
815 }
816 DELAY(delta*1000);
817 }
818 #if KBDIO_DEBUG >= 2
819 if ((c1 > 0) || (c2 > 0))
820 log(LOG_DEBUG, "kbdio: %d:%d char read (empty_both_buffers)\n", c1, c2);
821 #endif
822
823 emptyq(&kbdcp(p)->kbd);
824 emptyq(&kbdcp(p)->aux);
825 }
826
827 /* keyboard and mouse device control */
828
829 /* NOTE: enable the keyboard port but disable the keyboard
830 * interrupt before calling "reset_kbd()".
831 */
832 int
833 reset_kbd(KBDC p)
834 {
835 int retry = KBD_MAXRETRY;
836 int again = KBD_MAXWAIT;
837 int c = KBD_RESEND; /* keep the compiler happy */
838
839 while (retry-- > 0) {
840 empty_both_buffers(p, 10);
841 if (!write_kbd_command(p, KBDC_RESET_KBD))
842 continue;
843 emptyq(&kbdcp(p)->kbd);
844 c = read_controller_data(p);
845 if (verbose || bootverbose)
846 log(LOG_DEBUG, "kbdio: RESET_KBD return code:%04x\n", c);
847 if (c == KBD_ACK) /* keyboard has agreed to reset itself... */
848 break;
849 }
850 if (retry < 0)
851 return FALSE;
852
853 while (again-- > 0) {
854 /* wait awhile, well, in fact we must wait quite loooooooooooong */
855 DELAY(KBD_RESETDELAY*1000);
856 c = read_controller_data(p); /* RESET_DONE/RESET_FAIL */
857 if (c != -1) /* wait again if the controller is not ready */
858 break;
859 }
860 if (verbose || bootverbose)
861 log(LOG_DEBUG, "kbdio: RESET_KBD status:%04x\n", c);
862 if (c != KBD_RESET_DONE)
863 return FALSE;
864 return TRUE;
865 }
866
867 /* NOTE: enable the aux port but disable the aux interrupt
868 * before calling `reset_aux_dev()'.
869 */
870 int
871 reset_aux_dev(KBDC p)
872 {
873 int retry = KBD_MAXRETRY;
874 int again = KBD_MAXWAIT;
875 int c = PSM_RESEND; /* keep the compiler happy */
876
877 while (retry-- > 0) {
878 empty_both_buffers(p, 10);
879 if (!write_aux_command(p, PSMC_RESET_DEV))
880 continue;
881 emptyq(&kbdcp(p)->aux);
882 /* NOTE: Compaq Armada laptops require extra delay here. XXX */
883 for (again = KBD_MAXWAIT; again > 0; --again) {
884 DELAY(KBD_RESETDELAY*1000);
885 c = read_aux_data_no_wait(p);
886 if (c != -1)
887 break;
888 }
889 if (verbose || bootverbose)
890 log(LOG_DEBUG, "kbdio: RESET_AUX return code:%04x\n", c);
891 if (c == PSM_ACK) /* aux dev is about to reset... */
892 break;
893 }
894 if (retry < 0)
895 return FALSE;
896
897 for (again = KBD_MAXWAIT; again > 0; --again) {
898 /* wait awhile, well, quite looooooooooooong */
899 DELAY(KBD_RESETDELAY*1000);
900 c = read_aux_data_no_wait(p); /* RESET_DONE/RESET_FAIL */
901 if (c != -1) /* wait again if the controller is not ready */
902 break;
903 }
904 if (verbose || bootverbose)
905 log(LOG_DEBUG, "kbdio: RESET_AUX status:%04x\n", c);
906 if (c != PSM_RESET_DONE) /* reset status */
907 return FALSE;
908
909 c = read_aux_data(p); /* device ID */
910 if (verbose || bootverbose)
911 log(LOG_DEBUG, "kbdio: RESET_AUX ID:%04x\n", c);
912 /* NOTE: we could check the device ID now, but leave it later... */
913 return TRUE;
914 }
915
916 /* controller diagnostics and setup */
917
918 int
919 test_controller(KBDC p)
920 {
921 int retry = KBD_MAXRETRY;
922 int again = KBD_MAXWAIT;
923 int c = KBD_DIAG_FAIL;
924
925 while (retry-- > 0) {
926 empty_both_buffers(p, 10);
927 if (write_controller_command(p, KBDC_DIAGNOSE))
928 break;
929 }
930 if (retry < 0)
931 return FALSE;
932
933 emptyq(&kbdcp(p)->kbd);
934 while (again-- > 0) {
935 /* wait awhile */
936 DELAY(KBD_RESETDELAY*1000);
937 c = read_controller_data(p); /* DIAG_DONE/DIAG_FAIL */
938 if (c != -1) /* wait again if the controller is not ready */
939 break;
940 }
941 if (verbose || bootverbose)
942 log(LOG_DEBUG, "kbdio: DIAGNOSE status:%04x\n", c);
943 return (c == KBD_DIAG_DONE);
944 }
945
946 int
947 test_kbd_port(KBDC p)
948 {
949 int retry = KBD_MAXRETRY;
950 int again = KBD_MAXWAIT;
951 int c = -1;
952
953 while (retry-- > 0) {
954 empty_both_buffers(p, 10);
955 if (write_controller_command(p, KBDC_TEST_KBD_PORT))
956 break;
957 }
958 if (retry < 0)
959 return FALSE;
960
961 emptyq(&kbdcp(p)->kbd);
962 while (again-- > 0) {
963 c = read_controller_data(p);
964 if (c != -1) /* try again if the controller is not ready */
965 break;
966 }
967 if (verbose || bootverbose)
968 log(LOG_DEBUG, "kbdio: TEST_KBD_PORT status:%04x\n", c);
969 return c;
970 }
971
972 int
973 test_aux_port(KBDC p)
974 {
975 int retry = KBD_MAXRETRY;
976 int again = KBD_MAXWAIT;
977 int c = -1;
978
979 while (retry-- > 0) {
980 empty_both_buffers(p, 10);
981 if (write_controller_command(p, KBDC_TEST_AUX_PORT))
982 break;
983 }
984 if (retry < 0)
985 return FALSE;
986
987 emptyq(&kbdcp(p)->kbd);
988 while (again-- > 0) {
989 c = read_controller_data(p);
990 if (c != -1) /* try again if the controller is not ready */
991 break;
992 }
993 if (verbose || bootverbose)
994 log(LOG_DEBUG, "kbdio: TEST_AUX_PORT status:%04x\n", c);
995 return c;
996 }
997
998 int
999 kbdc_get_device_mask(KBDC p)
1000 {
1001 return kbdcp(p)->command_mask;
1002 }
1003
1004 void
1005 kbdc_set_device_mask(KBDC p, int mask)
1006 {
1007 kbdcp(p)->command_mask =
1008 mask & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS);
1009 }
1010
1011 int
1012 get_controller_command_byte(KBDC p)
1013 {
1014 if (kbdcp(p)->command_byte != -1)
1015 return kbdcp(p)->command_byte;
1016 if (!write_controller_command(p, KBDC_GET_COMMAND_BYTE))
1017 return -1;
1018 emptyq(&kbdcp(p)->kbd);
1019 kbdcp(p)->command_byte = read_controller_data(p);
1020 return kbdcp(p)->command_byte;
1021 }
1022
1023 int
1024 set_controller_command_byte(KBDC p, int mask, int command)
1025 {
1026 if (get_controller_command_byte(p) == -1)
1027 return FALSE;
1028
1029 command = (kbdcp(p)->command_byte & ~mask) | (command & mask);
1030 if (command & KBD_DISABLE_KBD_PORT) {
1031 if (!write_controller_command(p, KBDC_DISABLE_KBD_PORT))
1032 return FALSE;
1033 }
1034 if (!write_controller_command(p, KBDC_SET_COMMAND_BYTE))
1035 return FALSE;
1036 if (!write_controller_data(p, command))
1037 return FALSE;
1038 kbdcp(p)->command_byte = command;
1039
1040 if (verbose)
1041 log(LOG_DEBUG, "kbdio: new command byte:%04x (set_controller...)\n",
1042 command);
1043
1044 return TRUE;
1045 }
1046 #endif /* !PC98 */
Cache object: bb44e0708660e58f52a1af7f9fe7badc
|