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