atkbd_atkbdc.c revision 83492
191396Stmm/*-
291396Stmm * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3108834Stmm * All rights reserved.
491396Stmm *
591396Stmm * Redistribution and use in source and binary forms, with or without
691396Stmm * modification, are permitted provided that the following conditions
791396Stmm * are met:
891396Stmm * 1. Redistributions of source code must retain the above copyright
991396Stmm *    notice, this list of conditions and the following disclaimer as
1091396Stmm *    the first lines of this file unmodified.
1191396Stmm * 2. Redistributions in binary form must reproduce the above copyright
1291396Stmm *    notice, this list of conditions and the following disclaimer in the
1391396Stmm *    documentation and/or other materials provided with the distribution.
1491396Stmm *
1591396Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
1691396Stmm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1791396Stmm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1891396Stmm * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
1991396Stmm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2091396Stmm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2191396Stmm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2291396Stmm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2391396Stmm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2491396Stmm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2591396Stmm *
2691396Stmm * $FreeBSD: head/sys/dev/atkbdc/atkbd_atkbdc.c 83492 2001-09-15 04:38:20Z yokota $
2791396Stmm */
2891396Stmm
2991396Stmm#include "opt_kbd.h"
3091396Stmm
3191396Stmm#include <sys/param.h>
3291396Stmm#include <sys/systm.h>
3391396Stmm#include <sys/kernel.h>
3491396Stmm#include <sys/bus.h>
3591396Stmm
3691396Stmm#include <machine/bus.h>
37178470Smarius#include <machine/resource.h>
3891396Stmm#include <sys/rman.h>
3991396Stmm
40119418Sobrien#include <sys/kbio.h>
41119418Sobrien#include <dev/kbd/kbdreg.h>
42119418Sobrien#include <dev/kbd/atkbdreg.h>
4391396Stmm#include <dev/kbd/atkbdcreg.h>
4491396Stmm
4591396Stmm#include <isa/isareg.h>
4691396Stmm#include <isa/isavar.h>
4791396Stmm
4891396Stmmtypedef struct {
4991396Stmm	struct resource	*intr;
5091396Stmm	void		*ih;
5191396Stmm} atkbd_softc_t;
5291396Stmm
5391396Stmmdevclass_t	atkbd_devclass;
5491396Stmm
5591396Stmmstatic void	atkbdidentify(driver_t *driver, device_t dev);
5691396Stmmstatic int	atkbdprobe(device_t dev);
57133149Syongaristatic int	atkbdattach(device_t dev);
58133149Syongaristatic int	atkbdresume(device_t dev);
59133149Syongaristatic void	atkbd_isa_intr(void *arg);
60133149Syongari
61133149Syongaristatic device_method_t atkbd_methods[] = {
6291396Stmm	DEVMETHOD(device_identify,	atkbdidentify),
63133149Syongari	DEVMETHOD(device_probe,		atkbdprobe),
64178470Smarius	DEVMETHOD(device_attach,	atkbdattach),
6591396Stmm	DEVMETHOD(device_resume,	atkbdresume),
66178470Smarius	{ 0, 0 }
67210334Sattilio};
6891396Stmm
6991396Stmmstatic driver_t atkbd_driver = {
7091396Stmm	ATKBD_DRIVER_NAME,
7191396Stmm	atkbd_methods,
7295533Smike	sizeof(atkbd_softc_t),
7391396Stmm};
74130026Sphk
7591396Stmmstatic void
7691396Stmmatkbdidentify(driver_t *driver, device_t parent)
7791396Stmm{
7891396Stmm
7991396Stmm	/* always add at least one child */
8091396Stmm	BUS_ADD_CHILD(parent, KBDC_RID_KBD, driver->name, device_get_unit(parent));
81100980Sfenner}
8291396Stmm
8391396Stmmstatic int
8491396Stmmatkbdprobe(device_t dev)
8591396Stmm{
8691396Stmm	struct resource *res;
87147256Sbrooks	u_long irq;
88129006Sjoerg	int flags;
8991396Stmm	int rid;
90133149Syongari
91133149Syongari	device_set_desc(dev, "AT Keyboard");
92133149Syongari
93133149Syongari	/* obtain parameters */
94133149Syongari	flags = device_get_flags(dev);
95133149Syongari
9691396Stmm	/* see if IRQ is available */
9791396Stmm	rid = KBDC_RID_KBD;
9891396Stmm	res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
9991396Stmm				 RF_SHAREABLE | RF_ACTIVE);
10091396Stmm	if (res == NULL) {
101119351Smarcel		if (bootverbose)
102119351Smarcel			device_printf(dev, "unable to allocate IRQ\n");
10391396Stmm		return ENXIO;
104178470Smarius	}
105178470Smarius	irq = rman_get_start(res);
106178470Smarius	bus_release_resource(dev, SYS_RES_IRQ, rid, res);
10791396Stmm
108137982Syongari	/* probe the device */
10991396Stmm	return atkbd_probe_unit(device_get_unit(dev),
11091396Stmm				device_get_unit(device_get_parent(dev)),
11191396Stmm				irq, flags);
112164932Smarius}
11391396Stmm
114147256Sbrooksstatic int
11591396Stmmatkbdattach(device_t dev)
11691396Stmm{
11791396Stmm	atkbd_softc_t *sc;
11891396Stmm	keyboard_t *kbd;
11991396Stmm	u_long irq;
12091396Stmm	int flags;
12191396Stmm	int rid;
12291396Stmm	int error;
123164864Smarius
12491396Stmm	sc = device_get_softc(dev);
12591396Stmm
126151639Syongari	rid = KBDC_RID_KBD;
127133149Syongari	irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid);
12891396Stmm	flags = device_get_flags(dev);
12991396Stmm	error = atkbd_attach_unit(device_get_unit(dev), &kbd,
13091396Stmm				  device_get_unit(device_get_parent(dev)),
131133149Syongari				  irq, flags);
13291396Stmm	if (error)
13391396Stmm		return error;
13491396Stmm
13591396Stmm	/* declare our interrupt handler */
13691396Stmm	sc->intr = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
13791396Stmm				      RF_SHAREABLE | RF_ACTIVE);
13891396Stmm	if (sc->intr == NULL)
13991396Stmm		return ENXIO;
140108960Sobrien	error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, atkbd_isa_intr,
14191396Stmm			       kbd, &sc->ih);
14291396Stmm	if (error)
14391396Stmm		bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
144133599Smarius
14591396Stmm	return error;
14691396Stmm}
147133599Smarius
148178470Smariusstatic int
149178470Smariusatkbdresume(device_t dev)
150178470Smarius{
15191396Stmm	keyboard_t *kbd;
15291396Stmm
15391396Stmm	kbd = kbd_get_keyboard(kbd_find_keyboard(ATKBD_DRIVER_NAME,
154178470Smarius						 device_get_unit(dev)));
155178470Smarius	if (kbd)
15691396Stmm		(*kbdsw[kbd->kb_index]->clear_state)(kbd);
15791396Stmm	return 0;
158178470Smarius}
159178470Smarius
16091396Stmmstatic void
16191396Stmmatkbd_isa_intr(void *arg)
162178470Smarius{
163178470Smarius	keyboard_t *kbd;
16491396Stmm
16591396Stmm	kbd = (keyboard_t *)arg;
166178470Smarius	(*kbdsw[kbd->kb_index]->intr)(kbd, NULL);
167178470Smarius}
16891396Stmm
16991396StmmDRIVER_MODULE(atkbd, atkbdc, atkbd_driver, atkbd_devclass, 0, 0);
170178470Smarius