if_myx.c revision 1.10
1/* $OpenBSD: if_myx.c,v 1.10 2008/11/28 02:44:18 brad 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 0, "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) != 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 bzero(mxm->mxm_kva, mxm->mxm_size); 521 mxm->mxm_name = mname; 522 523 return (0); 524 unmap: 525 bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size); 526 free: 527 bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1); 528 destroy: 529 bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map); 530 return (1); 531} 532 533void 534myx_dmamem_free(struct myx_softc *sc, struct myx_dmamem *mxm) 535{ 536 bus_dmamap_unload(sc->sc_dmat, mxm->mxm_map); 537 bus_dmamem_unmap(sc->sc_dmat, mxm->mxm_kva, mxm->mxm_size); 538 bus_dmamem_free(sc->sc_dmat, &mxm->mxm_seg, 1); 539 bus_dmamap_destroy(sc->sc_dmat, mxm->mxm_map); 540} 541 542int 543myx_cmd(struct myx_softc *sc, u_int32_t cmd, struct myx_cmd *mc, u_int32_t *r) 544{ 545 bus_dmamap_t map = sc->sc_cmddma.mxm_map; 546 struct myx_response *mr; 547 u_int i; 548 u_int32_t result, data; 549#ifdef MYX_DEBUG 550 static const char *cmds[MYXCMD_MAX] = { 551 "CMD_NONE", 552 "CMD_RESET", 553 "CMD_GET_VERSION", 554 "CMD_SET_INTRQDMA", 555 "CMD_SET_BIGBUFSZ", 556 "CMD_SET_SMALLBUFSZ", 557 "CMD_GET_TXRINGOFF", 558 "CMD_GET_RXSMALLRINGOFF", 559 "CMD_GET_RXBIGRINGOFF", 560 "CMD_GET_INTRACKOFF", 561 "CMD_GET_INTRDEASSERTOFF", 562 "CMD_GET_TXRINGSZ", 563 "CMD_GET_RXRINGSZ", 564 "CMD_SET_INTRQSZ", 565 "CMD_SET_IFUP", 566 "CMD_SET_IFDOWN", 567 "CMD_SET_MTU", 568 "CMD_GET_INTRCOALDELAYOFF", 569 "CMD_SET_STATSINTVL", 570 "CMD_SET_STATSDMA_OLD", 571 "CMD_SET_PROMISC", 572 "CMD_UNSET_PROMISC", 573 "CMD_SET_LLADDR", 574 "CMD_SET_FC", 575 "CMD_UNSET_FC", 576 "CMD_DMA_TEST", 577 "CMD_SET_ALLMULTI", 578 "CMD_UNSET_ALLMULTI", 579 "CMD_SET_MCASTGROUP", 580 "CMD_UNSET_MCASTGROUP", 581 "CMD_UNSET_MCAST", 582 "CMD_SET_STATSDMA", 583 "CMD_UNALIGNED_DMA_TEST", 584 "CMD_GET_UNALIGNED_STATUS" 585 }; 586#endif 587 588 mc->mc_cmd = htobe32(cmd); 589 mc->mc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 590 mc->mc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 591 592 mr = (struct myx_response *)sc->sc_cmddma.mxm_kva; 593 mr->mr_result = 0xffffffff; 594 595 /* Send command */ 596 myx_write(sc, MYX_CMD, (u_int8_t *)mc, sizeof(struct myx_cmd)); 597 598 for (i = 0; i < 20; i++) { 599 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 600 BUS_DMASYNC_POSTREAD); 601 result = betoh32(mr->mr_result); 602 data = betoh32(mr->mr_data); 603 604 if (result != 0xffffffff) 605 break; 606 delay(1000); 607 } 608 609 DPRINTF(MYXDBG_CMD, "%s(%s): %s completed, i %d, " 610 "result 0x%x, data 0x%x (%u)\n", DEVNAME(sc), __func__, 611 cmds[cmd], i, result, data, data); 612 613 if (result != 0) 614 return (-1); 615 616 if (r != NULL) 617 *r = data; 618 return (0); 619} 620 621int 622myx_boot(struct myx_softc *sc, u_int32_t length, struct myx_bootcmd *bc) 623{ 624 bus_dmamap_t map = sc->sc_cmddma.mxm_map; 625 u_int32_t *status; 626 u_int i; 627 628 bc->bc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 629 bc->bc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 630 bc->bc_result = 0xffffffff; 631 bc->bc_offset = htobe32(MYX_FW_BOOT); 632 bc->bc_length = htobe32(length); 633 bc->bc_copyto = htobe32(8); 634 bc->bc_jumpto = htobe32(0); 635 636 status = (u_int32_t *)sc->sc_cmddma.mxm_kva; 637 *status = 0; 638 639 /* Send command */ 640 myx_write(sc, MYX_BOOT, (u_int8_t *)bc, sizeof(struct myx_bootcmd)); 641 642 for (i = 0; i < 200; i++) { 643 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 644 BUS_DMASYNC_POSTREAD); 645 if (*status == 0xffffffff) 646 break; 647 delay(1000); 648 } 649 650 DPRINTF(MYXDBG_CMD, "%s(%s): boot completed, i %d, result 0x%x\n", 651 DEVNAME(sc), __func__, i, betoh32(*status)); 652 653 if (*status != 0xffffffff) 654 return (-1); 655 656 return (0); 657} 658 659int 660myx_rdma(struct myx_softc *sc, u_int do_enable) 661{ 662 struct myx_rdmacmd rc; 663 bus_dmamap_t map = sc->sc_cmddma.mxm_map; 664 bus_dmamap_t pad = sc->sc_paddma.mxm_map; 665 u_int32_t *status; 666 u_int i; 667 668 /* 669 * It is required to setup a _dummy_ RDMA address. It also makes 670 * some PCI-E chipsets resend dropped messages. 671 */ 672 rc.rc_addr_high = htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 673 rc.rc_addr_low = htobe32(MYX_ADDRLOW(map->dm_segs[0].ds_addr)); 674 rc.rc_result = 0xffffffff; 675 rc.rc_rdma_high = htobe32(MYX_ADDRHIGH(pad->dm_segs[0].ds_addr)); 676 rc.rc_rdma_low = htobe32(MYX_ADDRLOW(pad->dm_segs[0].ds_addr)); 677 rc.rc_enable = htobe32(do_enable); 678 679 status = (u_int32_t *)sc->sc_cmddma.mxm_kva; 680 *status = 0; 681 682 /* Send command */ 683 myx_write(sc, MYX_RDMA, (u_int8_t *)&rc, sizeof(struct myx_rdmacmd)); 684 685 for (i = 0; i < 20; i++) { 686 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 687 BUS_DMASYNC_POSTREAD); 688 if (*status == 0xffffffff) 689 break; 690 delay(1000); 691 } 692 693 DPRINTF(MYXDBG_CMD, "%s(%s): dummy RDMA %s, i %d, result 0x%x\n", 694 DEVNAME(sc), __func__, 695 do_enable ? "enabled" : "disabled", i, betoh32(*status)); 696 697 if (*status != 0xffffffff) 698 return (-1); 699 700 return (0); 701} 702 703int 704myx_reset(struct myx_softc *sc) 705{ 706 struct myx_cmd mc; 707 u_int32_t data; 708 struct ifnet *ifp = &sc->sc_ac.ac_if; 709 710 bzero(&mc, sizeof(mc)); 711 if (myx_cmd(sc, MYXCMD_RESET, &mc, NULL) != 0) { 712 printf("%s: failed to reset the device\n", DEVNAME(sc)); 713 return (-1); 714 } 715 716 if (myx_rdma(sc, MYXRDMA_ON) != 0) { 717 printf("%s: failed to enable dummy RDMA\n", DEVNAME(sc)); 718 return (-1); 719 } 720 721 if (myx_cmd(sc, MYXCMD_GET_INTRCOALDELAYOFF, &mc, 722 &sc->sc_irqcoaloff) != 0) { 723 printf("%s: failed to get IRQ coal offset\n", DEVNAME(sc)); 724 return (-1); 725 } 726 data = htobe32(MYX_IRQCOALDELAY); 727 myx_write(sc, sc->sc_irqcoaloff, (u_int8_t *)&data, sizeof(data)); 728 729 if (myx_cmd(sc, MYXCMD_GET_INTRACKOFF, &mc, 730 &sc->sc_irqclaimoff) != 0) { 731 printf("%s: failed to get IRQ ack offset\n", DEVNAME(sc)); 732 return (-1); 733 } 734 735 if (myx_cmd(sc, MYXCMD_GET_INTRDEASSERTOFF, &mc, 736 &sc->sc_irqdeassertoff) != 0) { 737 printf("%s: failed to get IRQ deassert offset\n", DEVNAME(sc)); 738 return (-1); 739 } 740 741 if (myx_cmd(sc, MYXCMD_UNSET_PROMISC, &mc, NULL) != 0) { 742 printf("%s: failed to disable promisc mode\n", DEVNAME(sc)); 743 return (-1); 744 } 745 746 if (myx_cmd(sc, MYXCMD_FC_DEFAULT, &mc, NULL) != 0) { 747 printf("%s: failed to configure flow control\n", DEVNAME(sc)); 748 return (-1); 749 } 750 751 if (myx_setlladdr(sc, LLADDR(ifp->if_sadl)) != 0) 752 return (-1); 753 754 return (0); 755} 756 757 758int 759myx_media_change(struct ifnet *ifp) 760{ 761 return (EINVAL); 762} 763 764void 765myx_media_status(struct ifnet *ifp, struct ifmediareq *imr) 766{ 767 struct myx_softc *sc = (struct myx_softc *)ifp->if_softc; 768 769 imr->ifm_active = IFM_ETHER|sc->sc_phy; 770 imr->ifm_status = IFM_AVALID; 771 myx_link_state(sc); 772 if (!LINK_STATE_IS_UP(ifp->if_link_state)) 773 return; 774 imr->ifm_active |= IFM_FDX; 775 imr->ifm_status |= IFM_ACTIVE; 776 777 /* Flow control */ 778 if (sc->sc_hwflags & MYXFLAG_FLOW_CONTROL) 779 imr->ifm_active |= IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE; 780} 781 782void 783myx_link_state(struct myx_softc *sc) 784{ 785 struct ifnet *ifp = &sc->sc_ac.ac_if; 786 int link_state = LINK_STATE_DOWN; 787 788 if (sc->sc_sts == NULL) 789 return; 790 if (sc->sc_sts->ms_linkstate == MYXSTS_LINKUP) 791 link_state = LINK_STATE_FULL_DUPLEX; 792 if (ifp->if_link_state != link_state) { 793 ifp->if_link_state = link_state; 794 if_link_state_change(ifp); 795 } 796} 797 798void 799myx_watchdog(struct ifnet *ifp) 800{ 801 return; 802} 803 804void 805myx_tick(void *arg) 806{ 807 struct myx_softc *sc = (struct myx_softc *)arg; 808 809 if (!sc->sc_active) 810 return; 811 812 myx_link_state(sc); 813 timeout_add_sec(&sc->sc_tick, 1); 814} 815 816int 817myx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 818{ 819 struct myx_softc *sc = (struct myx_softc *)ifp->if_softc; 820 struct ifaddr *ifa = (struct ifaddr *)data; 821 struct ifreq *ifr = (struct ifreq *)data; 822 int s, error = 0; 823 824 s = splnet(); 825 826 switch (cmd) { 827 case SIOCSIFADDR: 828 ifp->if_flags |= IFF_UP; 829#ifdef INET 830 if (ifa->ifa_addr->sa_family == AF_INET) 831 arp_ifinit(&sc->sc_ac, ifa); 832#endif 833 /* FALLTHROUGH */ 834 835 case SIOCSIFFLAGS: 836 if (ifp->if_flags & IFF_UP) { 837 if (ifp->if_flags & IFF_RUNNING) 838 myx_iff(sc); 839 else 840 myx_init(ifp); 841 } else { 842 if (ifp->if_flags & IFF_RUNNING) 843 myx_stop(ifp); 844 } 845 break; 846 847 case SIOCGIFMEDIA: 848 case SIOCSIFMEDIA: 849 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 850 break; 851 852 default: 853 error = ether_ioctl(ifp, &sc->sc_ac, cmd, data); 854 } 855 856 if (error == ENETRESET) { 857 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 858 (IFF_UP | IFF_RUNNING)) 859 myx_iff(sc); 860 error = 0; 861 } 862 863 splx(s); 864 return (error); 865} 866 867void 868myx_iff(struct myx_softc *sc) 869{ 870 /* XXX set multicast filters etc. */ 871 return; 872} 873 874void 875myx_init(struct ifnet *ifp) 876{ 877 struct myx_softc *sc = (struct myx_softc *)ifp->if_softc; 878 struct myx_cmd mc; 879 880 if (myx_reset(sc) != 0) 881 return; 882 883 if (myx_init_rings(sc) != 0) 884 return; 885 886 if (myx_cmd(sc, MYXCMD_SET_IFUP, &mc, NULL) != 0) { 887 printf("%s: failed to start the device\n", DEVNAME(sc)); 888 myx_free_rings(sc); 889 return; 890 } 891 892 ifp->if_flags |= IFF_RUNNING; 893 ifp->if_flags &= ~IFF_OACTIVE; 894} 895 896void 897myx_start(struct ifnet *ifp) 898{ 899} 900 901void 902myx_stop(struct ifnet *ifp) 903{ 904 struct myx_softc *sc = (struct myx_softc *)ifp->if_softc; 905 struct myx_cmd mc; 906 907 bzero(&mc, sizeof(mc)); 908 (void)myx_cmd(sc, MYXCMD_SET_IFDOWN, &mc, NULL); 909 myx_free_rings(sc); 910 911 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 912} 913 914int 915myx_setlladdr(struct myx_softc *sc, u_int8_t *addr) 916{ 917 struct myx_cmd mc; 918 919 bzero(&mc, sizeof(mc)); 920 mc.mc_data0 = addr[3] | addr[2] << 8 | addr[1] << 16 | addr[0] << 24; 921 mc.mc_data1 = addr[5] | addr[4] << 8; 922 if (myx_cmd(sc, MYXCMD_SET_LLADDR, &mc, NULL) != 0) { 923 printf("%s: failed to set the lladdr\n", DEVNAME(sc)); 924 return (-1); 925 } 926 return (0); 927} 928 929int 930myx_intr(void *arg) 931{ 932 struct myx_softc *sc = (struct myx_softc *)arg; 933 u_int32_t data, valid; 934 struct myx_status *sts = sc->sc_sts; 935 bus_dmamap_t map = sc->sc_stsdma.mxm_map; 936 937 if (!sc->sc_active) 938 return (0); 939 940 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 941 BUS_DMASYNC_POSTWRITE); 942 943 /* 944 * XXX The 'valid' flags should be set by the NIC, but it doesn't 945 * XXX work yet. 946 */ 947 valid = sts->ms_isvalid; 948 if (!valid) 949 return (0); 950 951 data = 0; 952 myx_write(sc, sc->sc_irqdeassertoff, (u_int8_t *)&data, sizeof(data)); 953 954 DPRINTF(MYXDBG_INTR, "%s(%s): interrupt, valid 0x%x\n", 955 DEVNAME(sc), __func__, valid); 956 957#ifdef MYX_DEBUG 958#define DPRINT_STATUS(_n) \ 959 DPRINTF(MYXDBG_INTR, "%s(%s): %s: %u, 0x%x\n", DEVNAME(sc), __func__,\ 960 #_n, sts->_n, sts->_n) 961 962 DPRINT_STATUS(ms_reserved); 963 DPRINT_STATUS(ms_dropped_pause); 964 DPRINT_STATUS(ms_dropped_unicast); 965 DPRINT_STATUS(ms_dropped_crc32err); 966 DPRINT_STATUS(ms_dropped_phyerr); 967 DPRINT_STATUS(ms_dropped_mcast); 968 DPRINT_STATUS(ms_txdonecnt); 969 DPRINT_STATUS(ms_linkstate); 970 DPRINT_STATUS(ms_dropped_linkoverflow); 971 DPRINT_STATUS(ms_dropped_linkerror); 972 DPRINT_STATUS(ms_dropped_runt); 973 DPRINT_STATUS(ms_dropped_overrun); 974 DPRINT_STATUS(ms_dropped_smallbufunderrun); 975 DPRINT_STATUS(ms_dropped_bigbufunderrun); 976 DPRINT_STATUS(ms_rdmatags_available); 977 DPRINT_STATUS(ms_txstopped); 978 DPRINT_STATUS(ms_linkdowncnt); 979 DPRINT_STATUS(ms_statusupdated); 980 DPRINT_STATUS(ms_isvalid); 981#endif 982 983 data = htobe32(3); 984 if (sts->ms_isvalid) 985 myx_write(sc, sc->sc_irqclaimoff, (u_int8_t *)&data, 986 sizeof(data)); 987 myx_write(sc, sc->sc_irqclaimoff + sizeof(u_int32_t), 988 (u_int8_t *)&data, sizeof(data)); 989 990 return (1); 991} 992 993int 994myx_init_rings(struct myx_softc *sc) 995{ 996 struct myx_cmd mc; 997 struct ifnet *ifp = &sc->sc_ac.ac_if; 998 bus_dmamap_t map; 999 int i; 1000 struct myx_buf *mb; 1001 struct myx_rxbufdesc *rxb; 1002 u_int32_t data; 1003 1004 bzero(&mc, sizeof(mc)); 1005 if (!(myx_cmd(sc, MYXCMD_GET_RXRINGSZ, &mc, 1006 &sc->sc_rxringsize) == 0 && sc->sc_rxringsize && 1007 myx_cmd(sc, MYXCMD_GET_RXSMALLRINGOFF, &mc, 1008 &sc->sc_rxsmallringoff) == 0 && sc->sc_rxsmallringoff && 1009 myx_cmd(sc, MYXCMD_GET_RXBIGRINGOFF, &mc, 1010 &sc->sc_rxbigringoff) == 0 && sc->sc_rxbigringoff && 1011 myx_cmd(sc, MYXCMD_GET_TXRINGSZ, &mc, 1012 &sc->sc_txringsize) == 0 && sc->sc_txringsize && 1013 myx_cmd(sc, MYXCMD_GET_TXRINGOFF, &mc, 1014 &sc->sc_txringoff) == 0 && sc->sc_txringoff)) { 1015 printf("%s: failed to get ring sizes and offsets\n", 1016 DEVNAME(sc)); 1017 return (-1); 1018 } 1019 sc->sc_rxndesc = sc->sc_rxringsize / sizeof(struct myx_rxbufdesc); 1020 sc->sc_txndesc = sc->sc_txringsize / sizeof(struct myx_txdesc); 1021 sc->sc_rxdescsize = sc->sc_rxndesc * 2 * sizeof(struct myx_rxdesc); 1022 sc->sc_rxbufsize = sc->sc_rxndesc * sizeof(struct myx_buf); 1023 sc->sc_rxbufdescsize = sc->sc_rxndesc * sizeof(struct myx_rxbufdesc); 1024 IFQ_SET_MAXLEN(&ifp->if_snd, sc->sc_txndesc - 1); 1025 IFQ_SET_READY(&ifp->if_snd); 1026 1027 DPRINTF(MYXDBG_INIT, "%s(%s): Rx ring ndesc %u size %u bufsize %u, " 1028 "Tx ring ndesc %u size %u offset 0x%x\n", DEVNAME(sc), __func__, 1029 sc->sc_rxndesc, sc->sc_rxdescsize, sc->sc_rxringsize, 1030 sc->sc_txndesc, sc->sc_txringsize, sc->sc_txringoff); 1031 1032 /* 1033 * Setup Rx DMA descriptors 1034 */ 1035 if (myx_dmamem_alloc(sc, &sc->sc_rxdma, 1036 sc->sc_rxdescsize, MYXALIGN_DATA, "rxring") != 0) { 1037 printf(": failed to allocate Rx DMA memory\n"); 1038 return (-1); 1039 } 1040 sc->sc_rxdesc = (struct myx_rxdesc *)sc->sc_rxdma.mxm_kva; 1041 1042 bzero(&mc, sizeof(mc)); 1043 mc.mc_data0 = htobe32(sc->sc_rxdescsize); 1044 if (myx_cmd(sc, MYXCMD_SET_INTRQSZ, &mc, NULL) != 0) { 1045 printf("%s: failed to set Rx DMA size\n", DEVNAME(sc)); 1046 goto err; 1047 } 1048 1049 map = sc->sc_rxdma.mxm_map; 1050 mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr); 1051 mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr); 1052 if (myx_cmd(sc, MYXCMD_SET_INTRQDMA, &mc, NULL) != 0) { 1053 printf("%s: failed to set Rx DMA address\n", DEVNAME(sc)); 1054 goto err; 1055 } 1056 1057#ifdef notyet 1058 /* 1059 * XXX It fails to set the MTU and it always returns 1060 * XXX MYXCMD_ERR_RANGE. 1061 */ 1062 bzero(&mc, sizeof(mc)); 1063 mc.mc_data0 = ifp->if_mtu + ETHER_HDR_LEN + 4; 1064 if (myx_cmd(sc, MYXCMD_SET_MTU, &mc, NULL) != 0) { 1065 printf("%s: failed to set MTU size %d\n", 1066 DEVNAME(sc), ifp->if_mtu + ETHER_HDR_LEN + 4); 1067 goto err; 1068 } 1069#endif 1070 1071 /* 1072 * Setup Rx buffer descriptors 1073 */ 1074 sc->sc_rxbuf[MYX_RXSMALL] = (struct myx_buf *) 1075 malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK); 1076 sc->sc_rxbufdesc[MYX_RXSMALL] = (struct myx_rxbufdesc *) 1077 malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK); 1078 sc->sc_rxbuf[MYX_RXBIG] = (struct myx_buf *) 1079 malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK); 1080 sc->sc_rxbufdesc[MYX_RXBIG] = (struct myx_rxbufdesc *) 1081 malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK); 1082 if (sc->sc_rxbuf[MYX_RXSMALL] == NULL || 1083 sc->sc_rxbufdesc[MYX_RXSMALL] == NULL || 1084 sc->sc_rxbuf[MYX_RXBIG] == NULL || 1085 sc->sc_rxbufdesc[MYX_RXBIG] == NULL) { 1086 printf("%s: failed to allocate rx buffers\n", DEVNAME(sc)); 1087 goto err; 1088 } 1089 1090 for (i = 0; i < sc->sc_rxndesc; i++) { 1091 /* 1092 * Small Rx buffers and descriptors 1093 */ 1094 mb = sc->sc_rxbuf[MYX_RXSMALL] + i; 1095 rxb = sc->sc_rxbufdesc[MYX_RXSMALL] + i; 1096 1097 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, 1098 MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) { 1099 printf("%s: unable to create dmamap for small rx %d\n", 1100 DEVNAME(sc), i); 1101 goto err; 1102 } 1103 1104 map = mb->mb_dmamap; 1105 mb->mb_m = myx_getbuf(sc, map, 1); 1106 if (mb->mb_m == NULL) { 1107 bus_dmamap_destroy(sc->sc_dmat, map); 1108 goto err; 1109 } 1110 1111 bus_dmamap_sync(sc->sc_dmat, map, 0, 1112 mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD); 1113 1114 rxb->rb_addr_high = 1115 htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1116 rxb->rb_addr_low = 1117 htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1118 1119 data = sc->sc_rxsmallringoff + i * sizeof(*rxb); 1120 myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb)); 1121 1122 /* 1123 * Big Rx buffers and descriptors 1124 */ 1125 mb = sc->sc_rxbuf[MYX_RXBIG] + i; 1126 rxb = sc->sc_rxbufdesc[MYX_RXBIG] + i; 1127 1128 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, 1129 MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) { 1130 printf("%s: unable to create dmamap for big rx %d\n", 1131 DEVNAME(sc), i); 1132 goto err; 1133 } 1134 1135 map = mb->mb_dmamap; 1136 mb->mb_m = myx_getbuf(sc, map, 1); 1137 if (mb->mb_m == NULL) { 1138 bus_dmamap_destroy(sc->sc_dmat, map); 1139 goto err; 1140 } 1141 1142 bus_dmamap_sync(sc->sc_dmat, map, 0, 1143 mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD); 1144 1145 rxb->rb_addr_high = 1146 htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1147 rxb->rb_addr_low = 1148 htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1149 1150 data = sc->sc_rxbigringoff + i * sizeof(*rxb); 1151 myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb)); 1152 } 1153 1154 bzero(&mc, sizeof(mc)); 1155 mc.mc_data0 = MYX_MAX_MTU_SMALL; 1156 if (myx_cmd(sc, MYXCMD_SET_SMALLBUFSZ, &mc, NULL) != 0) { 1157 printf("%s: failed to set small buf size\n", DEVNAME(sc)); 1158 goto err; 1159 } 1160 1161 bzero(&mc, sizeof(mc)); 1162 mc.mc_data0 = MCLBYTES; 1163 if (myx_cmd(sc, MYXCMD_SET_BIGBUFSZ, &mc, NULL) != 0) { 1164 printf("%s: failed to set big buf size\n", DEVNAME(sc)); 1165 goto err; 1166 } 1167 1168 /* 1169 * Setup status DMA 1170 */ 1171 map = sc->sc_stsdma.mxm_map; 1172 1173 bzero(&mc, sizeof(mc)); 1174 mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr); 1175 mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr); 1176 mc.mc_data2 = sizeof(struct myx_status); 1177 if (myx_cmd(sc, MYXCMD_SET_STATSDMA, &mc, NULL) != 0) { 1178 printf("%s: failed to set status DMA offset\n", DEVNAME(sc)); 1179 goto err; 1180 } 1181 1182 bus_dmamap_sync(sc->sc_dmat, map, 0, 1183 map->dm_mapsize, BUS_DMASYNC_PREWRITE); 1184 1185 return (0); 1186 err: 1187 myx_free_rings(sc); 1188 return (-1); 1189} 1190 1191void 1192myx_free_rings(struct myx_softc *sc) 1193{ 1194 if (sc->sc_rxbuf[MYX_RXSMALL] != NULL) { 1195 free(sc->sc_rxbuf[MYX_RXSMALL], M_DEVBUF); 1196 sc->sc_rxbuf[MYX_RXSMALL] = NULL; 1197 } 1198 if (sc->sc_rxbufdesc[MYX_RXSMALL] != NULL) { 1199 free(sc->sc_rxbufdesc[MYX_RXSMALL], M_DEVBUF); 1200 sc->sc_rxbufdesc[MYX_RXSMALL] = NULL; 1201 } 1202 if (sc->sc_rxbuf[MYX_RXBIG] != NULL) { 1203 free(sc->sc_rxbuf[MYX_RXBIG], M_DEVBUF); 1204 sc->sc_rxbuf[MYX_RXBIG] = NULL; 1205 } 1206 if (sc->sc_rxbufdesc[MYX_RXBIG] != NULL) { 1207 free(sc->sc_rxbufdesc[MYX_RXBIG], M_DEVBUF); 1208 sc->sc_rxbufdesc[MYX_RXBIG] = NULL; 1209 } 1210 if (sc->sc_rxdesc != NULL) { 1211 myx_dmamem_free(sc, &sc->sc_rxdma); 1212 sc->sc_rxdesc = NULL; 1213 } 1214 if (sc->sc_sts != NULL) { 1215 myx_dmamem_free(sc, &sc->sc_stsdma); 1216 sc->sc_sts = NULL; 1217 } 1218 return; 1219} 1220 1221struct mbuf * 1222myx_getbuf(struct myx_softc *sc, bus_dmamap_t map, int wait) 1223{ 1224 struct mbuf *m = NULL; 1225 1226 MGETHDR(m, wait ? M_WAIT : M_DONTWAIT, MT_DATA); 1227 if (m == NULL) 1228 goto merr; 1229 1230 MCLGET(m, wait ? M_WAIT : M_DONTWAIT); 1231 if ((m->m_flags & M_EXT) == 0) 1232 goto merr; 1233 m->m_len = m->m_pkthdr.len = MCLBYTES; 1234 1235 if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, 1236 wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) != 0) { 1237 printf("%s: could not load mbuf dma map\n", DEVNAME(sc)); 1238 goto err; 1239 } 1240 1241 return (m); 1242 merr: 1243 printf("%s: unable to allocate mbuf\n", DEVNAME(sc)); 1244 err: 1245 if (m != NULL) 1246 m_freem(m); 1247 return (NULL); 1248} 1249