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/misc/atkbdc_layer/atkbdc_isa.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  * (MPSAFE)
    3  *
    4  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer as
   12  *    the first lines of this file unmodified.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * $FreeBSD: src/sys/isa/atkbdc_isa.c,v 1.14.2.1 2000/03/31 12:52:05 yokota Exp $
   29  */
   30 
   31 #include "opt_kbd.h"
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/bus.h>
   37 #include <sys/malloc.h>
   38 #include <sys/rman.h>
   39 #include <sys/thread.h>
   40 
   41 #include <dev/misc/kbd/atkbdcreg.h>
   42 
   43 #include <bus/isa/isareg.h>
   44 #include <bus/isa/isavar.h>
   45 
   46 #if 0
   47 #define lwkt_gettoken(x)
   48 #define lwkt_reltoken(x)
   49 #endif
   50 
   51 MALLOC_DEFINE(M_ATKBDDEV, "atkbddev", "AT Keyboard device");
   52 
   53 /* children */
   54 typedef struct atkbdc_device {
   55         int flags;      /* configuration flags */
   56         int irq;        /* ISA IRQ mask */
   57         u_int32_t vendorid;
   58         u_int32_t serial;
   59         u_int32_t logicalid;
   60         u_int32_t compatid;
   61 } atkbdc_device_t;
   62 
   63 /* kbdc */
   64 devclass_t atkbdc_devclass;
   65 
   66 static int      atkbdc_probe(device_t dev);
   67 static int      atkbdc_attach(device_t dev);
   68 static int      atkbdc_print_child(device_t bus, device_t dev);
   69 static int      atkbdc_read_ivar(device_t bus, device_t dev, int index,
   70                                  u_long *val);
   71 static int      atkbdc_write_ivar(device_t bus, device_t dev, int index,
   72                                   u_long val);
   73 
   74 static device_method_t atkbdc_methods[] = {
   75         DEVMETHOD(device_probe,         atkbdc_probe),
   76         DEVMETHOD(device_attach,        atkbdc_attach),
   77         DEVMETHOD(device_suspend,       bus_generic_suspend),
   78         DEVMETHOD(device_resume,        bus_generic_resume),
   79 
   80         DEVMETHOD(bus_print_child,      atkbdc_print_child),
   81         DEVMETHOD(bus_read_ivar,        atkbdc_read_ivar),
   82         DEVMETHOD(bus_write_ivar,       atkbdc_write_ivar),
   83         DEVMETHOD(bus_alloc_resource,   bus_generic_alloc_resource),
   84         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
   85         DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
   86         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
   87         DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
   88         DEVMETHOD(bus_teardown_intr,    bus_generic_teardown_intr),
   89 
   90         DEVMETHOD_END
   91 };
   92 
   93 static driver_t atkbdc_driver = {
   94         ATKBDC_DRIVER_NAME,
   95         atkbdc_methods,
   96         sizeof(atkbdc_softc_t *),
   97 };
   98 
   99 static struct isa_pnp_id atkbdc_ids[] = {
  100         { 0x0303d041, "Keyboard controller (i8042)" },  /* PNP0303 */
  101         { 0 }
  102 };
  103 
  104 static int
  105 atkbdc_probe(device_t dev)
  106 {
  107         struct resource *port0;
  108         struct resource *port1;
  109         int             error;
  110         int             rid;
  111 #if defined(__i386__) || defined(__x86_64__)
  112         bus_space_tag_t tag;
  113         bus_space_handle_t ioh1;
  114         volatile int    i;
  115 #endif
  116 
  117         /* check PnP IDs */
  118         if (ISA_PNP_PROBE(device_get_parent(dev), dev, atkbdc_ids) == ENXIO)
  119                 return ENXIO;
  120 
  121         device_set_desc(dev, "Keyboard controller (i8042)");
  122 
  123         rid = 0;
  124         port0 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
  125                                    RF_ACTIVE);
  126         if (port0 == NULL)
  127                 return ENXIO;
  128         /* XXX */
  129         if (bus_get_resource_start(dev, SYS_RES_IOPORT, 1) <= 0) {
  130                 bus_set_resource(dev, SYS_RES_IOPORT, 1,
  131                     rman_get_start(port0) + KBD_STATUS_PORT, 1, -1);
  132         }
  133         rid = 1;
  134         port1 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
  135                                    RF_ACTIVE);
  136         if (port1 == NULL) {
  137                 bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
  138                 return ENXIO;
  139         }
  140 
  141 #if defined(__i386__) || defined(__x86_64__)
  142         /*
  143          * Check if we really have AT keyboard controller. Poll status
  144          * register until we get "all clear" indication. If no such
  145          * indication comes, it probably means that there is no AT
  146          * keyboard controller present. Give up in such case. Check relies
  147          * on the fact that reading from non-existing in/out port returns
  148          * 0xff on i386. May or may not be true on other platforms.
  149          */
  150         tag = rman_get_bustag(port0);
  151         ioh1 = rman_get_bushandle(port1);
  152         for (i = 65536; i != 0; --i) {
  153                 if ((bus_space_read_1(tag, ioh1, 0) & 0x2) == 0)
  154                         break;
  155                 DELAY(16);
  156         }
  157         if (i == 0) {
  158                 bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
  159                 bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
  160                 return ENXIO;
  161         }
  162 #endif
  163 
  164         error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
  165 
  166         bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
  167         bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
  168 
  169         return error;
  170 }
  171 
  172 static void
  173 atkbdc_add_device(device_t dev, const char *name, int unit)
  174 {
  175         atkbdc_device_t *kdev;
  176         device_t        child;
  177         int             t;
  178 
  179         if (resource_int_value(name, unit, "disabled", &t) == 0 && t != 0)
  180                 return;
  181 
  182         kdev = kmalloc(sizeof(struct atkbdc_device), M_ATKBDDEV, 
  183                         M_WAITOK | M_ZERO);
  184 
  185         if (resource_int_value(name, unit, "irq", &t) == 0)
  186                 kdev->irq = t;
  187         else
  188                 kdev->irq = -1;
  189 
  190         if (resource_int_value(name, unit, "flags", &t) == 0)
  191                 kdev->flags = t;
  192         else
  193                 kdev->flags = 0;
  194 
  195         child = device_add_child(dev, name, unit);
  196         device_set_ivars(child, kdev);
  197 }
  198 
  199 static int
  200 atkbdc_attach(device_t dev)
  201 {
  202         atkbdc_softc_t  *sc;
  203         int             unit;
  204         int             error;
  205         int             rid;
  206         int             i;
  207 
  208         lwkt_gettoken(&tty_token);
  209         unit = device_get_unit(dev);
  210         sc = *(atkbdc_softc_t **)device_get_softc(dev);
  211         if (sc == NULL) {
  212                 /*
  213                  * We have to maintain two copies of the kbdc_softc struct,
  214                  * as the low-level console needs to have access to the
  215                  * keyboard controller before kbdc is probed and attached. 
  216                  * kbdc_soft[] contains the default entry for that purpose.
  217                  * See atkbdc.c. XXX
  218                  */
  219                 sc = atkbdc_get_softc(unit);
  220                 if (sc == NULL) {
  221                         lwkt_reltoken(&tty_token);
  222                         return ENOMEM;
  223                 }
  224         }
  225 
  226         rid = 0;
  227         sc->port0 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
  228                                        RF_ACTIVE);
  229         if (sc->port0 == NULL) {
  230                 lwkt_reltoken(&tty_token);
  231                 return ENXIO;
  232         }
  233         rid = 1;
  234         sc->port1 = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
  235                                        RF_ACTIVE);
  236         if (sc->port1 == NULL) {
  237                 bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
  238                 lwkt_reltoken(&tty_token);
  239                 return ENXIO;
  240         }
  241 
  242         error = atkbdc_attach_unit(unit, sc, sc->port0, sc->port1);
  243         if (error) {
  244                 bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
  245                 bus_release_resource(dev, SYS_RES_IOPORT, 1, sc->port1);
  246                 lwkt_reltoken(&tty_token);
  247                 return error;
  248         }
  249         *(atkbdc_softc_t **)device_get_softc(dev) = sc;
  250 
  251         /*
  252          * Add all devices configured to be attached to atkbdc0.
  253          */
  254         for (i = resource_query_string(-1, "at", device_get_nameunit(dev));
  255              i != -1;
  256              i = resource_query_string(i, "at", device_get_nameunit(dev))) {
  257                 atkbdc_add_device(dev, resource_query_name(i),
  258                                   resource_query_unit(i));
  259         }
  260 
  261         /*
  262          * and atkbdc?
  263          */
  264         for (i = resource_query_string(-1, "at", device_get_name(dev));
  265              i != -1;
  266              i = resource_query_string(i, "at", device_get_name(dev))) {
  267                 atkbdc_add_device(dev, resource_query_name(i),
  268                                   resource_query_unit(i));
  269         }
  270 
  271         bus_generic_attach(dev);
  272 
  273         lwkt_reltoken(&tty_token);
  274         return 0;
  275 }
  276 
  277 static int
  278 atkbdc_print_child(device_t bus, device_t dev)
  279 {
  280         atkbdc_device_t *kbdcdev;
  281         int retval = 0;
  282 
  283         kbdcdev = (atkbdc_device_t *)device_get_ivars(dev);
  284 
  285         retval += bus_print_child_header(bus, dev);
  286         if (kbdcdev->flags != 0)
  287                 retval += kprintf(" flags 0x%x", kbdcdev->flags);
  288         if (kbdcdev->irq != -1)
  289                 retval += kprintf(" irq %d", kbdcdev->irq);
  290         retval += bus_print_child_footer(bus, dev);
  291 
  292         return (retval);
  293 }
  294 
  295 static int
  296 atkbdc_read_ivar(device_t bus, device_t dev, int index, u_long *val)
  297 {
  298         atkbdc_device_t *ivar;
  299 
  300         lwkt_gettoken(&tty_token);
  301         ivar = (atkbdc_device_t *)device_get_ivars(dev);
  302         switch (index) {
  303         case KBDC_IVAR_IRQ:
  304                 *val = (u_long)ivar->irq;
  305                 break;
  306         case KBDC_IVAR_FLAGS:
  307                 *val = (u_long)ivar->flags;
  308                 break;
  309         case KBDC_IVAR_VENDORID:
  310                 *val = (u_long)ivar->vendorid;
  311                 break;
  312         case KBDC_IVAR_SERIAL:
  313                 *val = (u_long)ivar->serial;
  314                 break;
  315         case KBDC_IVAR_LOGICALID:
  316                 *val = (u_long)ivar->logicalid;
  317                 break;
  318         case KBDC_IVAR_COMPATID:
  319                 *val = (u_long)ivar->compatid;
  320                 break;
  321         default:
  322                 lwkt_reltoken(&tty_token);
  323                 return ENOENT;
  324         }
  325 
  326         lwkt_reltoken(&tty_token);
  327         return 0;
  328 }
  329 
  330 static int
  331 atkbdc_write_ivar(device_t bus, device_t dev, int index, u_long val)
  332 {
  333         atkbdc_device_t *ivar;
  334 
  335         lwkt_gettoken(&tty_token);
  336         ivar = (atkbdc_device_t *)device_get_ivars(dev);
  337         switch (index) {
  338         case KBDC_IVAR_IRQ:
  339                 ivar->irq = (int)val;
  340                 break;
  341         case KBDC_IVAR_FLAGS:
  342                 ivar->flags = (int)val;
  343                 break;
  344         case KBDC_IVAR_VENDORID:
  345                 ivar->vendorid = (u_int32_t)val;
  346                 break;
  347         case KBDC_IVAR_SERIAL:
  348                 ivar->serial = (u_int32_t)val;
  349                 break;
  350         case KBDC_IVAR_LOGICALID:
  351                 ivar->logicalid = (u_int32_t)val;
  352                 break;
  353         case KBDC_IVAR_COMPATID:
  354                 ivar->compatid = (u_int32_t)val;
  355                 break;
  356         default:
  357                 lwkt_reltoken(&tty_token);
  358                 return ENOENT;
  359         }
  360 
  361         lwkt_reltoken(&tty_token);
  362         return 0;
  363 }
  364 
  365 DRIVER_MODULE(atkbdc, isa, atkbdc_driver, atkbdc_devclass, NULL, NULL);
  366 DRIVER_MODULE(atkbdc, acpi, atkbdc_driver, atkbdc_devclass, NULL, NULL);

Cache object: 45d3334365b9c4bf7a0123f7d0ab3bda


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