Fixes to parse more complex ISA PnP configurations.
Submitted by: Nikolai Saoukh <nms@Brigada-A.Ethereal.RU> PR: kern/17219
This commit is contained in:
parent
39f1e703ec
commit
acd3131b4b
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user