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