Date: Mon, 6 Mar 2000 16:21:39 +0300 (MSK) From: nms@Brigada-A.Ethereal.RU To: FreeBSD-gnats-submit@freebsd.org Subject: kern/17219: ISA PNP Parser rather limited (with patch, includes patch from kern/16712) Message-ID: <20000306132139.EE40A1FC@Brigada-A.Ethereal.RU>
next in thread | raw e-mail | index | archive | help
>Number: 17219
>Category: kern
>Synopsis: ISA PNP Parser rather limited (with patch, includes patch from kern/16712)
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Mon Mar 6 05:30:00 PST 2000
>Closed-Date:
>Last-Modified:
>Originator: Nikolai Saoukh
>Release: FreeBSD 4.0-CURRENT i386
>Organization:
>Environment:
>Description:
As present (src/sys/isa/pnpparse.c, version 1.2) pnp parser can not parse a little
bit more complex configuration. for example
IBM0000: start dependant
IBM0000: adding io range 0xa20-0xa23, size=0x4, align=0x4
IBM0000: start dependant
IBM0000: adding io range 0xa24-0xa27, size=0x4, align=0x4
IBM0000: end dependant
IBM0000: adding memory range 0xc0000-0xdffff, size=0x4000, align=0x4000
IBM0000: adding memory range 0xc8000-0xdffff, size=0x2000, align=0x2000
IBM0000: adding irq mask 0xe08
(taken from IBM Auto 16/4 Token-Ring ISA Adapter).
>How-To-Repeat:
>Fix:
The patch attached (it incorporates patch from kern/16712)
--- pnpparse.c.orig Tue Feb 22 11:23:27 2000
+++ pnpparse.c Mon Mar 6 16:05:55 2000
@@ -36,4 +36,6 @@
#include <isa/pnpvar.h>
+#define MAXDEP 8
+
#define I16(p) ((p)[0] + ((p)[1] << 8))
#define I32(p) (I16(p) + (I16(p+2) << 16))
@@ -43,6 +45,5 @@
*
* 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
@@ -53,14 +54,15 @@
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) {
@@ -95,5 +97,5 @@
}
if (config->ic_nirq == ISA_NIRQ) {
- device_printf(parent, "too many irqs");
+ device_printf(parent, "too many irqs\n");
scanning = 0;
break;
@@ -111,5 +113,5 @@
}
if (config->ic_ndrq == ISA_NDRQ) {
- device_printf(parent, "too many drqs");
+ device_printf(parent, "too many drqs\n");
scanning = 0;
break;
@@ -125,12 +127,10 @@
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,
@@ -139,9 +139,8 @@
*/
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;
@@ -151,7 +150,5 @@
pnp_eisaformat(id));
}
- ISA_ADD_CONFIG(parent, dev, priority, config);
- config = &logdev;
- seenalt = 1;
+ config = &configs[0]; /* back to main config */
break;
@@ -168,5 +165,5 @@
}
if (config->ic_nport == ISA_NPORT) {
- device_printf(parent, "too many ports");
+ device_printf(parent, "too many ports\n");
scanning = 0;
break;
@@ -189,5 +186,5 @@
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",
@@ -199,5 +196,5 @@
}
if (config->ic_nport == ISA_NPORT) {
- device_printf(parent, "too many ports");
+ device_printf(parent, "too many ports\n");
scanning = 0;
break;
@@ -215,5 +212,5 @@
case PNP_TAG_END:
if (bootverbose) {
- printf("%s: start dependant\n",
+ printf("%s: end config\n",
pnp_eisaformat(id));
}
@@ -223,5 +220,5 @@
default:
/* Skip this resource */
- device_printf(parent, "unexpected tag %d\n",
+ device_printf(parent, "unexpected small tag %d\n",
PNP_SRES_NUM(tag));
break;
@@ -252,7 +249,7 @@
/*
- * 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';
@@ -268,11 +265,11 @@
I16(resinfo + 1)<<8,
(I16(resinfo + 3)<<8)
- + I16(resinfo + 7) - 1,
- I16(resinfo + 7),
+ + (I16(resinfo + 7) << 8) - 1,
+ I16(resinfo + 7) << 8,
I16(resinfo + 5));
}
if (config->ic_nmem == ISA_NMEM) {
- device_printf(parent, "too many memory ranges");
+ device_printf(parent, "too many memory ranges\n");
scanning = 0;
break;
@@ -285,5 +282,5 @@
+ I16(resinfo + 7) - 1;
config->ic_mem[config->ic_nmem].ir_size =
- I16(resinfo + 7);
+ I16(resinfo + 7) << 8;
config->ic_mem[config->ic_nmem].ir_align =
I16(resinfo + 5);
@@ -296,5 +293,5 @@
case PNP_TAG_MEMORY32_RANGE:
if (bootverbose) {
- printf("%s: adding memory range "
+ printf("%s: adding memory32 range "
"%#x-%#x, size=%#x, "
"align=%#x\n",
@@ -308,5 +305,5 @@
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,5 +331,5 @@
}
if (bootverbose) {
- printf("%s: adding memory range "
+ printf("%s: adding fixed memory32 range "
"%#x-%#x, size=%#x\n",
pnp_eisaformat(id),
@@ -344,5 +341,5 @@
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,18 +359,51 @@
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]);
+ }
}
-
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000306132139.EE40A1FC>
