Annotation of sys/dev/pci/if_myx.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_myx.c,v 1.5 2007/06/01 18:07:08 reyk Exp $ */
2:
3: /*
4: * Copyright (c) 2007 Reyk Floeter <reyk@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: /*
20: * Driver for the Myricom Myri-10G Lanai-Z8E Ethernet chipsets.
21: */
22:
23: #include "bpfilter.h"
24:
25: #include <sys/param.h>
26: #include <sys/systm.h>
27: #include <sys/sockio.h>
28: #include <sys/mbuf.h>
29: #include <sys/kernel.h>
30: #include <sys/socket.h>
31: #include <sys/malloc.h>
32: #include <sys/timeout.h>
33: #include <sys/proc.h>
34: #include <sys/device.h>
35: #include <sys/sensors.h>
36:
37: #include <machine/bus.h>
38: #include <machine/intr.h>
39:
40: #include <net/if.h>
41: #include <net/if_dl.h>
42: #include <net/if_media.h>
43: #include <net/if_types.h>
44:
45: #if NBPFILTER > 0
46: #include <net/bpf.h>
47: #endif
48:
49: #ifdef INET
50: #include <netinet/in.h>
51: #include <netinet/if_ether.h>
52: #endif
53:
54: #include <dev/pci/pcireg.h>
55: #include <dev/pci/pcivar.h>
56: #include <dev/pci/pcidevs.h>
57:
58: #include <dev/pci/if_myxreg.h>
59:
60: #define MYX_DEBUG
61: #ifdef MYX_DEBUG
62: #define MYXDBG_INIT (1<<0) /* chipset initialization */
63: #define MYXDBG_CMD (2<<0) /* commands */
64: #define MYXDBG_INTR (3<<0) /* interrupts */
65: #define MYXDBG_ALL 0xffff /* enable all debugging messages */
66: int myx_debug = MYXDBG_ALL;
67: #define DPRINTF(_lvl, _arg...) do { \
68: if (myx_debug & (_lvl)) \
69: printf(_arg); \
70: } while (0)
71: #else
72: #define DPRINTF(_lvl, arg...)
73: #endif
74:
75: #define DEVNAME(_s) ((_s)->_s##_dev.dv_xname)
76:
77: struct myx_dmamem {
78: bus_dmamap_t mxm_map;
79: bus_dma_segment_t mxm_seg;
80: int mxm_nsegs;
81: size_t mxm_size;
82: caddr_t mxm_kva;
83: const char *mxm_name;
84: };
85:
86: struct myx_buf {
87: bus_dmamap_t mb_dmamap;
88: struct mbuf *mb_m;
89: };
90:
91: struct myx_softc {
92: struct device sc_dev;
93: struct arpcom sc_ac;
94:
95: pci_chipset_tag_t sc_pc;
96: pcitag_t sc_tag;
97: u_int sc_function;
98:
99: bus_dma_tag_t sc_dmat;
100: bus_space_tag_t sc_memt;
101: bus_space_handle_t sc_memh;
102: bus_size_t sc_mems;
103:
104: struct myx_dmamem sc_cmddma;
105: struct myx_dmamem sc_paddma;
106:
107: struct myx_dmamem sc_stsdma;
108: struct myx_status *sc_sts;
109:
110: struct myx_dmamem sc_rxdma;
111: struct myx_rxdesc *sc_rxdesc;
112: struct myx_rxbufdesc *sc_rxbufdesc[2];
113: struct myx_buf *sc_rxbuf[2];
114: #define MYX_RXSMALL 0
115: #define MYX_RXBIG 1
116: int sc_rxactive;
117: int sc_rxidx;
118:
119: void *sc_irqh;
120: u_int32_t sc_irqcoaloff;
121: u_int32_t sc_irqclaimoff;
122: u_int32_t sc_irqdeassertoff;
123:
124: u_int8_t sc_lladdr[ETHER_ADDR_LEN];
125: struct ifmedia sc_media;
126:
127: u_int32_t sc_rxringsize;
128: u_int32_t sc_rxsmallringoff;
129: u_int32_t sc_rxbigringoff;
130: int sc_rxndesc;
131: size_t sc_rxdescsize;
132: size_t sc_rxbufsize;
133: size_t sc_rxbufdescsize;
134: u_int32_t sc_txringsize;
135: u_int32_t sc_txringoff;
136: int sc_txndesc;
137:
138: u_int sc_phy; /* PHY type (CX4/SR/LR) */
139: u_int sc_hwflags;
140: #define MYXFLAG_FLOW_CONTROL (1<<0) /* Rx/Tx pause is enabled */
141: #define MYXFLAG_PROMISC (1<<1) /* promisc mode is enabled */
142: #define MYXFLAG_ALLMULTI (1<<2) /* allmulti is set */
143: u_int8_t sc_active;
144:
145: struct timeout sc_tick;
146: };
147:
148: int myx_match(struct device *, void *, void *);
149: void myx_attach(struct device *, struct device *, void *);
150: int myx_query(struct myx_softc *sc);
151: u_int myx_ether_aton(char *, u_int8_t *, u_int);
152: int myx_loadfirmware(struct myx_softc *, u_int8_t *, size_t,
153: u_int32_t, int);
154: void myx_attachhook(void *);
155: void myx_read(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
156: void myx_rawread(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
157: void myx_write(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
158: void myx_rawwrite(struct myx_softc *, bus_size_t, u_int8_t *, bus_size_t);
159: int myx_cmd(struct myx_softc *, u_int32_t, struct myx_cmd *, u_int32_t *);
160: int myx_boot(struct myx_softc *, u_int32_t, struct myx_bootcmd *);
161: int myx_rdma(struct myx_softc *, u_int);
162: int myx_reset(struct myx_softc *);
163: int myx_dmamem_alloc(struct myx_softc *, struct myx_dmamem *,
164: bus_size_t, u_int align, const char *);
165: void myx_dmamem_free(struct myx_softc *, struct myx_dmamem *);
166: int myx_media_change(struct ifnet *);
167: void myx_media_status(struct ifnet *, struct ifmediareq *);
168: void myx_link_state(struct myx_softc *);
169: void myx_watchdog(struct ifnet *);
170: void myx_tick(void *);
171: int myx_ioctl(struct ifnet *, u_long, caddr_t);
172: void myx_iff(struct myx_softc *);
173: void myx_init(struct ifnet *);
174: void myx_start(struct ifnet *);
175: void myx_stop(struct ifnet *);
176: int myx_setlladdr(struct myx_softc *, u_int8_t *);
177: int myx_intr(void *);
178: int myx_init_rings(struct myx_softc *);
179: void myx_free_rings(struct myx_softc *);
180: struct mbuf *myx_getbuf(struct myx_softc *, bus_dmamap_t, int);
181:
182: struct cfdriver myx_cd = {
183: 0, "myx", DV_IFNET
184: };
185: struct cfattach myx_ca = {
186: sizeof(struct myx_softc), myx_match, myx_attach
187: };
188:
189: const struct pci_matchid myx_devices[] = {
190: { PCI_VENDOR_MYRICOM, PCI_PRODUCT_MYRICOM_Z8E }
191: };
192:
193: int
194: myx_match(struct device *parent, void *match, void *aux)
195: {
196: return (pci_matchbyid((struct pci_attach_args *)aux,
197: myx_devices, sizeof(myx_devices) / sizeof(myx_devices[0])));
198: }
199:
200: void
201: myx_attach(struct device *parent, struct device *self, void *aux)
202: {
203: struct myx_softc *sc = (struct myx_softc *)self;
204: struct pci_attach_args *pa = aux;
205: pci_intr_handle_t ih;
206: pcireg_t memtype;
207: const char *intrstr;
208: struct ifnet *ifp;
209:
210: sc->sc_pc = pa->pa_pc;
211: sc->sc_tag = pa->pa_tag;
212: sc->sc_dmat = pa->pa_dmat;
213: sc->sc_function = pa->pa_function;
214:
215: memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, MYXBAR0);
216: switch (memtype) {
217: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
218: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
219: break;
220: default:
221: printf(": invalid memory type: 0x%x\n", memtype);
222: return;
223: }
224:
225: /* Map the PCI memory space */
226: if (pci_mapreg_map(pa, MYXBAR0, memtype, 0, &sc->sc_memt,
227: &sc->sc_memh, NULL, &sc->sc_mems, 0) != 0) {
228: printf(": unable to map register memory\n");
229: return;
230: }
231:
232: /* Get the board information and initialize the h/w */
233: if (myx_query(sc) != 0)
234: goto unmap;
235:
236: /*
237: * Allocate command DMA memory
238: */
239: if (myx_dmamem_alloc(sc, &sc->sc_cmddma, MYXALIGN_CMD,
240: MYXALIGN_CMD, "cmd") != 0) {
241: printf(": failed to allocate command DMA memory\n");
242: goto unmap;
243: }
244:
245: if (myx_dmamem_alloc(sc, &sc->sc_paddma,
246: MYXALIGN_CMD, MYXALIGN_CMD, "pad") != 0) {
247: printf(": failed to allocate pad DMA memory\n");
248: goto err2;
249: }
250:
251: if (myx_dmamem_alloc(sc, &sc->sc_stsdma,
252: sizeof(struct myx_status), MYXALIGN_DATA /* XXX */, "status") != 0) {
253: printf(": failed to allocate status DMA memory\n");
254: goto err1;
255: }
256: sc->sc_sts = (struct myx_status *)sc->sc_stsdma.mxm_kva;
257:
258: /*
259: * Map and establish the interrupt
260: */
261: if (pci_intr_map(pa, &ih) != 0) {
262: printf(": unable to map interrupt\n");
263: goto err;
264: }
265: intrstr = pci_intr_string(pa->pa_pc, ih);
266: sc->sc_irqh = pci_intr_establish(pa->pa_pc, ih, IPL_NET,
267: myx_intr, sc, DEVNAME(sc));
268: if (sc->sc_irqh == NULL) {
269: printf(": unable to establish interrupt %s\n", intrstr);
270: goto err;
271: }
272: printf(": %s, address %s\n", intrstr,
273: ether_sprintf(sc->sc_ac.ac_enaddr));
274:
275: ifp = &sc->sc_ac.ac_if;
276: ifp->if_softc = sc;
277: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
278: ifp->if_ioctl = myx_ioctl;
279: ifp->if_start = myx_start;
280: ifp->if_watchdog = myx_watchdog;
281: strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
282: IFQ_SET_MAXLEN(&ifp->if_snd, MYX_NTXDESC_MIN - 1);
283: IFQ_SET_READY(&ifp->if_snd);
284:
285: ifp->if_capabilities = IFCAP_VLAN_MTU;
286: #if 0
287: ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
288: ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
289: IFCAP_CSUM_UDPv4;
290: #endif
291: ifp->if_baudrate = ULONG_MAX; /* XXX fix if_baudrate */
292:
293: ifmedia_init(&sc->sc_media, 0,
294: myx_media_change, myx_media_status);
295: ifmedia_add(&sc->sc_media, IFM_ETHER|sc->sc_phy, 0, NULL);
296: ifmedia_set(&sc->sc_media, IFM_ETHER|sc->sc_phy);
297:
298: if_attach(ifp);
299: ether_ifattach(ifp);
300:
301: timeout_set(&sc->sc_tick, myx_tick, sc);
302: timeout_add(&sc->sc_tick, hz);
303:
304: mountroothook_establish(myx_attachhook, sc);
305:
306: return;
307:
308: err:
309: myx_dmamem_free(sc, &sc->sc_stsdma);
310: err1:
311: myx_dmamem_free(sc, &sc->sc_paddma);
312: err2:
313: myx_dmamem_free(sc, &sc->sc_cmddma);
314: unmap:
315: bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
316: sc->sc_mems = 0;
317: }
318:
319: u_int
320: myx_ether_aton(char *mac, u_int8_t *lladdr, u_int maxlen)
321: {
322: u_int i, j;
323: u_int8_t digit;
324:
325: bzero(lladdr, ETHER_ADDR_LEN);
326: for (i = j = 0; mac[i] != '\0' && i < maxlen; i++) {
327: if (mac[i] >= '0' && mac[i] <= '9')
328: digit = mac[i] - '0';
329: else if (mac[i] >= 'A' && mac[i] <= 'F')
330: digit = mac[i] - 'A' + 10;
331: else if (mac[i] >= 'a' && mac[i] <= 'f')
332: digit = mac[i] - 'a' + 10;
333: else
334: continue;
335: if ((j & 1) == 0)
336: digit <<= 4;
337: lladdr[j++/2] |= digit;
338: }
339:
340: return (i);
341: }
342:
343: int
344: myx_query(struct myx_softc *sc)
345: {
346: u_int8_t eeprom[MYX_EEPROM_SIZE];
347: u_int i, maxlen;
348:
349: myx_read(sc, MYX_EEPROM, eeprom, MYX_EEPROM_SIZE);
350:
351: for (i = 0; i < MYX_EEPROM_SIZE; i++) {
352: maxlen = MYX_EEPROM_SIZE - i;
353: if (eeprom[i] == '\0')
354: break;
355: if (maxlen > 4 && bcmp("MAC=", &eeprom[i], 4) == 0) {
356: i += 4;
357: i += myx_ether_aton(&eeprom[i],
358: sc->sc_ac.ac_enaddr, maxlen);
359: }
360: for (; i < MYX_EEPROM_SIZE; i++)
361: if (eeprom[i] == '\0')
362: break;
363: }
364:
365: return (0);
366: }
367:
368: int
369: myx_loadfirmware(struct myx_softc *sc, u_int8_t *fw, size_t fwlen,
370: u_int32_t fwhdroff, int reload)
371: {
372: struct myx_firmware_hdr *fwhdr;
373: u_int i, len, ret = 0;
374:
375: fwhdr = (struct myx_firmware_hdr *)(fw + fwhdroff);
376: DPRINTF(MYXDBG_INIT, "%s(%s): "
377: "fw hdr off %d, length %d, type 0x%x, version %s\n",
378: DEVNAME(sc), __func__,
379: fwhdroff, betoh32(fwhdr->fw_hdrlength),
380: betoh32(fwhdr->fw_type),
381: fwhdr->fw_version);
382:
383: if (betoh32(fwhdr->fw_type) != MYXFW_TYPE_ETH ||
384: bcmp(MYXFW_VER, fwhdr->fw_version, strlen(MYXFW_VER)) != 0) {
385: if (reload)
386: printf("%s: invalid firmware type 0x%x version %s\n",
387: DEVNAME(sc), betoh32(fwhdr->fw_type),
388: fwhdr->fw_version);
389: ret = 1;
390: goto done;
391: }
392:
393: if (!reload)
394: goto done;
395:
396: /* Write the firmware to the card's SRAM */
397: for (i = 0; i < fwlen; i += 256) {
398: len = min(256, fwlen - i);
399: myx_rawwrite(sc, i + MYX_FW, fw + i, min(256, fwlen - i));
400: }
401:
402: done:
403: free(fw, M_DEVBUF);
404: return (ret);
405: }
406:
407: void
408: myx_attachhook(void *arg)
409: {
410: struct myx_softc *sc = (struct myx_softc *)arg;
411: size_t fwlen;
412: u_int8_t *fw = NULL;
413: u_int32_t fwhdroff;
414: struct myx_bootcmd bc;
415:
416: /*
417: * First try the firmware found in the SRAM
418: */
419: myx_read(sc, MYX_HEADER_POS, (u_int8_t *)&fwhdroff, sizeof(fwhdroff));
420: fwhdroff = betoh32(fwhdroff);
421: fwlen = sizeof(struct myx_firmware_hdr);
422: if ((fwhdroff + fwlen) > MYX_SRAM_SIZE)
423: goto load;
424:
425: fw = malloc(fwlen, M_DEVBUF, M_WAIT);
426: myx_rawread(sc, MYX_HEADER_POS, fw, fwlen);
427:
428: if (myx_loadfirmware(sc, fw, fwlen, fwhdroff, 0) == 0)
429: goto boot;
430:
431: load:
432: /*
433: * Now try the firmware stored on disk
434: */
435: if (loadfirmware(MYXFW_ALIGNED /* XXX */, &fw, &fwlen) != 0) {
436: printf("%s: could not load firmware\n", DEVNAME(sc));
437: return;
438: }
439: if (fwlen > MYX_SRAM_SIZE || fwlen < MYXFW_MIN_LEN) {
440: printf("%s: invalid firmware image size\n", DEVNAME(sc));
441: goto err;
442: }
443:
444: bcopy(fw + MYX_HEADER_POS, &fwhdroff, sizeof(fwhdroff));
445: fwhdroff = betoh32(fwhdroff);
446: if ((fwhdroff + sizeof(struct myx_firmware_hdr)) > fwlen) {
447: printf("%s: invalid firmware image\n", DEVNAME(sc));
448: goto err;
449: }
450:
451: if (myx_loadfirmware(sc, fw, fwlen, fwhdroff, 1) != 0) {
452: fw = NULL;
453: goto err;
454: }
455: fw = NULL;
456:
457: boot:
458: bzero(&bc, sizeof(bc));
459: if (myx_boot(sc, fwlen, &bc) != 0) {
460: printf("%s: failed to bootstrap the device\n", DEVNAME(sc));
461: goto err;
462: }
463: if (myx_reset(sc) != 0)
464: goto err;
465:
466: sc->sc_active = 1;
467: return;
468:
469: err:
470: if (fw != NULL)
471: free(fw, M_DEVBUF);
472: }
473:
474: void
475: myx_read(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr, bus_size_t len)
476: {
477: bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
478: BUS_SPACE_BARRIER_READ);
479: bus_space_read_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len / 4);
480: }
481:
482: void
483: myx_rawread(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr,
484: bus_size_t len)
485: {
486: bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
487: BUS_SPACE_BARRIER_READ);
488: bus_space_read_raw_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len);
489: }
490:
491: void
492: myx_write(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr, bus_size_t len)
493: {
494: bus_space_write_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len / 4);
495: bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
496: BUS_SPACE_BARRIER_WRITE);
497: }
498:
499: void
500: myx_rawwrite(struct myx_softc *sc, bus_size_t off, u_int8_t *ptr,
501: bus_size_t len)
502: {
503: bus_space_write_raw_region_4(sc->sc_memt, sc->sc_memh, off, ptr, len);
504: bus_space_barrier(sc->sc_memt, sc->sc_memh, off, len,
505: BUS_SPACE_BARRIER_WRITE);
506: }
507:
508: int
509: myx_dmamem_alloc(struct myx_softc *sc, struct myx_dmamem *mxm,
510: bus_size_t size, u_int align, const char *mname)
511: {
512: mxm->mxm_size = size;
513:
514: if (bus_dmamap_create(sc->sc_dmat, mxm->mxm_size, 1,
515: mxm->mxm_size, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
516: &mxm->mxm_map) != 0)
517: return (1);
518: if (bus_dmamem_alloc(sc->sc_dmat, mxm->mxm_size,
519: align, 0, &mxm->mxm_seg, 1, &mxm->mxm_nsegs,
520: BUS_DMA_WAITOK) != 0)
521: goto destroy;
522: if (bus_dmamem_map(sc->sc_dmat, &mxm->mxm_seg, mxm->mxm_nsegs,
523: mxm->mxm_size, &mxm->mxm_kva, BUS_DMA_WAITOK) != 0)
524: goto free;
525: if (bus_dmamap_load(sc->sc_dmat, mxm->mxm_map, mxm->mxm_kva,
526: mxm->mxm_size, NULL, BUS_DMA_WAITOK) != 0)
527: goto unmap;
528:
529: bzero(mxm->mxm_kva, mxm->mxm_size);
530: mxm->mxm_name = mname;
531:
532: return (0);
533: unmap:
534: bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size);
535: free:
536: bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1);
537: destroy:
538: bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map);
539: return (1);
540: }
541:
542: void
543: myx_dmamem_free(struct myx_softc *sc, struct myx_dmamem *mxm)
544: {
545: bus_dmamap_unload(sc->sc_dmat, mxm->mxm_map);
546: bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size);
547: bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1);
548: bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map);
549: }
550:
551: int
552: myx_cmd(struct myx_softc *sc, u_int32_t cmd, struct myx_cmd *mc, u_int32_t *r)
553: {
554: bus_dmamap_t map = sc->sc_cmddma.mxm_map;
555: struct myx_response *mr;
556: u_int i;
557: u_int32_t result, data;
558: #ifdef MYX_DEBUG
559: static const char *cmds[MYXCMD_MAX] = {
560: "CMD_NONE",
561: "CMD_RESET",
562: "CMD_GET_VERSION",
563: "CMD_SET_INTRQDMA",
564: "CMD_SET_BIGBUFSZ",
565: "CMD_SET_SMALLBUFSZ",
566: "CMD_GET_TXRINGOFF",
567: "CMD_GET_RXSMALLRINGOFF",
568: "CMD_GET_RXBIGRINGOFF",
569: "CMD_GET_INTRACKOFF",
570: "CMD_GET_INTRDEASSERTOFF",
571: "CMD_GET_TXRINGSZ",
572: "CMD_GET_RXRINGSZ",
573: "CMD_SET_INTRQSZ",
574: "CMD_SET_IFUP",
575: "CMD_SET_IFDOWN",
576: "CMD_SET_MTU",
577: "CMD_GET_INTRCOALDELAYOFF",
578: "CMD_SET_STATSINTVL",
579: "CMD_SET_STATSDMA_OLD",
580: "CMD_SET_PROMISC",
581: "CMD_UNSET_PROMISC",
582: "CMD_SET_LLADDR",
583: "CMD_SET_FC",
584: "CMD_UNSET_FC",
585: "CMD_DMA_TEST",
586: "CMD_SET_ALLMULTI",
587: "CMD_UNSET_ALLMULTI",
588: "CMD_SET_MCASTGROUP",
589: "CMD_UNSET_MCASTGROUP",
590: "CMD_UNSET_MCAST",
591: "CMD_SET_STATSDMA",
592: "CMD_UNALIGNED_DMA_TEST",
593: "CMD_GET_UNALIGNED_STATUS"
594: };
595: #endif
596:
597: mc->mc_cmd = htobe32(cmd);
598: mc->mc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
599: mc->mc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr));
600:
601: mr = (struct myx_response *)sc->sc_cmddma.mxm_kva;
602: mr->mr_result = 0xffffffff;
603:
604: /* Send command */
605: myx_write(sc, MYX_CMD, (u_int8_t *)mc, sizeof(struct myx_cmd));
606:
607: for (i = 0; i < 20; i++) {
608: bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
609: BUS_DMASYNC_POSTREAD);
610: result = betoh32(mr->mr_result);
611: data = betoh32(mr->mr_data);
612:
613: if (result != 0xffffffff)
614: break;
615: delay(1000);
616: }
617:
618: DPRINTF(MYXDBG_CMD, "%s(%s): %s completed, i %d, "
619: "result 0x%x, data 0x%x (%u)\n", DEVNAME(sc), __func__,
620: cmds[cmd], i, result, data, data);
621:
622: if (result != 0)
623: return (-1);
624:
625: if (r != NULL)
626: *r = data;
627: return (0);
628: }
629:
630: int
631: myx_boot(struct myx_softc *sc, u_int32_t length, struct myx_bootcmd *bc)
632: {
633: bus_dmamap_t map = sc->sc_cmddma.mxm_map;
634: u_int32_t *status;
635: u_int i;
636:
637: bc->bc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
638: bc->bc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr));
639: bc->bc_result = 0xffffffff;
640: bc->bc_offset = htobe32(MYX_FW_BOOT);
641: bc->bc_length = htobe32(length);
642: bc->bc_copyto = htobe32(8);
643: bc->bc_jumpto = htobe32(0);
644:
645: status = (u_int32_t *)sc->sc_cmddma.mxm_kva;
646: *status = 0;
647:
648: /* Send command */
649: myx_write(sc, MYX_BOOT, (u_int8_t *)bc, sizeof(struct myx_bootcmd));
650:
651: for (i = 0; i < 200; i++) {
652: bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
653: BUS_DMASYNC_POSTREAD);
654: if (*status == 0xffffffff)
655: break;
656: delay(1000);
657: }
658:
659: DPRINTF(MYXDBG_CMD, "%s(%s): boot completed, i %d, result 0x%x\n",
660: DEVNAME(sc), __func__, i, betoh32(*status));
661:
662: if (*status != 0xffffffff)
663: return (-1);
664:
665: return (0);
666: }
667:
668: int
669: myx_rdma(struct myx_softc *sc, u_int do_enable)
670: {
671: struct myx_rdmacmd rc;
672: bus_dmamap_t map = sc->sc_cmddma.mxm_map;
673: bus_dmamap_t pad = sc->sc_paddma.mxm_map;
674: u_int32_t *status;
675: u_int i;
676:
677: /*
678: * It is required to setup a _dummy_ RDMA address. It also makes
679: * some PCI-E chipsets resend dropped messages.
680: */
681: rc.rc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
682: rc.rc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr));
683: rc.rc_result = 0xffffffff;
684: rc.rc_rdma_high = htobe32(MYX_ADDRHIGH(pad->dm_segs[0].ds_addr));
685: rc.rc_rdma_low = htobe32(MYX_ADDRLOW(pad->dm_segs[0].ds_addr));
686: rc.rc_enable = htobe32(do_enable);
687:
688: status = (u_int32_t *)sc->sc_cmddma.mxm_kva;
689: *status = 0;
690:
691: /* Send command */
692: myx_write(sc, MYX_RDMA, (u_int8_t *)&rc, sizeof(struct myx_rdmacmd));
693:
694: for (i = 0; i < 20; i++) {
695: bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
696: BUS_DMASYNC_POSTREAD);
697: if (*status == 0xffffffff)
698: break;
699: delay(1000);
700: }
701:
702: DPRINTF(MYXDBG_CMD, "%s(%s): dummy RDMA %s, i %d, result 0x%x\n",
703: DEVNAME(sc), __func__,
704: do_enable ? "enabled" : "disabled", i, betoh32(*status));
705:
706: if (*status != 0xffffffff)
707: return (-1);
708:
709: return (0);
710: }
711:
712: int
713: myx_reset(struct myx_softc *sc)
714: {
715: struct myx_cmd mc;
716: u_int32_t data;
717: struct ifnet *ifp = &sc->sc_ac.ac_if;
718:
719: bzero(&mc, sizeof(mc));
720: if (myx_cmd(sc, MYXCMD_RESET, &mc, NULL) != 0) {
721: printf("%s: failed to reset the device\n", DEVNAME(sc));
722: return (-1);
723: }
724:
725: if (myx_rdma(sc, MYXRDMA_ON) != 0) {
726: printf("%s: failed to enable dummy RDMA\n", DEVNAME(sc));
727: return (-1);
728: }
729:
730: if (myx_cmd(sc, MYXCMD_GET_INTRCOALDELAYOFF, &mc,
731: &sc->sc_irqcoaloff) != 0) {
732: printf("%s: failed to get IRQ coal offset\n", DEVNAME(sc));
733: return (-1);
734: }
735: data = htobe32(MYX_IRQCOALDELAY);
736: myx_write(sc, sc->sc_irqcoaloff, (u_int8_t *)&data, sizeof(data));
737:
738: if (myx_cmd(sc, MYXCMD_GET_INTRACKOFF, &mc,
739: &sc->sc_irqclaimoff) != 0) {
740: printf("%s: failed to get IRQ ack offset\n", DEVNAME(sc));
741: return (-1);
742: }
743:
744: if (myx_cmd(sc, MYXCMD_GET_INTRDEASSERTOFF, &mc,
745: &sc->sc_irqdeassertoff) != 0) {
746: printf("%s: failed to get IRQ deassert offset\n", DEVNAME(sc));
747: return (-1);
748: }
749:
750: if (myx_cmd(sc, MYXCMD_UNSET_PROMISC, &mc, NULL) != 0) {
751: printf("%s: failed to disable promisc mode\n", DEVNAME(sc));
752: return (-1);
753: }
754:
755: if (myx_cmd(sc, MYXCMD_FC_DEFAULT, &mc, NULL) != 0) {
756: printf("%s: failed to configure flow control\n", DEVNAME(sc));
757: return (-1);
758: }
759:
760: if (myx_setlladdr(sc, LLADDR(ifp->if_sadl)) != 0)
761: return (-1);
762:
763: return (0);
764: }
765:
766:
767: int
768: myx_media_change(struct ifnet *ifp)
769: {
770: return (EINVAL);
771: }
772:
773: void
774: myx_media_status(struct ifnet *ifp, struct ifmediareq *imr)
775: {
776: struct myx_softc *sc = (struct myx_softc *)ifp->if_softc;
777:
778: imr->ifm_active = IFM_ETHER|sc->sc_phy;
779: imr->ifm_status = IFM_AVALID;
780: myx_link_state(sc);
781: if (!LINK_STATE_IS_UP(ifp->if_link_state))
782: return;
783: imr->ifm_active |= IFM_FDX;
784: imr->ifm_status |= IFM_ACTIVE;
785:
786: /* Flow control */
787: if (sc->sc_hwflags & MYXFLAG_FLOW_CONTROL)
788: imr->ifm_active |= IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE;
789: }
790:
791: void
792: myx_link_state(struct myx_softc *sc)
793: {
794: struct ifnet *ifp = &sc->sc_ac.ac_if;
795: int link_state = LINK_STATE_DOWN;
796:
797: if (sc->sc_sts == NULL)
798: return;
799: if (sc->sc_sts->ms_linkstate == MYXSTS_LINKUP)
800: link_state = LINK_STATE_FULL_DUPLEX;
801: if (ifp->if_link_state != link_state) {
802: ifp->if_link_state = link_state;
803: if_link_state_change(ifp);
804: }
805: }
806:
807: void
808: myx_watchdog(struct ifnet *ifp)
809: {
810: return;
811: }
812:
813: void
814: myx_tick(void *arg)
815: {
816: struct myx_softc *sc = (struct myx_softc *)arg;
817:
818: if (!sc->sc_active)
819: return;
820:
821: myx_link_state(sc);
822: timeout_add(&sc->sc_tick, hz);
823: }
824:
825: int
826: myx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
827: {
828: struct myx_softc *sc = (struct myx_softc *)ifp->if_softc;
829: struct ifaddr *ifa = (struct ifaddr *)data;
830: struct ifreq *ifr = (struct ifreq *)data;
831: int s, error = 0;
832:
833: s = splnet();
834: if ((error = ether_ioctl(ifp, &sc->sc_ac, cmd, data)) > 0) {
835: splx(s);
836: return (error);
837: }
838:
839: switch (cmd) {
840: case SIOCSIFADDR:
841: ifp->if_flags |= IFF_UP;
842: #ifdef INET
843: if (ifa->ifa_addr->sa_family == AF_INET)
844: arp_ifinit(&sc->sc_ac, ifa);
845: #endif
846: /* FALLTHROUGH */
847: case SIOCSIFFLAGS:
848: if (ifp->if_flags & IFF_UP) {
849: if (ifp->if_flags & IFF_RUNNING)
850: myx_iff(sc);
851: else
852: myx_init(ifp);
853: } else {
854: if (ifp->if_flags & IFF_RUNNING)
855: myx_stop(ifp);
856: }
857: break;
858:
859: case SIOCSIFMTU:
860: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
861: error = EINVAL;
862: else if (ifp->if_mtu != ifr->ifr_mtu)
863: ifp->if_mtu = ifr->ifr_mtu;
864: break;
865:
866: case SIOCADDMULTI:
867: error = ether_addmulti(ifr, &sc->sc_ac);
868: break;
869:
870: case SIOCDELMULTI:
871: error = ether_delmulti(ifr, &sc->sc_ac);
872: break;
873:
874: case SIOCGIFMEDIA:
875: case SIOCSIFMEDIA:
876: error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
877: break;
878:
879: default:
880: error = ENOTTY;
881: }
882:
883: if (error == ENETRESET) {
884: if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
885: (IFF_UP | IFF_RUNNING))
886: myx_iff(sc);
887: error = 0;
888: }
889:
890: splx(s);
891:
892: return (error);
893: }
894:
895: void
896: myx_iff(struct myx_softc *sc)
897: {
898: /* XXX set multicast filters etc. */
899: return;
900: }
901:
902: void
903: myx_init(struct ifnet *ifp)
904: {
905: struct myx_softc *sc = (struct myx_softc *)ifp->if_softc;
906: struct myx_cmd mc;
907:
908: if (myx_reset(sc) != 0)
909: return;
910:
911: if (myx_init_rings(sc) != 0)
912: return;
913:
914: if (myx_cmd(sc, MYXCMD_SET_IFUP, &mc, NULL) != 0) {
915: printf("%s: failed to start the device\n", DEVNAME(sc));
916: myx_free_rings(sc);
917: return;
918: }
919:
920: ifp->if_flags |= IFF_RUNNING;
921: ifp->if_flags &= ~IFF_OACTIVE;
922: }
923:
924: void
925: myx_start(struct ifnet *ifp)
926: {
927: }
928:
929: void
930: myx_stop(struct ifnet *ifp)
931: {
932: struct myx_softc *sc = (struct myx_softc *)ifp->if_softc;
933: struct myx_cmd mc;
934:
935: bzero(&mc, sizeof(mc));
936: (void)myx_cmd(sc, MYXCMD_SET_IFDOWN, &mc, NULL);
937: myx_free_rings(sc);
938:
939: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
940: }
941:
942: int
943: myx_setlladdr(struct myx_softc *sc, u_int8_t *addr)
944: {
945: struct myx_cmd mc;
946:
947: bzero(&mc, sizeof(mc));
948: mc.mc_data0 = addr[3] | addr[2] << 8 | addr[1] << 16 | addr[0] << 24;
949: mc.mc_data1 = addr[5] | addr[4] << 8;
950: if (myx_cmd(sc, MYXCMD_SET_LLADDR, &mc, NULL) != 0) {
951: printf("%s: failed to set the lladdr\n", DEVNAME(sc));
952: return (-1);
953: }
954: return (0);
955: }
956:
957: int
958: myx_intr(void *arg)
959: {
960: struct myx_softc *sc = (struct myx_softc *)arg;
961: u_int32_t data, valid;
962: struct myx_status *sts = sc->sc_sts;
963: bus_dmamap_t map = sc->sc_stsdma.mxm_map;
964:
965: if (!sc->sc_active)
966: return (0);
967:
968: bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
969: BUS_DMASYNC_POSTWRITE);
970:
971: /*
972: * XXX The 'valid' flags should be set by the NIC, but it doesn't
973: * XXX work yet.
974: */
975: valid = sts->ms_isvalid;
976: if (!valid)
977: return (0);
978:
979: data = 0;
980: myx_write(sc, sc->sc_irqdeassertoff, (u_int8_t *)&data, sizeof(data));
981:
982: DPRINTF(MYXDBG_INTR, "%s(%s): interrupt, valid 0x%x\n",
983: DEVNAME(sc), __func__, valid);
984:
985: #ifdef MYX_DEBUG
986: #define DPRINT_STATUS(_n) \
987: DPRINTF(MYXDBG_INTR, "%s(%s): %s: %u, 0x%x\n", DEVNAME(sc), __func__,\
988: #_n, sts->_n, sts->_n)
989:
990: DPRINT_STATUS(ms_reserved);
991: DPRINT_STATUS(ms_dropped_pause);
992: DPRINT_STATUS(ms_dropped_unicast);
993: DPRINT_STATUS(ms_dropped_crc32err);
994: DPRINT_STATUS(ms_dropped_phyerr);
995: DPRINT_STATUS(ms_dropped_mcast);
996: DPRINT_STATUS(ms_txdonecnt);
997: DPRINT_STATUS(ms_linkstate);
998: DPRINT_STATUS(ms_dropped_linkoverflow);
999: DPRINT_STATUS(ms_dropped_linkerror);
1000: DPRINT_STATUS(ms_dropped_runt);
1001: DPRINT_STATUS(ms_dropped_overrun);
1002: DPRINT_STATUS(ms_dropped_smallbufunderrun);
1003: DPRINT_STATUS(ms_dropped_bigbufunderrun);
1004: DPRINT_STATUS(ms_rdmatags_available);
1005: DPRINT_STATUS(ms_txstopped);
1006: DPRINT_STATUS(ms_linkdowncnt);
1007: DPRINT_STATUS(ms_statusupdated);
1008: DPRINT_STATUS(ms_isvalid);
1009: #endif
1010:
1011: data = htobe32(3);
1012: if (sts->ms_isvalid)
1013: myx_write(sc, sc->sc_irqclaimoff, (u_int8_t *)&data,
1014: sizeof(data));
1015: myx_write(sc, sc->sc_irqclaimoff + sizeof(u_int32_t),
1016: (u_int8_t *)&data, sizeof(data));
1017:
1018: return (1);
1019: }
1020:
1021: int
1022: myx_init_rings(struct myx_softc *sc)
1023: {
1024: struct myx_cmd mc;
1025: struct ifnet *ifp = &sc->sc_ac.ac_if;
1026: bus_dmamap_t map;
1027: int i;
1028: struct myx_buf *mb;
1029: struct myx_rxbufdesc *rxb;
1030: u_int32_t data;
1031:
1032: bzero(&mc, sizeof(mc));
1033: if (!(myx_cmd(sc, MYXCMD_GET_RXRINGSZ, &mc,
1034: &sc->sc_rxringsize) == 0 && sc->sc_rxringsize &&
1035: myx_cmd(sc, MYXCMD_GET_RXSMALLRINGOFF, &mc,
1036: &sc->sc_rxsmallringoff) == 0 && sc->sc_rxsmallringoff &&
1037: myx_cmd(sc, MYXCMD_GET_RXBIGRINGOFF, &mc,
1038: &sc->sc_rxbigringoff) == 0 && sc->sc_rxbigringoff &&
1039: myx_cmd(sc, MYXCMD_GET_TXRINGSZ, &mc,
1040: &sc->sc_txringsize) == 0 && sc->sc_txringsize &&
1041: myx_cmd(sc, MYXCMD_GET_TXRINGOFF, &mc,
1042: &sc->sc_txringoff) == 0 && sc->sc_txringoff)) {
1043: printf("%s: failed to get ring sizes and offsets\n",
1044: DEVNAME(sc));
1045: return (-1);
1046: }
1047: sc->sc_rxndesc = sc->sc_rxringsize / sizeof(struct myx_rxbufdesc);
1048: sc->sc_txndesc = sc->sc_txringsize / sizeof(struct myx_txdesc);
1049: sc->sc_rxdescsize = sc->sc_rxndesc * 2 * sizeof(struct myx_rxdesc);
1050: sc->sc_rxbufsize = sc->sc_rxndesc * sizeof(struct myx_buf);
1051: sc->sc_rxbufdescsize = sc->sc_rxndesc * sizeof(struct myx_rxbufdesc);
1052: IFQ_SET_MAXLEN(&ifp->if_snd, sc->sc_txndesc - 1);
1053: IFQ_SET_READY(&ifp->if_snd);
1054:
1055: DPRINTF(MYXDBG_INIT, "%s(%s): Rx ring ndesc %u size %u bufsize %u, "
1056: "Tx ring ndesc %u size %u offset 0x%x\n", DEVNAME(sc), __func__,
1057: sc->sc_rxndesc, sc->sc_rxdescsize, sc->sc_rxringsize,
1058: sc->sc_txndesc, sc->sc_txringsize, sc->sc_txringoff);
1059:
1060: /*
1061: * Setup Rx DMA descriptors
1062: */
1063: if (myx_dmamem_alloc(sc, &sc->sc_rxdma,
1064: sc->sc_rxdescsize, MYXALIGN_DATA, "rxring") != 0) {
1065: printf(": failed to allocate Rx DMA memory\n");
1066: return (-1);
1067: }
1068: sc->sc_rxdesc = (struct myx_rxdesc *)sc->sc_rxdma.mxm_kva;
1069:
1070: bzero(&mc, sizeof(mc));
1071: mc.mc_data0 = htobe32(sc->sc_rxdescsize);
1072: if (myx_cmd(sc, MYXCMD_SET_INTRQSZ, &mc, NULL) != 0) {
1073: printf("%s: failed to set Rx DMA size\n", DEVNAME(sc));
1074: goto err;
1075: }
1076:
1077: map = sc->sc_rxdma.mxm_map;
1078: mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr);
1079: mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr);
1080: if (myx_cmd(sc, MYXCMD_SET_INTRQDMA, &mc, NULL) != 0) {
1081: printf("%s: failed to set Rx DMA address\n", DEVNAME(sc));
1082: goto err;
1083: }
1084:
1085: #ifdef notyet
1086: /*
1087: * XXX It fails to set the MTU and it always returns
1088: * XXX MYXCMD_ERR_RANGE.
1089: */
1090: bzero(&mc, sizeof(mc));
1091: mc.mc_data0 = ifp->if_mtu + ETHER_HDR_LEN + 4;
1092: if (myx_cmd(sc, MYXCMD_SET_MTU, &mc, NULL) != 0) {
1093: printf("%s: failed to set MTU size %d\n",
1094: DEVNAME(sc), ifp->if_mtu + ETHER_HDR_LEN + 4);
1095: goto err;
1096: }
1097: #endif
1098:
1099: /*
1100: * Setup Rx buffer descriptors
1101: */
1102: sc->sc_rxbuf[MYX_RXSMALL] = (struct myx_buf *)
1103: malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK);
1104: sc->sc_rxbufdesc[MYX_RXSMALL] = (struct myx_rxbufdesc *)
1105: malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK);
1106: sc->sc_rxbuf[MYX_RXBIG] = (struct myx_buf *)
1107: malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK);
1108: sc->sc_rxbufdesc[MYX_RXBIG] = (struct myx_rxbufdesc *)
1109: malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK);
1110: if (sc->sc_rxbuf[MYX_RXSMALL] == NULL ||
1111: sc->sc_rxbufdesc[MYX_RXSMALL] == NULL ||
1112: sc->sc_rxbuf[MYX_RXBIG] == NULL ||
1113: sc->sc_rxbufdesc[MYX_RXBIG] == NULL) {
1114: printf("%s: failed to allocate rx buffers\n", DEVNAME(sc));
1115: goto err;
1116: }
1117:
1118: for (i = 0; i < sc->sc_rxndesc; i++) {
1119: /*
1120: * Small Rx buffers and descriptors
1121: */
1122: mb = sc->sc_rxbuf[MYX_RXSMALL] + i;
1123: rxb = sc->sc_rxbufdesc[MYX_RXSMALL] + i;
1124:
1125: if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1126: MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) {
1127: printf("%s: unable to create dmamap for small rx %d\n",
1128: DEVNAME(sc), i);
1129: goto err;
1130: }
1131:
1132: map = mb->mb_dmamap;
1133: mb->mb_m = myx_getbuf(sc, map, 1);
1134: if (mb->mb_m == NULL) {
1135: bus_dmamap_destroy(sc->sc_dmat, map);
1136: goto err;
1137: }
1138:
1139: bus_dmamap_sync(sc->sc_dmat, map, 0,
1140: mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
1141:
1142: rxb->rb_addr_high =
1143: htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1144: rxb->rb_addr_low =
1145: htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1146:
1147: data = sc->sc_rxsmallringoff + i * sizeof(*rxb);
1148: myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb));
1149:
1150: /*
1151: * Big Rx buffers and descriptors
1152: */
1153: mb = sc->sc_rxbuf[MYX_RXBIG] + i;
1154: rxb = sc->sc_rxbufdesc[MYX_RXBIG] + i;
1155:
1156: if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1157: MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) {
1158: printf("%s: unable to create dmamap for big rx %d\n",
1159: DEVNAME(sc), i);
1160: goto err;
1161: }
1162:
1163: map = mb->mb_dmamap;
1164: mb->mb_m = myx_getbuf(sc, map, 1);
1165: if (mb->mb_m == NULL) {
1166: bus_dmamap_destroy(sc->sc_dmat, map);
1167: goto err;
1168: }
1169:
1170: bus_dmamap_sync(sc->sc_dmat, map, 0,
1171: mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD);
1172:
1173: rxb->rb_addr_high =
1174: htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1175: rxb->rb_addr_low =
1176: htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr));
1177:
1178: data = sc->sc_rxbigringoff + i * sizeof(*rxb);
1179: myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb));
1180: }
1181:
1182: bzero(&mc, sizeof(mc));
1183: mc.mc_data0 = MYX_MAX_MTU_SMALL;
1184: if (myx_cmd(sc, MYXCMD_SET_SMALLBUFSZ, &mc, NULL) != 0) {
1185: printf("%s: failed to set small buf size\n", DEVNAME(sc));
1186: goto err;
1187: }
1188:
1189: bzero(&mc, sizeof(mc));
1190: mc.mc_data0 = MCLBYTES;
1191: if (myx_cmd(sc, MYXCMD_SET_BIGBUFSZ, &mc, NULL) != 0) {
1192: printf("%s: failed to set big buf size\n", DEVNAME(sc));
1193: goto err;
1194: }
1195:
1196: /*
1197: * Setup status DMA
1198: */
1199: map = sc->sc_stsdma.mxm_map;
1200:
1201: bzero(&mc, sizeof(mc));
1202: mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr);
1203: mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr);
1204: mc.mc_data2 = sizeof(struct myx_status);
1205: if (myx_cmd(sc, MYXCMD_SET_STATSDMA, &mc, NULL) != 0) {
1206: printf("%s: failed to set status DMA offset\n", DEVNAME(sc));
1207: goto err;
1208: }
1209:
1210: bus_dmamap_sync(sc->sc_dmat, map, 0,
1211: map->dm_mapsize, BUS_DMASYNC_PREWRITE);
1212:
1213: return (0);
1214: err:
1215: myx_free_rings(sc);
1216: return (-1);
1217: }
1218:
1219: void
1220: myx_free_rings(struct myx_softc *sc)
1221: {
1222: if (sc->sc_rxbuf[MYX_RXSMALL] != NULL) {
1223: free(sc->sc_rxbuf[MYX_RXSMALL], M_DEVBUF);
1224: sc->sc_rxbuf[MYX_RXSMALL] = NULL;
1225: }
1226: if (sc->sc_rxbufdesc[MYX_RXSMALL] != NULL) {
1227: free(sc->sc_rxbufdesc[MYX_RXSMALL], M_DEVBUF);
1228: sc->sc_rxbufdesc[MYX_RXSMALL] = NULL;
1229: }
1230: if (sc->sc_rxbuf[MYX_RXBIG] != NULL) {
1231: free(sc->sc_rxbuf[MYX_RXBIG], M_DEVBUF);
1232: sc->sc_rxbuf[MYX_RXBIG] = NULL;
1233: }
1234: if (sc->sc_rxbufdesc[MYX_RXBIG] != NULL) {
1235: free(sc->sc_rxbufdesc[MYX_RXBIG], M_DEVBUF);
1236: sc->sc_rxbufdesc[MYX_RXBIG] = NULL;
1237: }
1238: if (sc->sc_rxdesc != NULL) {
1239: myx_dmamem_free(sc, &sc->sc_rxdma);
1240: sc->sc_rxdesc = NULL;
1241: }
1242: if (sc->sc_sts != NULL) {
1243: myx_dmamem_free(sc, &sc->sc_stsdma);
1244: sc->sc_sts = NULL;
1245: }
1246: return;
1247: }
1248:
1249: struct mbuf *
1250: myx_getbuf(struct myx_softc *sc, bus_dmamap_t map, int wait)
1251: {
1252: struct mbuf *m = NULL;
1253:
1254: MGETHDR(m, wait ? M_WAIT : M_DONTWAIT, MT_DATA);
1255: if (m == NULL)
1256: goto merr;
1257:
1258: MCLGET(m, wait ? M_WAIT : M_DONTWAIT);
1259: if ((m->m_flags & M_EXT) == 0)
1260: goto merr;
1261: m->m_len = m->m_pkthdr.len = MCLBYTES;
1262:
1263: if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m,
1264: wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) != 0) {
1265: printf("%s: could not load mbuf dma map\n", DEVNAME(sc));
1266: goto err;
1267: }
1268:
1269: return (m);
1270: merr:
1271: printf("%s: unable to allocate mbuf\n", DEVNAME(sc));
1272: err:
1273: if (m != NULL)
1274: m_freem(m);
1275: return (NULL);
1276: }
CVSweb