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/i386/isa/kbdio.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 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


[ 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.