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>