1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2005, M. Warner Losh
5 * All rights reserved.
6 * Copyright (c) 1995, David Greenman
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice unmodified, this list of conditions, and the following
14 * disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD: stable/12/sys/dev/ed/if_ed_wd80x3.c 326255 2017-11-27 14:52:40Z pfg $");
34
35 #include "opt_ed.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/sockio.h>
40 #include <sys/mbuf.h>
41 #include <sys/kernel.h>
42 #include <sys/socket.h>
43 #include <sys/syslog.h>
44
45 #include <sys/bus.h>
46
47 #include <machine/bus.h>
48 #include <sys/rman.h>
49 #include <machine/resource.h>
50
51 #include <net/ethernet.h>
52 #include <net/if.h>
53 #include <net/if_arp.h>
54 #include <net/if_dl.h>
55 #include <net/if_mib.h>
56 #include <net/if_media.h>
57
58 #include <net/bpf.h>
59
60 #include <dev/ed/if_edreg.h>
61 #include <dev/ed/if_edvar.h>
62
63 /*
64 * Interrupt conversion table for WD/SMC ASIC/83C584
65 */
66 static uint16_t ed_intr_val[] = {
67 9,
68 3,
69 5,
70 7,
71 10,
72 11,
73 15,
74 4
75 };
76
77 /*
78 * Interrupt conversion table for 83C790
79 */
80 static uint16_t ed_790_intr_val[] = {
81 0,
82 9,
83 3,
84 5,
85 7,
86 10,
87 11,
88 15
89 };
90
91 /*
92 * Probe and vendor-specific initialization routine for SMC/WD80x3 boards
93 */
94 int
ed_probe_WD80x3_generic(device_t dev,int flags,uint16_t * intr_vals[])95 ed_probe_WD80x3_generic(device_t dev, int flags, uint16_t *intr_vals[])
96 {
97 struct ed_softc *sc = device_get_softc(dev);
98 int error;
99 int i;
100 u_int memsize;
101 u_char iptr, isa16bit, sum, totalsum;
102 rman_res_t irq, junk, pmem;
103
104 sc->chip_type = ED_CHIP_TYPE_DP8390;
105
106 if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER) {
107 totalsum = ED_WD_ROM_CHECKSUM_TOTAL_TOSH_ETHER;
108 ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_POW);
109 DELAY(10000);
110 }
111 else
112 totalsum = ED_WD_ROM_CHECKSUM_TOTAL;
113
114 /*
115 * Attempt to do a checksum over the station address PROM. If it
116 * fails, it's probably not a SMC/WD board. There is a problem with
117 * this, though: some clone WD boards don't pass the checksum test.
118 * Danpex boards for one.
119 */
120 for (sum = 0, i = 0; i < 8; ++i)
121 sum += ed_asic_inb(sc, ED_WD_PROM + i);
122
123 if (sum != totalsum) {
124 /*
125 * Checksum is invalid. This often happens with cheap WD8003E
126 * clones. In this case, the checksum byte (the eighth byte)
127 * seems to always be zero.
128 */
129 if (ed_asic_inb(sc, ED_WD_CARD_ID) != ED_TYPE_WD8003E ||
130 ed_asic_inb(sc, ED_WD_PROM + 7) != 0)
131 return (ENXIO);
132 }
133 /* reset card to force it into a known state. */
134 if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER)
135 ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_RST | ED_WD_MSR_POW);
136 else
137 ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_RST);
138
139 DELAY(100);
140 ed_asic_outb(sc, ED_WD_MSR, ed_asic_inb(sc, ED_WD_MSR) & ~ED_WD_MSR_RST);
141 /* wait in the case this card is reading its EEROM */
142 DELAY(5000);
143
144 sc->vendor = ED_VENDOR_WD_SMC;
145 sc->type = ed_asic_inb(sc, ED_WD_CARD_ID);
146
147 /*
148 * Set initial values for width/size.
149 */
150 memsize = 8192;
151 isa16bit = 0;
152 switch (sc->type) {
153 case ED_TYPE_WD8003S:
154 sc->type_str = "WD8003S";
155 break;
156 case ED_TYPE_WD8003E:
157 sc->type_str = "WD8003E";
158 break;
159 case ED_TYPE_WD8003EB:
160 sc->type_str = "WD8003EB";
161 break;
162 case ED_TYPE_WD8003W:
163 sc->type_str = "WD8003W";
164 break;
165 case ED_TYPE_WD8013EBT:
166 sc->type_str = "WD8013EBT";
167 memsize = 16384;
168 isa16bit = 1;
169 break;
170 case ED_TYPE_WD8013W:
171 sc->type_str = "WD8013W";
172 memsize = 16384;
173 isa16bit = 1;
174 break;
175 case ED_TYPE_WD8013EP: /* also WD8003EP */
176 if (ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_16BIT) {
177 isa16bit = 1;
178 memsize = 16384;
179 sc->type_str = "WD8013EP";
180 } else
181 sc->type_str = "WD8003EP";
182 break;
183 case ED_TYPE_WD8013WC:
184 sc->type_str = "WD8013WC";
185 memsize = 16384;
186 isa16bit = 1;
187 break;
188 case ED_TYPE_WD8013EBP:
189 sc->type_str = "WD8013EBP";
190 memsize = 16384;
191 isa16bit = 1;
192 break;
193 case ED_TYPE_WD8013EPC:
194 sc->type_str = "WD8013EPC";
195 memsize = 16384;
196 isa16bit = 1;
197 break;
198 case ED_TYPE_SMC8216C: /* 8216 has 16K shared mem -- 8416 has 8K */
199 case ED_TYPE_SMC8216T:
200 if (sc->type == ED_TYPE_SMC8216C)
201 sc->type_str = "SMC8216/SMC8216C";
202 else
203 sc->type_str = "SMC8216T";
204
205 ed_asic_outb(sc, ED_WD790_HWR,
206 ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH);
207 switch (ed_asic_inb(sc, ED_WD790_RAR) & ED_WD790_RAR_SZ64) {
208 case ED_WD790_RAR_SZ64:
209 memsize = 65536;
210 break;
211 case ED_WD790_RAR_SZ32:
212 memsize = 32768;
213 break;
214 case ED_WD790_RAR_SZ16:
215 memsize = 16384;
216 break;
217 case ED_WD790_RAR_SZ8:
218 /* 8216 has 16K shared mem -- 8416 has 8K */
219 if (sc->type == ED_TYPE_SMC8216C)
220 sc->type_str = "SMC8416C/SMC8416BT";
221 else
222 sc->type_str = "SMC8416T";
223 memsize = 8192;
224 break;
225 }
226 ed_asic_outb(sc, ED_WD790_HWR,
227 ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
228
229 isa16bit = 1;
230 sc->chip_type = ED_CHIP_TYPE_WD790;
231 break;
232 case ED_TYPE_TOSHIBA1:
233 sc->type_str = "Toshiba1";
234 memsize = 32768;
235 isa16bit = 1;
236 break;
237 case ED_TYPE_TOSHIBA4:
238 sc->type_str = "Toshiba4";
239 memsize = 32768;
240 isa16bit = 1;
241 break;
242 default:
243 sc->type_str = "";
244 break;
245 }
246
247 /*
248 * Make some adjustments to initial values depending on what is found
249 * in the ICR.
250 */
251 if (isa16bit && (sc->type != ED_TYPE_WD8013EBT)
252 && (sc->type != ED_TYPE_TOSHIBA1) && (sc->type != ED_TYPE_TOSHIBA4)
253 && ((ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) {
254 isa16bit = 0;
255 memsize = 8192;
256 }
257
258 /* Override memsize? XXX */
259 error = ed_alloc_memory(dev, 0, memsize);
260 if (error)
261 return (error);
262 sc->mem_start = 0;
263
264 #ifdef ED_DEBUG
265 printf("type = %x type_str=%s isa16bit=%d memsize=%d id_msize=%lu\n",
266 sc->type, sc->type_str, isa16bit, memsize,
267 rman_get_size(sc->mem_res));
268 for (i = 0; i < 8; i++)
269 printf("%x -> %x\n", i, ed_asic_inb(sc, i));
270 #endif
271 pmem = rman_get_start(sc->mem_res);
272 if (!(flags & ED_FLAGS_PCCARD)) {
273 error = ed_isa_mem_ok(dev, pmem, memsize);
274 if (error)
275 return (error);
276 }
277
278 /*
279 * (note that if the user specifies both of the following flags that
280 * '8bit' mode intentionally has precedence)
281 */
282 if (flags & ED_FLAGS_FORCE_16BIT_MODE)
283 isa16bit = 1;
284 if (flags & ED_FLAGS_FORCE_8BIT_MODE)
285 isa16bit = 0;
286
287 /*
288 * If possible, get the assigned interrupt number from the card and
289 * use it.
290 */
291 if ((sc->type & ED_WD_SOFTCONFIG) &&
292 (sc->chip_type != ED_CHIP_TYPE_WD790)) {
293
294 /*
295 * Assemble together the encoded interrupt number.
296 */
297 iptr = (ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_IR2) |
298 ((ed_asic_inb(sc, ED_WD_IRR) &
299 (ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5);
300
301 /*
302 * If no interrupt specified (or "?"), use what the board tells us.
303 */
304 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
305 if (error && intr_vals[0] != NULL)
306 error = bus_set_resource(dev, SYS_RES_IRQ, 0,
307 intr_vals[0][iptr], 1);
308 if (error)
309 return (error);
310
311 /*
312 * Enable the interrupt.
313 */
314 ed_asic_outb(sc, ED_WD_IRR,
315 ed_asic_inb(sc, ED_WD_IRR) | ED_WD_IRR_IEN);
316 }
317 if (sc->chip_type == ED_CHIP_TYPE_WD790) {
318 ed_asic_outb(sc, ED_WD790_HWR,
319 ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH);
320 iptr = (((ed_asic_inb(sc, ED_WD790_GCR) & ED_WD790_GCR_IR2) >> 4) |
321 (ed_asic_inb(sc, ED_WD790_GCR) &
322 (ED_WD790_GCR_IR1 | ED_WD790_GCR_IR0)) >> 2);
323 ed_asic_outb(sc, ED_WD790_HWR,
324 ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
325
326 /*
327 * If no interrupt specified (or "?"), use what the board tells us.
328 */
329 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
330 if (error && intr_vals[1] != NULL)
331 error = bus_set_resource(dev, SYS_RES_IRQ, 0,
332 intr_vals[1][iptr], 1);
333 if (error)
334 return (error);
335
336 /*
337 * Enable interrupts.
338 */
339 ed_asic_outb(sc, ED_WD790_ICR,
340 ed_asic_inb(sc, ED_WD790_ICR) | ED_WD790_ICR_EIL);
341 }
342 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
343 if (error) {
344 device_printf(dev, "%s cards don't support auto-detected/assigned interrupts.\n",
345 sc->type_str);
346 return (ENXIO);
347 }
348 sc->isa16bit = isa16bit;
349 sc->mem_shared = 1;
350
351 /*
352 * allocate one xmit buffer if < 16k, two buffers otherwise
353 */
354 if (memsize < 16384 || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
355 sc->txb_cnt = 1;
356 else
357 sc->txb_cnt = 2;
358 sc->tx_page_start = ED_WD_PAGE_OFFSET;
359 sc->rec_page_start = ED_WD_PAGE_OFFSET + ED_TXBUF_SIZE * sc->txb_cnt;
360 sc->rec_page_stop = ED_WD_PAGE_OFFSET + memsize / ED_PAGE_SIZE;
361 sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * sc->rec_page_start);
362 sc->mem_size = memsize;
363 sc->mem_end = sc->mem_start + memsize;
364
365 /*
366 * Get station address from on-board ROM
367 */
368 for (i = 0; i < ETHER_ADDR_LEN; ++i)
369 sc->enaddr[i] = ed_asic_inb(sc, ED_WD_PROM + i);
370
371 /*
372 * Set upper address bits and 8/16 bit access to shared memory.
373 */
374 if (isa16bit) {
375 if (sc->chip_type == ED_CHIP_TYPE_WD790)
376 sc->wd_laar_proto = ed_asic_inb(sc, ED_WD_LAAR);
377 else
378 sc->wd_laar_proto = ED_WD_LAAR_L16EN |
379 ((pmem >> 19) & ED_WD_LAAR_ADDRHI);
380 /*
381 * Enable 16bit access
382 */
383 ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto |
384 ED_WD_LAAR_M16EN);
385 } else {
386 if (((sc->type & ED_WD_SOFTCONFIG) ||
387 (sc->type == ED_TYPE_TOSHIBA1) ||
388 (sc->type == ED_TYPE_TOSHIBA4) ||
389 (sc->type == ED_TYPE_WD8013EBT)) &&
390 (sc->chip_type != ED_CHIP_TYPE_WD790)) {
391 sc->wd_laar_proto = (pmem >> 19) &
392 ED_WD_LAAR_ADDRHI;
393 ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto);
394 }
395 }
396
397 /*
398 * Set address and enable interface shared memory.
399 */
400 if (sc->chip_type != ED_CHIP_TYPE_WD790) {
401 if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER) {
402 ed_asic_outb(sc, ED_WD_MSR + 1,
403 ((pmem >> 8) & 0xe0) | 4);
404 ed_asic_outb(sc, ED_WD_MSR + 2, ((pmem >> 16) & 0x0f));
405 ed_asic_outb(sc, ED_WD_MSR,
406 ED_WD_MSR_MENB | ED_WD_MSR_POW);
407 } else {
408 ed_asic_outb(sc, ED_WD_MSR, ((pmem >> 13) &
409 ED_WD_MSR_ADDR) | ED_WD_MSR_MENB);
410 }
411 sc->cr_proto = ED_CR_RD2;
412 } else {
413 ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_MENB);
414 ed_asic_outb(sc, ED_WD790_HWR,
415 (ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH));
416 ed_asic_outb(sc, ED_WD790_RAR,
417 ((pmem >> 13) & 0x0f) | ((pmem >> 11) & 0x40) |
418 (ed_asic_inb(sc, ED_WD790_RAR) & 0xb0));
419 ed_asic_outb(sc, ED_WD790_HWR,
420 (ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH));
421 sc->cr_proto = 0;
422 }
423
424 /*
425 * Disable 16bit access to shared memory - we leave it
426 * disabled so that 1) machines reboot properly when the board
427 * is set 16 bit mode and there are conflicting 8bit
428 * devices/ROMS in the same 128k address space as this boards
429 * shared memory. and 2) so that other 8 bit devices with
430 * shared memory can be used in this 128k region, too.
431 */
432 error = ed_clear_memory(dev);
433 ed_disable_16bit_access(sc);
434 sc->sc_write_mbufs = ed_shmem_write_mbufs;
435 return (error);
436 }
437
438 int
ed_probe_WD80x3(device_t dev,int port_rid,int flags)439 ed_probe_WD80x3(device_t dev, int port_rid, int flags)
440 {
441 struct ed_softc *sc = device_get_softc(dev);
442 int error;
443 static uint16_t *intr_vals[] = {ed_intr_val, ed_790_intr_val};
444
445 error = ed_alloc_port(dev, port_rid, ED_WD_IO_PORTS);
446 if (error)
447 return (error);
448
449 sc->asic_offset = ED_WD_ASIC_OFFSET;
450 sc->nic_offset = ED_WD_NIC_OFFSET;
451
452 return ed_probe_WD80x3_generic(dev, flags, intr_vals);
453 }
454