if_stge.c revision 215297
1160641Syongari/* $NetBSD: if_stge.c,v 1.32 2005/12/11 12:22:49 christos Exp $ */ 2160641Syongari 3160641Syongari/*- 4160641Syongari * Copyright (c) 2001 The NetBSD Foundation, Inc. 5160641Syongari * All rights reserved. 6160641Syongari * 7160641Syongari * This code is derived from software contributed to The NetBSD Foundation 8160641Syongari * by Jason R. Thorpe. 9160641Syongari * 10160641Syongari * Redistribution and use in source and binary forms, with or without 11160641Syongari * modification, are permitted provided that the following conditions 12160641Syongari * are met: 13160641Syongari * 1. Redistributions of source code must retain the above copyright 14160641Syongari * notice, this list of conditions and the following disclaimer. 15160641Syongari * 2. Redistributions in binary form must reproduce the above copyright 16160641Syongari * notice, this list of conditions and the following disclaimer in the 17160641Syongari * documentation and/or other materials provided with the distribution. 18160641Syongari * 19160641Syongari * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20160641Syongari * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21160641Syongari * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22160641Syongari * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23160641Syongari * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24160641Syongari * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25160641Syongari * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26160641Syongari * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27160641Syongari * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28160641Syongari * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29160641Syongari * POSSIBILITY OF SUCH DAMAGE. 30160641Syongari */ 31160641Syongari 32160641Syongari/* 33160641Syongari * Device driver for the Sundance Tech. TC9021 10/100/1000 34160641Syongari * Ethernet controller. 35160641Syongari */ 36160641Syongari 37160641Syongari#include <sys/cdefs.h> 38160641Syongari__FBSDID("$FreeBSD: head/sys/dev/stge/if_stge.c 215297 2010-11-14 13:26:10Z marius $"); 39160641Syongari 40160641Syongari#ifdef HAVE_KERNEL_OPTION_HEADERS 41160641Syongari#include "opt_device_polling.h" 42160641Syongari#endif 43160641Syongari 44160641Syongari#include <sys/param.h> 45160641Syongari#include <sys/systm.h> 46160641Syongari#include <sys/endian.h> 47160641Syongari#include <sys/mbuf.h> 48160641Syongari#include <sys/malloc.h> 49160641Syongari#include <sys/kernel.h> 50160641Syongari#include <sys/module.h> 51160641Syongari#include <sys/socket.h> 52160641Syongari#include <sys/sockio.h> 53160641Syongari#include <sys/sysctl.h> 54160641Syongari#include <sys/taskqueue.h> 55160641Syongari 56160641Syongari#include <net/bpf.h> 57160641Syongari#include <net/ethernet.h> 58160641Syongari#include <net/if.h> 59160641Syongari#include <net/if_dl.h> 60160641Syongari#include <net/if_media.h> 61160641Syongari#include <net/if_types.h> 62160641Syongari#include <net/if_vlan_var.h> 63160641Syongari 64160641Syongari#include <machine/bus.h> 65160641Syongari#include <machine/resource.h> 66160641Syongari#include <sys/bus.h> 67160641Syongari#include <sys/rman.h> 68160641Syongari 69160641Syongari#include <dev/mii/mii.h> 70160641Syongari#include <dev/mii/miivar.h> 71160641Syongari 72160641Syongari#include <dev/pci/pcireg.h> 73160641Syongari#include <dev/pci/pcivar.h> 74160641Syongari 75160641Syongari#include <dev/stge/if_stgereg.h> 76160641Syongari 77160641Syongari#define STGE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 78160641Syongari 79160641SyongariMODULE_DEPEND(stge, pci, 1, 1, 1); 80160641SyongariMODULE_DEPEND(stge, ether, 1, 1, 1); 81160641SyongariMODULE_DEPEND(stge, miibus, 1, 1, 1); 82160641Syongari 83160641Syongari/* "device miibus" required. See GENERIC if you get errors here. */ 84160641Syongari#include "miibus_if.h" 85160641Syongari 86160641Syongari/* 87160641Syongari * Devices supported by this driver. 88160641Syongari */ 89160641Syongaristatic struct stge_product { 90160641Syongari uint16_t stge_vendorid; 91160641Syongari uint16_t stge_deviceid; 92160641Syongari const char *stge_name; 93160641Syongari} stge_products[] = { 94160641Syongari { VENDOR_SUNDANCETI, DEVICEID_SUNDANCETI_ST1023, 95160641Syongari "Sundance ST-1023 Gigabit Ethernet" }, 96160641Syongari 97160641Syongari { VENDOR_SUNDANCETI, DEVICEID_SUNDANCETI_ST2021, 98160641Syongari "Sundance ST-2021 Gigabit Ethernet" }, 99160641Syongari 100160641Syongari { VENDOR_TAMARACK, DEVICEID_TAMARACK_TC9021, 101160641Syongari "Tamarack TC9021 Gigabit Ethernet" }, 102160641Syongari 103160641Syongari { VENDOR_TAMARACK, DEVICEID_TAMARACK_TC9021_ALT, 104160641Syongari "Tamarack TC9021 Gigabit Ethernet" }, 105160641Syongari 106160641Syongari /* 107160641Syongari * The Sundance sample boards use the Sundance vendor ID, 108160641Syongari * but the Tamarack product ID. 109160641Syongari */ 110160641Syongari { VENDOR_SUNDANCETI, DEVICEID_TAMARACK_TC9021, 111160641Syongari "Sundance TC9021 Gigabit Ethernet" }, 112160641Syongari 113160641Syongari { VENDOR_SUNDANCETI, DEVICEID_TAMARACK_TC9021_ALT, 114160641Syongari "Sundance TC9021 Gigabit Ethernet" }, 115160641Syongari 116160641Syongari { VENDOR_DLINK, DEVICEID_DLINK_DL4000, 117160641Syongari "D-Link DL-4000 Gigabit Ethernet" }, 118160641Syongari 119160641Syongari { VENDOR_ANTARES, DEVICEID_ANTARES_TC9021, 120160641Syongari "Antares Gigabit Ethernet" } 121160641Syongari}; 122160641Syongari 123160641Syongaristatic int stge_probe(device_t); 124160641Syongaristatic int stge_attach(device_t); 125160641Syongaristatic int stge_detach(device_t); 126173839Syongaristatic int stge_shutdown(device_t); 127160641Syongaristatic int stge_suspend(device_t); 128160641Syongaristatic int stge_resume(device_t); 129160641Syongari 130160641Syongaristatic int stge_encap(struct stge_softc *, struct mbuf **); 131160641Syongaristatic void stge_start(struct ifnet *); 132160641Syongaristatic void stge_start_locked(struct ifnet *); 133169157Syongaristatic void stge_watchdog(struct stge_softc *); 134160641Syongaristatic int stge_ioctl(struct ifnet *, u_long, caddr_t); 135160641Syongaristatic void stge_init(void *); 136160641Syongaristatic void stge_init_locked(struct stge_softc *); 137160641Syongaristatic void stge_vlan_setup(struct stge_softc *); 138160641Syongaristatic void stge_stop(struct stge_softc *); 139160641Syongaristatic void stge_start_tx(struct stge_softc *); 140160641Syongaristatic void stge_start_rx(struct stge_softc *); 141160641Syongaristatic void stge_stop_tx(struct stge_softc *); 142160641Syongaristatic void stge_stop_rx(struct stge_softc *); 143160641Syongari 144160641Syongaristatic void stge_reset(struct stge_softc *, uint32_t); 145160641Syongaristatic int stge_eeprom_wait(struct stge_softc *); 146160641Syongaristatic void stge_read_eeprom(struct stge_softc *, int, uint16_t *); 147160641Syongaristatic void stge_tick(void *); 148160641Syongaristatic void stge_stats_update(struct stge_softc *); 149160641Syongaristatic void stge_set_filter(struct stge_softc *); 150160641Syongaristatic void stge_set_multi(struct stge_softc *); 151160641Syongari 152160641Syongaristatic void stge_link_task(void *, int); 153160641Syongaristatic void stge_intr(void *); 154160641Syongaristatic __inline int stge_tx_error(struct stge_softc *); 155160641Syongaristatic void stge_txeof(struct stge_softc *); 156193096Sattiliostatic int stge_rxeof(struct stge_softc *); 157160641Syongaristatic __inline void stge_discard_rxbuf(struct stge_softc *, int); 158160641Syongaristatic int stge_newbuf(struct stge_softc *, int); 159160641Syongari#ifndef __NO_STRICT_ALIGNMENT 160160641Syongaristatic __inline struct mbuf *stge_fixup_rx(struct stge_softc *, struct mbuf *); 161160641Syongari#endif 162160641Syongari 163160641Syongaristatic void stge_mii_sync(struct stge_softc *); 164160641Syongaristatic void stge_mii_send(struct stge_softc *, uint32_t, int); 165160641Syongaristatic int stge_mii_readreg(struct stge_softc *, struct stge_mii_frame *); 166160641Syongaristatic int stge_mii_writereg(struct stge_softc *, struct stge_mii_frame *); 167160641Syongaristatic int stge_miibus_readreg(device_t, int, int); 168160641Syongaristatic int stge_miibus_writereg(device_t, int, int, int); 169160641Syongaristatic void stge_miibus_statchg(device_t); 170160641Syongaristatic int stge_mediachange(struct ifnet *); 171160641Syongaristatic void stge_mediastatus(struct ifnet *, struct ifmediareq *); 172160641Syongari 173160641Syongaristatic void stge_dmamap_cb(void *, bus_dma_segment_t *, int, int); 174160641Syongaristatic int stge_dma_alloc(struct stge_softc *); 175160641Syongaristatic void stge_dma_free(struct stge_softc *); 176160641Syongaristatic void stge_dma_wait(struct stge_softc *); 177160641Syongaristatic void stge_init_tx_ring(struct stge_softc *); 178160641Syongaristatic int stge_init_rx_ring(struct stge_softc *); 179160641Syongari#ifdef DEVICE_POLLING 180193096Sattiliostatic int stge_poll(struct ifnet *, enum poll_cmd, int); 181160641Syongari#endif 182160641Syongari 183175315Syongaristatic void stge_setwol(struct stge_softc *); 184160641Syongaristatic int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int); 185160641Syongaristatic int sysctl_hw_stge_rxint_nframe(SYSCTL_HANDLER_ARGS); 186160641Syongaristatic int sysctl_hw_stge_rxint_dmawait(SYSCTL_HANDLER_ARGS); 187160641Syongari 188160641Syongaristatic device_method_t stge_methods[] = { 189160641Syongari /* Device interface */ 190160641Syongari DEVMETHOD(device_probe, stge_probe), 191160641Syongari DEVMETHOD(device_attach, stge_attach), 192160641Syongari DEVMETHOD(device_detach, stge_detach), 193160641Syongari DEVMETHOD(device_shutdown, stge_shutdown), 194160641Syongari DEVMETHOD(device_suspend, stge_suspend), 195160641Syongari DEVMETHOD(device_resume, stge_resume), 196160641Syongari 197160641Syongari /* MII interface */ 198160641Syongari DEVMETHOD(miibus_readreg, stge_miibus_readreg), 199160641Syongari DEVMETHOD(miibus_writereg, stge_miibus_writereg), 200160641Syongari DEVMETHOD(miibus_statchg, stge_miibus_statchg), 201160641Syongari 202160641Syongari { 0, 0 } 203160641Syongari 204160641Syongari}; 205160641Syongari 206160641Syongaristatic driver_t stge_driver = { 207160641Syongari "stge", 208160641Syongari stge_methods, 209160641Syongari sizeof(struct stge_softc) 210160641Syongari}; 211160641Syongari 212160641Syongaristatic devclass_t stge_devclass; 213160641Syongari 214160641SyongariDRIVER_MODULE(stge, pci, stge_driver, stge_devclass, 0, 0); 215160641SyongariDRIVER_MODULE(miibus, stge, miibus_driver, miibus_devclass, 0, 0); 216160641Syongari 217160641Syongaristatic struct resource_spec stge_res_spec_io[] = { 218160641Syongari { SYS_RES_IOPORT, PCIR_BAR(0), RF_ACTIVE }, 219160641Syongari { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, 220160641Syongari { -1, 0, 0 } 221160641Syongari}; 222160641Syongari 223160641Syongaristatic struct resource_spec stge_res_spec_mem[] = { 224160641Syongari { SYS_RES_MEMORY, PCIR_BAR(1), RF_ACTIVE }, 225160641Syongari { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE }, 226160641Syongari { -1, 0, 0 } 227160641Syongari}; 228160641Syongari 229160641Syongari#define MII_SET(x) \ 230160641Syongari CSR_WRITE_1(sc, STGE_PhyCtrl, CSR_READ_1(sc, STGE_PhyCtrl) | (x)) 231160641Syongari#define MII_CLR(x) \ 232160641Syongari CSR_WRITE_1(sc, STGE_PhyCtrl, CSR_READ_1(sc, STGE_PhyCtrl) & ~(x)) 233160641Syongari 234160641Syongari/* 235160641Syongari * Sync the PHYs by setting data bit and strobing the clock 32 times. 236160641Syongari */ 237160641Syongaristatic void 238160641Syongaristge_mii_sync(struct stge_softc *sc) 239160641Syongari{ 240160641Syongari int i; 241160641Syongari 242160641Syongari MII_SET(PC_MgmtDir | PC_MgmtData); 243160641Syongari 244160641Syongari for (i = 0; i < 32; i++) { 245160641Syongari MII_SET(PC_MgmtClk); 246160641Syongari DELAY(1); 247160641Syongari MII_CLR(PC_MgmtClk); 248160641Syongari DELAY(1); 249160641Syongari } 250160641Syongari} 251160641Syongari 252160641Syongari/* 253160641Syongari * Clock a series of bits through the MII. 254160641Syongari */ 255160641Syongaristatic void 256160641Syongaristge_mii_send(struct stge_softc *sc, uint32_t bits, int cnt) 257160641Syongari{ 258160641Syongari int i; 259160641Syongari 260160641Syongari MII_CLR(PC_MgmtClk); 261160641Syongari 262160641Syongari for (i = (0x1 << (cnt - 1)); i; i >>= 1) { 263160641Syongari if (bits & i) 264160641Syongari MII_SET(PC_MgmtData); 265160641Syongari else 266160641Syongari MII_CLR(PC_MgmtData); 267160641Syongari DELAY(1); 268160641Syongari MII_CLR(PC_MgmtClk); 269160641Syongari DELAY(1); 270160641Syongari MII_SET(PC_MgmtClk); 271160641Syongari } 272160641Syongari} 273160641Syongari 274160641Syongari/* 275160641Syongari * Read an PHY register through the MII. 276160641Syongari */ 277160641Syongaristatic int 278160641Syongaristge_mii_readreg(struct stge_softc *sc, struct stge_mii_frame *frame) 279160641Syongari{ 280160641Syongari int i, ack; 281160641Syongari 282160641Syongari /* 283160641Syongari * Set up frame for RX. 284160641Syongari */ 285160641Syongari frame->mii_stdelim = STGE_MII_STARTDELIM; 286160641Syongari frame->mii_opcode = STGE_MII_READOP; 287160641Syongari frame->mii_turnaround = 0; 288160641Syongari frame->mii_data = 0; 289160641Syongari 290160641Syongari CSR_WRITE_1(sc, STGE_PhyCtrl, 0 | sc->sc_PhyCtrl); 291160641Syongari /* 292160641Syongari * Turn on data xmit. 293160641Syongari */ 294160641Syongari MII_SET(PC_MgmtDir); 295160641Syongari 296160641Syongari stge_mii_sync(sc); 297160641Syongari 298160641Syongari /* 299160641Syongari * Send command/address info. 300160641Syongari */ 301160641Syongari stge_mii_send(sc, frame->mii_stdelim, 2); 302160641Syongari stge_mii_send(sc, frame->mii_opcode, 2); 303160641Syongari stge_mii_send(sc, frame->mii_phyaddr, 5); 304160641Syongari stge_mii_send(sc, frame->mii_regaddr, 5); 305160641Syongari 306160641Syongari /* Turn off xmit. */ 307160641Syongari MII_CLR(PC_MgmtDir); 308160641Syongari 309160641Syongari /* Idle bit */ 310160641Syongari MII_CLR((PC_MgmtClk | PC_MgmtData)); 311160641Syongari DELAY(1); 312160641Syongari MII_SET(PC_MgmtClk); 313160641Syongari DELAY(1); 314160641Syongari 315160641Syongari /* Check for ack */ 316160641Syongari MII_CLR(PC_MgmtClk); 317160641Syongari DELAY(1); 318160641Syongari ack = CSR_READ_1(sc, STGE_PhyCtrl) & PC_MgmtData; 319160641Syongari MII_SET(PC_MgmtClk); 320160641Syongari DELAY(1); 321160641Syongari 322160641Syongari /* 323160641Syongari * Now try reading data bits. If the ack failed, we still 324160641Syongari * need to clock through 16 cycles to keep the PHY(s) in sync. 325160641Syongari */ 326160641Syongari if (ack) { 327160641Syongari for(i = 0; i < 16; i++) { 328160641Syongari MII_CLR(PC_MgmtClk); 329160641Syongari DELAY(1); 330160641Syongari MII_SET(PC_MgmtClk); 331160641Syongari DELAY(1); 332160641Syongari } 333160641Syongari goto fail; 334160641Syongari } 335160641Syongari 336160641Syongari for (i = 0x8000; i; i >>= 1) { 337160641Syongari MII_CLR(PC_MgmtClk); 338160641Syongari DELAY(1); 339160641Syongari if (!ack) { 340160641Syongari if (CSR_READ_1(sc, STGE_PhyCtrl) & PC_MgmtData) 341160641Syongari frame->mii_data |= i; 342160641Syongari DELAY(1); 343160641Syongari } 344160641Syongari MII_SET(PC_MgmtClk); 345160641Syongari DELAY(1); 346160641Syongari } 347160641Syongari 348160641Syongarifail: 349160641Syongari MII_CLR(PC_MgmtClk); 350160641Syongari DELAY(1); 351160641Syongari MII_SET(PC_MgmtClk); 352160641Syongari DELAY(1); 353160641Syongari 354160641Syongari if (ack) 355160641Syongari return(1); 356160641Syongari return(0); 357160641Syongari} 358160641Syongari 359160641Syongari/* 360160641Syongari * Write to a PHY register through the MII. 361160641Syongari */ 362160641Syongaristatic int 363160641Syongaristge_mii_writereg(struct stge_softc *sc, struct stge_mii_frame *frame) 364160641Syongari{ 365160641Syongari 366160641Syongari /* 367160641Syongari * Set up frame for TX. 368160641Syongari */ 369160641Syongari frame->mii_stdelim = STGE_MII_STARTDELIM; 370160641Syongari frame->mii_opcode = STGE_MII_WRITEOP; 371160641Syongari frame->mii_turnaround = STGE_MII_TURNAROUND; 372160641Syongari 373160641Syongari /* 374160641Syongari * Turn on data output. 375160641Syongari */ 376160641Syongari MII_SET(PC_MgmtDir); 377160641Syongari 378160641Syongari stge_mii_sync(sc); 379160641Syongari 380160641Syongari stge_mii_send(sc, frame->mii_stdelim, 2); 381160641Syongari stge_mii_send(sc, frame->mii_opcode, 2); 382160641Syongari stge_mii_send(sc, frame->mii_phyaddr, 5); 383160641Syongari stge_mii_send(sc, frame->mii_regaddr, 5); 384160641Syongari stge_mii_send(sc, frame->mii_turnaround, 2); 385160641Syongari stge_mii_send(sc, frame->mii_data, 16); 386160641Syongari 387160641Syongari /* Idle bit. */ 388160641Syongari MII_SET(PC_MgmtClk); 389160641Syongari DELAY(1); 390160641Syongari MII_CLR(PC_MgmtClk); 391160641Syongari DELAY(1); 392160641Syongari 393160641Syongari /* 394160641Syongari * Turn off xmit. 395160641Syongari */ 396160641Syongari MII_CLR(PC_MgmtDir); 397160641Syongari 398160641Syongari return(0); 399160641Syongari} 400160641Syongari 401160641Syongari/* 402160641Syongari * sc_miibus_readreg: [mii interface function] 403160641Syongari * 404160641Syongari * Read a PHY register on the MII of the TC9021. 405160641Syongari */ 406160641Syongaristatic int 407160641Syongaristge_miibus_readreg(device_t dev, int phy, int reg) 408160641Syongari{ 409160641Syongari struct stge_softc *sc; 410160641Syongari struct stge_mii_frame frame; 411160641Syongari int error; 412160641Syongari 413160641Syongari sc = device_get_softc(dev); 414160641Syongari 415160641Syongari if (reg == STGE_PhyCtrl) { 416160641Syongari /* XXX allow ip1000phy read STGE_PhyCtrl register. */ 417160641Syongari STGE_MII_LOCK(sc); 418160641Syongari error = CSR_READ_1(sc, STGE_PhyCtrl); 419160641Syongari STGE_MII_UNLOCK(sc); 420160641Syongari return (error); 421160641Syongari } 422160641Syongari bzero(&frame, sizeof(frame)); 423160641Syongari frame.mii_phyaddr = phy; 424160641Syongari frame.mii_regaddr = reg; 425160641Syongari 426160641Syongari STGE_MII_LOCK(sc); 427160641Syongari error = stge_mii_readreg(sc, &frame); 428160641Syongari STGE_MII_UNLOCK(sc); 429160641Syongari 430160641Syongari if (error != 0) { 431160641Syongari /* Don't show errors for PHY probe request */ 432160641Syongari if (reg != 1) 433160641Syongari device_printf(sc->sc_dev, "phy read fail\n"); 434160641Syongari return (0); 435160641Syongari } 436160641Syongari return (frame.mii_data); 437160641Syongari} 438160641Syongari 439160641Syongari/* 440160641Syongari * stge_miibus_writereg: [mii interface function] 441160641Syongari * 442160641Syongari * Write a PHY register on the MII of the TC9021. 443160641Syongari */ 444160641Syongaristatic int 445160641Syongaristge_miibus_writereg(device_t dev, int phy, int reg, int val) 446160641Syongari{ 447160641Syongari struct stge_softc *sc; 448160641Syongari struct stge_mii_frame frame; 449160641Syongari int error; 450160641Syongari 451160641Syongari sc = device_get_softc(dev); 452160641Syongari 453160641Syongari bzero(&frame, sizeof(frame)); 454160641Syongari frame.mii_phyaddr = phy; 455160641Syongari frame.mii_regaddr = reg; 456160641Syongari frame.mii_data = val; 457160641Syongari 458160641Syongari STGE_MII_LOCK(sc); 459160641Syongari error = stge_mii_writereg(sc, &frame); 460160641Syongari STGE_MII_UNLOCK(sc); 461160641Syongari 462160641Syongari if (error != 0) 463160641Syongari device_printf(sc->sc_dev, "phy write fail\n"); 464160641Syongari return (0); 465160641Syongari} 466160641Syongari 467160641Syongari/* 468160641Syongari * stge_miibus_statchg: [mii interface function] 469160641Syongari * 470160641Syongari * Callback from MII layer when media changes. 471160641Syongari */ 472160641Syongaristatic void 473160641Syongaristge_miibus_statchg(device_t dev) 474160641Syongari{ 475160641Syongari struct stge_softc *sc; 476160641Syongari 477160641Syongari sc = device_get_softc(dev); 478160641Syongari taskqueue_enqueue(taskqueue_swi, &sc->sc_link_task); 479160641Syongari} 480160641Syongari 481160641Syongari/* 482160641Syongari * stge_mediastatus: [ifmedia interface function] 483160641Syongari * 484160641Syongari * Get the current interface media status. 485160641Syongari */ 486160641Syongaristatic void 487160641Syongaristge_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 488160641Syongari{ 489160641Syongari struct stge_softc *sc; 490160641Syongari struct mii_data *mii; 491160641Syongari 492160641Syongari sc = ifp->if_softc; 493160641Syongari mii = device_get_softc(sc->sc_miibus); 494160641Syongari 495160641Syongari mii_pollstat(mii); 496160641Syongari ifmr->ifm_status = mii->mii_media_status; 497160641Syongari ifmr->ifm_active = mii->mii_media_active; 498160641Syongari} 499160641Syongari 500160641Syongari/* 501160641Syongari * stge_mediachange: [ifmedia interface function] 502160641Syongari * 503160641Syongari * Set hardware to newly-selected media. 504160641Syongari */ 505160641Syongaristatic int 506160641Syongaristge_mediachange(struct ifnet *ifp) 507160641Syongari{ 508160641Syongari struct stge_softc *sc; 509160641Syongari struct mii_data *mii; 510160641Syongari 511160641Syongari sc = ifp->if_softc; 512160641Syongari mii = device_get_softc(sc->sc_miibus); 513160641Syongari mii_mediachg(mii); 514160641Syongari 515160641Syongari return (0); 516160641Syongari} 517160641Syongari 518160641Syongaristatic int 519160641Syongaristge_eeprom_wait(struct stge_softc *sc) 520160641Syongari{ 521160641Syongari int i; 522160641Syongari 523160641Syongari for (i = 0; i < STGE_TIMEOUT; i++) { 524160641Syongari DELAY(1000); 525160641Syongari if ((CSR_READ_2(sc, STGE_EepromCtrl) & EC_EepromBusy) == 0) 526160641Syongari return (0); 527160641Syongari } 528160641Syongari return (1); 529160641Syongari} 530160641Syongari 531160641Syongari/* 532160641Syongari * stge_read_eeprom: 533160641Syongari * 534160641Syongari * Read data from the serial EEPROM. 535160641Syongari */ 536160641Syongaristatic void 537160641Syongaristge_read_eeprom(struct stge_softc *sc, int offset, uint16_t *data) 538160641Syongari{ 539160641Syongari 540160641Syongari if (stge_eeprom_wait(sc)) 541160641Syongari device_printf(sc->sc_dev, "EEPROM failed to come ready\n"); 542160641Syongari 543160641Syongari CSR_WRITE_2(sc, STGE_EepromCtrl, 544160641Syongari EC_EepromAddress(offset) | EC_EepromOpcode(EC_OP_RR)); 545160641Syongari if (stge_eeprom_wait(sc)) 546160641Syongari device_printf(sc->sc_dev, "EEPROM read timed out\n"); 547160641Syongari *data = CSR_READ_2(sc, STGE_EepromData); 548160641Syongari} 549160641Syongari 550160641Syongari 551160641Syongaristatic int 552160641Syongaristge_probe(device_t dev) 553160641Syongari{ 554160641Syongari struct stge_product *sp; 555160641Syongari int i; 556160641Syongari uint16_t vendor, devid; 557160641Syongari 558160641Syongari vendor = pci_get_vendor(dev); 559160641Syongari devid = pci_get_device(dev); 560160641Syongari sp = stge_products; 561160641Syongari for (i = 0; i < sizeof(stge_products)/sizeof(stge_products[0]); 562160641Syongari i++, sp++) { 563160641Syongari if (vendor == sp->stge_vendorid && 564160641Syongari devid == sp->stge_deviceid) { 565160641Syongari device_set_desc(dev, sp->stge_name); 566160641Syongari return (BUS_PROBE_DEFAULT); 567160641Syongari } 568160641Syongari } 569160641Syongari 570160641Syongari return (ENXIO); 571160641Syongari} 572160641Syongari 573160641Syongaristatic int 574160641Syongaristge_attach(device_t dev) 575160641Syongari{ 576160641Syongari struct stge_softc *sc; 577160641Syongari struct ifnet *ifp; 578160641Syongari uint8_t enaddr[ETHER_ADDR_LEN]; 579213893Smarius int error, flags, i; 580160641Syongari uint16_t cmd; 581160641Syongari uint32_t val; 582160641Syongari 583160641Syongari error = 0; 584160641Syongari sc = device_get_softc(dev); 585160641Syongari sc->sc_dev = dev; 586160641Syongari 587160641Syongari mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 588160641Syongari MTX_DEF); 589160641Syongari mtx_init(&sc->sc_mii_mtx, "stge_mii_mutex", NULL, MTX_DEF); 590160641Syongari callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); 591160641Syongari TASK_INIT(&sc->sc_link_task, 0, stge_link_task, sc); 592160641Syongari 593160641Syongari /* 594160641Syongari * Map the device. 595160641Syongari */ 596160641Syongari pci_enable_busmaster(dev); 597160641Syongari cmd = pci_read_config(dev, PCIR_COMMAND, 2); 598160641Syongari val = pci_read_config(dev, PCIR_BAR(1), 4); 599160641Syongari if ((val & 0x01) != 0) 600160641Syongari sc->sc_spec = stge_res_spec_mem; 601160641Syongari else { 602160641Syongari val = pci_read_config(dev, PCIR_BAR(0), 4); 603160641Syongari if ((val & 0x01) == 0) { 604160641Syongari device_printf(sc->sc_dev, "couldn't locate IO BAR\n"); 605160641Syongari error = ENXIO; 606160641Syongari goto fail; 607160641Syongari } 608160641Syongari sc->sc_spec = stge_res_spec_io; 609160641Syongari } 610160641Syongari error = bus_alloc_resources(dev, sc->sc_spec, sc->sc_res); 611160641Syongari if (error != 0) { 612160641Syongari device_printf(dev, "couldn't allocate %s resources\n", 613160641Syongari sc->sc_spec == stge_res_spec_mem ? "memory" : "I/O"); 614160641Syongari goto fail; 615160641Syongari } 616160641Syongari sc->sc_rev = pci_get_revid(dev); 617160641Syongari 618160641Syongari SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 619160641Syongari SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 620160641Syongari "rxint_nframe", CTLTYPE_INT|CTLFLAG_RW, &sc->sc_rxint_nframe, 0, 621160641Syongari sysctl_hw_stge_rxint_nframe, "I", "stge rx interrupt nframe"); 622160641Syongari 623160641Syongari SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 624160641Syongari SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 625160641Syongari "rxint_dmawait", CTLTYPE_INT|CTLFLAG_RW, &sc->sc_rxint_dmawait, 0, 626160641Syongari sysctl_hw_stge_rxint_dmawait, "I", "stge rx interrupt dmawait"); 627160641Syongari 628160641Syongari /* Pull in device tunables. */ 629160641Syongari sc->sc_rxint_nframe = STGE_RXINT_NFRAME_DEFAULT; 630160641Syongari error = resource_int_value(device_get_name(dev), device_get_unit(dev), 631160641Syongari "rxint_nframe", &sc->sc_rxint_nframe); 632160641Syongari if (error == 0) { 633160641Syongari if (sc->sc_rxint_nframe < STGE_RXINT_NFRAME_MIN || 634160641Syongari sc->sc_rxint_nframe > STGE_RXINT_NFRAME_MAX) { 635160641Syongari device_printf(dev, "rxint_nframe value out of range; " 636160641Syongari "using default: %d\n", STGE_RXINT_NFRAME_DEFAULT); 637160641Syongari sc->sc_rxint_nframe = STGE_RXINT_NFRAME_DEFAULT; 638160641Syongari } 639160641Syongari } 640160641Syongari 641160641Syongari sc->sc_rxint_dmawait = STGE_RXINT_DMAWAIT_DEFAULT; 642160641Syongari error = resource_int_value(device_get_name(dev), device_get_unit(dev), 643160641Syongari "rxint_dmawait", &sc->sc_rxint_dmawait); 644160641Syongari if (error == 0) { 645160641Syongari if (sc->sc_rxint_dmawait < STGE_RXINT_DMAWAIT_MIN || 646160641Syongari sc->sc_rxint_dmawait > STGE_RXINT_DMAWAIT_MAX) { 647160641Syongari device_printf(dev, "rxint_dmawait value out of range; " 648160641Syongari "using default: %d\n", STGE_RXINT_DMAWAIT_DEFAULT); 649160641Syongari sc->sc_rxint_dmawait = STGE_RXINT_DMAWAIT_DEFAULT; 650160641Syongari } 651160641Syongari } 652160641Syongari 653160641Syongari if ((error = stge_dma_alloc(sc) != 0)) 654160641Syongari goto fail; 655160641Syongari 656160641Syongari /* 657160641Syongari * Determine if we're copper or fiber. It affects how we 658160641Syongari * reset the card. 659160641Syongari */ 660160641Syongari if (CSR_READ_4(sc, STGE_AsicCtrl) & AC_PhyMedia) 661160641Syongari sc->sc_usefiber = 1; 662160641Syongari else 663160641Syongari sc->sc_usefiber = 0; 664160641Syongari 665160641Syongari /* Load LED configuration from EEPROM. */ 666160641Syongari stge_read_eeprom(sc, STGE_EEPROM_LEDMode, &sc->sc_led); 667160641Syongari 668160641Syongari /* 669160641Syongari * Reset the chip to a known state. 670160641Syongari */ 671160641Syongari STGE_LOCK(sc); 672160641Syongari stge_reset(sc, STGE_RESET_FULL); 673160641Syongari STGE_UNLOCK(sc); 674160641Syongari 675160641Syongari /* 676160641Syongari * Reading the station address from the EEPROM doesn't seem 677160641Syongari * to work, at least on my sample boards. Instead, since 678160641Syongari * the reset sequence does AutoInit, read it from the station 679160641Syongari * address registers. For Sundance 1023 you can only read it 680160641Syongari * from EEPROM. 681160641Syongari */ 682160641Syongari if (pci_get_device(dev) != DEVICEID_SUNDANCETI_ST1023) { 683160641Syongari uint16_t v; 684160641Syongari 685160641Syongari v = CSR_READ_2(sc, STGE_StationAddress0); 686160641Syongari enaddr[0] = v & 0xff; 687160641Syongari enaddr[1] = v >> 8; 688160641Syongari v = CSR_READ_2(sc, STGE_StationAddress1); 689160641Syongari enaddr[2] = v & 0xff; 690160641Syongari enaddr[3] = v >> 8; 691160641Syongari v = CSR_READ_2(sc, STGE_StationAddress2); 692160641Syongari enaddr[4] = v & 0xff; 693160641Syongari enaddr[5] = v >> 8; 694160641Syongari sc->sc_stge1023 = 0; 695160641Syongari } else { 696160641Syongari uint16_t myaddr[ETHER_ADDR_LEN / 2]; 697160641Syongari for (i = 0; i <ETHER_ADDR_LEN / 2; i++) { 698160641Syongari stge_read_eeprom(sc, STGE_EEPROM_StationAddress0 + i, 699160641Syongari &myaddr[i]); 700160641Syongari myaddr[i] = le16toh(myaddr[i]); 701160641Syongari } 702160641Syongari bcopy(myaddr, enaddr, sizeof(enaddr)); 703160641Syongari sc->sc_stge1023 = 1; 704160641Syongari } 705160641Syongari 706160641Syongari ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 707160641Syongari if (ifp == NULL) { 708160641Syongari device_printf(sc->sc_dev, "failed to if_alloc()\n"); 709160641Syongari error = ENXIO; 710160641Syongari goto fail; 711160641Syongari } 712160641Syongari 713160641Syongari ifp->if_softc = sc; 714160641Syongari if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 715160641Syongari ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 716160641Syongari ifp->if_ioctl = stge_ioctl; 717160641Syongari ifp->if_start = stge_start; 718160641Syongari ifp->if_init = stge_init; 719160641Syongari ifp->if_mtu = ETHERMTU; 720160641Syongari ifp->if_snd.ifq_drv_maxlen = STGE_TX_RING_CNT - 1; 721160641Syongari IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 722160641Syongari IFQ_SET_READY(&ifp->if_snd); 723160641Syongari /* Revision B3 and earlier chips have checksum bug. */ 724160641Syongari if (sc->sc_rev >= 0x0c) { 725160641Syongari ifp->if_hwassist = STGE_CSUM_FEATURES; 726160641Syongari ifp->if_capabilities = IFCAP_HWCSUM; 727160641Syongari } else { 728160641Syongari ifp->if_hwassist = 0; 729160641Syongari ifp->if_capabilities = 0; 730160641Syongari } 731175315Syongari ifp->if_capabilities |= IFCAP_WOL_MAGIC; 732160641Syongari ifp->if_capenable = ifp->if_capabilities; 733160641Syongari 734160641Syongari /* 735160641Syongari * Read some important bits from the PhyCtrl register. 736160641Syongari */ 737160641Syongari sc->sc_PhyCtrl = CSR_READ_1(sc, STGE_PhyCtrl) & 738160641Syongari (PC_PhyDuplexPolarity | PC_PhyLnkPolarity); 739160641Syongari 740160641Syongari /* Set up MII bus. */ 741215297Smarius flags = MIIF_DOPAUSE; 742213893Smarius if (sc->sc_rev >= 0x40 && sc->sc_rev <= 0x4e) 743213893Smarius flags |= MIIF_MACPRIV0; 744213893Smarius error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, stge_mediachange, 745213893Smarius stge_mediastatus, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 746213893Smarius flags); 747213893Smarius if (error != 0) { 748213893Smarius device_printf(sc->sc_dev, "attaching PHYs failed\n"); 749160641Syongari goto fail; 750160641Syongari } 751160641Syongari 752160641Syongari ether_ifattach(ifp, enaddr); 753160641Syongari 754160641Syongari /* VLAN capability setup */ 755160641Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING; 756160641Syongari if (sc->sc_rev >= 0x0c) 757160641Syongari ifp->if_capabilities |= IFCAP_VLAN_HWCSUM; 758160641Syongari ifp->if_capenable = ifp->if_capabilities; 759160641Syongari#ifdef DEVICE_POLLING 760160641Syongari ifp->if_capabilities |= IFCAP_POLLING; 761160641Syongari#endif 762160641Syongari /* 763160641Syongari * Tell the upper layer(s) we support long frames. 764160641Syongari * Must appear after the call to ether_ifattach() because 765160641Syongari * ether_ifattach() sets ifi_hdrlen to the default value. 766160641Syongari */ 767160641Syongari ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 768160641Syongari 769160641Syongari /* 770160641Syongari * The manual recommends disabling early transmit, so we 771160641Syongari * do. It's disabled anyway, if using IP checksumming, 772160641Syongari * since the entire packet must be in the FIFO in order 773160641Syongari * for the chip to perform the checksum. 774160641Syongari */ 775160641Syongari sc->sc_txthresh = 0x0fff; 776160641Syongari 777160641Syongari /* 778160641Syongari * Disable MWI if the PCI layer tells us to. 779160641Syongari */ 780160641Syongari sc->sc_DMACtrl = 0; 781160641Syongari if ((cmd & PCIM_CMD_MWRICEN) == 0) 782160641Syongari sc->sc_DMACtrl |= DMAC_MWIDisable; 783160641Syongari 784160641Syongari /* 785160641Syongari * Hookup IRQ 786160641Syongari */ 787160641Syongari error = bus_setup_intr(dev, sc->sc_res[1], INTR_TYPE_NET | INTR_MPSAFE, 788166901Spiso NULL, stge_intr, sc, &sc->sc_ih); 789160641Syongari if (error != 0) { 790160641Syongari ether_ifdetach(ifp); 791160641Syongari device_printf(sc->sc_dev, "couldn't set up IRQ\n"); 792160641Syongari sc->sc_ifp = NULL; 793160641Syongari goto fail; 794160641Syongari } 795160641Syongari 796160641Syongarifail: 797160641Syongari if (error != 0) 798160641Syongari stge_detach(dev); 799160641Syongari 800160641Syongari return (error); 801160641Syongari} 802160641Syongari 803160641Syongaristatic int 804160641Syongaristge_detach(device_t dev) 805160641Syongari{ 806160641Syongari struct stge_softc *sc; 807160641Syongari struct ifnet *ifp; 808160641Syongari 809160641Syongari sc = device_get_softc(dev); 810160641Syongari 811160641Syongari ifp = sc->sc_ifp; 812160641Syongari#ifdef DEVICE_POLLING 813160641Syongari if (ifp && ifp->if_capenable & IFCAP_POLLING) 814160641Syongari ether_poll_deregister(ifp); 815160641Syongari#endif 816160641Syongari if (device_is_attached(dev)) { 817160641Syongari STGE_LOCK(sc); 818160641Syongari /* XXX */ 819160641Syongari sc->sc_detach = 1; 820160641Syongari stge_stop(sc); 821160641Syongari STGE_UNLOCK(sc); 822160641Syongari callout_drain(&sc->sc_tick_ch); 823160641Syongari taskqueue_drain(taskqueue_swi, &sc->sc_link_task); 824160641Syongari ether_ifdetach(ifp); 825160641Syongari } 826160641Syongari 827160641Syongari if (sc->sc_miibus != NULL) { 828160641Syongari device_delete_child(dev, sc->sc_miibus); 829160641Syongari sc->sc_miibus = NULL; 830160641Syongari } 831160641Syongari bus_generic_detach(dev); 832160641Syongari stge_dma_free(sc); 833160641Syongari 834160641Syongari if (ifp != NULL) { 835160641Syongari if_free(ifp); 836160641Syongari sc->sc_ifp = NULL; 837160641Syongari } 838160641Syongari 839160641Syongari if (sc->sc_ih) { 840160641Syongari bus_teardown_intr(dev, sc->sc_res[1], sc->sc_ih); 841160641Syongari sc->sc_ih = NULL; 842160641Syongari } 843160641Syongari bus_release_resources(dev, sc->sc_spec, sc->sc_res); 844160641Syongari 845160641Syongari mtx_destroy(&sc->sc_mii_mtx); 846160641Syongari mtx_destroy(&sc->sc_mtx); 847160641Syongari 848160641Syongari return (0); 849160641Syongari} 850160641Syongari 851160641Syongaristruct stge_dmamap_arg { 852160641Syongari bus_addr_t stge_busaddr; 853160641Syongari}; 854160641Syongari 855160641Syongaristatic void 856160641Syongaristge_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 857160641Syongari{ 858160641Syongari struct stge_dmamap_arg *ctx; 859160641Syongari 860160641Syongari if (error != 0) 861160641Syongari return; 862160641Syongari 863160641Syongari ctx = (struct stge_dmamap_arg *)arg; 864160641Syongari ctx->stge_busaddr = segs[0].ds_addr; 865160641Syongari} 866160641Syongari 867160641Syongaristatic int 868160641Syongaristge_dma_alloc(struct stge_softc *sc) 869160641Syongari{ 870160641Syongari struct stge_dmamap_arg ctx; 871160641Syongari struct stge_txdesc *txd; 872160641Syongari struct stge_rxdesc *rxd; 873160641Syongari int error, i; 874160641Syongari 875160641Syongari /* create parent tag. */ 876166165Smarius error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),/* parent */ 877160641Syongari 1, 0, /* algnmnt, boundary */ 878160641Syongari STGE_DMA_MAXADDR, /* lowaddr */ 879160641Syongari BUS_SPACE_MAXADDR, /* highaddr */ 880160641Syongari NULL, NULL, /* filter, filterarg */ 881160641Syongari BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 882160641Syongari 0, /* nsegments */ 883160641Syongari BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 884160641Syongari 0, /* flags */ 885160641Syongari NULL, NULL, /* lockfunc, lockarg */ 886160641Syongari &sc->sc_cdata.stge_parent_tag); 887160641Syongari if (error != 0) { 888160641Syongari device_printf(sc->sc_dev, "failed to create parent DMA tag\n"); 889160641Syongari goto fail; 890160641Syongari } 891160641Syongari /* create tag for Tx ring. */ 892160641Syongari error = bus_dma_tag_create(sc->sc_cdata.stge_parent_tag,/* parent */ 893160641Syongari STGE_RING_ALIGN, 0, /* algnmnt, boundary */ 894160641Syongari BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 895160641Syongari BUS_SPACE_MAXADDR, /* highaddr */ 896160641Syongari NULL, NULL, /* filter, filterarg */ 897160641Syongari STGE_TX_RING_SZ, /* maxsize */ 898160641Syongari 1, /* nsegments */ 899160641Syongari STGE_TX_RING_SZ, /* maxsegsize */ 900160641Syongari 0, /* flags */ 901160641Syongari NULL, NULL, /* lockfunc, lockarg */ 902160641Syongari &sc->sc_cdata.stge_tx_ring_tag); 903160641Syongari if (error != 0) { 904160641Syongari device_printf(sc->sc_dev, 905160641Syongari "failed to allocate Tx ring DMA tag\n"); 906160641Syongari goto fail; 907160641Syongari } 908160641Syongari 909160641Syongari /* create tag for Rx ring. */ 910160641Syongari error = bus_dma_tag_create(sc->sc_cdata.stge_parent_tag,/* parent */ 911160641Syongari STGE_RING_ALIGN, 0, /* algnmnt, boundary */ 912160641Syongari BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 913160641Syongari BUS_SPACE_MAXADDR, /* highaddr */ 914160641Syongari NULL, NULL, /* filter, filterarg */ 915160641Syongari STGE_RX_RING_SZ, /* maxsize */ 916160641Syongari 1, /* nsegments */ 917160641Syongari STGE_RX_RING_SZ, /* maxsegsize */ 918160641Syongari 0, /* flags */ 919160641Syongari NULL, NULL, /* lockfunc, lockarg */ 920160641Syongari &sc->sc_cdata.stge_rx_ring_tag); 921160641Syongari if (error != 0) { 922160641Syongari device_printf(sc->sc_dev, 923160641Syongari "failed to allocate Rx ring DMA tag\n"); 924160641Syongari goto fail; 925160641Syongari } 926160641Syongari 927160641Syongari /* create tag for Tx buffers. */ 928160641Syongari error = bus_dma_tag_create(sc->sc_cdata.stge_parent_tag,/* parent */ 929160641Syongari 1, 0, /* algnmnt, boundary */ 930160641Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 931160641Syongari BUS_SPACE_MAXADDR, /* highaddr */ 932160641Syongari NULL, NULL, /* filter, filterarg */ 933160641Syongari MCLBYTES * STGE_MAXTXSEGS, /* maxsize */ 934160641Syongari STGE_MAXTXSEGS, /* nsegments */ 935160641Syongari MCLBYTES, /* maxsegsize */ 936160641Syongari 0, /* flags */ 937160641Syongari NULL, NULL, /* lockfunc, lockarg */ 938160641Syongari &sc->sc_cdata.stge_tx_tag); 939160641Syongari if (error != 0) { 940160641Syongari device_printf(sc->sc_dev, "failed to allocate Tx DMA tag\n"); 941160641Syongari goto fail; 942160641Syongari } 943160641Syongari 944160641Syongari /* create tag for Rx buffers. */ 945160641Syongari error = bus_dma_tag_create(sc->sc_cdata.stge_parent_tag,/* parent */ 946160641Syongari 1, 0, /* algnmnt, boundary */ 947160641Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 948160641Syongari BUS_SPACE_MAXADDR, /* highaddr */ 949160641Syongari NULL, NULL, /* filter, filterarg */ 950160641Syongari MCLBYTES, /* maxsize */ 951160641Syongari 1, /* nsegments */ 952160641Syongari MCLBYTES, /* maxsegsize */ 953160641Syongari 0, /* flags */ 954160641Syongari NULL, NULL, /* lockfunc, lockarg */ 955160641Syongari &sc->sc_cdata.stge_rx_tag); 956160641Syongari if (error != 0) { 957160641Syongari device_printf(sc->sc_dev, "failed to allocate Rx DMA tag\n"); 958160641Syongari goto fail; 959160641Syongari } 960160641Syongari 961160641Syongari /* allocate DMA'able memory and load the DMA map for Tx ring. */ 962160641Syongari error = bus_dmamem_alloc(sc->sc_cdata.stge_tx_ring_tag, 963160641Syongari (void **)&sc->sc_rdata.stge_tx_ring, BUS_DMA_NOWAIT | BUS_DMA_ZERO, 964160641Syongari &sc->sc_cdata.stge_tx_ring_map); 965160641Syongari if (error != 0) { 966160641Syongari device_printf(sc->sc_dev, 967160641Syongari "failed to allocate DMA'able memory for Tx ring\n"); 968160641Syongari goto fail; 969160641Syongari } 970160641Syongari 971160641Syongari ctx.stge_busaddr = 0; 972160641Syongari error = bus_dmamap_load(sc->sc_cdata.stge_tx_ring_tag, 973160641Syongari sc->sc_cdata.stge_tx_ring_map, sc->sc_rdata.stge_tx_ring, 974160641Syongari STGE_TX_RING_SZ, stge_dmamap_cb, &ctx, BUS_DMA_NOWAIT); 975160641Syongari if (error != 0 || ctx.stge_busaddr == 0) { 976160641Syongari device_printf(sc->sc_dev, 977160641Syongari "failed to load DMA'able memory for Tx ring\n"); 978160641Syongari goto fail; 979160641Syongari } 980160641Syongari sc->sc_rdata.stge_tx_ring_paddr = ctx.stge_busaddr; 981160641Syongari 982160641Syongari /* allocate DMA'able memory and load the DMA map for Rx ring. */ 983160641Syongari error = bus_dmamem_alloc(sc->sc_cdata.stge_rx_ring_tag, 984160641Syongari (void **)&sc->sc_rdata.stge_rx_ring, BUS_DMA_NOWAIT | BUS_DMA_ZERO, 985160641Syongari &sc->sc_cdata.stge_rx_ring_map); 986160641Syongari if (error != 0) { 987160641Syongari device_printf(sc->sc_dev, 988160641Syongari "failed to allocate DMA'able memory for Rx ring\n"); 989160641Syongari goto fail; 990160641Syongari } 991160641Syongari 992160641Syongari ctx.stge_busaddr = 0; 993160641Syongari error = bus_dmamap_load(sc->sc_cdata.stge_rx_ring_tag, 994160641Syongari sc->sc_cdata.stge_rx_ring_map, sc->sc_rdata.stge_rx_ring, 995160641Syongari STGE_RX_RING_SZ, stge_dmamap_cb, &ctx, BUS_DMA_NOWAIT); 996160641Syongari if (error != 0 || ctx.stge_busaddr == 0) { 997160641Syongari device_printf(sc->sc_dev, 998160641Syongari "failed to load DMA'able memory for Rx ring\n"); 999160641Syongari goto fail; 1000160641Syongari } 1001160641Syongari sc->sc_rdata.stge_rx_ring_paddr = ctx.stge_busaddr; 1002160641Syongari 1003160641Syongari /* create DMA maps for Tx buffers. */ 1004160641Syongari for (i = 0; i < STGE_TX_RING_CNT; i++) { 1005160641Syongari txd = &sc->sc_cdata.stge_txdesc[i]; 1006160641Syongari txd->tx_m = NULL; 1007160641Syongari txd->tx_dmamap = 0; 1008160641Syongari error = bus_dmamap_create(sc->sc_cdata.stge_tx_tag, 0, 1009160641Syongari &txd->tx_dmamap); 1010160641Syongari if (error != 0) { 1011160641Syongari device_printf(sc->sc_dev, 1012160641Syongari "failed to create Tx dmamap\n"); 1013160641Syongari goto fail; 1014160641Syongari } 1015160641Syongari } 1016160641Syongari /* create DMA maps for Rx buffers. */ 1017160641Syongari if ((error = bus_dmamap_create(sc->sc_cdata.stge_rx_tag, 0, 1018160641Syongari &sc->sc_cdata.stge_rx_sparemap)) != 0) { 1019160641Syongari device_printf(sc->sc_dev, "failed to create spare Rx dmamap\n"); 1020160641Syongari goto fail; 1021160641Syongari } 1022160641Syongari for (i = 0; i < STGE_RX_RING_CNT; i++) { 1023160641Syongari rxd = &sc->sc_cdata.stge_rxdesc[i]; 1024160641Syongari rxd->rx_m = NULL; 1025160641Syongari rxd->rx_dmamap = 0; 1026160641Syongari error = bus_dmamap_create(sc->sc_cdata.stge_rx_tag, 0, 1027160641Syongari &rxd->rx_dmamap); 1028160641Syongari if (error != 0) { 1029160641Syongari device_printf(sc->sc_dev, 1030160641Syongari "failed to create Rx dmamap\n"); 1031160641Syongari goto fail; 1032160641Syongari } 1033160641Syongari } 1034160641Syongari 1035160641Syongarifail: 1036160641Syongari return (error); 1037160641Syongari} 1038160641Syongari 1039160641Syongaristatic void 1040160641Syongaristge_dma_free(struct stge_softc *sc) 1041160641Syongari{ 1042160641Syongari struct stge_txdesc *txd; 1043160641Syongari struct stge_rxdesc *rxd; 1044160641Syongari int i; 1045160641Syongari 1046160641Syongari /* Tx ring */ 1047160641Syongari if (sc->sc_cdata.stge_tx_ring_tag) { 1048160641Syongari if (sc->sc_cdata.stge_tx_ring_map) 1049160641Syongari bus_dmamap_unload(sc->sc_cdata.stge_tx_ring_tag, 1050160641Syongari sc->sc_cdata.stge_tx_ring_map); 1051160641Syongari if (sc->sc_cdata.stge_tx_ring_map && 1052160641Syongari sc->sc_rdata.stge_tx_ring) 1053160641Syongari bus_dmamem_free(sc->sc_cdata.stge_tx_ring_tag, 1054160641Syongari sc->sc_rdata.stge_tx_ring, 1055160641Syongari sc->sc_cdata.stge_tx_ring_map); 1056160641Syongari sc->sc_rdata.stge_tx_ring = NULL; 1057160641Syongari sc->sc_cdata.stge_tx_ring_map = 0; 1058160641Syongari bus_dma_tag_destroy(sc->sc_cdata.stge_tx_ring_tag); 1059160641Syongari sc->sc_cdata.stge_tx_ring_tag = NULL; 1060160641Syongari } 1061160641Syongari /* Rx ring */ 1062160641Syongari if (sc->sc_cdata.stge_rx_ring_tag) { 1063160641Syongari if (sc->sc_cdata.stge_rx_ring_map) 1064160641Syongari bus_dmamap_unload(sc->sc_cdata.stge_rx_ring_tag, 1065160641Syongari sc->sc_cdata.stge_rx_ring_map); 1066160641Syongari if (sc->sc_cdata.stge_rx_ring_map && 1067160641Syongari sc->sc_rdata.stge_rx_ring) 1068160641Syongari bus_dmamem_free(sc->sc_cdata.stge_rx_ring_tag, 1069160641Syongari sc->sc_rdata.stge_rx_ring, 1070160641Syongari sc->sc_cdata.stge_rx_ring_map); 1071160641Syongari sc->sc_rdata.stge_rx_ring = NULL; 1072160641Syongari sc->sc_cdata.stge_rx_ring_map = 0; 1073160641Syongari bus_dma_tag_destroy(sc->sc_cdata.stge_rx_ring_tag); 1074160641Syongari sc->sc_cdata.stge_rx_ring_tag = NULL; 1075160641Syongari } 1076160641Syongari /* Tx buffers */ 1077160641Syongari if (sc->sc_cdata.stge_tx_tag) { 1078160641Syongari for (i = 0; i < STGE_TX_RING_CNT; i++) { 1079160641Syongari txd = &sc->sc_cdata.stge_txdesc[i]; 1080160641Syongari if (txd->tx_dmamap) { 1081160641Syongari bus_dmamap_destroy(sc->sc_cdata.stge_tx_tag, 1082160641Syongari txd->tx_dmamap); 1083160641Syongari txd->tx_dmamap = 0; 1084160641Syongari } 1085160641Syongari } 1086160641Syongari bus_dma_tag_destroy(sc->sc_cdata.stge_tx_tag); 1087160641Syongari sc->sc_cdata.stge_tx_tag = NULL; 1088160641Syongari } 1089160641Syongari /* Rx buffers */ 1090160641Syongari if (sc->sc_cdata.stge_rx_tag) { 1091160641Syongari for (i = 0; i < STGE_RX_RING_CNT; i++) { 1092160641Syongari rxd = &sc->sc_cdata.stge_rxdesc[i]; 1093160641Syongari if (rxd->rx_dmamap) { 1094160641Syongari bus_dmamap_destroy(sc->sc_cdata.stge_rx_tag, 1095160641Syongari rxd->rx_dmamap); 1096160641Syongari rxd->rx_dmamap = 0; 1097160641Syongari } 1098160641Syongari } 1099160641Syongari if (sc->sc_cdata.stge_rx_sparemap) { 1100160641Syongari bus_dmamap_destroy(sc->sc_cdata.stge_rx_tag, 1101160641Syongari sc->sc_cdata.stge_rx_sparemap); 1102160641Syongari sc->sc_cdata.stge_rx_sparemap = 0; 1103160641Syongari } 1104160641Syongari bus_dma_tag_destroy(sc->sc_cdata.stge_rx_tag); 1105160641Syongari sc->sc_cdata.stge_rx_tag = NULL; 1106160641Syongari } 1107160641Syongari 1108160641Syongari if (sc->sc_cdata.stge_parent_tag) { 1109160641Syongari bus_dma_tag_destroy(sc->sc_cdata.stge_parent_tag); 1110160641Syongari sc->sc_cdata.stge_parent_tag = NULL; 1111160641Syongari } 1112160641Syongari} 1113160641Syongari 1114160641Syongari/* 1115160641Syongari * stge_shutdown: 1116160641Syongari * 1117160641Syongari * Make sure the interface is stopped at reboot time. 1118160641Syongari */ 1119173839Syongaristatic int 1120160641Syongaristge_shutdown(device_t dev) 1121160641Syongari{ 1122160641Syongari 1123175315Syongari return (stge_suspend(dev)); 1124175315Syongari} 1125160641Syongari 1126175315Syongaristatic void 1127175315Syongaristge_setwol(struct stge_softc *sc) 1128175315Syongari{ 1129175315Syongari struct ifnet *ifp; 1130175315Syongari uint8_t v; 1131173839Syongari 1132175315Syongari STGE_LOCK_ASSERT(sc); 1133175315Syongari 1134175315Syongari ifp = sc->sc_ifp; 1135175315Syongari v = CSR_READ_1(sc, STGE_WakeEvent); 1136175315Syongari /* Disable all WOL bits. */ 1137175315Syongari v &= ~(WE_WakePktEnable | WE_MagicPktEnable | WE_LinkEventEnable | 1138175315Syongari WE_WakeOnLanEnable); 1139175315Syongari if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) 1140175315Syongari v |= WE_MagicPktEnable | WE_WakeOnLanEnable; 1141175315Syongari CSR_WRITE_1(sc, STGE_WakeEvent, v); 1142175315Syongari /* Reset Tx and prevent transmission. */ 1143175315Syongari CSR_WRITE_4(sc, STGE_AsicCtrl, 1144175315Syongari CSR_READ_4(sc, STGE_AsicCtrl) | AC_TxReset); 1145175315Syongari /* 1146175315Syongari * TC9021 automatically reset link speed to 100Mbps when it's put 1147175315Syongari * into sleep so there is no need to try to resetting link speed. 1148175315Syongari */ 1149160641Syongari} 1150160641Syongari 1151160641Syongaristatic int 1152160641Syongaristge_suspend(device_t dev) 1153160641Syongari{ 1154160641Syongari struct stge_softc *sc; 1155160641Syongari 1156160641Syongari sc = device_get_softc(dev); 1157160641Syongari 1158160641Syongari STGE_LOCK(sc); 1159160641Syongari stge_stop(sc); 1160160641Syongari sc->sc_suspended = 1; 1161175315Syongari stge_setwol(sc); 1162160641Syongari STGE_UNLOCK(sc); 1163160641Syongari 1164160641Syongari return (0); 1165160641Syongari} 1166160641Syongari 1167160641Syongaristatic int 1168160641Syongaristge_resume(device_t dev) 1169160641Syongari{ 1170160641Syongari struct stge_softc *sc; 1171160641Syongari struct ifnet *ifp; 1172175315Syongari uint8_t v; 1173160641Syongari 1174160641Syongari sc = device_get_softc(dev); 1175160641Syongari 1176160641Syongari STGE_LOCK(sc); 1177175315Syongari /* 1178175315Syongari * Clear WOL bits, so special frames wouldn't interfere 1179175315Syongari * normal Rx operation anymore. 1180175315Syongari */ 1181175315Syongari v = CSR_READ_1(sc, STGE_WakeEvent); 1182175315Syongari v &= ~(WE_WakePktEnable | WE_MagicPktEnable | WE_LinkEventEnable | 1183175315Syongari WE_WakeOnLanEnable); 1184175315Syongari CSR_WRITE_1(sc, STGE_WakeEvent, v); 1185160641Syongari ifp = sc->sc_ifp; 1186160641Syongari if (ifp->if_flags & IFF_UP) 1187160641Syongari stge_init_locked(sc); 1188160641Syongari 1189160641Syongari sc->sc_suspended = 0; 1190160641Syongari STGE_UNLOCK(sc); 1191160641Syongari 1192160641Syongari return (0); 1193160641Syongari} 1194160641Syongari 1195160641Syongaristatic void 1196160641Syongaristge_dma_wait(struct stge_softc *sc) 1197160641Syongari{ 1198160641Syongari int i; 1199160641Syongari 1200160641Syongari for (i = 0; i < STGE_TIMEOUT; i++) { 1201160641Syongari DELAY(2); 1202160641Syongari if ((CSR_READ_4(sc, STGE_DMACtrl) & DMAC_TxDMAInProg) == 0) 1203160641Syongari break; 1204160641Syongari } 1205160641Syongari 1206160641Syongari if (i == STGE_TIMEOUT) 1207160641Syongari device_printf(sc->sc_dev, "DMA wait timed out\n"); 1208160641Syongari} 1209160641Syongari 1210160641Syongaristatic int 1211160641Syongaristge_encap(struct stge_softc *sc, struct mbuf **m_head) 1212160641Syongari{ 1213160641Syongari struct stge_txdesc *txd; 1214160641Syongari struct stge_tfd *tfd; 1215161235Syongari struct mbuf *m; 1216160641Syongari bus_dma_segment_t txsegs[STGE_MAXTXSEGS]; 1217160641Syongari int error, i, nsegs, si; 1218160641Syongari uint64_t csum_flags, tfc; 1219160641Syongari 1220160641Syongari STGE_LOCK_ASSERT(sc); 1221160641Syongari 1222160641Syongari if ((txd = STAILQ_FIRST(&sc->sc_cdata.stge_txfreeq)) == NULL) 1223160641Syongari return (ENOBUFS); 1224160641Syongari 1225160641Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_cdata.stge_tx_tag, 1226161235Syongari txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); 1227160641Syongari if (error == EFBIG) { 1228175430Syongari m = m_collapse(*m_head, M_DONTWAIT, STGE_MAXTXSEGS); 1229161235Syongari if (m == NULL) { 1230161235Syongari m_freem(*m_head); 1231161235Syongari *m_head = NULL; 1232160641Syongari return (ENOMEM); 1233160641Syongari } 1234161235Syongari *m_head = m; 1235160641Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_cdata.stge_tx_tag, 1236161235Syongari txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); 1237160641Syongari if (error != 0) { 1238161235Syongari m_freem(*m_head); 1239161235Syongari *m_head = NULL; 1240160641Syongari return (error); 1241160641Syongari } 1242160641Syongari } else if (error != 0) 1243160641Syongari return (error); 1244160641Syongari if (nsegs == 0) { 1245161235Syongari m_freem(*m_head); 1246161235Syongari *m_head = NULL; 1247160641Syongari return (EIO); 1248160641Syongari } 1249160641Syongari 1250161235Syongari m = *m_head; 1251160641Syongari csum_flags = 0; 1252160641Syongari if ((m->m_pkthdr.csum_flags & STGE_CSUM_FEATURES) != 0) { 1253160641Syongari if (m->m_pkthdr.csum_flags & CSUM_IP) 1254160641Syongari csum_flags |= TFD_IPChecksumEnable; 1255160641Syongari if (m->m_pkthdr.csum_flags & CSUM_TCP) 1256160641Syongari csum_flags |= TFD_TCPChecksumEnable; 1257160641Syongari else if (m->m_pkthdr.csum_flags & CSUM_UDP) 1258160641Syongari csum_flags |= TFD_UDPChecksumEnable; 1259160641Syongari } 1260160641Syongari 1261160641Syongari si = sc->sc_cdata.stge_tx_prod; 1262160641Syongari tfd = &sc->sc_rdata.stge_tx_ring[si]; 1263160641Syongari for (i = 0; i < nsegs; i++) 1264160641Syongari tfd->tfd_frags[i].frag_word0 = 1265160641Syongari htole64(FRAG_ADDR(txsegs[i].ds_addr) | 1266160641Syongari FRAG_LEN(txsegs[i].ds_len)); 1267160641Syongari sc->sc_cdata.stge_tx_cnt++; 1268160641Syongari 1269160641Syongari tfc = TFD_FrameId(si) | TFD_WordAlign(TFD_WordAlign_disable) | 1270160641Syongari TFD_FragCount(nsegs) | csum_flags; 1271160641Syongari if (sc->sc_cdata.stge_tx_cnt >= STGE_TX_HIWAT) 1272160641Syongari tfc |= TFD_TxDMAIndicate; 1273160641Syongari 1274160641Syongari /* Update producer index. */ 1275160641Syongari sc->sc_cdata.stge_tx_prod = (si + 1) % STGE_TX_RING_CNT; 1276160641Syongari 1277160641Syongari /* Check if we have a VLAN tag to insert. */ 1278162375Sandre if (m->m_flags & M_VLANTAG) 1279162375Sandre tfc |= (TFD_VLANTagInsert | TFD_VID(m->m_pkthdr.ether_vtag)); 1280160641Syongari tfd->tfd_control = htole64(tfc); 1281160641Syongari 1282160641Syongari /* Update Tx Queue. */ 1283160641Syongari STAILQ_REMOVE_HEAD(&sc->sc_cdata.stge_txfreeq, tx_q); 1284160641Syongari STAILQ_INSERT_TAIL(&sc->sc_cdata.stge_txbusyq, txd, tx_q); 1285160641Syongari txd->tx_m = m; 1286160641Syongari 1287160641Syongari /* Sync descriptors. */ 1288160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_tx_tag, txd->tx_dmamap, 1289160641Syongari BUS_DMASYNC_PREWRITE); 1290160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_tx_ring_tag, 1291160641Syongari sc->sc_cdata.stge_tx_ring_map, 1292160641Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1293160641Syongari 1294160641Syongari return (0); 1295160641Syongari} 1296160641Syongari 1297160641Syongari/* 1298160641Syongari * stge_start: [ifnet interface function] 1299160641Syongari * 1300160641Syongari * Start packet transmission on the interface. 1301160641Syongari */ 1302160641Syongaristatic void 1303160641Syongaristge_start(struct ifnet *ifp) 1304160641Syongari{ 1305160641Syongari struct stge_softc *sc; 1306160641Syongari 1307160641Syongari sc = ifp->if_softc; 1308160641Syongari STGE_LOCK(sc); 1309160641Syongari stge_start_locked(ifp); 1310160641Syongari STGE_UNLOCK(sc); 1311160641Syongari} 1312160641Syongari 1313160641Syongaristatic void 1314160641Syongaristge_start_locked(struct ifnet *ifp) 1315160641Syongari{ 1316160641Syongari struct stge_softc *sc; 1317160641Syongari struct mbuf *m_head; 1318160641Syongari int enq; 1319160641Syongari 1320160641Syongari sc = ifp->if_softc; 1321160641Syongari 1322160641Syongari STGE_LOCK_ASSERT(sc); 1323160641Syongari 1324160641Syongari if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) != 1325169158Syongari IFF_DRV_RUNNING || sc->sc_link == 0) 1326160641Syongari return; 1327160641Syongari 1328160641Syongari for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) { 1329160641Syongari if (sc->sc_cdata.stge_tx_cnt >= STGE_TX_HIWAT) { 1330160641Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1331160641Syongari break; 1332160641Syongari } 1333160641Syongari 1334160641Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 1335160641Syongari if (m_head == NULL) 1336160641Syongari break; 1337160641Syongari /* 1338160641Syongari * Pack the data into the transmit ring. If we 1339160641Syongari * don't have room, set the OACTIVE flag and wait 1340160641Syongari * for the NIC to drain the ring. 1341160641Syongari */ 1342160641Syongari if (stge_encap(sc, &m_head)) { 1343160641Syongari if (m_head == NULL) 1344160641Syongari break; 1345160641Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 1346160641Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1347160641Syongari break; 1348160641Syongari } 1349160641Syongari 1350160641Syongari enq++; 1351160641Syongari /* 1352160641Syongari * If there's a BPF listener, bounce a copy of this frame 1353160641Syongari * to him. 1354160641Syongari */ 1355167190Scsjp ETHER_BPF_MTAP(ifp, m_head); 1356160641Syongari } 1357160641Syongari 1358160641Syongari if (enq > 0) { 1359160641Syongari /* Transmit */ 1360160641Syongari CSR_WRITE_4(sc, STGE_DMACtrl, DMAC_TxDMAPollNow); 1361160641Syongari 1362160641Syongari /* Set a timeout in case the chip goes out to lunch. */ 1363169157Syongari sc->sc_watchdog_timer = 5; 1364160641Syongari } 1365160641Syongari} 1366160641Syongari 1367160641Syongari/* 1368169157Syongari * stge_watchdog: 1369160641Syongari * 1370160641Syongari * Watchdog timer handler. 1371160641Syongari */ 1372160641Syongaristatic void 1373169157Syongaristge_watchdog(struct stge_softc *sc) 1374160641Syongari{ 1375169157Syongari struct ifnet *ifp; 1376160641Syongari 1377169157Syongari STGE_LOCK_ASSERT(sc); 1378160641Syongari 1379169157Syongari if (sc->sc_watchdog_timer == 0 || --sc->sc_watchdog_timer) 1380169157Syongari return; 1381169157Syongari 1382169157Syongari ifp = sc->sc_ifp; 1383160641Syongari if_printf(sc->sc_ifp, "device timeout\n"); 1384160641Syongari ifp->if_oerrors++; 1385212972Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1386160641Syongari stge_init_locked(sc); 1387169159Syongari if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1388169159Syongari stge_start_locked(ifp); 1389160641Syongari} 1390160641Syongari 1391160641Syongari/* 1392160641Syongari * stge_ioctl: [ifnet interface function] 1393160641Syongari * 1394160641Syongari * Handle control requests from the operator. 1395160641Syongari */ 1396160641Syongaristatic int 1397160641Syongaristge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1398160641Syongari{ 1399160641Syongari struct stge_softc *sc; 1400160641Syongari struct ifreq *ifr; 1401160641Syongari struct mii_data *mii; 1402160641Syongari int error, mask; 1403160641Syongari 1404160641Syongari sc = ifp->if_softc; 1405160641Syongari ifr = (struct ifreq *)data; 1406160641Syongari error = 0; 1407160641Syongari switch (cmd) { 1408160641Syongari case SIOCSIFMTU: 1409160641Syongari if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > STGE_JUMBO_MTU) 1410160641Syongari error = EINVAL; 1411160641Syongari else if (ifp->if_mtu != ifr->ifr_mtu) { 1412160641Syongari ifp->if_mtu = ifr->ifr_mtu; 1413160641Syongari STGE_LOCK(sc); 1414212972Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1415212972Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1416212972Syongari stge_init_locked(sc); 1417212972Syongari } 1418160641Syongari STGE_UNLOCK(sc); 1419160641Syongari } 1420160641Syongari break; 1421160641Syongari case SIOCSIFFLAGS: 1422160641Syongari STGE_LOCK(sc); 1423160641Syongari if ((ifp->if_flags & IFF_UP) != 0) { 1424160641Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1425160641Syongari if (((ifp->if_flags ^ sc->sc_if_flags) 1426160641Syongari & IFF_PROMISC) != 0) 1427160641Syongari stge_set_filter(sc); 1428160641Syongari } else { 1429160641Syongari if (sc->sc_detach == 0) 1430160641Syongari stge_init_locked(sc); 1431160641Syongari } 1432160641Syongari } else { 1433160641Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1434160641Syongari stge_stop(sc); 1435160641Syongari } 1436160641Syongari sc->sc_if_flags = ifp->if_flags; 1437160641Syongari STGE_UNLOCK(sc); 1438160641Syongari break; 1439160641Syongari case SIOCADDMULTI: 1440160641Syongari case SIOCDELMULTI: 1441160641Syongari STGE_LOCK(sc); 1442160641Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1443160641Syongari stge_set_multi(sc); 1444160641Syongari STGE_UNLOCK(sc); 1445160641Syongari break; 1446160641Syongari case SIOCSIFMEDIA: 1447160641Syongari case SIOCGIFMEDIA: 1448160641Syongari mii = device_get_softc(sc->sc_miibus); 1449160641Syongari error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1450160641Syongari break; 1451160641Syongari case SIOCSIFCAP: 1452160641Syongari mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1453160641Syongari#ifdef DEVICE_POLLING 1454160641Syongari if ((mask & IFCAP_POLLING) != 0) { 1455160641Syongari if ((ifr->ifr_reqcap & IFCAP_POLLING) != 0) { 1456160641Syongari error = ether_poll_register(stge_poll, ifp); 1457160641Syongari if (error != 0) 1458160641Syongari break; 1459160641Syongari STGE_LOCK(sc); 1460160641Syongari CSR_WRITE_2(sc, STGE_IntEnable, 0); 1461160641Syongari ifp->if_capenable |= IFCAP_POLLING; 1462160641Syongari STGE_UNLOCK(sc); 1463160641Syongari } else { 1464160641Syongari error = ether_poll_deregister(ifp); 1465160641Syongari if (error != 0) 1466160641Syongari break; 1467160641Syongari STGE_LOCK(sc); 1468160641Syongari CSR_WRITE_2(sc, STGE_IntEnable, 1469160641Syongari sc->sc_IntEnable); 1470160641Syongari ifp->if_capenable &= ~IFCAP_POLLING; 1471160641Syongari STGE_UNLOCK(sc); 1472160641Syongari } 1473160641Syongari } 1474160641Syongari#endif 1475160641Syongari if ((mask & IFCAP_HWCSUM) != 0) { 1476160641Syongari ifp->if_capenable ^= IFCAP_HWCSUM; 1477160641Syongari if ((IFCAP_HWCSUM & ifp->if_capenable) != 0 && 1478160641Syongari (IFCAP_HWCSUM & ifp->if_capabilities) != 0) 1479160641Syongari ifp->if_hwassist = STGE_CSUM_FEATURES; 1480160641Syongari else 1481160641Syongari ifp->if_hwassist = 0; 1482160641Syongari } 1483175315Syongari if ((mask & IFCAP_WOL) != 0 && 1484175315Syongari (ifp->if_capabilities & IFCAP_WOL) != 0) { 1485175315Syongari if ((mask & IFCAP_WOL_MAGIC) != 0) 1486175315Syongari ifp->if_capenable ^= IFCAP_WOL_MAGIC; 1487175315Syongari } 1488160641Syongari if ((mask & IFCAP_VLAN_HWTAGGING) != 0) { 1489160641Syongari ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 1490160641Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1491160641Syongari STGE_LOCK(sc); 1492160641Syongari stge_vlan_setup(sc); 1493160641Syongari STGE_UNLOCK(sc); 1494160641Syongari } 1495160641Syongari } 1496160641Syongari VLAN_CAPABILITIES(ifp); 1497160641Syongari break; 1498160641Syongari default: 1499160641Syongari error = ether_ioctl(ifp, cmd, data); 1500160641Syongari break; 1501160641Syongari } 1502160641Syongari 1503160641Syongari return (error); 1504160641Syongari} 1505160641Syongari 1506160641Syongaristatic void 1507160641Syongaristge_link_task(void *arg, int pending) 1508160641Syongari{ 1509160641Syongari struct stge_softc *sc; 1510169158Syongari struct mii_data *mii; 1511160641Syongari uint32_t v, ac; 1512160641Syongari int i; 1513160641Syongari 1514160641Syongari sc = (struct stge_softc *)arg; 1515160641Syongari STGE_LOCK(sc); 1516169158Syongari 1517169158Syongari mii = device_get_softc(sc->sc_miibus); 1518169158Syongari if (mii->mii_media_status & IFM_ACTIVE) { 1519169158Syongari if (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) 1520169158Syongari sc->sc_link = 1; 1521169158Syongari } else 1522169158Syongari sc->sc_link = 0; 1523169158Syongari 1524169158Syongari sc->sc_MACCtrl = 0; 1525169158Syongari if (((mii->mii_media_active & IFM_GMASK) & IFM_FDX) != 0) 1526169158Syongari sc->sc_MACCtrl |= MC_DuplexSelect; 1527215297Smarius if (((mii->mii_media_active & IFM_GMASK) & IFM_ETH_RXPAUSE) != 0) 1528169158Syongari sc->sc_MACCtrl |= MC_RxFlowControlEnable; 1529215297Smarius if (((mii->mii_media_active & IFM_GMASK) & IFM_ETH_TXPAUSE) != 0) 1530169158Syongari sc->sc_MACCtrl |= MC_TxFlowControlEnable; 1531160641Syongari /* 1532160641Syongari * Update STGE_MACCtrl register depending on link status. 1533160641Syongari * (duplex, flow control etc) 1534160641Syongari */ 1535160641Syongari v = ac = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 1536160641Syongari v &= ~(MC_DuplexSelect|MC_RxFlowControlEnable|MC_TxFlowControlEnable); 1537160641Syongari v |= sc->sc_MACCtrl; 1538160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, v); 1539160641Syongari if (((ac ^ sc->sc_MACCtrl) & MC_DuplexSelect) != 0) { 1540160641Syongari /* Duplex setting changed, reset Tx/Rx functions. */ 1541160641Syongari ac = CSR_READ_4(sc, STGE_AsicCtrl); 1542160641Syongari ac |= AC_TxReset | AC_RxReset; 1543160641Syongari CSR_WRITE_4(sc, STGE_AsicCtrl, ac); 1544160641Syongari for (i = 0; i < STGE_TIMEOUT; i++) { 1545160641Syongari DELAY(100); 1546160641Syongari if ((CSR_READ_4(sc, STGE_AsicCtrl) & AC_ResetBusy) == 0) 1547160641Syongari break; 1548160641Syongari } 1549160641Syongari if (i == STGE_TIMEOUT) 1550160641Syongari device_printf(sc->sc_dev, "reset failed to complete\n"); 1551160641Syongari } 1552160641Syongari STGE_UNLOCK(sc); 1553160641Syongari} 1554160641Syongari 1555160641Syongaristatic __inline int 1556160641Syongaristge_tx_error(struct stge_softc *sc) 1557160641Syongari{ 1558160641Syongari uint32_t txstat; 1559160641Syongari int error; 1560160641Syongari 1561160641Syongari for (error = 0;;) { 1562160641Syongari txstat = CSR_READ_4(sc, STGE_TxStatus); 1563160641Syongari if ((txstat & TS_TxComplete) == 0) 1564160641Syongari break; 1565160641Syongari /* Tx underrun */ 1566160641Syongari if ((txstat & TS_TxUnderrun) != 0) { 1567160641Syongari /* 1568160641Syongari * XXX 1569160641Syongari * There should be a more better way to recover 1570160641Syongari * from Tx underrun instead of a full reset. 1571160641Syongari */ 1572160641Syongari if (sc->sc_nerr++ < STGE_MAXERR) 1573160641Syongari device_printf(sc->sc_dev, "Tx underrun, " 1574160641Syongari "resetting...\n"); 1575160641Syongari if (sc->sc_nerr == STGE_MAXERR) 1576160641Syongari device_printf(sc->sc_dev, "too many errors; " 1577160641Syongari "not reporting any more\n"); 1578160641Syongari error = -1; 1579160641Syongari break; 1580160641Syongari } 1581160641Syongari /* Maximum/Late collisions, Re-enable Tx MAC. */ 1582160641Syongari if ((txstat & (TS_MaxCollisions|TS_LateCollision)) != 0) 1583160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, 1584160641Syongari (CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK) | 1585160641Syongari MC_TxEnable); 1586160641Syongari } 1587160641Syongari 1588160641Syongari return (error); 1589160641Syongari} 1590160641Syongari 1591160641Syongari/* 1592160641Syongari * stge_intr: 1593160641Syongari * 1594160641Syongari * Interrupt service routine. 1595160641Syongari */ 1596160641Syongaristatic void 1597160641Syongaristge_intr(void *arg) 1598160641Syongari{ 1599160641Syongari struct stge_softc *sc; 1600160641Syongari struct ifnet *ifp; 1601160641Syongari int reinit; 1602160641Syongari uint16_t status; 1603160641Syongari 1604160641Syongari sc = (struct stge_softc *)arg; 1605160641Syongari ifp = sc->sc_ifp; 1606160641Syongari 1607160641Syongari STGE_LOCK(sc); 1608160641Syongari 1609160641Syongari#ifdef DEVICE_POLLING 1610160641Syongari if ((ifp->if_capenable & IFCAP_POLLING) != 0) 1611160641Syongari goto done_locked; 1612160641Syongari#endif 1613160641Syongari status = CSR_READ_2(sc, STGE_IntStatus); 1614160641Syongari if (sc->sc_suspended || (status & IS_InterruptStatus) == 0) 1615160641Syongari goto done_locked; 1616160641Syongari 1617160641Syongari /* Disable interrupts. */ 1618160641Syongari for (reinit = 0;;) { 1619160641Syongari status = CSR_READ_2(sc, STGE_IntStatusAck); 1620160641Syongari status &= sc->sc_IntEnable; 1621160641Syongari if (status == 0) 1622160641Syongari break; 1623160641Syongari /* Host interface errors. */ 1624160641Syongari if ((status & IS_HostError) != 0) { 1625160641Syongari device_printf(sc->sc_dev, 1626160641Syongari "Host interface error, resetting...\n"); 1627160641Syongari reinit = 1; 1628160641Syongari goto force_init; 1629160641Syongari } 1630160641Syongari 1631160641Syongari /* Receive interrupts. */ 1632160641Syongari if ((status & IS_RxDMAComplete) != 0) { 1633160641Syongari stge_rxeof(sc); 1634160641Syongari if ((status & IS_RFDListEnd) != 0) 1635160641Syongari CSR_WRITE_4(sc, STGE_DMACtrl, 1636160641Syongari DMAC_RxDMAPollNow); 1637160641Syongari } 1638160641Syongari 1639160641Syongari /* Transmit interrupts. */ 1640160641Syongari if ((status & (IS_TxDMAComplete | IS_TxComplete)) != 0) 1641160641Syongari stge_txeof(sc); 1642160641Syongari 1643160641Syongari /* Transmission errors.*/ 1644160641Syongari if ((status & IS_TxComplete) != 0) { 1645160641Syongari if ((reinit = stge_tx_error(sc)) != 0) 1646160641Syongari break; 1647160641Syongari } 1648160641Syongari } 1649160641Syongari 1650160641Syongariforce_init: 1651212972Syongari if (reinit != 0) { 1652212972Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1653160641Syongari stge_init_locked(sc); 1654212972Syongari } 1655160641Syongari 1656160641Syongari /* Re-enable interrupts. */ 1657160641Syongari CSR_WRITE_2(sc, STGE_IntEnable, sc->sc_IntEnable); 1658160641Syongari 1659160641Syongari /* Try to get more packets going. */ 1660160641Syongari if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1661160641Syongari stge_start_locked(ifp); 1662160641Syongari 1663160641Syongaridone_locked: 1664160641Syongari STGE_UNLOCK(sc); 1665160641Syongari} 1666160641Syongari 1667160641Syongari/* 1668160641Syongari * stge_txeof: 1669160641Syongari * 1670160641Syongari * Helper; handle transmit interrupts. 1671160641Syongari */ 1672160641Syongaristatic void 1673160641Syongaristge_txeof(struct stge_softc *sc) 1674160641Syongari{ 1675160641Syongari struct ifnet *ifp; 1676160641Syongari struct stge_txdesc *txd; 1677160641Syongari uint64_t control; 1678160641Syongari int cons; 1679160641Syongari 1680160641Syongari STGE_LOCK_ASSERT(sc); 1681160641Syongari 1682160641Syongari ifp = sc->sc_ifp; 1683160641Syongari 1684160641Syongari txd = STAILQ_FIRST(&sc->sc_cdata.stge_txbusyq); 1685160641Syongari if (txd == NULL) 1686160641Syongari return; 1687160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_tx_ring_tag, 1688160641Syongari sc->sc_cdata.stge_tx_ring_map, BUS_DMASYNC_POSTREAD); 1689160641Syongari 1690160641Syongari /* 1691160641Syongari * Go through our Tx list and free mbufs for those 1692160641Syongari * frames which have been transmitted. 1693160641Syongari */ 1694160641Syongari for (cons = sc->sc_cdata.stge_tx_cons;; 1695160641Syongari cons = (cons + 1) % STGE_TX_RING_CNT) { 1696160641Syongari if (sc->sc_cdata.stge_tx_cnt <= 0) 1697160641Syongari break; 1698160641Syongari control = le64toh(sc->sc_rdata.stge_tx_ring[cons].tfd_control); 1699160641Syongari if ((control & TFD_TFDDone) == 0) 1700160641Syongari break; 1701160641Syongari sc->sc_cdata.stge_tx_cnt--; 1702160641Syongari ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1703160641Syongari 1704160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_tx_tag, txd->tx_dmamap, 1705160641Syongari BUS_DMASYNC_POSTWRITE); 1706160641Syongari bus_dmamap_unload(sc->sc_cdata.stge_tx_tag, txd->tx_dmamap); 1707160641Syongari 1708160641Syongari /* Output counter is updated with statistics register */ 1709160641Syongari m_freem(txd->tx_m); 1710160641Syongari txd->tx_m = NULL; 1711160641Syongari STAILQ_REMOVE_HEAD(&sc->sc_cdata.stge_txbusyq, tx_q); 1712160641Syongari STAILQ_INSERT_TAIL(&sc->sc_cdata.stge_txfreeq, txd, tx_q); 1713160641Syongari txd = STAILQ_FIRST(&sc->sc_cdata.stge_txbusyq); 1714160641Syongari } 1715160641Syongari sc->sc_cdata.stge_tx_cons = cons; 1716160641Syongari if (sc->sc_cdata.stge_tx_cnt == 0) 1717169157Syongari sc->sc_watchdog_timer = 0; 1718160641Syongari 1719160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_tx_ring_tag, 1720160641Syongari sc->sc_cdata.stge_tx_ring_map, 1721160641Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1722160641Syongari} 1723160641Syongari 1724160641Syongaristatic __inline void 1725160641Syongaristge_discard_rxbuf(struct stge_softc *sc, int idx) 1726160641Syongari{ 1727160641Syongari struct stge_rfd *rfd; 1728160641Syongari 1729160641Syongari rfd = &sc->sc_rdata.stge_rx_ring[idx]; 1730160641Syongari rfd->rfd_status = 0; 1731160641Syongari} 1732160641Syongari 1733160641Syongari#ifndef __NO_STRICT_ALIGNMENT 1734160641Syongari/* 1735160641Syongari * It seems that TC9021's DMA engine has alignment restrictions in 1736160641Syongari * DMA scatter operations. The first DMA segment has no address 1737160641Syongari * alignment restrictins but the rest should be aligned on 4(?) bytes 1738160641Syongari * boundary. Otherwise it would corrupt random memory. Since we don't 1739160641Syongari * know which one is used for the first segment in advance we simply 1740160641Syongari * don't align at all. 1741160641Syongari * To avoid copying over an entire frame to align, we allocate a new 1742160641Syongari * mbuf and copy ethernet header to the new mbuf. The new mbuf is 1743160641Syongari * prepended into the existing mbuf chain. 1744160641Syongari */ 1745160641Syongaristatic __inline struct mbuf * 1746160641Syongaristge_fixup_rx(struct stge_softc *sc, struct mbuf *m) 1747160641Syongari{ 1748160641Syongari struct mbuf *n; 1749160641Syongari 1750160641Syongari n = NULL; 1751160641Syongari if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN)) { 1752160641Syongari bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len); 1753160641Syongari m->m_data += ETHER_HDR_LEN; 1754160641Syongari n = m; 1755160641Syongari } else { 1756160641Syongari MGETHDR(n, M_DONTWAIT, MT_DATA); 1757160641Syongari if (n != NULL) { 1758160641Syongari bcopy(m->m_data, n->m_data, ETHER_HDR_LEN); 1759160641Syongari m->m_data += ETHER_HDR_LEN; 1760160641Syongari m->m_len -= ETHER_HDR_LEN; 1761160641Syongari n->m_len = ETHER_HDR_LEN; 1762160641Syongari M_MOVE_PKTHDR(n, m); 1763160641Syongari n->m_next = m; 1764160641Syongari } else 1765160641Syongari m_freem(m); 1766160641Syongari } 1767160641Syongari 1768160641Syongari return (n); 1769160641Syongari} 1770160641Syongari#endif 1771160641Syongari 1772160641Syongari/* 1773160641Syongari * stge_rxeof: 1774160641Syongari * 1775160641Syongari * Helper; handle receive interrupts. 1776160641Syongari */ 1777193096Sattiliostatic int 1778160641Syongaristge_rxeof(struct stge_softc *sc) 1779160641Syongari{ 1780160641Syongari struct ifnet *ifp; 1781160641Syongari struct stge_rxdesc *rxd; 1782160641Syongari struct mbuf *mp, *m; 1783160641Syongari uint64_t status64; 1784160641Syongari uint32_t status; 1785193096Sattilio int cons, prog, rx_npkts; 1786160641Syongari 1787160641Syongari STGE_LOCK_ASSERT(sc); 1788160641Syongari 1789193096Sattilio rx_npkts = 0; 1790160641Syongari ifp = sc->sc_ifp; 1791160641Syongari 1792160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_rx_ring_tag, 1793160641Syongari sc->sc_cdata.stge_rx_ring_map, BUS_DMASYNC_POSTREAD); 1794160641Syongari 1795160641Syongari prog = 0; 1796160641Syongari for (cons = sc->sc_cdata.stge_rx_cons; prog < STGE_RX_RING_CNT; 1797160641Syongari prog++, cons = (cons + 1) % STGE_RX_RING_CNT) { 1798160641Syongari status64 = le64toh(sc->sc_rdata.stge_rx_ring[cons].rfd_status); 1799160641Syongari status = RFD_RxStatus(status64); 1800160641Syongari if ((status & RFD_RFDDone) == 0) 1801160641Syongari break; 1802160641Syongari#ifdef DEVICE_POLLING 1803160641Syongari if (ifp->if_capenable & IFCAP_POLLING) { 1804160641Syongari if (sc->sc_cdata.stge_rxcycles <= 0) 1805160641Syongari break; 1806160641Syongari sc->sc_cdata.stge_rxcycles--; 1807160641Syongari } 1808160641Syongari#endif 1809160641Syongari prog++; 1810160641Syongari rxd = &sc->sc_cdata.stge_rxdesc[cons]; 1811160641Syongari mp = rxd->rx_m; 1812160641Syongari 1813160641Syongari /* 1814160641Syongari * If the packet had an error, drop it. Note we count 1815160641Syongari * the error later in the periodic stats update. 1816160641Syongari */ 1817160641Syongari if ((status & RFD_FrameEnd) != 0 && (status & 1818160641Syongari (RFD_RxFIFOOverrun | RFD_RxRuntFrame | 1819160641Syongari RFD_RxAlignmentError | RFD_RxFCSError | 1820160641Syongari RFD_RxLengthError)) != 0) { 1821160641Syongari stge_discard_rxbuf(sc, cons); 1822160641Syongari if (sc->sc_cdata.stge_rxhead != NULL) { 1823160641Syongari m_freem(sc->sc_cdata.stge_rxhead); 1824160641Syongari STGE_RXCHAIN_RESET(sc); 1825160641Syongari } 1826160641Syongari continue; 1827160641Syongari } 1828160641Syongari /* 1829160641Syongari * Add a new receive buffer to the ring. 1830160641Syongari */ 1831160641Syongari if (stge_newbuf(sc, cons) != 0) { 1832160641Syongari ifp->if_iqdrops++; 1833160641Syongari stge_discard_rxbuf(sc, cons); 1834160641Syongari if (sc->sc_cdata.stge_rxhead != NULL) { 1835160641Syongari m_freem(sc->sc_cdata.stge_rxhead); 1836160641Syongari STGE_RXCHAIN_RESET(sc); 1837160641Syongari } 1838160641Syongari continue; 1839160641Syongari } 1840160641Syongari 1841160641Syongari if ((status & RFD_FrameEnd) != 0) 1842160641Syongari mp->m_len = RFD_RxDMAFrameLen(status) - 1843160641Syongari sc->sc_cdata.stge_rxlen; 1844160641Syongari sc->sc_cdata.stge_rxlen += mp->m_len; 1845160641Syongari 1846160641Syongari /* Chain mbufs. */ 1847160641Syongari if (sc->sc_cdata.stge_rxhead == NULL) { 1848160641Syongari sc->sc_cdata.stge_rxhead = mp; 1849160641Syongari sc->sc_cdata.stge_rxtail = mp; 1850160641Syongari } else { 1851160641Syongari mp->m_flags &= ~M_PKTHDR; 1852160641Syongari sc->sc_cdata.stge_rxtail->m_next = mp; 1853160641Syongari sc->sc_cdata.stge_rxtail = mp; 1854160641Syongari } 1855160641Syongari 1856160641Syongari if ((status & RFD_FrameEnd) != 0) { 1857160641Syongari m = sc->sc_cdata.stge_rxhead; 1858160641Syongari m->m_pkthdr.rcvif = ifp; 1859160641Syongari m->m_pkthdr.len = sc->sc_cdata.stge_rxlen; 1860160641Syongari 1861160641Syongari if (m->m_pkthdr.len > sc->sc_if_framesize) { 1862160641Syongari m_freem(m); 1863160641Syongari STGE_RXCHAIN_RESET(sc); 1864160641Syongari continue; 1865160641Syongari } 1866160641Syongari /* 1867160641Syongari * Set the incoming checksum information for 1868160641Syongari * the packet. 1869160641Syongari */ 1870160641Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) { 1871160641Syongari if ((status & RFD_IPDetected) != 0) { 1872160641Syongari m->m_pkthdr.csum_flags |= 1873160641Syongari CSUM_IP_CHECKED; 1874160641Syongari if ((status & RFD_IPError) == 0) 1875160641Syongari m->m_pkthdr.csum_flags |= 1876160641Syongari CSUM_IP_VALID; 1877160641Syongari } 1878160641Syongari if (((status & RFD_TCPDetected) != 0 && 1879160641Syongari (status & RFD_TCPError) == 0) || 1880160641Syongari ((status & RFD_UDPDetected) != 0 && 1881160641Syongari (status & RFD_UDPError) == 0)) { 1882160641Syongari m->m_pkthdr.csum_flags |= 1883160641Syongari (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); 1884160641Syongari m->m_pkthdr.csum_data = 0xffff; 1885160641Syongari } 1886160641Syongari } 1887160641Syongari 1888160641Syongari#ifndef __NO_STRICT_ALIGNMENT 1889160641Syongari if (sc->sc_if_framesize > (MCLBYTES - ETHER_ALIGN)) { 1890160641Syongari if ((m = stge_fixup_rx(sc, m)) == NULL) { 1891160641Syongari STGE_RXCHAIN_RESET(sc); 1892160641Syongari continue; 1893160641Syongari } 1894160641Syongari } 1895160641Syongari#endif 1896160641Syongari /* Check for VLAN tagged packets. */ 1897160641Syongari if ((status & RFD_VLANDetected) != 0 && 1898162375Sandre (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 1899162375Sandre m->m_pkthdr.ether_vtag = RFD_TCI(status64); 1900162375Sandre m->m_flags |= M_VLANTAG; 1901162375Sandre } 1902160641Syongari 1903160641Syongari STGE_UNLOCK(sc); 1904160641Syongari /* Pass it on. */ 1905160641Syongari (*ifp->if_input)(ifp, m); 1906160641Syongari STGE_LOCK(sc); 1907193096Sattilio rx_npkts++; 1908160641Syongari 1909160641Syongari STGE_RXCHAIN_RESET(sc); 1910160641Syongari } 1911160641Syongari } 1912160641Syongari 1913160641Syongari if (prog > 0) { 1914160641Syongari /* Update the consumer index. */ 1915160641Syongari sc->sc_cdata.stge_rx_cons = cons; 1916160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_rx_ring_tag, 1917160641Syongari sc->sc_cdata.stge_rx_ring_map, 1918160641Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1919160641Syongari } 1920193096Sattilio return (rx_npkts); 1921160641Syongari} 1922160641Syongari 1923160641Syongari#ifdef DEVICE_POLLING 1924193096Sattiliostatic int 1925160641Syongaristge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 1926160641Syongari{ 1927160641Syongari struct stge_softc *sc; 1928160641Syongari uint16_t status; 1929193096Sattilio int rx_npkts; 1930160641Syongari 1931193096Sattilio rx_npkts = 0; 1932160641Syongari sc = ifp->if_softc; 1933160641Syongari STGE_LOCK(sc); 1934160641Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1935160641Syongari STGE_UNLOCK(sc); 1936193096Sattilio return (rx_npkts); 1937160641Syongari } 1938160641Syongari 1939160641Syongari sc->sc_cdata.stge_rxcycles = count; 1940193096Sattilio rx_npkts = stge_rxeof(sc); 1941160641Syongari stge_txeof(sc); 1942160641Syongari 1943160641Syongari if (cmd == POLL_AND_CHECK_STATUS) { 1944160641Syongari status = CSR_READ_2(sc, STGE_IntStatus); 1945160641Syongari status &= sc->sc_IntEnable; 1946160641Syongari if (status != 0) { 1947160641Syongari if ((status & IS_HostError) != 0) { 1948160641Syongari device_printf(sc->sc_dev, 1949160641Syongari "Host interface error, resetting...\n"); 1950212972Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1951160641Syongari stge_init_locked(sc); 1952160641Syongari } 1953160641Syongari if ((status & IS_TxComplete) != 0) { 1954212972Syongari if (stge_tx_error(sc) != 0) { 1955212972Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1956160641Syongari stge_init_locked(sc); 1957212972Syongari } 1958160641Syongari } 1959160641Syongari } 1960160641Syongari 1961160641Syongari } 1962160641Syongari 1963160641Syongari if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1964160641Syongari stge_start_locked(ifp); 1965160641Syongari 1966160641Syongari STGE_UNLOCK(sc); 1967193096Sattilio return (rx_npkts); 1968160641Syongari} 1969160641Syongari#endif /* DEVICE_POLLING */ 1970160641Syongari 1971160641Syongari/* 1972160641Syongari * stge_tick: 1973160641Syongari * 1974160641Syongari * One second timer, used to tick the MII. 1975160641Syongari */ 1976160641Syongaristatic void 1977160641Syongaristge_tick(void *arg) 1978160641Syongari{ 1979160641Syongari struct stge_softc *sc; 1980160641Syongari struct mii_data *mii; 1981160641Syongari 1982160641Syongari sc = (struct stge_softc *)arg; 1983160641Syongari 1984160641Syongari STGE_LOCK_ASSERT(sc); 1985160641Syongari 1986160641Syongari mii = device_get_softc(sc->sc_miibus); 1987160641Syongari mii_tick(mii); 1988160641Syongari 1989160641Syongari /* Update statistics counters. */ 1990160641Syongari stge_stats_update(sc); 1991160641Syongari 1992160641Syongari /* 1993160641Syongari * Relcaim any pending Tx descriptors to release mbufs in a 1994160641Syongari * timely manner as we don't generate Tx completion interrupts 1995160641Syongari * for every frame. This limits the delay to a maximum of one 1996160641Syongari * second. 1997160641Syongari */ 1998160641Syongari if (sc->sc_cdata.stge_tx_cnt != 0) 1999160641Syongari stge_txeof(sc); 2000160641Syongari 2001169157Syongari stge_watchdog(sc); 2002169157Syongari 2003160641Syongari callout_reset(&sc->sc_tick_ch, hz, stge_tick, sc); 2004160641Syongari} 2005160641Syongari 2006160641Syongari/* 2007160641Syongari * stge_stats_update: 2008160641Syongari * 2009160641Syongari * Read the TC9021 statistics counters. 2010160641Syongari */ 2011160641Syongaristatic void 2012160641Syongaristge_stats_update(struct stge_softc *sc) 2013160641Syongari{ 2014160641Syongari struct ifnet *ifp; 2015160641Syongari 2016160641Syongari STGE_LOCK_ASSERT(sc); 2017160641Syongari 2018160641Syongari ifp = sc->sc_ifp; 2019160641Syongari 2020160641Syongari CSR_READ_4(sc,STGE_OctetRcvOk); 2021160641Syongari 2022160641Syongari ifp->if_ipackets += CSR_READ_4(sc, STGE_FramesRcvdOk); 2023160641Syongari 2024160641Syongari ifp->if_ierrors += CSR_READ_2(sc, STGE_FramesLostRxErrors); 2025160641Syongari 2026160641Syongari CSR_READ_4(sc, STGE_OctetXmtdOk); 2027160641Syongari 2028160641Syongari ifp->if_opackets += CSR_READ_4(sc, STGE_FramesXmtdOk); 2029160641Syongari 2030160641Syongari ifp->if_collisions += 2031160641Syongari CSR_READ_4(sc, STGE_LateCollisions) + 2032160641Syongari CSR_READ_4(sc, STGE_MultiColFrames) + 2033160641Syongari CSR_READ_4(sc, STGE_SingleColFrames); 2034160641Syongari 2035160641Syongari ifp->if_oerrors += 2036160641Syongari CSR_READ_2(sc, STGE_FramesAbortXSColls) + 2037160641Syongari CSR_READ_2(sc, STGE_FramesWEXDeferal); 2038160641Syongari} 2039160641Syongari 2040160641Syongari/* 2041160641Syongari * stge_reset: 2042160641Syongari * 2043160641Syongari * Perform a soft reset on the TC9021. 2044160641Syongari */ 2045160641Syongaristatic void 2046160641Syongaristge_reset(struct stge_softc *sc, uint32_t how) 2047160641Syongari{ 2048160641Syongari uint32_t ac; 2049160641Syongari uint8_t v; 2050160641Syongari int i, dv; 2051160641Syongari 2052160641Syongari STGE_LOCK_ASSERT(sc); 2053160641Syongari 2054160641Syongari dv = 5000; 2055160641Syongari ac = CSR_READ_4(sc, STGE_AsicCtrl); 2056160641Syongari switch (how) { 2057160641Syongari case STGE_RESET_TX: 2058160641Syongari ac |= AC_TxReset | AC_FIFO; 2059160641Syongari dv = 100; 2060160641Syongari break; 2061160641Syongari case STGE_RESET_RX: 2062160641Syongari ac |= AC_RxReset | AC_FIFO; 2063160641Syongari dv = 100; 2064160641Syongari break; 2065160641Syongari case STGE_RESET_FULL: 2066160641Syongari default: 2067160641Syongari /* 2068160641Syongari * Only assert RstOut if we're fiber. We need GMII clocks 2069160641Syongari * to be present in order for the reset to complete on fiber 2070160641Syongari * cards. 2071160641Syongari */ 2072160641Syongari ac |= AC_GlobalReset | AC_RxReset | AC_TxReset | 2073160641Syongari AC_DMA | AC_FIFO | AC_Network | AC_Host | AC_AutoInit | 2074160641Syongari (sc->sc_usefiber ? AC_RstOut : 0); 2075160641Syongari break; 2076160641Syongari } 2077160641Syongari 2078160641Syongari CSR_WRITE_4(sc, STGE_AsicCtrl, ac); 2079160641Syongari 2080160641Syongari /* Account for reset problem at 10Mbps. */ 2081160641Syongari DELAY(dv); 2082160641Syongari 2083160641Syongari for (i = 0; i < STGE_TIMEOUT; i++) { 2084160641Syongari if ((CSR_READ_4(sc, STGE_AsicCtrl) & AC_ResetBusy) == 0) 2085160641Syongari break; 2086160641Syongari DELAY(dv); 2087160641Syongari } 2088160641Syongari 2089160641Syongari if (i == STGE_TIMEOUT) 2090160641Syongari device_printf(sc->sc_dev, "reset failed to complete\n"); 2091160641Syongari 2092160641Syongari /* Set LED, from Linux IPG driver. */ 2093160641Syongari ac = CSR_READ_4(sc, STGE_AsicCtrl); 2094160641Syongari ac &= ~(AC_LEDMode | AC_LEDSpeed | AC_LEDModeBit1); 2095160641Syongari if ((sc->sc_led & 0x01) != 0) 2096160641Syongari ac |= AC_LEDMode; 2097160641Syongari if ((sc->sc_led & 0x03) != 0) 2098160641Syongari ac |= AC_LEDModeBit1; 2099160641Syongari if ((sc->sc_led & 0x08) != 0) 2100160641Syongari ac |= AC_LEDSpeed; 2101160641Syongari CSR_WRITE_4(sc, STGE_AsicCtrl, ac); 2102160641Syongari 2103160641Syongari /* Set PHY, from Linux IPG driver */ 2104160641Syongari v = CSR_READ_1(sc, STGE_PhySet); 2105160641Syongari v &= ~(PS_MemLenb9b | PS_MemLen | PS_NonCompdet); 2106160641Syongari v |= ((sc->sc_led & 0x70) >> 4); 2107160641Syongari CSR_WRITE_1(sc, STGE_PhySet, v); 2108160641Syongari} 2109160641Syongari 2110160641Syongari/* 2111160641Syongari * stge_init: [ ifnet interface function ] 2112160641Syongari * 2113160641Syongari * Initialize the interface. 2114160641Syongari */ 2115160641Syongaristatic void 2116160641Syongaristge_init(void *xsc) 2117160641Syongari{ 2118160641Syongari struct stge_softc *sc; 2119160641Syongari 2120160641Syongari sc = (struct stge_softc *)xsc; 2121160641Syongari STGE_LOCK(sc); 2122160641Syongari stge_init_locked(sc); 2123160641Syongari STGE_UNLOCK(sc); 2124160641Syongari} 2125160641Syongari 2126160641Syongaristatic void 2127160641Syongaristge_init_locked(struct stge_softc *sc) 2128160641Syongari{ 2129160641Syongari struct ifnet *ifp; 2130160641Syongari struct mii_data *mii; 2131160641Syongari uint16_t eaddr[3]; 2132160641Syongari uint32_t v; 2133160641Syongari int error; 2134160641Syongari 2135160641Syongari STGE_LOCK_ASSERT(sc); 2136160641Syongari 2137160641Syongari ifp = sc->sc_ifp; 2138212972Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2139212972Syongari return; 2140160641Syongari mii = device_get_softc(sc->sc_miibus); 2141160641Syongari 2142160641Syongari /* 2143160641Syongari * Cancel any pending I/O. 2144160641Syongari */ 2145160641Syongari stge_stop(sc); 2146160641Syongari 2147175315Syongari /* 2148175315Syongari * Reset the chip to a known state. 2149175315Syongari */ 2150175315Syongari stge_reset(sc, STGE_RESET_FULL); 2151175315Syongari 2152160641Syongari /* Init descriptors. */ 2153160641Syongari error = stge_init_rx_ring(sc); 2154160641Syongari if (error != 0) { 2155160641Syongari device_printf(sc->sc_dev, 2156160641Syongari "initialization failed: no memory for rx buffers\n"); 2157160641Syongari stge_stop(sc); 2158160641Syongari goto out; 2159160641Syongari } 2160160641Syongari stge_init_tx_ring(sc); 2161160641Syongari 2162160641Syongari /* Set the station address. */ 2163160641Syongari bcopy(IF_LLADDR(ifp), eaddr, ETHER_ADDR_LEN); 2164160641Syongari CSR_WRITE_2(sc, STGE_StationAddress0, htole16(eaddr[0])); 2165160641Syongari CSR_WRITE_2(sc, STGE_StationAddress1, htole16(eaddr[1])); 2166160641Syongari CSR_WRITE_2(sc, STGE_StationAddress2, htole16(eaddr[2])); 2167160641Syongari 2168160641Syongari /* 2169160641Syongari * Set the statistics masks. Disable all the RMON stats, 2170160641Syongari * and disable selected stats in the non-RMON stats registers. 2171160641Syongari */ 2172160641Syongari CSR_WRITE_4(sc, STGE_RMONStatisticsMask, 0xffffffff); 2173160641Syongari CSR_WRITE_4(sc, STGE_StatisticsMask, 2174160641Syongari (1U << 1) | (1U << 2) | (1U << 3) | (1U << 4) | (1U << 5) | 2175160641Syongari (1U << 6) | (1U << 7) | (1U << 8) | (1U << 9) | (1U << 10) | 2176160641Syongari (1U << 13) | (1U << 14) | (1U << 15) | (1U << 19) | (1U << 20) | 2177160641Syongari (1U << 21)); 2178160641Syongari 2179160641Syongari /* Set up the receive filter. */ 2180160641Syongari stge_set_filter(sc); 2181160641Syongari /* Program multicast filter. */ 2182160641Syongari stge_set_multi(sc); 2183160641Syongari 2184160641Syongari /* 2185160641Syongari * Give the transmit and receive ring to the chip. 2186160641Syongari */ 2187160641Syongari CSR_WRITE_4(sc, STGE_TFDListPtrHi, 2188160641Syongari STGE_ADDR_HI(STGE_TX_RING_ADDR(sc, 0))); 2189160641Syongari CSR_WRITE_4(sc, STGE_TFDListPtrLo, 2190160641Syongari STGE_ADDR_LO(STGE_TX_RING_ADDR(sc, 0))); 2191160641Syongari 2192160641Syongari CSR_WRITE_4(sc, STGE_RFDListPtrHi, 2193160641Syongari STGE_ADDR_HI(STGE_RX_RING_ADDR(sc, 0))); 2194160641Syongari CSR_WRITE_4(sc, STGE_RFDListPtrLo, 2195160641Syongari STGE_ADDR_LO(STGE_RX_RING_ADDR(sc, 0))); 2196160641Syongari 2197160641Syongari /* 2198160641Syongari * Initialize the Tx auto-poll period. It's OK to make this number 2199160641Syongari * large (255 is the max, but we use 127) -- we explicitly kick the 2200160641Syongari * transmit engine when there's actually a packet. 2201160641Syongari */ 2202160641Syongari CSR_WRITE_1(sc, STGE_TxDMAPollPeriod, 127); 2203160641Syongari 2204160641Syongari /* ..and the Rx auto-poll period. */ 2205160641Syongari CSR_WRITE_1(sc, STGE_RxDMAPollPeriod, 1); 2206160641Syongari 2207160641Syongari /* Initialize the Tx start threshold. */ 2208160641Syongari CSR_WRITE_2(sc, STGE_TxStartThresh, sc->sc_txthresh); 2209160641Syongari 2210160641Syongari /* Rx DMA thresholds, from Linux */ 2211160641Syongari CSR_WRITE_1(sc, STGE_RxDMABurstThresh, 0x30); 2212160641Syongari CSR_WRITE_1(sc, STGE_RxDMAUrgentThresh, 0x30); 2213160641Syongari 2214160641Syongari /* Rx early threhold, from Linux */ 2215160641Syongari CSR_WRITE_2(sc, STGE_RxEarlyThresh, 0x7ff); 2216160641Syongari 2217160641Syongari /* Tx DMA thresholds, from Linux */ 2218160641Syongari CSR_WRITE_1(sc, STGE_TxDMABurstThresh, 0x30); 2219160641Syongari CSR_WRITE_1(sc, STGE_TxDMAUrgentThresh, 0x04); 2220160641Syongari 2221160641Syongari /* 2222160641Syongari * Initialize the Rx DMA interrupt control register. We 2223160641Syongari * request an interrupt after every incoming packet, but 2224160641Syongari * defer it for sc_rxint_dmawait us. When the number of 2225160641Syongari * interrupts pending reaches STGE_RXINT_NFRAME, we stop 2226160641Syongari * deferring the interrupt, and signal it immediately. 2227160641Syongari */ 2228160641Syongari CSR_WRITE_4(sc, STGE_RxDMAIntCtrl, 2229160641Syongari RDIC_RxFrameCount(sc->sc_rxint_nframe) | 2230160641Syongari RDIC_RxDMAWaitTime(STGE_RXINT_USECS2TICK(sc->sc_rxint_dmawait))); 2231160641Syongari 2232160641Syongari /* 2233160641Syongari * Initialize the interrupt mask. 2234160641Syongari */ 2235160641Syongari sc->sc_IntEnable = IS_HostError | IS_TxComplete | 2236160641Syongari IS_TxDMAComplete | IS_RxDMAComplete | IS_RFDListEnd; 2237160641Syongari#ifdef DEVICE_POLLING 2238160641Syongari /* Disable interrupts if we are polling. */ 2239160641Syongari if ((ifp->if_capenable & IFCAP_POLLING) != 0) 2240160641Syongari CSR_WRITE_2(sc, STGE_IntEnable, 0); 2241160641Syongari else 2242160641Syongari#endif 2243160641Syongari CSR_WRITE_2(sc, STGE_IntEnable, sc->sc_IntEnable); 2244160641Syongari 2245160641Syongari /* 2246160641Syongari * Configure the DMA engine. 2247160641Syongari * XXX Should auto-tune TxBurstLimit. 2248160641Syongari */ 2249160641Syongari CSR_WRITE_4(sc, STGE_DMACtrl, sc->sc_DMACtrl | DMAC_TxBurstLimit(3)); 2250160641Syongari 2251160641Syongari /* 2252160641Syongari * Send a PAUSE frame when we reach 29,696 bytes in the Rx 2253160641Syongari * FIFO, and send an un-PAUSE frame when we reach 3056 bytes 2254160641Syongari * in the Rx FIFO. 2255160641Syongari */ 2256160641Syongari CSR_WRITE_2(sc, STGE_FlowOnTresh, 29696 / 16); 2257160641Syongari CSR_WRITE_2(sc, STGE_FlowOffThresh, 3056 / 16); 2258160641Syongari 2259160641Syongari /* 2260160641Syongari * Set the maximum frame size. 2261160641Syongari */ 2262160641Syongari sc->sc_if_framesize = ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN; 2263160641Syongari CSR_WRITE_2(sc, STGE_MaxFrameSize, sc->sc_if_framesize); 2264160641Syongari 2265160641Syongari /* 2266160641Syongari * Initialize MacCtrl -- do it before setting the media, 2267160641Syongari * as setting the media will actually program the register. 2268160641Syongari * 2269160641Syongari * Note: We have to poke the IFS value before poking 2270160641Syongari * anything else. 2271160641Syongari */ 2272160641Syongari /* Tx/Rx MAC should be disabled before programming IFS.*/ 2273160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, MC_IFSSelect(MC_IFS96bit)); 2274160641Syongari 2275160641Syongari stge_vlan_setup(sc); 2276160641Syongari 2277160641Syongari if (sc->sc_rev >= 6) { /* >= B.2 */ 2278160641Syongari /* Multi-frag frame bug work-around. */ 2279160641Syongari CSR_WRITE_2(sc, STGE_DebugCtrl, 2280160641Syongari CSR_READ_2(sc, STGE_DebugCtrl) | 0x0200); 2281160641Syongari 2282160641Syongari /* Tx Poll Now bug work-around. */ 2283160641Syongari CSR_WRITE_2(sc, STGE_DebugCtrl, 2284160641Syongari CSR_READ_2(sc, STGE_DebugCtrl) | 0x0010); 2285160641Syongari /* Tx Poll Now bug work-around. */ 2286160641Syongari CSR_WRITE_2(sc, STGE_DebugCtrl, 2287160641Syongari CSR_READ_2(sc, STGE_DebugCtrl) | 0x0020); 2288160641Syongari } 2289160641Syongari 2290160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2291160641Syongari v |= MC_StatisticsEnable | MC_TxEnable | MC_RxEnable; 2292160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, v); 2293160641Syongari /* 2294160641Syongari * It seems that transmitting frames without checking the state of 2295160641Syongari * Rx/Tx MAC wedge the hardware. 2296160641Syongari */ 2297160641Syongari stge_start_tx(sc); 2298160641Syongari stge_start_rx(sc); 2299160641Syongari 2300169158Syongari sc->sc_link = 0; 2301160641Syongari /* 2302160641Syongari * Set the current media. 2303160641Syongari */ 2304160641Syongari mii_mediachg(mii); 2305160641Syongari 2306160641Syongari /* 2307160641Syongari * Start the one second MII clock. 2308160641Syongari */ 2309160641Syongari callout_reset(&sc->sc_tick_ch, hz, stge_tick, sc); 2310160641Syongari 2311160641Syongari /* 2312160641Syongari * ...all done! 2313160641Syongari */ 2314160641Syongari ifp->if_drv_flags |= IFF_DRV_RUNNING; 2315160641Syongari ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2316160641Syongari 2317160641Syongari out: 2318160641Syongari if (error != 0) 2319160641Syongari device_printf(sc->sc_dev, "interface not running\n"); 2320160641Syongari} 2321160641Syongari 2322160641Syongaristatic void 2323160641Syongaristge_vlan_setup(struct stge_softc *sc) 2324160641Syongari{ 2325160641Syongari struct ifnet *ifp; 2326160641Syongari uint32_t v; 2327160641Syongari 2328160641Syongari ifp = sc->sc_ifp; 2329160641Syongari /* 2330160641Syongari * The NIC always copy a VLAN tag regardless of STGE_MACCtrl 2331160641Syongari * MC_AutoVLANuntagging bit. 2332160641Syongari * MC_AutoVLANtagging bit selects which VLAN source to use 2333160641Syongari * between STGE_VLANTag and TFC. However TFC TFD_VLANTagInsert 2334160641Syongari * bit has priority over MC_AutoVLANtagging bit. So we always 2335160641Syongari * use TFC instead of STGE_VLANTag register. 2336160641Syongari */ 2337160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2338160641Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 2339160641Syongari v |= MC_AutoVLANuntagging; 2340160641Syongari else 2341160641Syongari v &= ~MC_AutoVLANuntagging; 2342160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, v); 2343160641Syongari} 2344160641Syongari 2345160641Syongari/* 2346160641Syongari * Stop transmission on the interface. 2347160641Syongari */ 2348160641Syongaristatic void 2349160641Syongaristge_stop(struct stge_softc *sc) 2350160641Syongari{ 2351160641Syongari struct ifnet *ifp; 2352160641Syongari struct stge_txdesc *txd; 2353160641Syongari struct stge_rxdesc *rxd; 2354160641Syongari uint32_t v; 2355160641Syongari int i; 2356160641Syongari 2357160641Syongari STGE_LOCK_ASSERT(sc); 2358160641Syongari /* 2359160641Syongari * Stop the one second clock. 2360160641Syongari */ 2361160641Syongari callout_stop(&sc->sc_tick_ch); 2362169157Syongari sc->sc_watchdog_timer = 0; 2363160641Syongari 2364160641Syongari /* 2365160641Syongari * Disable interrupts. 2366160641Syongari */ 2367160641Syongari CSR_WRITE_2(sc, STGE_IntEnable, 0); 2368160641Syongari 2369160641Syongari /* 2370160641Syongari * Stop receiver, transmitter, and stats update. 2371160641Syongari */ 2372160641Syongari stge_stop_rx(sc); 2373160641Syongari stge_stop_tx(sc); 2374160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2375160641Syongari v |= MC_StatisticsDisable; 2376160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, v); 2377160641Syongari 2378160641Syongari /* 2379160641Syongari * Stop the transmit and receive DMA. 2380160641Syongari */ 2381160641Syongari stge_dma_wait(sc); 2382160641Syongari CSR_WRITE_4(sc, STGE_TFDListPtrHi, 0); 2383160641Syongari CSR_WRITE_4(sc, STGE_TFDListPtrLo, 0); 2384160641Syongari CSR_WRITE_4(sc, STGE_RFDListPtrHi, 0); 2385160641Syongari CSR_WRITE_4(sc, STGE_RFDListPtrLo, 0); 2386160641Syongari 2387160641Syongari /* 2388160641Syongari * Free RX and TX mbufs still in the queues. 2389160641Syongari */ 2390160641Syongari for (i = 0; i < STGE_RX_RING_CNT; i++) { 2391160641Syongari rxd = &sc->sc_cdata.stge_rxdesc[i]; 2392160641Syongari if (rxd->rx_m != NULL) { 2393160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_rx_tag, 2394160641Syongari rxd->rx_dmamap, BUS_DMASYNC_POSTREAD); 2395160641Syongari bus_dmamap_unload(sc->sc_cdata.stge_rx_tag, 2396160641Syongari rxd->rx_dmamap); 2397160641Syongari m_freem(rxd->rx_m); 2398160641Syongari rxd->rx_m = NULL; 2399160641Syongari } 2400160641Syongari } 2401160641Syongari for (i = 0; i < STGE_TX_RING_CNT; i++) { 2402160641Syongari txd = &sc->sc_cdata.stge_txdesc[i]; 2403160641Syongari if (txd->tx_m != NULL) { 2404160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_tx_tag, 2405160641Syongari txd->tx_dmamap, BUS_DMASYNC_POSTWRITE); 2406160641Syongari bus_dmamap_unload(sc->sc_cdata.stge_tx_tag, 2407160641Syongari txd->tx_dmamap); 2408160641Syongari m_freem(txd->tx_m); 2409160641Syongari txd->tx_m = NULL; 2410160641Syongari } 2411160641Syongari } 2412160641Syongari 2413160641Syongari /* 2414160641Syongari * Mark the interface down and cancel the watchdog timer. 2415160641Syongari */ 2416160641Syongari ifp = sc->sc_ifp; 2417160641Syongari ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2418169158Syongari sc->sc_link = 0; 2419160641Syongari} 2420160641Syongari 2421160641Syongaristatic void 2422160641Syongaristge_start_tx(struct stge_softc *sc) 2423160641Syongari{ 2424160641Syongari uint32_t v; 2425160641Syongari int i; 2426160641Syongari 2427160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2428160641Syongari if ((v & MC_TxEnabled) != 0) 2429160641Syongari return; 2430160641Syongari v |= MC_TxEnable; 2431160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, v); 2432160641Syongari CSR_WRITE_1(sc, STGE_TxDMAPollPeriod, 127); 2433160641Syongari for (i = STGE_TIMEOUT; i > 0; i--) { 2434160641Syongari DELAY(10); 2435160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2436160641Syongari if ((v & MC_TxEnabled) != 0) 2437160641Syongari break; 2438160641Syongari } 2439160641Syongari if (i == 0) 2440160641Syongari device_printf(sc->sc_dev, "Starting Tx MAC timed out\n"); 2441160641Syongari} 2442160641Syongari 2443160641Syongaristatic void 2444160641Syongaristge_start_rx(struct stge_softc *sc) 2445160641Syongari{ 2446160641Syongari uint32_t v; 2447160641Syongari int i; 2448160641Syongari 2449160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2450160641Syongari if ((v & MC_RxEnabled) != 0) 2451160641Syongari return; 2452160641Syongari v |= MC_RxEnable; 2453160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, v); 2454160641Syongari CSR_WRITE_1(sc, STGE_RxDMAPollPeriod, 1); 2455160641Syongari for (i = STGE_TIMEOUT; i > 0; i--) { 2456160641Syongari DELAY(10); 2457160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2458160641Syongari if ((v & MC_RxEnabled) != 0) 2459160641Syongari break; 2460160641Syongari } 2461160641Syongari if (i == 0) 2462160641Syongari device_printf(sc->sc_dev, "Starting Rx MAC timed out\n"); 2463160641Syongari} 2464160641Syongari 2465160641Syongaristatic void 2466160641Syongaristge_stop_tx(struct stge_softc *sc) 2467160641Syongari{ 2468160641Syongari uint32_t v; 2469160641Syongari int i; 2470160641Syongari 2471160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2472160641Syongari if ((v & MC_TxEnabled) == 0) 2473160641Syongari return; 2474160641Syongari v |= MC_TxDisable; 2475160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, v); 2476160641Syongari for (i = STGE_TIMEOUT; i > 0; i--) { 2477160641Syongari DELAY(10); 2478160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2479160641Syongari if ((v & MC_TxEnabled) == 0) 2480160641Syongari break; 2481160641Syongari } 2482160641Syongari if (i == 0) 2483160641Syongari device_printf(sc->sc_dev, "Stopping Tx MAC timed out\n"); 2484160641Syongari} 2485160641Syongari 2486160641Syongaristatic void 2487160641Syongaristge_stop_rx(struct stge_softc *sc) 2488160641Syongari{ 2489160641Syongari uint32_t v; 2490160641Syongari int i; 2491160641Syongari 2492160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2493160641Syongari if ((v & MC_RxEnabled) == 0) 2494160641Syongari return; 2495160641Syongari v |= MC_RxDisable; 2496160641Syongari CSR_WRITE_4(sc, STGE_MACCtrl, v); 2497160641Syongari for (i = STGE_TIMEOUT; i > 0; i--) { 2498160641Syongari DELAY(10); 2499160641Syongari v = CSR_READ_4(sc, STGE_MACCtrl) & MC_MASK; 2500160641Syongari if ((v & MC_RxEnabled) == 0) 2501160641Syongari break; 2502160641Syongari } 2503160641Syongari if (i == 0) 2504160641Syongari device_printf(sc->sc_dev, "Stopping Rx MAC timed out\n"); 2505160641Syongari} 2506160641Syongari 2507160641Syongaristatic void 2508160641Syongaristge_init_tx_ring(struct stge_softc *sc) 2509160641Syongari{ 2510160641Syongari struct stge_ring_data *rd; 2511160641Syongari struct stge_txdesc *txd; 2512160641Syongari bus_addr_t addr; 2513160641Syongari int i; 2514160641Syongari 2515160641Syongari STAILQ_INIT(&sc->sc_cdata.stge_txfreeq); 2516160641Syongari STAILQ_INIT(&sc->sc_cdata.stge_txbusyq); 2517160641Syongari 2518160641Syongari sc->sc_cdata.stge_tx_prod = 0; 2519160641Syongari sc->sc_cdata.stge_tx_cons = 0; 2520160641Syongari sc->sc_cdata.stge_tx_cnt = 0; 2521160641Syongari 2522160641Syongari rd = &sc->sc_rdata; 2523160641Syongari bzero(rd->stge_tx_ring, STGE_TX_RING_SZ); 2524160641Syongari for (i = 0; i < STGE_TX_RING_CNT; i++) { 2525160641Syongari if (i == (STGE_TX_RING_CNT - 1)) 2526160641Syongari addr = STGE_TX_RING_ADDR(sc, 0); 2527160641Syongari else 2528160641Syongari addr = STGE_TX_RING_ADDR(sc, i + 1); 2529160641Syongari rd->stge_tx_ring[i].tfd_next = htole64(addr); 2530160641Syongari rd->stge_tx_ring[i].tfd_control = htole64(TFD_TFDDone); 2531160641Syongari txd = &sc->sc_cdata.stge_txdesc[i]; 2532160641Syongari STAILQ_INSERT_TAIL(&sc->sc_cdata.stge_txfreeq, txd, tx_q); 2533160641Syongari } 2534160641Syongari 2535160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_tx_ring_tag, 2536160641Syongari sc->sc_cdata.stge_tx_ring_map, 2537160641Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2538160641Syongari 2539160641Syongari} 2540160641Syongari 2541160641Syongaristatic int 2542160641Syongaristge_init_rx_ring(struct stge_softc *sc) 2543160641Syongari{ 2544160641Syongari struct stge_ring_data *rd; 2545160641Syongari bus_addr_t addr; 2546160641Syongari int i; 2547160641Syongari 2548160641Syongari sc->sc_cdata.stge_rx_cons = 0; 2549160641Syongari STGE_RXCHAIN_RESET(sc); 2550160641Syongari 2551160641Syongari rd = &sc->sc_rdata; 2552160641Syongari bzero(rd->stge_rx_ring, STGE_RX_RING_SZ); 2553160641Syongari for (i = 0; i < STGE_RX_RING_CNT; i++) { 2554160641Syongari if (stge_newbuf(sc, i) != 0) 2555160641Syongari return (ENOBUFS); 2556160641Syongari if (i == (STGE_RX_RING_CNT - 1)) 2557160641Syongari addr = STGE_RX_RING_ADDR(sc, 0); 2558160641Syongari else 2559160641Syongari addr = STGE_RX_RING_ADDR(sc, i + 1); 2560160641Syongari rd->stge_rx_ring[i].rfd_next = htole64(addr); 2561160641Syongari rd->stge_rx_ring[i].rfd_status = 0; 2562160641Syongari } 2563160641Syongari 2564160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_rx_ring_tag, 2565160641Syongari sc->sc_cdata.stge_rx_ring_map, 2566160641Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2567160641Syongari 2568160641Syongari return (0); 2569160641Syongari} 2570160641Syongari 2571160641Syongari/* 2572160641Syongari * stge_newbuf: 2573160641Syongari * 2574160641Syongari * Add a receive buffer to the indicated descriptor. 2575160641Syongari */ 2576160641Syongaristatic int 2577160641Syongaristge_newbuf(struct stge_softc *sc, int idx) 2578160641Syongari{ 2579160641Syongari struct stge_rxdesc *rxd; 2580160641Syongari struct stge_rfd *rfd; 2581160641Syongari struct mbuf *m; 2582160641Syongari bus_dma_segment_t segs[1]; 2583160641Syongari bus_dmamap_t map; 2584160641Syongari int nsegs; 2585160641Syongari 2586160641Syongari m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 2587160641Syongari if (m == NULL) 2588160641Syongari return (ENOBUFS); 2589160641Syongari m->m_len = m->m_pkthdr.len = MCLBYTES; 2590160641Syongari /* 2591160641Syongari * The hardware requires 4bytes aligned DMA address when JUMBO 2592160641Syongari * frame is used. 2593160641Syongari */ 2594160641Syongari if (sc->sc_if_framesize <= (MCLBYTES - ETHER_ALIGN)) 2595160641Syongari m_adj(m, ETHER_ALIGN); 2596160641Syongari 2597160641Syongari if (bus_dmamap_load_mbuf_sg(sc->sc_cdata.stge_rx_tag, 2598160641Syongari sc->sc_cdata.stge_rx_sparemap, m, segs, &nsegs, 0) != 0) { 2599160641Syongari m_freem(m); 2600160641Syongari return (ENOBUFS); 2601160641Syongari } 2602160641Syongari KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 2603160641Syongari 2604160641Syongari rxd = &sc->sc_cdata.stge_rxdesc[idx]; 2605160641Syongari if (rxd->rx_m != NULL) { 2606160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_rx_tag, rxd->rx_dmamap, 2607160641Syongari BUS_DMASYNC_POSTREAD); 2608160641Syongari bus_dmamap_unload(sc->sc_cdata.stge_rx_tag, rxd->rx_dmamap); 2609160641Syongari } 2610160641Syongari map = rxd->rx_dmamap; 2611160641Syongari rxd->rx_dmamap = sc->sc_cdata.stge_rx_sparemap; 2612160641Syongari sc->sc_cdata.stge_rx_sparemap = map; 2613160641Syongari bus_dmamap_sync(sc->sc_cdata.stge_rx_tag, rxd->rx_dmamap, 2614160641Syongari BUS_DMASYNC_PREREAD); 2615160641Syongari rxd->rx_m = m; 2616160641Syongari 2617160641Syongari rfd = &sc->sc_rdata.stge_rx_ring[idx]; 2618160641Syongari rfd->rfd_frag.frag_word0 = 2619160641Syongari htole64(FRAG_ADDR(segs[0].ds_addr) | FRAG_LEN(segs[0].ds_len)); 2620160641Syongari rfd->rfd_status = 0; 2621160641Syongari 2622160641Syongari return (0); 2623160641Syongari} 2624160641Syongari 2625160641Syongari/* 2626160641Syongari * stge_set_filter: 2627160641Syongari * 2628160641Syongari * Set up the receive filter. 2629160641Syongari */ 2630160641Syongaristatic void 2631160641Syongaristge_set_filter(struct stge_softc *sc) 2632160641Syongari{ 2633160641Syongari struct ifnet *ifp; 2634160641Syongari uint16_t mode; 2635160641Syongari 2636160641Syongari STGE_LOCK_ASSERT(sc); 2637160641Syongari 2638160641Syongari ifp = sc->sc_ifp; 2639160641Syongari 2640160641Syongari mode = CSR_READ_2(sc, STGE_ReceiveMode); 2641160641Syongari mode |= RM_ReceiveUnicast; 2642160641Syongari if ((ifp->if_flags & IFF_BROADCAST) != 0) 2643160641Syongari mode |= RM_ReceiveBroadcast; 2644160641Syongari else 2645160641Syongari mode &= ~RM_ReceiveBroadcast; 2646160641Syongari if ((ifp->if_flags & IFF_PROMISC) != 0) 2647160641Syongari mode |= RM_ReceiveAllFrames; 2648160641Syongari else 2649160641Syongari mode &= ~RM_ReceiveAllFrames; 2650160641Syongari 2651160641Syongari CSR_WRITE_2(sc, STGE_ReceiveMode, mode); 2652160641Syongari} 2653160641Syongari 2654160641Syongaristatic void 2655160641Syongaristge_set_multi(struct stge_softc *sc) 2656160641Syongari{ 2657160641Syongari struct ifnet *ifp; 2658160641Syongari struct ifmultiaddr *ifma; 2659160641Syongari uint32_t crc; 2660160641Syongari uint32_t mchash[2]; 2661160641Syongari uint16_t mode; 2662160641Syongari int count; 2663160641Syongari 2664160641Syongari STGE_LOCK_ASSERT(sc); 2665160641Syongari 2666160641Syongari ifp = sc->sc_ifp; 2667160641Syongari 2668160641Syongari mode = CSR_READ_2(sc, STGE_ReceiveMode); 2669160641Syongari if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { 2670160641Syongari if ((ifp->if_flags & IFF_PROMISC) != 0) 2671160641Syongari mode |= RM_ReceiveAllFrames; 2672160641Syongari else if ((ifp->if_flags & IFF_ALLMULTI) != 0) 2673160641Syongari mode |= RM_ReceiveMulticast; 2674160641Syongari CSR_WRITE_2(sc, STGE_ReceiveMode, mode); 2675160641Syongari return; 2676160641Syongari } 2677160641Syongari 2678160641Syongari /* clear existing filters. */ 2679160641Syongari CSR_WRITE_4(sc, STGE_HashTable0, 0); 2680160641Syongari CSR_WRITE_4(sc, STGE_HashTable1, 0); 2681160641Syongari 2682160641Syongari /* 2683160641Syongari * Set up the multicast address filter by passing all multicast 2684160641Syongari * addresses through a CRC generator, and then using the low-order 2685160641Syongari * 6 bits as an index into the 64 bit multicast hash table. The 2686160641Syongari * high order bits select the register, while the rest of the bits 2687160641Syongari * select the bit within the register. 2688160641Syongari */ 2689160641Syongari 2690160641Syongari bzero(mchash, sizeof(mchash)); 2691160641Syongari 2692160641Syongari count = 0; 2693195049Srwatson if_maddr_rlock(sc->sc_ifp); 2694160641Syongari TAILQ_FOREACH(ifma, &sc->sc_ifp->if_multiaddrs, ifma_link) { 2695160641Syongari if (ifma->ifma_addr->sa_family != AF_LINK) 2696160641Syongari continue; 2697160641Syongari crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) 2698160641Syongari ifma->ifma_addr), ETHER_ADDR_LEN); 2699160641Syongari 2700160641Syongari /* Just want the 6 least significant bits. */ 2701160641Syongari crc &= 0x3f; 2702160641Syongari 2703160641Syongari /* Set the corresponding bit in the hash table. */ 2704160641Syongari mchash[crc >> 5] |= 1 << (crc & 0x1f); 2705160641Syongari count++; 2706160641Syongari } 2707195049Srwatson if_maddr_runlock(ifp); 2708160641Syongari 2709160641Syongari mode &= ~(RM_ReceiveMulticast | RM_ReceiveAllFrames); 2710160641Syongari if (count > 0) 2711160641Syongari mode |= RM_ReceiveMulticastHash; 2712160641Syongari else 2713160641Syongari mode &= ~RM_ReceiveMulticastHash; 2714160641Syongari 2715160641Syongari CSR_WRITE_4(sc, STGE_HashTable0, mchash[0]); 2716160641Syongari CSR_WRITE_4(sc, STGE_HashTable1, mchash[1]); 2717160641Syongari CSR_WRITE_2(sc, STGE_ReceiveMode, mode); 2718160641Syongari} 2719160641Syongari 2720160641Syongaristatic int 2721160641Syongarisysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high) 2722160641Syongari{ 2723160641Syongari int error, value; 2724160641Syongari 2725160641Syongari if (!arg1) 2726160641Syongari return (EINVAL); 2727160641Syongari value = *(int *)arg1; 2728160641Syongari error = sysctl_handle_int(oidp, &value, 0, req); 2729160641Syongari if (error || !req->newptr) 2730160641Syongari return (error); 2731160641Syongari if (value < low || value > high) 2732160641Syongari return (EINVAL); 2733160641Syongari *(int *)arg1 = value; 2734160641Syongari 2735160641Syongari return (0); 2736160641Syongari} 2737160641Syongari 2738160641Syongaristatic int 2739160641Syongarisysctl_hw_stge_rxint_nframe(SYSCTL_HANDLER_ARGS) 2740160641Syongari{ 2741160641Syongari return (sysctl_int_range(oidp, arg1, arg2, req, 2742160641Syongari STGE_RXINT_NFRAME_MIN, STGE_RXINT_NFRAME_MAX)); 2743160641Syongari} 2744160641Syongari 2745160641Syongaristatic int 2746160641Syongarisysctl_hw_stge_rxint_dmawait(SYSCTL_HANDLER_ARGS) 2747160641Syongari{ 2748160641Syongari return (sysctl_int_range(oidp, arg1, arg2, req, 2749160641Syongari STGE_RXINT_DMAWAIT_MIN, STGE_RXINT_DMAWAIT_MAX)); 2750160641Syongari} 2751