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