aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDoug Rabson <dfr@FreeBSD.org>1999-10-14 21:03:03 +0000
committerDoug Rabson <dfr@FreeBSD.org>1999-10-14 21:03:03 +0000
commitbb2b9030e84f6638c53379fa3061ee49bef5b868 (patch)
tree9cfc808248748600189af9b09481a97025b4b8ce /sys
parent0fe2cc8ec8b378c99b16273edd6240d99290df41 (diff)
downloadsrc-bb2b9030e84f6638c53379fa3061ee49bef5b868.tar.gz
src-bb2b9030e84f6638c53379fa3061ee49bef5b868.zip
* Add some verbose logging to the PnP parser and fix a couple of bugs.
* Move pnp_eisaformat() to pnp.c, declared in <isa/pnpvar.h>. * Turn the pnpbios code into an enumerator for the isa bus. This allows all devices known to the bios to be probed automatically. Currently the pnpbios code is dependant on the PNPBIOS option. As the code is tested more and when more drivers are converted this will be made the default. I have PnP changes in the wings for fdc, atkbd, psm, pcaudio, and joy. Sio already works with pnpbios.
Notes
Notes: svn path=/head/; revision=52241
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/bios.c73
-rw-r--r--sys/i386/i386/bios.c73
-rw-r--r--sys/isa/pnp.c18
-rw-r--r--sys/isa/pnpparse.c199
-rw-r--r--sys/isa/pnpvar.h1
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 */