Annotation of sys/dev/pci/if_cas.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_cas.c,v 1.8 2007/04/18 21:08:35 kettenis Exp $ */
2:
3: /*
4: *
5: * Copyright (C) 2007 Mark Kettenis.
6: * Copyright (C) 2001 Eduardo Horvath.
7: * All rights reserved.
8: *
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: *
31: */
32:
33: /*
34: * Driver for Sun Cassini ethernet controllers.
35: */
36:
37: #include "bpfilter.h"
38:
39: #include <sys/param.h>
40: #include <sys/systm.h>
41: #include <sys/timeout.h>
42: #include <sys/mbuf.h>
43: #include <sys/syslog.h>
44: #include <sys/malloc.h>
45: #include <sys/kernel.h>
46: #include <sys/socket.h>
47: #include <sys/ioctl.h>
48: #include <sys/errno.h>
49: #include <sys/device.h>
50:
51: #include <machine/endian.h>
52:
53: #include <net/if.h>
54: #include <net/if_dl.h>
55: #include <net/if_media.h>
56:
57: #ifdef INET
58: #include <netinet/in.h>
59: #include <netinet/if_ether.h>
60: #endif
61:
62: #if NBPFILTER > 0
63: #include <net/bpf.h>
64: #endif
65:
66: #include <machine/bus.h>
67: #include <machine/intr.h>
68:
69: #include <dev/mii/mii.h>
70: #include <dev/mii/miivar.h>
71: #include <dev/mii/mii_bitbang.h>
72:
73: #include <dev/pci/if_casreg.h>
74: #include <dev/pci/if_casvar.h>
75:
76: #include <dev/pci/pcivar.h>
77: #include <dev/pci/pcireg.h>
78: #include <dev/pci/pcidevs.h>
79:
80: #ifdef __sparc64__
81: #include <dev/ofw/openfirm.h>
82: #endif
83:
84: #define TRIES 10000
85:
86: struct cfdriver cas_cd = {
87: NULL, "cas", DV_IFNET
88: };
89:
90: int cas_match(struct device *, void *, void *);
91: void cas_attach(struct device *, struct device *, void *);
92: int cas_pci_enaddr(struct cas_softc *, struct pci_attach_args *);
93:
94: struct cfattach cas_ca = {
95: sizeof(struct cas_softc), cas_match, cas_attach
96: };
97:
98: void cas_config(struct cas_softc *);
99: void cas_start(struct ifnet *);
100: void cas_stop(struct ifnet *, int);
101: int cas_ioctl(struct ifnet *, u_long, caddr_t);
102: void cas_tick(void *);
103: void cas_watchdog(struct ifnet *);
104: void cas_shutdown(void *);
105: int cas_init(struct ifnet *);
106: void cas_init_regs(struct cas_softc *);
107: int cas_ringsize(int);
108: int cas_cringsize(int);
109: int cas_meminit(struct cas_softc *);
110: void cas_mifinit(struct cas_softc *);
111: int cas_bitwait(struct cas_softc *, bus_space_handle_t, int,
112: u_int32_t, u_int32_t);
113: void cas_reset(struct cas_softc *);
114: int cas_reset_rx(struct cas_softc *);
115: int cas_reset_tx(struct cas_softc *);
116: int cas_disable_rx(struct cas_softc *);
117: int cas_disable_tx(struct cas_softc *);
118: void cas_rxdrain(struct cas_softc *);
119: int cas_add_rxbuf(struct cas_softc *, int idx);
120: void cas_setladrf(struct cas_softc *);
121: int cas_encap(struct cas_softc *, struct mbuf *, u_int32_t *);
122:
123: /* MII methods & callbacks */
124: int cas_mii_readreg(struct device *, int, int);
125: void cas_mii_writereg(struct device *, int, int, int);
126: void cas_mii_statchg(struct device *);
127: int cas_pcs_readreg(struct device *, int, int);
128: void cas_pcs_writereg(struct device *, int, int, int);
129:
130: int cas_mediachange(struct ifnet *);
131: void cas_mediastatus(struct ifnet *, struct ifmediareq *);
132:
133: int cas_eint(struct cas_softc *, u_int);
134: int cas_rint(struct cas_softc *);
135: int cas_tint(struct cas_softc *, u_int32_t);
136: int cas_pint(struct cas_softc *);
137: int cas_intr(void *);
138:
139: #ifdef CAS_DEBUG
140: #define DPRINTF(sc, x) if ((sc)->sc_arpcom.ac_if.if_flags & IFF_DEBUG) \
141: printf x
142: #else
143: #define DPRINTF(sc, x) /* nothing */
144: #endif
145:
146: const struct pci_matchid cas_pci_devices[] = {
147: { PCI_VENDOR_SUN, PCI_PRODUCT_SUN_CASSINI }
148: };
149:
150: int
151: cas_match(struct device *parent, void *cf, void *aux)
152: {
153: return (pci_matchbyid((struct pci_attach_args *)aux, cas_pci_devices,
154: sizeof(cas_pci_devices)/sizeof(cas_pci_devices[0])));
155: }
156:
157: #define PROMHDR_PTR_DATA 0x18
158: #define PROMDATA_PTR_VPD 0x08
159: #define PROMDATA_DATA2 0x0a
160:
161: static const u_int8_t cas_promhdr[] = { 0x55, 0xaa };
162: static const u_int8_t cas_promdat[] = {
163: 'P', 'C', 'I', 'R',
164: PCI_VENDOR_SUN & 0xff, PCI_VENDOR_SUN >> 8,
165: PCI_PRODUCT_SUN_CASSINI & 0xff, PCI_PRODUCT_SUN_CASSINI >> 8
166: };
167:
168: static const u_int8_t cas_promdat2[] = {
169: 0x18, 0x00, /* structure length */
170: 0x00, /* structure revision */
171: 0x00, /* interface revision */
172: PCI_SUBCLASS_NETWORK_ETHERNET, /* subclass code */
173: PCI_CLASS_NETWORK /* class code */
174: };
175:
176: int
177: cas_pci_enaddr(struct cas_softc *sc, struct pci_attach_args *pa)
178: {
179: struct pci_vpd_largeres *res;
180: struct pci_vpd *vpd;
181: bus_space_handle_t romh;
182: bus_space_tag_t romt;
183: bus_size_t romsize;
184: u_int8_t buf[32], *desc;
185: pcireg_t address, mask;
186: int dataoff, vpdoff, len;
187: int rv = -1;
188:
189: address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
190: pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, 0xfffffffe);
191: mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
192: address |= PCI_ROM_ENABLE;
193: pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address);
194:
195: romt = pa->pa_memt;
196: romsize = PCI_ROM_SIZE(mask);
197: if (bus_space_map(romt, PCI_ROM_ADDR(address), romsize, 0, &romh)) {
198: romsize = 0;
199: goto fail;
200: }
201:
202: bus_space_read_region_1(romt, romh, 0, buf, sizeof(buf));
203: if (bcmp(buf, cas_promhdr, sizeof(cas_promhdr)))
204: goto fail;
205:
206: dataoff = buf[PROMHDR_PTR_DATA] | (buf[PROMHDR_PTR_DATA + 1] << 8);
207: if (dataoff < 0x1c)
208: goto fail;
209:
210: bus_space_read_region_1(romt, romh, dataoff, buf, sizeof(buf));
211: if (bcmp(buf, cas_promdat, sizeof(cas_promdat)) ||
212: bcmp(buf + PROMDATA_DATA2, cas_promdat2, sizeof(cas_promdat2)))
213: goto fail;
214:
215: vpdoff = buf[PROMDATA_PTR_VPD] | (buf[PROMDATA_PTR_VPD + 1] << 8);
216: if (vpdoff < 0x1c)
217: goto fail;
218:
219: next:
220: bus_space_read_region_1(romt, romh, vpdoff, buf, sizeof(buf));
221: if (!PCI_VPDRES_ISLARGE(buf[0]))
222: goto fail;
223:
224: res = (struct pci_vpd_largeres *)buf;
225: vpdoff += sizeof(*res);
226:
227: len = ((res->vpdres_len_msb << 8) + res->vpdres_len_lsb);
228: switch(PCI_VPDRES_LARGE_NAME(res->vpdres_byte0)) {
229: case PCI_VPDRES_TYPE_IDENTIFIER_STRING:
230: /* Skip identifier string. */
231: vpdoff += len;
232: goto next;
233:
234: case PCI_VPDRES_TYPE_VPD:
235: while (len > 0) {
236: bus_space_read_region_1(romt, romh, vpdoff,
237: buf, sizeof(buf));
238:
239: vpd = (struct pci_vpd *)buf;
240: vpdoff += sizeof(*vpd) + vpd->vpd_len;
241: len -= sizeof(*vpd) + vpd->vpd_len;
242:
243: /*
244: * We're looking for an "Enhanced" VPD...
245: */
246: if (vpd->vpd_key0 != 'Z')
247: continue;
248:
249: desc = buf + sizeof(*vpd);
250:
251: /*
252: * ...which is an instance property...
253: */
254: if (desc[0] != 'I')
255: continue;
256: desc += 3;
257:
258: /*
259: * ...that's a byte array with the proper
260: * length for a MAC address...
261: */
262: if (desc[0] != 'B' || desc[1] != ETHER_ADDR_LEN)
263: continue;
264: desc += 2;
265:
266: /*
267: * ...named "local-mac-address".
268: */
269: if (strcmp(desc, "local-mac-address") != 0)
270: continue;
271: desc += strlen("local-mac-address") + 1;
272:
273: bcopy(desc, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
274: rv = 0;
275: }
276: break;
277:
278: default:
279: goto fail;
280: }
281:
282: fail:
283: if (romsize != 0)
284: bus_space_unmap(romt, romh, romsize);
285:
286: address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
287: address &= ~PCI_ROM_ENABLE;
288: pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address);
289:
290: return (rv);
291: }
292:
293: void
294: cas_attach(struct device *parent, struct device *self, void *aux)
295: {
296: struct pci_attach_args *pa = aux;
297: struct cas_softc *sc = (void *)self;
298: pci_intr_handle_t ih;
299: #ifdef __sparc64__
300: /* XXX the following declarations should be elsewhere */
301: extern void myetheraddr(u_char *);
302: #endif
303: const char *intrstr = NULL;
304: bus_size_t size;
305: int gotenaddr = 0;
306:
307: sc->sc_dmatag = pa->pa_dmat;
308:
309: #define PCI_CAS_BASEADDR 0x10
310: if (pci_mapreg_map(pa, PCI_CAS_BASEADDR, PCI_MAPREG_TYPE_MEM, 0,
311: &sc->sc_memt, &sc->sc_memh, NULL, &size, 0) != 0) {
312: printf(": could not map registers\n");
313: return;
314: }
315:
316: if (cas_pci_enaddr(sc, pa) == 0)
317: gotenaddr = 1;
318:
319: #ifdef __sparc64__
320: if (!gotenaddr) {
321: if (OF_getprop(PCITAG_NODE(pa->pa_tag), "local-mac-address",
322: sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN) <= 0)
323: myetheraddr(sc->sc_arpcom.ac_enaddr);
324: gotenaddr = 1;
325: }
326: #endif
327: #ifdef __powerpc__
328: if (!gotenaddr) {
329: pci_ether_hw_addr(pa->pa_pc, sc->sc_arpcom.ac_enaddr);
330: gotenaddr = 1;
331: }
332: #endif
333:
334: sc->sc_burst = 16; /* XXX */
335:
336: if (pci_intr_map(pa, &ih) != 0) {
337: printf(": couldn't map interrupt\n");
338: bus_space_unmap(sc->sc_memt, sc->sc_memh, size);
339: return;
340: }
341: intrstr = pci_intr_string(pa->pa_pc, ih);
342: sc->sc_ih = pci_intr_establish(pa->pa_pc,
343: ih, IPL_NET, cas_intr, sc, self->dv_xname);
344: if (sc->sc_ih == NULL) {
345: printf(": couldn't establish interrupt");
346: if (intrstr != NULL)
347: printf(" at %s", intrstr);
348: printf("\n");
349: bus_space_unmap(sc->sc_memt, sc->sc_memh, size);
350: return;
351: }
352:
353: printf(": %s", intrstr);
354:
355: /*
356: * call the main configure
357: */
358: cas_config(sc);
359: }
360:
361: /*
362: * cas_config:
363: *
364: * Attach a Cassini interface to the system.
365: */
366: void
367: cas_config(struct cas_softc *sc)
368: {
369: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
370: struct mii_data *mii = &sc->sc_mii;
371: struct mii_softc *child;
372: int i, error;
373:
374: /* Make sure the chip is stopped. */
375: ifp->if_softc = sc;
376: cas_reset(sc);
377:
378: /*
379: * Allocate the control data structures, and create and load the
380: * DMA map for it.
381: */
382: if ((error = bus_dmamem_alloc(sc->sc_dmatag,
383: sizeof(struct cas_control_data), CAS_PAGE_SIZE, 0, &sc->sc_cdseg,
384: 1, &sc->sc_cdnseg, 0)) != 0) {
385: printf("\n%s: unable to allocate control data, error = %d\n",
386: sc->sc_dev.dv_xname, error);
387: goto fail_0;
388: }
389:
390: /* XXX should map this in with correct endianness */
391: if ((error = bus_dmamem_map(sc->sc_dmatag, &sc->sc_cdseg, sc->sc_cdnseg,
392: sizeof(struct cas_control_data), (caddr_t *)&sc->sc_control_data,
393: BUS_DMA_COHERENT)) != 0) {
394: printf("\n%s: unable to map control data, error = %d\n",
395: sc->sc_dev.dv_xname, error);
396: goto fail_1;
397: }
398:
399: if ((error = bus_dmamap_create(sc->sc_dmatag,
400: sizeof(struct cas_control_data), 1,
401: sizeof(struct cas_control_data), 0, 0, &sc->sc_cddmamap)) != 0) {
402: printf("\n%s: unable to create control data DMA map, "
403: "error = %d\n", sc->sc_dev.dv_xname, error);
404: goto fail_2;
405: }
406:
407: if ((error = bus_dmamap_load(sc->sc_dmatag, sc->sc_cddmamap,
408: sc->sc_control_data, sizeof(struct cas_control_data), NULL,
409: 0)) != 0) {
410: printf("\n%s: unable to load control data DMA map, error = %d\n",
411: sc->sc_dev.dv_xname, error);
412: goto fail_3;
413: }
414:
415: /*
416: * Create the receive buffer DMA maps.
417: */
418: for (i = 0; i < CAS_NRXDESC; i++) {
419: bus_dma_segment_t seg;
420: caddr_t kva;
421: int rseg;
422:
423: if ((error = bus_dmamem_alloc(sc->sc_dmatag, CAS_PAGE_SIZE,
424: CAS_PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
425: printf("\n%s: unable to alloc rx DMA mem %d, "
426: "error = %d\n", sc->sc_dev.dv_xname, i, error);
427: goto fail_5;
428: }
429: sc->sc_rxsoft[i].rxs_dmaseg = seg;
430:
431: if ((error = bus_dmamem_map(sc->sc_dmatag, &seg, rseg,
432: CAS_PAGE_SIZE, &kva, BUS_DMA_NOWAIT)) != 0) {
433: printf("\n%s: unable to alloc rx DMA mem %d, "
434: "error = %d\n", sc->sc_dev.dv_xname, i, error);
435: goto fail_5;
436: }
437: sc->sc_rxsoft[i].rxs_kva = kva;
438:
439: if ((error = bus_dmamap_create(sc->sc_dmatag, CAS_PAGE_SIZE, 1,
440: CAS_PAGE_SIZE, 0, 0, &sc->sc_rxsoft[i].rxs_dmamap)) != 0) {
441: printf("\n%s: unable to create rx DMA map %d, "
442: "error = %d\n", sc->sc_dev.dv_xname, i, error);
443: goto fail_5;
444: }
445:
446: if ((error = bus_dmamap_load(sc->sc_dmatag,
447: sc->sc_rxsoft[i].rxs_dmamap, kva, CAS_PAGE_SIZE, NULL,
448: BUS_DMA_NOWAIT)) != 0) {
449: printf("\n%s: unable to load rx DMA map %d, "
450: "error = %d\n", sc->sc_dev.dv_xname, i, error);
451: goto fail_5;
452: }
453: }
454:
455: /*
456: * Create the transmit buffer DMA maps.
457: */
458: for (i = 0; i < CAS_NTXDESC; i++) {
459: if ((error = bus_dmamap_create(sc->sc_dmatag, MCLBYTES,
460: CAS_NTXSEGS, MCLBYTES, 0, BUS_DMA_NOWAIT,
461: &sc->sc_txd[i].sd_map)) != 0) {
462: printf("\n%s: unable to create tx DMA map %d, "
463: "error = %d\n", sc->sc_dev.dv_xname, i, error);
464: goto fail_6;
465: }
466: sc->sc_txd[i].sd_mbuf = NULL;
467: }
468:
469: /*
470: * From this point forward, the attachment cannot fail. A failure
471: * before this point releases all resources that may have been
472: * allocated.
473: */
474:
475: /* Announce ourselves. */
476: printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
477:
478: /* Get RX FIFO size */
479: sc->sc_rxfifosize = 16 * 1024;
480:
481: /* Initialize ifnet structure. */
482: strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, sizeof ifp->if_xname);
483: ifp->if_softc = sc;
484: ifp->if_flags =
485: IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
486: ifp->if_start = cas_start;
487: ifp->if_ioctl = cas_ioctl;
488: ifp->if_watchdog = cas_watchdog;
489: IFQ_SET_MAXLEN(&ifp->if_snd, CAS_NTXDESC - 1);
490: IFQ_SET_READY(&ifp->if_snd);
491:
492: ifp->if_capabilities = IFCAP_VLAN_MTU;
493:
494: /* Initialize ifmedia structures and MII info */
495: mii->mii_ifp = ifp;
496: mii->mii_readreg = cas_mii_readreg;
497: mii->mii_writereg = cas_mii_writereg;
498: mii->mii_statchg = cas_mii_statchg;
499:
500: ifmedia_init(&mii->mii_media, 0, cas_mediachange, cas_mediastatus);
501:
502: bus_space_write_4(sc->sc_memt, sc->sc_memh, CAS_MII_DATAPATH_MODE, 0);
503:
504: cas_mifinit(sc);
505:
506: if (sc->sc_mif_config & CAS_MIF_CONFIG_MDI1) {
507: sc->sc_mif_config |= CAS_MIF_CONFIG_PHY_SEL;
508: bus_space_write_4(sc->sc_memt, sc->sc_memh,
509: CAS_MIF_CONFIG, sc->sc_mif_config);
510: }
511:
512: mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY,
513: MII_OFFSET_ANY, 0);
514:
515: child = LIST_FIRST(&mii->mii_phys);
516: if (child == NULL &&
517: sc->sc_mif_config & (CAS_MIF_CONFIG_MDI0|CAS_MIF_CONFIG_MDI1)) {
518: /*
519: * Try the external PCS SERDES if we didn't find any
520: * MII devices.
521: */
522: bus_space_write_4(sc->sc_memt, sc->sc_memh,
523: CAS_MII_DATAPATH_MODE, CAS_MII_DATAPATH_SERDES);
524:
525: bus_space_write_4(sc->sc_memt, sc->sc_memh,
526: CAS_MII_SLINK_CONTROL,
527: CAS_MII_SLINK_LOOPBACK|CAS_MII_SLINK_EN_SYNC_D);
528:
529: bus_space_write_4(sc->sc_memt, sc->sc_memh,
530: CAS_MII_CONFIG, CAS_MII_CONFIG_ENABLE);
531:
532: mii->mii_readreg = cas_pcs_readreg;
533: mii->mii_writereg = cas_pcs_writereg;
534:
535: mii_attach(&sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY,
536: MII_OFFSET_ANY, MIIF_NOISOLATE);
537: }
538:
539: child = LIST_FIRST(&mii->mii_phys);
540: if (child == NULL) {
541: /* No PHY attached */
542: ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
543: ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL);
544: } else {
545: /*
546: * Walk along the list of attached MII devices and
547: * establish an `MII instance' to `phy number'
548: * mapping. We'll use this mapping in media change
549: * requests to determine which phy to use to program
550: * the MIF configuration register.
551: */
552: for (; child != NULL; child = LIST_NEXT(child, mii_list)) {
553: /*
554: * Note: we support just two PHYs: the built-in
555: * internal device and an external on the MII
556: * connector.
557: */
558: if (child->mii_phy > 1 || child->mii_inst > 1) {
559: printf("%s: cannot accommodate MII device %s"
560: " at phy %d, instance %d\n",
561: sc->sc_dev.dv_xname,
562: child->mii_dev.dv_xname,
563: child->mii_phy, child->mii_inst);
564: continue;
565: }
566:
567: sc->sc_phys[child->mii_inst] = child->mii_phy;
568: }
569:
570: /*
571: * XXX - we can really do the following ONLY if the
572: * phy indeed has the auto negotiation capability!!
573: */
574: ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
575: }
576:
577: /* Attach the interface. */
578: if_attach(ifp);
579: ether_ifattach(ifp);
580:
581: sc->sc_sh = shutdownhook_establish(cas_shutdown, sc);
582: if (sc->sc_sh == NULL)
583: panic("cas_config: can't establish shutdownhook");
584:
585: timeout_set(&sc->sc_tick_ch, cas_tick, sc);
586: return;
587:
588: /*
589: * Free any resources we've allocated during the failed attach
590: * attempt. Do this in reverse order and fall through.
591: */
592: fail_6:
593: for (i = 0; i < CAS_NTXDESC; i++) {
594: if (sc->sc_txd[i].sd_map != NULL)
595: bus_dmamap_destroy(sc->sc_dmatag,
596: sc->sc_txd[i].sd_map);
597: }
598: fail_5:
599: for (i = 0; i < CAS_NRXDESC; i++) {
600: if (sc->sc_rxsoft[i].rxs_dmamap != NULL)
601: bus_dmamap_destroy(sc->sc_dmatag,
602: sc->sc_rxsoft[i].rxs_dmamap);
603: }
604: bus_dmamap_unload(sc->sc_dmatag, sc->sc_cddmamap);
605: fail_3:
606: bus_dmamap_destroy(sc->sc_dmatag, sc->sc_cddmamap);
607: fail_2:
608: bus_dmamem_unmap(sc->sc_dmatag, (caddr_t)sc->sc_control_data,
609: sizeof(struct cas_control_data));
610: fail_1:
611: bus_dmamem_free(sc->sc_dmatag, &sc->sc_cdseg, sc->sc_cdnseg);
612: fail_0:
613: return;
614: }
615:
616:
617: void
618: cas_tick(void *arg)
619: {
620: struct cas_softc *sc = arg;
621: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
622: bus_space_tag_t t = sc->sc_memt;
623: bus_space_handle_t mac = sc->sc_memh;
624: int s;
625:
626: /* unload collisions counters */
627: ifp->if_collisions +=
628: bus_space_read_4(t, mac, CAS_MAC_NORM_COLL_CNT) +
629: bus_space_read_4(t, mac, CAS_MAC_FIRST_COLL_CNT) +
630: bus_space_read_4(t, mac, CAS_MAC_EXCESS_COLL_CNT) +
631: bus_space_read_4(t, mac, CAS_MAC_LATE_COLL_CNT);
632:
633: /* clear the hardware counters */
634: bus_space_write_4(t, mac, CAS_MAC_NORM_COLL_CNT, 0);
635: bus_space_write_4(t, mac, CAS_MAC_FIRST_COLL_CNT, 0);
636: bus_space_write_4(t, mac, CAS_MAC_EXCESS_COLL_CNT, 0);
637: bus_space_write_4(t, mac, CAS_MAC_LATE_COLL_CNT, 0);
638:
639: s = splnet();
640: mii_tick(&sc->sc_mii);
641: splx(s);
642:
643: timeout_add(&sc->sc_tick_ch, hz);
644: }
645:
646: int
647: cas_bitwait(struct cas_softc *sc, bus_space_handle_t h, int r,
648: u_int32_t clr, u_int32_t set)
649: {
650: int i;
651: u_int32_t reg;
652:
653: for (i = TRIES; i--; DELAY(100)) {
654: reg = bus_space_read_4(sc->sc_memt, h, r);
655: if ((reg & clr) == 0 && (reg & set) == set)
656: return (1);
657: }
658:
659: return (0);
660: }
661:
662: void
663: cas_reset(struct cas_softc *sc)
664: {
665: bus_space_tag_t t = sc->sc_memt;
666: bus_space_handle_t h = sc->sc_memh;
667: int s;
668:
669: s = splnet();
670: DPRINTF(sc, ("%s: cas_reset\n", sc->sc_dev.dv_xname));
671: cas_reset_rx(sc);
672: cas_reset_tx(sc);
673:
674: /* Do a full reset */
675: bus_space_write_4(t, h, CAS_RESET, CAS_RESET_RX|CAS_RESET_TX);
676: if (!cas_bitwait(sc, h, CAS_RESET, CAS_RESET_RX | CAS_RESET_TX, 0))
677: printf("%s: cannot reset device\n", sc->sc_dev.dv_xname);
678: splx(s);
679: }
680:
681:
682: /*
683: * cas_rxdrain:
684: *
685: * Drain the receive queue.
686: */
687: void
688: cas_rxdrain(struct cas_softc *sc)
689: {
690: /* Nothing to do yet. */
691: }
692:
693: /*
694: * Reset the whole thing.
695: */
696: void
697: cas_stop(struct ifnet *ifp, int disable)
698: {
699: struct cas_softc *sc = (struct cas_softc *)ifp->if_softc;
700: struct cas_sxd *sd;
701: u_int32_t i;
702:
703: DPRINTF(sc, ("%s: cas_stop\n", sc->sc_dev.dv_xname));
704:
705: timeout_del(&sc->sc_tick_ch);
706:
707: /*
708: * Mark the interface down and cancel the watchdog timer.
709: */
710: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
711: ifp->if_timer = 0;
712:
713: mii_down(&sc->sc_mii);
714:
715: cas_reset_rx(sc);
716: cas_reset_tx(sc);
717:
718: /*
719: * Release any queued transmit buffers.
720: */
721: for (i = 0; i < CAS_NTXDESC; i++) {
722: sd = &sc->sc_txd[i];
723: if (sd->sd_mbuf != NULL) {
724: bus_dmamap_sync(sc->sc_dmatag, sd->sd_map, 0,
725: sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
726: bus_dmamap_unload(sc->sc_dmatag, sd->sd_map);
727: m_freem(sd->sd_mbuf);
728: sd->sd_mbuf = NULL;
729: }
730: }
731: sc->sc_tx_cnt = sc->sc_tx_prod = sc->sc_tx_cons = 0;
732:
733: if (disable)
734: cas_rxdrain(sc);
735: }
736:
737:
738: /*
739: * Reset the receiver
740: */
741: int
742: cas_reset_rx(struct cas_softc *sc)
743: {
744: bus_space_tag_t t = sc->sc_memt;
745: bus_space_handle_t h = sc->sc_memh;
746:
747: /*
748: * Resetting while DMA is in progress can cause a bus hang, so we
749: * disable DMA first.
750: */
751: cas_disable_rx(sc);
752: bus_space_write_4(t, h, CAS_RX_CONFIG, 0);
753: /* Wait till it finishes */
754: if (!cas_bitwait(sc, h, CAS_RX_CONFIG, 1, 0))
755: printf("%s: cannot disable rx dma\n", sc->sc_dev.dv_xname);
756: /* Wait 5ms extra. */
757: delay(5000);
758:
759: /* Finally, reset the ERX */
760: bus_space_write_4(t, h, CAS_RESET, CAS_RESET_RX);
761: /* Wait till it finishes */
762: if (!cas_bitwait(sc, h, CAS_RESET, CAS_RESET_RX, 0)) {
763: printf("%s: cannot reset receiver\n", sc->sc_dev.dv_xname);
764: return (1);
765: }
766: return (0);
767: }
768:
769:
770: /*
771: * Reset the transmitter
772: */
773: int
774: cas_reset_tx(struct cas_softc *sc)
775: {
776: bus_space_tag_t t = sc->sc_memt;
777: bus_space_handle_t h = sc->sc_memh;
778:
779: /*
780: * Resetting while DMA is in progress can cause a bus hang, so we
781: * disable DMA first.
782: */
783: cas_disable_tx(sc);
784: bus_space_write_4(t, h, CAS_TX_CONFIG, 0);
785: /* Wait till it finishes */
786: if (!cas_bitwait(sc, h, CAS_TX_CONFIG, 1, 0))
787: printf("%s: cannot disable tx dma\n", sc->sc_dev.dv_xname);
788: /* Wait 5ms extra. */
789: delay(5000);
790:
791: /* Finally, reset the ETX */
792: bus_space_write_4(t, h, CAS_RESET, CAS_RESET_TX);
793: /* Wait till it finishes */
794: if (!cas_bitwait(sc, h, CAS_RESET, CAS_RESET_TX, 0)) {
795: printf("%s: cannot reset transmitter\n",
796: sc->sc_dev.dv_xname);
797: return (1);
798: }
799: return (0);
800: }
801:
802: /*
803: * disable receiver.
804: */
805: int
806: cas_disable_rx(struct cas_softc *sc)
807: {
808: bus_space_tag_t t = sc->sc_memt;
809: bus_space_handle_t h = sc->sc_memh;
810: u_int32_t cfg;
811:
812: /* Flip the enable bit */
813: cfg = bus_space_read_4(t, h, CAS_MAC_RX_CONFIG);
814: cfg &= ~CAS_MAC_RX_ENABLE;
815: bus_space_write_4(t, h, CAS_MAC_RX_CONFIG, cfg);
816:
817: /* Wait for it to finish */
818: return (cas_bitwait(sc, h, CAS_MAC_RX_CONFIG, CAS_MAC_RX_ENABLE, 0));
819: }
820:
821: /*
822: * disable transmitter.
823: */
824: int
825: cas_disable_tx(struct cas_softc *sc)
826: {
827: bus_space_tag_t t = sc->sc_memt;
828: bus_space_handle_t h = sc->sc_memh;
829: u_int32_t cfg;
830:
831: /* Flip the enable bit */
832: cfg = bus_space_read_4(t, h, CAS_MAC_TX_CONFIG);
833: cfg &= ~CAS_MAC_TX_ENABLE;
834: bus_space_write_4(t, h, CAS_MAC_TX_CONFIG, cfg);
835:
836: /* Wait for it to finish */
837: return (cas_bitwait(sc, h, CAS_MAC_TX_CONFIG, CAS_MAC_TX_ENABLE, 0));
838: }
839:
840: /*
841: * Initialize interface.
842: */
843: int
844: cas_meminit(struct cas_softc *sc)
845: {
846: struct cas_rxsoft *rxs;
847: int i, error;
848:
849: rxs = (void *)&error;
850:
851: /*
852: * Initialize the transmit descriptor ring.
853: */
854: for (i = 0; i < CAS_NTXDESC; i++) {
855: sc->sc_txdescs[i].cd_flags = 0;
856: sc->sc_txdescs[i].cd_addr = 0;
857: }
858: CAS_CDTXSYNC(sc, 0, CAS_NTXDESC,
859: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
860:
861: /*
862: * Initialize the receive descriptor and receive job
863: * descriptor rings.
864: */
865: for (i = 0; i < CAS_NRXDESC; i++)
866: CAS_INIT_RXDESC(sc, i, i);
867: sc->sc_rxdptr = 0;
868: sc->sc_rxptr = 0;
869:
870: /*
871: * Initialize the receive completion ring.
872: */
873: for (i = 0; i < CAS_NRXCOMP; i++) {
874: sc->sc_rxcomps[i].cc_word[0] = 0;
875: sc->sc_rxcomps[i].cc_word[1] = 0;
876: sc->sc_rxcomps[i].cc_word[2] = 0;
877: sc->sc_rxcomps[i].cc_word[3] = CAS_DMA_WRITE(CAS_RC3_OWN);
878: CAS_CDRXCSYNC(sc, i,
879: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
880: }
881:
882: return (0);
883: }
884:
885: int
886: cas_ringsize(int sz)
887: {
888: switch (sz) {
889: case 32:
890: return CAS_RING_SZ_32;
891: case 64:
892: return CAS_RING_SZ_64;
893: case 128:
894: return CAS_RING_SZ_128;
895: case 256:
896: return CAS_RING_SZ_256;
897: case 512:
898: return CAS_RING_SZ_512;
899: case 1024:
900: return CAS_RING_SZ_1024;
901: case 2048:
902: return CAS_RING_SZ_2048;
903: case 4096:
904: return CAS_RING_SZ_4096;
905: case 8192:
906: return CAS_RING_SZ_8192;
907: default:
908: printf("cas: invalid Receive Descriptor ring size %d\n", sz);
909: return CAS_RING_SZ_32;
910: }
911: }
912:
913: int
914: cas_cringsize(int sz)
915: {
916: int i;
917:
918: for (i = 0; i < 9; i++)
919: if (sz == (128 << i))
920: return i;
921:
922: printf("cas: invalid completion ring size %d\n", sz);
923: return 128;
924: }
925:
926: /*
927: * Initialization of interface; set up initialization block
928: * and transmit/receive descriptor rings.
929: */
930: int
931: cas_init(struct ifnet *ifp)
932: {
933:
934: struct cas_softc *sc = (struct cas_softc *)ifp->if_softc;
935: bus_space_tag_t t = sc->sc_memt;
936: bus_space_handle_t h = sc->sc_memh;
937: int s;
938: u_int max_frame_size;
939: u_int32_t v;
940:
941: s = splnet();
942:
943: DPRINTF(sc, ("%s: cas_init: calling stop\n", sc->sc_dev.dv_xname));
944: /*
945: * Initialization sequence. The numbered steps below correspond
946: * to the sequence outlined in section 6.3.5.1 in the Ethernet
947: * Channel Engine manual (part of the PCIO manual).
948: * See also the STP2002-STQ document from Sun Microsystems.
949: */
950:
951: /* step 1 & 2. Reset the Ethernet Channel */
952: cas_stop(ifp, 0);
953: cas_reset(sc);
954: DPRINTF(sc, ("%s: cas_init: restarting\n", sc->sc_dev.dv_xname));
955:
956: /* Re-initialize the MIF */
957: cas_mifinit(sc);
958:
959: /* step 3. Setup data structures in host memory */
960: cas_meminit(sc);
961:
962: /* step 4. TX MAC registers & counters */
963: cas_init_regs(sc);
964: max_frame_size = ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN;
965: v = (max_frame_size) | (0x2000 << 16) /* Burst size */;
966: bus_space_write_4(t, h, CAS_MAC_MAC_MAX_FRAME, v);
967:
968: /* step 5. RX MAC registers & counters */
969: cas_setladrf(sc);
970:
971: /* step 6 & 7. Program Descriptor Ring Base Addresses */
972: KASSERT((CAS_CDTXADDR(sc, 0) & 0x1fff) == 0);
973: bus_space_write_4(t, h, CAS_TX_RING_PTR_HI,
974: (((uint64_t)CAS_CDTXADDR(sc,0)) >> 32));
975: bus_space_write_4(t, h, CAS_TX_RING_PTR_LO, CAS_CDTXADDR(sc, 0));
976:
977: KASSERT((CAS_CDRXADDR(sc, 0) & 0x1fff) == 0);
978: bus_space_write_4(t, h, CAS_RX_DRING_PTR_HI,
979: (((uint64_t)CAS_CDRXADDR(sc,0)) >> 32));
980: bus_space_write_4(t, h, CAS_RX_DRING_PTR_LO, CAS_CDRXADDR(sc, 0));
981:
982: KASSERT((CAS_CDRXCADDR(sc, 0) & 0x1fff) == 0);
983: bus_space_write_4(t, h, CAS_RX_CRING_PTR_HI,
984: (((uint64_t)CAS_CDRXCADDR(sc,0)) >> 32));
985: bus_space_write_4(t, h, CAS_RX_CRING_PTR_LO, CAS_CDRXCADDR(sc, 0));
986:
987: /* step 8. Global Configuration & Interrupt Mask */
988: bus_space_write_4(t, h, CAS_INTMASK,
989: ~(CAS_INTR_TX_INTME|CAS_INTR_TX_EMPTY|
990: CAS_INTR_TX_TAG_ERR|
991: CAS_INTR_RX_DONE|CAS_INTR_RX_NOBUF|
992: CAS_INTR_RX_TAG_ERR|
993: CAS_INTR_RX_COMP_FULL|CAS_INTR_PCS|
994: CAS_INTR_MAC_CONTROL|CAS_INTR_MIF|
995: CAS_INTR_BERR));
996: bus_space_write_4(t, h, CAS_MAC_RX_MASK,
997: CAS_MAC_RX_DONE|CAS_MAC_RX_FRAME_CNT);
998: bus_space_write_4(t, h, CAS_MAC_TX_MASK, CAS_MAC_TX_XMIT_DONE);
999: bus_space_write_4(t, h, CAS_MAC_CONTROL_MASK, 0); /* XXXX */
1000:
1001: /* step 9. ETX Configuration: use mostly default values */
1002:
1003: /* Enable DMA */
1004: v = cas_ringsize(CAS_NTXDESC /*XXX*/) << 10;
1005: bus_space_write_4(t, h, CAS_TX_CONFIG,
1006: v|CAS_TX_CONFIG_TXDMA_EN|(1<<24)|(1<<29));
1007: bus_space_write_4(t, h, CAS_TX_KICK, 0);
1008:
1009: /* step 10. ERX Configuration */
1010:
1011: /* Encode Receive Descriptor ring size */
1012: v = cas_ringsize(CAS_NRXDESC) << CAS_RX_CONFIG_RXDRNG_SZ_SHIFT;
1013:
1014: /* Encode Receive Completion ring size */
1015: v |= cas_cringsize(CAS_NRXCOMP) << CAS_RX_CONFIG_RXCRNG_SZ_SHIFT;
1016:
1017: /* Enable DMA */
1018: bus_space_write_4(t, h, CAS_RX_CONFIG,
1019: v|(2<<CAS_RX_CONFIG_FBOFF_SHFT)|CAS_RX_CONFIG_RXDMA_EN);
1020:
1021: /*
1022: * The following value is for an OFF Threshold of about 3/4 full
1023: * and an ON Threshold of 1/4 full.
1024: */
1025: bus_space_write_4(t, h, CAS_RX_PAUSE_THRESH,
1026: (3 * sc->sc_rxfifosize / 256) |
1027: ( (sc->sc_rxfifosize / 256) << 12));
1028: bus_space_write_4(t, h, CAS_RX_BLANKING, (6<<12)|6);
1029:
1030: /* step 11. Configure Media */
1031: mii_mediachg(&sc->sc_mii);
1032:
1033: /* step 12. RX_MAC Configuration Register */
1034: v = bus_space_read_4(t, h, CAS_MAC_RX_CONFIG);
1035: v |= CAS_MAC_RX_ENABLE | CAS_MAC_RX_STRIP_CRC;
1036: bus_space_write_4(t, h, CAS_MAC_RX_CONFIG, v);
1037:
1038: /* step 14. Issue Transmit Pending command */
1039:
1040: /* step 15. Give the receiver a swift kick */
1041: bus_space_write_4(t, h, CAS_RX_KICK, CAS_NRXDESC-4);
1042:
1043: /* Start the one second timer. */
1044: timeout_add(&sc->sc_tick_ch, hz);
1045:
1046: ifp->if_flags |= IFF_RUNNING;
1047: ifp->if_flags &= ~IFF_OACTIVE;
1048: ifp->if_timer = 0;
1049: splx(s);
1050:
1051: return (0);
1052: }
1053:
1054: void
1055: cas_init_regs(struct cas_softc *sc)
1056: {
1057: bus_space_tag_t t = sc->sc_memt;
1058: bus_space_handle_t h = sc->sc_memh;
1059: u_int32_t v, r;
1060:
1061: /* These regs are not cleared on reset */
1062: sc->sc_inited = 0;
1063: if (!sc->sc_inited) {
1064:
1065: /* Wooo. Magic values. */
1066: bus_space_write_4(t, h, CAS_MAC_IPG0, 0);
1067: bus_space_write_4(t, h, CAS_MAC_IPG1, 8);
1068: bus_space_write_4(t, h, CAS_MAC_IPG2, 4);
1069:
1070: bus_space_write_4(t, h, CAS_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN);
1071: /* Max frame and max burst size */
1072: v = ETHER_MAX_LEN | (0x2000 << 16) /* Burst size */;
1073: bus_space_write_4(t, h, CAS_MAC_MAC_MAX_FRAME, v);
1074:
1075: bus_space_write_4(t, h, CAS_MAC_PREAMBLE_LEN, 0x7);
1076: bus_space_write_4(t, h, CAS_MAC_JAM_SIZE, 0x4);
1077: bus_space_write_4(t, h, CAS_MAC_ATTEMPT_LIMIT, 0x10);
1078: /* Dunno.... */
1079: bus_space_write_4(t, h, CAS_MAC_CONTROL_TYPE, 0x8088);
1080: bus_space_write_4(t, h, CAS_MAC_RANDOM_SEED,
1081: ((sc->sc_arpcom.ac_enaddr[5]<<8)|sc->sc_arpcom.ac_enaddr[4])&0x3ff);
1082:
1083: /* Secondary MAC addresses set to 0:0:0:0:0:0 */
1084: for (r = CAS_MAC_ADDR3; r < CAS_MAC_ADDR42; r += 4)
1085: bus_space_write_4(t, h, r, 0);
1086:
1087: /* MAC control addr set to 0:1:c2:0:1:80 */
1088: bus_space_write_4(t, h, CAS_MAC_ADDR42, 0x0001);
1089: bus_space_write_4(t, h, CAS_MAC_ADDR43, 0xc200);
1090: bus_space_write_4(t, h, CAS_MAC_ADDR44, 0x0180);
1091:
1092: /* MAC filter addr set to 0:0:0:0:0:0 */
1093: bus_space_write_4(t, h, CAS_MAC_ADDR_FILTER0, 0);
1094: bus_space_write_4(t, h, CAS_MAC_ADDR_FILTER1, 0);
1095: bus_space_write_4(t, h, CAS_MAC_ADDR_FILTER2, 0);
1096:
1097: bus_space_write_4(t, h, CAS_MAC_ADR_FLT_MASK1_2, 0);
1098: bus_space_write_4(t, h, CAS_MAC_ADR_FLT_MASK0, 0);
1099:
1100: /* Hash table initialized to 0 */
1101: for (r = CAS_MAC_HASH0; r <= CAS_MAC_HASH15; r += 4)
1102: bus_space_write_4(t, h, r, 0);
1103:
1104: sc->sc_inited = 1;
1105: }
1106:
1107: /* Counters need to be zeroed */
1108: bus_space_write_4(t, h, CAS_MAC_NORM_COLL_CNT, 0);
1109: bus_space_write_4(t, h, CAS_MAC_FIRST_COLL_CNT, 0);
1110: bus_space_write_4(t, h, CAS_MAC_EXCESS_COLL_CNT, 0);
1111: bus_space_write_4(t, h, CAS_MAC_LATE_COLL_CNT, 0);
1112: bus_space_write_4(t, h, CAS_MAC_DEFER_TMR_CNT, 0);
1113: bus_space_write_4(t, h, CAS_MAC_PEAK_ATTEMPTS, 0);
1114: bus_space_write_4(t, h, CAS_MAC_RX_FRAME_COUNT, 0);
1115: bus_space_write_4(t, h, CAS_MAC_RX_LEN_ERR_CNT, 0);
1116: bus_space_write_4(t, h, CAS_MAC_RX_ALIGN_ERR, 0);
1117: bus_space_write_4(t, h, CAS_MAC_RX_CRC_ERR_CNT, 0);
1118: bus_space_write_4(t, h, CAS_MAC_RX_CODE_VIOL, 0);
1119:
1120: /* Un-pause stuff */
1121: bus_space_write_4(t, h, CAS_MAC_SEND_PAUSE_CMD, 0);
1122:
1123: /*
1124: * Set the station address.
1125: */
1126: bus_space_write_4(t, h, CAS_MAC_ADDR0,
1127: (sc->sc_arpcom.ac_enaddr[4]<<8) | sc->sc_arpcom.ac_enaddr[5]);
1128: bus_space_write_4(t, h, CAS_MAC_ADDR1,
1129: (sc->sc_arpcom.ac_enaddr[2]<<8) | sc->sc_arpcom.ac_enaddr[3]);
1130: bus_space_write_4(t, h, CAS_MAC_ADDR2,
1131: (sc->sc_arpcom.ac_enaddr[0]<<8) | sc->sc_arpcom.ac_enaddr[1]);
1132: }
1133:
1134: /*
1135: * Receive interrupt.
1136: */
1137: int
1138: cas_rint(struct cas_softc *sc)
1139: {
1140: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1141: bus_space_tag_t t = sc->sc_memt;
1142: bus_space_handle_t h = sc->sc_memh;
1143: struct cas_rxsoft *rxs;
1144: struct mbuf *m;
1145: u_int64_t word[4];
1146: int len, off, idx;
1147: int i, skip;
1148: caddr_t cp;
1149:
1150: for (i = sc->sc_rxptr;; i = CAS_NEXTRX(i + skip)) {
1151: CAS_CDRXCSYNC(sc, i,
1152: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1153:
1154: word[0] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[0]);
1155: word[1] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[1]);
1156: word[2] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[2]);
1157: word[3] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[3]);
1158:
1159: /* Stop if the hardware still owns the descriptor. */
1160: if ((word[0] & CAS_RC0_TYPE) == 0 || word[3] & CAS_RC3_OWN)
1161: break;
1162:
1163: len = CAS_RC1_HDR_LEN(word[1]);
1164: if (len > 0) {
1165: off = CAS_RC1_HDR_OFF(word[1]);
1166: idx = CAS_RC1_HDR_IDX(word[1]);
1167: rxs = &sc->sc_rxsoft[idx];
1168:
1169: DPRINTF(sc, ("hdr at idx %d, off %d, len %d\n",
1170: idx, off, len));
1171:
1172: bus_dmamap_sync(sc->sc_dmatag, rxs->rxs_dmamap, 0,
1173: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
1174:
1175: cp = rxs->rxs_kva + off * 256;
1176: m = m_devget(cp, len + ETHER_ALIGN, 0, ifp, NULL);
1177:
1178: if (word[0] & CAS_RC0_RELEASE_HDR)
1179: cas_add_rxbuf(sc, idx);
1180:
1181: if (m != NULL) {
1182: m_adj(m, ETHER_ALIGN);
1183:
1184: #if NBPFILTER > 0
1185: /*
1186: * Pass this up to any BPF listeners, but only
1187: * pass it up the stack if its for us.
1188: */
1189: if (ifp->if_bpf)
1190: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1191: #endif /* NPBFILTER > 0 */
1192:
1193: ifp->if_ipackets++;
1194: ether_input_mbuf(ifp, m);
1195: } else
1196: ifp->if_ierrors++;
1197: }
1198:
1199: len = CAS_RC0_DATA_LEN(word[0]);
1200: if (len > 0) {
1201: off = CAS_RC0_DATA_OFF(word[0]);
1202: idx = CAS_RC0_DATA_IDX(word[0]);
1203: rxs = &sc->sc_rxsoft[idx];
1204:
1205: DPRINTF(sc, ("data at idx %d, off %d, len %d\n",
1206: idx, off, len));
1207:
1208: bus_dmamap_sync(sc->sc_dmatag, rxs->rxs_dmamap, 0,
1209: rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
1210:
1211: /* XXX We should not be copying the packet here. */
1212: cp = rxs->rxs_kva + off;
1213: m = m_devget(cp, len + ETHER_ALIGN, 0, ifp, NULL);
1214:
1215: if (word[0] & CAS_RC0_RELEASE_DATA)
1216: cas_add_rxbuf(sc, idx);
1217:
1218: if (m != NULL) {
1219: m_adj(m, ETHER_ALIGN);
1220:
1221: #if NBPFILTER > 0
1222: /*
1223: * Pass this up to any BPF listeners, but only
1224: * pass it up the stack if its for us.
1225: */
1226: if (ifp->if_bpf)
1227: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1228: #endif /* NPBFILTER > 0 */
1229:
1230: ifp->if_ipackets++;
1231: ether_input_mbuf(ifp, m);
1232: } else
1233: ifp->if_ierrors++;
1234: }
1235:
1236: if (word[0] & CAS_RC0_SPLIT)
1237: printf("split packet\n");
1238:
1239: skip = CAS_RC0_SKIP(word[0]);
1240: }
1241:
1242: while (sc->sc_rxptr != i) {
1243: sc->sc_rxcomps[sc->sc_rxptr].cc_word[0] = 0;
1244: sc->sc_rxcomps[sc->sc_rxptr].cc_word[1] = 0;
1245: sc->sc_rxcomps[sc->sc_rxptr].cc_word[2] = 0;
1246: sc->sc_rxcomps[sc->sc_rxptr].cc_word[3] =
1247: CAS_DMA_WRITE(CAS_RC3_OWN);
1248: CAS_CDRXCSYNC(sc, sc->sc_rxptr,
1249: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1250:
1251: sc->sc_rxptr = CAS_NEXTRX(sc->sc_rxptr);
1252: }
1253:
1254: bus_space_write_4(t, h, CAS_RX_COMP_TAIL, sc->sc_rxptr);
1255:
1256: DPRINTF(sc, ("cas_rint: done sc->rxptr %d, complete %d\n",
1257: sc->sc_rxptr, bus_space_read_4(t, h, CAS_RX_COMPLETION)));
1258:
1259: return (1);
1260: }
1261:
1262: /*
1263: * cas_add_rxbuf:
1264: *
1265: * Add a receive buffer to the indicated descriptor.
1266: */
1267: int
1268: cas_add_rxbuf(struct cas_softc *sc, int idx)
1269: {
1270: bus_space_tag_t t = sc->sc_memt;
1271: bus_space_handle_t h = sc->sc_memh;
1272:
1273: CAS_INIT_RXDESC(sc, sc->sc_rxdptr, idx);
1274:
1275: if ((sc->sc_rxdptr % 4) == 0)
1276: bus_space_write_4(t, h, CAS_RX_KICK, sc->sc_rxdptr);
1277:
1278: sc->sc_rxdptr++;
1279: return (0);
1280: }
1281:
1282: int
1283: cas_eint(struct cas_softc *sc, u_int status)
1284: {
1285: if ((status & CAS_INTR_MIF) != 0) {
1286: #ifdef CAS_DEBUG
1287: printf("%s: link status changed\n", sc->sc_dev.dv_xname);
1288: #endif
1289: return (1);
1290: }
1291:
1292: printf("%s: status=%b\n", sc->sc_dev.dv_xname, status, CAS_INTR_BITS);
1293: return (1);
1294: }
1295:
1296: int
1297: cas_pint(struct cas_softc *sc)
1298: {
1299: bus_space_tag_t t = sc->sc_memt;
1300: bus_space_handle_t seb = sc->sc_memh;
1301: u_int32_t status;
1302:
1303: status = bus_space_read_4(t, seb, CAS_MII_INTERRUP_STATUS);
1304: status |= bus_space_read_4(t, seb, CAS_MII_INTERRUP_STATUS);
1305: #ifdef CAS_DEBUG
1306: if (status)
1307: printf("%s: link status changed\n", sc->sc_dev.dv_xname);
1308: #endif
1309: return (1);
1310: }
1311:
1312: int
1313: cas_intr(void *v)
1314: {
1315: struct cas_softc *sc = (struct cas_softc *)v;
1316: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1317: bus_space_tag_t t = sc->sc_memt;
1318: bus_space_handle_t seb = sc->sc_memh;
1319: u_int32_t status;
1320: int r = 0;
1321:
1322: status = bus_space_read_4(t, seb, CAS_STATUS);
1323: DPRINTF(sc, ("%s: cas_intr: cplt %xstatus %b\n",
1324: sc->sc_dev.dv_xname, (status>>19), status, CAS_INTR_BITS));
1325:
1326: if ((status & CAS_INTR_PCS) != 0)
1327: r |= cas_pint(sc);
1328:
1329: if ((status & (CAS_INTR_TX_TAG_ERR | CAS_INTR_RX_TAG_ERR |
1330: CAS_INTR_RX_COMP_FULL | CAS_INTR_BERR)) != 0)
1331: r |= cas_eint(sc, status);
1332:
1333: if ((status & (CAS_INTR_TX_EMPTY | CAS_INTR_TX_INTME)) != 0)
1334: r |= cas_tint(sc, status);
1335:
1336: if ((status & (CAS_INTR_RX_DONE | CAS_INTR_RX_NOBUF)) != 0)
1337: r |= cas_rint(sc);
1338:
1339: /* We should eventually do more than just print out error stats. */
1340: if (status & CAS_INTR_TX_MAC) {
1341: int txstat = bus_space_read_4(t, seb, CAS_MAC_TX_STATUS);
1342: #ifdef CAS_DEBUG
1343: if (txstat & ~CAS_MAC_TX_XMIT_DONE)
1344: printf("%s: MAC tx fault, status %x\n",
1345: sc->sc_dev.dv_xname, txstat);
1346: #endif
1347: if (txstat & (CAS_MAC_TX_UNDERRUN | CAS_MAC_TX_PKT_TOO_LONG))
1348: cas_init(ifp);
1349: }
1350: if (status & CAS_INTR_RX_MAC) {
1351: int rxstat = bus_space_read_4(t, seb, CAS_MAC_RX_STATUS);
1352: #ifdef CAS_DEBUG
1353: if (rxstat & ~CAS_MAC_RX_DONE)
1354: printf("%s: MAC rx fault, status %x\n",
1355: sc->sc_dev.dv_xname, rxstat);
1356: #endif
1357: /*
1358: * On some chip revisions CAS_MAC_RX_OVERFLOW happen often
1359: * due to a silicon bug so handle them silently.
1360: */
1361: if (rxstat & CAS_MAC_RX_OVERFLOW) {
1362: ifp->if_ierrors++;
1363: cas_init(ifp);
1364: }
1365: #ifdef CAS_DEBUG
1366: else if (rxstat & ~(CAS_MAC_RX_DONE | CAS_MAC_RX_FRAME_CNT))
1367: printf("%s: MAC rx fault, status %x\n",
1368: sc->sc_dev.dv_xname, rxstat);
1369: #endif
1370: }
1371: return (r);
1372: }
1373:
1374:
1375: void
1376: cas_watchdog(struct ifnet *ifp)
1377: {
1378: struct cas_softc *sc = ifp->if_softc;
1379:
1380: DPRINTF(sc, ("cas_watchdog: CAS_RX_CONFIG %x CAS_MAC_RX_STATUS %x "
1381: "CAS_MAC_RX_CONFIG %x\n",
1382: bus_space_read_4(sc->sc_memt, sc->sc_memh, CAS_RX_CONFIG),
1383: bus_space_read_4(sc->sc_memt, sc->sc_memh, CAS_MAC_RX_STATUS),
1384: bus_space_read_4(sc->sc_memt, sc->sc_memh, CAS_MAC_RX_CONFIG)));
1385:
1386: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
1387: ++ifp->if_oerrors;
1388:
1389: /* Try to get more packets going. */
1390: cas_init(ifp);
1391: }
1392:
1393: /*
1394: * Initialize the MII Management Interface
1395: */
1396: void
1397: cas_mifinit(struct cas_softc *sc)
1398: {
1399: bus_space_tag_t t = sc->sc_memt;
1400: bus_space_handle_t mif = sc->sc_memh;
1401:
1402: /* Configure the MIF in frame mode */
1403: sc->sc_mif_config = bus_space_read_4(t, mif, CAS_MIF_CONFIG);
1404: sc->sc_mif_config &= ~CAS_MIF_CONFIG_BB_ENA;
1405: bus_space_write_4(t, mif, CAS_MIF_CONFIG, sc->sc_mif_config);
1406: }
1407:
1408: /*
1409: * MII interface
1410: *
1411: * The Cassini MII interface supports at least three different operating modes:
1412: *
1413: * Bitbang mode is implemented using data, clock and output enable registers.
1414: *
1415: * Frame mode is implemented by loading a complete frame into the frame
1416: * register and polling the valid bit for completion.
1417: *
1418: * Polling mode uses the frame register but completion is indicated by
1419: * an interrupt.
1420: *
1421: */
1422: int
1423: cas_mii_readreg(struct device *self, int phy, int reg)
1424: {
1425: struct cas_softc *sc = (void *)self;
1426: bus_space_tag_t t = sc->sc_memt;
1427: bus_space_handle_t mif = sc->sc_memh;
1428: int n;
1429: u_int32_t v;
1430:
1431: #ifdef CAS_DEBUG
1432: if (sc->sc_debug)
1433: printf("cas_mii_readreg: phy %d reg %d\n", phy, reg);
1434: #endif
1435:
1436: /* Construct the frame command */
1437: v = (reg << CAS_MIF_REG_SHIFT) | (phy << CAS_MIF_PHY_SHIFT) |
1438: CAS_MIF_FRAME_READ;
1439:
1440: bus_space_write_4(t, mif, CAS_MIF_FRAME, v);
1441: for (n = 0; n < 100; n++) {
1442: DELAY(1);
1443: v = bus_space_read_4(t, mif, CAS_MIF_FRAME);
1444: if (v & CAS_MIF_FRAME_TA0)
1445: return (v & CAS_MIF_FRAME_DATA);
1446: }
1447:
1448: printf("%s: mii_read timeout\n", sc->sc_dev.dv_xname);
1449: return (0);
1450: }
1451:
1452: void
1453: cas_mii_writereg(struct device *self, int phy, int reg, int val)
1454: {
1455: struct cas_softc *sc = (void *)self;
1456: bus_space_tag_t t = sc->sc_memt;
1457: bus_space_handle_t mif = sc->sc_memh;
1458: int n;
1459: u_int32_t v;
1460:
1461: #ifdef CAS_DEBUG
1462: if (sc->sc_debug)
1463: printf("cas_mii_writereg: phy %d reg %d val %x\n",
1464: phy, reg, val);
1465: #endif
1466:
1467: #if 0
1468: /* Select the desired PHY in the MIF configuration register */
1469: v = bus_space_read_4(t, mif, CAS_MIF_CONFIG);
1470: /* Clear PHY select bit */
1471: v &= ~CAS_MIF_CONFIG_PHY_SEL;
1472: if (phy == CAS_PHYAD_EXTERNAL)
1473: /* Set PHY select bit to get at external device */
1474: v |= CAS_MIF_CONFIG_PHY_SEL;
1475: bus_space_write_4(t, mif, CAS_MIF_CONFIG, v);
1476: #endif
1477: /* Construct the frame command */
1478: v = CAS_MIF_FRAME_WRITE |
1479: (phy << CAS_MIF_PHY_SHIFT) |
1480: (reg << CAS_MIF_REG_SHIFT) |
1481: (val & CAS_MIF_FRAME_DATA);
1482:
1483: bus_space_write_4(t, mif, CAS_MIF_FRAME, v);
1484: for (n = 0; n < 100; n++) {
1485: DELAY(1);
1486: v = bus_space_read_4(t, mif, CAS_MIF_FRAME);
1487: if (v & CAS_MIF_FRAME_TA0)
1488: return;
1489: }
1490:
1491: printf("%s: mii_write timeout\n", sc->sc_dev.dv_xname);
1492: }
1493:
1494: void
1495: cas_mii_statchg(struct device *dev)
1496: {
1497: struct cas_softc *sc = (void *)dev;
1498: #ifdef CAS_DEBUG
1499: int instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
1500: #endif
1501: bus_space_tag_t t = sc->sc_memt;
1502: bus_space_handle_t mac = sc->sc_memh;
1503: u_int32_t v;
1504:
1505: #ifdef CAS_DEBUG
1506: if (sc->sc_debug)
1507: printf("cas_mii_statchg: status change: phy = %d\n",
1508: sc->sc_phys[instance]);
1509: #endif
1510:
1511: /* Set tx full duplex options */
1512: bus_space_write_4(t, mac, CAS_MAC_TX_CONFIG, 0);
1513: delay(10000); /* reg must be cleared and delay before changing. */
1514: v = CAS_MAC_TX_ENA_IPG0|CAS_MAC_TX_NGU|CAS_MAC_TX_NGU_LIMIT|
1515: CAS_MAC_TX_ENABLE;
1516: if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0) {
1517: v |= CAS_MAC_TX_IGN_CARRIER|CAS_MAC_TX_IGN_COLLIS;
1518: }
1519: bus_space_write_4(t, mac, CAS_MAC_TX_CONFIG, v);
1520:
1521: /* XIF Configuration */
1522: v = CAS_MAC_XIF_TX_MII_ENA;
1523: v |= CAS_MAC_XIF_LINK_LED;
1524:
1525: /* MII needs echo disable if half duplex. */
1526: if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0)
1527: /* turn on full duplex LED */
1528: v |= CAS_MAC_XIF_FDPLX_LED;
1529: else
1530: /* half duplex -- disable echo */
1531: v |= CAS_MAC_XIF_ECHO_DISABL;
1532:
1533: switch (IFM_SUBTYPE(sc->sc_mii.mii_media_active)) {
1534: case IFM_1000_T: /* Gigabit using GMII interface */
1535: case IFM_1000_SX:
1536: v |= CAS_MAC_XIF_GMII_MODE;
1537: break;
1538: default:
1539: v &= ~CAS_MAC_XIF_GMII_MODE;
1540: }
1541: bus_space_write_4(t, mac, CAS_MAC_XIF_CONFIG, v);
1542: }
1543:
1544: int
1545: cas_pcs_readreg(struct device *self, int phy, int reg)
1546: {
1547: struct cas_softc *sc = (void *)self;
1548: bus_space_tag_t t = sc->sc_memt;
1549: bus_space_handle_t pcs = sc->sc_memh;
1550:
1551: #ifdef CAS_DEBUG
1552: if (sc->sc_debug)
1553: printf("cas_pcs_readreg: phy %d reg %d\n", phy, reg);
1554: #endif
1555:
1556: if (phy != CAS_PHYAD_EXTERNAL)
1557: return (0);
1558:
1559: switch (reg) {
1560: case MII_BMCR:
1561: reg = CAS_MII_CONTROL;
1562: break;
1563: case MII_BMSR:
1564: reg = CAS_MII_STATUS;
1565: break;
1566: case MII_ANAR:
1567: reg = CAS_MII_ANAR;
1568: break;
1569: case MII_ANLPAR:
1570: reg = CAS_MII_ANLPAR;
1571: break;
1572: case MII_EXTSR:
1573: return (EXTSR_1000XFDX|EXTSR_1000XHDX);
1574: default:
1575: return (0);
1576: }
1577:
1578: return bus_space_read_4(t, pcs, reg);
1579: }
1580:
1581: void
1582: cas_pcs_writereg(struct device *self, int phy, int reg, int val)
1583: {
1584: struct cas_softc *sc = (void *)self;
1585: bus_space_tag_t t = sc->sc_memt;
1586: bus_space_handle_t pcs = sc->sc_memh;
1587:
1588: #ifdef CAS_DEBUG
1589: if (sc->sc_debug)
1590: printf("cas_pcs_writereg: phy %d reg %d val %x\n",
1591: phy, reg, val);
1592: #endif
1593:
1594: if (phy != CAS_PHYAD_EXTERNAL)
1595: return;
1596:
1597: switch (reg) {
1598: case MII_BMCR:
1599: reg = CAS_MII_CONTROL;
1600: break;
1601: case MII_BMSR:
1602: reg = CAS_MII_STATUS;
1603: break;
1604: case MII_ANAR:
1605: reg = CAS_MII_ANAR;
1606: break;
1607: case MII_ANLPAR:
1608: reg = CAS_MII_ANLPAR;
1609: break;
1610: default:
1611: return;
1612: }
1613:
1614: bus_space_write_4(t, pcs, reg, val);
1615:
1616: if (reg == CAS_MII_ANAR) {
1617: bus_space_write_4(t, pcs, CAS_MII_SLINK_CONTROL,
1618: CAS_MII_SLINK_LOOPBACK|CAS_MII_SLINK_EN_SYNC_D);
1619: bus_space_write_4(t, pcs, CAS_MII_CONFIG,
1620: CAS_MII_CONFIG_ENABLE);
1621: }
1622: }
1623:
1624: int
1625: cas_mediachange(struct ifnet *ifp)
1626: {
1627: struct cas_softc *sc = ifp->if_softc;
1628: struct mii_data *mii = &sc->sc_mii;
1629:
1630: if (mii->mii_instance) {
1631: struct mii_softc *miisc;
1632: LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
1633: mii_phy_reset(miisc);
1634: }
1635:
1636: return (mii_mediachg(&sc->sc_mii));
1637: }
1638:
1639: void
1640: cas_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
1641: {
1642: struct cas_softc *sc = ifp->if_softc;
1643:
1644: mii_pollstat(&sc->sc_mii);
1645: ifmr->ifm_active = sc->sc_mii.mii_media_active;
1646: ifmr->ifm_status = sc->sc_mii.mii_media_status;
1647: }
1648:
1649: /*
1650: * Process an ioctl request.
1651: */
1652: int
1653: cas_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1654: {
1655: struct cas_softc *sc = ifp->if_softc;
1656: struct ifaddr *ifa = (struct ifaddr *)data;
1657: struct ifreq *ifr = (struct ifreq *)data;
1658: int s, error = 0;
1659:
1660: s = splnet();
1661:
1662: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
1663: splx(s);
1664: return (error);
1665: }
1666:
1667: switch (cmd) {
1668:
1669: case SIOCSIFADDR:
1670: ifp->if_flags |= IFF_UP;
1671: if ((ifp->if_flags & IFF_RUNNING) == 0)
1672: cas_init(ifp);
1673: #ifdef INET
1674: if (ifa->ifa_addr->sa_family == AF_INET)
1675: arp_ifinit(&sc->sc_arpcom, ifa);
1676: #endif
1677: break;
1678:
1679: case SIOCSIFFLAGS:
1680: if (ifp->if_flags & IFF_UP) {
1681: if ((ifp->if_flags & IFF_RUNNING) &&
1682: ((ifp->if_flags ^ sc->sc_if_flags) &
1683: (IFF_ALLMULTI | IFF_PROMISC)) != 0)
1684: cas_setladrf(sc);
1685: else {
1686: if ((ifp->if_flags & IFF_RUNNING) == 0)
1687: cas_init(ifp);
1688: }
1689: } else {
1690: if (ifp->if_flags & IFF_RUNNING)
1691: cas_stop(ifp, 1);
1692: }
1693: sc->sc_if_flags = ifp->if_flags;
1694:
1695: #ifdef CAS_DEBUG
1696: sc->sc_debug = (ifp->if_flags & IFF_DEBUG) != 0 ? 1 : 0;
1697: #endif
1698: break;
1699:
1700: case SIOCSIFMTU:
1701: if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
1702: error = EINVAL;
1703: } else if (ifp->if_mtu != ifr->ifr_mtu) {
1704: ifp->if_mtu = ifr->ifr_mtu;
1705: }
1706: break;
1707:
1708: case SIOCADDMULTI:
1709: case SIOCDELMULTI:
1710: error = (cmd == SIOCADDMULTI) ?
1711: ether_addmulti(ifr, &sc->sc_arpcom) :
1712: ether_delmulti(ifr, &sc->sc_arpcom);
1713:
1714: if (error == ENETRESET) {
1715: /*
1716: * Multicast list has changed; set the hardware filter
1717: * accordingly.
1718: */
1719: if (ifp->if_flags & IFF_RUNNING)
1720: cas_setladrf(sc);
1721: error = 0;
1722: }
1723: break;
1724:
1725: case SIOCGIFMEDIA:
1726: case SIOCSIFMEDIA:
1727: error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
1728: break;
1729:
1730: default:
1731: error = EINVAL;
1732: break;
1733: }
1734:
1735: splx(s);
1736: return (error);
1737: }
1738:
1739:
1740: void
1741: cas_shutdown(void *arg)
1742: {
1743: struct cas_softc *sc = (struct cas_softc *)arg;
1744: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1745:
1746: cas_stop(ifp, 1);
1747: }
1748:
1749: /*
1750: * Set up the logical address filter.
1751: */
1752: void
1753: cas_setladrf(struct cas_softc *sc)
1754: {
1755: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1756: struct ether_multi *enm;
1757: struct ether_multistep step;
1758: struct arpcom *ac = &sc->sc_arpcom;
1759: bus_space_tag_t t = sc->sc_memt;
1760: bus_space_handle_t h = sc->sc_memh;
1761: u_int32_t crc, hash[16], v;
1762: int i;
1763:
1764: /* Get current RX configuration */
1765: v = bus_space_read_4(t, h, CAS_MAC_RX_CONFIG);
1766:
1767:
1768: /*
1769: * Turn off promiscuous mode, promiscuous group mode (all multicast),
1770: * and hash filter. Depending on the case, the right bit will be
1771: * enabled.
1772: */
1773: v &= ~(CAS_MAC_RX_PROMISCUOUS|CAS_MAC_RX_HASH_FILTER|
1774: CAS_MAC_RX_PROMISC_GRP);
1775:
1776: if ((ifp->if_flags & IFF_PROMISC) != 0) {
1777: /* Turn on promiscuous mode */
1778: v |= CAS_MAC_RX_PROMISCUOUS;
1779: ifp->if_flags |= IFF_ALLMULTI;
1780: goto chipit;
1781: }
1782:
1783: /*
1784: * Set up multicast address filter by passing all multicast addresses
1785: * through a crc generator, and then using the high order 8 bits as an
1786: * index into the 256 bit logical address filter. The high order 4
1787: * bits selects the word, while the other 4 bits select the bit within
1788: * the word (where bit 0 is the MSB).
1789: */
1790:
1791: /* Clear hash table */
1792: for (i = 0; i < 16; i++)
1793: hash[i] = 0;
1794:
1795:
1796: ETHER_FIRST_MULTI(step, ac, enm);
1797: while (enm != NULL) {
1798: if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1799: /*
1800: * We must listen to a range of multicast addresses.
1801: * For now, just accept all multicasts, rather than
1802: * trying to set only those filter bits needed to match
1803: * the range. (At this time, the only use of address
1804: * ranges is for IP multicast routing, for which the
1805: * range is big enough to require all bits set.)
1806: * XXX use the addr filter for this
1807: */
1808: ifp->if_flags |= IFF_ALLMULTI;
1809: v |= CAS_MAC_RX_PROMISC_GRP;
1810: goto chipit;
1811: }
1812:
1813: crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
1814:
1815: /* Just want the 8 most significant bits. */
1816: crc >>= 24;
1817:
1818: /* Set the corresponding bit in the filter. */
1819: hash[crc >> 4] |= 1 << (15 - (crc & 15));
1820:
1821: ETHER_NEXT_MULTI(step, enm);
1822: }
1823:
1824: v |= CAS_MAC_RX_HASH_FILTER;
1825: ifp->if_flags &= ~IFF_ALLMULTI;
1826:
1827: /* Now load the hash table into the chip (if we are using it) */
1828: for (i = 0; i < 16; i++) {
1829: bus_space_write_4(t, h,
1830: CAS_MAC_HASH0 + i * (CAS_MAC_HASH1-CAS_MAC_HASH0),
1831: hash[i]);
1832: }
1833:
1834: chipit:
1835: bus_space_write_4(t, h, CAS_MAC_RX_CONFIG, v);
1836: }
1837:
1838: int
1839: cas_encap(struct cas_softc *sc, struct mbuf *mhead, u_int32_t *bixp)
1840: {
1841: u_int64_t flags;
1842: u_int32_t cur, frag, i;
1843: bus_dmamap_t map;
1844:
1845: cur = frag = *bixp;
1846: map = sc->sc_txd[cur].sd_map;
1847:
1848: if (bus_dmamap_load_mbuf(sc->sc_dmatag, map, mhead,
1849: BUS_DMA_NOWAIT) != 0) {
1850: return (ENOBUFS);
1851: }
1852:
1853: if ((sc->sc_tx_cnt + map->dm_nsegs) > (CAS_NTXDESC - 2)) {
1854: bus_dmamap_unload(sc->sc_dmatag, map);
1855: return (ENOBUFS);
1856: }
1857:
1858: bus_dmamap_sync(sc->sc_dmatag, map, 0, map->dm_mapsize,
1859: BUS_DMASYNC_PREWRITE);
1860:
1861: for (i = 0; i < map->dm_nsegs; i++) {
1862: sc->sc_txdescs[frag].cd_addr =
1863: CAS_DMA_WRITE(map->dm_segs[i].ds_addr);
1864: flags = (map->dm_segs[i].ds_len & CAS_TD_BUFSIZE) |
1865: (i == 0 ? CAS_TD_START_OF_PACKET : 0) |
1866: ((i == (map->dm_nsegs - 1)) ? CAS_TD_END_OF_PACKET : 0);
1867: sc->sc_txdescs[frag].cd_flags = CAS_DMA_WRITE(flags);
1868: bus_dmamap_sync(sc->sc_dmatag, sc->sc_cddmamap,
1869: CAS_CDTXOFF(frag), sizeof(struct cas_desc),
1870: BUS_DMASYNC_PREWRITE);
1871: cur = frag;
1872: if (++frag == CAS_NTXDESC)
1873: frag = 0;
1874: }
1875:
1876: sc->sc_tx_cnt += map->dm_nsegs;
1877: sc->sc_txd[*bixp].sd_map = sc->sc_txd[cur].sd_map;
1878: sc->sc_txd[cur].sd_map = map;
1879: sc->sc_txd[cur].sd_mbuf = mhead;
1880:
1881: bus_space_write_4(sc->sc_memt, sc->sc_memh, CAS_TX_KICK, frag);
1882:
1883: *bixp = frag;
1884:
1885: /* sync descriptors */
1886:
1887: return (0);
1888: }
1889:
1890: /*
1891: * Transmit interrupt.
1892: */
1893: int
1894: cas_tint(struct cas_softc *sc, u_int32_t status)
1895: {
1896: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1897: struct cas_sxd *sd;
1898: u_int32_t cons, hwcons;
1899:
1900: hwcons = status >> 19;
1901: cons = sc->sc_tx_cons;
1902: while (cons != hwcons) {
1903: sd = &sc->sc_txd[cons];
1904: if (sd->sd_mbuf != NULL) {
1905: bus_dmamap_sync(sc->sc_dmatag, sd->sd_map, 0,
1906: sd->sd_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1907: bus_dmamap_unload(sc->sc_dmatag, sd->sd_map);
1908: m_freem(sd->sd_mbuf);
1909: sd->sd_mbuf = NULL;
1910: }
1911: sc->sc_tx_cnt--;
1912: ifp->if_opackets++;
1913: if (++cons == CAS_NTXDESC)
1914: cons = 0;
1915: }
1916: sc->sc_tx_cons = cons;
1917:
1918: cas_start(ifp);
1919:
1920: if (sc->sc_tx_cnt == 0)
1921: ifp->if_timer = 0;
1922:
1923: return (1);
1924: }
1925:
1926: void
1927: cas_start(struct ifnet *ifp)
1928: {
1929: struct cas_softc *sc = ifp->if_softc;
1930: struct mbuf *m;
1931: u_int32_t bix;
1932:
1933: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
1934: return;
1935:
1936: bix = sc->sc_tx_prod;
1937: while (sc->sc_txd[bix].sd_mbuf == NULL) {
1938: IFQ_POLL(&ifp->if_snd, m);
1939: if (m == NULL)
1940: break;
1941:
1942: #if NBPFILTER > 0
1943: /*
1944: * If BPF is listening on this interface, let it see the
1945: * packet before we commit it to the wire.
1946: */
1947: if (ifp->if_bpf)
1948: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
1949: #endif
1950:
1951: /*
1952: * Encapsulate this packet and start it going...
1953: * or fail...
1954: */
1955: if (cas_encap(sc, m, &bix)) {
1956: ifp->if_timer = 2;
1957: break;
1958: }
1959:
1960: IFQ_DEQUEUE(&ifp->if_snd, m);
1961: ifp->if_timer = 5;
1962: }
1963:
1964: sc->sc_tx_prod = bix;
1965: }
CVSweb