diff options
author | yokota <yokota@FreeBSD.org> | 2001-09-05 03:54:33 +0000 |
---|---|---|
committer | yokota <yokota@FreeBSD.org> | 2001-09-05 03:54:33 +0000 |
commit | fb9afad90ef704606abdfb01a279a685bd8483b7 (patch) | |
tree | d38fcd9f070b41f11a15c00daf65269c937a5a90 /sys/isa/isa_common.c | |
parent | 72b8fa9d630b906a60463c3dd1d89e435769debe (diff) | |
download | FreeBSD-src-fb9afad90ef704606abdfb01a279a685bd8483b7.zip FreeBSD-src-fb9afad90ef704606abdfb01a279a685bd8483b7.tar.gz |
Rework the ISA PnP driver pnp and the PnP resource parser to fix
the following bugs.
- When constructing a resource configuration, respect the order
in which resource descriptors are read, in order to establish
the correct mapping between the descriptors and configuration
registers.
"Plug and Play ISA Specification, Version 1.0a", Sec 4.6.1, May 5,
1994. "Clarifications to the Plug and Play ISA Specification,
Version 1.0a", Sec 6.2.1, Dec. 10, 1994.
- Do not ignore null (empty) descriptors; they are valid descriptors
acting as filler.
"Clarifications to the Plug and Play ISA Specification, Version 1.0a",
Sec 6.2.1.
- Correctly set up logical device configuration registers for null
resources.
"Clarifications to the Plug and Play ISA Specification, Version 1.0a"
- Handle null resources properly in the resource allocator for the
ISA bus.
Diffstat (limited to 'sys/isa/isa_common.c')
-rw-r--r-- | sys/isa/isa_common.c | 94 |
1 files changed, 92 insertions, 2 deletions
diff --git a/sys/isa/isa_common.c b/sys/isa/isa_common.c index 22677e3..d5aee38 100644 --- a/sys/isa/isa_common.c +++ b/sys/isa/isa_common.c @@ -133,9 +133,20 @@ isa_find_memory(device_t child, result->ic_nmem = config->ic_nmem; for (i = 0; i < config->ic_nmem; i++) { u_int32_t start, end, size, align; + + size = config->ic_mem[i].ir_size; + + /* the PnP device may have a null resource as filler */ + if (size == 0) { + result->ic_mem[i].ir_start = 0; + result->ic_mem[i].ir_end = 0; + result->ic_mem[i].ir_size = 0; + result->ic_mem[i].ir_align = 0; + continue; + } + for (start = config->ic_mem[i].ir_start, end = config->ic_mem[i].ir_end, - size = config->ic_mem[i].ir_size, align = config->ic_mem[i].ir_align; start + size - 1 <= end; start += align) { @@ -197,9 +208,20 @@ isa_find_port(device_t child, result->ic_nport = config->ic_nport; for (i = 0; i < config->ic_nport; i++) { u_int32_t start, end, size, align; + + size = config->ic_port[i].ir_size; + + /* the PnP device may have a null resource as filler */ + if (size == 0) { + result->ic_port[i].ir_start = 0; + result->ic_port[i].ir_end = 0; + result->ic_port[i].ir_size = 0; + result->ic_port[i].ir_align = 0; + continue; + } + for (start = config->ic_port[i].ir_start, end = config->ic_port[i].ir_end, - size = config->ic_port[i].ir_size, align = config->ic_port[i].ir_align; start + size - 1 <= end; start += align) { @@ -285,6 +307,13 @@ isa_find_irq(device_t child, for (i = 0; i < config->ic_nirq; i++) { u_int32_t mask = config->ic_irqmask[i]; int irq; + + /* the PnP device may have a null resource as filler */ + if (mask == 0) { + result->ic_irqmask[i] = 0; + continue; + } + for (irq = find_first_bit(mask); irq != -1; irq = find_next_bit(mask, irq)) { @@ -344,6 +373,13 @@ isa_find_drq(device_t child, for (i = 0; i < config->ic_ndrq; i++) { u_int32_t mask = config->ic_drqmask[i]; int drq; + + /* the PnP device may have a null resource as filler */ + if (mask == 0) { + result->ic_drqmask[i] = 0; + continue; + } + for (drq = find_first_bit(mask); drq != -1; drq = find_next_bit(mask, drq)) { @@ -430,6 +466,55 @@ isa_assign_resources(device_t child) } /* + * Return non-zero if the device has a single configuration, that is, + * a fixed set of resoruces. + */ +static int +isa_has_single_config(device_t dev) +{ + struct isa_device *idev = DEVTOISA(dev); + struct isa_config_entry *ice; + u_int32_t mask; + int i; + + ice = TAILQ_FIRST(&idev->id_configs); + if (TAILQ_NEXT(ice, ice_link)) + return 0; + + for (i = 0; i < ice->ice_config.ic_nmem; ++i) { + if (ice->ice_config.ic_mem[i].ir_size == 0) + continue; + if (ice->ice_config.ic_mem[i].ir_end != + ice->ice_config.ic_mem[i].ir_start + + ice->ice_config.ic_mem[i].ir_size - 1) + return 0; + } + for (i = 0; i < ice->ice_config.ic_nport; ++i) { + if (ice->ice_config.ic_port[i].ir_size == 0) + continue; + if (ice->ice_config.ic_port[i].ir_end != + ice->ice_config.ic_port[i].ir_start + + ice->ice_config.ic_port[i].ir_size - 1) + return 0; + } + for (i = 0; i < ice->ice_config.ic_nirq; ++i) { + mask = ice->ice_config.ic_irqmask[i]; + if (mask == 0) + continue; + if (find_next_bit(mask, find_first_bit(mask)) != -1) + return 0; + } + for (i = 0; i < ice->ice_config.ic_ndrq; ++i) { + mask = ice->ice_config.ic_drqmask[i]; + if (mask == 0) + continue; + if (find_next_bit(mask, find_first_bit(mask)) != -1) + return 0; + } + return 1; +} + +/* * Called after other devices have initialised to probe for isa devices. */ void @@ -962,6 +1047,11 @@ isa_add_config(device_t dev, device_t child, else TAILQ_INSERT_TAIL(&idev->id_configs, newice, ice_link); + if (isa_has_single_config(child)) + idev->id_config_attr &= ~ISACFGATTR_MULTI; + else + idev->id_config_attr |= ISACFGATTR_MULTI; + return 0; } |