This source file includes following definitions.
- myx_match
- myx_attach
- myx_ether_aton
- myx_query
- myx_loadfirmware
- myx_attachhook
- myx_read
- myx_rawread
- myx_write
- myx_rawwrite
- myx_dmamem_alloc
- myx_dmamem_free
- myx_cmd
- myx_boot
- myx_rdma
- myx_reset
- myx_media_change
- myx_media_status
- myx_link_state
- myx_watchdog
- myx_tick
- myx_ioctl
- myx_iff
- myx_init
- myx_start
- myx_stop
- myx_setlladdr
- myx_intr
- myx_init_rings
- myx_free_rings
- myx_getbuf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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)
63 #define MYXDBG_CMD (2<<0)
64 #define MYXDBG_INTR (3<<0)
65 #define MYXDBG_ALL 0xffff
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;
139 u_int sc_hwflags;
140 #define MYXFLAG_FLOW_CONTROL (1<<0)
141 #define MYXFLAG_PROMISC (1<<1)
142 #define MYXFLAG_ALLMULTI (1<<2)
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
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
233 if (myx_query(sc) != 0)
234 goto unmap;
235
236
237
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 , "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
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;
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
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
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
434
435 if (loadfirmware(MYXFW_ALIGNED , &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
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
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
679
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
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
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
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
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
973
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
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
1088
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
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
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
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
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 }