The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/kbd/atkbdc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 0ffceedfa4cb30e16bc7f8545fea5c22


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.