summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-08-03 00:41:47 +0000
committernjl <njl@FreeBSD.org>2004-08-03 00:41:47 +0000
commit53952beb8e0e58c401450f6ac5cb6db589f14b47 (patch)
tree9fb44c58102ee5047cb62513d8f44e89c8d8712a
parentf1c5d06dafda07bbabdf361ed5f124b97f49a5d3 (diff)
downloadFreeBSD-src-53952beb8e0e58c401450f6ac5cb6db589f14b47.zip
FreeBSD-src-53952beb8e0e58c401450f6ac5cb6db589f14b47.tar.gz
Change EISA probing to be less invasive. Instead of probing all slots
unconditionally, stop after the first one (system board) if no EISA hardware is detected. This fixes a boot hang (i.e. Thinkpad) when ACPI is disabled. Also, split the probe code into a separate function and do some style cleanup. Note that the Adaptec 2842 VLB controller probe is broken by this change and will fail to probe. It should be fixed separately.
-rw-r--r--sys/dev/eisa/eisaconf.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/sys/dev/eisa/eisaconf.c b/sys/dev/eisa/eisaconf.c
index de5f4ff..a26e17d 100644
--- a/sys/dev/eisa/eisaconf.c
+++ b/sys/dev/eisa/eisaconf.c
@@ -92,6 +92,7 @@ TUNABLE_INT("hw.eisa_slots", &num_eisa_slots);
static devclass_t eisa_devclass;
+static int eisa_probe_slot(int slot, eisa_id_t *eisa_id);
static void eisa_reg_print (device_t, char *, char *, int *);
static struct irq_node * eisa_find_irq(struct eisa_device *e_dev, int rid);
static struct resvaddr * eisa_find_maddr(struct eisa_device *e_dev, int rid);
@@ -152,24 +153,31 @@ DRIVER_MODULE(mainboard, eisa, mainboard_driver, mainboard_devclass, 0, 0);
static int
eisa_probe(device_t dev)
{
- int i,slot;
+ int devices_found, i, slot;
struct eisa_device *e_dev;
device_t child;
- int eisaBase = 0xc80;
eisa_id_t eisa_id;
- int devices_found = 0;
device_set_desc(dev, "EISA bus");
- for (slot = 0; slot < num_eisa_slots; eisaBase+=0x1000, slot++) {
- int id_size = sizeof(eisa_id);
+ devices_found = 0;
+ for (slot = 0; slot < num_eisa_slots; slot++) {
eisa_id = 0;
- for( i = 0; i < id_size; i++ ) {
- outb(eisaBase,0x80 + i); /*Some cards require priming*/
- eisa_id |= inb(eisaBase+i) << ((id_size-i-1)*CHAR_BIT);
+ if (eisa_probe_slot(i, &eisa_id)) {
+ /*
+ * If there's no card in the first slot (the
+ * mainboard), then the system doesn't have EISA.
+ * We abort the probe early in this case since
+ * continuing on causes a hang on some systems.
+ * Interestingly enough, the inb has been seen to
+ * cause the hang. However, aborting here causes
+ * the Adaptec 2842 probe to fail so that driver
+ * needs to be fixed separately.
+ */
+ if (slot == 0)
+ break;
+ continue;
}
- if (eisa_id & 0x80000000)
- continue; /* no EISA card in slot */
devices_found++;
@@ -182,7 +190,6 @@ eisa_probe(device_t dev)
}
e_dev->id = eisa_id;
-
e_dev->ioconf.slot = slot;
/* Initialize our lists of reserved addresses */
@@ -202,6 +209,31 @@ eisa_probe(device_t dev)
return devices_found ? 0 : ENXIO;
}
+static int
+eisa_probe_slot(int slot, eisa_id_t *eisa_id)
+{
+ eisa_id_t probe_id;
+ int base, i, id_size, ret;
+
+ ret = ENXIO;
+ probe_id = 0;
+ id_size = sizeof(probe_id);
+ base = 0x0c80 + (slot * 0x1000);
+
+ for (i = 0; i < id_size; i++) {
+ outb(base, 0x80 + i); /* Some cards require priming. */
+ probe_id |= inb(base + i) << ((id_size - i - 1) * CHAR_BIT);
+ }
+
+ /* If we found a card, return its EISA id. */
+ if ((probe_id & 0x80000000) == 0) {
+ *eisa_id = probe_id;
+ ret = 0;
+ }
+
+ return (ret);
+}
+
static void
eisa_probe_nomatch(device_t dev, device_t child)
{
OpenPOWER on IntegriCloud