if_myx.c revision 1.7
1/* $OpenBSD: if_myx.c,v 1.7 2008/05/23 08:49:27 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(&sc->sc_tick, hz); 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(&sc->sc_tick, hz); 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 if ((error = ether_ioctl(ifp, &sc->sc_ac, cmd, data)) > 0) { 826 splx(s); 827 return (error); 828 } 829 830 switch (cmd) { 831 case SIOCSIFADDR: 832 ifp->if_flags |= IFF_UP; 833#ifdef INET 834 if (ifa->ifa_addr->sa_family == AF_INET) 835 arp_ifinit(&sc->sc_ac, ifa); 836#endif 837 /* FALLTHROUGH */ 838 case SIOCSIFFLAGS: 839 if (ifp->if_flags & IFF_UP) { 840 if (ifp->if_flags & IFF_RUNNING) 841 myx_iff(sc); 842 else 843 myx_init(ifp); 844 } else { 845 if (ifp->if_flags & IFF_RUNNING) 846 myx_stop(ifp); 847 } 848 break; 849 850 case SIOCSIFMTU: 851 if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu) 852 error = EINVAL; 853 else if (ifp->if_mtu != ifr->ifr_mtu) 854 ifp->if_mtu = ifr->ifr_mtu; 855 break; 856 857 case SIOCADDMULTI: 858 error = ether_addmulti(ifr, &sc->sc_ac); 859 break; 860 861 case SIOCDELMULTI: 862 error = ether_delmulti(ifr, &sc->sc_ac); 863 break; 864 865 case SIOCGIFMEDIA: 866 case SIOCSIFMEDIA: 867 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 868 break; 869 870 default: 871 error = ENOTTY; 872 } 873 874 if (error == ENETRESET) { 875 if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == 876 (IFF_UP | IFF_RUNNING)) 877 myx_iff(sc); 878 error = 0; 879 } 880 881 splx(s); 882 883 return (error); 884} 885 886void 887myx_iff(struct myx_softc *sc) 888{ 889 /* XXX set multicast filters etc. */ 890 return; 891} 892 893void 894myx_init(struct ifnet *ifp) 895{ 896 struct myx_softc *sc = (struct myx_softc *)ifp->if_softc; 897 struct myx_cmd mc; 898 899 if (myx_reset(sc) != 0) 900 return; 901 902 if (myx_init_rings(sc) != 0) 903 return; 904 905 if (myx_cmd(sc, MYXCMD_SET_IFUP, &mc, NULL) != 0) { 906 printf("%s: failed to start the device\n", DEVNAME(sc)); 907 myx_free_rings(sc); 908 return; 909 } 910 911 ifp->if_flags |= IFF_RUNNING; 912 ifp->if_flags &= ~IFF_OACTIVE; 913} 914 915void 916myx_start(struct ifnet *ifp) 917{ 918} 919 920void 921myx_stop(struct ifnet *ifp) 922{ 923 struct myx_softc *sc = (struct myx_softc *)ifp->if_softc; 924 struct myx_cmd mc; 925 926 bzero(&mc, sizeof(mc)); 927 (void)myx_cmd(sc, MYXCMD_SET_IFDOWN, &mc, NULL); 928 myx_free_rings(sc); 929 930 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 931} 932 933int 934myx_setlladdr(struct myx_softc *sc, u_int8_t *addr) 935{ 936 struct myx_cmd mc; 937 938 bzero(&mc, sizeof(mc)); 939 mc.mc_data0 = addr[3] | addr[2] << 8 | addr[1] << 16 | addr[0] << 24; 940 mc.mc_data1 = addr[5] | addr[4] << 8; 941 if (myx_cmd(sc, MYXCMD_SET_LLADDR, &mc, NULL) != 0) { 942 printf("%s: failed to set the lladdr\n", DEVNAME(sc)); 943 return (-1); 944 } 945 return (0); 946} 947 948int 949myx_intr(void *arg) 950{ 951 struct myx_softc *sc = (struct myx_softc *)arg; 952 u_int32_t data, valid; 953 struct myx_status *sts = sc->sc_sts; 954 bus_dmamap_t map = sc->sc_stsdma.mxm_map; 955 956 if (!sc->sc_active) 957 return (0); 958 959 bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, 960 BUS_DMASYNC_POSTWRITE); 961 962 /* 963 * XXX The 'valid' flags should be set by the NIC, but it doesn't 964 * XXX work yet. 965 */ 966 valid = sts->ms_isvalid; 967 if (!valid) 968 return (0); 969 970 data = 0; 971 myx_write(sc, sc->sc_irqdeassertoff, (u_int8_t *)&data, sizeof(data)); 972 973 DPRINTF(MYXDBG_INTR, "%s(%s): interrupt, valid 0x%x\n", 974 DEVNAME(sc), __func__, valid); 975 976#ifdef MYX_DEBUG 977#define DPRINT_STATUS(_n) \ 978 DPRINTF(MYXDBG_INTR, "%s(%s): %s: %u, 0x%x\n", DEVNAME(sc), __func__,\ 979 #_n, sts->_n, sts->_n) 980 981 DPRINT_STATUS(ms_reserved); 982 DPRINT_STATUS(ms_dropped_pause); 983 DPRINT_STATUS(ms_dropped_unicast); 984 DPRINT_STATUS(ms_dropped_crc32err); 985 DPRINT_STATUS(ms_dropped_phyerr); 986 DPRINT_STATUS(ms_dropped_mcast); 987 DPRINT_STATUS(ms_txdonecnt); 988 DPRINT_STATUS(ms_linkstate); 989 DPRINT_STATUS(ms_dropped_linkoverflow); 990 DPRINT_STATUS(ms_dropped_linkerror); 991 DPRINT_STATUS(ms_dropped_runt); 992 DPRINT_STATUS(ms_dropped_overrun); 993 DPRINT_STATUS(ms_dropped_smallbufunderrun); 994 DPRINT_STATUS(ms_dropped_bigbufunderrun); 995 DPRINT_STATUS(ms_rdmatags_available); 996 DPRINT_STATUS(ms_txstopped); 997 DPRINT_STATUS(ms_linkdowncnt); 998 DPRINT_STATUS(ms_statusupdated); 999 DPRINT_STATUS(ms_isvalid); 1000#endif 1001 1002 data = htobe32(3); 1003 if (sts->ms_isvalid) 1004 myx_write(sc, sc->sc_irqclaimoff, (u_int8_t *)&data, 1005 sizeof(data)); 1006 myx_write(sc, sc->sc_irqclaimoff + sizeof(u_int32_t), 1007 (u_int8_t *)&data, sizeof(data)); 1008 1009 return (1); 1010} 1011 1012int 1013myx_init_rings(struct myx_softc *sc) 1014{ 1015 struct myx_cmd mc; 1016 struct ifnet *ifp = &sc->sc_ac.ac_if; 1017 bus_dmamap_t map; 1018 int i; 1019 struct myx_buf *mb; 1020 struct myx_rxbufdesc *rxb; 1021 u_int32_t data; 1022 1023 bzero(&mc, sizeof(mc)); 1024 if (!(myx_cmd(sc, MYXCMD_GET_RXRINGSZ, &mc, 1025 &sc->sc_rxringsize) == 0 && sc->sc_rxringsize && 1026 myx_cmd(sc, MYXCMD_GET_RXSMALLRINGOFF, &mc, 1027 &sc->sc_rxsmallringoff) == 0 && sc->sc_rxsmallringoff && 1028 myx_cmd(sc, MYXCMD_GET_RXBIGRINGOFF, &mc, 1029 &sc->sc_rxbigringoff) == 0 && sc->sc_rxbigringoff && 1030 myx_cmd(sc, MYXCMD_GET_TXRINGSZ, &mc, 1031 &sc->sc_txringsize) == 0 && sc->sc_txringsize && 1032 myx_cmd(sc, MYXCMD_GET_TXRINGOFF, &mc, 1033 &sc->sc_txringoff) == 0 && sc->sc_txringoff)) { 1034 printf("%s: failed to get ring sizes and offsets\n", 1035 DEVNAME(sc)); 1036 return (-1); 1037 } 1038 sc->sc_rxndesc = sc->sc_rxringsize / sizeof(struct myx_rxbufdesc); 1039 sc->sc_txndesc = sc->sc_txringsize / sizeof(struct myx_txdesc); 1040 sc->sc_rxdescsize = sc->sc_rxndesc * 2 * sizeof(struct myx_rxdesc); 1041 sc->sc_rxbufsize = sc->sc_rxndesc * sizeof(struct myx_buf); 1042 sc->sc_rxbufdescsize = sc->sc_rxndesc * sizeof(struct myx_rxbufdesc); 1043 IFQ_SET_MAXLEN(&ifp->if_snd, sc->sc_txndesc - 1); 1044 IFQ_SET_READY(&ifp->if_snd); 1045 1046 DPRINTF(MYXDBG_INIT, "%s(%s): Rx ring ndesc %u size %u bufsize %u, " 1047 "Tx ring ndesc %u size %u offset 0x%x\n", DEVNAME(sc), __func__, 1048 sc->sc_rxndesc, sc->sc_rxdescsize, sc->sc_rxringsize, 1049 sc->sc_txndesc, sc->sc_txringsize, sc->sc_txringoff); 1050 1051 /* 1052 * Setup Rx DMA descriptors 1053 */ 1054 if (myx_dmamem_alloc(sc, &sc->sc_rxdma, 1055 sc->sc_rxdescsize, MYXALIGN_DATA, "rxring") != 0) { 1056 printf(": failed to allocate Rx DMA memory\n"); 1057 return (-1); 1058 } 1059 sc->sc_rxdesc = (struct myx_rxdesc *)sc->sc_rxdma.mxm_kva; 1060 1061 bzero(&mc, sizeof(mc)); 1062 mc.mc_data0 = htobe32(sc->sc_rxdescsize); 1063 if (myx_cmd(sc, MYXCMD_SET_INTRQSZ, &mc, NULL) != 0) { 1064 printf("%s: failed to set Rx DMA size\n", DEVNAME(sc)); 1065 goto err; 1066 } 1067 1068 map = sc->sc_rxdma.mxm_map; 1069 mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr); 1070 mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr); 1071 if (myx_cmd(sc, MYXCMD_SET_INTRQDMA, &mc, NULL) != 0) { 1072 printf("%s: failed to set Rx DMA address\n", DEVNAME(sc)); 1073 goto err; 1074 } 1075 1076#ifdef notyet 1077 /* 1078 * XXX It fails to set the MTU and it always returns 1079 * XXX MYXCMD_ERR_RANGE. 1080 */ 1081 bzero(&mc, sizeof(mc)); 1082 mc.mc_data0 = ifp->if_mtu + ETHER_HDR_LEN + 4; 1083 if (myx_cmd(sc, MYXCMD_SET_MTU, &mc, NULL) != 0) { 1084 printf("%s: failed to set MTU size %d\n", 1085 DEVNAME(sc), ifp->if_mtu + ETHER_HDR_LEN + 4); 1086 goto err; 1087 } 1088#endif 1089 1090 /* 1091 * Setup Rx buffer descriptors 1092 */ 1093 sc->sc_rxbuf[MYX_RXSMALL] = (struct myx_buf *) 1094 malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK); 1095 sc->sc_rxbufdesc[MYX_RXSMALL] = (struct myx_rxbufdesc *) 1096 malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK); 1097 sc->sc_rxbuf[MYX_RXBIG] = (struct myx_buf *) 1098 malloc(sc->sc_rxbufsize, M_DEVBUF, M_WAITOK); 1099 sc->sc_rxbufdesc[MYX_RXBIG] = (struct myx_rxbufdesc *) 1100 malloc(sc->sc_rxbufdescsize, M_DEVBUF, M_WAITOK); 1101 if (sc->sc_rxbuf[MYX_RXSMALL] == NULL || 1102 sc->sc_rxbufdesc[MYX_RXSMALL] == NULL || 1103 sc->sc_rxbuf[MYX_RXBIG] == NULL || 1104 sc->sc_rxbufdesc[MYX_RXBIG] == NULL) { 1105 printf("%s: failed to allocate rx buffers\n", DEVNAME(sc)); 1106 goto err; 1107 } 1108 1109 for (i = 0; i < sc->sc_rxndesc; i++) { 1110 /* 1111 * Small Rx buffers and descriptors 1112 */ 1113 mb = sc->sc_rxbuf[MYX_RXSMALL] + i; 1114 rxb = sc->sc_rxbufdesc[MYX_RXSMALL] + i; 1115 1116 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, 1117 MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) { 1118 printf("%s: unable to create dmamap for small rx %d\n", 1119 DEVNAME(sc), i); 1120 goto err; 1121 } 1122 1123 map = mb->mb_dmamap; 1124 mb->mb_m = myx_getbuf(sc, map, 1); 1125 if (mb->mb_m == NULL) { 1126 bus_dmamap_destroy(sc->sc_dmat, map); 1127 goto err; 1128 } 1129 1130 bus_dmamap_sync(sc->sc_dmat, map, 0, 1131 mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD); 1132 1133 rxb->rb_addr_high = 1134 htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1135 rxb->rb_addr_low = 1136 htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1137 1138 data = sc->sc_rxsmallringoff + i * sizeof(*rxb); 1139 myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb)); 1140 1141 /* 1142 * Big Rx buffers and descriptors 1143 */ 1144 mb = sc->sc_rxbuf[MYX_RXBIG] + i; 1145 rxb = sc->sc_rxbufdesc[MYX_RXBIG] + i; 1146 1147 if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, 1148 MCLBYTES, 0, BUS_DMA_WAITOK, &mb->mb_dmamap) != 0) { 1149 printf("%s: unable to create dmamap for big rx %d\n", 1150 DEVNAME(sc), i); 1151 goto err; 1152 } 1153 1154 map = mb->mb_dmamap; 1155 mb->mb_m = myx_getbuf(sc, map, 1); 1156 if (mb->mb_m == NULL) { 1157 bus_dmamap_destroy(sc->sc_dmat, map); 1158 goto err; 1159 } 1160 1161 bus_dmamap_sync(sc->sc_dmat, map, 0, 1162 mb->mb_m->m_pkthdr.len, BUS_DMASYNC_PREREAD); 1163 1164 rxb->rb_addr_high = 1165 htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1166 rxb->rb_addr_low = 1167 htobe32(MYX_ADDRHIGH(map->dm_segs[0].ds_addr)); 1168 1169 data = sc->sc_rxbigringoff + i * sizeof(*rxb); 1170 myx_write(sc, data, (u_int8_t *)rxb, sizeof(*rxb)); 1171 } 1172 1173 bzero(&mc, sizeof(mc)); 1174 mc.mc_data0 = MYX_MAX_MTU_SMALL; 1175 if (myx_cmd(sc, MYXCMD_SET_SMALLBUFSZ, &mc, NULL) != 0) { 1176 printf("%s: failed to set small buf size\n", DEVNAME(sc)); 1177 goto err; 1178 } 1179 1180 bzero(&mc, sizeof(mc)); 1181 mc.mc_data0 = MCLBYTES; 1182 if (myx_cmd(sc, MYXCMD_SET_BIGBUFSZ, &mc, NULL) != 0) { 1183 printf("%s: failed to set big buf size\n", DEVNAME(sc)); 1184 goto err; 1185 } 1186 1187 /* 1188 * Setup status DMA 1189 */ 1190 map = sc->sc_stsdma.mxm_map; 1191 1192 bzero(&mc, sizeof(mc)); 1193 mc.mc_data0 = MYX_ADDRLOW(map->dm_segs[0].ds_addr); 1194 mc.mc_data1 = MYX_ADDRHIGH(map->dm_segs[0].ds_addr); 1195 mc.mc_data2 = sizeof(struct myx_status); 1196 if (myx_cmd(sc, MYXCMD_SET_STATSDMA, &mc, NULL) != 0) { 1197 printf("%s: failed to set status DMA offset\n", DEVNAME(sc)); 1198 goto err; 1199 } 1200 1201 bus_dmamap_sync(sc->sc_dmat, map, 0, 1202 map->dm_mapsize, BUS_DMASYNC_PREWRITE); 1203 1204 return (0); 1205 err: 1206 myx_free_rings(sc); 1207 return (-1); 1208} 1209 1210void 1211myx_free_rings(struct myx_softc *sc) 1212{ 1213 if (sc->sc_rxbuf[MYX_RXSMALL] != NULL) { 1214 free(sc->sc_rxbuf[MYX_RXSMALL], M_DEVBUF); 1215 sc->sc_rxbuf[MYX_RXSMALL] = NULL; 1216 } 1217 if (sc->sc_rxbufdesc[MYX_RXSMALL] != NULL) { 1218 free(sc->sc_rxbufdesc[MYX_RXSMALL], M_DEVBUF); 1219 sc->sc_rxbufdesc[MYX_RXSMALL] = NULL; 1220 } 1221 if (sc->sc_rxbuf[MYX_RXBIG] != NULL) { 1222 free(sc->sc_rxbuf[MYX_RXBIG], M_DEVBUF); 1223 sc->sc_rxbuf[MYX_RXBIG] = NULL; 1224 } 1225 if (sc->sc_rxbufdesc[MYX_RXBIG] != NULL) { 1226 free(sc->sc_rxbufdesc[MYX_RXBIG], M_DEVBUF); 1227 sc->sc_rxbufdesc[MYX_RXBIG] = NULL; 1228 } 1229 if (sc->sc_rxdesc != NULL) { 1230 myx_dmamem_free(sc, &sc->sc_rxdma); 1231 sc->sc_rxdesc = NULL; 1232 } 1233 if (sc->sc_sts != NULL) { 1234 myx_dmamem_free(sc, &sc->sc_stsdma); 1235 sc->sc_sts = NULL; 1236 } 1237 return; 1238} 1239 1240struct mbuf * 1241myx_getbuf(struct myx_softc *sc, bus_dmamap_t map, int wait) 1242{ 1243 struct mbuf *m = NULL; 1244 1245 MGETHDR(m, wait ? M_WAIT : M_DONTWAIT, MT_DATA); 1246 if (m == NULL) 1247 goto merr; 1248 1249 MCLGET(m, wait ? M_WAIT : M_DONTWAIT); 1250 if ((m->m_flags & M_EXT) == 0) 1251 goto merr; 1252 m->m_len = m->m_pkthdr.len = MCLBYTES; 1253 1254 if (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, 1255 wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) != 0) { 1256 printf("%s: could not load mbuf dma map\n", DEVNAME(sc)); 1257 goto err; 1258 } 1259 1260 return (m); 1261 merr: 1262 printf("%s: unable to allocate mbuf\n", DEVNAME(sc)); 1263 err: 1264 if (m != NULL) 1265 m_freem(m); 1266 return (NULL); 1267} 1268