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: stable/9/sys/dev/ed/if_ed_3c503.c 264943 2014-04-25 21:32:38Z marius $");
32
33 #include "opt_ed.h"
34
35 #ifdef ED_3C503
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 static void ed_3c503_mediachg(struct ed_softc *sc);
64
65 /*
66 * Probe and vendor-specific initialization routine for 3Com 3c503 boards
67 */
68 int
ed_probe_3Com(device_t dev,int port_rid,int flags)69 ed_probe_3Com(device_t dev, int port_rid, int flags)
70 {
71 struct ed_softc *sc = device_get_softc(dev);
72 int error;
73 int i;
74 u_int memsize;
75 u_char isa16bit;
76 u_long conf_maddr, conf_msize, irq, junk, pmem;
77
78 error = ed_alloc_port(dev, 0, ED_3COM_IO_PORTS);
79 if (error)
80 return (error);
81
82 sc->asic_offset = ED_3COM_ASIC_OFFSET;
83 sc->nic_offset = ED_3COM_NIC_OFFSET;
84
85 /*
86 * Verify that the kernel configured I/O address matches the board
87 * configured address
88 */
89 switch (ed_asic_inb(sc, ED_3COM_BCFR)) {
90 case ED_3COM_BCFR_300:
91 if (rman_get_start(sc->port_res) != 0x300)
92 return (ENXIO);
93 break;
94 case ED_3COM_BCFR_310:
95 if (rman_get_start(sc->port_res) != 0x310)
96 return (ENXIO);
97 break;
98 case ED_3COM_BCFR_330:
99 if (rman_get_start(sc->port_res) != 0x330)
100 return (ENXIO);
101 break;
102 case ED_3COM_BCFR_350:
103 if (rman_get_start(sc->port_res) != 0x350)
104 return (ENXIO);
105 break;
106 case ED_3COM_BCFR_250:
107 if (rman_get_start(sc->port_res) != 0x250)
108 return (ENXIO);
109 break;
110 case ED_3COM_BCFR_280:
111 if (rman_get_start(sc->port_res) != 0x280)
112 return (ENXIO);
113 break;
114 case ED_3COM_BCFR_2A0:
115 if (rman_get_start(sc->port_res) != 0x2a0)
116 return (ENXIO);
117 break;
118 case ED_3COM_BCFR_2E0:
119 if (rman_get_start(sc->port_res) != 0x2e0)
120 return (ENXIO);
121 break;
122 default:
123 return (ENXIO);
124 }
125
126 error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
127 &conf_maddr, &conf_msize);
128 if (error)
129 return (error);
130
131 /*
132 * Verify that the kernel shared memory address matches the board
133 * configured address.
134 */
135 switch (ed_asic_inb(sc, ED_3COM_PCFR)) {
136 case ED_3COM_PCFR_DC000:
137 if (conf_maddr != 0xdc000)
138 return (ENXIO);
139 break;
140 case ED_3COM_PCFR_D8000:
141 if (conf_maddr != 0xd8000)
142 return (ENXIO);
143 break;
144 case ED_3COM_PCFR_CC000:
145 if (conf_maddr != 0xcc000)
146 return (ENXIO);
147 break;
148 case ED_3COM_PCFR_C8000:
149 if (conf_maddr != 0xc8000)
150 return (ENXIO);
151 break;
152 default:
153 return (ENXIO);
154 }
155
156
157 /*
158 * Reset NIC and ASIC. Enable on-board transceiver throughout reset
159 * sequence because it'll lock up if the cable isn't connected if we
160 * don't.
161 */
162 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL);
163
164 /*
165 * Wait for a while, then un-reset it
166 */
167 DELAY(50);
168
169 /*
170 * The 3Com ASIC defaults to rather strange settings for the CR after
171 * a reset - it's important to set it again after the following outb
172 * (this is done when we map the PROM below).
173 */
174 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
175
176 /*
177 * Wait a bit for the NIC to recover from the reset
178 */
179 DELAY(5000);
180
181 sc->vendor = ED_VENDOR_3COM;
182 sc->type_str = "3c503";
183 sc->mem_shared = 1;
184 sc->cr_proto = ED_CR_RD2;
185
186 /*
187 * Hmmm...a 16bit 3Com board has 16k of memory, but only an 8k window
188 * to it.
189 */
190 memsize = 8192;
191
192 /*
193 * Get station address from on-board ROM
194 */
195
196 /*
197 * First, map ethernet address PROM over the top of where the NIC
198 * registers normally appear.
199 */
200 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
201
202 for (i = 0; i < ETHER_ADDR_LEN; ++i)
203 sc->enaddr[i] = ed_nic_inb(sc, i);
204
205 /*
206 * Unmap PROM - select NIC registers. The proper setting of the
207 * tranceiver is set in ed_init so that the attach code is given a
208 * chance to set the default based on a compile-time config option
209 */
210 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
211
212 /*
213 * Determine if this is an 8bit or 16bit board
214 */
215
216 /*
217 * select page 0 registers
218 */
219 ed_nic_barrier(sc, ED_P0_CR, 1,
220 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
221 ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_0 | ED_CR_RD2 | ED_CR_STP);
222 ed_nic_barrier(sc, ED_P0_CR, 1,
223 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
224
225 /*
226 * Attempt to clear WTS bit. If it doesn't clear, then this is a 16bit
227 * board.
228 */
229 ed_nic_outb(sc, ED_P0_DCR, 0);
230
231 /*
232 * select page 2 registers
233 */
234 ed_nic_barrier(sc, ED_P0_CR, 1,
235 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
236 ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_2 | ED_CR_RD2 | ED_CR_STP);
237 ed_nic_barrier(sc, ED_P0_CR, 1,
238 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
239
240 /*
241 * The 3c503 forces the WTS bit to a one if this is a 16bit board
242 */
243 if (ed_nic_inb(sc, ED_P2_DCR) & ED_DCR_WTS)
244 isa16bit = 1;
245 else
246 isa16bit = 0;
247
248 /*
249 * select page 0 registers
250 */
251 ed_nic_outb(sc, ED_P2_CR, ED_CR_RD2 | ED_CR_STP);
252
253 error = ed_alloc_memory(dev, 0, memsize);
254 if (error)
255 return (error);
256
257 pmem = rman_get_start(sc->mem_res);
258 error = ed_isa_mem_ok(dev, pmem, memsize);
259 if (error)
260 return (error);
261
262 sc->mem_start = 0;
263 sc->mem_size = memsize;
264 sc->mem_end = sc->mem_start + memsize;
265
266 /*
267 * We have an entire 8k window to put the transmit buffers on the
268 * 16bit boards. But since the 16bit 3c503's shared memory is only
269 * fast enough to overlap the loading of one full-size packet, trying
270 * to load more than 2 buffers can actually leave the transmitter idle
271 * during the load. So 2 seems the best value. (Although a mix of
272 * variable-sized packets might change this assumption. Nonetheless,
273 * we optimize for linear transfers of same-size packets.)
274 */
275 if (isa16bit) {
276 if (flags & ED_FLAGS_NO_MULTI_BUFFERING)
277 sc->txb_cnt = 1;
278 else
279 sc->txb_cnt = 2;
280
281 sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_16BIT;
282 sc->rec_page_start = ED_3COM_RX_PAGE_OFFSET_16BIT;
283 sc->rec_page_stop = memsize / ED_PAGE_SIZE +
284 ED_3COM_RX_PAGE_OFFSET_16BIT;
285 sc->mem_ring = sc->mem_start;
286 } else {
287 sc->txb_cnt = 1;
288 sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_8BIT;
289 sc->rec_page_start = ED_TXBUF_SIZE + ED_3COM_TX_PAGE_OFFSET_8BIT;
290 sc->rec_page_stop = memsize / ED_PAGE_SIZE +
291 ED_3COM_TX_PAGE_OFFSET_8BIT;
292 sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE);
293 }
294
295 sc->isa16bit = isa16bit;
296
297 /*
298 * Initialize GA page start/stop registers. Probably only needed if
299 * doing DMA, but what the hell.
300 */
301 ed_asic_outb(sc, ED_3COM_PSTR, sc->rec_page_start);
302 ed_asic_outb(sc, ED_3COM_PSPR, sc->rec_page_stop);
303
304 /*
305 * Set IRQ. 3c503 only allows a choice of irq 2-5.
306 */
307 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
308 if (error)
309 return (error);
310
311 switch (irq) {
312 case 2:
313 case 9:
314 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
315 break;
316 case 3:
317 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
318 break;
319 case 4:
320 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
321 break;
322 case 5:
323 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
324 break;
325 default:
326 device_printf(dev, "Invalid irq configuration (%ld) must be 3-5,9 for 3c503\n",
327 irq);
328 return (ENXIO);
329 }
330
331 /*
332 * Initialize GA configuration register. Set bank and enable shared
333 * mem.
334 */
335 ed_asic_outb(sc, ED_3COM_GACFR, ED_3COM_GACFR_RSEL |
336 ED_3COM_GACFR_MBS0);
337
338 /*
339 * Initialize "Vector Pointer" registers. These gawd-awful things are
340 * compared to 20 bits of the address on ISA, and if they match, the
341 * shared memory is disabled. We set them to 0xffff0...allegedly the
342 * reset vector.
343 */
344 ed_asic_outb(sc, ED_3COM_VPTR2, 0xff);
345 ed_asic_outb(sc, ED_3COM_VPTR1, 0xff);
346 ed_asic_outb(sc, ED_3COM_VPTR0, 0x00);
347
348 error = ed_clear_memory(dev);
349 if (error == 0) {
350 sc->sc_mediachg = ed_3c503_mediachg;
351 sc->sc_write_mbufs = ed_shmem_write_mbufs;
352 }
353 return (error);
354 }
355
356 static void
ed_3c503_mediachg(struct ed_softc * sc)357 ed_3c503_mediachg(struct ed_softc *sc)
358 {
359 struct ifnet *ifp = sc->ifp;
360
361 /*
362 * If this is a 3Com board, the tranceiver must be software enabled
363 * (there is no settable hardware default).
364 */
365 if (ifp->if_flags & IFF_LINK2)
366 ed_asic_outb(sc, ED_3COM_CR, 0);
367 else
368 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
369 }
370
371 #endif /* ED_3C503 */
372