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