diff options
Diffstat (limited to 'sys/isa/pnpparse.c')
-rw-r--r-- | sys/isa/pnpparse.c | 199 |
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)); + } } } |