1/*	$NetBSD: if_le.c,v 1.36 2010/01/19 22:06:23 pooka Exp $	*/
2
3/*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*-
34 * Copyright (c) 1992, 1993
35 *	The Regents of the University of California.  All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * Ralph Campbell and Rick Macklem.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 *    notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 *    notice, this list of conditions and the following disclaimer in the
47 *    documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 *    may be used to endorse or promote products derived from this software
50 *    without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 *	@(#)if_le.c	8.2 (Berkeley) 11/16/93
65 */
66
67#include <sys/cdefs.h>
68__KERNEL_RCSID(0, "$NetBSD: if_le.c,v 1.36 2010/01/19 22:06:23 pooka Exp $");
69
70#include "opt_inet.h"
71
72#include <sys/param.h>
73#include <sys/cpu.h>
74#include <sys/device.h>
75#include <sys/syslog.h>
76#include <sys/socket.h>
77
78#include <uvm/uvm_extern.h>
79
80#include <net/if.h>
81#include <net/if_ether.h>
82#include <net/if_media.h>
83
84#ifdef INET
85#include <netinet/in.h>
86#include <netinet/if_inarp.h>
87#endif
88
89#include <machine/nexus.h>
90#include <machine/scb.h>
91#include <machine/mainbus.h>
92
93#include <dev/ic/lancereg.h>
94#include <dev/ic/lancevar.h>
95#include <dev/ic/am7990reg.h>
96#include <dev/ic/am7990var.h>
97
98#include "ioconf.h"
99
100#define	LE_VEC	0xd4	/* Interrupt vector on 3300/3400 */
101
102#define	LE_CSR	0x20084400
103#define	LE_ROM	0x20084200
104#define	LE_RAM	0x20120000
105
106struct le_softc {
107	struct	am7990_softc sc_am7990; /* Must be first */
108	struct	evcnt sc_intrcnt;
109	volatile uint16_t *sc_rap;
110	volatile uint16_t *sc_rdp;
111};
112
113static int	le_mainbus_match(device_t, cfdata_t, void *);
114static void	le_mainbus_attach(device_t, device_t, void *);
115static void	lewrcsr(struct lance_softc *, uint16_t, uint16_t);
116static uint16_t lerdcsr(struct lance_softc *, uint16_t);
117static void	lance_copytobuf_gap2(struct lance_softc *, void *, int, int);
118static void	lance_copyfrombuf_gap2(struct lance_softc *, void *, int, int);
119static void	lance_zerobuf_gap2(struct lance_softc *, int, int);
120
121CFATTACH_DECL_NEW(le_mainbus, sizeof(struct le_softc),
122    le_mainbus_match, le_mainbus_attach, NULL, NULL);
123
124void
125lewrcsr(struct lance_softc *ls, uint16_t port, uint16_t val)
126{
127	struct le_softc * const sc = (void *)ls;
128
129	*sc->sc_rap = port;
130	*sc->sc_rdp = val;
131}
132
133uint16_t
134lerdcsr(struct lance_softc *ls, uint16_t port)
135{
136	struct le_softc * const sc = (void *)ls;
137
138	*sc->sc_rap = port;
139	return *sc->sc_rdp;
140}
141
142int
143le_mainbus_match(device_t parent, cfdata_t cf, void *aux)
144{
145	struct mainbus_attach_args * const ma = aux;
146	int found;
147	vaddr_t va;
148
149	if (strcmp("lance", ma->ma_type))
150		return 0;
151
152	va = vax_map_physmem(LE_CSR, 1);
153	found = (badaddr((void *)va, 2) == 0);
154	vax_unmap_physmem(va, 1);
155
156	return found;
157}
158
159void
160le_mainbus_attach(device_t parent, device_t self, void *aux)
161{
162	struct le_softc * const sc = device_private(self);
163	int *lance_addr;
164	int i, vec, br;
165
166	sc->sc_am7990.lsc.sc_dev = self;
167	sc->sc_rdp = (uint16_t *)vax_map_physmem(LE_CSR, 1);
168	sc->sc_rap = sc->sc_rdp + 2;
169
170	/*
171	 * Set interrupt vector, by forcing an interrupt.
172	 */
173	scb_vecref(0, 0); /* Clear vector ref */
174	*sc->sc_rap = LE_CSR0;
175	*sc->sc_rdp = LE_C0_STOP;
176	DELAY(100);
177	*sc->sc_rdp = LE_C0_INIT|LE_C0_INEA;
178	DELAY(100000);
179	i = scb_vecref(&vec, &br);
180	if (i == 0 || vec == 0)
181		return;
182
183	scb_vecalloc(vec, (void (*)(void *))am7990_intr, sc,
184		SCB_ISTACK, &sc->sc_intrcnt);
185	evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
186		device_xname(self), "intr");
187
188	aprint_normal(": vec %o ipl %x\n%s", vec, br, device_xname(self));
189	/*
190	 * MD functions.
191	 */
192	sc->sc_am7990.lsc.sc_rdcsr = lerdcsr;
193	sc->sc_am7990.lsc.sc_wrcsr = lewrcsr;
194	sc->sc_am7990.lsc.sc_nocarrier = NULL;
195
196	sc->sc_am7990.lsc.sc_mem =
197	    (void *)uvm_km_alloc(kernel_map, (128 * 1024), 0, UVM_KMF_VAONLY);
198	if (sc->sc_am7990.lsc.sc_mem == 0)
199		return;
200
201	ioaccess((vaddr_t)sc->sc_am7990.lsc.sc_mem, LE_RAM,
202	    (128 * 1024) >> VAX_PGSHIFT);
203
204
205	sc->sc_am7990.lsc.sc_addr = 0;
206	sc->sc_am7990.lsc.sc_memsize = (64 * 1024);
207
208	sc->sc_am7990.lsc.sc_copytodesc = lance_copytobuf_gap2;
209	sc->sc_am7990.lsc.sc_copyfromdesc = lance_copyfrombuf_gap2;
210	sc->sc_am7990.lsc.sc_copytobuf = lance_copytobuf_gap2;
211	sc->sc_am7990.lsc.sc_copyfrombuf = lance_copyfrombuf_gap2;
212	sc->sc_am7990.lsc.sc_zerobuf = lance_zerobuf_gap2;
213
214	/*
215	 * Get the ethernet address out of rom
216	 */
217	lance_addr = (int *)vax_map_physmem(LE_ROM, 1);
218	for (i = 0; i < 6; i++)
219		sc->sc_am7990.lsc.sc_enaddr[i] = (u_char)lance_addr[i];
220	vax_unmap_physmem((vaddr_t)lance_addr, 1);
221
222	memcpy(sc->sc_am7990.lsc.sc_ethercom.ec_if.if_xname, device_xname(self),
223	    IFNAMSIZ);
224	am7990_config(&sc->sc_am7990);
225}
226
227/*
228 * gap2: two bytes of data followed by two bytes of pad.
229 *
230 * Buffers must be 4-byte aligned.  The code doesn't worry about
231 * doing an extra byte.
232 */
233
234void
235lance_copytobuf_gap2(struct lance_softc *sc, void *fromv, int boff, int len)
236{
237	volatile void *buf = sc->sc_mem;
238	char *from = fromv;
239	volatile uint16_t *bptr;
240
241	if (boff & 0x1) {
242		/* handle unaligned first byte */
243		bptr = ((volatile uint16_t *)buf) + (boff - 1);
244		*bptr = (*from++ << 8) | (*bptr & 0xff);
245		bptr += 2;
246		len--;
247	} else
248		bptr = ((volatile uint16_t *)buf) + boff;
249	while (len > 1) {
250		*bptr = (from[1] << 8) | (from[0] & 0xff);
251		bptr += 2;
252		from += 2;
253		len -= 2;
254	}
255	if (len == 1)
256		*bptr = (uint16_t)*from;
257}
258
259void
260lance_copyfrombuf_gap2(struct lance_softc *sc, void *tov, int boff, int len)
261{
262	volatile void *buf = sc->sc_mem;
263	char *to = tov;
264	volatile uint16_t *bptr;
265	uint16_t tmp;
266
267	if (boff & 0x1) {
268		/* handle unaligned first byte */
269		bptr = ((volatile uint16_t *)buf) + (boff - 1);
270		*to++ = (*bptr >> 8) & 0xff;
271		bptr += 2;
272		len--;
273	} else
274		bptr = ((volatile uint16_t *)buf) + boff;
275	while (len > 1) {
276		tmp = *bptr;
277		*to++ = tmp & 0xff;
278		*to++ = (tmp >> 8) & 0xff;
279		bptr += 2;
280		len -= 2;
281	}
282	if (len == 1)
283		*to = *bptr & 0xff;
284}
285
286void
287lance_zerobuf_gap2(struct lance_softc *sc, int boff, int len)
288{
289	volatile void *buf = sc->sc_mem;
290	volatile uint16_t *bptr;
291
292	if ((unsigned int)boff & 0x1) {
293		bptr = ((volatile uint16_t *)buf) + (boff - 1);
294		*bptr &= 0xff;
295		bptr += 2;
296		len--;
297	} else
298		bptr = ((volatile uint16_t *)buf) + boff;
299	while (len > 0) {
300		*bptr = 0;
301		bptr += 2;
302		len -= 2;
303	}
304}
305