2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: src/sys/isa/atkbdc_isa.c,v 1.14.2.1 2000/03/31 12:52:05 yokota Exp $
27 * $DragonFly: src/sys/dev/misc/atkbdc_layer/atkbdc_isa.c,v 1.6 2006/10/25 20:55:54 dillon Exp $
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/kernel.h>
36 #include <sys/malloc.h>
39 #include <dev/misc/kbd/atkbdcreg.h>
41 #include <bus/isa/isareg.h>
42 #include <bus/isa/isavar.h>
44 MALLOC_DEFINE(M_ATKBDDEV
, "atkbddev", "AT Keyboard device");
47 typedef struct atkbdc_device
{
48 int flags
; /* configuration flags */
49 int irq
; /* ISA IRQ mask */
57 devclass_t atkbdc_devclass
;
59 static int atkbdc_probe(device_t dev
);
60 static int atkbdc_attach(device_t dev
);
61 static int atkbdc_print_child(device_t bus
, device_t dev
);
62 static int atkbdc_read_ivar(device_t bus
, device_t dev
, int index
,
64 static int atkbdc_write_ivar(device_t bus
, device_t dev
, int index
,
67 static device_method_t atkbdc_methods
[] = {
68 DEVMETHOD(device_probe
, atkbdc_probe
),
69 DEVMETHOD(device_attach
, atkbdc_attach
),
70 DEVMETHOD(device_suspend
, bus_generic_suspend
),
71 DEVMETHOD(device_resume
, bus_generic_resume
),
73 DEVMETHOD(bus_print_child
, atkbdc_print_child
),
74 DEVMETHOD(bus_read_ivar
, atkbdc_read_ivar
),
75 DEVMETHOD(bus_write_ivar
, atkbdc_write_ivar
),
76 DEVMETHOD(bus_alloc_resource
, bus_generic_alloc_resource
),
77 DEVMETHOD(bus_release_resource
, bus_generic_release_resource
),
78 DEVMETHOD(bus_activate_resource
, bus_generic_activate_resource
),
79 DEVMETHOD(bus_deactivate_resource
, bus_generic_deactivate_resource
),
80 DEVMETHOD(bus_setup_intr
, bus_generic_setup_intr
),
81 DEVMETHOD(bus_teardown_intr
, bus_generic_teardown_intr
),
86 static driver_t atkbdc_driver
= {
89 sizeof(atkbdc_softc_t
*),
92 static struct isa_pnp_id atkbdc_ids
[] = {
93 { 0x0303d041, "Keyboard controller (i8042)" }, /* PNP0303 */
98 atkbdc_probe(device_t dev
)
100 struct resource
*port0
;
101 struct resource
*port1
;
106 if (ISA_PNP_PROBE(device_get_parent(dev
), dev
, atkbdc_ids
) == ENXIO
)
109 device_set_desc(dev
, "Keyboard controller (i8042)");
112 port0
= bus_alloc_resource(dev
, SYS_RES_IOPORT
, &rid
, 0, ~0, 1,
117 if (bus_get_resource_start(dev
, SYS_RES_IOPORT
, 1) <= 0) {
118 bus_set_resource(dev
, SYS_RES_IOPORT
, 1,
119 rman_get_start(port0
) + KBD_STATUS_PORT
, 1);
122 port1
= bus_alloc_resource(dev
, SYS_RES_IOPORT
, &rid
, 0, ~0, 1,
125 bus_release_resource(dev
, SYS_RES_IOPORT
, 0, port0
);
129 error
= atkbdc_probe_unit(device_get_unit(dev
), port0
, port1
);
131 bus_release_resource(dev
, SYS_RES_IOPORT
, 0, port0
);
132 bus_release_resource(dev
, SYS_RES_IOPORT
, 1, port1
);
138 atkbdc_add_device(device_t dev
, const char *name
, int unit
)
140 atkbdc_device_t
*kdev
;
144 if (resource_int_value(name
, unit
, "disabled", &t
) == 0 && t
!= 0)
147 kdev
= kmalloc(sizeof(struct atkbdc_device
), M_ATKBDDEV
,
150 if (resource_int_value(name
, unit
, "irq", &t
) == 0)
155 if (resource_int_value(name
, unit
, "flags", &t
) == 0)
160 child
= device_add_child(dev
, name
, unit
);
161 device_set_ivars(child
, kdev
);
165 atkbdc_attach(device_t dev
)
173 unit
= device_get_unit(dev
);
174 sc
= *(atkbdc_softc_t
**)device_get_softc(dev
);
177 * We have to maintain two copies of the kbdc_softc struct,
178 * as the low-level console needs to have access to the
179 * keyboard controller before kbdc is probed and attached.
180 * kbdc_soft[] contains the default entry for that purpose.
183 sc
= atkbdc_get_softc(unit
);
189 sc
->port0
= bus_alloc_resource(dev
, SYS_RES_IOPORT
, &rid
, 0, ~0, 1,
191 if (sc
->port0
== NULL
)
194 sc
->port1
= bus_alloc_resource(dev
, SYS_RES_IOPORT
, &rid
, 0, ~0, 1,
196 if (sc
->port1
== NULL
) {
197 bus_release_resource(dev
, SYS_RES_IOPORT
, 0, sc
->port0
);
201 error
= atkbdc_attach_unit(unit
, sc
, sc
->port0
, sc
->port1
);
203 bus_release_resource(dev
, SYS_RES_IOPORT
, 0, sc
->port0
);
204 bus_release_resource(dev
, SYS_RES_IOPORT
, 1, sc
->port1
);
207 *(atkbdc_softc_t
**)device_get_softc(dev
) = sc
;
210 * Add all devices configured to be attached to atkbdc0.
212 for (i
= resource_query_string(-1, "at", device_get_nameunit(dev
));
214 i
= resource_query_string(i
, "at", device_get_nameunit(dev
))) {
215 atkbdc_add_device(dev
, resource_query_name(i
),
216 resource_query_unit(i
));
222 for (i
= resource_query_string(-1, "at", device_get_name(dev
));
224 i
= resource_query_string(i
, "at", device_get_name(dev
))) {
225 atkbdc_add_device(dev
, resource_query_name(i
),
226 resource_query_unit(i
));
229 bus_generic_attach(dev
);
235 atkbdc_print_child(device_t bus
, device_t dev
)
237 atkbdc_device_t
*kbdcdev
;
240 kbdcdev
= (atkbdc_device_t
*)device_get_ivars(dev
);
242 retval
+= bus_print_child_header(bus
, dev
);
243 if (kbdcdev
->flags
!= 0)
244 retval
+= printf(" flags 0x%x", kbdcdev
->flags
);
245 if (kbdcdev
->irq
!= -1)
246 retval
+= printf(" irq %d", kbdcdev
->irq
);
247 retval
+= bus_print_child_footer(bus
, dev
);
253 atkbdc_read_ivar(device_t bus
, device_t dev
, int index
, u_long
*val
)
255 atkbdc_device_t
*ivar
;
257 ivar
= (atkbdc_device_t
*)device_get_ivars(dev
);
260 *val
= (u_long
)ivar
->irq
;
262 case KBDC_IVAR_FLAGS
:
263 *val
= (u_long
)ivar
->flags
;
265 case KBDC_IVAR_VENDORID
:
266 *val
= (u_long
)ivar
->vendorid
;
268 case KBDC_IVAR_SERIAL
:
269 *val
= (u_long
)ivar
->serial
;
271 case KBDC_IVAR_LOGICALID
:
272 *val
= (u_long
)ivar
->logicalid
;
274 case KBDC_IVAR_COMPATID
:
275 *val
= (u_long
)ivar
->compatid
;
284 atkbdc_write_ivar(device_t bus
, device_t dev
, int index
, u_long val
)
286 atkbdc_device_t
*ivar
;
288 ivar
= (atkbdc_device_t
*)device_get_ivars(dev
);
291 ivar
->irq
= (int)val
;
293 case KBDC_IVAR_FLAGS
:
294 ivar
->flags
= (int)val
;
296 case KBDC_IVAR_VENDORID
:
297 ivar
->vendorid
= (u_int32_t
)val
;
299 case KBDC_IVAR_SERIAL
:
300 ivar
->serial
= (u_int32_t
)val
;
302 case KBDC_IVAR_LOGICALID
:
303 ivar
->logicalid
= (u_int32_t
)val
;
305 case KBDC_IVAR_COMPATID
:
306 ivar
->compatid
= (u_int32_t
)val
;
314 DRIVER_MODULE(atkbdc
, isa
, atkbdc_driver
, atkbdc_devclass
, 0, 0);