if_lc_isa.c revision 1.1
1/*	$NetBSD: if_lc_isa.c,v 1.1 1997/07/31 21:58:19 matt Exp $ */
2
3/*-
4 * Copyright (c) 1994, 1995, 1997 Matt Thomas <matt@3am-software.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. The name of the author may not be used to endorse or promote products
13 *    derived from this software withough specific prior written permission
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27/*
28 * DEC EtherWORKS 3 Ethernet Controllers
29 *
30 * Written by Matt Thomas
31 *
32 *   This driver supports the LEMAC (DE203, DE204, and DE205) cards.
33 */
34
35#include "bpfilter.h"
36
37#include <sys/param.h>
38#include <sys/systm.h>
39#include <sys/mbuf.h>
40#include <sys/socket.h>
41#include <sys/ioctl.h>
42#include <sys/errno.h>
43#include <sys/syslog.h>
44#include <sys/select.h>
45#include <sys/device.h>
46#include <sys/queue.h>
47
48#include <net/if.h>
49#include <net/if_dl.h>
50#include <net/if_ether.h>
51#include <net/if_media.h>
52
53
54#ifdef INET
55#include <netinet/in.h>
56#include <netinet/in_systm.h>
57#include <netinet/in_var.h>
58#include <netinet/ip.h>
59#include <netinet/if_inarp.h>
60#endif
61
62#ifdef NS
63#include <netns/ns.h>
64#include <netns/ns_if.h>
65#endif
66
67#if NBPFILTER > 0
68#include <net/bpf.h>
69#include <net/bpfdesc.h>
70#endif
71
72#include <machine/cpu.h>
73#include <machine/bus.h>
74#include <machine/intr.h>
75
76#include <dev/ic/lemacreg.h>
77#include <dev/ic/lemacvar.h>
78
79#include <dev/isa/isavar.h>
80
81/*
82 * This keeps track of which ISAs have been through a lc probe sequence.
83 * A simple static variable isn't enough, since it's conceivable that
84 * a system might have more than one ISA bus.
85 *
86 * The "isa_bus" member is a pointer to the parent ISA bus device struct
87 * which will unique per ISA bus.
88 */
89
90#define MAXCARDS_PER_ISABUS	4	/* if you have more than 4, you lose */
91#define	MAXSLOTS_PER_BUS	16	/* 0x200-0x3FF in 0x20 incr. */
92
93struct lemac_isabus {
94    LIST_ENTRY(lemac_isabus) isa_link;
95    struct device *isa_bus;
96    struct lemac_card {
97	bus_addr_t iobase;
98	bus_addr_t maddr;
99	bus_size_t msize;
100	int irq;
101	int available;
102    } isa_cards[MAXCARDS_PER_ISABUS];
103};
104
105static LIST_HEAD(, lemac_isabus) lemac_isa_buses;
106static int lemac_isa_buses_inited;
107
108static void
109lemac_isa_card_add(
110    struct lemac_isabus *bus,
111    bus_addr_t iobase,
112    bus_addr_t maddr,
113    bus_size_t msize,
114    int irq)
115{
116    int idx;
117
118    for (idx = 0; idx < MAXCARDS_PER_ISABUS; idx++) {
119	if (bus->isa_cards[idx].available == 0) {
120	    bus->isa_cards[idx].iobase = iobase;
121	    bus->isa_cards[idx].maddr = maddr;
122	    bus->isa_cards[idx].msize = msize;
123	    bus->isa_cards[idx].irq = irq;
124	    bus->isa_cards[idx].available = 1;
125	    break;
126	}
127    }
128}
129
130/*
131 * We'd like like to allow the irq, maddr, and iobase addresses to be
132 * wildcarded. So, we probe all the cards the first time lemac_isa_probe()
133 * is called. On subsequent calls we look for matching cards.
134 */
135static int
136lemac_isa_probe(
137    struct device *parent,
138#ifdef __BROKEN_INDIRECT_CONFIG
139    void *match,
140#else
141    struct cfdata *match,
142#endif
143    void *aux)
144{
145    struct isa_attach_args * const ia = aux;
146    struct lemac_isabus *bus;
147    int idx;
148
149    if (lemac_isa_buses_inited == 0) {
150	LIST_INIT(&lemac_isa_buses);
151	lemac_isa_buses_inited = 1;
152    }
153
154    /*
155     * Probe this bus if we haven't done so already.
156     */
157    for (bus = lemac_isa_buses.lh_first; bus != NULL;
158					 bus = bus->isa_link.le_next) {
159	if (bus->isa_bus == parent)
160	    break;
161    }
162
163    if (bus == NULL) {
164	bus_addr_t iobase;
165	/*
166	 * Mark this bus so we don't probe it again.
167	 */
168	bus = (struct lemac_isabus *)
169	    malloc(sizeof(struct lemac_isabus), M_DEVBUF, M_NOWAIT);
170	if (bus == NULL)
171	    panic("lemac_isa_probe: can't allocate state storage for %s",
172		  parent->dv_xname);
173
174	bus->isa_bus = parent;
175	LIST_INSERT_HEAD(&lemac_isa_buses, bus, isa_link);
176
177	for (iobase = LEMAC_IOBASE_LOW; iobase < LEMAC_IOBASE_HIGH;
178					iobase += LEMAC_IOSIZE) {
179	    bus_space_handle_t ioh;
180	    /*
181	     * Map the LEMACs port-space for the probe sequence.
182	     */
183	    if (bus_space_map(ia->ia_iot, iobase, LEMAC_IOSIZE, 0, &ioh))
184		continue;
185
186	    /*
187	     * Read the Ethernet address from the EEPROM.
188	     * It must start with on the DEC OUIs and pass the
189	     * DEC ethernet checksum test.
190	     */
191
192	    if (lemac_port_check(ia->ia_iot, ioh)) {
193		int irq;
194		bus_addr_t maddr;
195		bus_addr_t msize;
196		bus_space_handle_t memh;
197
198		lemac_info_get(ia->ia_iot, ioh, &maddr, &msize, &irq);
199		if (!bus_space_map(ia->ia_memt, maddr, msize, 0, &memh)) {
200		    lemac_isa_card_add(bus, iobase, maddr, msize, irq);
201		    bus_space_unmap(ia->ia_memt, memh, msize);
202		}
203	    }
204
205	    bus_space_unmap(ia->ia_iot, ioh, LEMAC_IOSIZE);
206	}
207    }
208
209    for (idx = 0; idx < MAXCARDS_PER_ISABUS; idx++) {
210	if (bus->isa_cards[idx].available != 1)
211	    continue;
212	if (ia->ia_iobase != IOBASEUNK
213	        && ia->ia_iobase != bus->isa_cards[idx].iobase)
214	    continue;
215	if (ia->ia_maddr != MADDRUNK
216	        && ia->ia_maddr != bus->isa_cards[idx].maddr)
217	    continue;
218	if (ia->ia_irq != IRQUNK && ia->ia_irq != bus->isa_cards[idx].irq)
219	    continue;
220	break;
221    }
222    if (idx == MAXCARDS_PER_ISABUS)
223	return 0;
224
225    bus->isa_cards[idx].available++;
226    ia->ia_iobase = bus->isa_cards[idx].iobase;
227    ia->ia_irq    = bus->isa_cards[idx].irq;
228    ia->ia_iosize = LEMAC_IOSIZE;
229    ia->ia_maddr  = bus->isa_cards[idx].maddr;
230    ia->ia_msize  = bus->isa_cards[idx].msize;
231    return 1;
232}
233
234static void
235lemac_isa_attach(
236    struct device *parent,
237    struct device *self,
238    void *aux)
239{
240    lemac_softc_t *sc = (void *)self;
241    struct isa_attach_args *ia = aux;
242
243
244    /* Map i/o space. */
245    sc->sc_iot = ia->ia_iot;
246    if (bus_space_map(sc->sc_iot, ia->ia_iobase, ia->ia_iosize, 0, &sc->sc_ioh))
247	panic("\n%s: can't map i/o space 0x%x-0x%x\n",
248	      sc->sc_dv.dv_xname,
249	      ia->ia_iobase, ia->ia_iobase + ia->ia_iosize - 1);
250
251    if (ia->ia_msize && ia->ia_maddr) {
252	sc->sc_memt = ia->ia_memt;
253	/* Map memory space. */
254	if (bus_space_map(sc->sc_memt, ia->ia_maddr, ia->ia_msize, 0, &sc->sc_memh))
255	    panic("\n%s: can't map iomem space 0x%x-0x%x\n",
256		  sc->sc_dv.dv_xname,
257		  ia->ia_maddr, ia->ia_maddr + ia->ia_msize - 1);
258    }
259
260    sc->sc_ats = shutdownhook_establish(lemac_shutdown, sc);
261    if (sc->sc_ats == NULL)
262	printf("\n%s: warning: couldn't establish shutdown hook\n",
263	       sc->sc_dv.dv_xname);
264
265    lemac_ifattach(sc);
266
267    sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
268				   IPL_NET, lemac_intr, sc);
269}
270
271struct cfattach lc_isa_ca = {
272    sizeof(lemac_softc_t), lemac_isa_probe, lemac_isa_attach
273};
274