summaryrefslogtreecommitdiffstats
path: root/sys/isa/isa_common.c
diff options
context:
space:
mode:
authoryokota <yokota@FreeBSD.org>2001-09-05 03:54:33 +0000
committeryokota <yokota@FreeBSD.org>2001-09-05 03:54:33 +0000
commitfb9afad90ef704606abdfb01a279a685bd8483b7 (patch)
treed38fcd9f070b41f11a15c00daf65269c937a5a90 /sys/isa/isa_common.c
parent72b8fa9d630b906a60463c3dd1d89e435769debe (diff)
downloadFreeBSD-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.c94
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;
}
OpenPOWER on IntegriCloud