summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorderaadt <deraadt@NetBSD.org>1994-04-11 11:09:00 +0000
committerderaadt <deraadt@NetBSD.org>1994-04-11 11:09:00 +0000
commite7eb2d483159111d2d62c64cd79d8b085bf028f9 (patch)
treedf6255e955e004c30241a1b6494db3d8061e0648 /sys/dev
parentf7a0b6da1d653094fb602d4b3d4bf5607600068f (diff)
support multiple eisa/isa cards.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/isa/if_ep.c203
1 files changed, 129 insertions, 74 deletions
diff --git a/sys/dev/isa/if_ep.c b/sys/dev/isa/if_ep.c
index 36178d79d2c..05f21ca8413 100644
--- a/sys/dev/isa/if_ep.c
+++ b/sys/dev/isa/if_ep.c
@@ -21,7 +21,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: if_ep.c,v 1.27 1994/04/08 17:58:47 mycroft Exp $
+ * $Id: if_ep.c,v 1.28 1994/04/11 11:09:00 deraadt Exp $
*/
/*
* TODO:
@@ -112,11 +112,35 @@ static void epstop __P((struct ep_softc *));
static u_short epreadeeprom __P((int id_port, int offset));
static int epbusyeeprom __P((struct ep_softc *));
+#define MAXEPCARDS 20 /* if you have 21 cards in your machine... you lose */
+
+static struct epcard {
+ u_short port;
+ u_short irq;
+ char available;
+} epcards[MAXEPCARDS];
+static int nepcards;
+
+static void
+epaddcard(p, i)
+ short p;
+ u_short i;
+{
+ if (nepcards >= sizeof(epcards)/sizeof(epcards[0]))
+ return;
+ epcards[nepcards].port = p;
+ epcards[nepcards].irq = 1 << ((i == 2) ? 9 : i);
+ epcards[nepcards].available = 1;
+ nepcards++;
+}
+
/*
- * Eisa probe routine. If any part of this probe should fail to
- * return the desired result, the isa_epprobe() is called. Astute
- * readers will discover a problem that I don't feel inclined to address
- * at the moment.
+ * 3c579 cards on the EISA bus are probed by their slot number. 3c509
+ * cards on the ISA bus are probed in ethernet address order. The probe
+ * sequence requires careful orchestration, and we'd like like to allow
+ * the irq and base address to be wildcarded. So, we probe all the cards
+ * the first time epprobe() is called. On subsequent calls we look for
+ * matching cards.
*/
int
epprobe(parent, self, aux)
@@ -125,84 +149,115 @@ epprobe(parent, self, aux)
{
struct ep_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
- int port;
- int i;
- int eisa_slot;
- u_short k;
-
- eisa_slot=1;
- while (eisa_slot < 8) {
- port = 0x1000 * eisa_slot;
- outw(port + EP_COMMAND, GLOBAL_RESET);
- delay(1000);
- if (inw(port + EP_W0_MFG_ID) == MFG_ID)
- break;
- eisa_slot++;
- }
- k = inw(port + EP_W0_PRODUCT_ID);
- if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
- return isa_epprobe(sc, ia);
+ static int firsttime;
+ int slot, port, i;
+ u_short k, k2;
+
+ if (firsttime==0) {
+ firsttime = 1;
+
+ /* find all EISA cards */
+ for (slot = 1; slot < 8; slot++) {
+ port = 0x1000 * slot;
+ outw(port + EP_COMMAND, GLOBAL_RESET);
+ delay(1000);
+ if (inw(port + EP_W0_MFG_ID) != MFG_ID)
+ continue;
+ k = inw(port + EP_W0_PRODUCT_ID);
+ if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
+ continue;
+ k = inw(port + EP_W0_ADDRESS_CFG);
+ k = (k & 0x1f) * 0x10 + 0x200;
+ k2 = inw(port + EP_W0_RESOURCE_CFG);
+ k2 >>= 12;
+ epaddcard(port, k2);
+ }
- k = inw(port + EP_W0_ADDRESS_CFG);
- k = (k & 0x1f) * 0x10 + 0x200; /* decode base addr. */
-
- k = inw(port + EP_W0_RESOURCE_CFG);
- k >>= 12;
- if (ia->ia_irq != (1 << ((k == 2) ? 9 : k)))
- return isa_epprobe(sc, ia);
+ /* find all isa cards */
+ outw(BASE + EP_COMMAND, GLOBAL_RESET);
+ delay(1000);
+ elink_reset(); /* global reset to ELINK_ID_PORT */
+ delay(1000);
- ia->ia_iobase = port; /* Set the base addr for later */
- ia->ia_iosize = 0x10;
- ia->ia_msize = 0;
- return 1;
-}
+ for (slot = 0; slot < 10; slot++) {
+ outb(ELINK_ID_PORT, 0x00);
+ elink_idseq(ELINK_509_POLY);
+ delay(1000);
-/*
- * Rudimentary support for multiple cards is here but is not
- * currently handled. In the future we will have to add code
- * for tagging the cards for later activation. We wanna do something
- * about the ELINK_ID_PORT. We're limited due to current config procedure.
- * Magnum config holds promise of a fix but we'll have to wait a bit.
- */
-int
-isa_epprobe(sc, ia)
- struct ep_softc *sc;
- struct isa_attach_args *ia;
-{
- u_short k;
+ k = epreadeeprom(ELINK_ID_PORT, EEPROM_MFG_ID);
+ if (k == 0xff)
+ continue; /* no more isa cards */
+ if (k != MFG_ID)
+ continue;
+ k = epreadeeprom(ELINK_ID_PORT, EEPROM_PROD_ID);
+ if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
+ continue;
- outw(BASE + EP_COMMAND, GLOBAL_RESET);
- delay(1000);
- elink_reset(); /* global reset to ELINK_ID_PORT */
- delay(1000);
- outb(ELINK_ID_PORT, 0x00);
- elink_idseq(ELINK_509_POLY);
- delay(1000);
+ k = epreadeeprom(ELINK_ID_PORT, EEPROM_ADDR_CFG);
+ k = (k & 0x1f) * 0x10 + 0x200;
- /*
- * MFG_ID should have 0x6d50.
- * PROD_ID should be 0x9[0-f]50
- */
- k = epreadeeprom(ELINK_ID_PORT, EEPROM_MFG_ID);
- if (k != MFG_ID)
- return (0);
- k = epreadeeprom(ELINK_ID_PORT, EEPROM_PROD_ID);
- if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
- return (0);
+ k2 = epreadeeprom(ELINK_ID_PORT, EEPROM_RESOURCE_CFG);
+ k2 >>= 12;
+ epaddcard(k, k2);
- k = epreadeeprom(ELINK_ID_PORT, EEPROM_ADDR_CFG); /* get addr cfg */
- k = (k & 0x1f) * 0x10 + 0x200; /* decode base addr. */
- if (k != ia->ia_iobase)
- return (0);
+ /* so card will not respond to contention again */
+ outb(ELINK_ID_PORT, TAG_ADAPTER_0 + 1);
- k = epreadeeprom(ELINK_ID_PORT, EEPROM_RESOURCE_CFG);
- k >>= 12;
- if (ia->ia_irq != (1 << ((k == 2) ? 9 : k)))
- return (0);
+ /*
+ * XXX: this should probably not be done here
+ * because it enables the drq/irq lines from
+ * the board. Perhaps it should be done after
+ * we have checked for irq/drq collisions?
+ */
+ outb(ELINK_ID_PORT, ACTIVATE_ADAPTER_TO_CONFIG);
+ }
+ /* XXX should we sort by ethernet address? */
+ }
- outb(ELINK_ID_PORT, ACTIVATE_ADAPTER_TO_CONFIG);
+ /*
+ * a very specific search order:
+ * exact port & irq
+ * exact port, wildcard irq
+ * wildcard port, exact irq
+ * wildcard port & irq
+ * else fail..
+ */
+ if (ia->ia_iobase != (u_short)-1 || ia->ia_irq != (u_short)-1) {
+ for (i = 0; i<nepcards; i++) {
+ if (epcards[i].available == 0)
+ continue;
+ if (ia->ia_iobase == epcards[i].port &&
+ ia->ia_irq == epcards[i].irq)
+ goto good;
+ }
+ }
+ if (ia->ia_iobase != (u_short)-1 && ia->ia_irq == (u_short)-1) {
+ for (i = 0; i<nepcards; i++) {
+ if (epcards[i].available == 0)
+ continue;
+ if (ia->ia_iobase == epcards[i].port)
+ goto good;
+ }
+ }
+ if (ia->ia_iobase == (u_short)-1 && ia->ia_irq != (u_short)-1) {
+ for (i = 0; i<nepcards; i++) {
+ if (epcards[i].available == 0)
+ continue;
+ if (ia->ia_irq == epcards[i].irq)
+ goto good;
+ }
+ }
+ for (i = 0; i<nepcards; i++)
+ if (epcards[i].available != 0) {
+ goto good;
+ }
+ return 0;
- ia->ia_iosize = 0x10; /* 16 ports of I/O space used. */
+good:
+ epcards[i].available = 0;
+ ia->ia_iobase = epcards[i].port;
+ ia->ia_irq = epcards[i].irq;
+ ia->ia_iosize = 0x10;
ia->ia_msize = 0;
return 1;
}