atkbdc_isa.c revision 45723
11573Srgrimes/*- 21573Srgrimes * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 31573Srgrimes * All rights reserved. 41573Srgrimes * 51573Srgrimes * Redistribution and use in source and binary forms, with or without 61573Srgrimes * modification, are permitted provided that the following conditions 71573Srgrimes * are met: 81573Srgrimes * 1. Redistributions of source code must retain the above copyright 91573Srgrimes * notice, this list of conditions and the following disclaimer as 101573Srgrimes * the first lines of this file unmodified. 111573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121573Srgrimes * notice, this list of conditions and the following disclaimer in the 131573Srgrimes * documentation and/or other materials provided with the distribution. 141573Srgrimes * 151573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 161573Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 171573Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 181573Srgrimes * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 191573Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 201573Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 211573Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 221573Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 231573Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 241573Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 251573Srgrimes * 261573Srgrimes * $Id: atkbdc_isa.c,v 1.1 1999/01/23 16:53:27 dfr Exp $ 271573Srgrimes */ 281573Srgrimes 291573Srgrimes#include "atkbdc.h" 301573Srgrimes#include "opt_kbd.h" 311573Srgrimes 3254770Sgreen#if NATKBDC > 0 3354770Sgreen 341573Srgrimes#include <sys/param.h> 351573Srgrimes#include <sys/systm.h> 361573Srgrimes#include <sys/kernel.h> 3754770Sgreen#include <sys/bus.h> 3823668Speter#include <sys/malloc.h> 3954770Sgreen 4054770Sgreen#include <dev/kbd/atkbdcreg.h> 4154770Sgreen 421573Srgrimes#include <isa/isareg.h> 431573Srgrimes#include <isa/isavar.h> 441573Srgrimes 451573SrgrimesMALLOC_DEFINE(M_ATKBDDEV, "atkbddev", "AT Keyboard device"); 461573Srgrimes 471573Srgrimes/* children */ 481573Srgrimestypedef struct atkbdc_device { 491573Srgrimes int flags; /* configuration flags */ 501573Srgrimes int port; /* port number (same as the controller's) */ 511573Srgrimes int irq; /* ISA IRQ mask */ 521573Srgrimes} atkbdc_device_t; 531573Srgrimes 541573Srgrimes/* kbdc */ 551573Srgrimesdevclass_t atkbdc_devclass; 561573Srgrimes 571573Srgrimesstatic int atkbdc_probe(device_t dev); 581573Srgrimesstatic int atkbdc_attach(device_t dev); 591573Srgrimesstatic void atkbdc_print_child(device_t bus, device_t dev); 6054770Sgreenstatic int atkbdc_read_ivar(device_t bus, device_t dev, int index, 611573Srgrimes u_long *val); 621573Srgrimesstatic int atkbdc_write_ivar(device_t bus, device_t dev, int index, 631573Srgrimes u_long val); 6428913Simp 651573Srgrimesstatic device_method_t atkbdc_methods[] = { 6628913Simp DEVMETHOD(device_probe, atkbdc_probe), 671573Srgrimes DEVMETHOD(device_attach, atkbdc_attach), 6828913Simp 6928913Simp DEVMETHOD(bus_print_child, atkbdc_print_child), 7028913Simp DEVMETHOD(bus_read_ivar, atkbdc_read_ivar), 711573Srgrimes DEVMETHOD(bus_write_ivar, atkbdc_write_ivar), 721573Srgrimes DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), 731573Srgrimes DEVMETHOD(bus_release_resource, bus_generic_release_resource), 741573Srgrimes DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 751573Srgrimes DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 761573Srgrimes DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 771573Srgrimes DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 781573Srgrimes 791573Srgrimes { 0, 0 } 801573Srgrimes}; 811573Srgrimes 821573Srgrimesstatic driver_t atkbdc_driver = { 831573Srgrimes ATKBDC_DRIVER_NAME, 8428913Simp atkbdc_methods, 851573Srgrimes DRIVER_TYPE_MISC, 861573Srgrimes sizeof(atkbdc_softc_t *), 871573Srgrimes}; 881573Srgrimes 891573Srgrimesstatic int 901573Srgrimesatkbdc_probe(device_t dev) 911573Srgrimes{ 921573Srgrimes atkbdc_softc_t *sc; 931573Srgrimes int unit; 941573Srgrimes int error; 951573Srgrimes 961573Srgrimes unit = device_get_unit(dev); 971573Srgrimes sc = *(atkbdc_softc_t **)device_get_softc(dev); 981573Srgrimes if (sc == NULL) { 991573Srgrimes /* 1001573Srgrimes * We have to maintain two copies of the kbdc_softc struct, 1011573Srgrimes * as the low-level console needs to have access to the 1021573Srgrimes * keyboard controller before kbdc is probed and attached. 1031573Srgrimes * kbdc_soft[] contains the default entry for that purpose. 1041573Srgrimes * See atkbdc.c. XXX 10554770Sgreen */ 10654770Sgreen sc = atkbdc_get_softc(unit); 10754770Sgreen if (sc == NULL) 1081573Srgrimes return ENOMEM; 1091573Srgrimes } 1101573Srgrimes 1111573Srgrimes device_set_desc(dev, "keyboard controller (i8042)"); 1121573Srgrimes 1131573Srgrimes error = atkbdc_probe_unit(sc, unit, isa_get_port(dev)); 1141573Srgrimes if (error == 0) 1151573Srgrimes *(atkbdc_softc_t **)device_get_softc(dev) = sc; 1161573Srgrimes 1171573Srgrimes return error; 1181573Srgrimes} 1191573Srgrimes 1201573Srgrimesstatic void 1211573Srgrimesatkbdc_add_device(device_t dev, const char *name, int unit) 1221573Srgrimes{ 1231573Srgrimes atkbdc_softc_t *sc = *(atkbdc_softc_t **)device_get_softc(dev); 1241573Srgrimes atkbdc_device_t *kdev; 1251573Srgrimes device_t child; 1261573Srgrimes int t; 1271573Srgrimes 1281573Srgrimes kdev = malloc(sizeof(struct atkbdc_device), M_ATKBDDEV, M_NOWAIT); 1291573Srgrimes if (!kdev) 1301573Srgrimes return; 1311573Srgrimes bzero(kdev, sizeof *kdev); 1321573Srgrimes 1331573Srgrimes kdev->port = sc->port; 1341573Srgrimes 1351573Srgrimes if (resource_int_value(name, unit, "irq", &t) == 0) 1361573Srgrimes kdev->irq = t; 1371573Srgrimes else 1381573Srgrimes kdev->irq = -1; 1391573Srgrimes 1401573Srgrimes if (resource_int_value(name, unit, "flags", &t) == 0) 1411573Srgrimes kdev->flags = t; 1421573Srgrimes else 1431573Srgrimes kdev->flags = 0; 1441573Srgrimes 1451573Srgrimes child = device_add_child(dev, name, unit, kdev); 1461573Srgrimes} 1471573Srgrimes 1481573Srgrimesstatic int 1491573Srgrimesatkbdc_attach(device_t dev) 1501573Srgrimes{ 1511573Srgrimes atkbdc_softc_t *sc; 1521573Srgrimes int i; 1531573Srgrimes 1541573Srgrimes sc = *(atkbdc_softc_t **)device_get_softc(dev); 1551573Srgrimes if ((sc == NULL) || (sc->port <= 0)) 1561573Srgrimes return ENXIO; 1571573Srgrimes 1581573Srgrimes /* 1591573Srgrimes * Add all devices configured to be attached to atkbdc0. 1601573Srgrimes */ 1611573Srgrimes for (i = resource_query_string(-1, "at", "atkbdc0"); 1621573Srgrimes i != -1; 1631573Srgrimes i = resource_query_string(i, "at", "atkbdc0")) { 1641573Srgrimes atkbdc_add_device(dev, resource_query_name(i), 1651573Srgrimes resource_query_unit(i)); 1661573Srgrimes } 1671573Srgrimes 1681573Srgrimes /* 1691573Srgrimes * and atkbdc? 1701573Srgrimes */ 1711573Srgrimes for (i = resource_query_string(-1, "at", "atkbdc"); 1721573Srgrimes i != -1; 17354770Sgreen i = resource_query_string(i, "at", "atkbdc")) { 1741573Srgrimes atkbdc_add_device(dev, resource_query_name(i), 1751573Srgrimes resource_query_unit(i)); 1761573Srgrimes } 1771573Srgrimes 1781573Srgrimes#ifdef __i386__ 1791573Srgrimes /* 1801573Srgrimes * Foot protection... 1811573Srgrimes */ 1821573Srgrimes for (i = resource_locate(-1, "atkbd"); 1831573Srgrimes i != -1; 1841573Srgrimes i = resource_locate(i, "atkbd")) { 1851573Srgrimes if (device_find_child(dev, resource_query_name(i), 1861573Srgrimes resource_query_unit(i)) == NULL) { 1871573Srgrimes printf("WARNING: Update your atkbdc config!\n"); 1881573Srgrimes atkbdc_add_device(dev, resource_query_name(i), 1891573Srgrimes resource_query_unit(i)); 1901573Srgrimes } 1911573Srgrimes } 1921573Srgrimes#endif 1931573Srgrimes 1941573Srgrimes bus_generic_attach(dev); 1951573Srgrimes 1961573Srgrimes return 0; 1971573Srgrimes} 1981573Srgrimes 1991573Srgrimesstatic void 2001573Srgrimesatkbdc_print_child(device_t bus, device_t dev) 2011573Srgrimes{ 2021573Srgrimes atkbdc_device_t *kbdcdev; 2031573Srgrimes 2041573Srgrimes kbdcdev = (atkbdc_device_t *)device_get_ivars(dev); 2051573Srgrimes 2061573Srgrimes if (kbdcdev->flags != 0) 2071573Srgrimes printf(" flags 0x%x", kbdcdev->flags); 2081573Srgrimes 2091573Srgrimes printf(" on %s%d", device_get_name(bus), device_get_unit(bus)); 2101573Srgrimes} 2111573Srgrimes 2121573Srgrimesstatic int 2131573Srgrimesatkbdc_read_ivar(device_t bus, device_t dev, int index, u_long *val) 2141573Srgrimes{ 2151573Srgrimes atkbdc_device_t *ivar; 2161573Srgrimes 2171573Srgrimes ivar = (atkbdc_device_t *)device_get_ivars(dev); 2181573Srgrimes switch (index) { 2191573Srgrimes case KBDC_IVAR_PORT: 2201573Srgrimes *val = (u_long)ivar->port; 2211573Srgrimes break; 2221573Srgrimes case KBDC_IVAR_IRQ: 2231573Srgrimes *val = (u_long)ivar->irq; 2241573Srgrimes break; 2251573Srgrimes case KBDC_IVAR_FLAGS: 2261573Srgrimes *val = (u_long)ivar->flags; 2271573Srgrimes break; 2281573Srgrimes default: 2291573Srgrimes return ENOENT; 2301573Srgrimes } 2311573Srgrimes return 0; 2321573Srgrimes} 2331573Srgrimes 2341573Srgrimesstatic int 2351573Srgrimesatkbdc_write_ivar(device_t bus, device_t dev, int index, u_long val) 2361573Srgrimes{ 2371573Srgrimes atkbdc_device_t *ivar; 2381573Srgrimes 2391573Srgrimes ivar = (atkbdc_device_t *)device_get_ivars(dev); 2401573Srgrimes switch (index) { 2411573Srgrimes case KBDC_IVAR_PORT: 2421573Srgrimes ivar->port = (int)val; 2431573Srgrimes break; 2441573Srgrimes case KBDC_IVAR_IRQ: 2451573Srgrimes ivar->irq = (int)val; 2461573Srgrimes break; 2471573Srgrimes case KBDC_IVAR_FLAGS: 2481573Srgrimes ivar->flags = (int)val; 24954770Sgreen break; 25054770Sgreen default: 25154770Sgreen return ENOENT; 25254770Sgreen } 25354770Sgreen return 0; 25454770Sgreen} 25554770Sgreen 25654770SgreenDRIVER_MODULE(atkbdc, isa, atkbdc_driver, atkbdc_devclass, 0, 0); 2571573Srgrimes 2581573Srgrimes#endif /* NATKBDC > 0 */ 25937349Sphk