summaryrefslogtreecommitdiffstats
path: root/sys/isa/pnpparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/isa/pnpparse.c')
-rw-r--r--sys/isa/pnpparse.c199
1 files changed, 166 insertions, 33 deletions
diff --git a/sys/isa/pnpparse.c b/sys/isa/pnpparse.c
index 766869d..e513662 100644
--- a/sys/isa/pnpparse.c
+++ b/sys/isa/pnpparse.c
@@ -35,6 +35,9 @@
#include <isa/pnpreg.h>
#include <isa/pnpvar.h>
+#define I16(p) ((p)[0] + ((p)[1] << 8))
+#define I32(p) (I16(p) + (I16(p+2) << 16))
+
/*
* Parse resource data for Logical Devices.
*
@@ -48,13 +51,14 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
device_t parent = device_get_parent(dev);
u_char tag, *resp, *resinfo;
int large_len, scanning = len;
- u_int32_t compat_id;
+ u_int32_t id, compat_id;
struct isa_config logdev, alt;
struct isa_config *config;
int priority = 0;
int seenalt = 0;
char buf[100];
+ id = isa_get_logicalid(dev);
bzero(&logdev, sizeof logdev);
bzero(&alt, sizeof alt);
config = &logdev;
@@ -84,17 +88,27 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
break;
case PNP_TAG_IRQ_FORMAT:
+ if (bootverbose) {
+ printf("%s: adding irq mask %#04x\n",
+ pnp_eisaformat(id),
+ I16(resinfo));
+ }
if (config->ic_nirq == ISA_NIRQ) {
device_printf(parent, "too many irqs");
scanning = 0;
break;
}
config->ic_irqmask[config->ic_nirq] =
- resinfo[0] + (resinfo[1]<<8);
+ I16(resinfo);
config->ic_nirq++;
break;
case PNP_TAG_DMA_FORMAT:
+ if (bootverbose) {
+ printf("%s: adding dma mask %#02x\n",
+ pnp_eisaformat(id),
+ resinfo[0]);
+ }
if (config->ic_ndrq == ISA_NDRQ) {
device_printf(parent, "too many drqs");
scanning = 0;
@@ -106,6 +120,10 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
break;
case PNP_TAG_START_DEPENDANT:
+ if (bootverbose) {
+ printf("%s: start dependant\n",
+ pnp_eisaformat(id));
+ }
if (config == &alt) {
ISA_ADD_CONFIG(parent, dev,
priority, config);
@@ -128,47 +146,80 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
break;
case PNP_TAG_END_DEPENDANT:
+ if (bootverbose) {
+ printf("%s: end dependant\n",
+ pnp_eisaformat(id));
+ }
ISA_ADD_CONFIG(parent, dev, priority, config);
config = &logdev;
seenalt = 1;
break;
case PNP_TAG_IO_RANGE:
+ if (bootverbose) {
+ printf("%s: adding io range "
+ "%#x-%#x, size=%#x, "
+ "align=%#x\n",
+ pnp_eisaformat(id),
+ I16(resinfo + 1),
+ I16(resinfo + 3) + resinfo[6]-1,
+ resinfo[6],
+ resinfo[5]);
+ }
if (config->ic_nport == ISA_NPORT) {
device_printf(parent, "too many ports");
scanning = 0;
break;
}
config->ic_port[config->ic_nport].ir_start =
- resinfo[1] + (resinfo[2]<<8);
+ I16(resinfo + 1);
config->ic_port[config->ic_nport].ir_end =
- resinfo[3] + (resinfo[4]<<8)
- + resinfo[6] - 1;
- config->ic_port[config->ic_nport].ir_size
- =
+ I16(resinfo + 3) + resinfo[6] - 1;
+ config->ic_port[config->ic_nport].ir_size =
resinfo[6];
+ if (resinfo[5] == 0) {
+ /* Make sure align is at least one */
+ resinfo[5] = 1;
+ }
config->ic_port[config->ic_nport].ir_align =
resinfo[5];
config->ic_nport++;
break;
case PNP_TAG_IO_FIXED:
+ if (bootverbose) {
+ printf("%s: adding io range "
+ "%#x-%#x, size=%#x, "
+ "align=%#x\n",
+ pnp_eisaformat(id),
+ I16(resinfo),
+ I16(resinfo) + resinfo[2] - 1,
+ resinfo[2],
+ 1);
+ }
if (config->ic_nport == ISA_NPORT) {
device_printf(parent, "too many ports");
scanning = 0;
break;
}
config->ic_port[config->ic_nport].ir_start =
- resinfo[0] + (resinfo[1]<<8);
+ I16(resinfo);
config->ic_port[config->ic_nport].ir_end =
- resinfo[0] + (resinfo[1]<<8)
- + resinfo[2] - 1;
+ I16(resinfo) + resinfo[2] - 1;
config->ic_port[config->ic_nport].ir_size
= resinfo[2];
config->ic_port[config->ic_nport].ir_align = 1;
config->ic_nport++;
break;
+ case PNP_TAG_END:
+ if (bootverbose) {
+ printf("%s: start dependant\n",
+ pnp_eisaformat(id));
+ }
+ scanning = 0;
+ break;
+
default:
/* Skip this resource */
device_printf(parent, "unexpected tag %d\n",
@@ -181,7 +232,7 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
scanning = 0;
continue;
}
- large_len = resp[0] + (resp[1] << 8);
+ large_len = I16(resp);
resp += 2;
scanning -= 2;
@@ -193,7 +244,8 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
resp += large_len;
scanning -= large_len;
- if (PNP_LRES_NUM(tag) == PNP_TAG_ID_ANSI) {
+ switch (PNP_LRES_NUM(tag)) {
+ case PNP_TAG_ID_ANSI:
if (large_len > sizeof(buf) - 1)
large_len = sizeof(buf) - 1;
bcopy(resinfo, buf, large_len);
@@ -205,32 +257,113 @@ pnp_parse_resources(device_t dev, u_char *resources, int len)
large_len--;
buf[large_len] = '\0';
device_set_desc_copy(dev, buf);
- continue;
- }
+ break;
+
+ case PNP_TAG_MEMORY_RANGE:
+ if (bootverbose) {
+ printf("%s: adding memory range "
+ "%#x-%#x, size=%#x, "
+ "align=%#x\n",
+ pnp_eisaformat(id),
+ I16(resinfo + 1)<<8,
+ (I16(resinfo + 3)<<8)
+ + I16(resinfo + 7) - 1,
+ I16(resinfo + 7),
+ I16(resinfo + 5));
+ }
- if (PNP_LRES_NUM(tag) != PNP_TAG_MEMORY_RANGE) {
- /* skip */
- continue;
- }
+ if (config->ic_nmem == ISA_NMEM) {
+ device_printf(parent, "too many memory ranges");
+ scanning = 0;
+ break;
+ }
- if (config->ic_nmem == ISA_NMEM) {
- device_printf(parent, "too many memory ranges");
- scanning = 0;
+ config->ic_mem[config->ic_nmem].ir_start =
+ I16(resinfo + 1)<<8;
+ config->ic_mem[config->ic_nmem].ir_end =
+ (I16(resinfo + 3)<<8)
+ + I16(resinfo + 7) - 1;
+ config->ic_mem[config->ic_nmem].ir_size =
+ I16(resinfo + 7);
+ config->ic_mem[config->ic_nmem].ir_align =
+ I16(resinfo + 5);
+ if (!config->ic_mem[config->ic_nmem].ir_align)
+ config->ic_mem[config->ic_nmem]
+ .ir_align = 0x10000;
+ config->ic_nmem++;
break;
- }
- config->ic_mem[config->ic_nmem].ir_start =
- (resinfo[4]<<8) + (resinfo[5]<<16);
- config->ic_mem[config->ic_nmem].ir_end =
- (resinfo[6]<<8) + (resinfo[7]<<16);
- config->ic_mem[config->ic_nmem].ir_size =
- (resinfo[10]<<8) + (resinfo[11]<<16);
- config->ic_mem[config->ic_nmem].ir_align =
- resinfo[8] + (resinfo[9]<<8);
- if (!config->ic_mem[config->ic_nmem].ir_align)
+ case PNP_TAG_MEMORY32_RANGE:
+ if (bootverbose) {
+ printf("%s: adding memory range "
+ "%#x-%#x, size=%#x, "
+ "align=%#x\n",
+ pnp_eisaformat(id),
+ I32(resinfo + 1),
+ I32(resinfo + 5)
+ + I32(resinfo + 13) - 1,
+ I32(resinfo + 13),
+ I32(resinfo + 9));
+ }
+
+ if (config->ic_nmem == ISA_NMEM) {
+ device_printf(parent, "too many memory ranges");
+ scanning = 0;
+ break;
+ }
+
+ config->ic_mem[config->ic_nmem].ir_start =
+ I32(resinfo + 1);
+ config->ic_mem[config->ic_nmem].ir_end =
+ I32(resinfo + 5)
+ + I32(resinfo + 13) - 1;
+ config->ic_mem[config->ic_nmem].ir_size =
+ I32(resinfo + 13);
config->ic_mem[config->ic_nmem].ir_align =
- 0x10000;
- config->ic_nmem++;
+ I32(resinfo + 9);
+ config->ic_nmem++;
+ break;
+
+ case PNP_TAG_MEMORY32_FIXED:
+ if (I32(resinfo + 5) == 0) {
+ if (bootverbose) {
+ printf("%s: skipping empty range\n",
+ pnp_eisaformat(id));
+ }
+ continue;
+ }
+ if (bootverbose) {
+ printf("%s: adding memory range "
+ "%#x-%#x, size=%#x\n",
+ pnp_eisaformat(id),
+ I32(resinfo + 1),
+ I32(resinfo + 1)
+ + I32(resinfo + 5) - 1,
+ I32(resinfo + 5));
+ }
+
+ if (config->ic_nmem == ISA_NMEM) {
+ device_printf(parent, "too many memory ranges");
+ scanning = 0;
+ break;
+ }
+
+ config->ic_mem[config->ic_nmem].ir_start =
+ I32(resinfo + 1);
+ config->ic_mem[config->ic_nmem].ir_end =
+ I32(resinfo + 1)
+ + I32(resinfo + 5) - 1;
+ config->ic_mem[config->ic_nmem].ir_size =
+ I32(resinfo + 5);
+ config->ic_mem[config->ic_nmem].ir_align = 1;
+ config->ic_nmem++;
+ break;
+
+ default:
+ /* Skip this resource */
+ device_printf(parent, "unexpected tag %d\n",
+ PNP_SRES_NUM(tag));
+ }
}
}
OpenPOWER on IntegriCloud