summaryrefslogtreecommitdiff
path: root/sys/dev/isa
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>1999-12-27 21:51:36 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>1999-12-27 21:51:36 +0000
commitd22c519e835f6ff88c8df7f1ee3837808ed67a4b (patch)
tree32685fa72e7c6b42e4fceadac4bac4e7f18a3dc2 /sys/dev/isa
parent27c6ceea191523e7370c6ecd6a6837d88fe6a13b (diff)
Token ring driver for Tropic based boards; from NetBSD.
This is as is in NetBSD. I've some mods in my tree ready to be merged. For the records: * This driver needs massive work to be ready for production (people is invited to help, don't be shy). Rewrite part/whole is my list. * IP isn't working at the moment. ARP handling needs several changes. (remember this guys? maybe this time...) * This only handle SNAP frames. IPX using IPX frames doesn't work (you could receive but not transmit to be exact). In order to do that, dsap needs to be changed. I don't know how to setup multiple dsap's at the moment (don't worry about it now, our IPX code is going to be replaced soon since the current implementation is buggy). * Source routing is missing. * tcpdump needs some hacking too (in my tree too). * More things I'm probably forgetting now (haven't worked on this for a while). Our networking code needs some cleanup and rearrangement (specially the headers). net/if_ether.h is an example; arp is not ether specific.
Diffstat (limited to 'sys/dev/isa')
-rw-r--r--sys/dev/isa/if_tr_isa.c256
-rw-r--r--sys/dev/isa/if_tribm_isa.c174
-rw-r--r--sys/dev/isa/if_trtcm_isa.c359
3 files changed, 789 insertions, 0 deletions
diff --git a/sys/dev/isa/if_tr_isa.c b/sys/dev/isa/if_tr_isa.c
new file mode 100644
index 00000000000..bfd9bcfe485
--- /dev/null
+++ b/sys/dev/isa/if_tr_isa.c
@@ -0,0 +1,256 @@
+/* $OpenBSD: if_tr_isa.c,v 1.1 1999/12/27 21:51:35 fgsch Exp $ */
+/* $NetBSD: if_tr_isa.c,v 1.4 1999/04/30 15:29:24 bad Exp $ */
+
+#undef TRISADEBUG
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Onno van der Linden.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by The NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <dev/isa/isavar.h>
+
+#include <dev/ic/tropicreg.h>
+#include <dev/ic/tropicvar.h>
+
+
+int tr_isa_probe __P((struct device *, void *, void *));
+int trtcm_isa_probe __P((struct device *, void *, void *));
+int tribm_isa_probe __P((struct device *, void *, void *));
+void tr_isa_attach __P((struct device *, struct device *, void *));
+int tr_isa_map_io __P((struct isa_attach_args *, bus_space_handle_t *,
+ bus_space_handle_t *));
+void tr_isa_unmap_io __P((struct isa_attach_args *, bus_space_handle_t,
+ bus_space_handle_t));
+int trtcm_isa_mediachange __P((struct tr_softc *));
+void trtcm_isa_mediastatus __P((struct tr_softc *, struct ifmediareq *));
+#ifdef TRISADEBUG
+void tr_isa_dumpaip __P((bus_space_tag_t, bus_space_handle_t));
+#endif
+
+/*
+ * List of manufacturer specific probe routines. Order is important.
+ */
+int (*tr_isa_probe_list[])(struct device *, void *, void *) = {
+ trtcm_isa_probe,
+ tribm_isa_probe,
+ 0
+ };
+
+struct cfattach tr_isa_ca = {
+ sizeof(struct tr_softc), tr_isa_probe, tr_isa_attach
+};
+
+int
+tr_isa_map_io(ia, pioh, mmioh)
+struct isa_attach_args *ia;
+bus_space_handle_t *pioh, *mmioh;
+{
+ bus_size_t mmio;
+ u_int8_t s;
+
+ if (bus_space_map(ia->ia_iot, ia->ia_iobase, ia->ia_iosize, 0, pioh)) {
+ printf("tr_isa_map_io: can't map PIO ports\n");
+ return 1;
+ }
+
+ /* Read adapter switches and calculate addresses of MMIO. */
+ s = bus_space_read_1(ia->ia_iot, *pioh, TR_SWITCH);
+
+ if ((s & 0xfc) < ((TR_MMIO_MINADDR - TR_MMIO_OFFSET) >> 11) ||
+ (s & 0xfc) > ((TR_MMIO_MAXADDR - TR_MMIO_OFFSET) >> 11)) {
+ bus_space_unmap(ia->ia_iot, *pioh, ia->ia_iosize);
+ return 1;
+ }
+
+ mmio = ((s & 0xfc) << 11) + TR_MMIO_OFFSET;
+ if (bus_space_map(ia->ia_memt, mmio, TR_MMIO_SIZE, 0, mmioh)) {
+ printf("tr_isa_map_io: can't map MMIO region 0x%05lx/%d\n",
+ mmio, TR_MMIO_SIZE);
+ bus_space_unmap(ia->ia_iot, *pioh, ia->ia_iosize);
+ return 1;
+ }
+ return 0;
+}
+
+void
+tr_isa_unmap_io(ia, pioh, mmioh)
+struct isa_attach_args *ia;
+bus_space_handle_t pioh, mmioh;
+{
+ bus_space_unmap(ia->ia_memt, mmioh, TR_MMIO_SIZE);
+ bus_space_unmap(ia->ia_iot, pioh, ia->ia_iosize);
+}
+
+static u_char tr_isa_id[] = {
+ 5, 0, 4, 9, 4, 3, 4, 15, 3, 6, 3, 1, 3, 1, 3, 0, 3, 9, 3, 9, 3, 0, 2, 0
+};
+
+/*
+ * XXX handle multiple IBM TR cards (sram mapping !!)
+ */
+
+int
+tr_isa_probe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct isa_attach_args *ia = aux;
+ int i;
+ bus_size_t tr_id;
+ bus_space_handle_t sramh, pioh, mmioh;
+ int probecode;
+ int matched = 0;
+
+ for (i = 0; tr_isa_probe_list[i] != 0; i++) {
+ probecode = tr_isa_probe_list[i](parent, match, aux);
+ if (probecode < 0)
+ return 0; /* Fail instantly. */
+ if (probecode > 0)
+ break; /* We have a match. */
+ }
+ if (tr_isa_probe_list[i] == 0)
+ return 0; /* Nothing matched. */
+ if (tr_isa_map_io(ia, &pioh, &mmioh))
+ return 0;
+ tr_id = TR_ID_OFFSET;
+ matched = 1;
+ for (i = 0; i < sizeof(tr_isa_id); i++) {
+ if (bus_space_read_1(ia->ia_memt, mmioh, tr_id) !=
+ tr_isa_id[i])
+ matched = 0;
+ tr_id += 2;
+ }
+#ifdef TRISADEBUG
+ tr_isa_dumpaip(ia->ia_memt, mmioh);
+#endif
+ tr_isa_unmap_io(ia, pioh, mmioh);
+ if (!matched) {
+ return 0;
+ }
+ if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &sramh)) {
+ printf("tr_isa_probe: can't map shared ram\n");
+ return 0;
+ }
+ bus_space_unmap(ia->ia_memt, sramh, ia->ia_msize);
+ return 1;
+}
+
+int trtcm_setspeed(struct tr_softc *, int);
+
+void
+tr_isa_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct tr_softc *sc = (void *) self;
+ struct isa_attach_args *ia = aux;
+
+ sc->sc_piot = ia->ia_iot;
+ sc->sc_memt = ia->ia_memt;
+ if (tr_isa_map_io(ia, &sc->sc_pioh, &sc->sc_mmioh)) {
+ printf("tr_isa_attach: IO space vanished\n");
+ return;
+ }
+ if (bus_space_map(sc->sc_memt, ia->ia_maddr, ia->ia_msize, 0,
+ &sc->sc_sramh)) {
+ printf("tr_isa_attach: shared ram space vanished\n");
+ return;
+ }
+ /* set ACA offset */
+ sc->sc_aca = TR_ACA_OFFSET;
+ sc->sc_memwinsz = ia->ia_msize;
+ sc->sc_maddr = ia->ia_maddr;
+ /*
+ * Determine total RAM on adapter and decide how much to use.
+ * XXX Since we don't use RAM paging, use sc_memwinsz for now.
+ */
+ sc->sc_memsize = sc->sc_memwinsz;
+ sc->sc_memreserved = 0;
+
+ if (tr_reset(sc) != 0)
+ return;
+
+ if (ia->ia_aux != NULL) {
+ sc->sc_mediastatus = trtcm_isa_mediastatus;
+ sc->sc_mediachange = trtcm_isa_mediachange;
+ }
+ else {
+ sc->sc_mediastatus = NULL;
+ sc->sc_mediachange = NULL;
+ }
+
+ if (tr_attach(sc) != 0)
+ return;
+
+/*
+ * XXX 3Com 619 can use LEVEL intr
+ */
+ sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
+ IPL_NET, tr_intr, sc, sc->sc_dev.dv_xname);
+}
+
+#ifdef TRISADEBUG
+/*
+ * Dump the adapters AIP
+ */
+void
+tr_isa_dumpaip(memt, mmioh)
+ bus_space_tag_t memt;
+ bus_space_handle_t mmioh;
+{
+ unsigned int off, val;
+ printf("AIP contents:");
+ for (off=0; off < 256; off++) {
+ val = bus_space_read_1(memt, mmioh, TR_MAC_OFFSET + off);
+ if ((off % 16) == 0)
+ printf("\n");
+ printf("%02x ", val);
+ }
+ printf("\n");
+}
+#endif
diff --git a/sys/dev/isa/if_tribm_isa.c b/sys/dev/isa/if_tribm_isa.c
new file mode 100644
index 00000000000..69f92b688f9
--- /dev/null
+++ b/sys/dev/isa/if_tribm_isa.c
@@ -0,0 +1,174 @@
+/* $OpenBSD: if_tribm_isa.c,v 1.1 1999/12/27 21:51:35 fgsch Exp $ */
+/* $NetBSD: if_tribm_isa.c,v 1.2 1999/03/22 23:01:37 bad Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Onno van der Linden.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by The NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+
+#include <dev/ic/tropicreg.h>
+#include <dev/ic/tropicvar.h>
+
+int tribm_isa_probe __P((struct device *, void *, void *));
+int tr_isa_map_io __P((struct isa_attach_args *, bus_space_handle_t *,
+ bus_space_handle_t *));
+void tr_isa_unmap_io __P((struct isa_attach_args *, bus_space_handle_t,
+ bus_space_handle_t));
+
+int
+tribm_isa_probe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct isa_attach_args *ia = aux;
+ static int irq_f[4] = { 9, 3, 6, 7 };
+ static int irq_e[4] = { 9, 3, 10, 11 };
+ bus_space_tag_t piot = ia->ia_iot;
+ bus_space_tag_t memt = ia->ia_memt;
+ bus_space_handle_t pioh, mmioh;
+ int i, irq;
+ u_int8_t s;
+
+#ifdef notyet
+/* XXX Try both 0xa20 and 0xa24 and store that info like 3com */
+ if (ia->ia_iobase == IOBASEUNK)
+ ia->ia_iobase = 0xa20;
+#else
+ if (ia->ia_iobase == IOBASEUNK)
+ return 0;
+#endif
+
+ ia->ia_iosize = 4;
+ ia->ia_aux = NULL;
+
+ if (tr_isa_map_io(ia, &pioh, &mmioh))
+ return 0;
+
+/*
+ * F = Token-Ring Network PC Adapter
+ * Token-Ring Network PC Adapter II
+ * Token-Ring Network Adapter/A
+ * E = Token-Ring Network 16/4 Adapter/A (long card)
+ * Token-Ring Network 16/4 Adapter
+ * D = Token-Ring Network 16/4 Adapter/A (short card)
+ * 16/4 ISA-16 Adapter
+ * C = Auto 16/4 Token-Ring ISA Adapter
+ * Auto 16/4 Token-Ring MC Adapter
+ */
+/*
+ * XXX Both 0xD and 0xC types should be able to use 16-bit read and writes
+ */
+ switch (bus_space_read_1(memt, mmioh, TR_TYP_OFFSET)) {
+ case 0xF:
+ case 0xE:
+ case 0xD:
+ if (ia->ia_maddr == MADDRUNK)
+#ifdef notyet
+ ia->ia_maddr = TR_SRAM_DEFAULT;
+#else
+ return 0;
+#endif
+ break;
+ case 0xC:
+ i = bus_space_read_1(memt, mmioh, TR_ACA_OFFSET) << 12;
+ if (ia->ia_maddr == MADDRUNK)
+ ia->ia_maddr = i;
+ else if (ia->ia_maddr != i) {
+ printf(
+"tribm_isa_probe: sram mismatch; kernel configured %x != board configured %x\n",
+ ia->ia_maddr, i);
+ tr_isa_unmap_io(ia, pioh, mmioh);
+ return 0;
+ }
+ break;
+ default:
+ printf("tribm_isa_probe: unknown type code %x\n",
+ bus_space_read_1(memt, mmioh, TR_TYP_OFFSET));
+ tr_isa_unmap_io(ia, pioh, mmioh);
+ return 0;
+ }
+
+ s = bus_space_read_1(piot, pioh, TR_SWITCH);
+
+ switch (bus_space_read_1(memt, mmioh, TR_IRQ_OFFSET)) {
+ case 0xF:
+ irq = irq_f[s & 3];
+ break;
+ case 0xE:
+ irq = irq_e[s & 3];
+ break;
+ default:
+ printf("tribm_isa_probe: Unknown IRQ code %x\n",
+ bus_space_read_1(memt, mmioh, TR_IRQ_OFFSET));
+ tr_isa_unmap_io(ia, pioh, mmioh);
+ return 0;
+ }
+
+ if (ia->ia_irq == IRQUNK)
+ ia->ia_irq = irq;
+ else if (ia->ia_irq != irq) {
+ printf(
+"tribm_isa_probe: irq mismatch; kernel configured %d != board configured %d\n",
+ ia->ia_irq, irq);
+ tr_isa_unmap_io(ia, pioh, mmioh);
+ return 0;
+ }
+/*
+ * XXX 0x0c == MSIZEMASK (MSIZEBITS)
+ */
+ ia->ia_msize = 8192 <<
+ ((bus_space_read_1(memt, mmioh, TR_ACA_OFFSET + 1) & 0x0c) >> 2);
+ tr_isa_unmap_io(ia, pioh, mmioh);
+ /* Check alignment of membase. */
+ if ((ia->ia_maddr & (ia->ia_msize-1)) != 0) {
+ printf("tribm_isa_probe: SRAM unaligned 0x%04x/%d\n",
+ ia->ia_maddr, ia->ia_msize);
+ return 0;
+ }
+ return 1;
+}
diff --git a/sys/dev/isa/if_trtcm_isa.c b/sys/dev/isa/if_trtcm_isa.c
new file mode 100644
index 00000000000..3fb6063b675
--- /dev/null
+++ b/sys/dev/isa/if_trtcm_isa.c
@@ -0,0 +1,359 @@
+/* $OpenBSD: if_trtcm_isa.c,v 1.1 1999/12/27 21:51:35 fgsch Exp $ */
+/* $NetBSD: if_trtcm_isa.c,v 1.3 1999/04/30 15:29:24 bad Exp $ */
+
+#undef TRTCMISADEBUG
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Onno van der Linden.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by The NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <machine/bus.h>
+
+#include <dev/isa/isavar.h>
+#include <dev/isa/elink.h>
+
+#include <dev/ic/tropicreg.h>
+#include <dev/ic/tropicvar.h>
+
+#include <dev/ic/elink3reg.h>
+
+u_int16_t tcmreadeeprom __P((bus_space_tag_t, bus_space_handle_t, int));
+#ifdef TRTCMISADEBUG
+void tcmdumpeeprom __P((bus_space_tag_t, bus_space_handle_t));
+#endif
+
+int trtcm_isa_probe __P((struct device *, void *, void *));
+
+int trtcm_isa_mediachange __P((struct tr_softc *));
+void trtcm_isa_mediastatus __P((struct tr_softc *, struct ifmediareq *));
+
+/*
+ * TODO:
+ *
+ * if_media handling in the 3com case
+ * mediachange() and mediastatus() function
+ * certain newer cards can set their speed on the fly via
+ * DIR_SET_DEFAULT_RING_SPEED or set the speed in the eeprom ??
+ */
+
+static void tcmaddcard __P((int, int, int, int, u_int, int, int));
+
+/*
+ * This keeps track of which ISAs have been through a 3com probe sequence.
+ * A simple static variable isn't enough, since it's conceivable that
+ * a system might have more than one ISA bus.
+ *
+ * The "tcm_bus" member is the unit number of the parent ISA bus, e.g. "0"
+ * for "isa0".
+ */
+struct tcm_isa_done_probe {
+ LIST_ENTRY(tcm_isa_done_probe) tcm_link;
+ int tcm_bus;
+};
+static LIST_HEAD(, tcm_isa_done_probe) tcm_isa_all_probes;
+static int tcm_isa_probes_initialized;
+
+#define MAXTCMCARDS 20 /* if you have more than 20, you lose */
+
+static struct tcmcard {
+ int bus;
+ int iobase;
+ int irq;
+ int maddr;
+ u_int msize;
+ long model;
+ char available;
+ char pnpmode;
+} tcmcards[MAXTCMCARDS];
+
+static int ntcmcards = 0;
+
+static void
+tcmaddcard(bus, iobase, irq, maddr, msize, model, pnpmode)
+ int bus, iobase, irq, maddr;
+ u_int msize;
+ int model, pnpmode;
+{
+
+ if (ntcmcards >= MAXTCMCARDS)
+ return;
+ tcmcards[ntcmcards].bus = bus;
+ tcmcards[ntcmcards].iobase = iobase;
+ tcmcards[ntcmcards].irq = irq;
+ tcmcards[ntcmcards].maddr = maddr;
+ tcmcards[ntcmcards].msize = msize;
+ tcmcards[ntcmcards].model = model;
+ tcmcards[ntcmcards].available = 1;
+ tcmcards[ntcmcards].pnpmode = pnpmode;
+ ntcmcards++;
+}
+
+/*
+ * We get eeprom data from the id_port given an offset into the
+ * eeprom. Basically; after the ID_sequence is sent to all of
+ * the cards; they enter the ID_CMD state where they will accept
+ * command requests. 0x80-0xbf loads the eeprom data. We then
+ * read the port 16 times and with every read; the cards check
+ * for contention (ie: if one card writes a 0 bit and another
+ * writes a 1 bit then the host sees a 0. At the end of the cycle;
+ * each card compares the data on the bus; if there is a difference
+ * then that card goes into ID_WAIT state again). In the meantime;
+ * one bit of data is returned in the AX register which is conveniently
+ * returned to us by bus_space_read_1(). Hence; we read 16 times getting one
+ * bit of data with each read.
+ *
+ * NOTE: the caller must provide an i/o handle for ELINK_ID_PORT!
+ */
+u_int16_t
+tcmreadeeprom(iot, ioh, offset)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ int offset;
+{
+ u_int16_t data = 0;
+ int i;
+
+ bus_space_write_1(iot, ioh, 0, 0x80 + offset);
+ delay(1000);
+ for (i = 0; i < 16; i++)
+ data = (data << 1) | (bus_space_read_2(iot, ioh, 0) & 1);
+ return (data);
+}
+
+#ifdef TRTCMISADEBUG
+/*
+ * Dump the contents of the EEPROM to the console.
+ */
+void
+tcmdumpeeprom(iot, ioh)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+{
+ unsigned int off, val;
+
+ printf("EEPROM contents:");
+ for (off=0; off < 32; off++) {
+ val = tcmreadeeprom(iot, ioh, off);
+ if ((off % 8) == 0)
+ printf("\n");
+ printf("%04x ", val);
+ }
+ printf("\n");
+}
+#endif
+
+int
+trtcm_isa_mediachange(sc)
+ struct tr_softc *sc;
+{
+ return EINVAL;
+}
+
+void
+trtcm_isa_mediastatus(sc, ifmr)
+ struct tr_softc *sc;
+ struct ifmediareq *ifmr;
+{
+ struct ifmedia *ifm = &sc->sc_media;
+
+ ifmr->ifm_active = ifm->ifm_cur->ifm_media;
+}
+
+/* XXX hard coded constants in readeeprom elink_idseq */
+
+int
+trtcm_isa_probe(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
+{
+ struct isa_attach_args *ia = aux;
+ int bus = parent->dv_unit;
+ bus_space_tag_t iot = ia->ia_iot;
+ bus_space_handle_t ioh;
+ u_int msize;
+ int slot, iobase, irq, i, maddr, rsrccfg, pnpmode;
+ u_int16_t vendor, model;
+ struct tcm_isa_done_probe *tcm;
+ static int irqs[] = { 7, 15, 6, 11, 3, 10, 9, 5 };
+
+ if (tcm_isa_probes_initialized == 0) {
+ LIST_INIT(&tcm_isa_all_probes);
+ tcm_isa_probes_initialized = 1;
+ }
+
+ /*
+ * Probe this bus if we haven't done so already.
+ */
+ for (tcm = tcm_isa_all_probes.lh_first; tcm != NULL;
+ tcm = tcm->tcm_link.le_next)
+ if (tcm->tcm_bus == bus)
+ goto bus_probed;
+
+ /*
+ * Mark this bus so we don't probe it again.
+ */
+ tcm = (struct tcm_isa_done_probe *)
+ malloc(sizeof(struct tcm_isa_done_probe), M_DEVBUF, M_NOWAIT);
+ if (tcm == NULL) {
+ printf("trtcm_isa_probe: can't allocate state storage");
+ return 0;
+ }
+
+ tcm->tcm_bus = bus;
+ LIST_INSERT_HEAD(&tcm_isa_all_probes, tcm, tcm_link);
+
+ /*
+ * Map the TokenLink ID port for the probe sequence.
+ */
+ if (bus_space_map(iot, ELINK_ID_PORT, 1, 0, &ioh)) {
+ printf("trtcm_isa_probe: can't map TokenLink ID port\n");
+ return 0;
+ }
+
+ for (slot = 0; slot < MAXTCMCARDS; slot++) {
+ pnpmode = 0;
+ elink_reset(iot, ioh, bus);
+ elink_idseq(iot, ioh, TLINK_619_POLY);
+
+ /* Untag all the adapters so they will talk to us. */
+ if (slot == 0)
+ bus_space_write_1(iot, ioh, 0, TAG_ADAPTER + 0);
+
+ vendor = htons(tcmreadeeprom(iot, ioh, EEPROM_MFG_ID));
+ if (vendor != MFG_ID)
+ continue;
+
+ model = htons(tcmreadeeprom(iot, ioh, EEPROM_PROD_ID));
+ if (((model & 0xfff0) != 0x6190) &&
+ ((model & 0xfff0) != 0x3190)) { /* XXX hardcoded */
+#if 0
+ printf("trtcm: unknown model 0x%04x\n", model);
+#endif
+ continue;
+ }
+#ifdef TRTCMISADEBUG
+ tcmdumpeeprom(iot, ioh);
+
+ printf("speed: %d\n", (tcmreadeeprom(iot,ioh,8) & 2) ? 4 : 16);
+#endif
+
+ rsrccfg = iobase = tcmreadeeprom(iot, ioh, EEPROM_RESOURCE_CFG);
+ if (iobase & 0x20)
+ iobase = tcmreadeeprom(iot, ioh, EEPROM_ADDR_CFG) & 1 ?
+ 0xa20 : 0xa24;
+ else
+ iobase = (iobase & 0x1f) * 0x10 + 0x200;
+
+ maddr = ((tcmreadeeprom(iot, ioh, EEPROM_OEM_ADDR0) & 0xfc00)
+ << 3) + 0x80000;
+ msize = 65536 >> ((tcmreadeeprom(iot, ioh, 8) & 0x0c) >> 2);
+
+ irq = tcmreadeeprom(iot, ioh, EEPROM_ADDR_CFG) & 0x180;
+ irq |= (tcmreadeeprom(iot, ioh, EEPROM_RESOURCE_CFG) & 0x40);
+ irq = irqs[irq >> 6];
+
+ /* Tag card so it will not respond to contention again. */
+ bus_space_write_1(iot, ioh, 0, TAG_ADAPTER + 1);
+
+ /*
+ * Don't attach a 3c319 in PnP mode.
+ *
+ * XXX Testing for the 13th bit in iobase being 0 might not
+ * be the right thing to do, but the EEPROM of the 3C319 is
+ * undocumented according to 3COM and this is one of the
+ * three bits that changed when I put the card in PnP mode. -chb
+ */
+ if (((model & 0xffff0) == 0x3190) &&
+ ((rsrccfg & 0x1000) == 0)) {
+ printf("3COM 3C319 TokenLink Velocity in PnP mode\n");
+ pnpmode = 1;
+ }
+ else {
+ /*
+ * 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?
+ */
+ bus_space_write_1(iot, ioh, 0,
+ ACTIVATE_ADAPTER_TO_CONFIG);
+ }
+ tcmaddcard(bus, iobase, irq, maddr, msize, model, pnpmode);
+ }
+ bus_space_unmap(iot, ioh, 1);
+
+bus_probed:
+
+ for (i = 0; i < ntcmcards; i++) {
+ if (tcmcards[i].bus != bus)
+ continue;
+ if (tcmcards[i].available == 0)
+ continue;
+ if (ia->ia_iobase != IOBASEUNK &&
+ ia->ia_iobase != tcmcards[i].iobase)
+ continue;
+ if (ia->ia_irq != IRQUNK &&
+ ia->ia_irq != tcmcards[i].irq)
+ continue;
+ goto good;
+ }
+ return 0;
+
+good:
+ tcmcards[i].available = 0;
+ if (tcmcards[i].pnpmode)
+ return -1; /* XXX Don't actually probe this card. */
+ ia->ia_iobase = tcmcards[i].iobase;
+ ia->ia_irq = tcmcards[i].irq;
+ /* XXX probably right, but ...... */
+ if (ia->ia_iobase == 0xa20 || ia->ia_iobase == 0x0a24)
+ ia->ia_iosize = 4;
+ else
+ ia->ia_iosize = 16;
+ ia->ia_maddr = tcmcards[i].maddr;
+ ia->ia_msize = tcmcards[i].msize;
+ ia->ia_aux = (void *) tcmcards[i].model;
+ return 1;
+}