#include "opt_kbd.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/thread.h>
#include <sys/machintr.h>
#include <sys/kbio.h>
#include <dev/misc/kbd/kbdreg.h>
#include <dev/misc/kbd/atkbdreg.h>
#include <dev/misc/kbd/atkbdcreg.h>
#include <bus/isa/isareg.h>
#include <bus/isa/isavar.h>
#if 0
#define lwkt_gettoken(x)
#define lwkt_reltoken(x)
#endif
typedef struct {
struct resource *intr;
void *ih;
} atkbd_softc_t;
devclass_t atkbd_devclass;
static int atkbdprobe(device_t dev);
static int atkbdattach(device_t dev);
static int atkbdresume(device_t dev);
static void atkbd_isa_intr(void *arg);
static device_method_t atkbd_methods[] = {
DEVMETHOD(device_probe, atkbdprobe),
DEVMETHOD(device_attach, atkbdattach),
DEVMETHOD(device_resume, atkbdresume),
DEVMETHOD_END
};
static driver_t atkbd_driver = {
ATKBD_DRIVER_NAME,
atkbd_methods,
sizeof(atkbd_softc_t),
};
static int
atkbdprobe(device_t dev)
{
uintptr_t irq;
uintptr_t flags;
device_set_desc(dev, "AT Keyboard");
BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_IRQ, &irq);
BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_FLAGS, &flags);
return atkbd_probe_unit(device_get_unit(dev),
device_get_unit(device_get_parent(dev)),
irq, flags);
}
static int
atkbdattach(device_t dev)
{
atkbd_softc_t *sc;
keyboard_t *kbd;
uintptr_t irq;
uintptr_t flags;
int rid;
int error;
sc = device_get_softc(dev);
BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_IRQ, &irq);
BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_FLAGS, &flags);
error = atkbd_attach_unit(device_get_unit(dev), &kbd,
device_get_unit(device_get_parent(dev)),
irq, flags);
if (error)
return error;
rid = 0;
sc->intr = bus_alloc_legacy_irq_resource(dev, &rid, irq, RF_ACTIVE);
BUS_SETUP_INTR(device_get_parent(dev), dev, sc->intr, INTR_MPSAFE,
atkbd_isa_intr, kbd, &sc->ih, NULL, NULL);
return 0;
}
static int
atkbdresume(device_t dev)
{
atkbd_softc_t *sc;
keyboard_t *kbd;
int args[2];
lwkt_gettoken(&kbd_token);
sc = device_get_softc(dev);
kbd = kbd_get_keyboard(kbd_find_keyboard(ATKBD_DRIVER_NAME,
device_get_unit(dev)));
if (kbd) {
kbd->kb_flags &= ~KB_INITIALIZED;
args[0] = device_get_unit(device_get_parent(dev));
args[1] = rman_get_start(sc->intr);
sw_init(kbdsw[kbd->kb_index], device_get_unit(dev), &kbd,
args, device_get_flags(dev));
kbd_clear_state(kbd);
}
lwkt_reltoken(&kbd_token);
return 0;
}
static void
atkbd_isa_intr(void *arg)
{
keyboard_t *kbd;
lwkt_gettoken(&kbd_token);
kbd = (keyboard_t *)arg;
kbd_intr(kbd, NULL);
lwkt_reltoken(&kbd_token);
}
DRIVER_MODULE(atkbd, atkbdc, atkbd_driver, atkbd_devclass, NULL, NULL);