143105Sdfr/*-
243105Sdfr * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
343105Sdfr * All rights reserved.
443105Sdfr *
543105Sdfr * Redistribution and use in source and binary forms, with or without
643105Sdfr * modification, are permitted provided that the following conditions
743105Sdfr * are met:
843105Sdfr * 1. Redistributions of source code must retain the above copyright
943105Sdfr *    notice, this list of conditions and the following disclaimer as
1043105Sdfr *    the first lines of this file unmodified.
1143105Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1243105Sdfr *    notice, this list of conditions and the following disclaimer in the
1343105Sdfr *    documentation and/or other materials provided with the distribution.
1443105Sdfr *
1543105Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
1643105Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1743105Sdfr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1843105Sdfr * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1943105Sdfr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2043105Sdfr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2143105Sdfr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2243105Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2343105Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2443105Sdfr * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2543105Sdfr */
2643105Sdfr
27116181Sobrien#include <sys/cdefs.h>
28116181Sobrien__FBSDID("$FreeBSD$");
29116181Sobrien
3043105Sdfr#include "opt_kbd.h"
3143105Sdfr
3243105Sdfr#include <sys/param.h>
3343105Sdfr#include <sys/systm.h>
3443105Sdfr#include <sys/kernel.h>
35129880Sphk#include <sys/module.h>
3643105Sdfr#include <sys/bus.h>
3758271Syokota
3845720Speter#include <machine/bus.h>
3958271Syokota#include <machine/resource.h>
4043105Sdfr#include <sys/rman.h>
4143105Sdfr
4280040Syokota#include <sys/kbio.h>
4343105Sdfr#include <dev/kbd/kbdreg.h>
44147271Smarius#include <dev/atkbdc/atkbdreg.h>
45147271Smarius#include <dev/atkbdc/atkbdcreg.h>
4643105Sdfr
4758271Syokotatypedef struct {
4858271Syokota	struct resource	*intr;
4958271Syokota	void		*ih;
5058271Syokota} atkbd_softc_t;
5158271Syokota
52114293Smarkmstatic devclass_t	atkbd_devclass;
5343105Sdfr
5483147Syokotastatic void	atkbdidentify(driver_t *driver, device_t dev);
5543105Sdfrstatic int	atkbdprobe(device_t dev);
5643105Sdfrstatic int	atkbdattach(device_t dev);
5779022Syokotastatic int	atkbdresume(device_t dev);
58147271Smariusstatic void	atkbdintr(void *arg);
5943105Sdfr
6043105Sdfrstatic device_method_t atkbd_methods[] = {
6183147Syokota	DEVMETHOD(device_identify,	atkbdidentify),
6243105Sdfr	DEVMETHOD(device_probe,		atkbdprobe),
6343105Sdfr	DEVMETHOD(device_attach,	atkbdattach),
6479022Syokota	DEVMETHOD(device_resume,	atkbdresume),
6543105Sdfr	{ 0, 0 }
6643105Sdfr};
6743105Sdfr
6843105Sdfrstatic driver_t atkbd_driver = {
6943105Sdfr	ATKBD_DRIVER_NAME,
7043105Sdfr	atkbd_methods,
7158271Syokota	sizeof(atkbd_softc_t),
7243105Sdfr};
7343105Sdfr
7483147Syokotastatic void
7583147Syokotaatkbdidentify(driver_t *driver, device_t parent)
7683147Syokota{
7783147Syokota
7883147Syokota	/* always add at least one child */
7983492Syokota	BUS_ADD_CHILD(parent, KBDC_RID_KBD, driver->name, device_get_unit(parent));
8083147Syokota}
8183147Syokota
8243105Sdfrstatic int
8343105Sdfratkbdprobe(device_t dev)
8443105Sdfr{
8583147Syokota	struct resource *res;
8683147Syokota	u_long irq;
8783147Syokota	int flags;
8883147Syokota	int rid;
8943105Sdfr
9043105Sdfr	device_set_desc(dev, "AT Keyboard");
9143105Sdfr
9243105Sdfr	/* obtain parameters */
9383147Syokota	flags = device_get_flags(dev);
9443105Sdfr
9583147Syokota	/* see if IRQ is available */
9683147Syokota	rid = KBDC_RID_KBD;
97216492Sjhb	res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
9883147Syokota	if (res == NULL) {
9983147Syokota		if (bootverbose)
10083147Syokota			device_printf(dev, "unable to allocate IRQ\n");
10183147Syokota		return ENXIO;
10283147Syokota	}
10383147Syokota	irq = rman_get_start(res);
10483147Syokota	bus_release_resource(dev, SYS_RES_IRQ, rid, res);
10583147Syokota
10643105Sdfr	/* probe the device */
107245315Simp	return atkbd_probe_unit(dev, irq, flags);
10843105Sdfr}
10943105Sdfr
11043105Sdfrstatic int
11143105Sdfratkbdattach(device_t dev)
11243105Sdfr{
11358271Syokota	atkbd_softc_t *sc;
11450154Syokota	keyboard_t *kbd;
11583147Syokota	u_long irq;
11683147Syokota	int flags;
11758271Syokota	int rid;
11843105Sdfr	int error;
11943105Sdfr
12058271Syokota	sc = device_get_softc(dev);
12158271Syokota
12283147Syokota	rid = KBDC_RID_KBD;
12383147Syokota	irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid);
12483147Syokota	flags = device_get_flags(dev);
125245315Simp	error = atkbd_attach_unit(dev, &kbd, irq, flags);
12643105Sdfr	if (error)
12743105Sdfr		return error;
12843105Sdfr
12943105Sdfr	/* declare our interrupt handler */
130216492Sjhb	sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
13183147Syokota	if (sc->intr == NULL)
13283147Syokota		return ENXIO;
133166901Spiso	error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, NULL, atkbdintr,
13483147Syokota			       kbd, &sc->ih);
13583147Syokota	if (error)
13683147Syokota		bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
13743105Sdfr
13883147Syokota	return error;
13943105Sdfr}
14043105Sdfr
14179022Syokotastatic int
14279022Syokotaatkbdresume(device_t dev)
14379022Syokota{
14483855Syokota	atkbd_softc_t *sc;
14579022Syokota	keyboard_t *kbd;
14683855Syokota	int args[2];
14779022Syokota
14883855Syokota	sc = device_get_softc(dev);
14979022Syokota	kbd = kbd_get_keyboard(kbd_find_keyboard(ATKBD_DRIVER_NAME,
15079022Syokota						 device_get_unit(dev)));
15183855Syokota	if (kbd) {
15283855Syokota		kbd->kb_flags &= ~KB_INITIALIZED;
15383855Syokota		args[0] = device_get_unit(device_get_parent(dev));
15483855Syokota		args[1] = rman_get_start(sc->intr);
155174984Swkoszek		kbdd_init(kbd, device_get_unit(dev), &kbd, args,
156174984Swkoszek		    device_get_flags(dev));
157174984Swkoszek		kbdd_clear_state(kbd);
15883855Syokota	}
15979022Syokota	return 0;
16079022Syokota}
16179022Syokota
16244628Syokotastatic void
163147271Smariusatkbdintr(void *arg)
16444628Syokota{
16550154Syokota	keyboard_t *kbd;
16644628Syokota
16750154Syokota	kbd = (keyboard_t *)arg;
168174984Swkoszek	kbdd_intr(kbd, NULL);
16944628Syokota}
17044628Syokota
17143105SdfrDRIVER_MODULE(atkbd, atkbdc, atkbd_driver, atkbd_devclass, 0, 0);
172