Annotation of sys/dev/ic/hme.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: hme.c,v 1.46 2006/12/21 22:13:36 jason Exp $ */
2: /* $NetBSD: hme.c,v 1.21 2001/07/07 15:59:37 thorpej Exp $ */
3:
4: /*-
5: * Copyright (c) 1999 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Paul Kranenburg.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: /*
41: * HME Ethernet module driver.
42: */
43:
44: #include "bpfilter.h"
45: #include "vlan.h"
46:
47: #undef HMEDEBUG
48:
49: #include <sys/param.h>
50: #include <sys/systm.h>
51: #include <sys/kernel.h>
52: #include <sys/mbuf.h>
53: #include <sys/syslog.h>
54: #include <sys/socket.h>
55: #include <sys/device.h>
56: #include <sys/malloc.h>
57: #include <sys/ioctl.h>
58: #include <sys/errno.h>
59:
60: #include <net/if.h>
61: #include <net/if_dl.h>
62: #include <net/if_media.h>
63:
64: #ifdef INET
65: #include <netinet/in.h>
66: #include <netinet/in_systm.h>
67: #include <netinet/in_var.h>
68: #include <netinet/ip.h>
69: #include <netinet/if_ether.h>
70: #include <netinet/tcp.h>
71: #include <netinet/udp.h>
72: #endif
73:
74: #if NBPFILTER > 0
75: #include <net/bpf.h>
76: #endif
77:
78: #include <dev/mii/mii.h>
79: #include <dev/mii/miivar.h>
80:
81: #include <machine/bus.h>
82:
83: #include <dev/ic/hmereg.h>
84: #include <dev/ic/hmevar.h>
85:
86: struct cfdriver hme_cd = {
87: NULL, "hme", DV_IFNET
88: };
89:
90: #define HME_RX_OFFSET 2
91:
92: void hme_start(struct ifnet *);
93: void hme_stop(struct hme_softc *);
94: int hme_ioctl(struct ifnet *, u_long, caddr_t);
95: void hme_tick(void *);
96: void hme_watchdog(struct ifnet *);
97: void hme_shutdown(void *);
98: void hme_init(struct hme_softc *);
99: void hme_meminit(struct hme_softc *);
100: void hme_mifinit(struct hme_softc *);
101: void hme_reset(struct hme_softc *);
102: void hme_setladrf(struct hme_softc *);
103: int hme_newbuf(struct hme_softc *, struct hme_sxd *, int);
104: int hme_encap(struct hme_softc *, struct mbuf *, int *);
105:
106: /* MII methods & callbacks */
107: static int hme_mii_readreg(struct device *, int, int);
108: static void hme_mii_writereg(struct device *, int, int, int);
109: static void hme_mii_statchg(struct device *);
110:
111: int hme_mediachange(struct ifnet *);
112: void hme_mediastatus(struct ifnet *, struct ifmediareq *);
113:
114: int hme_eint(struct hme_softc *, u_int);
115: int hme_rint(struct hme_softc *);
116: int hme_tint(struct hme_softc *);
117: /* TCP/UDP checksum offload support */
118: void hme_rxcksum(struct mbuf *, u_int32_t);
119:
120: void
121: hme_config(sc)
122: struct hme_softc *sc;
123: {
124: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
125: struct mii_data *mii = &sc->sc_mii;
126: struct mii_softc *child;
127: bus_dma_tag_t dmatag = sc->sc_dmatag;
128: bus_dma_segment_t seg;
129: bus_size_t size;
130: int rseg, error, i;
131:
132: /*
133: * HME common initialization.
134: *
135: * hme_softc fields that must be initialized by the front-end:
136: *
137: * the bus tag:
138: * sc_bustag
139: *
140: * the dma bus tag:
141: * sc_dmatag
142: *
143: * the bus handles:
144: * sc_seb (Shared Ethernet Block registers)
145: * sc_erx (Receiver Unit registers)
146: * sc_etx (Transmitter Unit registers)
147: * sc_mac (MAC registers)
148: * sc_mif (Management Interface registers)
149: *
150: * the maximum bus burst size:
151: * sc_burst
152: *
153: * the local Ethernet address:
154: * sc_arpcom.ac_enaddr
155: *
156: */
157:
158: /* Make sure the chip is stopped. */
159: hme_stop(sc);
160:
161: for (i = 0; i < HME_TX_RING_SIZE; i++) {
162: if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, 1,
163: MCLBYTES, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
164: &sc->sc_txd[i].sd_map) != 0) {
165: sc->sc_txd[i].sd_map = NULL;
166: goto fail;
167: }
168: }
169: for (i = 0; i < HME_RX_RING_SIZE; i++) {
170: if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, 1,
171: MCLBYTES, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
172: &sc->sc_rxd[i].sd_map) != 0) {
173: sc->sc_rxd[i].sd_map = NULL;
174: goto fail;
175: }
176: }
177: if (bus_dmamap_create(sc->sc_dmatag, MCLBYTES, 1, MCLBYTES, 0,
178: BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_rxmap_spare) != 0) {
179: sc->sc_rxmap_spare = NULL;
180: goto fail;
181: }
182:
183: /*
184: * Allocate DMA capable memory
185: * Buffer descriptors must be aligned on a 2048 byte boundary;
186: * take this into account when calculating the size. Note that
187: * the maximum number of descriptors (256) occupies 2048 bytes,
188: * so we allocate that much regardless of the number of descriptors.
189: */
190: size = (HME_XD_SIZE * HME_RX_RING_MAX) + /* RX descriptors */
191: (HME_XD_SIZE * HME_TX_RING_MAX); /* TX descriptors */
192:
193: /* Allocate DMA buffer */
194: if ((error = bus_dmamem_alloc(dmatag, size, 2048, 0, &seg, 1, &rseg,
195: BUS_DMA_NOWAIT)) != 0) {
196: printf("\n%s: DMA buffer alloc error %d\n",
197: sc->sc_dev.dv_xname, error);
198: return;
199: }
200:
201: /* Map DMA memory in CPU addressable space */
202: if ((error = bus_dmamem_map(dmatag, &seg, rseg, size,
203: &sc->sc_rb.rb_membase, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
204: printf("\n%s: DMA buffer map error %d\n",
205: sc->sc_dev.dv_xname, error);
206: bus_dmamap_unload(dmatag, sc->sc_dmamap);
207: bus_dmamem_free(dmatag, &seg, rseg);
208: return;
209: }
210:
211: if ((error = bus_dmamap_create(dmatag, size, 1, size, 0,
212: BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
213: printf("\n%s: DMA map create error %d\n",
214: sc->sc_dev.dv_xname, error);
215: return;
216: }
217:
218: /* Load the buffer */
219: if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap,
220: sc->sc_rb.rb_membase, size, NULL,
221: BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
222: printf("\n%s: DMA buffer map load error %d\n",
223: sc->sc_dev.dv_xname, error);
224: bus_dmamem_free(dmatag, &seg, rseg);
225: return;
226: }
227: sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr;
228:
229: printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
230:
231: /* Initialize ifnet structure. */
232: strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof ifp->if_xname);
233: ifp->if_softc = sc;
234: ifp->if_start = hme_start;
235: ifp->if_ioctl = hme_ioctl;
236: ifp->if_watchdog = hme_watchdog;
237: ifp->if_flags =
238: IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
239: sc->sc_if_flags = ifp->if_flags;
240: IFQ_SET_READY(&ifp->if_snd);
241: ifp->if_capabilities = IFCAP_VLAN_MTU;
242:
243: /* Initialize ifmedia structures and MII info */
244: mii->mii_ifp = ifp;
245: mii->mii_readreg = hme_mii_readreg;
246: mii->mii_writereg = hme_mii_writereg;
247: mii->mii_statchg = hme_mii_statchg;
248:
249: ifmedia_init(&mii->mii_media, IFM_IMASK,
250: hme_mediachange, hme_mediastatus);
251:
252: hme_mifinit(sc);
253:
254: if (sc->sc_tcvr == -1)
255: mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY,
256: MII_OFFSET_ANY, 0);
257: else
258: mii_attach(&sc->sc_dev, mii, 0xffffffff, sc->sc_tcvr,
259: MII_OFFSET_ANY, 0);
260:
261: child = LIST_FIRST(&mii->mii_phys);
262: if (child == NULL) {
263: /* No PHY attached */
264: ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
265: ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
266: } else {
267: /*
268: * Walk along the list of attached MII devices and
269: * establish an `MII instance' to `phy number'
270: * mapping. We'll use this mapping in media change
271: * requests to determine which phy to use to program
272: * the MIF configuration register.
273: */
274: for (; child != NULL; child = LIST_NEXT(child, mii_list)) {
275: /*
276: * Note: we support just two PHYs: the built-in
277: * internal device and an external on the MII
278: * connector.
279: */
280: if (child->mii_phy > 1 || child->mii_inst > 1) {
281: printf("%s: cannot accommodate MII device %s"
282: " at phy %d, instance %d\n",
283: sc->sc_dev.dv_xname,
284: child->mii_dev.dv_xname,
285: child->mii_phy, child->mii_inst);
286: continue;
287: }
288:
289: sc->sc_phys[child->mii_inst] = child->mii_phy;
290: }
291:
292: /*
293: * XXX - we can really do the following ONLY if the
294: * phy indeed has the auto negotiation capability!!
295: */
296: ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
297: }
298:
299: /* Attach the interface. */
300: if_attach(ifp);
301: ether_ifattach(ifp);
302:
303: sc->sc_sh = shutdownhook_establish(hme_shutdown, sc);
304: if (sc->sc_sh == NULL)
305: panic("hme_config: can't establish shutdownhook");
306:
307: timeout_set(&sc->sc_tick_ch, hme_tick, sc);
308: return;
309:
310: fail:
311: if (sc->sc_rxmap_spare != NULL)
312: bus_dmamap_destroy(sc->sc_dmatag, sc->sc_rxmap_spare);
313: for (i = 0; i < HME_TX_RING_SIZE; i++)
314: if (sc->sc_txd[i].sd_map != NULL)
315: bus_dmamap_destroy(sc->sc_dmatag, sc->sc_txd[i].sd_map);
316: for (i = 0; i < HME_RX_RING_SIZE; i++)
317: if (sc->sc_rxd[i].sd_map != NULL)
318: bus_dmamap_destroy(sc->sc_dmatag, sc->sc_rxd[i].sd_map);
319: }
320:
321: void
322: hme_tick(arg)
323: void *arg;
324: {
325: struct hme_softc *sc = arg;
326: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
327: bus_space_tag_t t = sc->sc_bustag;
328: bus_space_handle_t mac = sc->sc_mac;
329: int s;
330:
331: s = splnet();
332: /*
333: * Unload collision counters
334: */
335: ifp->if_collisions +=
336: bus_space_read_4(t, mac, HME_MACI_NCCNT) +
337: bus_space_read_4(t, mac, HME_MACI_FCCNT) +
338: bus_space_read_4(t, mac, HME_MACI_EXCNT) +
339: bus_space_read_4(t, mac, HME_MACI_LTCNT);
340:
341: /*
342: * then clear the hardware counters.
343: */
344: bus_space_write_4(t, mac, HME_MACI_NCCNT, 0);
345: bus_space_write_4(t, mac, HME_MACI_FCCNT, 0);
346: bus_space_write_4(t, mac, HME_MACI_EXCNT, 0);
347: bus_space_write_4(t, mac, HME_MACI_LTCNT, 0);
348:
349: mii_tick(&sc->sc_mii);
350: splx(s);
351:
352: timeout_add(&sc->sc_tick_ch, hz);
353: }
354:
355: void
356: hme_reset(sc)
357: struct hme_softc *sc;
358: {
359: int s;
360:
361: s = splnet();
362: hme_init(sc);
363: splx(s);
364: }
365:
366: void
367: hme_stop(sc)
368: struct hme_softc *sc;
369: {
370: bus_space_tag_t t = sc->sc_bustag;
371: bus_space_handle_t seb = sc->sc_seb;
372: int n;
373:
374: timeout_del(&sc->sc_tick_ch);
375: mii_down(&sc->sc_mii);
376:
377: /* Mask all interrupts */
378: bus_space_write_4(t, seb, HME_SEBI_IMASK, 0xffffffff);
379:
380: /* Reset transmitter and receiver */
381: bus_space_write_4(t, seb, HME_SEBI_RESET,
382: (HME_SEB_RESET_ETX | HME_SEB_RESET_ERX));
383:
384: for (n = 0; n < 20; n++) {
385: u_int32_t v = bus_space_read_4(t, seb, HME_SEBI_RESET);
386: if ((v & (HME_SEB_RESET_ETX | HME_SEB_RESET_ERX)) == 0)
387: break;
388: DELAY(20);
389: }
390: if (n >= 20)
391: printf("%s: hme_stop: reset failed\n", sc->sc_dev.dv_xname);
392:
393: for (n = 0; n < HME_TX_RING_SIZE; n++) {
394: if (sc->sc_txd[n].sd_loaded) {
395: bus_dmamap_sync(sc->sc_dmatag, sc->sc_txd[n].sd_map,
396: 0, sc->sc_txd[n].sd_map->dm_mapsize,
397: BUS_DMASYNC_POSTWRITE);
398: bus_dmamap_unload(sc->sc_dmatag, sc->sc_txd[n].sd_map);
399: sc->sc_txd[n].sd_loaded = 0;
400: }
401: if (sc->sc_txd[n].sd_mbuf != NULL) {
402: m_freem(sc->sc_txd[n].sd_mbuf);
403: sc->sc_txd[n].sd_mbuf = NULL;
404: }
405: }
406: }
407:
408: void
409: hme_meminit(sc)
410: struct hme_softc *sc;
411: {
412: bus_addr_t dma;
413: caddr_t p;
414: unsigned int i;
415: struct hme_ring *hr = &sc->sc_rb;
416:
417: p = hr->rb_membase;
418: dma = hr->rb_dmabase;
419:
420: /*
421: * Allocate transmit descriptors
422: */
423: hr->rb_txd = p;
424: hr->rb_txddma = dma;
425: p += HME_TX_RING_SIZE * HME_XD_SIZE;
426: dma += HME_TX_RING_SIZE * HME_XD_SIZE;
427: /* We have reserved descriptor space until the next 2048 byte boundary.*/
428: dma = (bus_addr_t)roundup((u_long)dma, 2048);
429: p = (caddr_t)roundup((u_long)p, 2048);
430:
431: /*
432: * Allocate receive descriptors
433: */
434: hr->rb_rxd = p;
435: hr->rb_rxddma = dma;
436: p += HME_RX_RING_SIZE * HME_XD_SIZE;
437: dma += HME_RX_RING_SIZE * HME_XD_SIZE;
438: /* Again move forward to the next 2048 byte boundary.*/
439: dma = (bus_addr_t)roundup((u_long)dma, 2048);
440: p = (caddr_t)roundup((u_long)p, 2048);
441:
442: /*
443: * Initialize transmit descriptors
444: */
445: for (i = 0; i < HME_TX_RING_SIZE; i++) {
446: HME_XD_SETADDR(sc->sc_pci, hr->rb_txd, i, 0);
447: HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, i, 0);
448: sc->sc_txd[i].sd_mbuf = NULL;
449: }
450:
451: /*
452: * Initialize receive descriptors
453: */
454: for (i = 0; i < HME_RX_RING_SIZE; i++) {
455: if (hme_newbuf(sc, &sc->sc_rxd[i], 1)) {
456: printf("%s: rx allocation failed\n",
457: sc->sc_dev.dv_xname);
458: break;
459: }
460: HME_XD_SETADDR(sc->sc_pci, hr->rb_rxd, i,
461: sc->sc_rxd[i].sd_map->dm_segs[0].ds_addr);
462: HME_XD_SETFLAGS(sc->sc_pci, hr->rb_rxd, i,
463: HME_XD_OWN | HME_XD_ENCODE_RSIZE(HME_RX_PKTSIZE));
464: }
465:
466: sc->sc_tx_prod = sc->sc_tx_cons = sc->sc_tx_cnt = 0;
467: sc->sc_last_rd = 0;
468: }
469:
470: /*
471: * Initialization of interface; set up initialization block
472: * and transmit/receive descriptor rings.
473: */
474: void
475: hme_init(sc)
476: struct hme_softc *sc;
477: {
478: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
479: bus_space_tag_t t = sc->sc_bustag;
480: bus_space_handle_t seb = sc->sc_seb;
481: bus_space_handle_t etx = sc->sc_etx;
482: bus_space_handle_t erx = sc->sc_erx;
483: bus_space_handle_t mac = sc->sc_mac;
484: u_int8_t *ea;
485: u_int32_t v, n;
486:
487: /*
488: * Initialization sequence. The numbered steps below correspond
489: * to the sequence outlined in section 6.3.5.1 in the Ethernet
490: * Channel Engine manual (part of the PCIO manual).
491: * See also the STP2002-STQ document from Sun Microsystems.
492: */
493:
494: /* step 1 & 2. Reset the Ethernet Channel */
495: hme_stop(sc);
496:
497: /* Re-initialize the MIF */
498: hme_mifinit(sc);
499:
500: /* Call MI reset function if any */
501: if (sc->sc_hwreset)
502: (*sc->sc_hwreset)(sc);
503:
504: #if 0
505: /* Mask all MIF interrupts, just in case */
506: bus_space_write_4(t, mif, HME_MIFI_IMASK, 0xffff);
507: #endif
508:
509: /* step 3. Setup data structures in host memory */
510: hme_meminit(sc);
511:
512: /* step 4. TX MAC registers & counters */
513: bus_space_write_4(t, mac, HME_MACI_NCCNT, 0);
514: bus_space_write_4(t, mac, HME_MACI_FCCNT, 0);
515: bus_space_write_4(t, mac, HME_MACI_EXCNT, 0);
516: bus_space_write_4(t, mac, HME_MACI_LTCNT, 0);
517: bus_space_write_4(t, mac, HME_MACI_TXSIZE, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
518:
519: /* Load station MAC address */
520: ea = sc->sc_arpcom.ac_enaddr;
521: bus_space_write_4(t, mac, HME_MACI_MACADDR0, (ea[0] << 8) | ea[1]);
522: bus_space_write_4(t, mac, HME_MACI_MACADDR1, (ea[2] << 8) | ea[3]);
523: bus_space_write_4(t, mac, HME_MACI_MACADDR2, (ea[4] << 8) | ea[5]);
524:
525: /*
526: * Init seed for backoff
527: * (source suggested by manual: low 10 bits of MAC address)
528: */
529: v = ((ea[4] << 8) | ea[5]) & 0x3fff;
530: bus_space_write_4(t, mac, HME_MACI_RANDSEED, v);
531:
532:
533: /* Note: Accepting power-on default for other MAC registers here.. */
534:
535:
536: /* step 5. RX MAC registers & counters */
537: hme_setladrf(sc);
538:
539: /* step 6 & 7. Program Descriptor Ring Base Addresses */
540: bus_space_write_4(t, etx, HME_ETXI_RING, sc->sc_rb.rb_txddma);
541: bus_space_write_4(t, etx, HME_ETXI_RSIZE, HME_TX_RING_SIZE);
542:
543: bus_space_write_4(t, erx, HME_ERXI_RING, sc->sc_rb.rb_rxddma);
544: bus_space_write_4(t, mac, HME_MACI_RXSIZE, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
545:
546: /* step 8. Global Configuration & Interrupt Mask */
547: bus_space_write_4(t, seb, HME_SEBI_IMASK,
548: ~(HME_SEB_STAT_HOSTTOTX | HME_SEB_STAT_RXTOHOST |
549: HME_SEB_STAT_TXALL | HME_SEB_STAT_TXPERR |
550: HME_SEB_STAT_RCNTEXP | HME_SEB_STAT_ALL_ERRORS));
551:
552: switch (sc->sc_burst) {
553: default:
554: v = 0;
555: break;
556: case 16:
557: v = HME_SEB_CFG_BURST16;
558: break;
559: case 32:
560: v = HME_SEB_CFG_BURST32;
561: break;
562: case 64:
563: v = HME_SEB_CFG_BURST64;
564: break;
565: }
566: bus_space_write_4(t, seb, HME_SEBI_CFG, v);
567:
568: /* step 9. ETX Configuration: use mostly default values */
569:
570: /* Enable DMA */
571: v = bus_space_read_4(t, etx, HME_ETXI_CFG);
572: v |= HME_ETX_CFG_DMAENABLE;
573: bus_space_write_4(t, etx, HME_ETXI_CFG, v);
574:
575: /* Transmit Descriptor ring size: in increments of 16 */
576: bus_space_write_4(t, etx, HME_ETXI_RSIZE, HME_TX_RING_SIZE / 16 - 1);
577:
578: /* step 10. ERX Configuration */
579: v = bus_space_read_4(t, erx, HME_ERXI_CFG);
580: v &= ~HME_ERX_CFG_RINGSIZE256;
581: #if HME_RX_RING_SIZE == 32
582: v |= HME_ERX_CFG_RINGSIZE32;
583: #elif HME_RX_RING_SIZE == 64
584: v |= HME_ERX_CFG_RINGSIZE64;
585: #elif HME_RX_RING_SIZE == 128
586: v |= HME_ERX_CFG_RINGSIZE128;
587: #elif HME_RX_RING_SIZE == 256
588: v |= HME_ERX_CFG_RINGSIZE256;
589: #else
590: # error "RX ring size must be 32, 64, 128, or 256"
591: #endif
592: /* Enable DMA */
593: v |= HME_ERX_CFG_DMAENABLE | (HME_RX_OFFSET << 3);
594: /* RX TCP/UDP cksum offset */
595: n = (ETHER_HDR_LEN + sizeof(struct ip)) / 2;
596: n = (n << HME_ERX_CFG_CSUM_SHIFT) & HME_ERX_CFG_CSUMSTART;
597: v |= n;
598: bus_space_write_4(t, erx, HME_ERXI_CFG, v);
599:
600: /* step 11. XIF Configuration */
601: v = bus_space_read_4(t, mac, HME_MACI_XIF);
602: v |= HME_MAC_XIF_OE;
603: bus_space_write_4(t, mac, HME_MACI_XIF, v);
604:
605: /* step 12. RX_MAC Configuration Register */
606: v = bus_space_read_4(t, mac, HME_MACI_RXCFG);
607: v |= HME_MAC_RXCFG_ENABLE;
608: bus_space_write_4(t, mac, HME_MACI_RXCFG, v);
609:
610: /* step 13. TX_MAC Configuration Register */
611: v = bus_space_read_4(t, mac, HME_MACI_TXCFG);
612: v |= (HME_MAC_TXCFG_ENABLE | HME_MAC_TXCFG_DGIVEUP);
613: bus_space_write_4(t, mac, HME_MACI_TXCFG, v);
614:
615: /* step 14. Issue Transmit Pending command */
616:
617: /* Call MI initialization function if any */
618: if (sc->sc_hwinit)
619: (*sc->sc_hwinit)(sc);
620:
621: /* Set the current media. */
622: mii_mediachg(&sc->sc_mii);
623:
624: /* Start the one second timer. */
625: timeout_add(&sc->sc_tick_ch, hz);
626:
627: ifp->if_flags |= IFF_RUNNING;
628: ifp->if_flags &= ~IFF_OACTIVE;
629: sc->sc_if_flags = ifp->if_flags;
630: ifp->if_timer = 0;
631: hme_start(ifp);
632: }
633:
634: void
635: hme_start(ifp)
636: struct ifnet *ifp;
637: {
638: struct hme_softc *sc = (struct hme_softc *)ifp->if_softc;
639: struct mbuf *m;
640: int bix, cnt = 0;
641:
642: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
643: return;
644:
645: bix = sc->sc_tx_prod;
646: while (sc->sc_txd[bix].sd_mbuf == NULL) {
647: IFQ_POLL(&ifp->if_snd, m);
648: if (m == NULL)
649: break;
650:
651: #if NBPFILTER > 0
652: /*
653: * If BPF is listening on this interface, let it see the
654: * packet before we commit it to the wire.
655: */
656: if (ifp->if_bpf)
657: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
658: #endif
659:
660: if (hme_encap(sc, m, &bix)) {
661: ifp->if_flags |= IFF_OACTIVE;
662: break;
663: }
664:
665: IFQ_DEQUEUE(&ifp->if_snd, m);
666:
667: bus_space_write_4(sc->sc_bustag, sc->sc_etx, HME_ETXI_PENDING,
668: HME_ETX_TP_DMAWAKEUP);
669: cnt++;
670: }
671:
672: if (cnt != 0) {
673: sc->sc_tx_prod = bix;
674: ifp->if_timer = 5;
675: }
676: }
677:
678: /*
679: * Transmit interrupt.
680: */
681: int
682: hme_tint(sc)
683: struct hme_softc *sc;
684: {
685: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
686: unsigned int ri, txflags;
687: struct hme_sxd *sd;
688: int cnt = sc->sc_tx_cnt;
689:
690: /* Fetch current position in the transmit ring */
691: ri = sc->sc_tx_cons;
692: sd = &sc->sc_txd[ri];
693:
694: for (;;) {
695: if (cnt <= 0)
696: break;
697:
698: txflags = HME_XD_GETFLAGS(sc->sc_pci, sc->sc_rb.rb_txd, ri);
699:
700: if (txflags & HME_XD_OWN)
701: break;
702:
703: ifp->if_flags &= ~IFF_OACTIVE;
704: if (txflags & HME_XD_EOP)
705: ifp->if_opackets++;
706:
707: bus_dmamap_sync(sc->sc_dmatag, sd->sd_map,
708: 0, sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
709: bus_dmamap_unload(sc->sc_dmatag, sd->sd_map);
710: sd->sd_loaded = 0;
711:
712: if (sd->sd_mbuf != NULL) {
713: m_freem(sd->sd_mbuf);
714: sd->sd_mbuf = NULL;
715: }
716:
717: if (++ri == HME_TX_RING_SIZE) {
718: ri = 0;
719: sd = sc->sc_txd;
720: } else
721: sd++;
722:
723: --cnt;
724: }
725:
726: sc->sc_tx_cnt = cnt;
727: ifp->if_timer = cnt > 0 ? 5 : 0;
728:
729: /* Update ring */
730: sc->sc_tx_cons = ri;
731:
732: hme_start(ifp);
733:
734: return (1);
735: }
736:
737: /*
738: * XXX layering violation
739: *
740: * If we can have additional csum data member in 'struct pkthdr' for
741: * these incomplete checksum offload capable hardware, things would be
742: * much simpler. That member variable will carry partial checksum
743: * data and it may be evaluated in TCP/UDP input handler after
744: * computing pseudo header checksumming.
745: */
746: void
747: hme_rxcksum(struct mbuf *m, u_int32_t flags)
748: {
749: struct ether_header *eh;
750: struct ip *ip;
751: struct udphdr *uh;
752: int32_t hlen, len, pktlen;
753: u_int16_t cksum, *opts;
754: u_int32_t temp32;
755: union pseudoh {
756: struct hdr {
757: u_int16_t len;
758: u_int8_t ttl;
759: u_int8_t proto;
760: u_int32_t src;
761: u_int32_t dst;
762: } h;
763: u_int16_t w[6];
764: } ph;
765:
766: pktlen = m->m_pkthdr.len;
767: if (pktlen < sizeof(struct ether_header))
768: return;
769: eh = mtod(m, struct ether_header *);
770: if (eh->ether_type != htons(ETHERTYPE_IP))
771: return;
772: ip = (struct ip *)(eh + 1);
773: if (ip->ip_v != IPVERSION)
774: return;
775:
776: hlen = ip->ip_hl << 2;
777: pktlen -= sizeof(struct ether_header);
778: if (hlen < sizeof(struct ip))
779: return;
780: if (ntohs(ip->ip_len) < hlen)
781: return;
782: if (ntohs(ip->ip_len) != pktlen)
783: return;
784: if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
785: return; /* can't handle fragmented packet */
786:
787: switch (ip->ip_p) {
788: case IPPROTO_TCP:
789: if (pktlen < (hlen + sizeof(struct tcphdr)))
790: return;
791: break;
792: case IPPROTO_UDP:
793: if (pktlen < (hlen + sizeof(struct udphdr)))
794: return;
795: uh = (struct udphdr *)((caddr_t)ip + hlen);
796: if (uh->uh_sum == 0)
797: return; /* no checksum */
798: break;
799: default:
800: return;
801: }
802:
803: cksum = htons(~(flags & HME_XD_RXCKSUM));
804: /* cksum fixup for IP options */
805: len = hlen - sizeof(struct ip);
806: if (len > 0) {
807: opts = (u_int16_t *)(ip + 1);
808: for (; len > 0; len -= sizeof(u_int16_t), opts++) {
809: temp32 = cksum - *opts;
810: temp32 = (temp32 >> 16) + (temp32 & 65535);
811: cksum = temp32 & 65535;
812: }
813: }
814: /* cksum fixup for pseudo-header, replace with in_cksum_phdr()? */
815: ph.h.len = htons(ntohs(ip->ip_len) - hlen);
816: ph.h.ttl = 0;
817: ph.h.proto = ip->ip_p;
818: ph.h.src = ip->ip_src.s_addr;
819: ph.h.dst = ip->ip_dst.s_addr;
820: temp32 = cksum;
821: opts = &ph.w[0];
822: temp32 += opts[0] + opts[1] + opts[2] + opts[3] + opts[4] + opts[5];
823: temp32 = (temp32 >> 16) + (temp32 & 65535);
824: temp32 += (temp32 >> 16);
825: cksum = ~temp32;
826: if (cksum == 0) {
827: m->m_pkthdr.csum_flags |=
828: M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK;
829: }
830: }
831:
832: /*
833: * Receive interrupt.
834: */
835: int
836: hme_rint(sc)
837: struct hme_softc *sc;
838: {
839: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
840: struct mbuf *m;
841: struct hme_sxd *sd;
842: unsigned int ri, len;
843: u_int32_t flags;
844:
845: ri = sc->sc_last_rd;
846: sd = &sc->sc_rxd[ri];
847:
848: /*
849: * Process all buffers with valid data.
850: */
851: for (;;) {
852: flags = HME_XD_GETFLAGS(sc->sc_pci, sc->sc_rb.rb_rxd, ri);
853: if (flags & HME_XD_OWN)
854: break;
855:
856: if (flags & HME_XD_OFL) {
857: printf("%s: buffer overflow, ri=%d; flags=0x%x\n",
858: sc->sc_dev.dv_xname, ri, flags);
859: goto again;
860: }
861:
862: m = sd->sd_mbuf;
863: len = HME_XD_DECODE_RSIZE(flags);
864: m->m_pkthdr.len = m->m_len = len;
865:
866: if (hme_newbuf(sc, sd, 0)) {
867: /*
868: * Allocation of new mbuf cluster failed, leave the
869: * old one in place and keep going.
870: */
871: ifp->if_ierrors++;
872: goto again;
873: }
874:
875: ifp->if_ipackets++;
876: hme_rxcksum(m, flags);
877:
878: #if NBPFILTER > 0
879: if (ifp->if_bpf)
880: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
881: #endif
882:
883: ether_input_mbuf(ifp, m);
884:
885: again:
886: HME_XD_SETADDR(sc->sc_pci, sc->sc_rb.rb_rxd, ri,
887: sd->sd_map->dm_segs[0].ds_addr);
888: HME_XD_SETFLAGS(sc->sc_pci, sc->sc_rb.rb_rxd, ri,
889: HME_XD_OWN | HME_XD_ENCODE_RSIZE(HME_RX_PKTSIZE));
890:
891: if (++ri == HME_RX_RING_SIZE) {
892: ri = 0;
893: sd = sc->sc_rxd;
894: } else
895: sd++;
896: }
897:
898: sc->sc_last_rd = ri;
899: return (1);
900: }
901:
902: int
903: hme_eint(sc, status)
904: struct hme_softc *sc;
905: u_int status;
906: {
907: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
908:
909: if (status & HME_SEB_STAT_MIFIRQ) {
910: printf("%s: XXXlink status changed\n", sc->sc_dev.dv_xname);
911: status &= ~HME_SEB_STAT_MIFIRQ;
912: }
913:
914: if (status & HME_SEB_STAT_DTIMEXP) {
915: ifp->if_oerrors++;
916: status &= ~HME_SEB_STAT_DTIMEXP;
917: }
918:
919: if (status & HME_SEB_STAT_NORXD) {
920: ifp->if_ierrors++;
921: status &= ~HME_SEB_STAT_NORXD;
922: }
923:
924: status &= ~(HME_SEB_STAT_RXTOHOST | HME_SEB_STAT_GOTFRAME |
925: HME_SEB_STAT_SENTFRAME | HME_SEB_STAT_HOSTTOTX |
926: HME_SEB_STAT_TXALL);
927:
928: if (status == 0)
929: return (1);
930:
931: #ifdef HME_DEBUG
932: printf("%s: status=%b\n", sc->sc_dev.dv_xname, status, HME_SEB_STAT_BITS);
933: #endif
934: return (1);
935: }
936:
937: int
938: hme_intr(v)
939: void *v;
940: {
941: struct hme_softc *sc = (struct hme_softc *)v;
942: bus_space_tag_t t = sc->sc_bustag;
943: bus_space_handle_t seb = sc->sc_seb;
944: u_int32_t status;
945: int r = 0;
946:
947: status = bus_space_read_4(t, seb, HME_SEBI_STAT);
948:
949: if ((status & HME_SEB_STAT_ALL_ERRORS) != 0)
950: r |= hme_eint(sc, status);
951:
952: if ((status & (HME_SEB_STAT_TXALL | HME_SEB_STAT_HOSTTOTX)) != 0)
953: r |= hme_tint(sc);
954:
955: if ((status & HME_SEB_STAT_RXTOHOST) != 0)
956: r |= hme_rint(sc);
957:
958: return (r);
959: }
960:
961:
962: void
963: hme_watchdog(ifp)
964: struct ifnet *ifp;
965: {
966: struct hme_softc *sc = ifp->if_softc;
967:
968: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
969: ifp->if_oerrors++;
970:
971: hme_reset(sc);
972: }
973:
974: /*
975: * Initialize the MII Management Interface
976: */
977: void
978: hme_mifinit(sc)
979: struct hme_softc *sc;
980: {
981: bus_space_tag_t t = sc->sc_bustag;
982: bus_space_handle_t mif = sc->sc_mif;
983: bus_space_handle_t mac = sc->sc_mac;
984: int phy;
985: u_int32_t v;
986:
987: v = bus_space_read_4(t, mif, HME_MIFI_CFG);
988: phy = HME_PHYAD_EXTERNAL;
989: if (v & HME_MIF_CFG_MDI1)
990: phy = sc->sc_tcvr = HME_PHYAD_EXTERNAL;
991: else if (v & HME_MIF_CFG_MDI0)
992: phy = sc->sc_tcvr = HME_PHYAD_INTERNAL;
993: else
994: sc->sc_tcvr = -1;
995:
996: /* Configure the MIF in frame mode, no poll, current phy select */
997: v = 0;
998: if (phy == HME_PHYAD_EXTERNAL)
999: v |= HME_MIF_CFG_PHY;
1000: bus_space_write_4(t, mif, HME_MIFI_CFG, v);
1001:
1002: /* If an external transceiver is selected, enable its MII drivers */
1003: v = bus_space_read_4(t, mac, HME_MACI_XIF);
1004: v &= ~HME_MAC_XIF_MIIENABLE;
1005: if (phy == HME_PHYAD_EXTERNAL)
1006: v |= HME_MAC_XIF_MIIENABLE;
1007: bus_space_write_4(t, mac, HME_MACI_XIF, v);
1008: }
1009:
1010: /*
1011: * MII interface
1012: */
1013: static int
1014: hme_mii_readreg(self, phy, reg)
1015: struct device *self;
1016: int phy, reg;
1017: {
1018: struct hme_softc *sc = (struct hme_softc *)self;
1019: bus_space_tag_t t = sc->sc_bustag;
1020: bus_space_handle_t mif = sc->sc_mif;
1021: bus_space_handle_t mac = sc->sc_mac;
1022: u_int32_t v, xif_cfg, mifi_cfg;
1023: int n;
1024:
1025: if (phy != HME_PHYAD_EXTERNAL && phy != HME_PHYAD_INTERNAL)
1026: return (0);
1027:
1028: /* Select the desired PHY in the MIF configuration register */
1029: v = mifi_cfg = bus_space_read_4(t, mif, HME_MIFI_CFG);
1030: v &= ~HME_MIF_CFG_PHY;
1031: if (phy == HME_PHYAD_EXTERNAL)
1032: v |= HME_MIF_CFG_PHY;
1033: bus_space_write_4(t, mif, HME_MIFI_CFG, v);
1034:
1035: /* Enable MII drivers on external transceiver */
1036: v = xif_cfg = bus_space_read_4(t, mac, HME_MACI_XIF);
1037: if (phy == HME_PHYAD_EXTERNAL)
1038: v |= HME_MAC_XIF_MIIENABLE;
1039: else
1040: v &= ~HME_MAC_XIF_MIIENABLE;
1041: bus_space_write_4(t, mac, HME_MACI_XIF, v);
1042:
1043: /* Construct the frame command */
1044: v = (MII_COMMAND_START << HME_MIF_FO_ST_SHIFT) |
1045: HME_MIF_FO_TAMSB |
1046: (MII_COMMAND_READ << HME_MIF_FO_OPC_SHIFT) |
1047: (phy << HME_MIF_FO_PHYAD_SHIFT) |
1048: (reg << HME_MIF_FO_REGAD_SHIFT);
1049:
1050: bus_space_write_4(t, mif, HME_MIFI_FO, v);
1051: for (n = 0; n < 100; n++) {
1052: DELAY(1);
1053: v = bus_space_read_4(t, mif, HME_MIFI_FO);
1054: if (v & HME_MIF_FO_TALSB) {
1055: v &= HME_MIF_FO_DATA;
1056: goto out;
1057: }
1058: }
1059:
1060: v = 0;
1061: printf("%s: mii_read timeout\n", sc->sc_dev.dv_xname);
1062:
1063: out:
1064: /* Restore MIFI_CFG register */
1065: bus_space_write_4(t, mif, HME_MIFI_CFG, mifi_cfg);
1066: /* Restore XIF register */
1067: bus_space_write_4(t, mac, HME_MACI_XIF, xif_cfg);
1068: return (v);
1069: }
1070:
1071: static void
1072: hme_mii_writereg(self, phy, reg, val)
1073: struct device *self;
1074: int phy, reg, val;
1075: {
1076: struct hme_softc *sc = (void *)self;
1077: bus_space_tag_t t = sc->sc_bustag;
1078: bus_space_handle_t mif = sc->sc_mif;
1079: bus_space_handle_t mac = sc->sc_mac;
1080: u_int32_t v, xif_cfg, mifi_cfg;
1081: int n;
1082:
1083: /* We can at most have two PHYs */
1084: if (phy != HME_PHYAD_EXTERNAL && phy != HME_PHYAD_INTERNAL)
1085: return;
1086:
1087: /* Select the desired PHY in the MIF configuration register */
1088: v = mifi_cfg = bus_space_read_4(t, mif, HME_MIFI_CFG);
1089: v &= ~HME_MIF_CFG_PHY;
1090: if (phy == HME_PHYAD_EXTERNAL)
1091: v |= HME_MIF_CFG_PHY;
1092: bus_space_write_4(t, mif, HME_MIFI_CFG, v);
1093:
1094: /* Enable MII drivers on external transceiver */
1095: v = xif_cfg = bus_space_read_4(t, mac, HME_MACI_XIF);
1096: if (phy == HME_PHYAD_EXTERNAL)
1097: v |= HME_MAC_XIF_MIIENABLE;
1098: else
1099: v &= ~HME_MAC_XIF_MIIENABLE;
1100: bus_space_write_4(t, mac, HME_MACI_XIF, v);
1101:
1102: /* Construct the frame command */
1103: v = (MII_COMMAND_START << HME_MIF_FO_ST_SHIFT) |
1104: HME_MIF_FO_TAMSB |
1105: (MII_COMMAND_WRITE << HME_MIF_FO_OPC_SHIFT) |
1106: (phy << HME_MIF_FO_PHYAD_SHIFT) |
1107: (reg << HME_MIF_FO_REGAD_SHIFT) |
1108: (val & HME_MIF_FO_DATA);
1109:
1110: bus_space_write_4(t, mif, HME_MIFI_FO, v);
1111: for (n = 0; n < 100; n++) {
1112: DELAY(1);
1113: v = bus_space_read_4(t, mif, HME_MIFI_FO);
1114: if (v & HME_MIF_FO_TALSB)
1115: goto out;
1116: }
1117:
1118: printf("%s: mii_write timeout\n", sc->sc_dev.dv_xname);
1119: out:
1120: /* Restore MIFI_CFG register */
1121: bus_space_write_4(t, mif, HME_MIFI_CFG, mifi_cfg);
1122: /* Restore XIF register */
1123: bus_space_write_4(t, mac, HME_MACI_XIF, xif_cfg);
1124: }
1125:
1126: static void
1127: hme_mii_statchg(dev)
1128: struct device *dev;
1129: {
1130: struct hme_softc *sc = (void *)dev;
1131: bus_space_tag_t t = sc->sc_bustag;
1132: bus_space_handle_t mac = sc->sc_mac;
1133: u_int32_t v;
1134:
1135: #ifdef HMEDEBUG
1136: if (sc->sc_debug)
1137: printf("hme_mii_statchg: status change\n", phy);
1138: #endif
1139:
1140: /* Set the MAC Full Duplex bit appropriately */
1141: /* Apparently the hme chip is SIMPLEX if working in full duplex mode,
1142: but not otherwise. */
1143: v = bus_space_read_4(t, mac, HME_MACI_TXCFG);
1144: if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) {
1145: v |= HME_MAC_TXCFG_FULLDPLX;
1146: sc->sc_arpcom.ac_if.if_flags |= IFF_SIMPLEX;
1147: } else {
1148: v &= ~HME_MAC_TXCFG_FULLDPLX;
1149: sc->sc_arpcom.ac_if.if_flags &= ~IFF_SIMPLEX;
1150: }
1151: sc->sc_if_flags = sc->sc_arpcom.ac_if.if_flags;
1152: bus_space_write_4(t, mac, HME_MACI_TXCFG, v);
1153: }
1154:
1155: int
1156: hme_mediachange(ifp)
1157: struct ifnet *ifp;
1158: {
1159: struct hme_softc *sc = ifp->if_softc;
1160: bus_space_tag_t t = sc->sc_bustag;
1161: bus_space_handle_t mif = sc->sc_mif;
1162: bus_space_handle_t mac = sc->sc_mac;
1163: int instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
1164: int phy = sc->sc_phys[instance];
1165: u_int32_t v;
1166:
1167: #ifdef HMEDEBUG
1168: if (sc->sc_debug)
1169: printf("hme_mediachange: phy = %d\n", phy);
1170: #endif
1171: if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER)
1172: return (EINVAL);
1173:
1174: /* Select the current PHY in the MIF configuration register */
1175: v = bus_space_read_4(t, mif, HME_MIFI_CFG);
1176: v &= ~HME_MIF_CFG_PHY;
1177: if (phy == HME_PHYAD_EXTERNAL)
1178: v |= HME_MIF_CFG_PHY;
1179: bus_space_write_4(t, mif, HME_MIFI_CFG, v);
1180:
1181: /* If an external transceiver is selected, enable its MII drivers */
1182: v = bus_space_read_4(t, mac, HME_MACI_XIF);
1183: v &= ~HME_MAC_XIF_MIIENABLE;
1184: if (phy == HME_PHYAD_EXTERNAL)
1185: v |= HME_MAC_XIF_MIIENABLE;
1186: bus_space_write_4(t, mac, HME_MACI_XIF, v);
1187:
1188: return (mii_mediachg(&sc->sc_mii));
1189: }
1190:
1191: void
1192: hme_mediastatus(ifp, ifmr)
1193: struct ifnet *ifp;
1194: struct ifmediareq *ifmr;
1195: {
1196: struct hme_softc *sc = ifp->if_softc;
1197:
1198: if ((ifp->if_flags & IFF_UP) == 0)
1199: return;
1200:
1201: mii_pollstat(&sc->sc_mii);
1202: ifmr->ifm_active = sc->sc_mii.mii_media_active;
1203: ifmr->ifm_status = sc->sc_mii.mii_media_status;
1204: }
1205:
1206: /*
1207: * Process an ioctl request.
1208: */
1209: int
1210: hme_ioctl(ifp, cmd, data)
1211: struct ifnet *ifp;
1212: u_long cmd;
1213: caddr_t data;
1214: {
1215: struct hme_softc *sc = ifp->if_softc;
1216: struct ifaddr *ifa = (struct ifaddr *)data;
1217: struct ifreq *ifr = (struct ifreq *)data;
1218: int s, error = 0;
1219:
1220: s = splnet();
1221:
1222: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
1223: splx(s);
1224: return (error);
1225: }
1226:
1227: switch (cmd) {
1228:
1229: case SIOCSIFADDR:
1230: switch (ifa->ifa_addr->sa_family) {
1231: #ifdef INET
1232: case AF_INET:
1233: if (ifp->if_flags & IFF_UP)
1234: hme_setladrf(sc);
1235: else {
1236: ifp->if_flags |= IFF_UP;
1237: hme_init(sc);
1238: }
1239: arp_ifinit(&sc->sc_arpcom, ifa);
1240: break;
1241: #endif
1242: default:
1243: hme_init(sc);
1244: break;
1245: }
1246: break;
1247:
1248: case SIOCSIFFLAGS:
1249: if ((ifp->if_flags & IFF_UP) == 0 &&
1250: (ifp->if_flags & IFF_RUNNING) != 0) {
1251: /*
1252: * If interface is marked down and it is running, then
1253: * stop it.
1254: */
1255: hme_stop(sc);
1256: ifp->if_flags &= ~IFF_RUNNING;
1257: } else if ((ifp->if_flags & IFF_UP) != 0 &&
1258: (ifp->if_flags & IFF_RUNNING) == 0) {
1259: /*
1260: * If interface is marked up and it is stopped, then
1261: * start it.
1262: */
1263: hme_init(sc);
1264: } else if ((ifp->if_flags & IFF_UP) != 0) {
1265: /*
1266: * If setting debug or promiscuous mode, do not reset
1267: * the chip; for everything else, call hme_init()
1268: * which will trigger a reset.
1269: */
1270: #define RESETIGN (IFF_CANTCHANGE | IFF_DEBUG)
1271: if (ifp->if_flags == sc->sc_if_flags)
1272: break;
1273: if ((ifp->if_flags & (~RESETIGN))
1274: == (sc->sc_if_flags & (~RESETIGN)))
1275: hme_setladrf(sc);
1276: else
1277: hme_init(sc);
1278: #undef RESETIGN
1279: }
1280: #ifdef HMEDEBUG
1281: sc->sc_debug = (ifp->if_flags & IFF_DEBUG) != 0 ? 1 : 0;
1282: #endif
1283: break;
1284:
1285: case SIOCADDMULTI:
1286: case SIOCDELMULTI:
1287: error = (cmd == SIOCADDMULTI) ?
1288: ether_addmulti(ifr, &sc->sc_arpcom) :
1289: ether_delmulti(ifr, &sc->sc_arpcom);
1290:
1291: if (error == ENETRESET) {
1292: /*
1293: * Multicast list has changed; set the hardware filter
1294: * accordingly.
1295: */
1296: if (ifp->if_flags & IFF_RUNNING)
1297: hme_setladrf(sc);
1298: error = 0;
1299: }
1300: break;
1301:
1302: case SIOCGIFMEDIA:
1303: case SIOCSIFMEDIA:
1304: error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1305: break;
1306:
1307: default:
1308: error = ENOTTY;
1309: break;
1310: }
1311:
1312: sc->sc_if_flags = ifp->if_flags;
1313: splx(s);
1314: return (error);
1315: }
1316:
1317: void
1318: hme_shutdown(arg)
1319: void *arg;
1320: {
1321: hme_stop((struct hme_softc *)arg);
1322: }
1323:
1324: /*
1325: * Set up the logical address filter.
1326: */
1327: void
1328: hme_setladrf(sc)
1329: struct hme_softc *sc;
1330: {
1331: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1332: struct ether_multi *enm;
1333: struct ether_multistep step;
1334: struct arpcom *ac = &sc->sc_arpcom;
1335: bus_space_tag_t t = sc->sc_bustag;
1336: bus_space_handle_t mac = sc->sc_mac;
1337: u_int32_t hash[4];
1338: u_int32_t v, crc;
1339:
1340: /* Clear hash table */
1341: hash[3] = hash[2] = hash[1] = hash[0] = 0;
1342:
1343: /* Get current RX configuration */
1344: v = bus_space_read_4(t, mac, HME_MACI_RXCFG);
1345:
1346: if ((ifp->if_flags & IFF_PROMISC) != 0) {
1347: /* Turn on promiscuous mode; turn off the hash filter */
1348: v |= HME_MAC_RXCFG_PMISC;
1349: v &= ~HME_MAC_RXCFG_HENABLE;
1350: ifp->if_flags |= IFF_ALLMULTI;
1351: goto chipit;
1352: }
1353:
1354: /* Turn off promiscuous mode; turn on the hash filter */
1355: v &= ~HME_MAC_RXCFG_PMISC;
1356: v |= HME_MAC_RXCFG_HENABLE;
1357:
1358: /*
1359: * Set up multicast address filter by passing all multicast addresses
1360: * through a crc generator, and then using the high order 6 bits as an
1361: * index into the 64 bit logical address filter. The high order bit
1362: * selects the word, while the rest of the bits select the bit within
1363: * the word.
1364: */
1365:
1366: ETHER_FIRST_MULTI(step, ac, enm);
1367: while (enm != NULL) {
1368: if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1369: /*
1370: * We must listen to a range of multicast addresses.
1371: * For now, just accept all multicasts, rather than
1372: * trying to set only those filter bits needed to match
1373: * the range. (At this time, the only use of address
1374: * ranges is for IP multicast routing, for which the
1375: * range is big enough to require all bits set.)
1376: */
1377: hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
1378: ifp->if_flags |= IFF_ALLMULTI;
1379: goto chipit;
1380: }
1381:
1382: crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN)>> 26;
1383:
1384: /* Set the corresponding bit in the filter. */
1385: hash[crc >> 4] |= 1 << (crc & 0xf);
1386:
1387: ETHER_NEXT_MULTI(step, enm);
1388: }
1389:
1390: ifp->if_flags &= ~IFF_ALLMULTI;
1391:
1392: chipit:
1393: /* Now load the hash table into the chip */
1394: bus_space_write_4(t, mac, HME_MACI_HASHTAB0, hash[0]);
1395: bus_space_write_4(t, mac, HME_MACI_HASHTAB1, hash[1]);
1396: bus_space_write_4(t, mac, HME_MACI_HASHTAB2, hash[2]);
1397: bus_space_write_4(t, mac, HME_MACI_HASHTAB3, hash[3]);
1398: bus_space_write_4(t, mac, HME_MACI_RXCFG, v);
1399: }
1400:
1401: int
1402: hme_encap(sc, mhead, bixp)
1403: struct hme_softc *sc;
1404: struct mbuf *mhead;
1405: int *bixp;
1406: {
1407: struct hme_sxd *sd;
1408: struct mbuf *m;
1409: int frag, cur, cnt = 0;
1410: u_int32_t flags;
1411: struct hme_ring *hr = &sc->sc_rb;
1412:
1413: cur = frag = *bixp;
1414: sd = &sc->sc_txd[frag];
1415:
1416: for (m = mhead; m != NULL; m = m->m_next) {
1417: if (m->m_len == 0)
1418: continue;
1419:
1420: if ((HME_TX_RING_SIZE - (sc->sc_tx_cnt + cnt)) < 5)
1421: goto err;
1422:
1423: if (bus_dmamap_load(sc->sc_dmatag, sd->sd_map,
1424: mtod(m, caddr_t), m->m_len, NULL, BUS_DMA_NOWAIT) != 0)
1425: goto err;
1426:
1427: sd->sd_loaded = 1;
1428: bus_dmamap_sync(sc->sc_dmatag, sd->sd_map, 0,
1429: sd->sd_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
1430:
1431: sd->sd_mbuf = NULL;
1432:
1433: flags = HME_XD_ENCODE_TSIZE(m->m_len);
1434: if (cnt == 0)
1435: flags |= HME_XD_SOP;
1436: else
1437: flags |= HME_XD_OWN;
1438:
1439: HME_XD_SETADDR(sc->sc_pci, hr->rb_txd, frag,
1440: sd->sd_map->dm_segs[0].ds_addr);
1441: HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, frag, flags);
1442:
1443: cur = frag;
1444: cnt++;
1445: if (++frag == HME_TX_RING_SIZE) {
1446: frag = 0;
1447: sd = sc->sc_txd;
1448: } else
1449: sd++;
1450: }
1451:
1452: /* Set end of packet on last descriptor. */
1453: flags = HME_XD_GETFLAGS(sc->sc_pci, hr->rb_txd, cur);
1454: flags |= HME_XD_EOP;
1455: HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, cur, flags);
1456: sc->sc_txd[cur].sd_mbuf = mhead;
1457:
1458: /* Give first frame over to the hardware. */
1459: flags = HME_XD_GETFLAGS(sc->sc_pci, hr->rb_txd, (*bixp));
1460: flags |= HME_XD_OWN;
1461: HME_XD_SETFLAGS(sc->sc_pci, hr->rb_txd, (*bixp), flags);
1462:
1463: sc->sc_tx_cnt += cnt;
1464: *bixp = frag;
1465:
1466: /* sync descriptors */
1467:
1468: return (0);
1469:
1470: err:
1471: /*
1472: * Invalidate the stuff we may have already put into place. We
1473: * will be called again to queue it later.
1474: */
1475: for (; cnt > 0; cnt--) {
1476: if (--frag == -1)
1477: frag = HME_TX_RING_SIZE - 1;
1478: sd = &sc->sc_txd[frag];
1479: bus_dmamap_sync(sc->sc_dmatag, sd->sd_map, 0,
1480: sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1481: bus_dmamap_unload(sc->sc_dmatag, sd->sd_map);
1482: sd->sd_loaded = 0;
1483: sd->sd_mbuf = NULL;
1484: }
1485: return (ENOBUFS);
1486: }
1487:
1488: int
1489: hme_newbuf(sc, d, freeit)
1490: struct hme_softc *sc;
1491: struct hme_sxd *d;
1492: int freeit;
1493: {
1494: struct mbuf *m;
1495: bus_dmamap_t map;
1496:
1497: /*
1498: * All operations should be on local variables and/or rx spare map
1499: * until we're sure everything is a success.
1500: */
1501:
1502: MGETHDR(m, M_DONTWAIT, MT_DATA);
1503: if (m == NULL)
1504: return (ENOBUFS);
1505: m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if;
1506:
1507: MCLGET(m, M_DONTWAIT);
1508: if ((m->m_flags & M_EXT) == 0) {
1509: m_freem(m);
1510: return (ENOBUFS);
1511: }
1512:
1513: if (bus_dmamap_load(sc->sc_dmatag, sc->sc_rxmap_spare,
1514: mtod(m, caddr_t), MCLBYTES - HME_RX_OFFSET, NULL,
1515: BUS_DMA_NOWAIT) != 0) {
1516: m_freem(m);
1517: return (ENOBUFS);
1518: }
1519:
1520: /*
1521: * At this point we have a new buffer loaded into the spare map.
1522: * Just need to clear out the old mbuf/map and put the new one
1523: * in place.
1524: */
1525:
1526: if (d->sd_loaded) {
1527: bus_dmamap_sync(sc->sc_dmatag, d->sd_map,
1528: 0, d->sd_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1529: bus_dmamap_unload(sc->sc_dmatag, d->sd_map);
1530: d->sd_loaded = 0;
1531: }
1532:
1533: if ((d->sd_mbuf != NULL) && freeit) {
1534: m_freem(d->sd_mbuf);
1535: d->sd_mbuf = NULL;
1536: }
1537:
1538: map = d->sd_map;
1539: d->sd_map = sc->sc_rxmap_spare;
1540: sc->sc_rxmap_spare = map;
1541:
1542: d->sd_loaded = 1;
1543:
1544: bus_dmamap_sync(sc->sc_dmatag, d->sd_map, 0, d->sd_map->dm_mapsize,
1545: BUS_DMASYNC_PREREAD);
1546:
1547: m->m_data += HME_RX_OFFSET;
1548: d->sd_mbuf = m;
1549: return (0);
1550: }
CVSweb