- If the atkbdc device is assigned an IRQ resource by ACPI or the PnPBIOS,
allow the child atkbd device to reuse that IRQ resource instead of reallocating the same IRQ from the parent bus inside the atkbd driver. - Don't allocate a shared IRQ for the atkbd driver. For AT keyboard devices on an ISA bus the IRQ is not shareable. Instead, the bus driver should mark the IRQ shareable if the bus supports shared IRQs. - Don't identify child devices until after the atkbdc device itself has attached.
This commit is contained in:
parent
2f29acd7ec
commit
ce7a3e4774
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216492
@ -94,8 +94,7 @@ atkbdprobe(device_t dev)
|
|||||||
|
|
||||||
/* see if IRQ is available */
|
/* see if IRQ is available */
|
||||||
rid = KBDC_RID_KBD;
|
rid = KBDC_RID_KBD;
|
||||||
res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
|
||||||
RF_SHAREABLE | RF_ACTIVE);
|
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
if (bootverbose)
|
if (bootverbose)
|
||||||
device_printf(dev, "unable to allocate IRQ\n");
|
device_printf(dev, "unable to allocate IRQ\n");
|
||||||
@ -132,8 +131,7 @@ atkbdattach(device_t dev)
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
/* declare our interrupt handler */
|
/* declare our interrupt handler */
|
||||||
sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
|
||||||
RF_SHAREABLE | RF_ACTIVE);
|
|
||||||
if (sc->intr == NULL)
|
if (sc->intr == NULL)
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, NULL, atkbdintr,
|
error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, NULL, atkbdintr,
|
||||||
|
@ -49,6 +49,11 @@ static int atkbdc_isa_probe(device_t dev);
|
|||||||
static int atkbdc_isa_attach(device_t dev);
|
static int atkbdc_isa_attach(device_t dev);
|
||||||
static device_t atkbdc_isa_add_child(device_t bus, u_int order, const char *name,
|
static device_t atkbdc_isa_add_child(device_t bus, u_int order, const char *name,
|
||||||
int unit);
|
int unit);
|
||||||
|
static struct resource *atkbdc_isa_alloc_resource(device_t dev, device_t child,
|
||||||
|
int type, int *rid, u_long start, u_long end,
|
||||||
|
u_long count, u_int flags);
|
||||||
|
static int atkbdc_isa_release_resource(device_t dev, device_t child,
|
||||||
|
int type, int rid, struct resource *r);
|
||||||
|
|
||||||
static device_method_t atkbdc_isa_methods[] = {
|
static device_method_t atkbdc_isa_methods[] = {
|
||||||
DEVMETHOD(device_probe, atkbdc_isa_probe),
|
DEVMETHOD(device_probe, atkbdc_isa_probe),
|
||||||
@ -61,8 +66,8 @@ static device_method_t atkbdc_isa_methods[] = {
|
|||||||
DEVMETHOD(bus_read_ivar, atkbdc_read_ivar),
|
DEVMETHOD(bus_read_ivar, atkbdc_read_ivar),
|
||||||
DEVMETHOD(bus_write_ivar, atkbdc_write_ivar),
|
DEVMETHOD(bus_write_ivar, atkbdc_write_ivar),
|
||||||
DEVMETHOD(bus_get_resource_list,atkbdc_get_resource_list),
|
DEVMETHOD(bus_get_resource_list,atkbdc_get_resource_list),
|
||||||
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
|
DEVMETHOD(bus_alloc_resource, atkbdc_isa_alloc_resource),
|
||||||
DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
|
DEVMETHOD(bus_release_resource, atkbdc_isa_release_resource),
|
||||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
|
||||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
|
||||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||||
@ -170,8 +175,6 @@ atkbdc_isa_probe(device_t dev)
|
|||||||
device_verbose(dev);
|
device_verbose(dev);
|
||||||
|
|
||||||
error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
|
error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
|
||||||
if (error == 0)
|
|
||||||
bus_generic_probe(dev);
|
|
||||||
|
|
||||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
|
||||||
bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
|
bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
|
||||||
@ -216,14 +219,25 @@ atkbdc_isa_attach(device_t dev)
|
|||||||
return ENXIO;
|
return ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the device is not created by the PnP BIOS or ACPI, then
|
||||||
|
* the hint for the IRQ is on the child atkbd device, not the
|
||||||
|
* keyboard controller, so this can fail.
|
||||||
|
*/
|
||||||
|
rid = 0;
|
||||||
|
sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
|
||||||
|
|
||||||
error = atkbdc_attach_unit(unit, sc, sc->port0, sc->port1);
|
error = atkbdc_attach_unit(unit, sc, sc->port0, sc->port1);
|
||||||
if (error) {
|
if (error) {
|
||||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
|
bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->port0);
|
||||||
bus_release_resource(dev, SYS_RES_IOPORT, 1, sc->port1);
|
bus_release_resource(dev, SYS_RES_IOPORT, 1, sc->port1);
|
||||||
|
if (sc->irq != NULL)
|
||||||
|
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
*(atkbdc_softc_t **)device_get_softc(dev) = sc;
|
*(atkbdc_softc_t **)device_get_softc(dev) = sc;
|
||||||
|
|
||||||
|
bus_generic_probe(dev);
|
||||||
bus_generic_attach(dev);
|
bus_generic_attach(dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -233,9 +247,11 @@ static device_t
|
|||||||
atkbdc_isa_add_child(device_t bus, u_int order, const char *name, int unit)
|
atkbdc_isa_add_child(device_t bus, u_int order, const char *name, int unit)
|
||||||
{
|
{
|
||||||
atkbdc_device_t *ivar;
|
atkbdc_device_t *ivar;
|
||||||
|
atkbdc_softc_t *sc;
|
||||||
device_t child;
|
device_t child;
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
|
sc = *(atkbdc_softc_t **)device_get_softc(bus);
|
||||||
ivar = malloc(sizeof(struct atkbdc_device), M_ATKBDDEV,
|
ivar = malloc(sizeof(struct atkbdc_device), M_ATKBDDEV,
|
||||||
M_NOWAIT | M_ZERO);
|
M_NOWAIT | M_ZERO);
|
||||||
if (!ivar)
|
if (!ivar)
|
||||||
@ -251,15 +267,16 @@ atkbdc_isa_add_child(device_t bus, u_int order, const char *name, int unit)
|
|||||||
ivar->rid = order;
|
ivar->rid = order;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the device is not created by the PnP BIOS or ACPI,
|
* If the device is not created by the PnP BIOS or ACPI, refer
|
||||||
* refer to device hints for IRQ.
|
* to device hints for IRQ. We always populate the resource
|
||||||
|
* list entry so we can use a standard bus_get_resource()
|
||||||
|
* method.
|
||||||
*/
|
*/
|
||||||
if (ISA_PNP_PROBE(device_get_parent(bus), bus, atkbdc_ids) != 0) {
|
if (sc->irq == NULL) {
|
||||||
if (resource_int_value(name, unit, "irq", &t) != 0)
|
if (resource_int_value(name, unit, "irq", &t) != 0)
|
||||||
t = -1;
|
t = -1;
|
||||||
} else {
|
} else
|
||||||
t = bus_get_resource_start(bus, SYS_RES_IRQ, ivar->rid);
|
t = rman_get_start(sc->irq);
|
||||||
}
|
|
||||||
if (t > 0)
|
if (t > 0)
|
||||||
resource_list_add(&ivar->resources, SYS_RES_IRQ, ivar->rid,
|
resource_list_add(&ivar->resources, SYS_RES_IRQ, ivar->rid,
|
||||||
t, t, 1);
|
t, t, 1);
|
||||||
@ -272,5 +289,30 @@ atkbdc_isa_add_child(device_t bus, u_int order, const char *name, int unit)
|
|||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct resource *
|
||||||
|
atkbdc_isa_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||||
|
u_long start, u_long end, u_long count, u_int flags)
|
||||||
|
{
|
||||||
|
atkbdc_softc_t *sc;
|
||||||
|
|
||||||
|
sc = *(atkbdc_softc_t **)device_get_softc(dev);
|
||||||
|
if (type == SYS_RES_IRQ && *rid == KBDC_RID_KBD && sc->irq != NULL)
|
||||||
|
return (sc->irq);
|
||||||
|
return (bus_generic_rl_alloc_resource(dev, child, type, rid, start,
|
||||||
|
end, count, flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
atkbdc_isa_release_resource(device_t dev, device_t child, int type, int rid,
|
||||||
|
struct resource *r)
|
||||||
|
{
|
||||||
|
atkbdc_softc_t *sc;
|
||||||
|
|
||||||
|
sc = *(atkbdc_softc_t **)device_get_softc(dev);
|
||||||
|
if (type == SYS_RES_IRQ && rid == KBDC_RID_KBD && r == sc->irq)
|
||||||
|
return (0);
|
||||||
|
return (bus_generic_rl_release_resource(dev, child, type, rid, r));
|
||||||
|
}
|
||||||
|
|
||||||
DRIVER_MODULE(atkbdc, isa, atkbdc_isa_driver, atkbdc_devclass, 0, 0);
|
DRIVER_MODULE(atkbdc, isa, atkbdc_isa_driver, atkbdc_devclass, 0, 0);
|
||||||
DRIVER_MODULE(atkbdc, acpi, atkbdc_isa_driver, atkbdc_devclass, 0, 0);
|
DRIVER_MODULE(atkbdc, acpi, atkbdc_isa_driver, atkbdc_devclass, 0, 0);
|
||||||
|
@ -192,6 +192,7 @@ struct resource;
|
|||||||
typedef struct atkbdc_softc {
|
typedef struct atkbdc_softc {
|
||||||
struct resource *port0; /* data port */
|
struct resource *port0; /* data port */
|
||||||
struct resource *port1; /* status port */
|
struct resource *port1; /* status port */
|
||||||
|
struct resource *irq;
|
||||||
bus_space_tag_t iot;
|
bus_space_tag_t iot;
|
||||||
bus_space_handle_t ioh0;
|
bus_space_handle_t ioh0;
|
||||||
bus_space_handle_t ioh1;
|
bus_space_handle_t ioh1;
|
||||||
|
Loading…
Reference in New Issue
Block a user