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