diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 1999-12-27 21:51:36 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 1999-12-27 21:51:36 +0000 |
commit | d22c519e835f6ff88c8df7f1ee3837808ed67a4b (patch) | |
tree | 32685fa72e7c6b42e4fceadac4bac4e7f18a3dc2 /sys/dev/isa | |
parent | 27c6ceea191523e7370c6ecd6a6837d88fe6a13b (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.c | 256 | ||||
-rw-r--r-- | sys/dev/isa/if_tribm_isa.c | 174 | ||||
-rw-r--r-- | sys/dev/isa/if_trtcm_isa.c | 359 |
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; +} |