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