Skip site navigation (1)Skip section navigation (2)
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>