18a997770SDoug Rabson /*- 28a997770SDoug Rabson * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 38a997770SDoug Rabson * All rights reserved. 48a997770SDoug Rabson * 58a997770SDoug Rabson * Redistribution and use in source and binary forms, with or without 68a997770SDoug Rabson * modification, are permitted provided that the following conditions 78a997770SDoug Rabson * are met: 88a997770SDoug Rabson * 1. Redistributions of source code must retain the above copyright 98a997770SDoug Rabson * notice, this list of conditions and the following disclaimer as 108a997770SDoug Rabson * the first lines of this file unmodified. 118a997770SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 128a997770SDoug Rabson * notice, this list of conditions and the following disclaimer in the 138a997770SDoug Rabson * documentation and/or other materials provided with the distribution. 148a997770SDoug Rabson * 158a997770SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 168a997770SDoug Rabson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 178a997770SDoug Rabson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 188a997770SDoug Rabson * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 198a997770SDoug Rabson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 208a997770SDoug Rabson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 218a997770SDoug Rabson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 228a997770SDoug Rabson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238a997770SDoug Rabson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 248a997770SDoug Rabson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258a997770SDoug Rabson */ 268a997770SDoug Rabson 278c9bbf48SDavid E. O'Brien #include <sys/cdefs.h> 288c9bbf48SDavid E. O'Brien __FBSDID("$FreeBSD$"); 298c9bbf48SDavid E. O'Brien 308a997770SDoug Rabson #include "opt_kbd.h" 318a997770SDoug Rabson 328a997770SDoug Rabson #include <sys/param.h> 338a997770SDoug Rabson #include <sys/systm.h> 348a997770SDoug Rabson #include <sys/kernel.h> 355dba30f1SPoul-Henning Kamp #include <sys/module.h> 368a997770SDoug Rabson #include <sys/bus.h> 378a997770SDoug Rabson 38db3e34cbSKazutaka YOKOTA #include <machine/bus.h> 398a997770SDoug Rabson #include <machine/resource.h> 40db3e34cbSKazutaka YOKOTA #include <sys/rman.h> 418a997770SDoug Rabson 4276495257SKazutaka YOKOTA #include <sys/kbio.h> 438a997770SDoug Rabson #include <dev/kbd/kbdreg.h> 44520b6353SMarius Strobl #include <dev/atkbdc/atkbdreg.h> 45520b6353SMarius Strobl #include <dev/atkbdc/atkbdcreg.h> 468a997770SDoug Rabson 47db3e34cbSKazutaka YOKOTA typedef struct { 48db3e34cbSKazutaka YOKOTA struct resource *intr; 49db3e34cbSKazutaka YOKOTA void *ih; 50db3e34cbSKazutaka YOKOTA } atkbd_softc_t; 51db3e34cbSKazutaka YOKOTA 5251da11a2SMark Murray static devclass_t atkbd_devclass; 538a997770SDoug Rabson 54ef92e447SKazutaka YOKOTA static void atkbdidentify(driver_t *driver, device_t dev); 558a997770SDoug Rabson static int atkbdprobe(device_t dev); 568a997770SDoug Rabson static int atkbdattach(device_t dev); 576c726162SKazutaka YOKOTA static int atkbdresume(device_t dev); 58520b6353SMarius Strobl static void atkbdintr(void *arg); 598a997770SDoug Rabson 608a997770SDoug Rabson static device_method_t atkbd_methods[] = { 61ef92e447SKazutaka YOKOTA DEVMETHOD(device_identify, atkbdidentify), 628a997770SDoug Rabson DEVMETHOD(device_probe, atkbdprobe), 638a997770SDoug Rabson DEVMETHOD(device_attach, atkbdattach), 646c726162SKazutaka YOKOTA DEVMETHOD(device_resume, atkbdresume), 658a997770SDoug Rabson { 0, 0 } 668a997770SDoug Rabson }; 678a997770SDoug Rabson 688a997770SDoug Rabson static driver_t atkbd_driver = { 698a997770SDoug Rabson ATKBD_DRIVER_NAME, 708a997770SDoug Rabson atkbd_methods, 71db3e34cbSKazutaka YOKOTA sizeof(atkbd_softc_t), 728a997770SDoug Rabson }; 738a997770SDoug Rabson 74ef92e447SKazutaka YOKOTA static void 75ef92e447SKazutaka YOKOTA atkbdidentify(driver_t *driver, device_t parent) 76ef92e447SKazutaka YOKOTA { 77ef92e447SKazutaka YOKOTA 78ef92e447SKazutaka YOKOTA /* always add at least one child */ 79cd6cd68dSKazutaka YOKOTA BUS_ADD_CHILD(parent, KBDC_RID_KBD, driver->name, device_get_unit(parent)); 80ef92e447SKazutaka YOKOTA } 81ef92e447SKazutaka YOKOTA 828a997770SDoug Rabson static int 838a997770SDoug Rabson atkbdprobe(device_t dev) 848a997770SDoug Rabson { 85ef92e447SKazutaka YOKOTA struct resource *res; 86ef92e447SKazutaka YOKOTA u_long irq; 87ef92e447SKazutaka YOKOTA int flags; 88ef92e447SKazutaka YOKOTA int rid; 898a997770SDoug Rabson 908a997770SDoug Rabson device_set_desc(dev, "AT Keyboard"); 918a997770SDoug Rabson 928a997770SDoug Rabson /* obtain parameters */ 93ef92e447SKazutaka YOKOTA flags = device_get_flags(dev); 94ef92e447SKazutaka YOKOTA 95ef92e447SKazutaka YOKOTA /* see if IRQ is available */ 96ef92e447SKazutaka YOKOTA rid = KBDC_RID_KBD; 975f96beb9SNate Lawson res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 98ef92e447SKazutaka YOKOTA RF_SHAREABLE | RF_ACTIVE); 99ef92e447SKazutaka YOKOTA if (res == NULL) { 100ef92e447SKazutaka YOKOTA if (bootverbose) 101ef92e447SKazutaka YOKOTA device_printf(dev, "unable to allocate IRQ\n"); 102ef92e447SKazutaka YOKOTA return ENXIO; 103ef92e447SKazutaka YOKOTA } 104ef92e447SKazutaka YOKOTA irq = rman_get_start(res); 105ef92e447SKazutaka YOKOTA bus_release_resource(dev, SYS_RES_IRQ, rid, res); 1068a997770SDoug Rabson 1078a997770SDoug Rabson /* probe the device */ 108db3e34cbSKazutaka YOKOTA return atkbd_probe_unit(device_get_unit(dev), 109db3e34cbSKazutaka YOKOTA device_get_unit(device_get_parent(dev)), 110db3e34cbSKazutaka YOKOTA irq, flags); 1118a997770SDoug Rabson } 1128a997770SDoug Rabson 1138a997770SDoug Rabson static int 1148a997770SDoug Rabson atkbdattach(device_t dev) 1158a997770SDoug Rabson { 116db3e34cbSKazutaka YOKOTA atkbd_softc_t *sc; 117800da3b2SKazutaka YOKOTA keyboard_t *kbd; 118ef92e447SKazutaka YOKOTA u_long irq; 119ef92e447SKazutaka YOKOTA int flags; 120db3e34cbSKazutaka YOKOTA int rid; 1218a997770SDoug Rabson int error; 1228a997770SDoug Rabson 123db3e34cbSKazutaka YOKOTA sc = device_get_softc(dev); 124db3e34cbSKazutaka YOKOTA 125ef92e447SKazutaka YOKOTA rid = KBDC_RID_KBD; 126ef92e447SKazutaka YOKOTA irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid); 127ef92e447SKazutaka YOKOTA flags = device_get_flags(dev); 128db3e34cbSKazutaka YOKOTA error = atkbd_attach_unit(device_get_unit(dev), &kbd, 129db3e34cbSKazutaka YOKOTA device_get_unit(device_get_parent(dev)), 130db3e34cbSKazutaka YOKOTA irq, flags); 1318a997770SDoug Rabson if (error) 1328a997770SDoug Rabson return error; 1338a997770SDoug Rabson 1348a997770SDoug Rabson /* declare our interrupt handler */ 1355f96beb9SNate Lawson sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 1368a997770SDoug Rabson RF_SHAREABLE | RF_ACTIVE); 137ef92e447SKazutaka YOKOTA if (sc->intr == NULL) 138ef92e447SKazutaka YOKOTA return ENXIO; 139ef544f63SPaolo Pisati error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, NULL, atkbdintr, 140ef92e447SKazutaka YOKOTA kbd, &sc->ih); 141ef92e447SKazutaka YOKOTA if (error) 142ef92e447SKazutaka YOKOTA bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr); 1438a997770SDoug Rabson 144ef92e447SKazutaka YOKOTA return error; 1458a997770SDoug Rabson } 1468a997770SDoug Rabson 1476c726162SKazutaka YOKOTA static int 1486c726162SKazutaka YOKOTA atkbdresume(device_t dev) 1496c726162SKazutaka YOKOTA { 150275658afSKazutaka YOKOTA atkbd_softc_t *sc; 1516c726162SKazutaka YOKOTA keyboard_t *kbd; 152275658afSKazutaka YOKOTA int args[2]; 1536c726162SKazutaka YOKOTA 154275658afSKazutaka YOKOTA sc = device_get_softc(dev); 1556c726162SKazutaka YOKOTA kbd = kbd_get_keyboard(kbd_find_keyboard(ATKBD_DRIVER_NAME, 1566c726162SKazutaka YOKOTA device_get_unit(dev))); 157275658afSKazutaka YOKOTA if (kbd) { 158275658afSKazutaka YOKOTA kbd->kb_flags &= ~KB_INITIALIZED; 159275658afSKazutaka YOKOTA args[0] = device_get_unit(device_get_parent(dev)); 160275658afSKazutaka YOKOTA args[1] = rman_get_start(sc->intr); 161259699b2SWojciech A. Koszek kbdd_init(kbd, device_get_unit(dev), &kbd, args, 162259699b2SWojciech A. Koszek device_get_flags(dev)); 163259699b2SWojciech A. Koszek kbdd_clear_state(kbd); 164275658afSKazutaka YOKOTA } 1656c726162SKazutaka YOKOTA return 0; 1666c726162SKazutaka YOKOTA } 1676c726162SKazutaka YOKOTA 168e9deda23SKazutaka YOKOTA static void 169520b6353SMarius Strobl atkbdintr(void *arg) 170e9deda23SKazutaka YOKOTA { 171800da3b2SKazutaka YOKOTA keyboard_t *kbd; 172e9deda23SKazutaka YOKOTA 173800da3b2SKazutaka YOKOTA kbd = (keyboard_t *)arg; 174259699b2SWojciech A. Koszek kbdd_intr(kbd, NULL); 175e9deda23SKazutaka YOKOTA } 176e9deda23SKazutaka YOKOTA 1778a997770SDoug Rabson DRIVER_MODULE(atkbd, atkbdc, atkbd_driver, atkbd_devclass, 0, 0); 178