diff options
-rw-r--r-- | sys/amd64/amd64/bios.c | 73 | ||||
-rw-r--r-- | sys/i386/i386/bios.c | 73 | ||||
-rw-r--r-- | sys/isa/pnp.c | 18 | ||||
-rw-r--r-- | sys/isa/pnpparse.c | 199 | ||||
-rw-r--r-- | sys/isa/pnpvar.h | 1 |
5 files changed, 281 insertions, 83 deletions
diff --git a/sys/amd64/amd64/bios.c b/sys/amd64/amd64/bios.c index b66d87212226..63158c4686b7 100644 --- a/sys/amd64/amd64/bios.c +++ b/sys/amd64/amd64/bios.c @@ -31,10 +31,13 @@ * Code for dealing with the BIOS in x86 PC systems. */ +#include "opt_pnp.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/bus.h> #include <vm/vm.h> #include <vm/pmap.h> #include <machine/md_var.h> @@ -43,6 +46,8 @@ #include <machine/vmparam.h> #include <machine/pc/bios.h> #include <isa/pnpreg.h> +#include <isa/pnpvar.h> +#include <isa/isavar.h> #define BIOS_START 0xe0000 #define BIOS_SIZE 0x20000 @@ -57,10 +62,6 @@ static u_int bios32_SDCI = 0; static void bios32_init(void *junk); SYSINIT(bios32, SI_SUB_CPU, SI_ORDER_ANY, bios32_init, NULL); -static void pnpbios_scan(void); -static char *pnp_eisaformat(u_int8_t *data); - - /* * bios32_init * @@ -127,7 +128,6 @@ bios32_init(void *junk) printf("pnpbios: OEM ID %x\n", pt->oemdevid); } - pnpbios_scan(); } else { printf("pnpbios: Bad PnP BIOS data checksum\n"); } @@ -450,6 +450,8 @@ bios16(struct bios_args *args, char *fmt, ...) return (i); } +#ifdef PNPBIOS /* remove conditional later */ + /* * PnP BIOS interface; enumerate devices only known to the system * BIOS and save information about them for later use. @@ -484,10 +486,19 @@ struct pnp_sysdevargs }; /* + * This function is called after the bus has assigned resource + * locations for a logical device. + */ +static void +pnpbios_set_config(void *arg, struct isa_config *config, int enable) +{ +} + +/* * Quiz the PnP BIOS, build a list of PNP IDs and resource data. */ static void -pnpbios_scan(void) +pnpbios_identify(driver_t *driver, device_t parent) { struct PnPBIOS_table *pt = PnPBIOStable; struct bios_args args; @@ -498,6 +509,7 @@ pnpbios_scan(void) u_int8_t *devnodebuf, tag; u_int32_t *devid, *compid; int idx, left; + device_t dev; /* no PnP BIOS information */ if (pt == NULL) @@ -542,6 +554,16 @@ pnpbios_scan(void) break; } + /* Add the device and parse its resources */ + dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1); + isa_set_vendorid(dev, pd->devid); + isa_set_logicalid(dev, pd->devid); + ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0); + pnp_parse_resources(dev, &pd->devdata[0], + pd->size - sizeof(struct pnp_sysdev)); + if (!device_get_desc(dev)) + device_set_desc_copy(dev, pnp_eisaformat(pd->devid)); + /* Find device IDs */ devid = &pd->devid; compid = NULL; @@ -572,29 +594,30 @@ pnpbios_scan(void) } if (bootverbose) { printf("pnpbios: handle %d device ID %s (%08x)", - pd->handle, pnp_eisaformat((u_int8_t *)devid), *devid); + pd->handle, pnp_eisaformat(*devid), *devid); if (compid != NULL) printf(" compat ID %s (%08x)", - pnp_eisaformat((u_int8_t *)compid), *compid); + pnp_eisaformat(*compid), *compid); printf("\n"); } } } -/* XXX should be somewhere else */ -static char * -pnp_eisaformat(u_int8_t *data) -{ - static char idbuf[8]; - const char hextoascii[] = "0123456789abcdef"; - - idbuf[0] = '@' + ((data[0] & 0x7c) >> 2); - idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5)); - idbuf[2] = '@' + (data[1] & 0x1f); - idbuf[3] = hextoascii[(data[2] >> 4)]; - idbuf[4] = hextoascii[(data[2] & 0xf)]; - idbuf[5] = hextoascii[(data[3] >> 4)]; - idbuf[6] = hextoascii[(data[3] & 0xf)]; - idbuf[7] = 0; - return(idbuf); -} +static device_method_t pnpbios_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, pnpbios_identify), + + { 0, 0 } +}; + +static driver_t pnpbios_driver = { + "pnpbios", + pnpbios_methods, + 1, /* no softc */ +}; + +static devclass_t pnpbios_devclass; + +DRIVER_MODULE(pnpbios, isa, pnpbios_driver, pnpbios_devclass, 0, 0); + +#endif /* PNPBIOS */ diff --git a/sys/i386/i386/bios.c b/sys/i386/i386/bios.c index b66d87212226..63158c4686b7 100644 --- a/sys/i386/i386/bios.c +++ b/sys/i386/i386/bios.c @@ -31,10 +31,13 @@ * Code for dealing with the BIOS in x86 PC systems. */ +#include "opt_pnp.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/bus.h> #include <vm/vm.h> #include <vm/pmap.h> #include <machine/md_var.h> @@ -43,6 +46,8 @@ #include <machine/vmparam.h> #include <machine/pc/bios.h> #include <isa/pnpreg.h> +#include <isa/pnpvar.h> +#include <isa/isavar.h> #define BIOS_START 0xe0000 #define BIOS_SIZE 0x20000 @@ -57,10 +62,6 @@ static u_int bios32_SDCI = 0; static void bios32_init(void *junk); SYSINIT(bios32, SI_SUB_CPU, SI_ORDER_ANY, bios32_init, NULL); -static void pnpbios_scan(void); -static char *pnp_eisaformat(u_int8_t *data); - - /* * bios32_init * @@ -127,7 +128,6 @@ bios32_init(void *junk) printf("pnpbios: OEM ID %x\n", pt->oemdevid); } - pnpbios_scan(); } else { printf("pnpbios: Bad PnP BIOS data checksum\n"); } @@ -450,6 +450,8 @@ bios16(struct bios_args *args, char *fmt, ...) return (i); } +#ifdef PNPBIOS /* remove conditional later */ + /* * PnP BIOS interface; enumerate devices only known to the system * BIOS and save information about them for later use. @@ -484,10 +486,19 @@ struct pnp_sysdevargs }; /* + * This function is called after the bus has assigned resource + * locations for a logical device. + */ +static void +pnpbios_set_config(void *arg, struct isa_config *config, int enable) +{ +} + +/* * Quiz the PnP BIOS, build a list of PNP IDs and resource data. */ static void -pnpbios_scan(void) +pnpbios_identify(driver_t *driver, device_t parent) { struct PnPBIOS_table *pt = PnPBIOStable; struct bios_args args; @@ -498,6 +509,7 @@ pnpbios_scan(void) u_int8_t *devnodebuf, tag; u_int32_t *devid, *compid; int idx, left; + device_t dev; /* no PnP BIOS information */ if (pt == NULL) @@ -542,6 +554,16 @@ pnpbios_scan(void) break; } + /* Add the device and parse its resources */ + dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1); + isa_set_vendorid(dev, pd->devid); + isa_set_logicalid(dev, pd->devid); + ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0); + pnp_parse_resources(dev, &pd->devdata[0], + pd->size - sizeof(struct pnp_sysdev)); + if (!device_get_desc(dev)) + device_set_desc_copy(dev, pnp_eisaformat(pd->devid)); + /* Find device IDs */ devid = &pd->devid; compid = NULL; @@ -572,29 +594,30 @@ pnpbios_scan(void) } if (bootverbose) { printf("pnpbios: handle %d device ID %s (%08x)", - pd->handle, pnp_eisaformat((u_int8_t *)devid), *devid); + pd->handle, pnp_eisaformat(*devid), *devid); if (compid != NULL) printf(" compat ID %s (%08x)", - pnp_eisaformat((u_int8_t *)compid), *compid); + pnp_eisaformat(*compid), *compid); printf("\n"); } } } -/* XXX should be somewhere else */ -static char * -pnp_eisaformat(u_int8_t *data) -{ - static char idbuf[8]; - const char hextoascii[] = "0123456789abcdef"; - - idbuf[0] = '@' + ((data[0] & 0x7c) >> 2); - idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5)); - idbuf[2] = '@' + (data[1] & 0x1f); - idbuf[3] = hextoascii[(data[2] >> 4)]; - idbuf[4] = hextoascii[(data[2] & 0xf)]; - idbuf[5] = hextoascii[(data[3] >> 4)]; - idbuf[6] = hextoascii[(data[3] & 0xf)]; - idbuf[7] = 0; - return(idbuf); -} +static device_method_t pnpbios_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, pnpbios_identify), + + { 0, 0 } +}; + +static driver_t pnpbios_driver = { + "pnpbios", + pnpbios_methods, + 1, /* no softc */ +}; + +static devclass_t pnpbios_devclass; + +DRIVER_MODULE(pnpbios, isa, pnpbios_driver, pnpbios_devclass, 0, 0); + +#endif /* PNPBIOS */ diff --git a/sys/isa/pnp.c b/sys/isa/pnp.c index abd79f4affbb..12b5dabf1fe3 100644 --- a/sys/isa/pnp.c +++ b/sys/isa/pnp.c @@ -90,6 +90,24 @@ static void pnp_send_initiation_key(void); static int pnp_get_serial(pnp_id *p); static int pnp_isolation_protocol(device_t parent); +char * +pnp_eisaformat(u_int32_t id) +{ + u_int8_t *data = (u_int8_t *) &id; + static char idbuf[8]; + const char hextoascii[] = "0123456789abcdef"; + + idbuf[0] = '@' + ((data[0] & 0x7c) >> 2); + idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5)); + idbuf[2] = '@' + (data[1] & 0x1f); + idbuf[3] = hextoascii[(data[2] >> 4)]; + idbuf[4] = hextoascii[(data[2] & 0xf)]; + idbuf[5] = hextoascii[(data[3] >> 4)]; + idbuf[6] = hextoascii[(data[3] & 0xf)]; + idbuf[7] = 0; + return(idbuf); +} + static void pnp_write(int d, u_char r) { diff --git a/sys/isa/pnpparse.c b/sys/isa/pnpparse.c index 766869dff9e0..e513662524eb 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)); + } } } diff --git a/sys/isa/pnpvar.h b/sys/isa/pnpvar.h index bfd26dab2650..5f1a6dcdb234 100644 --- a/sys/isa/pnpvar.h +++ b/sys/isa/pnpvar.h @@ -52,6 +52,7 @@ u_char pnp_read(int d); /* currently unused, but who knows... */ | (PNP_HEXTONUM(s[6]) << 24) \ | (PNP_HEXTONUM(s[5]) << 28)) +char *pnp_eisaformat(u_int32_t id); void pnp_parse_resources(device_t dev, u_char *resources, int len); #endif /* KERNEL */ |