summaryrefslogtreecommitdiffstats
path: root/sys/isa/pnpparse.c
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2000-03-31 07:12:12 +0000
committerdfr <dfr@FreeBSD.org>2000-03-31 07:12:12 +0000
commit7c2c4384983ed7f9dd8cc3b0a2e79a2930206a24 (patch)
tree8b48e40ff76faab3d69865308e78b59ef6ff951b /sys/isa/pnpparse.c
parent66fbac6708f9965a51f2761d1dee2c005ed67283 (diff)
downloadFreeBSD-src-7c2c4384983ed7f9dd8cc3b0a2e79a2930206a24.zip
FreeBSD-src-7c2c4384983ed7f9dd8cc3b0a2e79a2930206a24.tar.gz
Fixes to parse more complex ISA PnP configurations.
Submitted by: Nikolai Saoukh <nms@Brigada-A.Ethereal.RU> PR: kern/17219
Diffstat (limited to 'sys/isa/pnpparse.c')
-rw-r--r--sys/isa/pnpparse.c118
1 files changed, 74 insertions, 44 deletions
diff --git a/sys/isa/pnpparse.c b/sys/isa/pnpparse.c
index 8782def..f5c8408 100644
--- a/sys/isa/pnpparse.c
+++ b/sys/isa/pnpparse.c
@@ -35,6 +35,8 @@
#include <isa/pnpreg.h>
#include <isa/pnpvar.h>
+#define MAXDEP 8
+
#define I16(p) ((p)[0] + ((p)[1] << 8))
#define I32(p) (I16(p) + (I16(p+2) << 16))
@@ -42,8 +44,7 @@
* Parse resource data for Logical Devices.
*
* This function exits as soon as it gets an error reading *ANY*
- * Resource Data or ir reaches the end of Resource Data. In the first
- * case the return value will be TRUE, FALSE otherwise.
+ * Resource Data or it reaches the end of Resource Data.
*/
void
pnp_parse_resources(device_t dev, u_char *resources, int len)
@@ -52,16 +53,17 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
u_char tag, *resp, *resinfo;
int large_len, scanning = len;
u_int32_t id, compat_id;
- struct isa_config logdev, alt;
struct isa_config *config;
- int priority = 0;
- int seenalt = 0;
+ int ncfgs = 1;
+ int priorities[1 + MAXDEP];
+ struct isa_config configs[1 + MAXDEP];
char buf[100];
+ int i;
id = isa_get_logicalid(dev);
- bzero(&logdev, sizeof logdev);
- bzero(&alt, sizeof alt);
- config = &logdev;
+ bzero(configs, sizeof configs);
+ config = &configs[0];
+ priorities[0] = 0;
resp = resources;
while (scanning > 0) {
tag = *resp++;
@@ -94,7 +96,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
I16(resinfo));
}
if (config->ic_nirq == ISA_NIRQ) {
- device_printf(parent, "too many irqs");
+ device_printf(parent, "too many irqs\n");
scanning = 0;
break;
}
@@ -110,7 +112,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
resinfo[0]);
}
if (config->ic_ndrq == ISA_NDRQ) {
- device_printf(parent, "too many drqs");
+ device_printf(parent, "too many drqs\n");
scanning = 0;
break;
}
@@ -124,25 +126,22 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
printf("%s: start dependant\n",
pnp_eisaformat(id));
}
- if (config == &alt) {
- ISA_ADD_CONFIG(parent, dev,
- priority, config);
- } else if (config != &logdev) {
- device_printf(parent, "malformed\n");
+ if (ncfgs >= MAXDEP) {
+ device_printf(parent, "too many dependant configs (%d)\n", MAXDEP);
scanning = 0;
break;
}
+ config = &configs[ncfgs];
/*
* If the priority is not specified,
* then use the default of
* 'acceptable'
*/
if (PNP_SRES_LEN(tag) > 0)
- priority = resinfo[0];
+ priorities[ncfgs] = resinfo[0];
else
- priority = 1;
- alt = logdev;
- config = &alt;
+ priorities[ncfgs] = 1;
+ ncfgs++;
break;
case PNP_TAG_END_DEPENDANT:
@@ -150,9 +149,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
printf("%s: end dependant\n",
pnp_eisaformat(id));
}
- ISA_ADD_CONFIG(parent, dev, priority, config);
- config = &logdev;
- seenalt = 1;
+ config = &configs[0]; /* back to main config */
break;
case PNP_TAG_IO_RANGE:
@@ -167,7 +164,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
resinfo[5]);
}
if (config->ic_nport == ISA_NPORT) {
- device_printf(parent, "too many ports");
+ device_printf(parent, "too many ports\n");
scanning = 0;
break;
}
@@ -188,7 +185,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
case PNP_TAG_IO_FIXED:
if (bootverbose) {
- printf("%s: adding io range "
+ printf("%s: adding fixed io range "
"%#x-%#x, size=%#x, "
"align=%#x\n",
pnp_eisaformat(id),
@@ -198,7 +195,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
1);
}
if (config->ic_nport == ISA_NPORT) {
- device_printf(parent, "too many ports");
+ device_printf(parent, "too many ports\n");
scanning = 0;
break;
}
@@ -214,7 +211,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
case PNP_TAG_END:
if (bootverbose) {
- printf("%s: start dependant\n",
+ printf("%s: end config\n",
pnp_eisaformat(id));
}
scanning = 0;
@@ -222,7 +219,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
default:
/* Skip this resource */
- device_printf(parent, "unexpected tag %d\n",
+ device_printf(parent, "unexpected small tag %d\n",
PNP_SRES_NUM(tag));
break;
}
@@ -251,9 +248,9 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
bcopy(resinfo, buf, large_len);
/*
- * Trim trailing spaces.
+ * Trim trailing spaces and garbage.
*/
- while (buf[large_len-1] == ' ')
+ while (large_len > 0 && buf[large_len - 1] <= ' ')
large_len--;
buf[large_len] = '\0';
device_set_desc_copy(dev, buf);
@@ -296,7 +293,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
case PNP_TAG_MEMORY32_RANGE:
if (bootverbose) {
- printf("%s: adding memory range "
+ printf("%s: adding memory32 range "
"%#x-%#x, size=%#x, "
"align=%#x\n",
pnp_eisaformat(id),
@@ -308,7 +305,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
}
if (config->ic_nmem == ISA_NMEM) {
- device_printf(parent, "too many memory ranges");
+ device_printf(parent, "too many memory ranges\n");
scanning = 0;
break;
}
@@ -334,7 +331,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
continue;
}
if (bootverbose) {
- printf("%s: adding memory range "
+ printf("%s: adding fixed memory32 range "
"%#x-%#x, size=%#x\n",
pnp_eisaformat(id),
I32(resinfo + 1),
@@ -344,7 +341,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
}
if (config->ic_nmem == ISA_NMEM) {
- device_printf(parent, "too many memory ranges");
+ device_printf(parent, "too many memory ranges\n");
scanning = 0;
break;
}
@@ -362,19 +359,52 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
default:
/* Skip this resource */
- device_printf(parent, "unexpected tag %d\n",
+ device_printf(parent, "unexpected large tag %d\n",
PNP_SRES_NUM(tag));
}
}
}
-
- /*
- * Some devices (e.g. network cards) don't have start
- * dependant tags and only have a single configuration. If we
- * finish parsing without seeing an end dependant tag, add the
- * non-dependant configuration to the device.
- */
- if (!seenalt)
- ISA_ADD_CONFIG(parent, dev, 1, config);
+ if(ncfgs == 1) {
+ /* Single config without dependants */
+ (void)ISA_ADD_CONFIG(parent, dev, priorities[0], &configs[0]);
+ return;
+ }
+ /* Cycle through dependant configs merging primary details */
+ for(i = 1; i < ncfgs; i++) {
+ int j;
+ config = &configs[i];
+ for(j = 0; j < configs[0].ic_nmem; j++) {
+ if (config->ic_nmem == ISA_NMEM) {
+ device_printf(parent, "too many memory ranges\n");
+ return;
+ }
+ config->ic_mem[config->ic_nmem] = configs[0].ic_mem[j];
+ config->ic_nmem++;
+ }
+ for(j = 0; j < configs[0].ic_nport; j++) {
+ if (config->ic_nport == ISA_NPORT) {
+ device_printf(parent, "too many port ranges\n");
+ return;
+ }
+ config->ic_port[config->ic_nport] = configs[0].ic_port[j];
+ config->ic_nport++;
+ }
+ for(j = 0; j < configs[0].ic_nirq; j++) {
+ if (config->ic_nirq == ISA_NIRQ) {
+ device_printf(parent, "too many irq ranges\n");
+ return;
+ }
+ config->ic_irqmask[config->ic_nirq] = configs[0].ic_irqmask[j];
+ config->ic_nirq++;
+ }
+ for(j = 0; j < configs[0].ic_ndrq; j++) {
+ if (config->ic_ndrq == ISA_NDRQ) {
+ device_printf(parent, "too many drq ranges\n");
+ return;
+ }
+ config->ic_drqmask[config->ic_ndrq] = configs[0].ic_drqmask[j];
+ config->ic_ndrq++;
+ }
+ (void)ISA_ADD_CONFIG(parent, dev, priorities[i], &configs[i]);
+ }
}
-
OpenPOWER on IntegriCloud