smc83c170.c revision 1.6 1 1.6 thorpej /* $NetBSD: smc83c170.c,v 1.6 1998/07/23 17:37:38 thorpej Exp $ */
2 1.1 thorpej
3 1.1 thorpej /*-
4 1.1 thorpej * Copyright (c) 1998 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.1 thorpej #include <sys/mbuf.h>
52 1.1 thorpej #include <sys/malloc.h>
53 1.1 thorpej #include <sys/kernel.h>
54 1.1 thorpej #include <sys/socket.h>
55 1.1 thorpej #include <sys/ioctl.h>
56 1.1 thorpej #include <sys/errno.h>
57 1.1 thorpej #include <sys/device.h>
58 1.1 thorpej
59 1.1 thorpej #include <net/if.h>
60 1.1 thorpej #include <net/if_dl.h>
61 1.1 thorpej #include <net/if_media.h>
62 1.1 thorpej #include <net/if_ether.h>
63 1.1 thorpej
64 1.1 thorpej #if NBPFILTER > 0
65 1.1 thorpej #include <net/bpf.h>
66 1.1 thorpej #endif
67 1.1 thorpej
68 1.1 thorpej #ifdef INET
69 1.1 thorpej #include <netinet/in.h>
70 1.1 thorpej #include <netinet/if_inarp.h>
71 1.1 thorpej #endif
72 1.1 thorpej
73 1.1 thorpej #ifdef NS
74 1.1 thorpej #include <netns/ns.h>
75 1.1 thorpej #include <netns/ns_if.h>
76 1.1 thorpej #endif
77 1.1 thorpej
78 1.1 thorpej #include <machine/bus.h>
79 1.1 thorpej #include <machine/intr.h>
80 1.1 thorpej
81 1.1 thorpej #include <dev/ic/smc83c170reg.h>
82 1.1 thorpej #include <dev/ic/smc83c170var.h>
83 1.1 thorpej
84 1.1 thorpej void epic_start __P((struct ifnet *));
85 1.1 thorpej void epic_watchdog __P((struct ifnet *));
86 1.1 thorpej int epic_ioctl __P((struct ifnet *, u_long, caddr_t));
87 1.1 thorpej
88 1.1 thorpej void epic_shutdown __P((void *));
89 1.1 thorpej
90 1.1 thorpej void epic_reset __P((struct epic_softc *));
91 1.1 thorpej void epic_init __P((struct epic_softc *));
92 1.1 thorpej void epic_stop __P((struct epic_softc *));
93 1.1 thorpej int epic_add_rxbuf __P((struct epic_softc *, int));
94 1.1 thorpej void epic_read_eeprom __P((struct epic_softc *, int, int, u_int16_t *));
95 1.1 thorpej void epic_set_mchash __P((struct epic_softc *));
96 1.6 thorpej void epic_fixup_clock_source __P((struct epic_softc *));
97 1.1 thorpej
98 1.1 thorpej /*
99 1.1 thorpej * Fudge the incoming packets by this much, to ensure the data after
100 1.1 thorpej * the Ethernet header is aligned.
101 1.1 thorpej */
102 1.1 thorpej #define RX_ALIGNMENT_FUDGE 2
103 1.1 thorpej
104 1.1 thorpej /* XXX Should be somewhere else. */
105 1.1 thorpej #define ETHER_MIN_LEN 60
106 1.1 thorpej
107 1.1 thorpej #define INTMASK (INTSTAT_FATAL_INT | INTSTAT_TXU | \
108 1.1 thorpej INTSTAT_TXC | INTSTAT_RQE | INTSTAT_RCC)
109 1.1 thorpej
110 1.1 thorpej /*
111 1.1 thorpej * Attach an EPIC interface to the system.
112 1.1 thorpej */
113 1.1 thorpej void
114 1.1 thorpej epic_attach(sc)
115 1.1 thorpej struct epic_softc *sc;
116 1.1 thorpej {
117 1.1 thorpej bus_space_tag_t st = sc->sc_st;
118 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
119 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
120 1.1 thorpej int i, rseg, error, attach_stage;
121 1.1 thorpej bus_dma_segment_t seg;
122 1.1 thorpej u_int8_t enaddr[ETHER_ADDR_LEN], devname[12 + 1];
123 1.1 thorpej u_int16_t myea[ETHER_ADDR_LEN / 2], mydevname[6];
124 1.1 thorpej
125 1.1 thorpej attach_stage = 0;
126 1.1 thorpej
127 1.1 thorpej /*
128 1.1 thorpej * Allocate the control data structures, and create and load the
129 1.1 thorpej * DMA map for it.
130 1.1 thorpej */
131 1.1 thorpej if ((error = bus_dmamem_alloc(sc->sc_dmat,
132 1.1 thorpej sizeof(struct epic_control_data), NBPG, 0, &seg, 1, &rseg,
133 1.1 thorpej BUS_DMA_NOWAIT)) != 0) {
134 1.1 thorpej printf("%s: unable to allocate control data, error = %d\n",
135 1.1 thorpej sc->sc_dev.dv_xname, error);
136 1.1 thorpej goto fail;
137 1.1 thorpej }
138 1.1 thorpej
139 1.1 thorpej attach_stage = 1;
140 1.1 thorpej
141 1.1 thorpej if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
142 1.1 thorpej sizeof(struct epic_control_data), (caddr_t *)&sc->sc_control_data,
143 1.1 thorpej BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
144 1.1 thorpej printf("%s: unable to map control data, error = %d\n",
145 1.1 thorpej sc->sc_dev.dv_xname, error);
146 1.1 thorpej goto fail;
147 1.1 thorpej }
148 1.1 thorpej
149 1.1 thorpej attach_stage = 2;
150 1.1 thorpej
151 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat,
152 1.1 thorpej sizeof(struct epic_control_data), 1,
153 1.1 thorpej sizeof(struct epic_control_data), 0, BUS_DMA_NOWAIT,
154 1.1 thorpej &sc->sc_cddmamap)) != 0) {
155 1.1 thorpej printf("%s: unable to create control data DMA map, "
156 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, error);
157 1.1 thorpej goto fail;
158 1.1 thorpej }
159 1.1 thorpej
160 1.1 thorpej attach_stage = 3;
161 1.1 thorpej
162 1.1 thorpej if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap,
163 1.1 thorpej sc->sc_control_data, sizeof(struct epic_control_data), NULL,
164 1.1 thorpej BUS_DMA_NOWAIT)) != 0) {
165 1.1 thorpej printf("%s: unable to load control data DMA map, error = %d\n",
166 1.1 thorpej sc->sc_dev.dv_xname, error);
167 1.1 thorpej goto fail;
168 1.1 thorpej }
169 1.1 thorpej
170 1.1 thorpej attach_stage = 4;
171 1.1 thorpej
172 1.1 thorpej /*
173 1.1 thorpej * Create the transmit buffer DMA maps.
174 1.1 thorpej */
175 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++) {
176 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
177 1.1 thorpej EPIC_NFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT,
178 1.1 thorpej &sc->sc_txsoft[i].ds_dmamap)) != 0) {
179 1.1 thorpej printf("%s: unable to create tx DMA map %d, "
180 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, i, error);
181 1.1 thorpej goto fail;
182 1.1 thorpej }
183 1.1 thorpej }
184 1.1 thorpej
185 1.1 thorpej attach_stage = 5;
186 1.1 thorpej
187 1.1 thorpej /*
188 1.1 thorpej * Create the recieve buffer DMA maps.
189 1.1 thorpej */
190 1.1 thorpej for (i = 0; i < EPIC_NRXDESC; i++) {
191 1.1 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
192 1.1 thorpej MCLBYTES, 0, BUS_DMA_NOWAIT,
193 1.1 thorpej &sc->sc_rxsoft[i].ds_dmamap)) != 0) {
194 1.1 thorpej printf("%s: unable to create rx DMA map %d, "
195 1.1 thorpej "error = %d\n", sc->sc_dev.dv_xname, i, error);
196 1.1 thorpej goto fail;
197 1.1 thorpej }
198 1.1 thorpej }
199 1.1 thorpej
200 1.1 thorpej attach_stage = 6;
201 1.1 thorpej
202 1.1 thorpej /*
203 1.1 thorpej * Pre-allocate the receive buffers.
204 1.1 thorpej */
205 1.1 thorpej for (i = 0; i < EPIC_NRXDESC; i++) {
206 1.1 thorpej if ((error = epic_add_rxbuf(sc, i)) != 0) {
207 1.1 thorpej printf("%s: unable to allocate or map rx buffer %d\n,"
208 1.1 thorpej " error = %d\n", sc->sc_dev.dv_xname, i, error);
209 1.1 thorpej goto fail;
210 1.1 thorpej }
211 1.1 thorpej }
212 1.1 thorpej
213 1.1 thorpej attach_stage = 7;
214 1.1 thorpej
215 1.1 thorpej /*
216 1.1 thorpej * Bring the chip out of low-power mode and reset it to a known state.
217 1.1 thorpej */
218 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, 0);
219 1.1 thorpej epic_reset(sc);
220 1.1 thorpej
221 1.1 thorpej /*
222 1.1 thorpej * Read the Ethernet address from the EEPROM.
223 1.1 thorpej */
224 1.1 thorpej epic_read_eeprom(sc, 0, (sizeof(myea) / sizeof(myea[0])), myea);
225 1.1 thorpej bcopy(myea, enaddr, sizeof(myea));
226 1.1 thorpej
227 1.1 thorpej /*
228 1.1 thorpej * ...and the device name.
229 1.1 thorpej */
230 1.1 thorpej epic_read_eeprom(sc, 0x2c, (sizeof(mydevname) / sizeof(mydevname[0])),
231 1.1 thorpej mydevname);
232 1.1 thorpej bcopy(mydevname, devname, sizeof(mydevname));
233 1.1 thorpej devname[sizeof(mydevname)] = '\0';
234 1.1 thorpej for (i = sizeof(mydevname) - 1; i >= 0; i--) {
235 1.1 thorpej if (devname[i] == ' ')
236 1.1 thorpej devname[i] = '\0';
237 1.1 thorpej else
238 1.1 thorpej break;
239 1.1 thorpej }
240 1.1 thorpej
241 1.1 thorpej printf("%s: %s, Ethernet address %s\n", sc->sc_dev.dv_xname,
242 1.1 thorpej devname, ether_sprintf(enaddr));
243 1.1 thorpej
244 1.1 thorpej ifp = &sc->sc_ethercom.ec_if;
245 1.1 thorpej strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
246 1.1 thorpej ifp->if_softc = sc;
247 1.1 thorpej ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
248 1.1 thorpej ifp->if_ioctl = epic_ioctl;
249 1.1 thorpej ifp->if_start = epic_start;
250 1.1 thorpej ifp->if_watchdog = epic_watchdog;
251 1.1 thorpej
252 1.1 thorpej /*
253 1.1 thorpej * Attach the interface.
254 1.1 thorpej */
255 1.1 thorpej if_attach(ifp);
256 1.1 thorpej ether_ifattach(ifp, enaddr);
257 1.1 thorpej #if NBPFILTER > 0
258 1.1 thorpej bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB,
259 1.1 thorpej sizeof(struct ether_header));
260 1.1 thorpej #endif
261 1.1 thorpej
262 1.1 thorpej /*
263 1.1 thorpej * Make sure the interface is shutdown during reboot.
264 1.1 thorpej */
265 1.1 thorpej sc->sc_sdhook = shutdownhook_establish(epic_shutdown, sc);
266 1.1 thorpej if (sc->sc_sdhook == NULL)
267 1.1 thorpej printf("%s: WARNING: unable to establish shutdown hook\n",
268 1.1 thorpej sc->sc_dev.dv_xname);
269 1.1 thorpej return;
270 1.1 thorpej
271 1.1 thorpej fail:
272 1.1 thorpej /*
273 1.1 thorpej * Free any resources we've allocated during the failed attach
274 1.1 thorpej * attempt. Do this in reverse order and fall through.
275 1.1 thorpej */
276 1.1 thorpej switch (attach_stage) {
277 1.1 thorpej case 7:
278 1.1 thorpej for (i = 0; i < EPIC_NRXDESC; i++) {
279 1.1 thorpej if (sc->sc_rxsoft[i].ds_mbuf != NULL) {
280 1.1 thorpej bus_dmamap_unload(sc->sc_dmat,
281 1.1 thorpej sc->sc_rxsoft[i].ds_dmamap);
282 1.1 thorpej m_freem(sc->sc_rxsoft[i].ds_mbuf);
283 1.1 thorpej }
284 1.1 thorpej }
285 1.1 thorpej /* FALLTHROUGH */
286 1.1 thorpej
287 1.1 thorpej case 6:
288 1.1 thorpej for (i = 0; i < EPIC_NRXDESC; i++)
289 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat,
290 1.1 thorpej sc->sc_rxsoft[i].ds_dmamap);
291 1.1 thorpej /* FALLTHROUGH */
292 1.1 thorpej
293 1.1 thorpej case 5:
294 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++)
295 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat,
296 1.1 thorpej sc->sc_txsoft[i].ds_dmamap);
297 1.1 thorpej /* FALLTHROUGH */
298 1.1 thorpej
299 1.1 thorpej case 4:
300 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap);
301 1.1 thorpej /* FALLTHROUGH */
302 1.1 thorpej
303 1.1 thorpej case 3:
304 1.1 thorpej bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap);
305 1.1 thorpej /* FALLTHROUGH */
306 1.1 thorpej
307 1.1 thorpej case 2:
308 1.1 thorpej bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_control_data,
309 1.1 thorpej sizeof(struct epic_control_data));
310 1.1 thorpej /* FALLTHROUGH */
311 1.1 thorpej
312 1.1 thorpej case 1:
313 1.1 thorpej bus_dmamem_free(sc->sc_dmat, &seg, rseg);
314 1.1 thorpej break;
315 1.1 thorpej }
316 1.1 thorpej }
317 1.1 thorpej
318 1.1 thorpej /*
319 1.1 thorpej * Shutdown hook. Make sure the interface is stopped at reboot.
320 1.1 thorpej */
321 1.1 thorpej void
322 1.1 thorpej epic_shutdown(arg)
323 1.1 thorpej void *arg;
324 1.1 thorpej {
325 1.1 thorpej struct epic_softc *sc = arg;
326 1.1 thorpej
327 1.1 thorpej epic_stop(sc);
328 1.1 thorpej }
329 1.1 thorpej
330 1.1 thorpej /*
331 1.1 thorpej * Start packet transmission on the interface.
332 1.1 thorpej * [ifnet interface function]
333 1.1 thorpej */
334 1.1 thorpej void
335 1.1 thorpej epic_start(ifp)
336 1.1 thorpej struct ifnet *ifp;
337 1.1 thorpej {
338 1.1 thorpej struct epic_softc *sc = ifp->if_softc;
339 1.1 thorpej struct epic_txdesc *txd;
340 1.1 thorpej struct epic_descsoft *ds;
341 1.1 thorpej struct epic_fraglist *fr;
342 1.1 thorpej bus_dmamap_t dmamap;
343 1.1 thorpej struct mbuf *m0;
344 1.1 thorpej int nexttx, seg, error, txqueued;
345 1.1 thorpej
346 1.1 thorpej txqueued = 0;
347 1.1 thorpej
348 1.1 thorpej /*
349 1.1 thorpej * Loop through the send queue, setting up transmit descriptors
350 1.1 thorpej * until we drain the queue, or use up all available transmit
351 1.1 thorpej * descriptors.
352 1.1 thorpej */
353 1.1 thorpej while (ifp->if_snd.ifq_head != NULL &&
354 1.1 thorpej sc->sc_txpending < EPIC_NTXDESC) {
355 1.1 thorpej /*
356 1.1 thorpej * Grab a packet off the queue.
357 1.1 thorpej */
358 1.1 thorpej IF_DEQUEUE(&ifp->if_snd, m0);
359 1.1 thorpej
360 1.1 thorpej /*
361 1.1 thorpej * Get the last and next available transmit descriptor.
362 1.1 thorpej */
363 1.1 thorpej nexttx = EPIC_NEXTTX(sc->sc_txlast);
364 1.1 thorpej txd = &sc->sc_control_data->ecd_txdescs[nexttx];
365 1.1 thorpej fr = &sc->sc_control_data->ecd_txfrags[nexttx];
366 1.1 thorpej ds = &sc->sc_txsoft[nexttx];
367 1.1 thorpej dmamap = ds->ds_dmamap;
368 1.1 thorpej
369 1.1 thorpej loadmap:
370 1.1 thorpej /*
371 1.1 thorpej * Load the DMA map with the packet.
372 1.1 thorpej */
373 1.1 thorpej error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, m0,
374 1.1 thorpej BUS_DMA_NOWAIT);
375 1.1 thorpej switch (error) {
376 1.1 thorpej case 0:
377 1.1 thorpej /* Success. */
378 1.1 thorpej break;
379 1.1 thorpej
380 1.1 thorpej case EFBIG:
381 1.1 thorpej {
382 1.1 thorpej struct mbuf *mn;
383 1.1 thorpej
384 1.1 thorpej /*
385 1.1 thorpej * We ran out of segments. We have to recopy this
386 1.1 thorpej * mbuf chain first. Bail out if we can't get the
387 1.1 thorpej * new buffers.
388 1.1 thorpej */
389 1.1 thorpej printf("%s: too many segments, ", sc->sc_dev.dv_xname);
390 1.1 thorpej
391 1.1 thorpej MGETHDR(mn, M_DONTWAIT, MT_DATA);
392 1.1 thorpej if (mn == NULL) {
393 1.1 thorpej m_freem(m0);
394 1.1 thorpej printf("aborting\n");
395 1.1 thorpej goto out;
396 1.1 thorpej }
397 1.1 thorpej if (m0->m_pkthdr.len > MHLEN) {
398 1.1 thorpej MCLGET(mn, M_DONTWAIT);
399 1.1 thorpej if ((mn->m_flags & M_EXT) == 0) {
400 1.1 thorpej m_freem(mn);
401 1.1 thorpej m_freem(m0);
402 1.1 thorpej printf("aborting\n");
403 1.1 thorpej goto out;
404 1.1 thorpej }
405 1.1 thorpej }
406 1.1 thorpej m_copydata(m0, 0, m0->m_pkthdr.len, mtod(mn, caddr_t));
407 1.1 thorpej mn->m_pkthdr.len = mn->m_len = m0->m_pkthdr.len;
408 1.1 thorpej m_freem(m0);
409 1.1 thorpej m0 = mn;
410 1.1 thorpej printf("retrying\n");
411 1.1 thorpej goto loadmap;
412 1.1 thorpej }
413 1.1 thorpej
414 1.1 thorpej default:
415 1.1 thorpej /*
416 1.1 thorpej * Some other problem; report it.
417 1.1 thorpej */
418 1.1 thorpej printf("%s: can't load mbuf chain, error = %d\n",
419 1.1 thorpej sc->sc_dev.dv_xname, error);
420 1.1 thorpej m_freem(m0);
421 1.1 thorpej goto out;
422 1.1 thorpej }
423 1.1 thorpej
424 1.1 thorpej /*
425 1.1 thorpej * Initialize the fraglist.
426 1.1 thorpej */
427 1.1 thorpej fr->ef_nfrags = dmamap->dm_nsegs;
428 1.1 thorpej for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
429 1.1 thorpej fr->ef_frags[seg].ef_addr =
430 1.1 thorpej dmamap->dm_segs[seg].ds_addr;
431 1.1 thorpej fr->ef_frags[seg].ef_length =
432 1.1 thorpej dmamap->dm_segs[seg].ds_len;
433 1.1 thorpej }
434 1.1 thorpej
435 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize,
436 1.1 thorpej BUS_DMASYNC_PREWRITE);
437 1.1 thorpej
438 1.1 thorpej /*
439 1.1 thorpej * Store a pointer to the packet so we can free it later.
440 1.1 thorpej */
441 1.1 thorpej ds->ds_mbuf = m0;
442 1.1 thorpej
443 1.1 thorpej /*
444 1.1 thorpej * Finish setting up the new transmit descriptor: set the
445 1.1 thorpej * packet length and give it to the EPIC.
446 1.1 thorpej */
447 1.1 thorpej txd->et_txlength = max(m0->m_pkthdr.len, ETHER_MIN_LEN);
448 1.1 thorpej txd->et_txstatus = ET_TXSTAT_OWNER;
449 1.1 thorpej
450 1.1 thorpej /*
451 1.1 thorpej * Committed; advance the lasttx pointer. If nothing was
452 1.1 thorpej * previously queued, reset the dirty pointer.
453 1.1 thorpej */
454 1.1 thorpej sc->sc_txlast = nexttx;
455 1.1 thorpej if (sc->sc_txpending == 0)
456 1.1 thorpej sc->sc_txdirty = nexttx;
457 1.1 thorpej
458 1.1 thorpej sc->sc_txpending++;
459 1.1 thorpej
460 1.1 thorpej txqueued = 1;
461 1.1 thorpej
462 1.1 thorpej #if NBPFILTER > 0
463 1.1 thorpej /*
464 1.1 thorpej * Pass the packet to any BPF listeners.
465 1.1 thorpej */
466 1.1 thorpej if (ifp->if_bpf)
467 1.1 thorpej bpf_mtap(ifp->if_bpf, m0);
468 1.1 thorpej #endif
469 1.1 thorpej }
470 1.1 thorpej
471 1.1 thorpej out:
472 1.1 thorpej /*
473 1.1 thorpej * We're finished. If we added more packets, make sure the
474 1.1 thorpej * transmit DMA engine is running.
475 1.1 thorpej */
476 1.1 thorpej if (txqueued) {
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.1 thorpej /*
481 1.1 thorpej * Set a 5 second watchdog timer.
482 1.1 thorpej */
483 1.1 thorpej ifp->if_timer = 5;
484 1.1 thorpej }
485 1.1 thorpej }
486 1.1 thorpej
487 1.1 thorpej /*
488 1.1 thorpej * Watchdog timer handler.
489 1.1 thorpej * [ifnet interface function]
490 1.1 thorpej */
491 1.1 thorpej void
492 1.1 thorpej epic_watchdog(ifp)
493 1.1 thorpej struct ifnet *ifp;
494 1.1 thorpej {
495 1.1 thorpej struct epic_softc *sc = ifp->if_softc;
496 1.1 thorpej
497 1.1 thorpej printf("%s: device timeout\n", sc->sc_dev.dv_xname);
498 1.1 thorpej ifp->if_oerrors++;
499 1.1 thorpej
500 1.1 thorpej epic_init(sc);
501 1.1 thorpej }
502 1.1 thorpej
503 1.1 thorpej /*
504 1.1 thorpej * Handle control requests from the operator.
505 1.1 thorpej * [ifnet interface function]
506 1.1 thorpej */
507 1.1 thorpej int
508 1.1 thorpej epic_ioctl(ifp, cmd, data)
509 1.1 thorpej struct ifnet *ifp;
510 1.1 thorpej u_long cmd;
511 1.1 thorpej caddr_t data;
512 1.1 thorpej {
513 1.1 thorpej struct epic_softc *sc = ifp->if_softc;
514 1.1 thorpej struct ifreq *ifr = (struct ifreq *)data;
515 1.1 thorpej struct ifaddr *ifa = (struct ifaddr *)data;
516 1.1 thorpej int s, error = 0;
517 1.1 thorpej
518 1.1 thorpej s = splimp();
519 1.1 thorpej
520 1.1 thorpej switch (cmd) {
521 1.1 thorpej case SIOCSIFADDR:
522 1.1 thorpej ifp->if_flags |= IFF_UP;
523 1.1 thorpej
524 1.1 thorpej switch (ifa->ifa_addr->sa_family) {
525 1.1 thorpej #ifdef INET
526 1.1 thorpej case AF_INET:
527 1.1 thorpej epic_init(sc);
528 1.1 thorpej arp_ifinit(ifp, ifa);
529 1.1 thorpej break;
530 1.1 thorpej #endif /* INET */
531 1.1 thorpej #ifdef NS
532 1.1 thorpej case AF_NS:
533 1.1 thorpej {
534 1.1 thorpej struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
535 1.1 thorpej
536 1.1 thorpej if (ns_nullhost(*ina))
537 1.1 thorpej ina->x_host = *(union ns_host *)
538 1.1 thorpej LLADDR(ifp->if_sadl);
539 1.1 thorpej else
540 1.1 thorpej bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl),
541 1.1 thorpej ifp->if_addrlen);
542 1.1 thorpej /* Set new address. */
543 1.1 thorpej epic_init(sc);
544 1.1 thorpej break;
545 1.1 thorpej }
546 1.1 thorpej #endif /* NS */
547 1.1 thorpej default:
548 1.1 thorpej epic_init(sc);
549 1.1 thorpej break;
550 1.1 thorpej }
551 1.1 thorpej break;
552 1.1 thorpej
553 1.1 thorpej case SIOCSIFMTU:
554 1.1 thorpej if (ifr->ifr_mtu > ETHERMTU)
555 1.1 thorpej error = EINVAL;
556 1.1 thorpej else
557 1.1 thorpej ifp->if_mtu = ifr->ifr_mtu;
558 1.1 thorpej break;
559 1.1 thorpej
560 1.1 thorpej case SIOCSIFFLAGS:
561 1.1 thorpej if ((ifp->if_flags & IFF_UP) == 0 &&
562 1.1 thorpej (ifp->if_flags & IFF_RUNNING) != 0) {
563 1.1 thorpej /*
564 1.1 thorpej * If interface is marked down and it is running, then
565 1.1 thorpej * stop it.
566 1.1 thorpej */
567 1.1 thorpej epic_stop(sc);
568 1.1 thorpej ifp->if_flags &= ~IFF_RUNNING;
569 1.1 thorpej } else if ((ifp->if_flags & IFF_UP) != 0 &&
570 1.1 thorpej (ifp->if_flags & IFF_RUNNING) == 0) {
571 1.1 thorpej /*
572 1.1 thorpej * If interfase it marked up and it is stopped, then
573 1.1 thorpej * start it.
574 1.1 thorpej */
575 1.1 thorpej epic_init(sc);
576 1.1 thorpej } else {
577 1.1 thorpej /*
578 1.1 thorpej * Reset the interface to pick up changes in any other
579 1.1 thorpej * flags that affect the hardware state.
580 1.1 thorpej */
581 1.1 thorpej epic_init(sc);
582 1.1 thorpej }
583 1.1 thorpej break;
584 1.1 thorpej
585 1.1 thorpej case SIOCADDMULTI:
586 1.1 thorpej case SIOCDELMULTI:
587 1.1 thorpej error = (cmd == SIOCADDMULTI) ?
588 1.1 thorpej ether_addmulti(ifr, &sc->sc_ethercom) :
589 1.1 thorpej ether_delmulti(ifr, &sc->sc_ethercom);
590 1.1 thorpej
591 1.1 thorpej if (error == ENETRESET) {
592 1.1 thorpej /*
593 1.1 thorpej * Multicast list has changed; set the hardware filter
594 1.1 thorpej * accordingly.
595 1.1 thorpej */
596 1.1 thorpej epic_init(sc);
597 1.1 thorpej error = 0;
598 1.1 thorpej }
599 1.1 thorpej break;
600 1.1 thorpej
601 1.1 thorpej default:
602 1.1 thorpej error = EINVAL;
603 1.1 thorpej break;
604 1.1 thorpej }
605 1.1 thorpej
606 1.1 thorpej splx(s);
607 1.1 thorpej return (error);
608 1.1 thorpej }
609 1.1 thorpej
610 1.1 thorpej /*
611 1.1 thorpej * Interrupt handler.
612 1.1 thorpej */
613 1.1 thorpej int
614 1.1 thorpej epic_intr(arg)
615 1.1 thorpej void *arg;
616 1.1 thorpej {
617 1.1 thorpej struct epic_softc *sc = arg;
618 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
619 1.1 thorpej struct ether_header *eh;
620 1.1 thorpej struct epic_rxdesc *rxd;
621 1.1 thorpej struct epic_txdesc *txd;
622 1.1 thorpej struct epic_descsoft *ds;
623 1.1 thorpej struct mbuf *m;
624 1.1 thorpej u_int32_t intstat;
625 1.1 thorpej int i, len, claimed = 0, error;
626 1.1 thorpej
627 1.1 thorpej top:
628 1.1 thorpej /*
629 1.1 thorpej * Get the interrupt status from the EPIC.
630 1.1 thorpej */
631 1.1 thorpej intstat = bus_space_read_4(sc->sc_st, sc->sc_sh, EPIC_INTSTAT);
632 1.1 thorpej if ((intstat & INTSTAT_INT_ACTV) == 0)
633 1.1 thorpej return (claimed);
634 1.1 thorpej
635 1.1 thorpej claimed = 1;
636 1.1 thorpej
637 1.1 thorpej /*
638 1.1 thorpej * Acknowledge the interrupt.
639 1.1 thorpej */
640 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_INTSTAT,
641 1.1 thorpej intstat & INTMASK);
642 1.1 thorpej
643 1.1 thorpej /*
644 1.1 thorpej * Check for receive interrupts.
645 1.1 thorpej */
646 1.1 thorpej if (intstat & (INTSTAT_RCC | INTSTAT_RQE)) {
647 1.1 thorpej for (i = sc->sc_rxptr;; i = EPIC_NEXTRX(i)) {
648 1.1 thorpej rxd = &sc->sc_control_data->ecd_rxdescs[i];
649 1.1 thorpej ds = &sc->sc_rxsoft[i];
650 1.1 thorpej m = ds->ds_mbuf;
651 1.1 thorpej error = 0;
652 1.1 thorpej
653 1.1 thorpej if (rxd->er_rxstatus & ER_RXSTAT_OWNER) {
654 1.1 thorpej /*
655 1.1 thorpej * We have processed all of the
656 1.1 thorpej * receive buffers.
657 1.1 thorpej */
658 1.1 thorpej break;
659 1.1 thorpej }
660 1.1 thorpej
661 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
662 1.1 thorpej ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
663 1.1 thorpej
664 1.1 thorpej /*
665 1.1 thorpej * Make sure the packet arrived intact.
666 1.1 thorpej */
667 1.1 thorpej if ((rxd->er_rxstatus & ER_RXSTAT_PKTINTACT) == 0) {
668 1.1 thorpej #if 1
669 1.1 thorpej if (rxd->er_rxstatus & ER_RXSTAT_CRCERROR)
670 1.1 thorpej printf("%s: CRC error\n",
671 1.1 thorpej sc->sc_dev.dv_xname);
672 1.1 thorpej if (rxd->er_rxstatus & ER_RXSTAT_ALIGNERROR)
673 1.1 thorpej printf("%s: alignment error\n",
674 1.1 thorpej sc->sc_dev.dv_xname);
675 1.1 thorpej #endif
676 1.1 thorpej ifp->if_ierrors++;
677 1.1 thorpej error = 1;
678 1.1 thorpej }
679 1.1 thorpej
680 1.1 thorpej /*
681 1.1 thorpej * Add a new buffer to the receive chain. If this
682 1.1 thorpej * fails, the old buffer is recycled.
683 1.1 thorpej */
684 1.1 thorpej if (epic_add_rxbuf(sc, i) == 0) {
685 1.1 thorpej /*
686 1.1 thorpej * We wanted to reset the buffer, but
687 1.1 thorpej * didn't want to pass it on up.
688 1.1 thorpej */
689 1.1 thorpej if (error) {
690 1.1 thorpej m_freem(m);
691 1.1 thorpej continue;
692 1.1 thorpej }
693 1.1 thorpej
694 1.1 thorpej len = rxd->er_buflength;
695 1.1 thorpej if (len < sizeof(struct ether_header)) {
696 1.1 thorpej m_freem(m);
697 1.1 thorpej continue;
698 1.1 thorpej }
699 1.1 thorpej
700 1.1 thorpej m->m_pkthdr.rcvif = ifp;
701 1.1 thorpej m->m_pkthdr.len = m->m_len = len;
702 1.1 thorpej eh = mtod(m, struct ether_header *);
703 1.1 thorpej #if NBPFILTER > 0
704 1.1 thorpej /*
705 1.1 thorpej * Pass this up to any BPF listeners.
706 1.1 thorpej */
707 1.1 thorpej if (ifp->if_bpf) {
708 1.1 thorpej bpf_mtap(ifp->if_bpf, m);
709 1.1 thorpej
710 1.1 thorpej /*
711 1.1 thorpej * Only pass this up the stack
712 1.1 thorpej * if it's for us.
713 1.1 thorpej */
714 1.1 thorpej if ((ifp->if_flags & IFF_PROMISC) &&
715 1.1 thorpej bcmp(LLADDR(ifp->if_sadl),
716 1.1 thorpej eh->ether_dhost,
717 1.1 thorpej ETHER_ADDR_LEN) != 0 &&
718 1.1 thorpej (rxd->er_rxstatus &
719 1.1 thorpej (ER_RXSTAT_BCAST|ER_RXSTAT_MCAST))
720 1.1 thorpej == 0) {
721 1.1 thorpej m_freem(m);
722 1.1 thorpej continue;
723 1.1 thorpej }
724 1.1 thorpej }
725 1.1 thorpej #endif /* NPBFILTER > 0 */
726 1.1 thorpej m->m_data += sizeof(struct ether_header);
727 1.1 thorpej m->m_len -= sizeof(struct ether_header);
728 1.1 thorpej m->m_pkthdr.len = m->m_len;
729 1.1 thorpej ether_input(ifp, eh, m);
730 1.1 thorpej }
731 1.1 thorpej }
732 1.1 thorpej
733 1.1 thorpej /*
734 1.1 thorpej * Update the recieve pointer.
735 1.1 thorpej */
736 1.1 thorpej sc->sc_rxptr = i;
737 1.1 thorpej
738 1.1 thorpej /*
739 1.1 thorpej * Check for receive queue underflow.
740 1.1 thorpej */
741 1.1 thorpej if (intstat & INTSTAT_RQE) {
742 1.1 thorpej printf("%s: receiver queue empty\n",
743 1.1 thorpej sc->sc_dev.dv_xname);
744 1.1 thorpej /*
745 1.1 thorpej * Ring is already built; just restart the
746 1.1 thorpej * receiver.
747 1.1 thorpej */
748 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_PRCDAR,
749 1.1 thorpej sc->sc_cddma + EPIC_CDOFF(ecd_rxdescs[0]));
750 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_COMMAND,
751 1.1 thorpej COMMAND_RXQUEUED | COMMAND_START_RX);
752 1.1 thorpej }
753 1.1 thorpej }
754 1.1 thorpej
755 1.1 thorpej /*
756 1.1 thorpej * Check for transmission complete interrupts.
757 1.1 thorpej */
758 1.1 thorpej if (intstat & (INTSTAT_TXC | INTSTAT_TXU)) {
759 1.1 thorpej for (i = sc->sc_txdirty;; i = EPIC_NEXTTX(i)) {
760 1.1 thorpej txd = &sc->sc_control_data->ecd_txdescs[i];
761 1.1 thorpej ds = &sc->sc_txsoft[i];
762 1.1 thorpej
763 1.1 thorpej if (sc->sc_txpending == 0 ||
764 1.1 thorpej (txd->et_txstatus & ET_TXSTAT_OWNER) != 0)
765 1.1 thorpej break;
766 1.1 thorpej
767 1.1 thorpej if (ds->ds_mbuf != NULL) {
768 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap,
769 1.1 thorpej 0, ds->ds_dmamap->dm_mapsize,
770 1.1 thorpej BUS_DMASYNC_POSTWRITE);
771 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
772 1.1 thorpej m_freem(ds->ds_mbuf);
773 1.1 thorpej ds->ds_mbuf = NULL;
774 1.1 thorpej }
775 1.1 thorpej sc->sc_txpending--;
776 1.1 thorpej
777 1.1 thorpej /*
778 1.1 thorpej * Check for errors and collisions.
779 1.1 thorpej */
780 1.1 thorpej if ((txd->et_txstatus & ET_TXSTAT_PACKETTX) == 0)
781 1.1 thorpej ifp->if_oerrors++;
782 1.1 thorpej ifp->if_collisions +=
783 1.1 thorpej TXSTAT_COLLISIONS(txd->et_txstatus);
784 1.1 thorpej if (txd->et_txstatus & ET_TXSTAT_CARSENSELOST) {
785 1.1 thorpej #if 1
786 1.1 thorpej printf("%s: lost carrier\n",
787 1.1 thorpej sc->sc_dev.dv_xname);
788 1.1 thorpej #endif
789 1.1 thorpej /* XXX clear "active" but in media data */
790 1.1 thorpej }
791 1.1 thorpej }
792 1.1 thorpej
793 1.1 thorpej /*
794 1.1 thorpej * Update the dirty transmit buffer pointer.
795 1.1 thorpej */
796 1.1 thorpej sc->sc_txdirty = i;
797 1.1 thorpej
798 1.1 thorpej /*
799 1.1 thorpej * Cancel the watchdog timer if there are no pending
800 1.1 thorpej * transmissions.
801 1.1 thorpej */
802 1.1 thorpej if (sc->sc_txpending == 0)
803 1.1 thorpej ifp->if_timer = 0;
804 1.1 thorpej
805 1.1 thorpej /*
806 1.1 thorpej * Kick the transmitter after a DMA underrun.
807 1.1 thorpej */
808 1.1 thorpej if (intstat & INTSTAT_TXU) {
809 1.1 thorpej printf("%s: transmit underrun\n", sc->sc_dev.dv_xname);
810 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh,
811 1.1 thorpej EPIC_COMMAND, COMMAND_TXUGO);
812 1.1 thorpej if (sc->sc_txpending)
813 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh,
814 1.1 thorpej EPIC_COMMAND, COMMAND_TXQUEUED);
815 1.1 thorpej }
816 1.1 thorpej
817 1.1 thorpej /*
818 1.1 thorpej * Try to get more packets going.
819 1.1 thorpej */
820 1.1 thorpej epic_start(ifp);
821 1.1 thorpej }
822 1.1 thorpej
823 1.1 thorpej /*
824 1.1 thorpej * Check for fatal interrupts.
825 1.1 thorpej */
826 1.1 thorpej if (intstat & INTSTAT_FATAL_INT) {
827 1.1 thorpej printf("%s: fatal error, resetting\n", sc->sc_dev.dv_xname);
828 1.1 thorpej epic_init(sc);
829 1.1 thorpej }
830 1.1 thorpej
831 1.1 thorpej /*
832 1.1 thorpej * Check for more interrupts.
833 1.1 thorpej */
834 1.1 thorpej goto top;
835 1.1 thorpej }
836 1.1 thorpej
837 1.1 thorpej /*
838 1.6 thorpej * Fixup the clock source on the EPIC.
839 1.6 thorpej */
840 1.6 thorpej void
841 1.6 thorpej epic_fixup_clock_source(sc)
842 1.6 thorpej struct epic_softc *sc;
843 1.6 thorpej {
844 1.6 thorpej int i;
845 1.6 thorpej
846 1.6 thorpej /*
847 1.6 thorpej * According to SMC Application Note 7-15, the EPIC's clock
848 1.6 thorpej * source is incorrect following a reset. This manifests itself
849 1.6 thorpej * as failure to recognize when host software has written to
850 1.6 thorpej * a register on the EPIC. The appnote recommends issuing at
851 1.6 thorpej * least 16 consecutive writes to the CLOCK TEST bit to correctly
852 1.6 thorpej * configure the clock source.
853 1.6 thorpej */
854 1.6 thorpej for (i = 0; i < 16; i++)
855 1.6 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_TEST,
856 1.6 thorpej TEST_CLOCKTEST);
857 1.6 thorpej }
858 1.6 thorpej
859 1.6 thorpej /*
860 1.1 thorpej * Perform a soft reset on the EPIC.
861 1.1 thorpej */
862 1.1 thorpej void
863 1.1 thorpej epic_reset(sc)
864 1.1 thorpej struct epic_softc *sc;
865 1.1 thorpej {
866 1.1 thorpej
867 1.6 thorpej epic_fixup_clock_source(sc);
868 1.6 thorpej
869 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_GENCTL, 0);
870 1.1 thorpej delay(100);
871 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_GENCTL, GENCTL_SOFTRESET);
872 1.1 thorpej delay(100);
873 1.6 thorpej
874 1.6 thorpej epic_fixup_clock_source(sc);
875 1.1 thorpej }
876 1.1 thorpej
877 1.1 thorpej /*
878 1.1 thorpej * Initialize the interface. Must be called at splimp().
879 1.1 thorpej */
880 1.1 thorpej void
881 1.1 thorpej epic_init(sc)
882 1.1 thorpej struct epic_softc *sc;
883 1.1 thorpej {
884 1.1 thorpej bus_space_tag_t st = sc->sc_st;
885 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
886 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
887 1.1 thorpej u_int8_t *enaddr = LLADDR(ifp->if_sadl);
888 1.1 thorpej struct epic_txdesc *txd;
889 1.1 thorpej struct epic_rxdesc *rxd;
890 1.1 thorpej u_int32_t genctl, reg0;
891 1.1 thorpej int i;
892 1.1 thorpej
893 1.1 thorpej /*
894 1.1 thorpej * Cancel any pending I/O.
895 1.1 thorpej */
896 1.1 thorpej epic_stop(sc);
897 1.1 thorpej
898 1.1 thorpej /*
899 1.1 thorpej * Reset the EPIC to a known state.
900 1.1 thorpej */
901 1.1 thorpej epic_reset(sc);
902 1.1 thorpej
903 1.1 thorpej /*
904 1.1 thorpej * Magical mystery initialization.
905 1.1 thorpej */
906 1.1 thorpej bus_space_write_4(st, sh, EPIC_TXTEST, 0);
907 1.1 thorpej
908 1.1 thorpej /*
909 1.1 thorpej * Initialize the EPIC genctl register:
910 1.1 thorpej *
911 1.1 thorpej * - 64 byte receive FIFO threshold
912 1.1 thorpej * - automatic advance to next receive frame
913 1.1 thorpej */
914 1.1 thorpej genctl = GENCTL_RX_FIFO_THRESH0 | GENCTL_ONECOPY;
915 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl);
916 1.1 thorpej
917 1.1 thorpej /*
918 1.1 thorpej * Reset the MII bus and PHY.
919 1.1 thorpej */
920 1.1 thorpej reg0 = bus_space_read_4(st, sh, EPIC_NVCTL);
921 1.1 thorpej bus_space_write_4(st, sh, EPIC_NVCTL, reg0 | NVCTL_GPIO1 | NVCTL_GPOE1);
922 1.1 thorpej bus_space_write_4(st, sh, EPIC_MIICFG, MIICFG_ENASER);
923 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl | GENCTL_RESET_PHY);
924 1.1 thorpej delay(100);
925 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl);
926 1.1 thorpej delay(100);
927 1.1 thorpej bus_space_write_4(st, sh, EPIC_NVCTL, reg0);
928 1.1 thorpej
929 1.1 thorpej /*
930 1.1 thorpej * Initialize Ethernet address.
931 1.1 thorpej */
932 1.1 thorpej reg0 = enaddr[1] << 8 | enaddr[0];
933 1.1 thorpej bus_space_write_4(st, sh, EPIC_LAN0, reg0);
934 1.1 thorpej reg0 = enaddr[3] << 8 | enaddr[2];
935 1.1 thorpej bus_space_write_4(st, sh, EPIC_LAN1, reg0);
936 1.1 thorpej reg0 = enaddr[5] << 8 | enaddr[4];
937 1.1 thorpej bus_space_write_4(st, sh, EPIC_LAN2, reg0);
938 1.1 thorpej
939 1.1 thorpej /*
940 1.1 thorpej * Set up the multicast hash table.
941 1.1 thorpej */
942 1.1 thorpej epic_set_mchash(sc);
943 1.1 thorpej
944 1.1 thorpej /*
945 1.1 thorpej * Initialize receive control. Remember the external buffer
946 1.1 thorpej * size setting.
947 1.1 thorpej */
948 1.1 thorpej reg0 = bus_space_read_4(st, sh, EPIC_RXCON) &
949 1.1 thorpej (RXCON_EXTBUFSIZESEL1 | RXCON_EXTBUFSIZESEL0);
950 1.1 thorpej reg0 |= (RXCON_RXMULTICAST | RXCON_RXBROADCAST);
951 1.1 thorpej if (ifp->if_flags & IFF_PROMISC)
952 1.1 thorpej reg0 |= RXCON_PROMISCMODE;
953 1.1 thorpej bus_space_write_4(st, sh, EPIC_RXCON, reg0);
954 1.1 thorpej
955 1.1 thorpej /*
956 1.1 thorpej * XXX Media (full-duplex in TXCON).
957 1.1 thorpej */
958 1.1 thorpej
959 1.1 thorpej /*
960 1.1 thorpej * Initialize the transmit descriptors.
961 1.1 thorpej */
962 1.1 thorpej txd = sc->sc_control_data->ecd_txdescs;
963 1.1 thorpej bzero(txd, sizeof(sc->sc_control_data->ecd_txdescs));
964 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++) {
965 1.1 thorpej txd[i].et_control = ET_TXCTL_LASTDESC | ET_TXCTL_IAF |
966 1.1 thorpej ET_TXCTL_FRAGLIST;
967 1.1 thorpej txd[i].et_bufaddr = sc->sc_cddma + EPIC_CDOFF(ecd_txfrags[i]);
968 1.1 thorpej txd[i].et_nextdesc = sc->sc_cddma +
969 1.1 thorpej EPIC_CDOFF(ecd_txdescs[(i + 1) & EPIC_NTXDESC_MASK]);
970 1.1 thorpej }
971 1.1 thorpej
972 1.1 thorpej /*
973 1.1 thorpej * Initialize the receive descriptors. Note the buffers
974 1.1 thorpej * and control word have already been initialized; we only
975 1.1 thorpej * need to initialize the ring.
976 1.1 thorpej */
977 1.1 thorpej rxd = sc->sc_control_data->ecd_rxdescs;
978 1.1 thorpej for (i = 0; i < EPIC_NRXDESC; i++) {
979 1.1 thorpej rxd[i].er_nextdesc = sc->sc_cddma +
980 1.1 thorpej EPIC_CDOFF(ecd_rxdescs[(i + 1) & EPIC_NRXDESC_MASK]);
981 1.1 thorpej }
982 1.1 thorpej
983 1.1 thorpej /*
984 1.1 thorpej * Initialize the interrupt mask and enable interrupts.
985 1.1 thorpej */
986 1.1 thorpej bus_space_write_4(st, sh, EPIC_INTMASK, INTMASK);
987 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, genctl | GENCTL_INTENA);
988 1.1 thorpej
989 1.1 thorpej /*
990 1.1 thorpej * Give the transmit and receive rings to the EPIC.
991 1.1 thorpej */
992 1.1 thorpej bus_space_write_4(st, sh, EPIC_PTCDAR,
993 1.1 thorpej sc->sc_cddma + EPIC_CDOFF(ecd_txdescs[0]));
994 1.1 thorpej bus_space_write_4(st, sh, EPIC_PRCDAR,
995 1.1 thorpej sc->sc_cddma + EPIC_CDOFF(ecd_rxdescs[0]));
996 1.1 thorpej
997 1.1 thorpej /*
998 1.1 thorpej * Initialize our ring pointers. txlast it initialized to
999 1.1 thorpej * the end of the list so that it will wrap around to the
1000 1.1 thorpej * first descriptor when the first packet is transmitted.
1001 1.1 thorpej */
1002 1.1 thorpej sc->sc_txpending = 0;
1003 1.1 thorpej sc->sc_txdirty = 0;
1004 1.1 thorpej sc->sc_txlast = EPIC_NTXDESC - 1;
1005 1.1 thorpej
1006 1.1 thorpej sc->sc_rxptr = 0;
1007 1.1 thorpej
1008 1.1 thorpej /*
1009 1.1 thorpej * Set the EPIC in motion.
1010 1.1 thorpej */
1011 1.1 thorpej bus_space_write_4(st, sh, EPIC_COMMAND,
1012 1.1 thorpej COMMAND_RXQUEUED | COMMAND_START_RX);
1013 1.1 thorpej
1014 1.1 thorpej /*
1015 1.1 thorpej * ...all done!
1016 1.1 thorpej */
1017 1.1 thorpej ifp->if_flags |= IFF_RUNNING;
1018 1.1 thorpej ifp->if_flags &= ~IFF_OACTIVE;
1019 1.1 thorpej }
1020 1.1 thorpej
1021 1.1 thorpej /*
1022 1.1 thorpej * Stop transmission on the interface.
1023 1.1 thorpej */
1024 1.1 thorpej void
1025 1.1 thorpej epic_stop(sc)
1026 1.1 thorpej struct epic_softc *sc;
1027 1.1 thorpej {
1028 1.1 thorpej bus_space_tag_t st = sc->sc_st;
1029 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
1030 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1031 1.1 thorpej struct epic_descsoft *ds;
1032 1.1 thorpej u_int32_t reg;
1033 1.1 thorpej int i;
1034 1.6 thorpej
1035 1.6 thorpej /* Paranoia... */
1036 1.6 thorpej epic_fixup_clock_source(sc);
1037 1.1 thorpej
1038 1.1 thorpej /*
1039 1.1 thorpej * Disable interrupts.
1040 1.1 thorpej */
1041 1.1 thorpej reg = bus_space_read_4(st, sh, EPIC_GENCTL);
1042 1.1 thorpej bus_space_write_4(st, sh, EPIC_GENCTL, reg & ~GENCTL_INTENA);
1043 1.1 thorpej bus_space_write_4(st, sh, EPIC_INTMASK, 0);
1044 1.1 thorpej
1045 1.1 thorpej /*
1046 1.1 thorpej * Stop the DMA engine and take the receiver off-line.
1047 1.1 thorpej */
1048 1.1 thorpej bus_space_write_4(st, sh, EPIC_COMMAND, COMMAND_STOP_RDMA |
1049 1.1 thorpej COMMAND_STOP_TDMA | COMMAND_STOP_RX);
1050 1.1 thorpej
1051 1.1 thorpej /*
1052 1.1 thorpej * Release any queued transmit buffers.
1053 1.1 thorpej */
1054 1.1 thorpej for (i = 0; i < EPIC_NTXDESC; i++) {
1055 1.1 thorpej ds = &sc->sc_txsoft[i];
1056 1.1 thorpej if (ds->ds_mbuf != NULL) {
1057 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
1058 1.1 thorpej m_freem(ds->ds_mbuf);
1059 1.1 thorpej ds->ds_mbuf = NULL;
1060 1.1 thorpej }
1061 1.1 thorpej }
1062 1.1 thorpej sc->sc_txpending = 0;
1063 1.1 thorpej
1064 1.1 thorpej /*
1065 1.1 thorpej * Release the receive buffers, then reallocate/reinitialize.
1066 1.1 thorpej */
1067 1.1 thorpej for (i = 0; i < EPIC_NRXDESC; i++) {
1068 1.1 thorpej ds = &sc->sc_rxsoft[i];
1069 1.1 thorpej if (ds->ds_mbuf != NULL) {
1070 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
1071 1.1 thorpej m_freem(ds->ds_mbuf);
1072 1.1 thorpej ds->ds_mbuf = NULL;
1073 1.1 thorpej }
1074 1.1 thorpej if (epic_add_rxbuf(sc, i) != 0) {
1075 1.1 thorpej /*
1076 1.1 thorpej * This "can't happen" - we're at splimp()
1077 1.1 thorpej * and we just freed the buffer we need
1078 1.1 thorpej * above.
1079 1.1 thorpej */
1080 1.1 thorpej panic("epic_stop: no buffers!");
1081 1.1 thorpej }
1082 1.1 thorpej }
1083 1.1 thorpej
1084 1.1 thorpej /*
1085 1.1 thorpej * Mark the interface down and cancel the watchdog timer.
1086 1.1 thorpej */
1087 1.1 thorpej ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1088 1.1 thorpej ifp->if_timer = 0;
1089 1.1 thorpej }
1090 1.1 thorpej
1091 1.1 thorpej /*
1092 1.1 thorpej * Read the EPIC Serial EEPROM.
1093 1.1 thorpej */
1094 1.1 thorpej void
1095 1.1 thorpej epic_read_eeprom(sc, word, wordcnt, data)
1096 1.1 thorpej struct epic_softc *sc;
1097 1.1 thorpej int word, wordcnt;
1098 1.1 thorpej u_int16_t *data;
1099 1.1 thorpej {
1100 1.1 thorpej bus_space_tag_t st = sc->sc_st;
1101 1.1 thorpej bus_space_handle_t sh = sc->sc_sh;
1102 1.1 thorpej u_int16_t reg;
1103 1.1 thorpej int i, x;
1104 1.1 thorpej
1105 1.1 thorpej #define EEPROM_WAIT_READY(st, sh) \
1106 1.1 thorpej while ((bus_space_read_4((st), (sh), EPIC_EECTL) & EECTL_EERDY) == 0) \
1107 1.1 thorpej /* nothing */
1108 1.1 thorpej
1109 1.1 thorpej /*
1110 1.1 thorpej * Enable the EEPROM.
1111 1.1 thorpej */
1112 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE);
1113 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1114 1.1 thorpej
1115 1.1 thorpej for (i = 0; i < wordcnt; i++) {
1116 1.1 thorpej /* Send CHIP SELECT for one clock tick. */
1117 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE|EECTL_EECS);
1118 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1119 1.1 thorpej
1120 1.1 thorpej /* Shift in the READ opcode. */
1121 1.1 thorpej for (x = 3; x > 0; x--) {
1122 1.1 thorpej reg = EECTL_ENABLE|EECTL_EECS;
1123 1.1 thorpej if (EPIC_EEPROM_OPC_READ & (1 << (x - 1)))
1124 1.1 thorpej reg |= EECTL_EEDI;
1125 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1126 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1127 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg|EECTL_EESK);
1128 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1129 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1130 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1131 1.1 thorpej }
1132 1.1 thorpej
1133 1.1 thorpej /* Shift in address. */
1134 1.1 thorpej for (x = 6; x > 0; x--) {
1135 1.1 thorpej reg = EECTL_ENABLE|EECTL_EECS;
1136 1.1 thorpej if ((word + i) & (1 << (x - 1)))
1137 1.1 thorpej reg |= EECTL_EEDI;
1138 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1139 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1140 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg|EECTL_EESK);
1141 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1142 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1143 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1144 1.1 thorpej }
1145 1.1 thorpej
1146 1.1 thorpej /* Shift out data. */
1147 1.1 thorpej reg = EECTL_ENABLE|EECTL_EECS;
1148 1.1 thorpej data[i] = 0;
1149 1.1 thorpej for (x = 16; x > 0; x--) {
1150 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg|EECTL_EESK);
1151 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1152 1.1 thorpej if (bus_space_read_4(st, sh, EPIC_EECTL) & EECTL_EEDO)
1153 1.1 thorpej data[i] |= (1 << (x - 1));
1154 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, reg);
1155 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1156 1.1 thorpej }
1157 1.1 thorpej
1158 1.1 thorpej /* Clear CHIP SELECT. */
1159 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, EECTL_ENABLE);
1160 1.1 thorpej EEPROM_WAIT_READY(st, sh);
1161 1.1 thorpej }
1162 1.1 thorpej
1163 1.1 thorpej /*
1164 1.1 thorpej * Disable the EEPROM.
1165 1.1 thorpej */
1166 1.1 thorpej bus_space_write_4(st, sh, EPIC_EECTL, 0);
1167 1.1 thorpej
1168 1.1 thorpej #undef EEPROM_WAIT_READY
1169 1.1 thorpej }
1170 1.1 thorpej
1171 1.1 thorpej /*
1172 1.1 thorpej * Add a receive buffer to the indicated descriptor.
1173 1.1 thorpej */
1174 1.1 thorpej int
1175 1.1 thorpej epic_add_rxbuf(sc, idx)
1176 1.1 thorpej struct epic_softc *sc;
1177 1.1 thorpej int idx;
1178 1.1 thorpej {
1179 1.1 thorpej struct epic_rxdesc *rxd = &sc->sc_control_data->ecd_rxdescs[idx];
1180 1.1 thorpej struct epic_descsoft *ds = &sc->sc_rxsoft[idx];
1181 1.1 thorpej struct mbuf *m, *oldm;
1182 1.1 thorpej int error = 0;
1183 1.1 thorpej
1184 1.1 thorpej oldm = ds->ds_mbuf;
1185 1.1 thorpej
1186 1.1 thorpej MGETHDR(m, M_DONTWAIT, MT_DATA);
1187 1.1 thorpej if (m != NULL) {
1188 1.1 thorpej MCLGET(m, M_DONTWAIT);
1189 1.1 thorpej if ((m->m_flags & M_EXT) == 0) {
1190 1.1 thorpej error = ENOMEM;
1191 1.1 thorpej m_freem(m);
1192 1.1 thorpej if (oldm == NULL)
1193 1.1 thorpej return (error);
1194 1.1 thorpej m = oldm;
1195 1.1 thorpej m->m_data = m->m_ext.ext_buf;
1196 1.1 thorpej }
1197 1.1 thorpej } else {
1198 1.1 thorpej error = ENOMEM;
1199 1.1 thorpej if (oldm == NULL)
1200 1.1 thorpej return (error);
1201 1.1 thorpej m = oldm;
1202 1.1 thorpej m->m_data = m->m_ext.ext_buf;
1203 1.1 thorpej }
1204 1.1 thorpej
1205 1.1 thorpej ds->ds_mbuf = m;
1206 1.1 thorpej
1207 1.1 thorpej /*
1208 1.1 thorpej * Set up the DMA map for this receive buffer.
1209 1.1 thorpej */
1210 1.1 thorpej if (m != oldm) {
1211 1.1 thorpej if (oldm != NULL)
1212 1.1 thorpej bus_dmamap_unload(sc->sc_dmat, ds->ds_dmamap);
1213 1.1 thorpej error = bus_dmamap_load(sc->sc_dmat, ds->ds_dmamap,
1214 1.1 thorpej m->m_ext.ext_buf, m->m_ext.ext_size, NULL, BUS_DMA_NOWAIT);
1215 1.1 thorpej if (error) {
1216 1.1 thorpej printf("%s: can't load rx buffer, error = %d\n",
1217 1.1 thorpej sc->sc_dev.dv_xname, error);
1218 1.1 thorpej panic("epic_add_rxbuf"); /* XXX */
1219 1.1 thorpej }
1220 1.1 thorpej }
1221 1.1 thorpej
1222 1.1 thorpej bus_dmamap_sync(sc->sc_dmat, ds->ds_dmamap, 0,
1223 1.1 thorpej ds->ds_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1224 1.1 thorpej
1225 1.1 thorpej /*
1226 1.1 thorpej * Move the data pointer up so that the incoming packet
1227 1.1 thorpej * will be 32-bit aligned.
1228 1.1 thorpej */
1229 1.1 thorpej m->m_data += RX_ALIGNMENT_FUDGE;
1230 1.1 thorpej
1231 1.1 thorpej /*
1232 1.1 thorpej * Initialize the receive descriptor.
1233 1.1 thorpej */
1234 1.1 thorpej rxd->er_bufaddr = ds->ds_dmamap->dm_segs[0].ds_addr +
1235 1.1 thorpej RX_ALIGNMENT_FUDGE;
1236 1.1 thorpej rxd->er_buflength = m->m_ext.ext_size - RX_ALIGNMENT_FUDGE;
1237 1.1 thorpej rxd->er_control = 0;
1238 1.1 thorpej rxd->er_rxstatus = ER_RXSTAT_OWNER;
1239 1.1 thorpej
1240 1.1 thorpej return (error);
1241 1.1 thorpej }
1242 1.1 thorpej
1243 1.1 thorpej /*
1244 1.1 thorpej * Set the EPIC multicast hash table.
1245 1.1 thorpej */
1246 1.1 thorpej void
1247 1.1 thorpej epic_set_mchash(sc)
1248 1.1 thorpej struct epic_softc *sc;
1249 1.1 thorpej {
1250 1.1 thorpej struct ethercom *ec = &sc->sc_ethercom;
1251 1.1 thorpej struct ifnet *ifp = &sc->sc_ethercom.ec_if;
1252 1.1 thorpej struct ether_multi *enm;
1253 1.1 thorpej struct ether_multistep step;
1254 1.1 thorpej u_int8_t *cp;
1255 1.1 thorpej u_int32_t crc, mchash[4];
1256 1.1 thorpej int len;
1257 1.1 thorpej static const u_int32_t crctab[] = {
1258 1.1 thorpej 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
1259 1.1 thorpej 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
1260 1.1 thorpej 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
1261 1.1 thorpej 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
1262 1.1 thorpej };
1263 1.1 thorpej
1264 1.1 thorpej /*
1265 1.1 thorpej * Set up the multicast address filter by passing all multicast
1266 1.1 thorpej * addresses through a CRC generator, and then using the high-order
1267 1.1 thorpej * 6 bits as an index into the 64 bit multicast hash table (only
1268 1.1 thorpej * the lower 16 bits of each 32 bit multicast hash register are
1269 1.1 thorpej * valid). The high order bit selects the register, while the
1270 1.1 thorpej * rest of the bits select the bit within the register.
1271 1.1 thorpej */
1272 1.1 thorpej
1273 1.1 thorpej if (ifp->if_flags & IFF_PROMISC)
1274 1.1 thorpej goto allmulti;
1275 1.1 thorpej
1276 1.1 thorpej #if 1 /* XXX thorpej - hardware bug in 10Mb mode */
1277 1.1 thorpej goto allmulti;
1278 1.1 thorpej #endif
1279 1.1 thorpej
1280 1.1 thorpej mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0;
1281 1.1 thorpej
1282 1.1 thorpej ETHER_FIRST_MULTI(step, ec, enm);
1283 1.1 thorpej while (enm != NULL) {
1284 1.1 thorpej if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1285 1.1 thorpej /*
1286 1.1 thorpej * We must listen to a range of multicast addresses.
1287 1.1 thorpej * For now, just accept all multicasts, rather than
1288 1.1 thorpej * trying to set only those filter bits needed to match
1289 1.1 thorpej * the range. (At this time, the only use of address
1290 1.1 thorpej * ranges is for IP multicast routing, for which the
1291 1.1 thorpej * range is big enough to require all bits set.)
1292 1.1 thorpej */
1293 1.1 thorpej goto allmulti;
1294 1.1 thorpej }
1295 1.1 thorpej
1296 1.1 thorpej cp = enm->enm_addrlo;
1297 1.1 thorpej crc = 0xffffffff;
1298 1.1 thorpej for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
1299 1.1 thorpej crc ^= *cp++;
1300 1.1 thorpej crc = (crc >> 4) ^ crctab[crc & 0xf];
1301 1.1 thorpej crc = (crc >> 4) ^ crctab[crc & 0xf];
1302 1.1 thorpej }
1303 1.1 thorpej /* Just want the 6 most significant bits. */
1304 1.1 thorpej crc >>= 26;
1305 1.1 thorpej
1306 1.1 thorpej /* Set the corresponding bit in the hash table. */
1307 1.1 thorpej mchash[crc >> 4] |= 1 << (crc & 0xf);
1308 1.1 thorpej
1309 1.1 thorpej ETHER_NEXT_MULTI(step, enm);
1310 1.1 thorpej }
1311 1.1 thorpej
1312 1.1 thorpej ifp->if_flags &= ~IFF_ALLMULTI;
1313 1.1 thorpej goto sethash;
1314 1.1 thorpej
1315 1.1 thorpej allmulti:
1316 1.1 thorpej ifp->if_flags |= IFF_ALLMULTI;
1317 1.1 thorpej mchash[0] = mchash[1] = mchash[2] = mchash[3] = 0xffff;
1318 1.1 thorpej
1319 1.1 thorpej sethash:
1320 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC0, mchash[0]);
1321 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC1, mchash[1]);
1322 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC2, mchash[2]);
1323 1.1 thorpej bus_space_write_4(sc->sc_st, sc->sc_sh, EPIC_MC3, mchash[3]);
1324 1.1 thorpej }
1325