smc83c170.c revision 1.29 1 1.29 thorpej /* $NetBSD: smc83c170.c,v 1.29 2000/03/23 07:01:32 thorpej Exp $ */
2 1.1 thorpej
3 1.1 thorpej /*-
4 1.10 thorpej * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5 1.1 thorpej * All rights reserved.
6 1.1 thorpej *
7 1.1 thorpej * This code is derived from software contributed to The NetBSD Foundation
8 1.1 thorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 1.1 thorpej * NASA Ames Research Center.
10 1.1 thorpej *
11 1.1 thorpej * Redistribution and use in source and binary forms, with or without
12 1.1 thorpej * modification, are permitted provided that the following conditions
13 1.1 thorpej * are met:
14 1.1 thorpej * 1. Redistributions of source code must retain the above copyright
15 1.1 thorpej * notice, this list of conditions and the following disclaimer.
16 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright
17 1.1 thorpej * notice, this list of conditions and the following disclaimer in the
18 1.1 thorpej * documentation and/or other materials provided with the distribution.
19 1.1 thorpej * 3. All advertising materials mentioning features or use of this software
20 1.1 thorpej * must display the following acknowledgement:
21 1.1 thorpej * This product includes software developed by the NetBSD
22 1.1 thorpej * Foundation, Inc. and its contributors.
23 1.1 thorpej * 4. Neither the name of The NetBSD Foundation nor the names of its
24 1.1 thorpej * contributors may be used to endorse or promote products derived
25 1.1 thorpej * from this software without specific prior written permission.
26 1.1 thorpej *
27 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 1.1 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 1.1 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 1.1 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 1.1 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.1 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.1 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.1 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.1 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.1 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.1 thorpej * POSSIBILITY OF SUCH DAMAGE.
38 1.1 thorpej */
39 1.1 thorpej
40 1.1 thorpej /*
41 1.1 thorpej * Device driver for the Standard Microsystems Corp. 83C170
42 1.1 thorpej * Ethernet PCI Integrated Controller (EPIC/100).
43 1.1 thorpej */
44 1.1 thorpej
45 1.2 jonathan #include "opt_inet.h"
46 1.3 jonathan #include "opt_ns.h"
47 1.1 thorpej #include "bpfilter.h"
48 1.1 thorpej
49 1.1 thorpej #include <sys/param.h>
50 1.1 thorpej #include <sys/systm.h>
51 1.29 thorpej #include <sys/callout.h>
52 1.1 thorpej #include <sys/mbuf.h>
53 1.1 thorpej #include <sys/malloc.h>
54 1.1 thorpej #include <sys/kernel.h>
55 1.1 thorpej #include <sys/socket.h>
56 1.1 thorpej #include <sys/ioctl.h>
57 1.1 thorpej #include <sys/errno.h>
58 1.1 thorpej #include <sys/device.h>
59 1.1 thorpej
60 1.1 thorpej #include <net/if.h>
61 1.1 thorpej #include <net/if_dl.h>
62 1.1 thorpej #include <net/if_media.h>
63 1.1 thorpej #include <net/if_ether.h>
64 1.1 thorpej
65 1.1 thorpej #if NBPFILTER > 0
66 1.1 thorpej #include <net/bpf.h>
67 1.1 thorpej #endif
68 1.1 thorpej
69 1.1 thorpej #ifdef INET
70 1.1 thorpej #include <netinet/in.h>
71 1.1 thorpej #include <netinet/if_inarp.h>
72 1.1 thorpej #endif
73 1.1 thorpej
74 1.1 thorpej #ifdef NS
75 1.1 thorpej #include <netns/ns.h>
76 1.1 thorpej #include <netns/ns_if.h>
77 1.1 thorpej #endif
78 1.1 thorpej
79 1.1 thorpej #include <machine/bus.h>
80 1.1 thorpej #include <machine/intr.h>
81 1.1 thorpej
82 1.8 thorpej #include <dev/mii/miivar.h>
83 1.8 thorpej
84 1.1 thorpej #include <dev/ic/smc83c170reg.h>
85 1.1 thorpej #include <dev/ic/smc83c170var.h>
86 1.1 thorpej
87 1.1 thorpej void epic_start __P((struct ifnet *));
88 1.1 thorpej void epic_watchdog __P((struct ifnet *));
89 1.1 thorpej int epic_ioctl __P((struct ifnet *, u_long, caddr_t));
90 1.1 thorpej
91 1.1 thorpej void epic_shutdown __P((void *));
92 1.1 thorpej
93 1.1 thorpej void epic_reset __P((struct epic_softc *));
94 1.19 thorpej int epic_init __P((struct epic_softc *));
95 1.19 thorpej void epic_rxdrain __P((struct epic_softc *));
96 1.19 thorpej void epic_stop __P((struct epic_softc *, int));
97 1.1 thorpej int epic_add_rxbuf __P((struct epic_softc *, int));
98 1.1 thorpej void epic_read_eeprom __P((struct epic_softc *, int, int, u_int16_t *));
99 1.1 thorpej void epic_set_mchash __P((struct epic_softc *));
100 1.6 thorpej void epic_fixup_clock_source __P((struct epic_softc *));
101 1.8 thorpej int epic_mii_read __P((struct device *, int, int));
102 1.8 thorpej void epic_mii_write __P((struct device *, int, int, int));
103 1.8 thorpej int epic_mii_wait __P((struct epic_softc *, u_int32_t));
104 1.8 thorpej void epic_tick __P((void *));
105 1.8 thorpej
106 1.8 thorpej void epic_statchg __P((struct device *));
107 1.8 thorpej int epic_mediachange __P((struct ifnet *));
108 1.8 thorpej void epic_mediastatus __P((struct ifnet *, struct ifmediareq *));
109 1.1 thorpej
110 1.1 thorpej #define INTMASK (INTSTAT_FATAL_INT | INTSTAT_TXU | \
111 1.21 thorpej INTSTAT_TXC | INTSTAT_RXE | INTSTAT_RQE | INTSTAT_RCC)
112 1.1 thorpej
113 1.19 thorpej int epic_copy_small = 0;
114 1.19 thorpej
115 1.1 thorpej /*
116 1.1 thorpej * Attach an EPIC interface to the system.
117 1.1 thorpej */
118 1.1 thorpej void
119 1.1 thorpej epic_attach(sc)
120 1.1 thorpej struct epic_softc *sc;
121 1.1 thorpej {
122 1.1 thorpej bus_space_tag_t st = sc->sc_st;
123 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
124 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
125 1.14 thorpej int i, rseg, error;
126 1.1 thorpej bus_dma_segment_t seg;
127 1.1 thorpej u_int8_t enaddr[ETHER_ADDR_LEN], devname[12 + 1];
128 1.1 thorpej u_int16_t myea[ETHER_ADDR_LEN / 2], mydevname[6];
129 1.1 thorpej
130 1.29 thorpej callout_init(&sc->sc_mii_callout);
131 1.29 thorpej
132 1.1 thorpej /*
133 1.1 thorpej * Allocate the control data structures, and create and load the
134 1.1 thorpej * DMA map for it.
135 1.1 thorpej */
136 1.1 thorpej if ((error = bus_dmamem_alloc(sc->sc_dmat,
137 1.1 thorpej sizeof(struct epic_control_data), NBPG, 0, &seg, 1, &rseg,
138 1.1 thorpej BUS_DMA_NOWAIT)) != 0) {
139 1.1 thorpej printf("%s: unable to allocate control data, error = %d\n",
140 1.1 thorpej sc->sc_dev.dv_xname, error);
141 1.14 thorpej goto fail_0;
142 1.1 thorpej }
143 1.1 thorpej
144 1.1 thorpej if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
145 1.1 thorpej sizeof(struct epic_control_data), (caddr_t *)&sc->sc_control_data,
146 1.1 thorpej BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
147 1.1 thorpej printf("%s: unable to map control data, error = %d\n",
148 1.1 thorpej sc->sc_dev.dv_xname, error);
149 1.14 thorpej goto fail_1;
150 1.1 thorpej }
151 1.1 thorpej
152 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat,
153 1.1 thorpej sizeof(struct epic_control_data), 1,
154 1.1 thorpej sizeof(struct epic_control_data), 0, BUS_DMA_NOWAIT,
155 1.1 thorpej &sc->sc_cddmamap)) != 0) {
156 1.1 thorpej printf("%s: unable to create control data DMA map, "
157 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, error);
158 1.14 thorpej goto fail_2;
159 1.1 thorpej }
160 1.1 thorpej
161 1.1 thorpej if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
162 1.1 thorpej sc->sc_control_data, sizeof(struct epic_control_data), NULL,
163 1.1 thorpej BUS_DMA_NOWAIT)) != 0) {
164 1.1 thorpej printf("%s: unable to load control data DMA map, error = %d\n",
165 1.1 thorpej sc->sc_dev.dv_xname, error);
166 1.14 thorpej goto fail_3;
167 1.1 thorpej }
168 1.1 thorpej
169 1.1 thorpej /*
170 1.1 thorpej * Create the transmit buffer DMA maps.
171 1.1 thorpej */
172 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++) {
173 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
174 1.1 thorpej EPIC_NFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT,
175 1.10 thorpej &EPIC_DSTX(sc, i)->ds_dmamap)) != 0) {
176 1.1 thorpej printf("%s: unable to create tx DMA map %d, "
177 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, i, error);
178 1.14 thorpej goto fail_4;
179 1.1 thorpej }
180 1.1 thorpej }
181 1.1 thorpej
182 1.1 thorpej /*
183 1.1 thorpej * Create the recieve buffer DMA maps.
184 1.1 thorpej */
185 1.1 thorpej for (i = 0; i < EPIC_NRXDESC; i++) {
186 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
187 1.1 thorpej MCLBYTES, 0, BUS_DMA_NOWAIT,
188 1.10 thorpej &EPIC_DSRX(sc, i)->ds_dmamap)) != 0) {
189 1.1 thorpej printf("%s: unable to create rx DMA map %d, "
190 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, i, error);
191 1.14 thorpej goto fail_5;
192 1.1 thorpej }
193 1.19 thorpej EPIC_DSRX(sc, i)->ds_mbuf = NULL;
194 1.1 thorpej }
195 1.1 thorpej
196 1.1 thorpej
197 1.1 thorpej /*
198 1.1 thorpej * Bring the chip out of low-power mode and reset it to a known state.
199 1.1 thorpej */
200 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, 0);
201 1.1 thorpej epic_reset(sc);
202 1.1 thorpej
203 1.1 thorpej /*
204 1.1 thorpej * Read the Ethernet address from the EEPROM.
205 1.1 thorpej */
206 1.1 thorpej epic_read_eeprom(sc, 0, (sizeof(myea) / sizeof(myea[0])), myea);
207 1.1 thorpej bcopy(myea, enaddr, sizeof(myea));
208 1.1 thorpej
209 1.1 thorpej /*
210 1.1 thorpej * ...and the device name.
211 1.1 thorpej */
212 1.1 thorpej epic_read_eeprom(sc, 0x2c, (sizeof(mydevname) / sizeof(mydevname[0])),
213 1.1 thorpej mydevname);
214 1.1 thorpej bcopy(mydevname, devname, sizeof(mydevname));
215 1.1 thorpej devname[sizeof(mydevname)] = '\0';
216 1.1 thorpej for (i = sizeof(mydevname) - 1; i >= 0; i--) {
217 1.1 thorpej if (devname[i] == ' ')
218 1.1 thorpej devname[i] = '\0';
219 1.1 thorpej else
220 1.1 thorpej break;
221 1.1 thorpej }
222 1.1 thorpej
223 1.1 thorpej printf("%s: %s, Ethernet address %s\n", sc->sc_dev.dv_xname,
224 1.1 thorpej devname, ether_sprintf(enaddr));
225 1.1 thorpej
226 1.8 thorpej /*
227 1.8 thorpej * Initialize our media structures and probe the MII.
228 1.8 thorpej */
229 1.8 thorpej sc->sc_mii.mii_ifp = ifp;
230 1.8 thorpej sc->sc_mii.mii_readreg = epic_mii_read;
231 1.8 thorpej sc->sc_mii.mii_writereg = epic_mii_write;
232 1.8 thorpej sc->sc_mii.mii_statchg = epic_statchg;
233 1.8 thorpej ifmedia_init(&sc->sc_mii.mii_media, 0, epic_mediachange,
234 1.8 thorpej epic_mediastatus);
235 1.24 thorpej mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
236 1.25 thorpej MII_OFFSET_ANY, 0);
237 1.8 thorpej if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
238 1.8 thorpej ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
239 1.8 thorpej ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
240 1.8 thorpej } else
241 1.8 thorpej ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
242 1.8 thorpej
243 1.1 thorpej strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
244 1.1 thorpej ifp->if_softc = sc;
245 1.1 thorpej ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
246 1.1 thorpej ifp->if_ioctl = epic_ioctl;
247 1.1 thorpej ifp->if_start = epic_start;
248 1.1 thorpej ifp->if_watchdog = epic_watchdog;
249 1.1 thorpej
250 1.1 thorpej /*
251 1.1 thorpej * Attach the interface.
252 1.1 thorpej */
253 1.1 thorpej if_attach(ifp);
254 1.1 thorpej ether_ifattach(ifp, enaddr);
255 1.1 thorpej #if NBPFILTER > 0
256 1.1 thorpej bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
257 1.1 thorpej sizeof(struct ether_header));
258 1.1 thorpej #endif
259 1.1 thorpej
260 1.1 thorpej /*
261 1.1 thorpej * Make sure the interface is shutdown during reboot.
262 1.1 thorpej */
263 1.1 thorpej sc->sc_sdhook = shutdownhook_establish(epic_shutdown, sc);
264 1.1 thorpej if (sc->sc_sdhook == NULL)
265 1.1 thorpej printf("%s: WARNING: unable to establish shutdown hook\n",
266 1.1 thorpej sc->sc_dev.dv_xname);
267 1.1 thorpej return;
268 1.1 thorpej
269 1.1 thorpej /*
270 1.1 thorpej * Free any resources we've allocated during the failed attach
271 1.1 thorpej * attempt. Do this in reverse order and fall through.
272 1.1 thorpej */
273 1.14 thorpej fail_5:
274 1.14 thorpej for (i = 0; i < EPIC_NRXDESC; i++) {
275 1.14 thorpej if (EPIC_DSRX(sc, i)->ds_dmamap != NULL)
276 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat,
277 1.10 thorpej EPIC_DSRX(sc, i)->ds_dmamap);
278 1.14 thorpej }
279 1.14 thorpej fail_4:
280 1.14 thorpej for (i = 0; i < EPIC_NTXDESC; i++) {
281 1.14 thorpej if (EPIC_DSTX(sc, i)->ds_dmamap != NULL)
282 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat,
283 1.10 thorpej EPIC_DSTX(sc, i)->ds_dmamap);
284 1.1 thorpej }
285 1.14 thorpej bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
286 1.14 thorpej fail_3:
287 1.14 thorpej bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
288 1.14 thorpej fail_2:
289 1.14 thorpej bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
290 1.14 thorpej sizeof(struct epic_control_data));
291 1.14 thorpej fail_1:
292 1.14 thorpej bus_dmamem_free(sc->sc_dmat, &seg, rseg);
293 1.14 thorpej fail_0:
294 1.14 thorpej return;
295 1.1 thorpej }
296 1.1 thorpej
297 1.1 thorpej /*
298 1.1 thorpej * Shutdown hook. Make sure the interface is stopped at reboot.
299 1.1 thorpej */
300 1.1 thorpej void
301 1.1 thorpej epic_shutdown(arg)
302 1.1 thorpej void *arg;
303 1.1 thorpej {
304 1.1 thorpej struct epic_softc *sc = arg;
305 1.1 thorpej
306 1.19 thorpej epic_stop(sc, 1);
307 1.1 thorpej }
308 1.1 thorpej
309 1.1 thorpej /*
310 1.1 thorpej * Start packet transmission on the interface.
311 1.1 thorpej * [ifnet interface function]
312 1.1 thorpej */
313 1.1 thorpej void
314 1.1 thorpej epic_start(ifp)
315 1.1 thorpej struct ifnet *ifp;
316 1.1 thorpej {
317 1.1 thorpej struct epic_softc *sc = ifp->if_softc;
318 1.10 thorpej struct mbuf *m0, *m;
319 1.1 thorpej struct epic_txdesc *txd;
320 1.1 thorpej struct epic_descsoft *ds;
321 1.1 thorpej struct epic_fraglist *fr;
322 1.1 thorpej bus_dmamap_t dmamap;
323 1.10 thorpej int error, firsttx, nexttx, opending, seg;
324 1.1 thorpej
325 1.10 thorpej /*
326 1.10 thorpej * Remember the previous txpending and the first transmit
327 1.10 thorpej * descriptor we use.
328 1.10 thorpej */
329 1.10 thorpej opending = sc->sc_txpending;
330 1.10 thorpej firsttx = EPIC_NEXTTX(sc->sc_txlast);
331 1.1 thorpej
332 1.1 thorpej /*
333 1.1 thorpej * Loop through the send queue, setting up transmit descriptors
334 1.1 thorpej * until we drain the queue, or use up all available transmit
335 1.1 thorpej * descriptors.
336 1.1 thorpej */
337 1.10 thorpej while (sc->sc_txpending < EPIC_NTXDESC) {
338 1.1 thorpej /*
339 1.1 thorpej * Grab a packet off the queue.
340 1.1 thorpej */
341 1.1 thorpej IF_DEQUEUE(&ifp->if_snd, m0);
342 1.10 thorpej if (m0 == NULL)
343 1.10 thorpej break;
344 1.1 thorpej
345 1.1 thorpej /*
346 1.1 thorpej * Get the last and next available transmit descriptor.
347 1.1 thorpej */
348 1.1 thorpej nexttx = EPIC_NEXTTX(sc->sc_txlast);
349 1.10 thorpej txd = EPIC_CDTX(sc, nexttx);
350 1.10 thorpej fr = EPIC_CDFL(sc, nexttx);
351 1.10 thorpej ds = EPIC_DSTX(sc, nexttx);
352 1.1 thorpej dmamap = ds->ds_dmamap;
353 1.1 thorpej
354 1.1 thorpej /*
355 1.10 thorpej * Load the DMA map. If this fails, the packet either
356 1.10 thorpej * didn't fit in the alloted number of frags, or we were
357 1.10 thorpej * short on resources. In this case, we'll copy and try
358 1.10 thorpej * again.
359 1.1 thorpej */
360 1.10 thorpej if (bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
361 1.10 thorpej BUS_DMA_NOWAIT) != 0) {
362 1.10 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA);
363 1.10 thorpej if (m == NULL) {
364 1.10 thorpej printf("%s: unable to allocate Tx mbuf\n",
365 1.10 thorpej sc->sc_dev.dv_xname);
366 1.10 thorpej IF_PREPEND(&ifp->if_snd, m0);
367 1.10 thorpej break;
368 1.1 thorpej }
369 1.1 thorpej if (m0->m_pkthdr.len > MHLEN) {
370 1.10 thorpej MCLGET(m, M_DONTWAIT);
371 1.10 thorpej if ((m->m_flags & M_EXT) == 0) {
372 1.10 thorpej printf("%s: unable to allocate Tx "
373 1.10 thorpej "cluster\n", sc->sc_dev.dv_xname);
374 1.10 thorpej m_freem(m);
375 1.10 thorpej IF_PREPEND(&ifp->if_snd, m0);
376 1.10 thorpej break;
377 1.1 thorpej }
378 1.1 thorpej }
379 1.10 thorpej m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
380 1.10 thorpej m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
381 1.1 thorpej m_freem(m0);
382 1.10 thorpej m0 = m;
383 1.10 thorpej error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap,
384 1.10 thorpej m0, BUS_DMA_NOWAIT);
385 1.10 thorpej if (error) {
386 1.10 thorpej printf("%s: unable to load Tx buffer, "
387 1.10 thorpej "error = %d\n", sc->sc_dev.dv_xname, error);
388 1.10 thorpej IF_PREPEND(&ifp->if_snd, m0);
389 1.10 thorpej break;
390 1.10 thorpej }
391 1.1 thorpej }
392 1.1 thorpej
393 1.10 thorpej /* Initialize the fraglist. */
394 1.1 thorpej fr->ef_nfrags = dmamap->dm_nsegs;
395 1.1 thorpej for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
396 1.1 thorpej fr->ef_frags[seg].ef_addr =
397 1.1 thorpej dmamap->dm_segs[seg].ds_addr;
398 1.1 thorpej fr->ef_frags[seg].ef_length =
399 1.1 thorpej dmamap->dm_segs[seg].ds_len;
400 1.1 thorpej }
401 1.1 thorpej
402 1.10 thorpej EPIC_CDFLSYNC(sc, nexttx, BUS_DMASYNC_PREWRITE);
403 1.10 thorpej
404 1.10 thorpej /* Sync the DMA map. */
405 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
406 1.1 thorpej BUS_DMASYNC_PREWRITE);
407 1.1 thorpej
408 1.1 thorpej /*
409 1.1 thorpej * Store a pointer to the packet so we can free it later.
410 1.1 thorpej */
411 1.1 thorpej ds->ds_mbuf = m0;
412 1.1 thorpej
413 1.1 thorpej /*
414 1.10 thorpej * Fill in the transmit descriptor. The EPIC doesn't
415 1.10 thorpej * auto-pad, so we have to do this ourselves.
416 1.1 thorpej */
417 1.10 thorpej txd->et_control = ET_TXCTL_LASTDESC | ET_TXCTL_FRAGLIST;
418 1.20 thorpej txd->et_txlength = max(m0->m_pkthdr.len,
419 1.20 thorpej ETHER_MIN_LEN - ETHER_CRC_LEN);
420 1.1 thorpej
421 1.1 thorpej /*
422 1.10 thorpej * If this is the first descriptor we're enqueueing,
423 1.10 thorpej * don't give it to the EPIC yet. That could cause
424 1.10 thorpej * a race condition. We'll do it below.
425 1.1 thorpej */
426 1.10 thorpej if (nexttx == firsttx)
427 1.10 thorpej txd->et_txstatus = 0;
428 1.10 thorpej else
429 1.10 thorpej txd->et_txstatus = ET_TXSTAT_OWNER;
430 1.10 thorpej
431 1.10 thorpej EPIC_CDTXSYNC(sc, nexttx,
432 1.10 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
433 1.1 thorpej
434 1.10 thorpej /* Advance the tx pointer. */
435 1.1 thorpej sc->sc_txpending++;
436 1.10 thorpej sc->sc_txlast = nexttx;
437 1.1 thorpej
438 1.1 thorpej #if NBPFILTER > 0
439 1.1 thorpej /*
440 1.1 thorpej * Pass the packet to any BPF listeners.
441 1.1 thorpej */
442 1.1 thorpej if (ifp->if_bpf)
443 1.1 thorpej bpf_mtap(ifp->if_bpf, m0);
444 1.1 thorpej #endif
445 1.1 thorpej }
446 1.1 thorpej
447 1.10 thorpej if (sc->sc_txpending == EPIC_NTXDESC) {
448 1.10 thorpej /* No more slots left; notify upper layer. */
449 1.10 thorpej ifp->if_flags |= IFF_OACTIVE;
450 1.10 thorpej }
451 1.10 thorpej
452 1.10 thorpej if (sc->sc_txpending != opending) {
453 1.10 thorpej /*
454 1.10 thorpej * We enqueued packets. If the transmitter was idle,
455 1.10 thorpej * reset the txdirty pointer.
456 1.10 thorpej */
457 1.10 thorpej if (opending == 0)
458 1.10 thorpej sc->sc_txdirty = firsttx;
459 1.10 thorpej
460 1.10 thorpej /*
461 1.10 thorpej * Cause a transmit interrupt to happen on the
462 1.10 thorpej * last packet we enqueued.
463 1.10 thorpej */
464 1.10 thorpej EPIC_CDTX(sc, sc->sc_txlast)->et_control |= ET_TXCTL_IAF;
465 1.10 thorpej EPIC_CDTXSYNC(sc, sc->sc_txlast,
466 1.10 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
467 1.10 thorpej
468 1.10 thorpej /*
469 1.10 thorpej * The entire packet chain is set up. Give the
470 1.10 thorpej * first descriptor to the EPIC now.
471 1.10 thorpej */
472 1.10 thorpej EPIC_CDTX(sc, firsttx)->et_txstatus = ET_TXSTAT_OWNER;
473 1.10 thorpej EPIC_CDTXSYNC(sc, firsttx,
474 1.10 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
475 1.10 thorpej
476 1.10 thorpej /* Start the transmitter. */
477 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_COMMAND,
478 1.1 thorpej COMMAND_TXQUEUED);
479 1.1 thorpej
480 1.10 thorpej /* Set a watchdog timer in case the chip flakes out. */
481 1.1 thorpej ifp->if_timer = 5;
482 1.1 thorpej }
483 1.1 thorpej }
484 1.1 thorpej
485 1.1 thorpej /*
486 1.1 thorpej * Watchdog timer handler.
487 1.1 thorpej * [ifnet interface function]
488 1.1 thorpej */
489 1.1 thorpej void
490 1.1 thorpej epic_watchdog(ifp)
491 1.1 thorpej struct ifnet *ifp;
492 1.1 thorpej {
493 1.1 thorpej struct epic_softc *sc = ifp->if_softc;
494 1.1 thorpej
495 1.1 thorpej printf("%s: device timeout\n", sc->sc_dev.dv_xname);
496 1.1 thorpej ifp->if_oerrors++;
497 1.1 thorpej
498 1.19 thorpej (void) epic_init(sc);
499 1.1 thorpej }
500 1.1 thorpej
501 1.1 thorpej /*
502 1.1 thorpej * Handle control requests from the operator.
503 1.1 thorpej * [ifnet interface function]
504 1.1 thorpej */
505 1.1 thorpej int
506 1.1 thorpej epic_ioctl(ifp, cmd, data)
507 1.1 thorpej struct ifnet *ifp;
508 1.1 thorpej u_long cmd;
509 1.1 thorpej caddr_t data;
510 1.1 thorpej {
511 1.1 thorpej struct epic_softc *sc = ifp->if_softc;
512 1.1 thorpej struct ifreq *ifr = (struct ifreq *)data;
513 1.1 thorpej struct ifaddr *ifa = (struct ifaddr *)data;
514 1.1 thorpej int s, error = 0;
515 1.1 thorpej
516 1.7 mycroft s = splnet();
517 1.1 thorpej
518 1.1 thorpej switch (cmd) {
519 1.1 thorpej case SIOCSIFADDR:
520 1.1 thorpej ifp->if_flags |= IFF_UP;
521 1.1 thorpej
522 1.1 thorpej switch (ifa->ifa_addr->sa_family) {
523 1.1 thorpej #ifdef INET
524 1.1 thorpej case AF_INET:
525 1.19 thorpej if ((error = epic_init(sc)) != 0)
526 1.19 thorpej break;
527 1.1 thorpej arp_ifinit(ifp, ifa);
528 1.1 thorpej break;
529 1.1 thorpej #endif /* INET */
530 1.1 thorpej #ifdef NS
531 1.1 thorpej case AF_NS:
532 1.1 thorpej {
533 1.1 thorpej struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
534 1.1 thorpej
535 1.1 thorpej if (ns_nullhost(*ina))
536 1.1 thorpej ina->x_host = *(union ns_host *)
537 1.1 thorpej LLADDR(ifp->if_sadl);
538 1.1 thorpej else
539 1.1 thorpej bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
540 1.1 thorpej ifp->if_addrlen);
541 1.1 thorpej /* Set new address. */
542 1.19 thorpej error = epic_init(sc);
543 1.1 thorpej break;
544 1.1 thorpej }
545 1.1 thorpej #endif /* NS */
546 1.1 thorpej default:
547 1.19 thorpej error = epic_init(sc);
548 1.1 thorpej break;
549 1.1 thorpej }
550 1.1 thorpej break;
551 1.1 thorpej
552 1.1 thorpej case SIOCSIFMTU:
553 1.1 thorpej if (ifr->ifr_mtu > ETHERMTU)
554 1.1 thorpej error = EINVAL;
555 1.1 thorpej else
556 1.1 thorpej ifp->if_mtu = ifr->ifr_mtu;
557 1.1 thorpej break;
558 1.1 thorpej
559 1.1 thorpej case SIOCSIFFLAGS:
560 1.1 thorpej if ((ifp->if_flags & IFF_UP) == 0 &&
561 1.1 thorpej (ifp->if_flags & IFF_RUNNING) != 0) {
562 1.1 thorpej /*
563 1.1 thorpej * If interface is marked down and it is running, then
564 1.1 thorpej * stop it.
565 1.1 thorpej */
566 1.19 thorpej epic_stop(sc, 1);
567 1.1 thorpej } else if ((ifp->if_flags & IFF_UP) != 0 &&
568 1.1 thorpej (ifp->if_flags & IFF_RUNNING) == 0) {
569 1.1 thorpej /*
570 1.1 thorpej * If interfase it marked up and it is stopped, then
571 1.1 thorpej * start it.
572 1.1 thorpej */
573 1.19 thorpej error = epic_init(sc);
574 1.10 thorpej } else if ((ifp->if_flags & IFF_UP) != 0) {
575 1.1 thorpej /*
576 1.1 thorpej * Reset the interface to pick up changes in any other
577 1.1 thorpej * flags that affect the hardware state.
578 1.1 thorpej */
579 1.19 thorpej error = epic_init(sc);
580 1.1 thorpej }
581 1.1 thorpej break;
582 1.1 thorpej
583 1.1 thorpej case SIOCADDMULTI:
584 1.1 thorpej case SIOCDELMULTI:
585 1.1 thorpej error = (cmd == SIOCADDMULTI) ?
586 1.1 thorpej ether_addmulti(ifr, &sc->sc_ethercom) :
587 1.1 thorpej ether_delmulti(ifr, &sc->sc_ethercom);
588 1.1 thorpej
589 1.1 thorpej if (error == ENETRESET) {
590 1.1 thorpej /*
591 1.1 thorpej * Multicast list has changed; set the hardware filter
592 1.13 thorpej * accordingly. Update our idea of the current media;
593 1.13 thorpej * epic_set_mchash() needs to know what it is.
594 1.1 thorpej */
595 1.13 thorpej mii_pollstat(&sc->sc_mii);
596 1.13 thorpej epic_set_mchash(sc);
597 1.1 thorpej error = 0;
598 1.1 thorpej }
599 1.1 thorpej break;
600 1.1 thorpej
601 1.8 thorpej case SIOCSIFMEDIA:
602 1.8 thorpej case SIOCGIFMEDIA:
603 1.8 thorpej error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
604 1.8 thorpej break;
605 1.8 thorpej
606 1.1 thorpej default:
607 1.1 thorpej error = EINVAL;
608 1.1 thorpej break;
609 1.1 thorpej }
610 1.1 thorpej
611 1.1 thorpej splx(s);
612 1.1 thorpej return (error);
613 1.1 thorpej }
614 1.1 thorpej
615 1.1 thorpej /*
616 1.1 thorpej * Interrupt handler.
617 1.1 thorpej */
618 1.1 thorpej int
619 1.1 thorpej epic_intr(arg)
620 1.1 thorpej void *arg;
621 1.1 thorpej {
622 1.1 thorpej struct epic_softc *sc = arg;
623 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
624 1.1 thorpej struct ether_header *eh;
625 1.1 thorpej struct epic_rxdesc *rxd;
626 1.1 thorpej struct epic_txdesc *txd;
627 1.1 thorpej struct epic_descsoft *ds;
628 1.1 thorpej struct mbuf *m;
629 1.1 thorpej u_int32_t intstat;
630 1.10 thorpej int i, len, claimed = 0;
631 1.1 thorpej
632 1.1 thorpej top:
633 1.1 thorpej /*
634 1.1 thorpej * Get the interrupt status from the EPIC.
635 1.1 thorpej */
636 1.1 thorpej intstat = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_INTSTAT);
637 1.1 thorpej if ((intstat & INTSTAT_INT_ACTV) == 0)
638 1.1 thorpej return (claimed);
639 1.1 thorpej
640 1.1 thorpej claimed = 1;
641 1.1 thorpej
642 1.1 thorpej /*
643 1.1 thorpej * Acknowledge the interrupt.
644 1.1 thorpej */
645 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_INTSTAT,
646 1.1 thorpej intstat & INTMASK);
647 1.1 thorpej
648 1.1 thorpej /*
649 1.1 thorpej * Check for receive interrupts.
650 1.1 thorpej */
651 1.21 thorpej if (intstat & (INTSTAT_RCC | INTSTAT_RXE | INTSTAT_RQE)) {
652 1.1 thorpej for (i = sc->sc_rxptr;; i = EPIC_NEXTRX(i)) {
653 1.10 thorpej rxd = EPIC_CDRX(sc, i);
654 1.10 thorpej ds = EPIC_DSRX(sc, i);
655 1.10 thorpej
656 1.10 thorpej EPIC_CDRXSYNC(sc, i,
657 1.10 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
658 1.1 thorpej
659 1.1 thorpej if (rxd->er_rxstatus & ER_RXSTAT_OWNER) {
660 1.1 thorpej /*
661 1.1 thorpej * We have processed all of the
662 1.1 thorpej * receive buffers.
663 1.1 thorpej */
664 1.1 thorpej break;
665 1.1 thorpej }
666 1.1 thorpej
667 1.1 thorpej /*
668 1.10 thorpej * Make sure the packet arrived intact. If an error
669 1.10 thorpej * occurred, update stats and reset the descriptor.
670 1.10 thorpej * The buffer will be reused the next time the
671 1.10 thorpej * descriptor comes up in the ring.
672 1.1 thorpej */
673 1.1 thorpej if ((rxd->er_rxstatus & ER_RXSTAT_PKTINTACT) == 0) {
674 1.1 thorpej if (rxd->er_rxstatus & ER_RXSTAT_CRCERROR)
675 1.1 thorpej printf("%s: CRC error\n",
676 1.1 thorpej sc->sc_dev.dv_xname);
677 1.1 thorpej if (rxd->er_rxstatus & ER_RXSTAT_ALIGNERROR)
678 1.1 thorpej printf("%s: alignment error\n",
679 1.1 thorpej sc->sc_dev.dv_xname);
680 1.1 thorpej ifp->if_ierrors++;
681 1.10 thorpej EPIC_INIT_RXDESC(sc, i);
682 1.10 thorpej continue;
683 1.1 thorpej }
684 1.1 thorpej
685 1.10 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
686 1.10 thorpej ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
687 1.10 thorpej
688 1.21 thorpej /*
689 1.21 thorpej * The EPIC includes the CRC with every packet;
690 1.21 thorpej * trim it.
691 1.21 thorpej */
692 1.21 thorpej len = rxd->er_rxlength - ETHER_CRC_LEN;
693 1.21 thorpej
694 1.19 thorpej if (len < sizeof(struct ether_header)) {
695 1.19 thorpej /*
696 1.19 thorpej * Runt packet; drop it now.
697 1.19 thorpej */
698 1.10 thorpej ifp->if_ierrors++;
699 1.10 thorpej EPIC_INIT_RXDESC(sc, i);
700 1.10 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
701 1.10 thorpej ds->ds_dmamap->dm_mapsize,
702 1.10 thorpej BUS_DMASYNC_PREREAD);
703 1.10 thorpej continue;
704 1.10 thorpej }
705 1.10 thorpej
706 1.19 thorpej /*
707 1.19 thorpej * If the packet is small enough to fit in a
708 1.19 thorpej * single header mbuf, allocate one and copy
709 1.19 thorpej * the data into it. This greatly reduces
710 1.19 thorpej * memory consumption when we receive lots
711 1.19 thorpej * of small packets.
712 1.19 thorpej *
713 1.19 thorpej * Otherwise, we add a new buffer to the receive
714 1.19 thorpej * chain. If this fails, we drop the packet and
715 1.19 thorpej * recycle the old buffer.
716 1.19 thorpej */
717 1.19 thorpej if (epic_copy_small != 0 && len <= MHLEN) {
718 1.19 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA);
719 1.19 thorpej if (m == NULL)
720 1.19 thorpej goto dropit;
721 1.19 thorpej memcpy(mtod(m, caddr_t),
722 1.19 thorpej mtod(ds->ds_mbuf, caddr_t), len);
723 1.19 thorpej EPIC_INIT_RXDESC(sc, i);
724 1.19 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
725 1.19 thorpej ds->ds_dmamap->dm_mapsize,
726 1.19 thorpej BUS_DMASYNC_PREREAD);
727 1.19 thorpej } else {
728 1.19 thorpej m = ds->ds_mbuf;
729 1.19 thorpej if (epic_add_rxbuf(sc, i) != 0) {
730 1.19 thorpej dropit:
731 1.19 thorpej ifp->if_ierrors++;
732 1.19 thorpej EPIC_INIT_RXDESC(sc, i);
733 1.19 thorpej bus_dmamap_sync(sc->sc_dmat,
734 1.19 thorpej ds->ds_dmamap, 0,
735 1.19 thorpej ds->ds_dmamap->dm_mapsize,
736 1.19 thorpej BUS_DMASYNC_PREREAD);
737 1.19 thorpej continue;
738 1.19 thorpej }
739 1.10 thorpej }
740 1.10 thorpej
741 1.10 thorpej m->m_pkthdr.rcvif = ifp;
742 1.10 thorpej m->m_pkthdr.len = m->m_len = len;
743 1.10 thorpej eh = mtod(m, struct ether_header *);
744 1.1 thorpej
745 1.10 thorpej #if NBPFILTER > 0
746 1.10 thorpej /*
747 1.10 thorpej * Pass this up to any BPF listeners, but only
748 1.10 thorpej * pass it up the stack if its for us.
749 1.10 thorpej */
750 1.10 thorpej if (ifp->if_bpf) {
751 1.10 thorpej bpf_mtap(ifp->if_bpf, m);
752 1.10 thorpej if ((ifp->if_flags & IFF_PROMISC) != 0 &&
753 1.26 thorpej memcmp(LLADDR(ifp->if_sadl),
754 1.26 thorpej eh->ether_dhost,
755 1.26 thorpej ETHER_ADDR_LEN) != 0 &&
756 1.26 thorpej ETHER_IS_MULTICAST(eh->ether_dhost) == 0) {
757 1.1 thorpej m_freem(m);
758 1.1 thorpej continue;
759 1.1 thorpej }
760 1.10 thorpej }
761 1.1 thorpej #endif /* NPBFILTER > 0 */
762 1.10 thorpej
763 1.16 thorpej /* Pass it on. */
764 1.16 thorpej (*ifp->if_input)(ifp, m);
765 1.17 thorpej ifp->if_ipackets++;
766 1.1 thorpej }
767 1.10 thorpej
768 1.10 thorpej /* Update the recieve pointer. */
769 1.1 thorpej sc->sc_rxptr = i;
770 1.1 thorpej
771 1.1 thorpej /*
772 1.1 thorpej * Check for receive queue underflow.
773 1.1 thorpej */
774 1.1 thorpej if (intstat & INTSTAT_RQE) {
775 1.1 thorpej printf("%s: receiver queue empty\n",
776 1.1 thorpej sc->sc_dev.dv_xname);
777 1.1 thorpej /*
778 1.1 thorpej * Ring is already built; just restart the
779 1.1 thorpej * receiver.
780 1.1 thorpej */
781 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_PRCDAR,
782 1.10 thorpej EPIC_CDRXADDR(sc, sc->sc_rxptr));
783 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_COMMAND,
784 1.1 thorpej COMMAND_RXQUEUED | COMMAND_START_RX);
785 1.1 thorpej }
786 1.1 thorpej }
787 1.1 thorpej
788 1.1 thorpej /*
789 1.1 thorpej * Check for transmission complete interrupts.
790 1.1 thorpej */
791 1.1 thorpej if (intstat & (INTSTAT_TXC | INTSTAT_TXU)) {
792 1.10 thorpej ifp->if_flags &= ~IFF_OACTIVE;
793 1.10 thorpej for (i = sc->sc_txdirty; sc->sc_txpending != 0;
794 1.10 thorpej i = EPIC_NEXTTX(i), sc->sc_txpending--) {
795 1.10 thorpej txd = EPIC_CDTX(sc, i);
796 1.10 thorpej ds = EPIC_DSTX(sc, i);
797 1.1 thorpej
798 1.10 thorpej EPIC_CDTXSYNC(sc, i,
799 1.10 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
800 1.10 thorpej
801 1.10 thorpej if (txd->et_txstatus & ET_TXSTAT_OWNER)
802 1.1 thorpej break;
803 1.1 thorpej
804 1.10 thorpej EPIC_CDFLSYNC(sc, i, BUS_DMASYNC_POSTWRITE);
805 1.10 thorpej
806 1.10 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap,
807 1.10 thorpej 0, ds->ds_dmamap->dm_mapsize,
808 1.10 thorpej BUS_DMASYNC_POSTWRITE);
809 1.10 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
810 1.10 thorpej m_freem(ds->ds_mbuf);
811 1.10 thorpej ds->ds_mbuf = NULL;
812 1.1 thorpej
813 1.1 thorpej /*
814 1.1 thorpej * Check for errors and collisions.
815 1.1 thorpej */
816 1.1 thorpej if ((txd->et_txstatus & ET_TXSTAT_PACKETTX) == 0)
817 1.1 thorpej ifp->if_oerrors++;
818 1.10 thorpej else
819 1.10 thorpej ifp->if_opackets++;
820 1.1 thorpej ifp->if_collisions +=
821 1.1 thorpej TXSTAT_COLLISIONS(txd->et_txstatus);
822 1.10 thorpej if (txd->et_txstatus & ET_TXSTAT_CARSENSELOST)
823 1.1 thorpej printf("%s: lost carrier\n",
824 1.1 thorpej sc->sc_dev.dv_xname);
825 1.1 thorpej }
826 1.1 thorpej
827 1.10 thorpej /* Update the dirty transmit buffer pointer. */
828 1.1 thorpej sc->sc_txdirty = i;
829 1.1 thorpej
830 1.1 thorpej /*
831 1.1 thorpej * Cancel the watchdog timer if there are no pending
832 1.1 thorpej * transmissions.
833 1.1 thorpej */
834 1.1 thorpej if (sc->sc_txpending == 0)
835 1.1 thorpej ifp->if_timer = 0;
836 1.1 thorpej
837 1.1 thorpej /*
838 1.1 thorpej * Kick the transmitter after a DMA underrun.
839 1.1 thorpej */
840 1.1 thorpej if (intstat & INTSTAT_TXU) {
841 1.1 thorpej printf("%s: transmit underrun\n", sc->sc_dev.dv_xname);
842 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh,
843 1.1 thorpej EPIC_COMMAND, COMMAND_TXUGO);
844 1.1 thorpej if (sc->sc_txpending)
845 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh,
846 1.1 thorpej EPIC_COMMAND, COMMAND_TXQUEUED);
847 1.1 thorpej }
848 1.1 thorpej
849 1.1 thorpej /*
850 1.1 thorpej * Try to get more packets going.
851 1.1 thorpej */
852 1.1 thorpej epic_start(ifp);
853 1.1 thorpej }
854 1.1 thorpej
855 1.1 thorpej /*
856 1.1 thorpej * Check for fatal interrupts.
857 1.1 thorpej */
858 1.1 thorpej if (intstat & INTSTAT_FATAL_INT) {
859 1.21 thorpej if (intstat & INTSTAT_PTA)
860 1.21 thorpej printf("%s: PCI target abort error\n",
861 1.21 thorpej sc->sc_dev.dv_xname);
862 1.21 thorpej else if (intstat & INTSTAT_PMA)
863 1.21 thorpej printf("%s: PCI master abort error\n",
864 1.21 thorpej sc->sc_dev.dv_xname);
865 1.21 thorpej else if (intstat & INTSTAT_APE)
866 1.21 thorpej printf("%s: PCI address parity error\n",
867 1.21 thorpej sc->sc_dev.dv_xname);
868 1.21 thorpej else if (intstat & INTSTAT_DPE)
869 1.21 thorpej printf("%s: PCI data parity error\n",
870 1.21 thorpej sc->sc_dev.dv_xname);
871 1.21 thorpej else
872 1.21 thorpej printf("%s: unknown fatal error\n",
873 1.21 thorpej sc->sc_dev.dv_xname);
874 1.19 thorpej (void) epic_init(sc);
875 1.1 thorpej }
876 1.1 thorpej
877 1.1 thorpej /*
878 1.1 thorpej * Check for more interrupts.
879 1.1 thorpej */
880 1.1 thorpej goto top;
881 1.1 thorpej }
882 1.1 thorpej
883 1.1 thorpej /*
884 1.8 thorpej * One second timer, used to tick the MII.
885 1.8 thorpej */
886 1.8 thorpej void
887 1.8 thorpej epic_tick(arg)
888 1.8 thorpej void *arg;
889 1.8 thorpej {
890 1.8 thorpej struct epic_softc *sc = arg;
891 1.8 thorpej int s;
892 1.8 thorpej
893 1.12 thorpej s = splnet();
894 1.8 thorpej mii_tick(&sc->sc_mii);
895 1.8 thorpej splx(s);
896 1.8 thorpej
897 1.29 thorpej callout_reset(&sc->sc_mii_callout, hz, epic_tick, sc);
898 1.8 thorpej }
899 1.8 thorpej
900 1.8 thorpej /*
901 1.6 thorpej * Fixup the clock source on the EPIC.
902 1.6 thorpej */
903 1.6 thorpej void
904 1.6 thorpej epic_fixup_clock_source(sc)
905 1.6 thorpej struct epic_softc *sc;
906 1.6 thorpej {
907 1.6 thorpej int i;
908 1.6 thorpej
909 1.6 thorpej /*
910 1.6 thorpej * According to SMC Application Note 7-15, the EPIC's clock
911 1.6 thorpej * source is incorrect following a reset. This manifests itself
912 1.6 thorpej * as failure to recognize when host software has written to
913 1.6 thorpej * a register on the EPIC. The appnote recommends issuing at
914 1.6 thorpej * least 16 consecutive writes to the CLOCK TEST bit to correctly
915 1.6 thorpej * configure the clock source.
916 1.6 thorpej */
917 1.6 thorpej for (i = 0; i < 16; i++)
918 1.6 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_TEST,
919 1.6 thorpej TEST_CLOCKTEST);
920 1.6 thorpej }
921 1.6 thorpej
922 1.6 thorpej /*
923 1.1 thorpej * Perform a soft reset on the EPIC.
924 1.1 thorpej */
925 1.1 thorpej void
926 1.1 thorpej epic_reset(sc)
927 1.1 thorpej struct epic_softc *sc;
928 1.1 thorpej {
929 1.1 thorpej
930 1.6 thorpej epic_fixup_clock_source(sc);
931 1.6 thorpej
932 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_GENCTL, 0);
933 1.1 thorpej delay(100);
934 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_GENCTL, GENCTL_SOFTRESET);
935 1.1 thorpej delay(100);
936 1.6 thorpej
937 1.6 thorpej epic_fixup_clock_source(sc);
938 1.1 thorpej }
939 1.1 thorpej
940 1.1 thorpej /*
941 1.7 mycroft * Initialize the interface. Must be called at splnet().
942 1.1 thorpej */
943 1.19 thorpej int
944 1.1 thorpej epic_init(sc)
945 1.1 thorpej struct epic_softc *sc;
946 1.1 thorpej {
947 1.1 thorpej bus_space_tag_t st = sc->sc_st;
948 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
949 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
950 1.1 thorpej u_int8_t *enaddr = LLADDR(ifp->if_sadl);
951 1.1 thorpej struct epic_txdesc *txd;
952 1.19 thorpej struct epic_descsoft *ds;
953 1.1 thorpej u_int32_t genctl, reg0;
954 1.19 thorpej int i, error = 0;
955 1.1 thorpej
956 1.1 thorpej /*
957 1.1 thorpej * Cancel any pending I/O.
958 1.1 thorpej */
959 1.19 thorpej epic_stop(sc, 0);
960 1.1 thorpej
961 1.1 thorpej /*
962 1.1 thorpej * Reset the EPIC to a known state.
963 1.1 thorpej */
964 1.1 thorpej epic_reset(sc);
965 1.1 thorpej
966 1.1 thorpej /*
967 1.1 thorpej * Magical mystery initialization.
968 1.1 thorpej */
969 1.1 thorpej bus_space_write_4(st, sh, EPIC_TXTEST, 0);
970 1.1 thorpej
971 1.1 thorpej /*
972 1.1 thorpej * Initialize the EPIC genctl register:
973 1.1 thorpej *
974 1.1 thorpej * - 64 byte receive FIFO threshold
975 1.1 thorpej * - automatic advance to next receive frame
976 1.1 thorpej */
977 1.1 thorpej genctl = GENCTL_RX_FIFO_THRESH0 | GENCTL_ONECOPY;
978 1.18 thorpej #if BYTE_ORDER == BIG_ENDIAN
979 1.18 thorpej genctl |= GENCTL_BIG_ENDIAN;
980 1.18 thorpej #endif
981 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl);
982 1.1 thorpej
983 1.1 thorpej /*
984 1.1 thorpej * Reset the MII bus and PHY.
985 1.1 thorpej */
986 1.1 thorpej reg0 = bus_space_read_4(st, sh, EPIC_NVCTL);
987 1.1 thorpej bus_space_write_4(st, sh, EPIC_NVCTL, reg0 | NVCTL_GPIO1 | NVCTL_GPOE1);
988 1.1 thorpej bus_space_write_4(st, sh, EPIC_MIICFG, MIICFG_ENASER);
989 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl | GENCTL_RESET_PHY);
990 1.1 thorpej delay(100);
991 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl);
992 1.1 thorpej delay(100);
993 1.1 thorpej bus_space_write_4(st, sh, EPIC_NVCTL, reg0);
994 1.1 thorpej
995 1.1 thorpej /*
996 1.1 thorpej * Initialize Ethernet address.
997 1.1 thorpej */
998 1.1 thorpej reg0 = enaddr[1] << 8 | enaddr[0];
999 1.1 thorpej bus_space_write_4(st, sh, EPIC_LAN0, reg0);
1000 1.1 thorpej reg0 = enaddr[3] << 8 | enaddr[2];
1001 1.1 thorpej bus_space_write_4(st, sh, EPIC_LAN1, reg0);
1002 1.1 thorpej reg0 = enaddr[5] << 8 | enaddr[4];
1003 1.1 thorpej bus_space_write_4(st, sh, EPIC_LAN2, reg0);
1004 1.1 thorpej
1005 1.1 thorpej /*
1006 1.1 thorpej * Initialize receive control. Remember the external buffer
1007 1.1 thorpej * size setting.
1008 1.1 thorpej */
1009 1.1 thorpej reg0 = bus_space_read_4(st, sh, EPIC_RXCON) &
1010 1.1 thorpej (RXCON_EXTBUFSIZESEL1 | RXCON_EXTBUFSIZESEL0);
1011 1.1 thorpej reg0 |= (RXCON_RXMULTICAST | RXCON_RXBROADCAST);
1012 1.1 thorpej if (ifp->if_flags & IFF_PROMISC)
1013 1.1 thorpej reg0 |= RXCON_PROMISCMODE;
1014 1.1 thorpej bus_space_write_4(st, sh, EPIC_RXCON, reg0);
1015 1.1 thorpej
1016 1.13 thorpej /* Set the current media. */
1017 1.8 thorpej mii_mediachg(&sc->sc_mii);
1018 1.1 thorpej
1019 1.13 thorpej /* Set up the multicast hash table. */
1020 1.13 thorpej epic_set_mchash(sc);
1021 1.13 thorpej
1022 1.1 thorpej /*
1023 1.10 thorpej * Initialize the transmit descriptor ring. txlast is initialized
1024 1.10 thorpej * to the end of the list so that it will wrap around to the first
1025 1.10 thorpej * descriptor when the first packet is transmitted.
1026 1.1 thorpej */
1027 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++) {
1028 1.10 thorpej txd = EPIC_CDTX(sc, i);
1029 1.10 thorpej memset(txd, 0, sizeof(struct epic_txdesc));
1030 1.10 thorpej txd->et_bufaddr = EPIC_CDFLADDR(sc, i);
1031 1.10 thorpej txd->et_nextdesc = EPIC_CDTXADDR(sc, EPIC_NEXTTX(i));
1032 1.10 thorpej EPIC_CDTXSYNC(sc, i, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1033 1.1 thorpej }
1034 1.10 thorpej sc->sc_txpending = 0;
1035 1.10 thorpej sc->sc_txdirty = 0;
1036 1.10 thorpej sc->sc_txlast = EPIC_NTXDESC - 1;
1037 1.1 thorpej
1038 1.1 thorpej /*
1039 1.19 thorpej * Initialize the receive descriptor ring.
1040 1.1 thorpej */
1041 1.19 thorpej for (i = 0; i < EPIC_NRXDESC; i++) {
1042 1.19 thorpej ds = EPIC_DSRX(sc, i);
1043 1.19 thorpej if (ds->ds_mbuf == NULL) {
1044 1.19 thorpej if ((error = epic_add_rxbuf(sc, i)) != 0) {
1045 1.19 thorpej printf("%s: unable to allocate or map rx "
1046 1.19 thorpej "buffer %d error = %d\n",
1047 1.19 thorpej sc->sc_dev.dv_xname, i, error);
1048 1.19 thorpej /*
1049 1.19 thorpej * XXX Should attempt to run with fewer receive
1050 1.19 thorpej * XXX buffers instead of just failing.
1051 1.19 thorpej */
1052 1.19 thorpej epic_rxdrain(sc);
1053 1.19 thorpej goto out;
1054 1.19 thorpej }
1055 1.19 thorpej }
1056 1.19 thorpej }
1057 1.10 thorpej sc->sc_rxptr = 0;
1058 1.1 thorpej
1059 1.1 thorpej /*
1060 1.1 thorpej * Initialize the interrupt mask and enable interrupts.
1061 1.1 thorpej */
1062 1.1 thorpej bus_space_write_4(st, sh, EPIC_INTMASK, INTMASK);
1063 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl | GENCTL_INTENA);
1064 1.1 thorpej
1065 1.1 thorpej /*
1066 1.1 thorpej * Give the transmit and receive rings to the EPIC.
1067 1.1 thorpej */
1068 1.1 thorpej bus_space_write_4(st, sh, EPIC_PTCDAR,
1069 1.10 thorpej EPIC_CDTXADDR(sc, EPIC_NEXTTX(sc->sc_txlast)));
1070 1.1 thorpej bus_space_write_4(st, sh, EPIC_PRCDAR,
1071 1.10 thorpej EPIC_CDRXADDR(sc, sc->sc_rxptr));
1072 1.1 thorpej
1073 1.1 thorpej /*
1074 1.1 thorpej * Set the EPIC in motion.
1075 1.1 thorpej */
1076 1.1 thorpej bus_space_write_4(st, sh, EPIC_COMMAND,
1077 1.1 thorpej COMMAND_RXQUEUED | COMMAND_START_RX);
1078 1.1 thorpej
1079 1.1 thorpej /*
1080 1.1 thorpej * ...all done!
1081 1.1 thorpej */
1082 1.1 thorpej ifp->if_flags |= IFF_RUNNING;
1083 1.1 thorpej ifp->if_flags &= ~IFF_OACTIVE;
1084 1.8 thorpej
1085 1.8 thorpej /*
1086 1.8 thorpej * Start the one second clock.
1087 1.8 thorpej */
1088 1.29 thorpej callout_reset(&sc->sc_mii_callout, hz, epic_tick, sc);
1089 1.9 thorpej
1090 1.9 thorpej /*
1091 1.9 thorpej * Attempt to start output on the interface.
1092 1.9 thorpej */
1093 1.9 thorpej epic_start(ifp);
1094 1.19 thorpej
1095 1.19 thorpej out:
1096 1.19 thorpej if (error)
1097 1.19 thorpej printf("%s: interface not running\n", sc->sc_dev.dv_xname);
1098 1.19 thorpej return (error);
1099 1.19 thorpej }
1100 1.19 thorpej
1101 1.19 thorpej /*
1102 1.19 thorpej * Drain the receive queue.
1103 1.19 thorpej */
1104 1.19 thorpej void
1105 1.19 thorpej epic_rxdrain(sc)
1106 1.19 thorpej struct epic_softc *sc;
1107 1.19 thorpej {
1108 1.19 thorpej struct epic_descsoft *ds;
1109 1.19 thorpej int i;
1110 1.19 thorpej
1111 1.19 thorpej for (i = 0; i < EPIC_NRXDESC; i++) {
1112 1.19 thorpej ds = EPIC_DSRX(sc, i);
1113 1.19 thorpej if (ds->ds_mbuf != NULL) {
1114 1.19 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
1115 1.19 thorpej m_freem(ds->ds_mbuf);
1116 1.19 thorpej ds->ds_mbuf = NULL;
1117 1.19 thorpej }
1118 1.19 thorpej }
1119 1.1 thorpej }
1120 1.1 thorpej
1121 1.1 thorpej /*
1122 1.1 thorpej * Stop transmission on the interface.
1123 1.1 thorpej */
1124 1.1 thorpej void
1125 1.19 thorpej epic_stop(sc, drain)
1126 1.1 thorpej struct epic_softc *sc;
1127 1.19 thorpej int drain;
1128 1.1 thorpej {
1129 1.1 thorpej bus_space_tag_t st = sc->sc_st;
1130 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
1131 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1132 1.1 thorpej struct epic_descsoft *ds;
1133 1.1 thorpej u_int32_t reg;
1134 1.1 thorpej int i;
1135 1.6 thorpej
1136 1.8 thorpej /*
1137 1.8 thorpej * Stop the one second clock.
1138 1.8 thorpej */
1139 1.29 thorpej callout_stop(&sc->sc_mii_callout);
1140 1.23 thorpej
1141 1.23 thorpej /* Down the MII. */
1142 1.23 thorpej mii_down(&sc->sc_mii);
1143 1.8 thorpej
1144 1.6 thorpej /* Paranoia... */
1145 1.6 thorpej epic_fixup_clock_source(sc);
1146 1.1 thorpej
1147 1.1 thorpej /*
1148 1.1 thorpej * Disable interrupts.
1149 1.1 thorpej */
1150 1.1 thorpej reg = bus_space_read_4(st, sh, EPIC_GENCTL);
1151 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, reg & ~GENCTL_INTENA);
1152 1.1 thorpej bus_space_write_4(st, sh, EPIC_INTMASK, 0);
1153 1.1 thorpej
1154 1.1 thorpej /*
1155 1.1 thorpej * Stop the DMA engine and take the receiver off-line.
1156 1.1 thorpej */
1157 1.1 thorpej bus_space_write_4(st, sh, EPIC_COMMAND, COMMAND_STOP_RDMA |
1158 1.1 thorpej COMMAND_STOP_TDMA | COMMAND_STOP_RX);
1159 1.1 thorpej
1160 1.1 thorpej /*
1161 1.1 thorpej * Release any queued transmit buffers.
1162 1.1 thorpej */
1163 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++) {
1164 1.10 thorpej ds = EPIC_DSTX(sc, i);
1165 1.1 thorpej if (ds->ds_mbuf != NULL) {
1166 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
1167 1.1 thorpej m_freem(ds->ds_mbuf);
1168 1.1 thorpej ds->ds_mbuf = NULL;
1169 1.1 thorpej }
1170 1.19 thorpej }
1171 1.19 thorpej
1172 1.19 thorpej if (drain) {
1173 1.19 thorpej /*
1174 1.19 thorpej * Release the receive buffers.
1175 1.19 thorpej */
1176 1.19 thorpej epic_rxdrain(sc);
1177 1.1 thorpej }
1178 1.1 thorpej
1179 1.1 thorpej /*
1180 1.1 thorpej * Mark the interface down and cancel the watchdog timer.
1181 1.1 thorpej */
1182 1.1 thorpej ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1183 1.1 thorpej ifp->if_timer = 0;
1184 1.1 thorpej }
1185 1.1 thorpej
1186 1.1 thorpej /*
1187 1.1 thorpej * Read the EPIC Serial EEPROM.
1188 1.1 thorpej */
1189 1.1 thorpej void
1190 1.1 thorpej epic_read_eeprom(sc, word, wordcnt, data)
1191 1.1 thorpej struct epic_softc *sc;
1192 1.1 thorpej int word, wordcnt;
1193 1.1 thorpej u_int16_t *data;
1194 1.1 thorpej {
1195 1.1 thorpej bus_space_tag_t st = sc->sc_st;
1196 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
1197 1.1 thorpej u_int16_t reg;
1198 1.1 thorpej int i, x;
1199 1.1 thorpej
1200 1.1 thorpej #define EEPROM_WAIT_READY(st, sh) \
1201 1.1 thorpej while ((bus_space_read_4((st), (sh), EPIC_EECTL) & EECTL_EERDY) == 0) \
1202 1.1 thorpej /* nothing */
1203 1.1 thorpej
1204 1.1 thorpej /*
1205 1.1 thorpej * Enable the EEPROM.
1206 1.1 thorpej */
1207 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE);
1208 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1209 1.1 thorpej
1210 1.1 thorpej for (i = 0; i < wordcnt; i++) {
1211 1.1 thorpej /* Send CHIP SELECT for one clock tick. */
1212 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE|EECTL_EECS);
1213 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1214 1.1 thorpej
1215 1.1 thorpej /* Shift in the READ opcode. */
1216 1.1 thorpej for (x = 3; x > 0; x--) {
1217 1.1 thorpej reg = EECTL_ENABLE|EECTL_EECS;
1218 1.1 thorpej if (EPIC_EEPROM_OPC_READ & (1 << (x - 1)))
1219 1.1 thorpej reg |= EECTL_EEDI;
1220 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1221 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1222 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg|EECTL_EESK);
1223 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1224 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1225 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1226 1.1 thorpej }
1227 1.1 thorpej
1228 1.1 thorpej /* Shift in address. */
1229 1.1 thorpej for (x = 6; x > 0; x--) {
1230 1.1 thorpej reg = EECTL_ENABLE|EECTL_EECS;
1231 1.1 thorpej if ((word + i) & (1 << (x - 1)))
1232 1.1 thorpej reg |= EECTL_EEDI;
1233 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1234 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1235 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg|EECTL_EESK);
1236 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1237 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1238 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1239 1.1 thorpej }
1240 1.1 thorpej
1241 1.1 thorpej /* Shift out data. */
1242 1.1 thorpej reg = EECTL_ENABLE|EECTL_EECS;
1243 1.1 thorpej data[i] = 0;
1244 1.1 thorpej for (x = 16; x > 0; x--) {
1245 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg|EECTL_EESK);
1246 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1247 1.1 thorpej if (bus_space_read_4(st, sh, EPIC_EECTL) & EECTL_EEDO)
1248 1.1 thorpej data[i] |= (1 << (x - 1));
1249 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1250 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1251 1.1 thorpej }
1252 1.1 thorpej
1253 1.1 thorpej /* Clear CHIP SELECT. */
1254 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE);
1255 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1256 1.1 thorpej }
1257 1.1 thorpej
1258 1.1 thorpej /*
1259 1.1 thorpej * Disable the EEPROM.
1260 1.1 thorpej */
1261 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, 0);
1262 1.1 thorpej
1263 1.1 thorpej #undef EEPROM_WAIT_READY
1264 1.1 thorpej }
1265 1.1 thorpej
1266 1.1 thorpej /*
1267 1.1 thorpej * Add a receive buffer to the indicated descriptor.
1268 1.1 thorpej */
1269 1.1 thorpej int
1270 1.1 thorpej epic_add_rxbuf(sc, idx)
1271 1.1 thorpej struct epic_softc *sc;
1272 1.1 thorpej int idx;
1273 1.1 thorpej {
1274 1.10 thorpej struct epic_descsoft *ds = EPIC_DSRX(sc, idx);
1275 1.10 thorpej struct mbuf *m;
1276 1.10 thorpej int error;
1277 1.1 thorpej
1278 1.10 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA);
1279 1.10 thorpej if (m == NULL)
1280 1.10 thorpej return (ENOBUFS);
1281 1.1 thorpej
1282 1.10 thorpej MCLGET(m, M_DONTWAIT);
1283 1.10 thorpej if ((m->m_flags & M_EXT) == 0) {
1284 1.10 thorpej m_freem(m);
1285 1.10 thorpej return (ENOBUFS);
1286 1.1 thorpej }
1287 1.1 thorpej
1288 1.10 thorpej if (ds->ds_mbuf != NULL)
1289 1.10 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
1290 1.10 thorpej
1291 1.1 thorpej ds->ds_mbuf = m;
1292 1.1 thorpej
1293 1.10 thorpej error = bus_dmamap_load(sc->sc_dmat, ds->ds_dmamap,
1294 1.10 thorpej m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
1295 1.10 thorpej if (error) {
1296 1.10 thorpej printf("%s: can't load rx DMA map %d, error = %d\n",
1297 1.10 thorpej sc->sc_dev.dv_xname, idx, error);
1298 1.10 thorpej panic("epic_add_rxbuf"); /* XXX */
1299 1.1 thorpej }
1300 1.1 thorpej
1301 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
1302 1.1 thorpej ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1303 1.1 thorpej
1304 1.10 thorpej EPIC_INIT_RXDESC(sc, idx);
1305 1.1 thorpej
1306 1.10 thorpej return (0);
1307 1.1 thorpej }
1308 1.1 thorpej
1309 1.1 thorpej /*
1310 1.1 thorpej * Set the EPIC multicast hash table.
1311 1.13 thorpej *
1312 1.13 thorpej * NOTE: We rely on a recently-updated mii_media_active here!
1313 1.1 thorpej */
1314 1.1 thorpej void
1315 1.1 thorpej epic_set_mchash(sc)
1316 1.1 thorpej struct epic_softc *sc;
1317 1.1 thorpej {
1318 1.1 thorpej struct ethercom *ec = &sc->sc_ethercom;
1319 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1320 1.1 thorpej struct ether_multi *enm;
1321 1.1 thorpej struct ether_multistep step;
1322 1.1 thorpej u_int8_t *cp;
1323 1.1 thorpej u_int32_t crc, mchash[4];
1324 1.1 thorpej int len;
1325 1.1 thorpej static const u_int32_t crctab[] = {
1326 1.1 thorpej 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1327 1.1 thorpej 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1328 1.1 thorpej 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1329 1.1 thorpej 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1330 1.1 thorpej };
1331 1.1 thorpej
1332 1.1 thorpej /*
1333 1.1 thorpej * Set up the multicast address filter by passing all multicast
1334 1.1 thorpej * addresses through a CRC generator, and then using the high-order
1335 1.1 thorpej * 6 bits as an index into the 64 bit multicast hash table (only
1336 1.1 thorpej * the lower 16 bits of each 32 bit multicast hash register are
1337 1.1 thorpej * valid). The high order bit selects the register, while the
1338 1.1 thorpej * rest of the bits select the bit within the register.
1339 1.1 thorpej */
1340 1.1 thorpej
1341 1.1 thorpej if (ifp->if_flags & IFF_PROMISC)
1342 1.1 thorpej goto allmulti;
1343 1.1 thorpej
1344 1.13 thorpej if (IFM_SUBTYPE(sc->sc_mii.mii_media_active) == IFM_10_T) {
1345 1.13 thorpej /* XXX hardware bug in 10Mbps mode. */
1346 1.13 thorpej goto allmulti;
1347 1.13 thorpej }
1348 1.1 thorpej
1349 1.1 thorpej mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0;
1350 1.1 thorpej
1351 1.1 thorpej ETHER_FIRST_MULTI(step, ec, enm);
1352 1.1 thorpej while (enm != NULL) {
1353 1.1 thorpej if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1354 1.1 thorpej /*
1355 1.1 thorpej * We must listen to a range of multicast addresses.
1356 1.1 thorpej * For now, just accept all multicasts, rather than
1357 1.1 thorpej * trying to set only those filter bits needed to match
1358 1.1 thorpej * the range. (At this time, the only use of address
1359 1.1 thorpej * ranges is for IP multicast routing, for which the
1360 1.1 thorpej * range is big enough to require all bits set.)
1361 1.1 thorpej */
1362 1.1 thorpej goto allmulti;
1363 1.1 thorpej }
1364 1.1 thorpej
1365 1.1 thorpej cp = enm->enm_addrlo;
1366 1.1 thorpej crc = 0xffffffff;
1367 1.1 thorpej for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
1368 1.1 thorpej crc ^= *cp++;
1369 1.1 thorpej crc = (crc >> 4) ^ crctab[crc & 0xf];
1370 1.1 thorpej crc = (crc >> 4) ^ crctab[crc & 0xf];
1371 1.1 thorpej }
1372 1.1 thorpej /* Just want the 6 most significant bits. */
1373 1.1 thorpej crc >>= 26;
1374 1.1 thorpej
1375 1.1 thorpej /* Set the corresponding bit in the hash table. */
1376 1.1 thorpej mchash[crc >> 4] |= 1 << (crc & 0xf);
1377 1.1 thorpej
1378 1.1 thorpej ETHER_NEXT_MULTI(step, enm);
1379 1.1 thorpej }
1380 1.1 thorpej
1381 1.1 thorpej ifp->if_flags &= ~IFF_ALLMULTI;
1382 1.1 thorpej goto sethash;
1383 1.1 thorpej
1384 1.1 thorpej allmulti:
1385 1.1 thorpej ifp->if_flags |= IFF_ALLMULTI;
1386 1.1 thorpej mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0xffff;
1387 1.1 thorpej
1388 1.1 thorpej sethash:
1389 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC0, mchash[0]);
1390 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC1, mchash[1]);
1391 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC2, mchash[2]);
1392 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC3, mchash[3]);
1393 1.8 thorpej }
1394 1.8 thorpej
1395 1.8 thorpej /*
1396 1.8 thorpej * Wait for the MII to become ready.
1397 1.8 thorpej */
1398 1.8 thorpej int
1399 1.8 thorpej epic_mii_wait(sc, rw)
1400 1.8 thorpej struct epic_softc *sc;
1401 1.8 thorpej u_int32_t rw;
1402 1.8 thorpej {
1403 1.8 thorpej int i;
1404 1.8 thorpej
1405 1.8 thorpej for (i = 0; i < 50; i++) {
1406 1.8 thorpej if ((bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_MMCTL) & rw)
1407 1.8 thorpej == 0)
1408 1.8 thorpej break;
1409 1.8 thorpej delay(2);
1410 1.8 thorpej }
1411 1.8 thorpej if (i == 50) {
1412 1.8 thorpej printf("%s: MII timed out\n", sc->sc_dev.dv_xname);
1413 1.8 thorpej return (1);
1414 1.8 thorpej }
1415 1.8 thorpej
1416 1.8 thorpej return (0);
1417 1.8 thorpej }
1418 1.8 thorpej
1419 1.8 thorpej /*
1420 1.8 thorpej * Read from the MII.
1421 1.8 thorpej */
1422 1.8 thorpej int
1423 1.8 thorpej epic_mii_read(self, phy, reg)
1424 1.8 thorpej struct device *self;
1425 1.8 thorpej int phy, reg;
1426 1.8 thorpej {
1427 1.8 thorpej struct epic_softc *sc = (struct epic_softc *)self;
1428 1.8 thorpej
1429 1.8 thorpej if (epic_mii_wait(sc, MMCTL_WRITE))
1430 1.8 thorpej return (0);
1431 1.8 thorpej
1432 1.8 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MMCTL,
1433 1.8 thorpej MMCTL_ARG(phy, reg, MMCTL_READ));
1434 1.8 thorpej
1435 1.8 thorpej if (epic_mii_wait(sc, MMCTL_READ))
1436 1.8 thorpej return (0);
1437 1.8 thorpej
1438 1.8 thorpej return (bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_MMDATA) &
1439 1.8 thorpej MMDATA_MASK);
1440 1.8 thorpej }
1441 1.8 thorpej
1442 1.8 thorpej /*
1443 1.8 thorpej * Write to the MII.
1444 1.8 thorpej */
1445 1.8 thorpej void
1446 1.8 thorpej epic_mii_write(self, phy, reg, val)
1447 1.8 thorpej struct device *self;
1448 1.8 thorpej int phy, reg, val;
1449 1.8 thorpej {
1450 1.8 thorpej struct epic_softc *sc = (struct epic_softc *)self;
1451 1.8 thorpej
1452 1.8 thorpej if (epic_mii_wait(sc, MMCTL_WRITE))
1453 1.8 thorpej return;
1454 1.8 thorpej
1455 1.8 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MMDATA, val);
1456 1.8 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MMCTL,
1457 1.8 thorpej MMCTL_ARG(phy, reg, MMCTL_WRITE));
1458 1.8 thorpej }
1459 1.8 thorpej
1460 1.8 thorpej /*
1461 1.8 thorpej * Callback from PHY when media changes.
1462 1.8 thorpej */
1463 1.8 thorpej void
1464 1.8 thorpej epic_statchg(self)
1465 1.8 thorpej struct device *self;
1466 1.8 thorpej {
1467 1.11 thorpej struct epic_softc *sc = (struct epic_softc *)self;
1468 1.11 thorpej u_int32_t txcon;
1469 1.11 thorpej
1470 1.11 thorpej /*
1471 1.11 thorpej * Update loopback bits in TXCON to reflect duplex mode.
1472 1.11 thorpej */
1473 1.11 thorpej txcon = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_TXCON);
1474 1.11 thorpej if (sc->sc_mii.mii_media_active & IFM_FDX)
1475 1.11 thorpej txcon |= (TXCON_LOOPBACK_D1|TXCON_LOOPBACK_D2);
1476 1.11 thorpej else
1477 1.11 thorpej txcon &= ~(TXCON_LOOPBACK_D1|TXCON_LOOPBACK_D2);
1478 1.11 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_TXCON, txcon);
1479 1.13 thorpej
1480 1.13 thorpej /*
1481 1.13 thorpej * There is a multicast filter bug in 10Mbps mode. Kick the
1482 1.13 thorpej * multicast filter in case the speed changed.
1483 1.13 thorpej */
1484 1.13 thorpej epic_set_mchash(sc);
1485 1.8 thorpej }
1486 1.8 thorpej
1487 1.8 thorpej /*
1488 1.8 thorpej * Callback from ifmedia to request current media status.
1489 1.8 thorpej */
1490 1.8 thorpej void
1491 1.8 thorpej epic_mediastatus(ifp, ifmr)
1492 1.8 thorpej struct ifnet *ifp;
1493 1.8 thorpej struct ifmediareq *ifmr;
1494 1.8 thorpej {
1495 1.8 thorpej struct epic_softc *sc = ifp->if_softc;
1496 1.8 thorpej
1497 1.8 thorpej mii_pollstat(&sc->sc_mii);
1498 1.8 thorpej ifmr->ifm_status = sc->sc_mii.mii_media_status;
1499 1.8 thorpej ifmr->ifm_active = sc->sc_mii.mii_media_active;
1500 1.8 thorpej }
1501 1.8 thorpej
1502 1.8 thorpej /*
1503 1.8 thorpej * Callback from ifmedia to request new media setting.
1504 1.8 thorpej */
1505 1.8 thorpej int
1506 1.8 thorpej epic_mediachange(ifp)
1507 1.8 thorpej struct ifnet *ifp;
1508 1.8 thorpej {
1509 1.11 thorpej struct epic_softc *sc = ifp->if_softc;
1510 1.8 thorpej
1511 1.8 thorpej if (ifp->if_flags & IFF_UP)
1512 1.11 thorpej mii_mediachg(&sc->sc_mii);
1513 1.8 thorpej return (0);
1514 1.1 thorpej }
1515