xref: /dflybsd-src/sys/dev/netif/lnc/lance.c (revision c443c74f42cc6a7f2385d56cc2b07c21939330d1)
1cfa96c6cSSepherosa Ziehau /*	$NetBSD: lance.c,v 1.34 2005/12/24 20:27:30 perry Exp $	*/
2cfa96c6cSSepherosa Ziehau /*	$FreeBSD: src/sys/dev/le/lance.c,v 1.2 2006/05/16 21:04:01 marius Exp $	*/
3cfa96c6cSSepherosa Ziehau 
4cfa96c6cSSepherosa Ziehau 
5cfa96c6cSSepherosa Ziehau /*-
6cfa96c6cSSepherosa Ziehau  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
7cfa96c6cSSepherosa Ziehau  * All rights reserved.
8cfa96c6cSSepherosa Ziehau  *
9cfa96c6cSSepherosa Ziehau  * This code is derived from software contributed to The NetBSD Foundation
10cfa96c6cSSepherosa Ziehau  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
11cfa96c6cSSepherosa Ziehau  * Simulation Facility, NASA Ames Research Center.
12cfa96c6cSSepherosa Ziehau  *
13cfa96c6cSSepherosa Ziehau  * Redistribution and use in source and binary forms, with or without
14cfa96c6cSSepherosa Ziehau  * modification, are permitted provided that the following conditions
15cfa96c6cSSepherosa Ziehau  * are met:
16cfa96c6cSSepherosa Ziehau  * 1. Redistributions of source code must retain the above copyright
17cfa96c6cSSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer.
18cfa96c6cSSepherosa Ziehau  * 2. Redistributions in binary form must reproduce the above copyright
19cfa96c6cSSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer in the
20cfa96c6cSSepherosa Ziehau  *    documentation and/or other materials provided with the distribution.
21cfa96c6cSSepherosa Ziehau  * 3. All advertising materials mentioning features or use of this software
22cfa96c6cSSepherosa Ziehau  *    must display the following acknowledgement:
23cfa96c6cSSepherosa Ziehau  *	This product includes software developed by the NetBSD
24cfa96c6cSSepherosa Ziehau  *	Foundation, Inc. and its contributors.
25cfa96c6cSSepherosa Ziehau  * 4. Neither the name of The NetBSD Foundation nor the names of its
26cfa96c6cSSepherosa Ziehau  *    contributors may be used to endorse or promote products derived
27cfa96c6cSSepherosa Ziehau  *    from this software without specific prior written permission.
28cfa96c6cSSepherosa Ziehau  *
29cfa96c6cSSepherosa Ziehau  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30cfa96c6cSSepherosa Ziehau  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31cfa96c6cSSepherosa Ziehau  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32cfa96c6cSSepherosa Ziehau  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33cfa96c6cSSepherosa Ziehau  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34cfa96c6cSSepherosa Ziehau  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35cfa96c6cSSepherosa Ziehau  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36cfa96c6cSSepherosa Ziehau  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37cfa96c6cSSepherosa Ziehau  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38cfa96c6cSSepherosa Ziehau  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39cfa96c6cSSepherosa Ziehau  * POSSIBILITY OF SUCH DAMAGE.
40cfa96c6cSSepherosa Ziehau  */
41cfa96c6cSSepherosa Ziehau 
42cfa96c6cSSepherosa Ziehau /*-
43cfa96c6cSSepherosa Ziehau  * Copyright (c) 1992, 1993
44cfa96c6cSSepherosa Ziehau  *	The Regents of the University of California.  All rights reserved.
45cfa96c6cSSepherosa Ziehau  *
46cfa96c6cSSepherosa Ziehau  * This code is derived from software contributed to Berkeley by
47cfa96c6cSSepherosa Ziehau  * Ralph Campbell and Rick Macklem.
48cfa96c6cSSepherosa Ziehau  *
49cfa96c6cSSepherosa Ziehau  * Redistribution and use in source and binary forms, with or without
50cfa96c6cSSepherosa Ziehau  * modification, are permitted provided that the following conditions
51cfa96c6cSSepherosa Ziehau  * are met:
52cfa96c6cSSepherosa Ziehau  * 1. Redistributions of source code must retain the above copyright
53cfa96c6cSSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer.
54cfa96c6cSSepherosa Ziehau  * 2. Redistributions in binary form must reproduce the above copyright
55cfa96c6cSSepherosa Ziehau  *    notice, this list of conditions and the following disclaimer in the
56cfa96c6cSSepherosa Ziehau  *    documentation and/or other materials provided with the distribution.
57cfa96c6cSSepherosa Ziehau  * 3. Neither the name of the University nor the names of its contributors
58cfa96c6cSSepherosa Ziehau  *    may be used to endorse or promote products derived from this software
59cfa96c6cSSepherosa Ziehau  *    without specific prior written permission.
60cfa96c6cSSepherosa Ziehau  *
61cfa96c6cSSepherosa Ziehau  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62cfa96c6cSSepherosa Ziehau  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63cfa96c6cSSepherosa Ziehau  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64cfa96c6cSSepherosa Ziehau  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65cfa96c6cSSepherosa Ziehau  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66cfa96c6cSSepherosa Ziehau  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67cfa96c6cSSepherosa Ziehau  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68cfa96c6cSSepherosa Ziehau  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69cfa96c6cSSepherosa Ziehau  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70cfa96c6cSSepherosa Ziehau  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71cfa96c6cSSepherosa Ziehau  * SUCH DAMAGE.
72cfa96c6cSSepherosa Ziehau  *
73cfa96c6cSSepherosa Ziehau  *	@(#)if_le.c	8.2 (Berkeley) 11/16/93
74cfa96c6cSSepherosa Ziehau  */
75cfa96c6cSSepherosa Ziehau 
76cfa96c6cSSepherosa Ziehau #include <sys/param.h>
77cfa96c6cSSepherosa Ziehau #include <sys/bus.h>
78cfa96c6cSSepherosa Ziehau #include <sys/endian.h>
79cfa96c6cSSepherosa Ziehau #include <sys/lock.h>
80*c443c74fSzrj #include <sys/malloc.h>	/* for M_NOWAIT */
81cfa96c6cSSepherosa Ziehau #include <sys/mbuf.h>
82cfa96c6cSSepherosa Ziehau #include <sys/socket.h>
83cfa96c6cSSepherosa Ziehau #include <sys/sockio.h>
84cfa96c6cSSepherosa Ziehau 
85cfa96c6cSSepherosa Ziehau #include <net/ethernet.h>
86cfa96c6cSSepherosa Ziehau #include <net/if.h>
87cfa96c6cSSepherosa Ziehau #include <net/ifq_var.h>
88cfa96c6cSSepherosa Ziehau #include <net/if_arp.h>
89cfa96c6cSSepherosa Ziehau #include <net/if_dl.h>
90cfa96c6cSSepherosa Ziehau #include <net/if_media.h>
91cfa96c6cSSepherosa Ziehau #include <net/if_types.h>
92cfa96c6cSSepherosa Ziehau #include <net/vlan/if_vlan_var.h>
93cfa96c6cSSepherosa Ziehau 
94cfa96c6cSSepherosa Ziehau #include <dev/netif/lnc/lancereg.h>
95cfa96c6cSSepherosa Ziehau #include <dev/netif/lnc/lancevar.h>
96cfa96c6cSSepherosa Ziehau 
97cfa96c6cSSepherosa Ziehau devclass_t le_devclass;
98cfa96c6cSSepherosa Ziehau 
99f0a26983SSepherosa Ziehau static void lance_start(struct ifnet *, struct ifaltq_subque *);
100cfa96c6cSSepherosa Ziehau static void lance_init(void *);
101cfa96c6cSSepherosa Ziehau static void lance_watchdog(struct ifnet *);
102cfa96c6cSSepherosa Ziehau static int lance_mediachange(struct ifnet *);
103cfa96c6cSSepherosa Ziehau static void lance_mediastatus(struct ifnet *, struct ifmediareq *);
104cfa96c6cSSepherosa Ziehau static int lance_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
105cfa96c6cSSepherosa Ziehau 
106e7a56c3eSSepherosa Ziehau void
lance_config(struct lance_softc * sc,const char * name,int unit)107cfa96c6cSSepherosa Ziehau lance_config(struct lance_softc *sc, const char* name, int unit)
108cfa96c6cSSepherosa Ziehau {
109cfa96c6cSSepherosa Ziehau 	struct ifnet *ifp;
110cfa96c6cSSepherosa Ziehau 	int i, nbuf;
111cfa96c6cSSepherosa Ziehau 
112cfa96c6cSSepherosa Ziehau 	ifp = sc->ifp = &sc->sc_if;
113cfa96c6cSSepherosa Ziehau 
114cfa96c6cSSepherosa Ziehau 	/* Initialize ifnet structure. */
115cfa96c6cSSepherosa Ziehau 	ifp->if_softc = sc;
116cfa96c6cSSepherosa Ziehau 	if_initname(ifp, name, unit);
117cfa96c6cSSepherosa Ziehau 	ifp->if_start = lance_start;
118cfa96c6cSSepherosa Ziehau 	ifp->if_ioctl = lance_ioctl;
119cfa96c6cSSepherosa Ziehau 	ifp->if_watchdog = lance_watchdog;
120cfa96c6cSSepherosa Ziehau 	ifp->if_init = lance_init;
121cfa96c6cSSepherosa Ziehau 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
122cfa96c6cSSepherosa Ziehau #ifdef LANCE_REVC_BUG
123cfa96c6cSSepherosa Ziehau 	ifp->if_flags &= ~IFF_MULTICAST;
124cfa96c6cSSepherosa Ziehau #endif
125cfa96c6cSSepherosa Ziehau 	ifp->if_baudrate = IF_Mbps(10);
126cfa96c6cSSepherosa Ziehau 	ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
127cfa96c6cSSepherosa Ziehau 	ifq_set_ready(&ifp->if_snd);
128cfa96c6cSSepherosa Ziehau 
129e7a56c3eSSepherosa Ziehau 	/* Attach the interface. */
130e7a56c3eSSepherosa Ziehau 	ether_ifattach(ifp, sc->sc_enaddr, NULL);
131e7a56c3eSSepherosa Ziehau 
132e7a56c3eSSepherosa Ziehau 	/* Claim 802.1q capability. */
133e7a56c3eSSepherosa Ziehau 	ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
134e7a56c3eSSepherosa Ziehau 	ifp->if_capabilities |= IFCAP_VLAN_MTU;
135e7a56c3eSSepherosa Ziehau 	ifp->if_capenable |= IFCAP_VLAN_MTU;
136e7a56c3eSSepherosa Ziehau 
137cfa96c6cSSepherosa Ziehau 	/* Initialize ifmedia structures. */
138cfa96c6cSSepherosa Ziehau 	ifmedia_init(&sc->sc_media, 0, lance_mediachange, lance_mediastatus);
139cfa96c6cSSepherosa Ziehau 	if (sc->sc_supmedia != NULL) {
140cfa96c6cSSepherosa Ziehau 		for (i = 0; i < sc->sc_nsupmedia; i++)
141cfa96c6cSSepherosa Ziehau 			ifmedia_add(&sc->sc_media, sc->sc_supmedia[i], 0, NULL);
142cfa96c6cSSepherosa Ziehau 		ifmedia_set(&sc->sc_media, sc->sc_defaultmedia);
143cfa96c6cSSepherosa Ziehau 	} else {
144cfa96c6cSSepherosa Ziehau 		ifmedia_add(&sc->sc_media,
145cfa96c6cSSepherosa Ziehau 		    IFM_MAKEWORD(IFM_ETHER, IFM_MANUAL, 0, 0), 0, NULL);
146cfa96c6cSSepherosa Ziehau 		ifmedia_set(&sc->sc_media,
147cfa96c6cSSepherosa Ziehau 		    IFM_MAKEWORD(IFM_ETHER, IFM_MANUAL, 0, 0));
148cfa96c6cSSepherosa Ziehau 	}
149cfa96c6cSSepherosa Ziehau 
150cfa96c6cSSepherosa Ziehau 	switch (sc->sc_memsize) {
151cfa96c6cSSepherosa Ziehau 	case 8192:
152cfa96c6cSSepherosa Ziehau 		sc->sc_nrbuf = 4;
153cfa96c6cSSepherosa Ziehau 		sc->sc_ntbuf = 1;
154cfa96c6cSSepherosa Ziehau 		break;
155cfa96c6cSSepherosa Ziehau 	case 16384:
156cfa96c6cSSepherosa Ziehau 		sc->sc_nrbuf = 8;
157cfa96c6cSSepherosa Ziehau 		sc->sc_ntbuf = 2;
158cfa96c6cSSepherosa Ziehau 		break;
159cfa96c6cSSepherosa Ziehau 	case 32768:
160cfa96c6cSSepherosa Ziehau 		sc->sc_nrbuf = 16;
161cfa96c6cSSepherosa Ziehau 		sc->sc_ntbuf = 4;
162cfa96c6cSSepherosa Ziehau 		break;
163cfa96c6cSSepherosa Ziehau 	case 65536:
164cfa96c6cSSepherosa Ziehau 		sc->sc_nrbuf = 32;
165cfa96c6cSSepherosa Ziehau 		sc->sc_ntbuf = 8;
166cfa96c6cSSepherosa Ziehau 		break;
167cfa96c6cSSepherosa Ziehau 	case 131072:
168cfa96c6cSSepherosa Ziehau 		sc->sc_nrbuf = 64;
169cfa96c6cSSepherosa Ziehau 		sc->sc_ntbuf = 16;
170cfa96c6cSSepherosa Ziehau 		break;
171cfa96c6cSSepherosa Ziehau 	case 262144:
172cfa96c6cSSepherosa Ziehau 		sc->sc_nrbuf = 128;
173cfa96c6cSSepherosa Ziehau 		sc->sc_ntbuf = 32;
174cfa96c6cSSepherosa Ziehau 		break;
175cfa96c6cSSepherosa Ziehau 	default:
176cfa96c6cSSepherosa Ziehau 		/* weird memory size; cope with it */
177cfa96c6cSSepherosa Ziehau 		nbuf = sc->sc_memsize / LEBLEN;
178cfa96c6cSSepherosa Ziehau 		sc->sc_ntbuf = nbuf / 5;
179cfa96c6cSSepherosa Ziehau 		sc->sc_nrbuf = nbuf - sc->sc_ntbuf;
180cfa96c6cSSepherosa Ziehau 	}
181cfa96c6cSSepherosa Ziehau 
182cfa96c6cSSepherosa Ziehau 	if_printf(ifp, "%d receive buffers, %d transmit buffers\n",
183cfa96c6cSSepherosa Ziehau 	    sc->sc_nrbuf, sc->sc_ntbuf);
184cfa96c6cSSepherosa Ziehau 
185cfa96c6cSSepherosa Ziehau 	/* Make sure the chip is stopped. */
186cfa96c6cSSepherosa Ziehau 	lance_stop(sc);
187cfa96c6cSSepherosa Ziehau }
188cfa96c6cSSepherosa Ziehau 
189cfa96c6cSSepherosa Ziehau void
lance_suspend(struct lance_softc * sc)190cfa96c6cSSepherosa Ziehau lance_suspend(struct lance_softc *sc)
191cfa96c6cSSepherosa Ziehau {
192cfa96c6cSSepherosa Ziehau 
193cfa96c6cSSepherosa Ziehau 	lwkt_serialize_enter(sc->ifp->if_serializer);
194cfa96c6cSSepherosa Ziehau 	lance_stop(sc);
195cfa96c6cSSepherosa Ziehau 	lwkt_serialize_exit(sc->ifp->if_serializer);
196cfa96c6cSSepherosa Ziehau }
197cfa96c6cSSepherosa Ziehau 
198cfa96c6cSSepherosa Ziehau void
lance_resume(struct lance_softc * sc)199cfa96c6cSSepherosa Ziehau lance_resume(struct lance_softc *sc)
200cfa96c6cSSepherosa Ziehau {
201cfa96c6cSSepherosa Ziehau 
202cfa96c6cSSepherosa Ziehau 	lwkt_serialize_enter(sc->ifp->if_serializer);
203cfa96c6cSSepherosa Ziehau 	if (sc->ifp->if_flags & IFF_UP)
204cfa96c6cSSepherosa Ziehau 		lance_init_locked(sc);
205cfa96c6cSSepherosa Ziehau 	lwkt_serialize_exit(sc->ifp->if_serializer);
206cfa96c6cSSepherosa Ziehau }
207cfa96c6cSSepherosa Ziehau 
208cfa96c6cSSepherosa Ziehau static void
lance_start(struct ifnet * ifp,struct ifaltq_subque * ifsq)209f0a26983SSepherosa Ziehau lance_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
210cfa96c6cSSepherosa Ziehau {
211cfa96c6cSSepherosa Ziehau 	struct lance_softc *sc = ifp->if_softc;
212cfa96c6cSSepherosa Ziehau 
213f0a26983SSepherosa Ziehau 	ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
214cfa96c6cSSepherosa Ziehau 	(*sc->sc_start_locked)(sc);
215cfa96c6cSSepherosa Ziehau }
216cfa96c6cSSepherosa Ziehau 
217cfa96c6cSSepherosa Ziehau void
lance_stop(struct lance_softc * sc)218cfa96c6cSSepherosa Ziehau lance_stop(struct lance_softc *sc)
219cfa96c6cSSepherosa Ziehau {
220cfa96c6cSSepherosa Ziehau 	struct ifnet *ifp = sc->ifp;
221cfa96c6cSSepherosa Ziehau 
222cfa96c6cSSepherosa Ziehau 	/*
223cfa96c6cSSepherosa Ziehau 	 * Mark the interface down and cancel the watchdog timer.
224cfa96c6cSSepherosa Ziehau 	 */
2259ed293e0SSepherosa Ziehau 	ifp->if_flags &= ~IFF_RUNNING;
2269ed293e0SSepherosa Ziehau 	ifq_clr_oactive(&ifp->if_snd);
227cfa96c6cSSepherosa Ziehau 	ifp->if_timer = 0;
228cfa96c6cSSepherosa Ziehau 
229cfa96c6cSSepherosa Ziehau 	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
230cfa96c6cSSepherosa Ziehau }
231cfa96c6cSSepherosa Ziehau 
232cfa96c6cSSepherosa Ziehau static void
lance_init(void * xsc)233cfa96c6cSSepherosa Ziehau lance_init(void *xsc)
234cfa96c6cSSepherosa Ziehau {
235cfa96c6cSSepherosa Ziehau 	struct lance_softc *sc = (struct lance_softc *)xsc;
236cfa96c6cSSepherosa Ziehau 
237cfa96c6cSSepherosa Ziehau 	crit_enter();
238cfa96c6cSSepherosa Ziehau 	lance_init_locked(sc);
239cfa96c6cSSepherosa Ziehau 	crit_exit();
240cfa96c6cSSepherosa Ziehau }
241cfa96c6cSSepherosa Ziehau 
242cfa96c6cSSepherosa Ziehau /*
243cfa96c6cSSepherosa Ziehau  * Initialization of interface; set up initialization block
244cfa96c6cSSepherosa Ziehau  * and transmit/receive descriptor rings.
245cfa96c6cSSepherosa Ziehau  */
246cfa96c6cSSepherosa Ziehau void
lance_init_locked(struct lance_softc * sc)247cfa96c6cSSepherosa Ziehau lance_init_locked(struct lance_softc *sc)
248cfa96c6cSSepherosa Ziehau {
249cfa96c6cSSepherosa Ziehau 	struct ifnet *ifp = sc->ifp;
250cfa96c6cSSepherosa Ziehau 	u_long a;
251cfa96c6cSSepherosa Ziehau 	int timo;
252cfa96c6cSSepherosa Ziehau 
253cfa96c6cSSepherosa Ziehau 	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
254cfa96c6cSSepherosa Ziehau 	DELAY(100);
255cfa96c6cSSepherosa Ziehau 
256cfa96c6cSSepherosa Ziehau 	/* Newer LANCE chips have a reset register. */
257cfa96c6cSSepherosa Ziehau 	if (sc->sc_hwreset)
258cfa96c6cSSepherosa Ziehau 		(*sc->sc_hwreset)(sc);
259cfa96c6cSSepherosa Ziehau 
260cfa96c6cSSepherosa Ziehau 	/* Set the correct byte swapping mode, etc. */
261cfa96c6cSSepherosa Ziehau 	(*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
262cfa96c6cSSepherosa Ziehau 
263cfa96c6cSSepherosa Ziehau 	/*
264cfa96c6cSSepherosa Ziehau 	 * Update our private copy of the Ethernet address.
265cfa96c6cSSepherosa Ziehau 	 * We NEED the copy so we can ensure its alignment!
266cfa96c6cSSepherosa Ziehau 	 */
267cfa96c6cSSepherosa Ziehau 	memcpy(sc->sc_enaddr, IF_LLADDR(ifp), ETHER_ADDR_LEN);
268cfa96c6cSSepherosa Ziehau 
269cfa96c6cSSepherosa Ziehau 	/* Set up LANCE init block. */
270cfa96c6cSSepherosa Ziehau 	(*sc->sc_meminit)(sc);
271cfa96c6cSSepherosa Ziehau 
272cfa96c6cSSepherosa Ziehau 	/* Give LANCE the physical address of its init block. */
273cfa96c6cSSepherosa Ziehau 	a = sc->sc_addr + LE_INITADDR(sc);
274cfa96c6cSSepherosa Ziehau 	(*sc->sc_wrcsr)(sc, LE_CSR1, a & 0xffff);
275cfa96c6cSSepherosa Ziehau 	(*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);
276cfa96c6cSSepherosa Ziehau 
277cfa96c6cSSepherosa Ziehau 	/* Try to initialize the LANCE. */
278cfa96c6cSSepherosa Ziehau 	DELAY(100);
279cfa96c6cSSepherosa Ziehau 	(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);
280cfa96c6cSSepherosa Ziehau 
281cfa96c6cSSepherosa Ziehau 	/* Wait for initialization to finish. */
282cfa96c6cSSepherosa Ziehau 	for (timo = 100000; timo; timo--)
283cfa96c6cSSepherosa Ziehau 		if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
284cfa96c6cSSepherosa Ziehau 			break;
285cfa96c6cSSepherosa Ziehau 
286cfa96c6cSSepherosa Ziehau 	/* Set the current media. */
287cfa96c6cSSepherosa Ziehau 	if (sc->sc_mediachange)
2887b9f668cSSascha Wildner 		(*sc->sc_mediachange)(sc);
289cfa96c6cSSepherosa Ziehau 
290cfa96c6cSSepherosa Ziehau 	if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
291cfa96c6cSSepherosa Ziehau 		/* Start the LANCE. */
292cfa96c6cSSepherosa Ziehau 		(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT);
293cfa96c6cSSepherosa Ziehau 		ifp->if_flags |= IFF_RUNNING;
2949ed293e0SSepherosa Ziehau 		ifq_clr_oactive(&ifp->if_snd);
295cfa96c6cSSepherosa Ziehau 		ifp->if_timer = 0;
2969db4b353SSepherosa Ziehau 		if_devstart(ifp);
297cfa96c6cSSepherosa Ziehau 	} else
298cfa96c6cSSepherosa Ziehau 		if_printf(ifp, "controller failed to initialize\n");
299cfa96c6cSSepherosa Ziehau 
300cfa96c6cSSepherosa Ziehau 	if (sc->sc_hwinit)
301cfa96c6cSSepherosa Ziehau 		(*sc->sc_hwinit)(sc);
302cfa96c6cSSepherosa Ziehau }
303cfa96c6cSSepherosa Ziehau 
304cfa96c6cSSepherosa Ziehau /*
305cfa96c6cSSepherosa Ziehau  * Routine to copy from mbuf chain to transmit buffer in
306cfa96c6cSSepherosa Ziehau  * network buffer memory.
307cfa96c6cSSepherosa Ziehau  */
308cfa96c6cSSepherosa Ziehau int
lance_put(struct lance_softc * sc,int boff,struct mbuf * m)309cfa96c6cSSepherosa Ziehau lance_put(struct lance_softc *sc, int boff, struct mbuf *m)
310cfa96c6cSSepherosa Ziehau {
311b8f5d60dSJeffrey Hsu 	int tlen = 0;
312cfa96c6cSSepherosa Ziehau 
313b8f5d60dSJeffrey Hsu 	for (; m; m = m_free(m)) {
314b8f5d60dSJeffrey Hsu 		if (m->m_len == 0)
315cfa96c6cSSepherosa Ziehau 			continue;
316b8f5d60dSJeffrey Hsu 		(*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, m->m_len);
317b8f5d60dSJeffrey Hsu 		boff += m->m_len;
318b8f5d60dSJeffrey Hsu 		tlen += m->m_len;
319cfa96c6cSSepherosa Ziehau 	}
320cfa96c6cSSepherosa Ziehau 	if (tlen < LEMINSIZE) {
321cfa96c6cSSepherosa Ziehau 		(*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen);
322cfa96c6cSSepherosa Ziehau 		tlen = LEMINSIZE;
323cfa96c6cSSepherosa Ziehau 	}
324cfa96c6cSSepherosa Ziehau 	return (tlen);
325cfa96c6cSSepherosa Ziehau }
326cfa96c6cSSepherosa Ziehau 
327cfa96c6cSSepherosa Ziehau /*
328cfa96c6cSSepherosa Ziehau  * Pull data off an interface.
329cfa96c6cSSepherosa Ziehau  * Len is length of data, with local net header stripped.
330cfa96c6cSSepherosa Ziehau  * We copy the data into mbufs.  When full cluster sized units are present
331cfa96c6cSSepherosa Ziehau  * we copy into clusters.
332cfa96c6cSSepherosa Ziehau  */
333cfa96c6cSSepherosa Ziehau struct mbuf *
lance_get(struct lance_softc * sc,int boff,int totlen)334cfa96c6cSSepherosa Ziehau lance_get(struct lance_softc *sc, int boff, int totlen)
335cfa96c6cSSepherosa Ziehau {
336cfa96c6cSSepherosa Ziehau 	struct ifnet *ifp = sc->ifp;
337d35a95a4SJeffrey Hsu 	struct mbuf *m0 = NULL, *newm;
3385432735eSSimon Schubert 	struct mbuf *m = NULL;
339d35a95a4SJeffrey Hsu 	int mlen;
340cfa96c6cSSepherosa Ziehau 
341cfa96c6cSSepherosa Ziehau 	if (totlen <= ETHER_HDR_LEN || totlen > LEBLEN - ETHER_CRC_LEN) {
342cfa96c6cSSepherosa Ziehau #ifdef LEDEBUG
343cfa96c6cSSepherosa Ziehau 		if_printf(ifp, "invalid packet size %d; dropping\n", totlen);
344cfa96c6cSSepherosa Ziehau #endif
345cfa96c6cSSepherosa Ziehau 		return (NULL);
346cfa96c6cSSepherosa Ziehau 	}
347cfa96c6cSSepherosa Ziehau 
348d35a95a4SJeffrey Hsu 	do {
349b5523eacSSascha Wildner 		newm = m_getl(totlen, M_NOWAIT, MT_DATA,
350d35a95a4SJeffrey Hsu 			      m0 == NULL ? M_PKTHDR : 0, &mlen);
351d35a95a4SJeffrey Hsu 		if (newm == NULL)
352d35a95a4SJeffrey Hsu 			goto bad;
353d35a95a4SJeffrey Hsu 
354d35a95a4SJeffrey Hsu 		if (m0 == NULL) {
355d35a95a4SJeffrey Hsu 			caddr_t newdata;
356d35a95a4SJeffrey Hsu 
357d35a95a4SJeffrey Hsu 			m0 = newm;
358cfa96c6cSSepherosa Ziehau 			m0->m_pkthdr.rcvif = ifp;
359cfa96c6cSSepherosa Ziehau 			m0->m_pkthdr.len = totlen;
360cfa96c6cSSepherosa Ziehau 			newdata = (caddr_t)
361d35a95a4SJeffrey Hsu 			    ALIGN(m0->m_data + ETHER_HDR_LEN) - ETHER_HDR_LEN;
362d35a95a4SJeffrey Hsu 			mlen -= newdata - m0->m_data;
363d35a95a4SJeffrey Hsu 			m0->m_data = newdata;
364d35a95a4SJeffrey Hsu 		} else {
365d35a95a4SJeffrey Hsu 			m->m_next = newm;
366cfa96c6cSSepherosa Ziehau 		}
367d35a95a4SJeffrey Hsu 		m = newm;
368cfa96c6cSSepherosa Ziehau 
369d35a95a4SJeffrey Hsu 		m->m_len = min(totlen, mlen);
370d35a95a4SJeffrey Hsu 		(*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, m->m_len);
371d35a95a4SJeffrey Hsu 		boff += m->m_len;
372d35a95a4SJeffrey Hsu 		totlen -= m->m_len;
373d35a95a4SJeffrey Hsu 	} while (totlen > 0);
374cfa96c6cSSepherosa Ziehau 
375cfa96c6cSSepherosa Ziehau 	return (m0);
376cfa96c6cSSepherosa Ziehau 
377cfa96c6cSSepherosa Ziehau bad:
378cfa96c6cSSepherosa Ziehau 	m_freem(m0);
379cfa96c6cSSepherosa Ziehau 	return (NULL);
380cfa96c6cSSepherosa Ziehau }
381cfa96c6cSSepherosa Ziehau 
382cfa96c6cSSepherosa Ziehau static void
lance_watchdog(struct ifnet * ifp)383cfa96c6cSSepherosa Ziehau lance_watchdog(struct ifnet *ifp)
384cfa96c6cSSepherosa Ziehau {
385cfa96c6cSSepherosa Ziehau 	struct lance_softc *sc = ifp->if_softc;
386cfa96c6cSSepherosa Ziehau 
387cfa96c6cSSepherosa Ziehau 	if_printf(ifp, "device timeout\n");
388d40991efSSepherosa Ziehau 	IFNET_STAT_INC(ifp, oerrors, 1);
389cfa96c6cSSepherosa Ziehau 	lance_init_locked(sc);
390cfa96c6cSSepherosa Ziehau }
391cfa96c6cSSepherosa Ziehau 
392cfa96c6cSSepherosa Ziehau static int
lance_mediachange(struct ifnet * ifp)393cfa96c6cSSepherosa Ziehau lance_mediachange(struct ifnet *ifp)
394cfa96c6cSSepherosa Ziehau {
395cfa96c6cSSepherosa Ziehau 	struct lance_softc *sc = ifp->if_softc;
396cfa96c6cSSepherosa Ziehau 	int error;
397cfa96c6cSSepherosa Ziehau 
398cfa96c6cSSepherosa Ziehau 	if (sc->sc_mediachange) {
399cfa96c6cSSepherosa Ziehau 		error = (*sc->sc_mediachange)(sc);
400cfa96c6cSSepherosa Ziehau 		return (error);
401cfa96c6cSSepherosa Ziehau 	}
402cfa96c6cSSepherosa Ziehau 	return (0);
403cfa96c6cSSepherosa Ziehau }
404cfa96c6cSSepherosa Ziehau 
405cfa96c6cSSepherosa Ziehau static void
lance_mediastatus(struct ifnet * ifp,struct ifmediareq * ifmr)406cfa96c6cSSepherosa Ziehau lance_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
407cfa96c6cSSepherosa Ziehau {
408cfa96c6cSSepherosa Ziehau 	struct lance_softc *sc = ifp->if_softc;
409cfa96c6cSSepherosa Ziehau 
410cfa96c6cSSepherosa Ziehau 	if (!(ifp->if_flags & IFF_UP)) {
411cfa96c6cSSepherosa Ziehau 		return;
412cfa96c6cSSepherosa Ziehau 	}
413cfa96c6cSSepherosa Ziehau 
414cfa96c6cSSepherosa Ziehau 	ifmr->ifm_status = IFM_AVALID;
415cfa96c6cSSepherosa Ziehau 	if (sc->sc_flags & LE_CARRIER)
416cfa96c6cSSepherosa Ziehau 		ifmr->ifm_status |= IFM_ACTIVE;
417cfa96c6cSSepherosa Ziehau 
418cfa96c6cSSepherosa Ziehau 	if (sc->sc_mediastatus)
419cfa96c6cSSepherosa Ziehau 		(*sc->sc_mediastatus)(sc, ifmr);
420cfa96c6cSSepherosa Ziehau }
421cfa96c6cSSepherosa Ziehau 
422cfa96c6cSSepherosa Ziehau /*
423cfa96c6cSSepherosa Ziehau  * Process an ioctl request.
424cfa96c6cSSepherosa Ziehau  */
425cfa96c6cSSepherosa Ziehau static int
lance_ioctl(struct ifnet * ifp,u_long cmd,caddr_t data,struct ucred * cr)426cfa96c6cSSepherosa Ziehau lance_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
427cfa96c6cSSepherosa Ziehau {
428cfa96c6cSSepherosa Ziehau 	struct lance_softc *sc = ifp->if_softc;
429cfa96c6cSSepherosa Ziehau 	struct ifreq *ifr = (struct ifreq *)data;
430cfa96c6cSSepherosa Ziehau 	int error = 0;
431cfa96c6cSSepherosa Ziehau 
432cfa96c6cSSepherosa Ziehau 	crit_enter();
433cfa96c6cSSepherosa Ziehau 
434cfa96c6cSSepherosa Ziehau 	switch (cmd) {
435cfa96c6cSSepherosa Ziehau 	case SIOCSIFFLAGS:
436cfa96c6cSSepherosa Ziehau 		if (ifp->if_flags & IFF_PROMISC) {
437cfa96c6cSSepherosa Ziehau 			if (!(sc->sc_flags & LE_PROMISC)) {
438cfa96c6cSSepherosa Ziehau 				sc->sc_flags |= LE_PROMISC;
439cfa96c6cSSepherosa Ziehau 				lance_init_locked(sc);
440cfa96c6cSSepherosa Ziehau 			}
441cfa96c6cSSepherosa Ziehau 		} else if (sc->sc_flags & LE_PROMISC) {
442cfa96c6cSSepherosa Ziehau 			sc->sc_flags &= ~LE_PROMISC;
443cfa96c6cSSepherosa Ziehau 			lance_init_locked(sc);
444cfa96c6cSSepherosa Ziehau 		}
445cfa96c6cSSepherosa Ziehau 
446cfa96c6cSSepherosa Ziehau 		if ((ifp->if_flags & IFF_ALLMULTI) &&
447cfa96c6cSSepherosa Ziehau 		    !(sc->sc_flags & LE_ALLMULTI)) {
448cfa96c6cSSepherosa Ziehau 			sc->sc_flags |= LE_ALLMULTI;
449cfa96c6cSSepherosa Ziehau 			lance_init_locked(sc);
450cfa96c6cSSepherosa Ziehau 		} else if (!(ifp->if_flags & IFF_ALLMULTI) &&
451cfa96c6cSSepherosa Ziehau 		    (sc->sc_flags & LE_ALLMULTI)) {
452cfa96c6cSSepherosa Ziehau 			sc->sc_flags &= ~LE_ALLMULTI;
453cfa96c6cSSepherosa Ziehau 			lance_init_locked(sc);
454cfa96c6cSSepherosa Ziehau 		}
455cfa96c6cSSepherosa Ziehau 
456cfa96c6cSSepherosa Ziehau 		if (!(ifp->if_flags & IFF_UP) &&
457cfa96c6cSSepherosa Ziehau 		    ifp->if_flags & IFF_RUNNING) {
458cfa96c6cSSepherosa Ziehau 			/*
459cfa96c6cSSepherosa Ziehau 			 * If interface is marked down and it is running, then
460cfa96c6cSSepherosa Ziehau 			 * stop it.
461cfa96c6cSSepherosa Ziehau 			 */
462cfa96c6cSSepherosa Ziehau 			lance_stop(sc);
463cfa96c6cSSepherosa Ziehau 		} else if (ifp->if_flags & IFF_UP &&
464cfa96c6cSSepherosa Ziehau 		    !(ifp->if_flags & IFF_RUNNING)) {
465cfa96c6cSSepherosa Ziehau 			/*
466cfa96c6cSSepherosa Ziehau 			 * If interface is marked up and it is stopped, then
467cfa96c6cSSepherosa Ziehau 			 * start it.
468cfa96c6cSSepherosa Ziehau 			 */
469cfa96c6cSSepherosa Ziehau 			lance_init_locked(sc);
470cfa96c6cSSepherosa Ziehau 		}
471cfa96c6cSSepherosa Ziehau #ifdef LEDEBUG
472cfa96c6cSSepherosa Ziehau 		if (ifp->if_flags & IFF_DEBUG)
473cfa96c6cSSepherosa Ziehau 			sc->sc_flags |= LE_DEBUG;
474cfa96c6cSSepherosa Ziehau 		else
475cfa96c6cSSepherosa Ziehau 			sc->sc_flags &= ~LE_DEBUG;
476cfa96c6cSSepherosa Ziehau #endif
477cfa96c6cSSepherosa Ziehau 		break;
478cfa96c6cSSepherosa Ziehau 
479cfa96c6cSSepherosa Ziehau 	case SIOCADDMULTI:
480cfa96c6cSSepherosa Ziehau 	case SIOCDELMULTI:
481cfa96c6cSSepherosa Ziehau 		/*
482cfa96c6cSSepherosa Ziehau 		 * Multicast list has changed; set the hardware filter
483cfa96c6cSSepherosa Ziehau 		 * accordingly.
484cfa96c6cSSepherosa Ziehau 		 */
485cfa96c6cSSepherosa Ziehau 		if (ifp->if_flags & IFF_RUNNING)
486cfa96c6cSSepherosa Ziehau 			lance_init_locked(sc);
487cfa96c6cSSepherosa Ziehau 		break;
488cfa96c6cSSepherosa Ziehau 
489cfa96c6cSSepherosa Ziehau 	case SIOCGIFMEDIA:
490cfa96c6cSSepherosa Ziehau 	case SIOCSIFMEDIA:
491cfa96c6cSSepherosa Ziehau 		error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
492cfa96c6cSSepherosa Ziehau 		break;
493cfa96c6cSSepherosa Ziehau 
494cfa96c6cSSepherosa Ziehau 	default:
495cfa96c6cSSepherosa Ziehau 		error = ether_ioctl(ifp, cmd, data);
496cfa96c6cSSepherosa Ziehau 		break;
497cfa96c6cSSepherosa Ziehau 	}
498cfa96c6cSSepherosa Ziehau 
499cfa96c6cSSepherosa Ziehau 	crit_exit();
500cfa96c6cSSepherosa Ziehau 
501cfa96c6cSSepherosa Ziehau 	return (error);
502cfa96c6cSSepherosa Ziehau }
503cfa96c6cSSepherosa Ziehau 
504cfa96c6cSSepherosa Ziehau /*
505cfa96c6cSSepherosa Ziehau  * Set up the logical address filter.
506cfa96c6cSSepherosa Ziehau  */
507cfa96c6cSSepherosa Ziehau void
lance_setladrf(struct lance_softc * sc,uint16_t * af)508cfa96c6cSSepherosa Ziehau lance_setladrf(struct lance_softc *sc, uint16_t *af)
509cfa96c6cSSepherosa Ziehau {
510cfa96c6cSSepherosa Ziehau 	struct ifnet *ifp = sc->ifp;
511cfa96c6cSSepherosa Ziehau 	struct ifmultiaddr *ifma;
512cfa96c6cSSepherosa Ziehau 	uint32_t crc;
513cfa96c6cSSepherosa Ziehau 
514cfa96c6cSSepherosa Ziehau 	/*
515cfa96c6cSSepherosa Ziehau 	 * Set up multicast address filter by passing all multicast addresses
516cfa96c6cSSepherosa Ziehau 	 * through a crc generator, and then using the high order 6 bits as an
517cfa96c6cSSepherosa Ziehau 	 * index into the 64 bit logical address filter.  The high order bit
518cfa96c6cSSepherosa Ziehau 	 * selects the word, while the rest of the bits select the bit within
519cfa96c6cSSepherosa Ziehau 	 * the word.
520cfa96c6cSSepherosa Ziehau 	 */
521cfa96c6cSSepherosa Ziehau 
522cfa96c6cSSepherosa Ziehau 	if (ifp->if_flags & IFF_PROMISC || sc->sc_flags & LE_ALLMULTI) {
523cfa96c6cSSepherosa Ziehau 		af[0] = af[1] = af[2] = af[3] = 0xffff;
524cfa96c6cSSepherosa Ziehau 		return;
525cfa96c6cSSepherosa Ziehau 	}
526cfa96c6cSSepherosa Ziehau 
527cfa96c6cSSepherosa Ziehau 	af[0] = af[1] = af[2] = af[3] = 0x0000;
528cfa96c6cSSepherosa Ziehau 
529441d34b2SSascha Wildner 	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
530cfa96c6cSSepherosa Ziehau 		if (ifma->ifma_addr->sa_family != AF_LINK)
531cfa96c6cSSepherosa Ziehau 			continue;
532cfa96c6cSSepherosa Ziehau 
533cfa96c6cSSepherosa Ziehau 		crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
534cfa96c6cSSepherosa Ziehau 		    ifma->ifma_addr), ETHER_ADDR_LEN);
535cfa96c6cSSepherosa Ziehau 
536cfa96c6cSSepherosa Ziehau 		/* Just want the 6 most significant bits. */
537cfa96c6cSSepherosa Ziehau 		crc >>= 26;
538cfa96c6cSSepherosa Ziehau 
539cfa96c6cSSepherosa Ziehau 		/* Set the corresponding bit in the filter. */
540cfa96c6cSSepherosa Ziehau 		af[crc >> 4] |= LE_HTOLE16(1 << (crc & 0xf));
541cfa96c6cSSepherosa Ziehau 	}
542cfa96c6cSSepherosa Ziehau }
543cfa96c6cSSepherosa Ziehau 
544cfa96c6cSSepherosa Ziehau /*
545cfa96c6cSSepherosa Ziehau  * Routines for accessing the transmit and receive buffers.
546cfa96c6cSSepherosa Ziehau  * The various CPU and adapter configurations supported by this
547cfa96c6cSSepherosa Ziehau  * driver require three different access methods for buffers
548cfa96c6cSSepherosa Ziehau  * and descriptors:
549cfa96c6cSSepherosa Ziehau  *	(1) contig (contiguous data; no padding),
550cfa96c6cSSepherosa Ziehau  *	(2) gap2 (two bytes of data followed by two bytes of padding),
551cfa96c6cSSepherosa Ziehau  *	(3) gap16 (16 bytes of data followed by 16 bytes of padding).
552cfa96c6cSSepherosa Ziehau  */
553cfa96c6cSSepherosa Ziehau 
554cfa96c6cSSepherosa Ziehau /*
555cfa96c6cSSepherosa Ziehau  * contig: contiguous data with no padding.
556cfa96c6cSSepherosa Ziehau  *
557cfa96c6cSSepherosa Ziehau  * Buffers may have any alignment.
558cfa96c6cSSepherosa Ziehau  */
559cfa96c6cSSepherosa Ziehau 
560cfa96c6cSSepherosa Ziehau void
lance_copytobuf_contig(struct lance_softc * sc,void * from,int boff,int len)561cfa96c6cSSepherosa Ziehau lance_copytobuf_contig(struct lance_softc *sc, void *from, int boff, int len)
562cfa96c6cSSepherosa Ziehau {
563cfa96c6cSSepherosa Ziehau 	volatile caddr_t buf = sc->sc_mem;
564cfa96c6cSSepherosa Ziehau 
565cfa96c6cSSepherosa Ziehau 	/*
566cfa96c6cSSepherosa Ziehau 	 * Just call memcpy() to do the work.
567cfa96c6cSSepherosa Ziehau 	 */
568cfa96c6cSSepherosa Ziehau 	memcpy(buf + boff, from, len);
569cfa96c6cSSepherosa Ziehau }
570cfa96c6cSSepherosa Ziehau 
571cfa96c6cSSepherosa Ziehau void
lance_copyfrombuf_contig(struct lance_softc * sc,void * to,int boff,int len)572cfa96c6cSSepherosa Ziehau lance_copyfrombuf_contig(struct lance_softc *sc, void *to, int boff, int len)
573cfa96c6cSSepherosa Ziehau {
574cfa96c6cSSepherosa Ziehau 	volatile caddr_t buf = sc->sc_mem;
575cfa96c6cSSepherosa Ziehau 
576cfa96c6cSSepherosa Ziehau 	/*
577cfa96c6cSSepherosa Ziehau 	 * Just call memcpy() to do the work.
578cfa96c6cSSepherosa Ziehau 	 */
579cfa96c6cSSepherosa Ziehau 	memcpy(to, buf + boff, len);
580cfa96c6cSSepherosa Ziehau }
581cfa96c6cSSepherosa Ziehau 
582cfa96c6cSSepherosa Ziehau void
lance_zerobuf_contig(struct lance_softc * sc,int boff,int len)583cfa96c6cSSepherosa Ziehau lance_zerobuf_contig(struct lance_softc *sc, int boff, int len)
584cfa96c6cSSepherosa Ziehau {
585cfa96c6cSSepherosa Ziehau 	volatile caddr_t buf = sc->sc_mem;
586cfa96c6cSSepherosa Ziehau 
587cfa96c6cSSepherosa Ziehau 	/*
588cfa96c6cSSepherosa Ziehau 	 * Just let memset() do the work
589cfa96c6cSSepherosa Ziehau 	 */
590cfa96c6cSSepherosa Ziehau 	memset(buf + boff, 0, len);
591cfa96c6cSSepherosa Ziehau }
592cfa96c6cSSepherosa Ziehau 
593cfa96c6cSSepherosa Ziehau #if 0
594cfa96c6cSSepherosa Ziehau /*
595cfa96c6cSSepherosa Ziehau  * Examples only; duplicate these and tweak (if necessary) in
596cfa96c6cSSepherosa Ziehau  * machine-specific front-ends.
597cfa96c6cSSepherosa Ziehau  */
598cfa96c6cSSepherosa Ziehau 
599cfa96c6cSSepherosa Ziehau /*
600cfa96c6cSSepherosa Ziehau  * gap2: two bytes of data followed by two bytes of pad.
601cfa96c6cSSepherosa Ziehau  *
602cfa96c6cSSepherosa Ziehau  * Buffers must be 4-byte aligned.  The code doesn't worry about
603cfa96c6cSSepherosa Ziehau  * doing an extra byte.
604cfa96c6cSSepherosa Ziehau  */
605cfa96c6cSSepherosa Ziehau 
606cfa96c6cSSepherosa Ziehau static void
607cfa96c6cSSepherosa Ziehau lance_copytobuf_gap2(struct lance_softc *sc, void *fromv, int boff, int len)
608cfa96c6cSSepherosa Ziehau {
609cfa96c6cSSepherosa Ziehau 	volatile caddr_t buf = sc->sc_mem;
610cfa96c6cSSepherosa Ziehau 	caddr_t from = fromv;
611cfa96c6cSSepherosa Ziehau 	volatile uint16_t *bptr;
612cfa96c6cSSepherosa Ziehau 
613cfa96c6cSSepherosa Ziehau 	if (boff & 0x1) {
614cfa96c6cSSepherosa Ziehau 		/* Handle unaligned first byte. */
615cfa96c6cSSepherosa Ziehau 		bptr = ((volatile uint16_t *)buf) + (boff - 1);
616cfa96c6cSSepherosa Ziehau 		*bptr = (*from++ << 8) | (*bptr & 0xff);
617cfa96c6cSSepherosa Ziehau 		bptr += 2;
618cfa96c6cSSepherosa Ziehau 		len--;
619cfa96c6cSSepherosa Ziehau 	} else
620cfa96c6cSSepherosa Ziehau 		bptr = ((volatile uint16_t *)buf) + boff;
621cfa96c6cSSepherosa Ziehau 	while (len > 1) {
622cfa96c6cSSepherosa Ziehau 		*bptr = (from[1] << 8) | (from[0] & 0xff);
623cfa96c6cSSepherosa Ziehau 		bptr += 2;
624cfa96c6cSSepherosa Ziehau 		from += 2;
625cfa96c6cSSepherosa Ziehau 		len -= 2;
626cfa96c6cSSepherosa Ziehau 	}
627cfa96c6cSSepherosa Ziehau 	if (len == 1)
628cfa96c6cSSepherosa Ziehau 		*bptr = (uint16_t)*from;
629cfa96c6cSSepherosa Ziehau }
630cfa96c6cSSepherosa Ziehau 
631cfa96c6cSSepherosa Ziehau static void
632cfa96c6cSSepherosa Ziehau lance_copyfrombuf_gap2(struct lance_softc *sc, void *tov, int boff, int len)
633cfa96c6cSSepherosa Ziehau {
634cfa96c6cSSepherosa Ziehau 	volatile caddr_t buf = sc->sc_mem;
635cfa96c6cSSepherosa Ziehau 	caddr_t to = tov;
636cfa96c6cSSepherosa Ziehau 	volatile uint16_t *bptr;
637cfa96c6cSSepherosa Ziehau 	uint16_t tmp;
638cfa96c6cSSepherosa Ziehau 
639cfa96c6cSSepherosa Ziehau 	if (boff & 0x1) {
640cfa96c6cSSepherosa Ziehau 		/* Handle unaligned first byte. */
641cfa96c6cSSepherosa Ziehau 		bptr = ((volatile uint16_t *)buf) + (boff - 1);
642cfa96c6cSSepherosa Ziehau 		*to++ = (*bptr >> 8) & 0xff;
643cfa96c6cSSepherosa Ziehau 		bptr += 2;
644cfa96c6cSSepherosa Ziehau 		len--;
645cfa96c6cSSepherosa Ziehau 	} else
646cfa96c6cSSepherosa Ziehau 		bptr = ((volatile uint16_t *)buf) + boff;
647cfa96c6cSSepherosa Ziehau 	while (len > 1) {
648cfa96c6cSSepherosa Ziehau 		tmp = *bptr;
649cfa96c6cSSepherosa Ziehau 		*to++ = tmp & 0xff;
650cfa96c6cSSepherosa Ziehau 		*to++ = (tmp >> 8) & 0xff;
651cfa96c6cSSepherosa Ziehau 		bptr += 2;
652cfa96c6cSSepherosa Ziehau 		len -= 2;
653cfa96c6cSSepherosa Ziehau 	}
654cfa96c6cSSepherosa Ziehau 	if (len == 1)
655cfa96c6cSSepherosa Ziehau 		*to = *bptr & 0xff;
656cfa96c6cSSepherosa Ziehau }
657cfa96c6cSSepherosa Ziehau 
658cfa96c6cSSepherosa Ziehau static void
659cfa96c6cSSepherosa Ziehau lance_zerobuf_gap2(struct lance_softc *sc, int boff, int len)
660cfa96c6cSSepherosa Ziehau {
661cfa96c6cSSepherosa Ziehau 	volatile caddr_t buf = sc->sc_mem;
662cfa96c6cSSepherosa Ziehau 	volatile uint16_t *bptr;
663cfa96c6cSSepherosa Ziehau 
664cfa96c6cSSepherosa Ziehau 	if ((unsigned)boff & 0x1) {
665cfa96c6cSSepherosa Ziehau 		bptr = ((volatile uint16_t *)buf) + (boff - 1);
666cfa96c6cSSepherosa Ziehau 		*bptr &= 0xff;
667cfa96c6cSSepherosa Ziehau 		bptr += 2;
668cfa96c6cSSepherosa Ziehau 		len--;
669cfa96c6cSSepherosa Ziehau 	} else
670cfa96c6cSSepherosa Ziehau 		bptr = ((volatile uint16_t *)buf) + boff;
671cfa96c6cSSepherosa Ziehau 	while (len > 0) {
672cfa96c6cSSepherosa Ziehau 		*bptr = 0;
673cfa96c6cSSepherosa Ziehau 		bptr += 2;
674cfa96c6cSSepherosa Ziehau 		len -= 2;
675cfa96c6cSSepherosa Ziehau 	}
676cfa96c6cSSepherosa Ziehau }
677cfa96c6cSSepherosa Ziehau 
678cfa96c6cSSepherosa Ziehau /*
679cfa96c6cSSepherosa Ziehau  * gap16: 16 bytes of data followed by 16 bytes of pad.
680cfa96c6cSSepherosa Ziehau  *
681cfa96c6cSSepherosa Ziehau  * Buffers must be 32-byte aligned.
682cfa96c6cSSepherosa Ziehau  */
683cfa96c6cSSepherosa Ziehau 
684cfa96c6cSSepherosa Ziehau static void
685cfa96c6cSSepherosa Ziehau lance_copytobuf_gap16(struct lance_softc *sc, void *fromv, int boff, int len)
686cfa96c6cSSepherosa Ziehau {
687cfa96c6cSSepherosa Ziehau 	volatile caddr_t buf = sc->sc_mem;
688cfa96c6cSSepherosa Ziehau 	caddr_t bptr, from = fromv;
689cfa96c6cSSepherosa Ziehau 	int xfer;
690cfa96c6cSSepherosa Ziehau 
691cfa96c6cSSepherosa Ziehau 	bptr = buf + ((boff << 1) & ~0x1f);
692cfa96c6cSSepherosa Ziehau 	boff &= 0xf;
693cfa96c6cSSepherosa Ziehau 	xfer = min(len, 16 - boff);
694cfa96c6cSSepherosa Ziehau 	while (len > 0) {
695cfa96c6cSSepherosa Ziehau 		memcpy(bptr + boff, from, xfer);
696cfa96c6cSSepherosa Ziehau 		from += xfer;
697cfa96c6cSSepherosa Ziehau 		bptr += 32;
698cfa96c6cSSepherosa Ziehau 		boff = 0;
699cfa96c6cSSepherosa Ziehau 		len -= xfer;
700cfa96c6cSSepherosa Ziehau 		xfer = min(len, 16);
701cfa96c6cSSepherosa Ziehau 	}
702cfa96c6cSSepherosa Ziehau }
703cfa96c6cSSepherosa Ziehau 
704cfa96c6cSSepherosa Ziehau static void
705cfa96c6cSSepherosa Ziehau lance_copyfrombuf_gap16(struct lance_softc *sc, void *tov, int boff, int len)
706cfa96c6cSSepherosa Ziehau {
707cfa96c6cSSepherosa Ziehau 	volatile caddr_t buf = sc->sc_mem;
708cfa96c6cSSepherosa Ziehau 	caddr_t bptr, to = tov;
709cfa96c6cSSepherosa Ziehau 	int xfer;
710cfa96c6cSSepherosa Ziehau 
711cfa96c6cSSepherosa Ziehau 	bptr = buf + ((boff << 1) & ~0x1f);
712cfa96c6cSSepherosa Ziehau 	boff &= 0xf;
713cfa96c6cSSepherosa Ziehau 	xfer = min(len, 16 - boff);
714cfa96c6cSSepherosa Ziehau 	while (len > 0) {
715cfa96c6cSSepherosa Ziehau 		memcpy(to, bptr + boff, xfer);
716cfa96c6cSSepherosa Ziehau 		to += xfer;
717cfa96c6cSSepherosa Ziehau 		bptr += 32;
718cfa96c6cSSepherosa Ziehau 		boff = 0;
719cfa96c6cSSepherosa Ziehau 		len -= xfer;
720cfa96c6cSSepherosa Ziehau 		xfer = min(len, 16);
721cfa96c6cSSepherosa Ziehau 	}
722cfa96c6cSSepherosa Ziehau }
723cfa96c6cSSepherosa Ziehau 
724cfa96c6cSSepherosa Ziehau static void
725cfa96c6cSSepherosa Ziehau lance_zerobuf_gap16(struct lance_softc *sc, int boff, int len)
726cfa96c6cSSepherosa Ziehau {
727cfa96c6cSSepherosa Ziehau 	volatile caddr_t buf = sc->sc_mem;
728cfa96c6cSSepherosa Ziehau 	caddr_t bptr;
729cfa96c6cSSepherosa Ziehau 	int xfer;
730cfa96c6cSSepherosa Ziehau 
731cfa96c6cSSepherosa Ziehau 	bptr = buf + ((boff << 1) & ~0x1f);
732cfa96c6cSSepherosa Ziehau 	boff &= 0xf;
733cfa96c6cSSepherosa Ziehau 	xfer = min(len, 16 - boff);
734cfa96c6cSSepherosa Ziehau 	while (len > 0) {
735cfa96c6cSSepherosa Ziehau 		memset(bptr + boff, 0, xfer);
736cfa96c6cSSepherosa Ziehau 		bptr += 32;
737cfa96c6cSSepherosa Ziehau 		boff = 0;
738cfa96c6cSSepherosa Ziehau 		len -= xfer;
739cfa96c6cSSepherosa Ziehau 		xfer = min(len, 16);
740cfa96c6cSSepherosa Ziehau 	}
741cfa96c6cSSepherosa Ziehau }
742cfa96c6cSSepherosa Ziehau #endif /* Example only */
743