2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2005, M. Warner Losh
6 * Copyright (c) 1995, David Greenman
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice unmodified, this list of conditions, and the following
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.
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
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/sockio.h>
43 #include <sys/kernel.h>
44 #include <sys/socket.h>
45 #include <sys/syslog.h>
49 #include <machine/bus.h>
51 #include <machine/resource.h>
53 #include <net/ethernet.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>
63 #include <dev/ed/if_edreg.h>
64 #include <dev/ed/if_edvar.h>
66 static void ed_3c503_mediachg(struct ed_softc *sc);
69 * Probe and vendor-specific initialization routine for 3Com 3c503 boards
72 ed_probe_3Com(device_t dev, int port_rid, int flags)
74 struct ed_softc *sc = device_get_softc(dev);
79 rman_res_t conf_maddr, conf_msize, irq, junk, pmem;
81 error = ed_alloc_port(dev, 0, ED_3COM_IO_PORTS);
85 sc->asic_offset = ED_3COM_ASIC_OFFSET;
86 sc->nic_offset = ED_3COM_NIC_OFFSET;
89 * Verify that the kernel configured I/O address matches the board
92 switch (ed_asic_inb(sc, ED_3COM_BCFR)) {
93 case ED_3COM_BCFR_300:
94 if (rman_get_start(sc->port_res) != 0x300)
97 case ED_3COM_BCFR_310:
98 if (rman_get_start(sc->port_res) != 0x310)
101 case ED_3COM_BCFR_330:
102 if (rman_get_start(sc->port_res) != 0x330)
105 case ED_3COM_BCFR_350:
106 if (rman_get_start(sc->port_res) != 0x350)
109 case ED_3COM_BCFR_250:
110 if (rman_get_start(sc->port_res) != 0x250)
113 case ED_3COM_BCFR_280:
114 if (rman_get_start(sc->port_res) != 0x280)
117 case ED_3COM_BCFR_2A0:
118 if (rman_get_start(sc->port_res) != 0x2a0)
121 case ED_3COM_BCFR_2E0:
122 if (rman_get_start(sc->port_res) != 0x2e0)
129 error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
130 &conf_maddr, &conf_msize);
135 * Verify that the kernel shared memory address matches the board
136 * configured address.
138 switch (ed_asic_inb(sc, ED_3COM_PCFR)) {
139 case ED_3COM_PCFR_DC000:
140 if (conf_maddr != 0xdc000)
143 case ED_3COM_PCFR_D8000:
144 if (conf_maddr != 0xd8000)
147 case ED_3COM_PCFR_CC000:
148 if (conf_maddr != 0xcc000)
151 case ED_3COM_PCFR_C8000:
152 if (conf_maddr != 0xc8000)
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
165 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL);
168 * Wait for a while, then un-reset it
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).
177 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
180 * Wait a bit for the NIC to recover from the reset
184 sc->vendor = ED_VENDOR_3COM;
185 sc->type_str = "3c503";
187 sc->cr_proto = ED_CR_RD2;
190 * Hmmm...a 16bit 3Com board has 16k of memory, but only an 8k window
196 * Get station address from on-board ROM
200 * First, map ethernet address PROM over the top of where the NIC
201 * registers normally appear.
203 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
205 for (i = 0; i < ETHER_ADDR_LEN; ++i)
206 sc->enaddr[i] = ed_nic_inb(sc, i);
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
213 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
216 * Determine if this is an 8bit or 16bit board
220 * select page 0 registers
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);
229 * Attempt to clear WTS bit. If it doesn't clear, then this is a 16bit
232 ed_nic_outb(sc, ED_P0_DCR, 0);
235 * select page 2 registers
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);
244 * The 3c503 forces the WTS bit to a one if this is a 16bit board
246 if (ed_nic_inb(sc, ED_P2_DCR) & ED_DCR_WTS)
252 * select page 0 registers
254 ed_nic_outb(sc, ED_P2_CR, ED_CR_RD2 | ED_CR_STP);
256 error = ed_alloc_memory(dev, 0, memsize);
260 pmem = rman_get_start(sc->mem_res);
261 error = ed_isa_mem_ok(dev, pmem, memsize);
266 sc->mem_size = memsize;
267 sc->mem_end = sc->mem_start + memsize;
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.)
279 if (flags & ED_FLAGS_NO_MULTI_BUFFERING)
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;
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);
298 sc->isa16bit = isa16bit;
301 * Initialize GA page start/stop registers. Probably only needed if
302 * doing DMA, but what the hell.
304 ed_asic_outb(sc, ED_3COM_PSTR, sc->rec_page_start);
305 ed_asic_outb(sc, ED_3COM_PSPR, sc->rec_page_stop);
308 * Set IRQ. 3c503 only allows a choice of irq 2-5.
310 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
317 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
320 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
323 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
326 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
329 device_printf(dev, "Invalid irq configuration (%jd) must be 3-5,9 for 3c503\n",
335 * Initialize GA configuration register. Set bank and enable shared
338 ed_asic_outb(sc, ED_3COM_GACFR, ED_3COM_GACFR_RSEL |
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
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);
351 error = ed_clear_memory(dev);
353 sc->sc_mediachg = ed_3c503_mediachg;
354 sc->sc_write_mbufs = ed_shmem_write_mbufs;
360 ed_3c503_mediachg(struct ed_softc *sc)
362 struct ifnet *ifp = sc->ifp;
365 * If this is a 3Com board, the tranceiver must be software enabled
366 * (there is no settable hardware default).
368 if (ifp->if_flags & IFF_LINK2)
369 ed_asic_outb(sc, ED_3COM_CR, 0);
371 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
374 #endif /* ED_3C503 */