1141586Simp/*-
2141586Simp * Copyright (c) 2005, M. Warner Losh
3141586Simp * All rights reserved.
4141586Simp * Copyright (c) 1995, David Greenman
5141586Simp * All rights reserved.
6141586Simp *
7141586Simp * Redistribution and use in source and binary forms, with or without
8141586Simp * modification, are permitted provided that the following conditions
9141586Simp * are met:
10141586Simp * 1. Redistributions of source code must retain the above copyright
11141586Simp *    notice unmodified, this list of conditions, and the following
12141586Simp *    disclaimer.
13141586Simp * 2. Redistributions in binary form must reproduce the above copyright
14141586Simp *    notice, this list of conditions and the following disclaimer in the
15141586Simp *    documentation and/or other materials provided with the distribution.
16141586Simp *
17141586Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18141586Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19141586Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20141586Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21141586Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22141586Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23141586Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24141586Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25141586Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26141586Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27141586Simp * SUCH DAMAGE.
28141586Simp */
29141586Simp
30141586Simp#include <sys/cdefs.h>
31141586Simp__FBSDID("$FreeBSD$");
32141586Simp
33141586Simp#include "opt_ed.h"
34141586Simp
35141586Simp#ifdef ED_3C503
36141586Simp
37141586Simp#include <sys/param.h>
38141586Simp#include <sys/systm.h>
39141586Simp#include <sys/sockio.h>
40141586Simp#include <sys/mbuf.h>
41141586Simp#include <sys/kernel.h>
42141586Simp#include <sys/socket.h>
43141586Simp#include <sys/syslog.h>
44141586Simp
45141586Simp#include <sys/bus.h>
46141586Simp
47141586Simp#include <machine/bus.h>
48141586Simp#include <sys/rman.h>
49141586Simp#include <machine/resource.h>
50141586Simp
51141586Simp#include <net/ethernet.h>
52141586Simp#include <net/if.h>
53257176Sglebius#include <net/if_var.h>		/* XXX: ed_3c503_mediachg() */
54141586Simp#include <net/if_arp.h>
55141586Simp#include <net/if_dl.h>
56141586Simp#include <net/if_mib.h>
57141586Simp#include <net/if_media.h>
58141586Simp
59141586Simp#include <net/bpf.h>
60141586Simp
61141586Simp#include <dev/ed/if_edreg.h>
62141586Simp#include <dev/ed/if_edvar.h>
63141586Simp
64154895Simpstatic void ed_3c503_mediachg(struct ed_softc *sc);
65154895Simp
66141586Simp/*
67141586Simp * Probe and vendor-specific initialization routine for 3Com 3c503 boards
68141586Simp */
69141586Simpint
70141586Simped_probe_3Com(device_t dev, int port_rid, int flags)
71141586Simp{
72141586Simp	struct ed_softc *sc = device_get_softc(dev);
73141586Simp	int	error;
74141586Simp	int     i;
75141586Simp	u_int   memsize;
76141586Simp	u_char  isa16bit;
77294883Sjhibbits	rman_res_t	conf_maddr, conf_msize, irq, junk, pmem;
78141586Simp
79141586Simp	error = ed_alloc_port(dev, 0, ED_3COM_IO_PORTS);
80141586Simp	if (error)
81141586Simp		return (error);
82141586Simp
83141586Simp	sc->asic_offset = ED_3COM_ASIC_OFFSET;
84141586Simp	sc->nic_offset  = ED_3COM_NIC_OFFSET;
85141586Simp
86141586Simp	/*
87141586Simp	 * Verify that the kernel configured I/O address matches the board
88141586Simp	 * configured address
89141586Simp	 */
90141586Simp	switch (ed_asic_inb(sc, ED_3COM_BCFR)) {
91141586Simp	case ED_3COM_BCFR_300:
92141586Simp		if (rman_get_start(sc->port_res) != 0x300)
93141586Simp			return (ENXIO);
94141586Simp		break;
95141586Simp	case ED_3COM_BCFR_310:
96141586Simp		if (rman_get_start(sc->port_res) != 0x310)
97141586Simp			return (ENXIO);
98141586Simp		break;
99141586Simp	case ED_3COM_BCFR_330:
100141586Simp		if (rman_get_start(sc->port_res) != 0x330)
101141586Simp			return (ENXIO);
102141586Simp		break;
103141586Simp	case ED_3COM_BCFR_350:
104141586Simp		if (rman_get_start(sc->port_res) != 0x350)
105141586Simp			return (ENXIO);
106141586Simp		break;
107141586Simp	case ED_3COM_BCFR_250:
108141586Simp		if (rman_get_start(sc->port_res) != 0x250)
109141586Simp			return (ENXIO);
110141586Simp		break;
111141586Simp	case ED_3COM_BCFR_280:
112141586Simp		if (rman_get_start(sc->port_res) != 0x280)
113141586Simp			return (ENXIO);
114141586Simp		break;
115141586Simp	case ED_3COM_BCFR_2A0:
116141586Simp		if (rman_get_start(sc->port_res) != 0x2a0)
117141586Simp			return (ENXIO);
118141586Simp		break;
119141586Simp	case ED_3COM_BCFR_2E0:
120141586Simp		if (rman_get_start(sc->port_res) != 0x2e0)
121141586Simp			return (ENXIO);
122141586Simp		break;
123141586Simp	default:
124141586Simp		return (ENXIO);
125141586Simp	}
126141586Simp
127141586Simp	error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
128141586Simp				 &conf_maddr, &conf_msize);
129141586Simp	if (error)
130141586Simp		return (error);
131141586Simp
132141586Simp	/*
133141586Simp	 * Verify that the kernel shared memory address matches the board
134141586Simp	 * configured address.
135141586Simp	 */
136141586Simp	switch (ed_asic_inb(sc, ED_3COM_PCFR)) {
137141586Simp	case ED_3COM_PCFR_DC000:
138141586Simp		if (conf_maddr != 0xdc000)
139141586Simp			return (ENXIO);
140141586Simp		break;
141141586Simp	case ED_3COM_PCFR_D8000:
142141586Simp		if (conf_maddr != 0xd8000)
143141586Simp			return (ENXIO);
144141586Simp		break;
145141586Simp	case ED_3COM_PCFR_CC000:
146141586Simp		if (conf_maddr != 0xcc000)
147141586Simp			return (ENXIO);
148141586Simp		break;
149141586Simp	case ED_3COM_PCFR_C8000:
150141586Simp		if (conf_maddr != 0xc8000)
151141586Simp			return (ENXIO);
152141586Simp		break;
153141586Simp	default:
154141586Simp		return (ENXIO);
155141586Simp	}
156141586Simp
157141586Simp
158141586Simp	/*
159141586Simp	 * Reset NIC and ASIC. Enable on-board transceiver throughout reset
160141586Simp	 * sequence because it'll lock up if the cable isn't connected if we
161141586Simp	 * don't.
162141586Simp	 */
163141586Simp	ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL);
164141586Simp
165141586Simp	/*
166141586Simp	 * Wait for a while, then un-reset it
167141586Simp	 */
168141586Simp	DELAY(50);
169141586Simp
170141586Simp	/*
171141586Simp	 * The 3Com ASIC defaults to rather strange settings for the CR after
172141586Simp	 * a reset - it's important to set it again after the following outb
173141586Simp	 * (this is done when we map the PROM below).
174141586Simp	 */
175141586Simp	ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
176141586Simp
177141586Simp	/*
178141586Simp	 * Wait a bit for the NIC to recover from the reset
179141586Simp	 */
180141586Simp	DELAY(5000);
181141586Simp
182141586Simp	sc->vendor = ED_VENDOR_3COM;
183141586Simp	sc->type_str = "3c503";
184141586Simp	sc->mem_shared = 1;
185141586Simp	sc->cr_proto = ED_CR_RD2;
186141586Simp
187141586Simp	/*
188141586Simp	 * Hmmm...a 16bit 3Com board has 16k of memory, but only an 8k window
189141586Simp	 * to it.
190141586Simp	 */
191141586Simp	memsize = 8192;
192141586Simp
193141586Simp	/*
194141586Simp	 * Get station address from on-board ROM
195141586Simp	 */
196141586Simp
197141586Simp	/*
198141586Simp	 * First, map ethernet address PROM over the top of where the NIC
199141586Simp	 * registers normally appear.
200141586Simp	 */
201141586Simp	ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
202141586Simp
203141586Simp	for (i = 0; i < ETHER_ADDR_LEN; ++i)
204147256Sbrooks		sc->enaddr[i] = ed_nic_inb(sc, i);
205141586Simp
206141586Simp	/*
207141586Simp	 * Unmap PROM - select NIC registers. The proper setting of the
208141586Simp	 * tranceiver is set in ed_init so that the attach code is given a
209141586Simp	 * chance to set the default based on a compile-time config option
210141586Simp	 */
211141586Simp	ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
212141586Simp
213141586Simp	/*
214141586Simp	 * Determine if this is an 8bit or 16bit board
215141586Simp	 */
216141586Simp
217141586Simp	/*
218141586Simp	 * select page 0 registers
219141586Simp	 */
220260050Smarius	ed_nic_barrier(sc, ED_P0_CR, 1,
221260050Smarius	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
222260050Smarius	ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_0 | ED_CR_RD2 | ED_CR_STP);
223260050Smarius	ed_nic_barrier(sc, ED_P0_CR, 1,
224260050Smarius	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
225141586Simp
226141586Simp	/*
227141586Simp	 * Attempt to clear WTS bit. If it doesn't clear, then this is a 16bit
228141586Simp	 * board.
229141586Simp	 */
230141586Simp	ed_nic_outb(sc, ED_P0_DCR, 0);
231141586Simp
232141586Simp	/*
233141586Simp	 * select page 2 registers
234141586Simp	 */
235260050Smarius	ed_nic_barrier(sc, ED_P0_CR, 1,
236260050Smarius	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
237141586Simp	ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_2 | ED_CR_RD2 | ED_CR_STP);
238260050Smarius	ed_nic_barrier(sc, ED_P0_CR, 1,
239260050Smarius	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
240141586Simp
241141586Simp	/*
242141586Simp	 * The 3c503 forces the WTS bit to a one if this is a 16bit board
243141586Simp	 */
244141586Simp	if (ed_nic_inb(sc, ED_P2_DCR) & ED_DCR_WTS)
245141586Simp		isa16bit = 1;
246141586Simp	else
247141586Simp		isa16bit = 0;
248141586Simp
249141586Simp	/*
250141586Simp	 * select page 0 registers
251141586Simp	 */
252141586Simp	ed_nic_outb(sc, ED_P2_CR, ED_CR_RD2 | ED_CR_STP);
253141586Simp
254141586Simp	error = ed_alloc_memory(dev, 0, memsize);
255141586Simp	if (error)
256141586Simp		return (error);
257141586Simp
258141586Simp	pmem = rman_get_start(sc->mem_res);
259141586Simp	error = ed_isa_mem_ok(dev, pmem, memsize);
260141586Simp	if (error)
261141586Simp		return (error);
262141586Simp
263149558Simp	sc->mem_start = 0;
264141586Simp	sc->mem_size = memsize;
265141586Simp	sc->mem_end = sc->mem_start + memsize;
266141586Simp
267141586Simp	/*
268141586Simp	 * We have an entire 8k window to put the transmit buffers on the
269141586Simp	 * 16bit boards. But since the 16bit 3c503's shared memory is only
270141586Simp	 * fast enough to overlap the loading of one full-size packet, trying
271141586Simp	 * to load more than 2 buffers can actually leave the transmitter idle
272141586Simp	 * during the load. So 2 seems the best value. (Although a mix of
273141586Simp	 * variable-sized packets might change this assumption. Nonetheless,
274141586Simp	 * we optimize for linear transfers of same-size packets.)
275141586Simp	 */
276141586Simp	if (isa16bit) {
277141586Simp		if (flags & ED_FLAGS_NO_MULTI_BUFFERING)
278141586Simp			sc->txb_cnt = 1;
279141586Simp		else
280141586Simp			sc->txb_cnt = 2;
281141586Simp
282141586Simp		sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_16BIT;
283141586Simp		sc->rec_page_start = ED_3COM_RX_PAGE_OFFSET_16BIT;
284141586Simp		sc->rec_page_stop = memsize / ED_PAGE_SIZE +
285141586Simp		    ED_3COM_RX_PAGE_OFFSET_16BIT;
286141586Simp		sc->mem_ring = sc->mem_start;
287141586Simp	} else {
288141586Simp		sc->txb_cnt = 1;
289141586Simp		sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_8BIT;
290141586Simp		sc->rec_page_start = ED_TXBUF_SIZE + ED_3COM_TX_PAGE_OFFSET_8BIT;
291141586Simp		sc->rec_page_stop = memsize / ED_PAGE_SIZE +
292141586Simp		    ED_3COM_TX_PAGE_OFFSET_8BIT;
293141586Simp		sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE);
294141586Simp	}
295141586Simp
296141586Simp	sc->isa16bit = isa16bit;
297141586Simp
298141586Simp	/*
299141586Simp	 * Initialize GA page start/stop registers. Probably only needed if
300141586Simp	 * doing DMA, but what the hell.
301141586Simp	 */
302141586Simp	ed_asic_outb(sc, ED_3COM_PSTR, sc->rec_page_start);
303141586Simp	ed_asic_outb(sc, ED_3COM_PSPR, sc->rec_page_stop);
304141586Simp
305141586Simp	/*
306141586Simp	 * Set IRQ. 3c503 only allows a choice of irq 2-5.
307141586Simp	 */
308141586Simp	error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
309141586Simp	if (error)
310141586Simp		return (error);
311141586Simp
312141586Simp	switch (irq) {
313141586Simp	case 2:
314141586Simp	case 9:
315141586Simp		ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
316141586Simp		break;
317141586Simp	case 3:
318141586Simp		ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
319141586Simp		break;
320141586Simp	case 4:
321141586Simp		ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
322141586Simp		break;
323141586Simp	case 5:
324141586Simp		ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
325141586Simp		break;
326141586Simp	default:
327297000Sjhibbits		device_printf(dev, "Invalid irq configuration (%jd) must be 3-5,9 for 3c503\n",
328141586Simp			      irq);
329141586Simp		return (ENXIO);
330141586Simp	}
331141586Simp
332141586Simp	/*
333141586Simp	 * Initialize GA configuration register. Set bank and enable shared
334141586Simp	 * mem.
335141586Simp	 */
336141586Simp	ed_asic_outb(sc, ED_3COM_GACFR, ED_3COM_GACFR_RSEL |
337154924Simp	    ED_3COM_GACFR_MBS0);
338141586Simp
339141586Simp	/*
340141586Simp	 * Initialize "Vector Pointer" registers. These gawd-awful things are
341141586Simp	 * compared to 20 bits of the address on ISA, and if they match, the
342141586Simp	 * shared memory is disabled. We set them to 0xffff0...allegedly the
343141586Simp	 * reset vector.
344141586Simp	 */
345141586Simp	ed_asic_outb(sc, ED_3COM_VPTR2, 0xff);
346141586Simp	ed_asic_outb(sc, ED_3COM_VPTR1, 0xff);
347141586Simp	ed_asic_outb(sc, ED_3COM_VPTR0, 0x00);
348141586Simp
349154895Simp	error = ed_clear_memory(dev);
350154924Simp	if (error == 0) {
351154895Simp		sc->sc_mediachg = ed_3c503_mediachg;
352154924Simp		sc->sc_write_mbufs = ed_shmem_write_mbufs;
353154924Simp	}
354154895Simp	return (error);
355141586Simp}
356141586Simp
357154895Simpstatic void
358154895Simped_3c503_mediachg(struct ed_softc *sc)
359154895Simp{
360154895Simp	struct ifnet *ifp = sc->ifp;
361154895Simp
362154895Simp	/*
363154895Simp	 * If this is a 3Com board, the tranceiver must be software enabled
364154895Simp	 * (there is no settable hardware default).
365154895Simp	 */
366154895Simp	if (ifp->if_flags & IFF_LINK2)
367154895Simp		ed_asic_outb(sc, ED_3COM_CR, 0);
368154895Simp	else
369154895Simp		ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
370154895Simp}
371154895Simp
372141586Simp#endif /* ED_3C503 */
373