diff options
author | njl <njl@FreeBSD.org> | 2004-08-03 00:41:47 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2004-08-03 00:41:47 +0000 |
commit | 53952beb8e0e58c401450f6ac5cb6db589f14b47 (patch) | |
tree | 9fb44c58102ee5047cb62513d8f44e89c8d8712a /sys/dev/eisa | |
parent | f1c5d06dafda07bbabdf361ed5f124b97f49a5d3 (diff) | |
download | FreeBSD-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.
Diffstat (limited to 'sys/dev/eisa')
-rw-r--r-- | sys/dev/eisa/eisaconf.c | 54 |
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) { |