xref: /openbsd/sys/dev/isa/if_le_isa.c (revision 471aeecf)
1 /*	$OpenBSD: if_le_isa.c,v 1.23 2022/04/06 18:59:28 naddy Exp $	*/
2 /*	$NetBSD: if_le_isa.c,v 1.2 1996/05/12 23:52:56 mycroft Exp $	*/
3 
4 /*-
5  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
6  * Copyright (c) 1992, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Ralph Campbell and Rick Macklem.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *	@(#)if_le.c	8.2 (Berkeley) 11/16/93
37  */
38 
39 #include "bpfilter.h"
40 #include "isadma.h"
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/mbuf.h>
45 #include <sys/syslog.h>
46 #include <sys/socket.h>
47 #include <sys/device.h>
48 
49 #include <net/if.h>
50 #include <net/if_media.h>
51 
52 #include <netinet/in.h>
53 #include <netinet/if_ether.h>
54 
55 #include <machine/cpu.h>
56 #include <machine/intr.h>
57 
58 #include <dev/isa/isareg.h>
59 #include <dev/isa/isavar.h>
60 #include <dev/isa/isadmavar.h>
61 
62 #include <dev/ic/lancereg.h>
63 #include <dev/ic/lancevar.h>
64 #include <dev/ic/am7990reg.h>
65 #include <dev/ic/am7990var.h>
66 
67 #include <dev/isa/if_levar.h>
68 
69 static char *card_type[] =
70     { "unknown", "BICC Isolan", "NE2100", "DEPCA", "PCnet-ISA" };
71 
72 int	le_isa_probe(struct device *, void *, void *);
73 void	le_isa_attach(struct device *, struct device *, void *);
74 
75 const struct cfattach le_isa_ca = {
76 	sizeof(struct le_softc), le_isa_probe, le_isa_attach
77 };
78 
79 int	depca_isa_probe(struct le_softc *, struct isa_attach_args *);
80 int	ne2100_isa_probe(struct le_softc *, struct isa_attach_args *);
81 int	bicc_isa_probe(struct le_softc *, struct isa_attach_args *);
82 int	lance_isa_probe(struct lance_softc *);
83 
84 int
le_isa_probe(struct device * parent,void * match,void * aux)85 le_isa_probe(struct device *parent, void *match, void *aux)
86 {
87 	struct le_softc *lesc = match;
88 	struct isa_attach_args *ia = aux;
89 	u_int8_t bogusether[ETHER_ADDR_LEN] = { 255, 255, 255, 255, 255, 255 };
90 
91 #if NISADMA == 0
92 	if (ia->ia_drq != DRQUNK) {
93 		printf("cannot support dma lance devices\n");
94 		return 0;
95 	}
96 #endif
97 
98 	if (bicc_isa_probe(lesc, ia) == 0 && ne2100_isa_probe(lesc, ia) == 0 &&
99 	    depca_isa_probe(lesc, ia) == 0)
100 		return (0);
101 
102 	if (bcmp(lesc->sc_am7990.lsc.sc_arpcom.ac_enaddr, bogusether,
103 	    sizeof(bogusether)) == 0)
104 		return (0);
105 
106 	return (1);
107 }
108 
109 int
depca_isa_probe(struct le_softc * lesc,struct isa_attach_args * ia)110 depca_isa_probe(struct le_softc *lesc, struct isa_attach_args *ia)
111 {
112 	struct lance_softc *sc = &lesc->sc_am7990.lsc;
113 	bus_space_tag_t iot = lesc->sc_iot;
114 	bus_space_handle_t ioh = lesc->sc_ioh;
115 	int iosize = 16;
116 	int port;
117 
118 #if 0
119 	u_long sum, rom_sum;
120 	u_char x;
121 #endif
122 	int i;
123 
124 	if (bus_space_map(iot, ia->ia_iobase, iosize, 0, &ioh))
125 		return (0);
126 	lesc->sc_iot = iot;
127 	lesc->sc_ioh = ioh;
128 	lesc->sc_rap = DEPCA_RAP;
129 	lesc->sc_rdp = DEPCA_RDP;
130 	lesc->sc_card = DEPCA;
131 
132 	if (lance_isa_probe(sc) == 0) {
133 		bus_space_unmap(iot, ioh, iosize);
134 		return 0;
135 	}
136 
137 	bus_space_write_1(iot, ioh, DEPCA_CSR, DEPCA_CSR_DUM);
138 
139 	/*
140 	 * Extract the physical MAC address from the ROM.
141 	 *
142 	 * The address PROM is 32 bytes wide, and we access it through
143 	 * a single I/O port.  On each read, it rotates to the next
144 	 * position.  We find the ethernet address by looking for a
145 	 * particular sequence of bytes (0xff, 0x00, 0x55, 0xaa, 0xff,
146 	 * 0x00, 0x55, 0xaa), and then reading the next 8 bytes (the
147 	 * ethernet address and a checksum).
148 	 *
149 	 * It appears that the PROM can be at one of two locations, so
150 	 * we just try both.
151 	 */
152 	port = DEPCA_ADP;
153 	for (i = 0; i < 32; i++)
154 		if (bus_space_read_1(iot, ioh, port) == 0xff &&
155 		    bus_space_read_1(iot, ioh, port) == 0x00 &&
156 		    bus_space_read_1(iot, ioh, port) == 0x55 &&
157 		    bus_space_read_1(iot, ioh, port) == 0xaa &&
158 		    bus_space_read_1(iot, ioh, port) == 0xff &&
159 		    bus_space_read_1(iot, ioh, port) == 0x00 &&
160 		    bus_space_read_1(iot, ioh, port) == 0x55 &&
161 		    bus_space_read_1(iot, ioh, port) == 0xaa)
162 			goto found;
163 	port = DEPCA_ADP + 1;
164 	for (i = 0; i < 32; i++)
165 		if (bus_space_read_1(iot, ioh, port) == 0xff &&
166 		    bus_space_read_1(iot, ioh, port) == 0x00 &&
167 		    bus_space_read_1(iot, ioh, port) == 0x55 &&
168 		    bus_space_read_1(iot, ioh, port) == 0xaa &&
169 		    bus_space_read_1(iot, ioh, port) == 0xff &&
170 		    bus_space_read_1(iot, ioh, port) == 0x00 &&
171 		    bus_space_read_1(iot, ioh, port) == 0x55 &&
172 		    bus_space_read_1(iot, ioh, port) == 0xaa)
173 			goto found;
174 	printf("%s: address not found\n", sc->sc_dev.dv_xname);
175 	return 0;
176 
177 found:
178 	for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
179 		sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(iot, ioh, port);
180 
181 #if 0
182 	sum =
183 	    (sc->sc_arpcom.ac_enaddr[0] <<  2) +
184 	    (sc->sc_arpcom.ac_enaddr[1] << 10) +
185 	    (sc->sc_arpcom.ac_enaddr[2] <<  1) +
186 	    (sc->sc_arpcom.ac_enaddr[3] <<  9) +
187 	    (sc->sc_arpcom.ac_enaddr[4] <<  0) +
188 	    (sc->sc_arpcom.ac_enaddr[5] <<  8);
189 	sum = (sum & 0xffff) + (sum >> 16);
190 	sum = (sum & 0xffff) + (sum >> 16);
191 
192 	rom_sum = bus_space_read_1(iot, ioh, port);
193 	rom_sum |= bus_space_read_1(iot, ioh, port << 8);
194 
195 	if (sum != rom_sum) {
196 		printf("%s: checksum mismatch; calculated %04x != read %04x",
197 		    sc->sc_dev.dv_xname, sum, rom_sum);
198 		bus_space_unmap(iot, ioh, iosize);
199 		return 0;
200 	}
201 #endif
202 
203 	bus_space_write_1(iot, ioh, DEPCA_CSR, DEPCA_CSR_NORMAL);
204 
205 	ia->ia_iosize = iosize;
206 	ia->ia_drq = DRQUNK;
207 	bus_space_unmap(iot, ioh, ia->ia_iosize);
208 	return 1;
209 }
210 
211 int
ne2100_isa_probe(struct le_softc * lesc,struct isa_attach_args * ia)212 ne2100_isa_probe(struct le_softc *lesc, struct isa_attach_args *ia)
213 {
214 	struct lance_softc *sc = &lesc->sc_am7990.lsc;
215 	bus_space_tag_t iot = lesc->sc_iot;
216 	bus_space_handle_t ioh = lesc->sc_ioh;
217 	int iosize = 24;
218 	int i;
219 
220 	if (bus_space_map(iot, ia->ia_iobase, iosize, 0, &ioh))
221 		return (0);
222 	lesc->sc_iot = iot;
223 	lesc->sc_ioh = ioh;
224 	lesc->sc_rap = NE2100_RAP;
225 	lesc->sc_rdp = NE2100_RDP;
226 	lesc->sc_card = NE2100;
227 
228 	if (lance_isa_probe(sc) == 0) {
229 		bus_space_unmap(iot, ioh, iosize);
230 		return 0;
231 	}
232 
233 	/*
234 	 * Extract the physical MAC address from the ROM.
235 	 */
236 	for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
237 		sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(iot, ioh, i);
238 
239 	ia->ia_iosize = iosize;
240 	bus_space_unmap(iot, ioh, ia->ia_iosize);
241 	return 1;
242 }
243 
244 int
bicc_isa_probe(struct le_softc * lesc,struct isa_attach_args * ia)245 bicc_isa_probe(struct le_softc *lesc, struct isa_attach_args *ia)
246 {
247 	struct lance_softc *sc = &lesc->sc_am7990.lsc;
248 	bus_space_handle_t ioh;
249 	bus_space_tag_t iot = ia->ia_iot;
250 	int iosize = 16;
251 	int i;
252 
253 	if (bus_space_map(iot, ia->ia_iobase, iosize, 0, &ioh))
254 		return (0);
255 	lesc->sc_iot = iot;
256 	lesc->sc_ioh = ioh;
257 	lesc->sc_rap = BICC_RAP;
258 	lesc->sc_rdp = BICC_RDP;
259 	lesc->sc_card = BICC;
260 
261 	if (lance_isa_probe(sc) == 0) {
262 		bus_space_unmap(iot, ioh, iosize);
263 		return 0;
264 	}
265 
266 	/*
267 	 * Extract the physical MAC address from the ROM.
268 	 */
269 	for (i = 0; i < sizeof(sc->sc_arpcom.ac_enaddr); i++)
270 		sc->sc_arpcom.ac_enaddr[i] = bus_space_read_1(iot, ioh, i * 2);
271 
272 	ia->ia_iosize = iosize;
273 	bus_space_unmap(iot, ioh, ia->ia_iosize);
274 	return 1;
275 }
276 
277 /*
278  * Determine which chip is present on the card.
279  */
280 int
lance_isa_probe(struct lance_softc * sc)281 lance_isa_probe(struct lance_softc *sc)
282 {
283 
284 	/* Stop the LANCE chip and put it in a known state. */
285 	le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP);
286 	delay(100);
287 
288 	if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP)
289 		return 0;
290 
291 	le_isa_wrcsr(sc, LE_CSR3, sc->sc_conf3);
292 	return 1;
293 }
294 
295 void
le_isa_attach(struct device * parent,struct device * self,void * aux)296 le_isa_attach(struct device *parent, struct device *self,
297     void *aux)
298 {
299 	struct le_softc *lesc = (void *)self;
300 	struct lance_softc *sc = &lesc->sc_am7990.lsc;
301 	struct isa_attach_args *ia = aux;
302 	bus_space_tag_t iot = ia->ia_iot;
303 	bus_space_handle_t ioh;
304 
305 	if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh))
306 		panic("%s: can't map I/O-ports", sc->sc_dev.dv_xname);
307 	lesc->sc_iot = iot;
308 	lesc->sc_ioh = ioh;
309 
310 	printf(": %s Ethernet\n", card_type[lesc->sc_card]);
311 
312 	if (lesc->sc_card == DEPCA) {
313 		u_char *mem, val;
314 		int i;
315 
316 		mem = sc->sc_mem = ISA_HOLE_VADDR(ia->ia_maddr);
317 
318 		val = 0xff;
319 		for (;;) {
320 			for (i = 0; i < ia->ia_msize; i++)
321 				mem[i] = val;
322 			for (i = 0; i < ia->ia_msize; i++)
323 				if (mem[i] != val) {
324 					printf("%s: failed to clear memory\n",
325 					    sc->sc_dev.dv_xname);
326 					return;
327 				}
328 			if (val == 0x00)
329 				break;
330 			val -= 0x55;
331 		}
332 
333 		sc->sc_conf3 = LE_C3_ACON;
334 		sc->sc_addr = 0;
335 		sc->sc_memsize = ia->ia_msize;
336 	} else {
337 		sc->sc_mem = malloc(16384, M_DEVBUF, M_NOWAIT);
338 		if (sc->sc_mem == 0) {
339 			printf("%s: couldn't allocate memory for card\n",
340 			    sc->sc_dev.dv_xname);
341 			return;
342 		}
343 
344 		sc->sc_conf3 = 0;
345 		sc->sc_addr = kvtop(sc->sc_mem);
346 		sc->sc_memsize = 16384;
347 	}
348 
349 	sc->sc_copytodesc = lance_copytobuf_contig;
350 	sc->sc_copyfromdesc = lance_copyfrombuf_contig;
351 	sc->sc_copytobuf = lance_copytobuf_contig;
352 	sc->sc_copyfrombuf = lance_copyfrombuf_contig;
353 	sc->sc_zerobuf = lance_zerobuf_contig;
354 
355 	sc->sc_rdcsr = le_isa_rdcsr;
356 	sc->sc_wrcsr = le_isa_wrcsr;
357 	sc->sc_hwreset = NULL;
358 	sc->sc_hwinit = NULL;
359 
360 	printf("%s", sc->sc_dev.dv_xname);
361 	am7990_config(&lesc->sc_am7990);
362 
363 #if NISADMA > 0
364 	if (ia->ia_drq != DRQUNK)
365 		isadma_cascade(ia->ia_drq);
366 #endif
367 
368 	lesc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
369 	    IPL_NET, le_isa_intredge, sc, sc->sc_dev.dv_xname);
370 }
371