1206625Syongari/*- 2206625Syongari * Copyright (c) 2008-2010 Nikolay Denev <ndenev@gmail.com> 3206625Syongari * Copyright (c) 2007-2008 Alexander Pohoyda <alexander.pohoyda@gmx.net> 4206625Syongari * Copyright (c) 1997, 1998, 1999 5206625Syongari * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 6206625Syongari * 7206625Syongari * Redistribution and use in source and binary forms, with or without 8206625Syongari * modification, are permitted provided that the following conditions 9206625Syongari * are met: 10206625Syongari * 1. Redistributions of source code must retain the above copyright 11206625Syongari * notice, this list of conditions and the following disclaimer. 12206625Syongari * 2. Redistributions in binary form must reproduce the above copyright 13206625Syongari * notice, this list of conditions and the following disclaimer in the 14206625Syongari * documentation and/or other materials provided with the distribution. 15206625Syongari * 3. All advertising materials mentioning features or use of this software 16206625Syongari * must display the following acknowledgement: 17206625Syongari * This product includes software developed by Bill Paul. 18206625Syongari * 4. Neither the name of the author nor the names of any co-contributors 19206625Syongari * may be used to endorse or promote products derived from this software 20206625Syongari * without specific prior written permission. 21206625Syongari * 22206625Syongari * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' 23206625Syongari * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24206625Syongari * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25206625Syongari * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AUTHORS OR 26206625Syongari * THE VOICES IN THEIR HEADS BE LIABLE FOR ANY DIRECT, INDIRECT, 27206625Syongari * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28206625Syongari * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29206625Syongari * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30206625Syongari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31206625Syongari * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32206625Syongari * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 33206625Syongari * OF THE POSSIBILITY OF SUCH DAMAGE. 34206625Syongari */ 35206625Syongari 36206625Syongari#include <sys/cdefs.h> 37206625Syongari__FBSDID("$FreeBSD$"); 38206625Syongari 39206625Syongari/* 40206625Syongari * SiS 190/191 PCI Ethernet NIC driver. 41206625Syongari * 42206625Syongari * Adapted to SiS 190 NIC by Alexander Pohoyda based on the original 43206625Syongari * SiS 900 driver by Bill Paul, using SiS 190/191 Solaris driver by 44206625Syongari * Masayuki Murayama and SiS 190/191 GNU/Linux driver by K.M. Liu 45206625Syongari * <kmliu@sis.com>. Thanks to Pyun YongHyeon <pyunyh@gmail.com> for 46206625Syongari * review and very useful comments. 47206625Syongari * 48206625Syongari * Adapted to SiS 191 NIC by Nikolay Denev with further ideas from the 49206625Syongari * Linux and Solaris drivers. 50206625Syongari */ 51206625Syongari 52206625Syongari#include <sys/param.h> 53206625Syongari#include <sys/systm.h> 54206625Syongari#include <sys/bus.h> 55206625Syongari#include <sys/endian.h> 56206625Syongari#include <sys/kernel.h> 57206625Syongari#include <sys/lock.h> 58206625Syongari#include <sys/malloc.h> 59206625Syongari#include <sys/mbuf.h> 60206625Syongari#include <sys/module.h> 61206625Syongari#include <sys/mutex.h> 62206625Syongari#include <sys/rman.h> 63206625Syongari#include <sys/socket.h> 64206625Syongari#include <sys/sockio.h> 65206625Syongari 66206625Syongari#include <net/bpf.h> 67206625Syongari#include <net/if.h> 68257176Sglebius#include <net/if_var.h> 69206625Syongari#include <net/if_arp.h> 70206625Syongari#include <net/ethernet.h> 71206625Syongari#include <net/if_dl.h> 72206625Syongari#include <net/if_media.h> 73206625Syongari#include <net/if_types.h> 74206625Syongari#include <net/if_vlan_var.h> 75206625Syongari 76207851Syongari#include <netinet/in.h> 77207851Syongari#include <netinet/in_systm.h> 78207851Syongari#include <netinet/ip.h> 79207851Syongari#include <netinet/tcp.h> 80207851Syongari 81206625Syongari#include <machine/bus.h> 82207851Syongari#include <machine/in_cksum.h> 83206625Syongari 84206625Syongari#include <dev/mii/mii.h> 85206625Syongari#include <dev/mii/miivar.h> 86206625Syongari 87206625Syongari#include <dev/pci/pcireg.h> 88206625Syongari#include <dev/pci/pcivar.h> 89206625Syongari 90206672Syongari#include <dev/sge/if_sgereg.h> 91206625Syongari 92206625SyongariMODULE_DEPEND(sge, pci, 1, 1, 1); 93206625SyongariMODULE_DEPEND(sge, ether, 1, 1, 1); 94206625SyongariMODULE_DEPEND(sge, miibus, 1, 1, 1); 95206625Syongari 96206625Syongari/* "device miibus0" required. See GENERIC if you get errors here. */ 97206625Syongari#include "miibus_if.h" 98206625Syongari 99206625Syongari/* 100206625Syongari * Various supported device vendors/types and their names. 101206625Syongari */ 102206625Syongaristatic struct sge_type sge_devs[] = { 103206625Syongari { SIS_VENDORID, SIS_DEVICEID_190, "SiS190 Fast Ethernet" }, 104206625Syongari { SIS_VENDORID, SIS_DEVICEID_191, "SiS191 Fast/Gigabit Ethernet" }, 105206625Syongari { 0, 0, NULL } 106206625Syongari}; 107206625Syongari 108206625Syongaristatic int sge_probe(device_t); 109206625Syongaristatic int sge_attach(device_t); 110206625Syongaristatic int sge_detach(device_t); 111206625Syongaristatic int sge_shutdown(device_t); 112206625Syongaristatic int sge_suspend(device_t); 113206625Syongaristatic int sge_resume(device_t); 114206625Syongari 115206625Syongaristatic int sge_miibus_readreg(device_t, int, int); 116206625Syongaristatic int sge_miibus_writereg(device_t, int, int, int); 117206625Syongaristatic void sge_miibus_statchg(device_t); 118206625Syongari 119206625Syongaristatic int sge_newbuf(struct sge_softc *, int); 120206625Syongaristatic int sge_encap(struct sge_softc *, struct mbuf **); 121206625Syongaristatic __inline void 122206625Syongari sge_discard_rxbuf(struct sge_softc *, int); 123206625Syongaristatic void sge_rxeof(struct sge_softc *); 124206625Syongaristatic void sge_txeof(struct sge_softc *); 125206625Syongaristatic void sge_intr(void *); 126206625Syongaristatic void sge_tick(void *); 127206625Syongaristatic void sge_start(struct ifnet *); 128206625Syongaristatic void sge_start_locked(struct ifnet *); 129206625Syongaristatic int sge_ioctl(struct ifnet *, u_long, caddr_t); 130206625Syongaristatic void sge_init(void *); 131206625Syongaristatic void sge_init_locked(struct sge_softc *); 132206625Syongaristatic void sge_stop(struct sge_softc *); 133206625Syongaristatic void sge_watchdog(struct sge_softc *); 134206625Syongaristatic int sge_ifmedia_upd(struct ifnet *); 135206625Syongaristatic void sge_ifmedia_sts(struct ifnet *, struct ifmediareq *); 136206625Syongari 137206625Syongaristatic int sge_get_mac_addr_apc(struct sge_softc *, uint8_t *); 138206625Syongaristatic int sge_get_mac_addr_eeprom(struct sge_softc *, uint8_t *); 139206625Syongaristatic uint16_t sge_read_eeprom(struct sge_softc *, int); 140206625Syongari 141206625Syongaristatic void sge_rxfilter(struct sge_softc *); 142207380Syongaristatic void sge_setvlan(struct sge_softc *); 143206625Syongaristatic void sge_reset(struct sge_softc *); 144206625Syongaristatic int sge_list_rx_init(struct sge_softc *); 145206625Syongaristatic int sge_list_rx_free(struct sge_softc *); 146206625Syongaristatic int sge_list_tx_init(struct sge_softc *); 147206625Syongaristatic int sge_list_tx_free(struct sge_softc *); 148206625Syongari 149206625Syongaristatic int sge_dma_alloc(struct sge_softc *); 150206625Syongaristatic void sge_dma_free(struct sge_softc *); 151206625Syongaristatic void sge_dma_map_addr(void *, bus_dma_segment_t *, int, int); 152206625Syongari 153206625Syongaristatic device_method_t sge_methods[] = { 154206625Syongari /* Device interface */ 155206625Syongari DEVMETHOD(device_probe, sge_probe), 156206625Syongari DEVMETHOD(device_attach, sge_attach), 157206625Syongari DEVMETHOD(device_detach, sge_detach), 158206625Syongari DEVMETHOD(device_suspend, sge_suspend), 159206625Syongari DEVMETHOD(device_resume, sge_resume), 160206625Syongari DEVMETHOD(device_shutdown, sge_shutdown), 161206625Syongari 162206625Syongari /* MII interface */ 163206625Syongari DEVMETHOD(miibus_readreg, sge_miibus_readreg), 164206625Syongari DEVMETHOD(miibus_writereg, sge_miibus_writereg), 165206625Syongari DEVMETHOD(miibus_statchg, sge_miibus_statchg), 166206625Syongari 167227843Smarius DEVMETHOD_END 168206625Syongari}; 169206625Syongari 170206625Syongaristatic driver_t sge_driver = { 171206625Syongari "sge", sge_methods, sizeof(struct sge_softc) 172206625Syongari}; 173206625Syongari 174206625Syongaristatic devclass_t sge_devclass; 175206625Syongari 176206625SyongariDRIVER_MODULE(sge, pci, sge_driver, sge_devclass, 0, 0); 177206625SyongariDRIVER_MODULE(miibus, sge, miibus_driver, miibus_devclass, 0, 0); 178206625Syongari 179206625Syongari/* 180206625Syongari * Register space access macros. 181206625Syongari */ 182206625Syongari#define CSR_WRITE_4(sc, reg, val) bus_write_4(sc->sge_res, reg, val) 183206625Syongari#define CSR_WRITE_2(sc, reg, val) bus_write_2(sc->sge_res, reg, val) 184206625Syongari#define CSR_WRITE_1(cs, reg, val) bus_write_1(sc->sge_res, reg, val) 185206625Syongari 186206625Syongari#define CSR_READ_4(sc, reg) bus_read_4(sc->sge_res, reg) 187206625Syongari#define CSR_READ_2(sc, reg) bus_read_2(sc->sge_res, reg) 188206625Syongari#define CSR_READ_1(sc, reg) bus_read_1(sc->sge_res, reg) 189206625Syongari 190206625Syongari/* Define to show Tx/Rx error status. */ 191206625Syongari#undef SGE_SHOW_ERRORS 192206625Syongari 193206625Syongari#define SGE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 194206625Syongari 195206625Syongaristatic void 196206625Syongarisge_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 197206625Syongari{ 198206625Syongari bus_addr_t *p; 199206625Syongari 200206625Syongari if (error != 0) 201206625Syongari return; 202206625Syongari KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 203206625Syongari p = arg; 204206625Syongari *p = segs->ds_addr; 205206625Syongari} 206206625Syongari 207206625Syongari/* 208206625Syongari * Read a sequence of words from the EEPROM. 209206625Syongari */ 210206625Syongaristatic uint16_t 211206625Syongarisge_read_eeprom(struct sge_softc *sc, int offset) 212206625Syongari{ 213206625Syongari uint32_t val; 214206625Syongari int i; 215206625Syongari 216206625Syongari KASSERT(offset <= EI_OFFSET, ("EEPROM offset too big")); 217206625Syongari CSR_WRITE_4(sc, ROMInterface, 218206625Syongari EI_REQ | EI_OP_RD | (offset << EI_OFFSET_SHIFT)); 219206625Syongari DELAY(500); 220206625Syongari for (i = 0; i < SGE_TIMEOUT; i++) { 221206625Syongari val = CSR_READ_4(sc, ROMInterface); 222206625Syongari if ((val & EI_REQ) == 0) 223206625Syongari break; 224206625Syongari DELAY(100); 225206625Syongari } 226206625Syongari if (i == SGE_TIMEOUT) { 227206625Syongari device_printf(sc->sge_dev, 228206625Syongari "EEPROM read timeout : 0x%08x\n", val); 229206625Syongari return (0xffff); 230206625Syongari } 231206625Syongari 232206625Syongari return ((val & EI_DATA) >> EI_DATA_SHIFT); 233206625Syongari} 234206625Syongari 235206625Syongaristatic int 236206625Syongarisge_get_mac_addr_eeprom(struct sge_softc *sc, uint8_t *dest) 237206625Syongari{ 238206625Syongari uint16_t val; 239206625Syongari int i; 240206625Syongari 241206625Syongari val = sge_read_eeprom(sc, EEPROMSignature); 242206625Syongari if (val == 0xffff || val == 0) { 243206625Syongari device_printf(sc->sge_dev, 244206625Syongari "invalid EEPROM signature : 0x%04x\n", val); 245206625Syongari return (EINVAL); 246206625Syongari } 247206625Syongari 248206625Syongari for (i = 0; i < ETHER_ADDR_LEN; i += 2) { 249206625Syongari val = sge_read_eeprom(sc, EEPROMMACAddr + i / 2); 250206625Syongari dest[i + 0] = (uint8_t)val; 251206625Syongari dest[i + 1] = (uint8_t)(val >> 8); 252206625Syongari } 253206625Syongari 254206625Syongari if ((sge_read_eeprom(sc, EEPROMInfo) & 0x80) != 0) 255206625Syongari sc->sge_flags |= SGE_FLAG_RGMII; 256206625Syongari return (0); 257206625Syongari} 258206625Syongari 259206625Syongari/* 260206625Syongari * For SiS96x, APC CMOS RAM is used to store ethernet address. 261206625Syongari * APC CMOS RAM is accessed through ISA bridge. 262206625Syongari */ 263206625Syongaristatic int 264206625Syongarisge_get_mac_addr_apc(struct sge_softc *sc, uint8_t *dest) 265206625Syongari{ 266206625Syongari#if defined(__amd64__) || defined(__i386__) 267206625Syongari devclass_t pci; 268206625Syongari device_t bus, dev = NULL; 269206625Syongari device_t *kids; 270206625Syongari struct apc_tbl { 271206625Syongari uint16_t vid; 272206625Syongari uint16_t did; 273206625Syongari } *tp, apc_tbls[] = { 274206625Syongari { SIS_VENDORID, 0x0965 }, 275206625Syongari { SIS_VENDORID, 0x0966 }, 276206625Syongari { SIS_VENDORID, 0x0968 } 277206625Syongari }; 278206625Syongari uint8_t reg; 279298411Spfg int busnum, i, j, numkids; 280206625Syongari 281206625Syongari pci = devclass_find("pci"); 282206625Syongari for (busnum = 0; busnum < devclass_get_maxunit(pci); busnum++) { 283206625Syongari bus = devclass_get_device(pci, busnum); 284206625Syongari if (!bus) 285206625Syongari continue; 286206625Syongari if (device_get_children(bus, &kids, &numkids) != 0) 287206625Syongari continue; 288206625Syongari for (i = 0; i < numkids; i++) { 289206625Syongari dev = kids[i]; 290206625Syongari if (pci_get_class(dev) == PCIC_BRIDGE && 291206625Syongari pci_get_subclass(dev) == PCIS_BRIDGE_ISA) { 292206625Syongari tp = apc_tbls; 293298411Spfg for (j = 0; j < nitems(apc_tbls); j++) { 294206625Syongari if (pci_get_vendor(dev) == tp->vid && 295206625Syongari pci_get_device(dev) == tp->did) { 296206625Syongari free(kids, M_TEMP); 297206625Syongari goto apc_found; 298206625Syongari } 299206625Syongari tp++; 300206625Syongari } 301206625Syongari } 302206625Syongari } 303206625Syongari free(kids, M_TEMP); 304206625Syongari } 305206625Syongari device_printf(sc->sge_dev, "couldn't find PCI-ISA bridge\n"); 306206625Syongari return (EINVAL); 307206625Syongariapc_found: 308206625Syongari /* Enable port 0x78 and 0x79 to access APC registers. */ 309206625Syongari reg = pci_read_config(dev, 0x48, 1); 310206625Syongari pci_write_config(dev, 0x48, reg & ~0x02, 1); 311206625Syongari DELAY(50); 312206625Syongari pci_read_config(dev, 0x48, 1); 313206625Syongari /* Read stored ethernet address. */ 314206625Syongari for (i = 0; i < ETHER_ADDR_LEN; i++) { 315206625Syongari outb(0x78, 0x09 + i); 316206625Syongari dest[i] = inb(0x79); 317206625Syongari } 318206625Syongari outb(0x78, 0x12); 319206625Syongari if ((inb(0x79) & 0x80) != 0) 320206625Syongari sc->sge_flags |= SGE_FLAG_RGMII; 321206625Syongari /* Restore access to APC registers. */ 322206625Syongari pci_write_config(dev, 0x48, reg, 1); 323206625Syongari 324206625Syongari return (0); 325206625Syongari#else 326206625Syongari return (EINVAL); 327206625Syongari#endif 328206625Syongari} 329206625Syongari 330206625Syongaristatic int 331206625Syongarisge_miibus_readreg(device_t dev, int phy, int reg) 332206625Syongari{ 333206625Syongari struct sge_softc *sc; 334206625Syongari uint32_t val; 335206625Syongari int i; 336206625Syongari 337206625Syongari sc = device_get_softc(dev); 338206625Syongari CSR_WRITE_4(sc, GMIIControl, (phy << GMI_PHY_SHIFT) | 339206625Syongari (reg << GMI_REG_SHIFT) | GMI_OP_RD | GMI_REQ); 340206625Syongari DELAY(10); 341206625Syongari for (i = 0; i < SGE_TIMEOUT; i++) { 342206625Syongari val = CSR_READ_4(sc, GMIIControl); 343206625Syongari if ((val & GMI_REQ) == 0) 344206625Syongari break; 345206625Syongari DELAY(10); 346206625Syongari } 347206625Syongari if (i == SGE_TIMEOUT) { 348206625Syongari device_printf(sc->sge_dev, "PHY read timeout : %d\n", reg); 349206625Syongari return (0); 350206625Syongari } 351206625Syongari return ((val & GMI_DATA) >> GMI_DATA_SHIFT); 352206625Syongari} 353206625Syongari 354206625Syongaristatic int 355206625Syongarisge_miibus_writereg(device_t dev, int phy, int reg, int data) 356206625Syongari{ 357206625Syongari struct sge_softc *sc; 358206625Syongari uint32_t val; 359206625Syongari int i; 360206625Syongari 361206625Syongari sc = device_get_softc(dev); 362206625Syongari CSR_WRITE_4(sc, GMIIControl, (phy << GMI_PHY_SHIFT) | 363206625Syongari (reg << GMI_REG_SHIFT) | (data << GMI_DATA_SHIFT) | 364206625Syongari GMI_OP_WR | GMI_REQ); 365206625Syongari DELAY(10); 366206625Syongari for (i = 0; i < SGE_TIMEOUT; i++) { 367206625Syongari val = CSR_READ_4(sc, GMIIControl); 368206625Syongari if ((val & GMI_REQ) == 0) 369206625Syongari break; 370206625Syongari DELAY(10); 371206625Syongari } 372206625Syongari if (i == SGE_TIMEOUT) 373206625Syongari device_printf(sc->sge_dev, "PHY write timeout : %d\n", reg); 374206625Syongari return (0); 375206625Syongari} 376206625Syongari 377206625Syongaristatic void 378206625Syongarisge_miibus_statchg(device_t dev) 379206625Syongari{ 380206625Syongari struct sge_softc *sc; 381206625Syongari struct mii_data *mii; 382206625Syongari struct ifnet *ifp; 383206625Syongari uint32_t ctl, speed; 384206625Syongari 385206625Syongari sc = device_get_softc(dev); 386206625Syongari mii = device_get_softc(sc->sge_miibus); 387206625Syongari ifp = sc->sge_ifp; 388206625Syongari if (mii == NULL || ifp == NULL || 389206625Syongari (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 390206625Syongari return; 391206625Syongari speed = 0; 392206625Syongari sc->sge_flags &= ~SGE_FLAG_LINK; 393206625Syongari if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 394206625Syongari (IFM_ACTIVE | IFM_AVALID)) { 395206625Syongari switch (IFM_SUBTYPE(mii->mii_media_active)) { 396206625Syongari case IFM_10_T: 397206625Syongari sc->sge_flags |= SGE_FLAG_LINK; 398206625Syongari speed = SC_SPEED_10; 399206625Syongari break; 400206625Syongari case IFM_100_TX: 401206625Syongari sc->sge_flags |= SGE_FLAG_LINK; 402206625Syongari speed = SC_SPEED_100; 403206625Syongari break; 404206625Syongari case IFM_1000_T: 405206625Syongari if ((sc->sge_flags & SGE_FLAG_FASTETHER) == 0) { 406206625Syongari sc->sge_flags |= SGE_FLAG_LINK; 407206625Syongari speed = SC_SPEED_1000; 408206625Syongari } 409206625Syongari break; 410206625Syongari default: 411206625Syongari break; 412206625Syongari } 413206625Syongari } 414206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0) 415206625Syongari return; 416206625Syongari /* Reprogram MAC to resolved speed/duplex/flow-control parameters. */ 417206625Syongari ctl = CSR_READ_4(sc, StationControl); 418206625Syongari ctl &= ~(0x0f000000 | SC_FDX | SC_SPEED_MASK); 419206625Syongari if (speed == SC_SPEED_1000) { 420206625Syongari ctl |= 0x07000000; 421206625Syongari sc->sge_flags |= SGE_FLAG_SPEED_1000; 422206625Syongari } else { 423206625Syongari ctl |= 0x04000000; 424206625Syongari sc->sge_flags &= ~SGE_FLAG_SPEED_1000; 425206625Syongari } 426206625Syongari#ifdef notyet 427206625Syongari if ((sc->sge_flags & SGE_FLAG_GMII) != 0) 428206625Syongari ctl |= 0x03000000; 429206625Syongari#endif 430206625Syongari ctl |= speed; 431206625Syongari if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) { 432206625Syongari ctl |= SC_FDX; 433206625Syongari sc->sge_flags |= SGE_FLAG_FDX; 434206625Syongari } else 435206625Syongari sc->sge_flags &= ~SGE_FLAG_FDX; 436206625Syongari CSR_WRITE_4(sc, StationControl, ctl); 437206625Syongari if ((sc->sge_flags & SGE_FLAG_RGMII) != 0) { 438206625Syongari CSR_WRITE_4(sc, RGMIIDelay, 0x0441); 439206625Syongari CSR_WRITE_4(sc, RGMIIDelay, 0x0440); 440206625Syongari } 441206625Syongari} 442206625Syongari 443206625Syongaristatic void 444206625Syongarisge_rxfilter(struct sge_softc *sc) 445206625Syongari{ 446206625Syongari struct ifnet *ifp; 447206625Syongari struct ifmultiaddr *ifma; 448206625Syongari uint32_t crc, hashes[2]; 449206625Syongari uint16_t rxfilt; 450206625Syongari 451206625Syongari SGE_LOCK_ASSERT(sc); 452206625Syongari 453206625Syongari ifp = sc->sge_ifp; 454207375Syongari rxfilt = CSR_READ_2(sc, RxMacControl); 455207375Syongari rxfilt &= ~(AcceptBroadcast | AcceptAllPhys | AcceptMulticast); 456207375Syongari rxfilt |= AcceptMyPhys; 457206625Syongari if ((ifp->if_flags & IFF_BROADCAST) != 0) 458206625Syongari rxfilt |= AcceptBroadcast; 459206625Syongari if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { 460206625Syongari if ((ifp->if_flags & IFF_PROMISC) != 0) 461206625Syongari rxfilt |= AcceptAllPhys; 462206625Syongari rxfilt |= AcceptMulticast; 463206625Syongari hashes[0] = 0xFFFFFFFF; 464206625Syongari hashes[1] = 0xFFFFFFFF; 465207375Syongari } else { 466207375Syongari rxfilt |= AcceptMulticast; 467207375Syongari hashes[0] = hashes[1] = 0; 468207375Syongari /* Now program new ones. */ 469207375Syongari if_maddr_rlock(ifp); 470207375Syongari TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 471207375Syongari if (ifma->ifma_addr->sa_family != AF_LINK) 472207375Syongari continue; 473207375Syongari crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) 474207375Syongari ifma->ifma_addr), ETHER_ADDR_LEN); 475207375Syongari hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); 476207375Syongari } 477207375Syongari if_maddr_runlock(ifp); 478206625Syongari } 479209818Syongari CSR_WRITE_2(sc, RxMacControl, rxfilt); 480206625Syongari CSR_WRITE_4(sc, RxHashTable, hashes[0]); 481206625Syongari CSR_WRITE_4(sc, RxHashTable2, hashes[1]); 482206625Syongari} 483206625Syongari 484206625Syongaristatic void 485207380Syongarisge_setvlan(struct sge_softc *sc) 486207380Syongari{ 487207380Syongari struct ifnet *ifp; 488207380Syongari uint16_t rxfilt; 489207380Syongari 490207380Syongari SGE_LOCK_ASSERT(sc); 491207380Syongari 492207380Syongari ifp = sc->sge_ifp; 493207380Syongari if ((ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0) 494207380Syongari return; 495207380Syongari rxfilt = CSR_READ_2(sc, RxMacControl); 496207380Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 497207380Syongari rxfilt |= RXMAC_STRIP_VLAN; 498207380Syongari else 499207380Syongari rxfilt &= ~RXMAC_STRIP_VLAN; 500207380Syongari CSR_WRITE_2(sc, RxMacControl, rxfilt); 501207380Syongari} 502207380Syongari 503207380Syongaristatic void 504206625Syongarisge_reset(struct sge_softc *sc) 505206625Syongari{ 506206625Syongari 507206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 508206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 509206625Syongari 510206625Syongari /* Soft reset. */ 511206625Syongari CSR_WRITE_4(sc, IntrControl, 0x8000); 512206625Syongari CSR_READ_4(sc, IntrControl); 513206625Syongari DELAY(100); 514206625Syongari CSR_WRITE_4(sc, IntrControl, 0); 515206625Syongari /* Stop MAC. */ 516206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00); 517206625Syongari CSR_WRITE_4(sc, RX_CTL, 0x1a00); 518206625Syongari 519206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 520206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 521206625Syongari 522206625Syongari CSR_WRITE_4(sc, GMIIControl, 0); 523206625Syongari} 524206625Syongari 525206625Syongari/* 526206625Syongari * Probe for an SiS chip. Check the PCI vendor and device 527206625Syongari * IDs against our list and return a device name if we find a match. 528206625Syongari */ 529206625Syongaristatic int 530206625Syongarisge_probe(device_t dev) 531206625Syongari{ 532206625Syongari struct sge_type *t; 533206625Syongari 534206625Syongari t = sge_devs; 535206625Syongari while (t->sge_name != NULL) { 536206625Syongari if ((pci_get_vendor(dev) == t->sge_vid) && 537206625Syongari (pci_get_device(dev) == t->sge_did)) { 538206625Syongari device_set_desc(dev, t->sge_name); 539206625Syongari return (BUS_PROBE_DEFAULT); 540206625Syongari } 541206625Syongari t++; 542206625Syongari } 543206625Syongari 544206625Syongari return (ENXIO); 545206625Syongari} 546206625Syongari 547206625Syongari/* 548206625Syongari * Attach the interface. Allocate softc structures, do ifmedia 549206625Syongari * setup and ethernet/BPF attach. 550206625Syongari */ 551206625Syongaristatic int 552206625Syongarisge_attach(device_t dev) 553206625Syongari{ 554206625Syongari struct sge_softc *sc; 555206625Syongari struct ifnet *ifp; 556206625Syongari uint8_t eaddr[ETHER_ADDR_LEN]; 557206625Syongari int error = 0, rid; 558206625Syongari 559206625Syongari sc = device_get_softc(dev); 560206625Syongari sc->sge_dev = dev; 561206625Syongari 562206625Syongari mtx_init(&sc->sge_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 563206625Syongari MTX_DEF); 564206625Syongari callout_init_mtx(&sc->sge_stat_ch, &sc->sge_mtx, 0); 565206625Syongari 566206625Syongari /* 567206625Syongari * Map control/status registers. 568206625Syongari */ 569206625Syongari pci_enable_busmaster(dev); 570206625Syongari 571206625Syongari /* Allocate resources. */ 572206625Syongari sc->sge_res_id = PCIR_BAR(0); 573206625Syongari sc->sge_res_type = SYS_RES_MEMORY; 574206625Syongari sc->sge_res = bus_alloc_resource_any(dev, sc->sge_res_type, 575206625Syongari &sc->sge_res_id, RF_ACTIVE); 576206625Syongari if (sc->sge_res == NULL) { 577206625Syongari device_printf(dev, "couldn't allocate resource\n"); 578206625Syongari error = ENXIO; 579206625Syongari goto fail; 580206625Syongari } 581206625Syongari 582206625Syongari rid = 0; 583206625Syongari sc->sge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 584206625Syongari RF_SHAREABLE | RF_ACTIVE); 585206625Syongari if (sc->sge_irq == NULL) { 586206625Syongari device_printf(dev, "couldn't allocate IRQ resources\n"); 587206625Syongari error = ENXIO; 588206625Syongari goto fail; 589206625Syongari } 590206625Syongari sc->sge_rev = pci_get_revid(dev); 591206625Syongari if (pci_get_device(dev) == SIS_DEVICEID_190) 592207377Syongari sc->sge_flags |= SGE_FLAG_FASTETHER | SGE_FLAG_SIS190; 593206625Syongari /* Reset the adapter. */ 594206625Syongari sge_reset(sc); 595206625Syongari 596206625Syongari /* Get MAC address from the EEPROM. */ 597206625Syongari if ((pci_read_config(dev, 0x73, 1) & 0x01) != 0) 598206625Syongari sge_get_mac_addr_apc(sc, eaddr); 599206625Syongari else 600206625Syongari sge_get_mac_addr_eeprom(sc, eaddr); 601206625Syongari 602206625Syongari if ((error = sge_dma_alloc(sc)) != 0) 603206625Syongari goto fail; 604206625Syongari 605206625Syongari ifp = sc->sge_ifp = if_alloc(IFT_ETHER); 606206625Syongari if (ifp == NULL) { 607206625Syongari device_printf(dev, "cannot allocate ifnet structure.\n"); 608206625Syongari error = ENOSPC; 609206625Syongari goto fail; 610206625Syongari } 611206625Syongari ifp->if_softc = sc; 612206625Syongari if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 613206625Syongari ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 614206625Syongari ifp->if_ioctl = sge_ioctl; 615206625Syongari ifp->if_start = sge_start; 616206625Syongari ifp->if_init = sge_init; 617206625Syongari ifp->if_snd.ifq_drv_maxlen = SGE_TX_RING_CNT - 1; 618206625Syongari IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 619206625Syongari IFQ_SET_READY(&ifp->if_snd); 620207851Syongari ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_RXCSUM | IFCAP_TSO4; 621207851Syongari ifp->if_hwassist = SGE_CSUM_FEATURES | CSUM_TSO; 622206625Syongari ifp->if_capenable = ifp->if_capabilities; 623206625Syongari /* 624206625Syongari * Do MII setup. 625206625Syongari */ 626213894Smarius error = mii_attach(dev, &sc->sge_miibus, ifp, sge_ifmedia_upd, 627213894Smarius sge_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); 628213894Smarius if (error != 0) { 629213894Smarius device_printf(dev, "attaching PHYs failed\n"); 630206625Syongari goto fail; 631206625Syongari } 632206625Syongari 633206625Syongari /* 634206625Syongari * Call MI attach routine. 635206625Syongari */ 636206625Syongari ether_ifattach(ifp, eaddr); 637206625Syongari 638206625Syongari /* VLAN setup. */ 639207852Syongari ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM | 640207852Syongari IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU; 641206625Syongari ifp->if_capenable = ifp->if_capabilities; 642206625Syongari /* Tell the upper layer(s) we support long frames. */ 643270856Sglebius ifp->if_hdrlen = sizeof(struct ether_vlan_header); 644206625Syongari 645206625Syongari /* Hook interrupt last to avoid having to lock softc */ 646206625Syongari error = bus_setup_intr(dev, sc->sge_irq, INTR_TYPE_NET | INTR_MPSAFE, 647206625Syongari NULL, sge_intr, sc, &sc->sge_intrhand); 648206625Syongari if (error) { 649206625Syongari device_printf(dev, "couldn't set up irq\n"); 650206625Syongari ether_ifdetach(ifp); 651206625Syongari goto fail; 652206625Syongari } 653206625Syongari 654206625Syongarifail: 655206625Syongari if (error) 656206625Syongari sge_detach(dev); 657206625Syongari 658206625Syongari return (error); 659206625Syongari} 660206625Syongari 661206625Syongari/* 662206625Syongari * Shutdown hardware and free up resources. This can be called any 663206625Syongari * time after the mutex has been initialized. It is called in both 664206625Syongari * the error case in attach and the normal detach case so it needs 665206625Syongari * to be careful about only freeing resources that have actually been 666206625Syongari * allocated. 667206625Syongari */ 668206625Syongaristatic int 669206625Syongarisge_detach(device_t dev) 670206625Syongari{ 671206625Syongari struct sge_softc *sc; 672206625Syongari struct ifnet *ifp; 673206625Syongari 674206625Syongari sc = device_get_softc(dev); 675206625Syongari ifp = sc->sge_ifp; 676206625Syongari /* These should only be active if attach succeeded. */ 677206625Syongari if (device_is_attached(dev)) { 678206625Syongari ether_ifdetach(ifp); 679206625Syongari SGE_LOCK(sc); 680206625Syongari sge_stop(sc); 681206625Syongari SGE_UNLOCK(sc); 682206625Syongari callout_drain(&sc->sge_stat_ch); 683206625Syongari } 684206625Syongari if (sc->sge_miibus) 685206625Syongari device_delete_child(dev, sc->sge_miibus); 686206625Syongari bus_generic_detach(dev); 687206625Syongari 688206625Syongari if (sc->sge_intrhand) 689206625Syongari bus_teardown_intr(dev, sc->sge_irq, sc->sge_intrhand); 690206625Syongari if (sc->sge_irq) 691206625Syongari bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sge_irq); 692206625Syongari if (sc->sge_res) 693206625Syongari bus_release_resource(dev, sc->sge_res_type, sc->sge_res_id, 694206625Syongari sc->sge_res); 695206625Syongari if (ifp) 696206625Syongari if_free(ifp); 697206625Syongari sge_dma_free(sc); 698206625Syongari mtx_destroy(&sc->sge_mtx); 699206625Syongari 700206625Syongari return (0); 701206625Syongari} 702206625Syongari 703206625Syongari/* 704206625Syongari * Stop all chip I/O so that the kernel's probe routines don't 705206625Syongari * get confused by errant DMAs when rebooting. 706206625Syongari */ 707206625Syongaristatic int 708206625Syongarisge_shutdown(device_t dev) 709206625Syongari{ 710206625Syongari struct sge_softc *sc; 711206625Syongari 712206625Syongari sc = device_get_softc(dev); 713206625Syongari SGE_LOCK(sc); 714206625Syongari sge_stop(sc); 715206625Syongari SGE_UNLOCK(sc); 716206625Syongari return (0); 717206625Syongari} 718206625Syongari 719206625Syongaristatic int 720206625Syongarisge_suspend(device_t dev) 721206625Syongari{ 722206625Syongari struct sge_softc *sc; 723206625Syongari struct ifnet *ifp; 724206625Syongari 725206625Syongari sc = device_get_softc(dev); 726206625Syongari SGE_LOCK(sc); 727206625Syongari ifp = sc->sge_ifp; 728206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 729206625Syongari sge_stop(sc); 730206625Syongari SGE_UNLOCK(sc); 731206625Syongari return (0); 732206625Syongari} 733206625Syongari 734206625Syongaristatic int 735206625Syongarisge_resume(device_t dev) 736206625Syongari{ 737206625Syongari struct sge_softc *sc; 738206625Syongari struct ifnet *ifp; 739206625Syongari 740206625Syongari sc = device_get_softc(dev); 741206625Syongari SGE_LOCK(sc); 742206625Syongari ifp = sc->sge_ifp; 743206625Syongari if ((ifp->if_flags & IFF_UP) != 0) 744206625Syongari sge_init_locked(sc); 745206625Syongari SGE_UNLOCK(sc); 746206625Syongari return (0); 747206625Syongari} 748206625Syongari 749206625Syongaristatic int 750206625Syongarisge_dma_alloc(struct sge_softc *sc) 751206625Syongari{ 752206625Syongari struct sge_chain_data *cd; 753206625Syongari struct sge_list_data *ld; 754207628Syongari struct sge_rxdesc *rxd; 755207628Syongari struct sge_txdesc *txd; 756206625Syongari int error, i; 757206625Syongari 758206625Syongari cd = &sc->sge_cdata; 759206625Syongari ld = &sc->sge_ldata; 760206625Syongari error = bus_dma_tag_create(bus_get_dma_tag(sc->sge_dev), 761206625Syongari 1, 0, /* alignment, boundary */ 762206625Syongari BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 763206625Syongari BUS_SPACE_MAXADDR, /* highaddr */ 764206625Syongari NULL, NULL, /* filter, filterarg */ 765206625Syongari BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 766206625Syongari 1, /* nsegments */ 767206625Syongari BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 768206625Syongari 0, /* flags */ 769206625Syongari NULL, /* lockfunc */ 770206625Syongari NULL, /* lockarg */ 771206625Syongari &cd->sge_tag); 772206625Syongari if (error != 0) { 773206625Syongari device_printf(sc->sge_dev, 774206625Syongari "could not create parent DMA tag.\n"); 775206625Syongari goto fail; 776206625Syongari } 777206625Syongari 778206625Syongari /* RX descriptor ring */ 779206625Syongari error = bus_dma_tag_create(cd->sge_tag, 780206625Syongari SGE_DESC_ALIGN, 0, /* alignment, boundary */ 781206625Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 782206625Syongari BUS_SPACE_MAXADDR, /* highaddr */ 783206625Syongari NULL, NULL, /* filter, filterarg */ 784206625Syongari SGE_RX_RING_SZ, 1, /* maxsize,nsegments */ 785206625Syongari SGE_RX_RING_SZ, /* maxsegsize */ 786206625Syongari 0, /* flags */ 787206625Syongari NULL, /* lockfunc */ 788206625Syongari NULL, /* lockarg */ 789206625Syongari &cd->sge_rx_tag); 790206625Syongari if (error != 0) { 791206625Syongari device_printf(sc->sge_dev, 792206625Syongari "could not create Rx ring DMA tag.\n"); 793206625Syongari goto fail; 794206625Syongari } 795206625Syongari /* Allocate DMA'able memory and load DMA map for RX ring. */ 796206625Syongari error = bus_dmamem_alloc(cd->sge_rx_tag, (void **)&ld->sge_rx_ring, 797206625Syongari BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, 798206625Syongari &cd->sge_rx_dmamap); 799206625Syongari if (error != 0) { 800206625Syongari device_printf(sc->sge_dev, 801206625Syongari "could not allocate DMA'able memory for Rx ring.\n"); 802206625Syongari goto fail; 803206625Syongari } 804206625Syongari error = bus_dmamap_load(cd->sge_rx_tag, cd->sge_rx_dmamap, 805206625Syongari ld->sge_rx_ring, SGE_RX_RING_SZ, sge_dma_map_addr, 806206625Syongari &ld->sge_rx_paddr, BUS_DMA_NOWAIT); 807206625Syongari if (error != 0) { 808206625Syongari device_printf(sc->sge_dev, 809206625Syongari "could not load DMA'able memory for Rx ring.\n"); 810206625Syongari } 811206625Syongari 812206625Syongari /* TX descriptor ring */ 813206625Syongari error = bus_dma_tag_create(cd->sge_tag, 814206625Syongari SGE_DESC_ALIGN, 0, /* alignment, boundary */ 815206625Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 816206625Syongari BUS_SPACE_MAXADDR, /* highaddr */ 817206625Syongari NULL, NULL, /* filter, filterarg */ 818206625Syongari SGE_TX_RING_SZ, 1, /* maxsize,nsegments */ 819206625Syongari SGE_TX_RING_SZ, /* maxsegsize */ 820206625Syongari 0, /* flags */ 821206625Syongari NULL, /* lockfunc */ 822206625Syongari NULL, /* lockarg */ 823206625Syongari &cd->sge_tx_tag); 824206625Syongari if (error != 0) { 825206625Syongari device_printf(sc->sge_dev, 826206625Syongari "could not create Rx ring DMA tag.\n"); 827206625Syongari goto fail; 828206625Syongari } 829206625Syongari /* Allocate DMA'able memory and load DMA map for TX ring. */ 830206625Syongari error = bus_dmamem_alloc(cd->sge_tx_tag, (void **)&ld->sge_tx_ring, 831206625Syongari BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, 832206625Syongari &cd->sge_tx_dmamap); 833206625Syongari if (error != 0) { 834206625Syongari device_printf(sc->sge_dev, 835206625Syongari "could not allocate DMA'able memory for Tx ring.\n"); 836206625Syongari goto fail; 837206625Syongari } 838206625Syongari error = bus_dmamap_load(cd->sge_tx_tag, cd->sge_tx_dmamap, 839206625Syongari ld->sge_tx_ring, SGE_TX_RING_SZ, sge_dma_map_addr, 840206625Syongari &ld->sge_tx_paddr, BUS_DMA_NOWAIT); 841206625Syongari if (error != 0) { 842206625Syongari device_printf(sc->sge_dev, 843206625Syongari "could not load DMA'able memory for Rx ring.\n"); 844206625Syongari goto fail; 845206625Syongari } 846206625Syongari 847206625Syongari /* Create DMA tag for Tx buffers. */ 848206625Syongari error = bus_dma_tag_create(cd->sge_tag, 1, 0, BUS_SPACE_MAXADDR, 849207851Syongari BUS_SPACE_MAXADDR, NULL, NULL, SGE_TSO_MAXSIZE, SGE_MAXTXSEGS, 850207851Syongari SGE_TSO_MAXSEGSIZE, 0, NULL, NULL, &cd->sge_txmbuf_tag); 851206625Syongari if (error != 0) { 852206625Syongari device_printf(sc->sge_dev, 853206625Syongari "could not create Tx mbuf DMA tag.\n"); 854206625Syongari goto fail; 855206625Syongari } 856206625Syongari 857206625Syongari /* Create DMA tag for Rx buffers. */ 858206625Syongari error = bus_dma_tag_create(cd->sge_tag, SGE_RX_BUF_ALIGN, 0, 859206625Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, 860206625Syongari MCLBYTES, 0, NULL, NULL, &cd->sge_rxmbuf_tag); 861206625Syongari if (error != 0) { 862206625Syongari device_printf(sc->sge_dev, 863206625Syongari "could not create Rx mbuf DMA tag.\n"); 864206625Syongari goto fail; 865206625Syongari } 866206625Syongari 867206625Syongari /* Create DMA maps for Tx buffers. */ 868206625Syongari for (i = 0; i < SGE_TX_RING_CNT; i++) { 869207628Syongari txd = &cd->sge_txdesc[i]; 870207628Syongari txd->tx_m = NULL; 871207628Syongari txd->tx_dmamap = NULL; 872207628Syongari txd->tx_ndesc = 0; 873206625Syongari error = bus_dmamap_create(cd->sge_txmbuf_tag, 0, 874207628Syongari &txd->tx_dmamap); 875206625Syongari if (error != 0) { 876206625Syongari device_printf(sc->sge_dev, 877206625Syongari "could not create Tx DMA map.\n"); 878206625Syongari goto fail; 879206625Syongari } 880206625Syongari } 881206625Syongari /* Create spare DMA map for Rx buffer. */ 882206625Syongari error = bus_dmamap_create(cd->sge_rxmbuf_tag, 0, &cd->sge_rx_spare_map); 883206625Syongari if (error != 0) { 884206625Syongari device_printf(sc->sge_dev, 885206625Syongari "could not create spare Rx DMA map.\n"); 886206625Syongari goto fail; 887206625Syongari } 888206625Syongari /* Create DMA maps for Rx buffers. */ 889206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 890207628Syongari rxd = &cd->sge_rxdesc[i]; 891207628Syongari rxd->rx_m = NULL; 892207628Syongari rxd->rx_dmamap = NULL; 893206625Syongari error = bus_dmamap_create(cd->sge_rxmbuf_tag, 0, 894207628Syongari &rxd->rx_dmamap); 895206625Syongari if (error) { 896206625Syongari device_printf(sc->sge_dev, 897206625Syongari "could not create Rx DMA map.\n"); 898206625Syongari goto fail; 899206625Syongari } 900206625Syongari } 901206625Syongarifail: 902206625Syongari return (error); 903206625Syongari} 904206625Syongari 905206625Syongaristatic void 906206625Syongarisge_dma_free(struct sge_softc *sc) 907206625Syongari{ 908206625Syongari struct sge_chain_data *cd; 909206625Syongari struct sge_list_data *ld; 910207628Syongari struct sge_rxdesc *rxd; 911207628Syongari struct sge_txdesc *txd; 912206625Syongari int i; 913206625Syongari 914206625Syongari cd = &sc->sge_cdata; 915206625Syongari ld = &sc->sge_ldata; 916206625Syongari /* Rx ring. */ 917206625Syongari if (cd->sge_rx_tag != NULL) { 918267363Sjhb if (ld->sge_rx_paddr != 0) 919206625Syongari bus_dmamap_unload(cd->sge_rx_tag, cd->sge_rx_dmamap); 920267363Sjhb if (ld->sge_rx_ring != NULL) 921206625Syongari bus_dmamem_free(cd->sge_rx_tag, ld->sge_rx_ring, 922206625Syongari cd->sge_rx_dmamap); 923206625Syongari ld->sge_rx_ring = NULL; 924267363Sjhb ld->sge_rx_paddr = 0; 925206625Syongari bus_dma_tag_destroy(cd->sge_rx_tag); 926206625Syongari cd->sge_rx_tag = NULL; 927206625Syongari } 928206625Syongari /* Tx ring. */ 929206625Syongari if (cd->sge_tx_tag != NULL) { 930267363Sjhb if (ld->sge_tx_paddr != 0) 931206625Syongari bus_dmamap_unload(cd->sge_tx_tag, cd->sge_tx_dmamap); 932267363Sjhb if (ld->sge_tx_ring != NULL) 933206625Syongari bus_dmamem_free(cd->sge_tx_tag, ld->sge_tx_ring, 934206625Syongari cd->sge_tx_dmamap); 935206625Syongari ld->sge_tx_ring = NULL; 936267363Sjhb ld->sge_tx_paddr = 0; 937206625Syongari bus_dma_tag_destroy(cd->sge_tx_tag); 938206625Syongari cd->sge_tx_tag = NULL; 939206625Syongari } 940206625Syongari /* Rx buffers. */ 941206625Syongari if (cd->sge_rxmbuf_tag != NULL) { 942206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 943207628Syongari rxd = &cd->sge_rxdesc[i]; 944207628Syongari if (rxd->rx_dmamap != NULL) { 945206625Syongari bus_dmamap_destroy(cd->sge_rxmbuf_tag, 946207628Syongari rxd->rx_dmamap); 947207628Syongari rxd->rx_dmamap = NULL; 948206625Syongari } 949206625Syongari } 950206625Syongari if (cd->sge_rx_spare_map != NULL) { 951206625Syongari bus_dmamap_destroy(cd->sge_rxmbuf_tag, 952206625Syongari cd->sge_rx_spare_map); 953206625Syongari cd->sge_rx_spare_map = NULL; 954206625Syongari } 955206625Syongari bus_dma_tag_destroy(cd->sge_rxmbuf_tag); 956206625Syongari cd->sge_rxmbuf_tag = NULL; 957206625Syongari } 958206625Syongari /* Tx buffers. */ 959206625Syongari if (cd->sge_txmbuf_tag != NULL) { 960206625Syongari for (i = 0; i < SGE_TX_RING_CNT; i++) { 961207628Syongari txd = &cd->sge_txdesc[i]; 962207628Syongari if (txd->tx_dmamap != NULL) { 963206625Syongari bus_dmamap_destroy(cd->sge_txmbuf_tag, 964207628Syongari txd->tx_dmamap); 965207628Syongari txd->tx_dmamap = NULL; 966206625Syongari } 967206625Syongari } 968206625Syongari bus_dma_tag_destroy(cd->sge_txmbuf_tag); 969206625Syongari cd->sge_txmbuf_tag = NULL; 970206625Syongari } 971206625Syongari if (cd->sge_tag != NULL) 972206625Syongari bus_dma_tag_destroy(cd->sge_tag); 973206625Syongari cd->sge_tag = NULL; 974206625Syongari} 975206625Syongari 976206625Syongari/* 977206625Syongari * Initialize the TX descriptors. 978206625Syongari */ 979206625Syongaristatic int 980206625Syongarisge_list_tx_init(struct sge_softc *sc) 981206625Syongari{ 982206625Syongari struct sge_list_data *ld; 983206625Syongari struct sge_chain_data *cd; 984206625Syongari 985206625Syongari SGE_LOCK_ASSERT(sc); 986206625Syongari ld = &sc->sge_ldata; 987206625Syongari cd = &sc->sge_cdata; 988206625Syongari bzero(ld->sge_tx_ring, SGE_TX_RING_SZ); 989206625Syongari ld->sge_tx_ring[SGE_TX_RING_CNT - 1].sge_flags = htole32(RING_END); 990206625Syongari bus_dmamap_sync(cd->sge_tx_tag, cd->sge_tx_dmamap, 991206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 992206625Syongari cd->sge_tx_prod = 0; 993206625Syongari cd->sge_tx_cons = 0; 994206625Syongari cd->sge_tx_cnt = 0; 995206625Syongari return (0); 996206625Syongari} 997206625Syongari 998206625Syongaristatic int 999206625Syongarisge_list_tx_free(struct sge_softc *sc) 1000206625Syongari{ 1001206625Syongari struct sge_chain_data *cd; 1002207628Syongari struct sge_txdesc *txd; 1003206625Syongari int i; 1004206625Syongari 1005206625Syongari SGE_LOCK_ASSERT(sc); 1006206625Syongari cd = &sc->sge_cdata; 1007206625Syongari for (i = 0; i < SGE_TX_RING_CNT; i++) { 1008207628Syongari txd = &cd->sge_txdesc[i]; 1009207628Syongari if (txd->tx_m != NULL) { 1010207628Syongari bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap, 1011207628Syongari BUS_DMASYNC_POSTWRITE); 1012207628Syongari bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap); 1013207635Syongari m_freem(txd->tx_m); 1014207628Syongari txd->tx_m = NULL; 1015207628Syongari txd->tx_ndesc = 0; 1016206625Syongari } 1017206625Syongari } 1018206625Syongari 1019206625Syongari return (0); 1020206625Syongari} 1021206625Syongari 1022206625Syongari/* 1023206625Syongari * Initialize the RX descriptors and allocate mbufs for them. Note that 1024206625Syongari * we arrange the descriptors in a closed ring, so that the last descriptor 1025206625Syongari * has RING_END flag set. 1026206625Syongari */ 1027206625Syongaristatic int 1028206625Syongarisge_list_rx_init(struct sge_softc *sc) 1029206625Syongari{ 1030206625Syongari struct sge_chain_data *cd; 1031206625Syongari int i; 1032206625Syongari 1033206625Syongari SGE_LOCK_ASSERT(sc); 1034206625Syongari cd = &sc->sge_cdata; 1035206625Syongari cd->sge_rx_cons = 0; 1036206625Syongari bzero(sc->sge_ldata.sge_rx_ring, SGE_RX_RING_SZ); 1037206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 1038206625Syongari if (sge_newbuf(sc, i) != 0) 1039206625Syongari return (ENOBUFS); 1040206625Syongari } 1041206625Syongari bus_dmamap_sync(cd->sge_rx_tag, cd->sge_rx_dmamap, 1042206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1043206625Syongari return (0); 1044206625Syongari} 1045206625Syongari 1046206625Syongaristatic int 1047206625Syongarisge_list_rx_free(struct sge_softc *sc) 1048206625Syongari{ 1049206625Syongari struct sge_chain_data *cd; 1050207628Syongari struct sge_rxdesc *rxd; 1051206625Syongari int i; 1052206625Syongari 1053206625Syongari SGE_LOCK_ASSERT(sc); 1054206625Syongari cd = &sc->sge_cdata; 1055206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 1056207628Syongari rxd = &cd->sge_rxdesc[i]; 1057207628Syongari if (rxd->rx_m != NULL) { 1058207628Syongari bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, 1059206625Syongari BUS_DMASYNC_POSTREAD); 1060206625Syongari bus_dmamap_unload(cd->sge_rxmbuf_tag, 1061207628Syongari rxd->rx_dmamap); 1062207635Syongari m_freem(rxd->rx_m); 1063207628Syongari rxd->rx_m = NULL; 1064206625Syongari } 1065206625Syongari } 1066206625Syongari return (0); 1067206625Syongari} 1068206625Syongari 1069206625Syongari/* 1070206625Syongari * Initialize an RX descriptor and attach an MBUF cluster. 1071206625Syongari */ 1072206625Syongaristatic int 1073206625Syongarisge_newbuf(struct sge_softc *sc, int prod) 1074206625Syongari{ 1075206625Syongari struct mbuf *m; 1076206625Syongari struct sge_desc *desc; 1077206625Syongari struct sge_chain_data *cd; 1078207628Syongari struct sge_rxdesc *rxd; 1079206625Syongari bus_dma_segment_t segs[1]; 1080206625Syongari bus_dmamap_t map; 1081206625Syongari int error, nsegs; 1082206625Syongari 1083206625Syongari SGE_LOCK_ASSERT(sc); 1084206625Syongari 1085206625Syongari cd = &sc->sge_cdata; 1086243857Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 1087206625Syongari if (m == NULL) 1088206625Syongari return (ENOBUFS); 1089206625Syongari m->m_len = m->m_pkthdr.len = MCLBYTES; 1090206625Syongari m_adj(m, SGE_RX_BUF_ALIGN); 1091206625Syongari error = bus_dmamap_load_mbuf_sg(cd->sge_rxmbuf_tag, 1092206625Syongari cd->sge_rx_spare_map, m, segs, &nsegs, 0); 1093206625Syongari if (error != 0) { 1094206625Syongari m_freem(m); 1095206625Syongari return (error); 1096206625Syongari } 1097206625Syongari KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 1098207628Syongari rxd = &cd->sge_rxdesc[prod]; 1099207628Syongari if (rxd->rx_m != NULL) { 1100207628Syongari bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, 1101206625Syongari BUS_DMASYNC_POSTREAD); 1102207628Syongari bus_dmamap_unload(cd->sge_rxmbuf_tag, rxd->rx_dmamap); 1103206625Syongari } 1104207628Syongari map = rxd->rx_dmamap; 1105207628Syongari rxd->rx_dmamap = cd->sge_rx_spare_map; 1106206625Syongari cd->sge_rx_spare_map = map; 1107207628Syongari bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, 1108206625Syongari BUS_DMASYNC_PREREAD); 1109207628Syongari rxd->rx_m = m; 1110206625Syongari 1111206625Syongari desc = &sc->sge_ldata.sge_rx_ring[prod]; 1112206625Syongari desc->sge_sts_size = 0; 1113206625Syongari desc->sge_ptr = htole32(SGE_ADDR_LO(segs[0].ds_addr)); 1114206625Syongari desc->sge_flags = htole32(segs[0].ds_len); 1115206625Syongari if (prod == SGE_RX_RING_CNT - 1) 1116206625Syongari desc->sge_flags |= htole32(RING_END); 1117209818Syongari desc->sge_cmdsts = htole32(RDC_OWN | RDC_INTR); 1118206625Syongari return (0); 1119206625Syongari} 1120206625Syongari 1121206625Syongaristatic __inline void 1122206625Syongarisge_discard_rxbuf(struct sge_softc *sc, int index) 1123206625Syongari{ 1124206625Syongari struct sge_desc *desc; 1125206625Syongari 1126206625Syongari desc = &sc->sge_ldata.sge_rx_ring[index]; 1127206625Syongari desc->sge_sts_size = 0; 1128206625Syongari desc->sge_flags = htole32(MCLBYTES - SGE_RX_BUF_ALIGN); 1129206625Syongari if (index == SGE_RX_RING_CNT - 1) 1130206625Syongari desc->sge_flags |= htole32(RING_END); 1131209818Syongari desc->sge_cmdsts = htole32(RDC_OWN | RDC_INTR); 1132206625Syongari} 1133206625Syongari 1134206625Syongari/* 1135206625Syongari * A frame has been uploaded: pass the resulting mbuf chain up to 1136206625Syongari * the higher level protocols. 1137206625Syongari */ 1138206625Syongaristatic void 1139206625Syongarisge_rxeof(struct sge_softc *sc) 1140206625Syongari{ 1141206625Syongari struct ifnet *ifp; 1142206625Syongari struct mbuf *m; 1143206625Syongari struct sge_chain_data *cd; 1144206625Syongari struct sge_desc *cur_rx; 1145206625Syongari uint32_t rxinfo, rxstat; 1146206625Syongari int cons, prog; 1147206625Syongari 1148206625Syongari SGE_LOCK_ASSERT(sc); 1149206625Syongari 1150206625Syongari ifp = sc->sge_ifp; 1151206625Syongari cd = &sc->sge_cdata; 1152206625Syongari 1153206625Syongari bus_dmamap_sync(cd->sge_rx_tag, cd->sge_rx_dmamap, 1154206625Syongari BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1155206625Syongari cons = cd->sge_rx_cons; 1156206625Syongari for (prog = 0; prog < SGE_RX_RING_CNT; prog++, 1157206625Syongari SGE_INC(cons, SGE_RX_RING_CNT)) { 1158206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1159206625Syongari break; 1160206625Syongari cur_rx = &sc->sge_ldata.sge_rx_ring[cons]; 1161206625Syongari rxinfo = le32toh(cur_rx->sge_cmdsts); 1162206625Syongari if ((rxinfo & RDC_OWN) != 0) 1163206625Syongari break; 1164206625Syongari rxstat = le32toh(cur_rx->sge_sts_size); 1165207379Syongari if ((rxstat & RDS_CRCOK) == 0 || SGE_RX_ERROR(rxstat) != 0 || 1166207379Syongari SGE_RX_NSEGS(rxstat) != 1) { 1167206625Syongari /* XXX We don't support multi-segment frames yet. */ 1168206625Syongari#ifdef SGE_SHOW_ERRORS 1169206625Syongari device_printf(sc->sge_dev, "Rx error : 0x%b\n", rxstat, 1170206625Syongari RX_ERR_BITS); 1171206625Syongari#endif 1172206625Syongari sge_discard_rxbuf(sc, cons); 1173271849Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 1174206625Syongari continue; 1175206625Syongari } 1176207628Syongari m = cd->sge_rxdesc[cons].rx_m; 1177206625Syongari if (sge_newbuf(sc, cons) != 0) { 1178206625Syongari sge_discard_rxbuf(sc, cons); 1179271849Sglebius if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 1180206625Syongari continue; 1181206625Syongari } 1182206625Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) { 1183206625Syongari if ((rxinfo & RDC_IP_CSUM) != 0 && 1184206625Syongari (rxinfo & RDC_IP_CSUM_OK) != 0) 1185206625Syongari m->m_pkthdr.csum_flags |= 1186206625Syongari CSUM_IP_CHECKED | CSUM_IP_VALID; 1187206625Syongari if (((rxinfo & RDC_TCP_CSUM) != 0 && 1188206625Syongari (rxinfo & RDC_TCP_CSUM_OK) != 0) || 1189206625Syongari ((rxinfo & RDC_UDP_CSUM) != 0 && 1190206625Syongari (rxinfo & RDC_UDP_CSUM_OK) != 0)) { 1191206625Syongari m->m_pkthdr.csum_flags |= 1192206625Syongari CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 1193206625Syongari m->m_pkthdr.csum_data = 0xffff; 1194206625Syongari } 1195206625Syongari } 1196207380Syongari /* Check for VLAN tagged frame. */ 1197207380Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && 1198207380Syongari (rxstat & RDS_VLAN) != 0) { 1199207380Syongari m->m_pkthdr.ether_vtag = rxinfo & RDC_VLAN_MASK; 1200207380Syongari m->m_flags |= M_VLANTAG; 1201207380Syongari } 1202207852Syongari /* 1203207852Syongari * Account for 10bytes auto padding which is used 1204207852Syongari * to align IP header on 32bit boundary. Also note, 1205207852Syongari * CRC bytes is automatically removed by the 1206207852Syongari * hardware. 1207207852Syongari */ 1208207852Syongari m->m_data += SGE_RX_PAD_BYTES; 1209207852Syongari m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) - 1210207852Syongari SGE_RX_PAD_BYTES; 1211206625Syongari m->m_pkthdr.rcvif = ifp; 1212271849Sglebius if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 1213206625Syongari SGE_UNLOCK(sc); 1214206625Syongari (*ifp->if_input)(ifp, m); 1215206625Syongari SGE_LOCK(sc); 1216206625Syongari } 1217206625Syongari 1218206625Syongari if (prog > 0) { 1219206625Syongari bus_dmamap_sync(cd->sge_rx_tag, cd->sge_rx_dmamap, 1220206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1221206625Syongari cd->sge_rx_cons = cons; 1222206625Syongari } 1223206625Syongari} 1224206625Syongari 1225206625Syongari/* 1226206625Syongari * A frame was downloaded to the chip. It's safe for us to clean up 1227206625Syongari * the list buffers. 1228206625Syongari */ 1229206625Syongaristatic void 1230206625Syongarisge_txeof(struct sge_softc *sc) 1231206625Syongari{ 1232206625Syongari struct ifnet *ifp; 1233206625Syongari struct sge_list_data *ld; 1234206625Syongari struct sge_chain_data *cd; 1235207628Syongari struct sge_txdesc *txd; 1236206625Syongari uint32_t txstat; 1237207628Syongari int cons, nsegs, prod; 1238206625Syongari 1239206625Syongari SGE_LOCK_ASSERT(sc); 1240206625Syongari 1241206625Syongari ifp = sc->sge_ifp; 1242206625Syongari ld = &sc->sge_ldata; 1243206625Syongari cd = &sc->sge_cdata; 1244206625Syongari 1245206625Syongari if (cd->sge_tx_cnt == 0) 1246206625Syongari return; 1247206625Syongari bus_dmamap_sync(cd->sge_tx_tag, cd->sge_tx_dmamap, 1248206625Syongari BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1249206625Syongari cons = cd->sge_tx_cons; 1250206625Syongari prod = cd->sge_tx_prod; 1251207628Syongari for (; cons != prod;) { 1252206625Syongari txstat = le32toh(ld->sge_tx_ring[cons].sge_cmdsts); 1253206625Syongari if ((txstat & TDC_OWN) != 0) 1254206625Syongari break; 1255207628Syongari /* 1256207628Syongari * Only the first descriptor of multi-descriptor transmission 1257207628Syongari * is updated by controller. Driver should skip entire 1258207628Syongari * chained buffers for the transmitted frame. In other words 1259207628Syongari * TDC_OWN bit is valid only at the first descriptor of a 1260207628Syongari * multi-descriptor transmission. 1261207628Syongari */ 1262207628Syongari if (SGE_TX_ERROR(txstat) != 0) { 1263206625Syongari#ifdef SGE_SHOW_ERRORS 1264207628Syongari device_printf(sc->sge_dev, "Tx error : 0x%b\n", 1265207628Syongari txstat, TX_ERR_BITS); 1266206625Syongari#endif 1267271849Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1268207628Syongari } else { 1269206625Syongari#ifdef notyet 1270271849Sglebius if_inc_counter(ifp, IFCOUNTER_COLLISIONS, (txstat & 0xFFFF) - 1); 1271206625Syongari#endif 1272271849Sglebius if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 1273206625Syongari } 1274207628Syongari txd = &cd->sge_txdesc[cons]; 1275207628Syongari for (nsegs = 0; nsegs < txd->tx_ndesc; nsegs++) { 1276207628Syongari ld->sge_tx_ring[cons].sge_cmdsts = 0; 1277207628Syongari SGE_INC(cons, SGE_TX_RING_CNT); 1278207628Syongari } 1279207628Syongari /* Reclaim transmitted mbuf. */ 1280207628Syongari KASSERT(txd->tx_m != NULL, 1281207628Syongari ("%s: freeing NULL mbuf\n", __func__)); 1282207628Syongari bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap, 1283207628Syongari BUS_DMASYNC_POSTWRITE); 1284207628Syongari bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap); 1285207628Syongari m_freem(txd->tx_m); 1286207628Syongari txd->tx_m = NULL; 1287207628Syongari cd->sge_tx_cnt -= txd->tx_ndesc; 1288207628Syongari KASSERT(cd->sge_tx_cnt >= 0, 1289207628Syongari ("%s: Active Tx desc counter was garbled\n", __func__)); 1290207628Syongari txd->tx_ndesc = 0; 1291207628Syongari ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1292206625Syongari } 1293206625Syongari cd->sge_tx_cons = cons; 1294206625Syongari if (cd->sge_tx_cnt == 0) 1295206625Syongari sc->sge_timer = 0; 1296206625Syongari} 1297206625Syongari 1298206625Syongaristatic void 1299206625Syongarisge_tick(void *arg) 1300206625Syongari{ 1301206625Syongari struct sge_softc *sc; 1302206625Syongari struct mii_data *mii; 1303206625Syongari struct ifnet *ifp; 1304206625Syongari 1305206625Syongari sc = arg; 1306206625Syongari SGE_LOCK_ASSERT(sc); 1307206625Syongari 1308206625Syongari ifp = sc->sge_ifp; 1309206625Syongari mii = device_get_softc(sc->sge_miibus); 1310206625Syongari mii_tick(mii); 1311206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0) { 1312206625Syongari sge_miibus_statchg(sc->sge_dev); 1313206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) != 0 && 1314206625Syongari !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1315206625Syongari sge_start_locked(ifp); 1316206625Syongari } 1317206625Syongari /* 1318206625Syongari * Reclaim transmitted frames here as we do not request 1319206625Syongari * Tx completion interrupt for every queued frames to 1320206625Syongari * reduce excessive interrupts. 1321206625Syongari */ 1322206625Syongari sge_txeof(sc); 1323206625Syongari sge_watchdog(sc); 1324206625Syongari callout_reset(&sc->sge_stat_ch, hz, sge_tick, sc); 1325206625Syongari} 1326206625Syongari 1327206625Syongaristatic void 1328206625Syongarisge_intr(void *arg) 1329206625Syongari{ 1330206625Syongari struct sge_softc *sc; 1331206625Syongari struct ifnet *ifp; 1332206625Syongari uint32_t status; 1333206625Syongari 1334206625Syongari sc = arg; 1335206625Syongari SGE_LOCK(sc); 1336206625Syongari ifp = sc->sge_ifp; 1337206625Syongari 1338206625Syongari status = CSR_READ_4(sc, IntrStatus); 1339206625Syongari if (status == 0xFFFFFFFF || (status & SGE_INTRS) == 0) { 1340206625Syongari /* Not ours. */ 1341206625Syongari SGE_UNLOCK(sc); 1342206625Syongari return; 1343206625Syongari } 1344206625Syongari /* Acknowledge interrupts. */ 1345206625Syongari CSR_WRITE_4(sc, IntrStatus, status); 1346206625Syongari /* Disable further interrupts. */ 1347206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 1348206625Syongari /* 1349206625Syongari * It seems the controller supports some kind of interrupt 1350206625Syongari * moderation mechanism but we still don't know how to 1351206625Syongari * enable that. To reduce number of generated interrupts 1352206625Syongari * under load we check pending interrupts in a loop. This 1353206625Syongari * will increase number of register access and is not correct 1354206625Syongari * way to handle interrupt moderation but there seems to be 1355206625Syongari * no other way at this time. 1356206625Syongari */ 1357206625Syongari for (;;) { 1358206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1359206625Syongari break; 1360206625Syongari if ((status & (INTR_RX_DONE | INTR_RX_IDLE)) != 0) { 1361206625Syongari sge_rxeof(sc); 1362206625Syongari /* Wakeup Rx MAC. */ 1363206625Syongari if ((status & INTR_RX_IDLE) != 0) 1364206625Syongari CSR_WRITE_4(sc, RX_CTL, 1365206625Syongari 0x1a00 | 0x000c | RX_CTL_POLL | RX_CTL_ENB); 1366206625Syongari } 1367206625Syongari if ((status & (INTR_TX_DONE | INTR_TX_IDLE)) != 0) 1368206625Syongari sge_txeof(sc); 1369206625Syongari status = CSR_READ_4(sc, IntrStatus); 1370206625Syongari if ((status & SGE_INTRS) == 0) 1371206625Syongari break; 1372206625Syongari /* Acknowledge interrupts. */ 1373206625Syongari CSR_WRITE_4(sc, IntrStatus, status); 1374206625Syongari } 1375206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1376206625Syongari /* Re-enable interrupts */ 1377206625Syongari CSR_WRITE_4(sc, IntrMask, SGE_INTRS); 1378206625Syongari if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1379206625Syongari sge_start_locked(ifp); 1380206625Syongari } 1381206625Syongari SGE_UNLOCK(sc); 1382206625Syongari} 1383206625Syongari 1384206625Syongari/* 1385206625Syongari * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data 1386206625Syongari * pointers to the fragment pointers. 1387206625Syongari */ 1388206625Syongaristatic int 1389206625Syongarisge_encap(struct sge_softc *sc, struct mbuf **m_head) 1390206625Syongari{ 1391206625Syongari struct mbuf *m; 1392206625Syongari struct sge_desc *desc; 1393207628Syongari struct sge_txdesc *txd; 1394206625Syongari bus_dma_segment_t txsegs[SGE_MAXTXSEGS]; 1395207851Syongari uint32_t cflags, mss; 1396207628Syongari int error, i, nsegs, prod, si; 1397206625Syongari 1398206625Syongari SGE_LOCK_ASSERT(sc); 1399206625Syongari 1400207628Syongari si = prod = sc->sge_cdata.sge_tx_prod; 1401207628Syongari txd = &sc->sge_cdata.sge_txdesc[prod]; 1402207851Syongari if (((*m_head)->m_pkthdr.csum_flags & CSUM_TSO) != 0) { 1403207851Syongari struct ether_header *eh; 1404207851Syongari struct ip *ip; 1405207851Syongari struct tcphdr *tcp; 1406207851Syongari uint32_t ip_off, poff; 1407207851Syongari 1408207851Syongari if (M_WRITABLE(*m_head) == 0) { 1409207851Syongari /* Get a writable copy. */ 1410243857Sglebius m = m_dup(*m_head, M_NOWAIT); 1411207851Syongari m_freem(*m_head); 1412207851Syongari if (m == NULL) { 1413207851Syongari *m_head = NULL; 1414207851Syongari return (ENOBUFS); 1415207851Syongari } 1416207851Syongari *m_head = m; 1417207851Syongari } 1418207851Syongari ip_off = sizeof(struct ether_header); 1419207851Syongari m = m_pullup(*m_head, ip_off); 1420207851Syongari if (m == NULL) { 1421207851Syongari *m_head = NULL; 1422207851Syongari return (ENOBUFS); 1423207851Syongari } 1424207851Syongari eh = mtod(m, struct ether_header *); 1425207851Syongari /* Check the existence of VLAN tag. */ 1426207851Syongari if (eh->ether_type == htons(ETHERTYPE_VLAN)) { 1427207851Syongari ip_off = sizeof(struct ether_vlan_header); 1428207851Syongari m = m_pullup(m, ip_off); 1429207851Syongari if (m == NULL) { 1430207851Syongari *m_head = NULL; 1431207851Syongari return (ENOBUFS); 1432207851Syongari } 1433207851Syongari } 1434207851Syongari m = m_pullup(m, ip_off + sizeof(struct ip)); 1435207851Syongari if (m == NULL) { 1436207851Syongari *m_head = NULL; 1437207851Syongari return (ENOBUFS); 1438207851Syongari } 1439207851Syongari ip = (struct ip *)(mtod(m, char *) + ip_off); 1440207851Syongari poff = ip_off + (ip->ip_hl << 2); 1441207851Syongari m = m_pullup(m, poff + sizeof(struct tcphdr)); 1442207851Syongari if (m == NULL) { 1443207851Syongari *m_head = NULL; 1444207851Syongari return (ENOBUFS); 1445207851Syongari } 1446207851Syongari tcp = (struct tcphdr *)(mtod(m, char *) + poff); 1447207851Syongari m = m_pullup(m, poff + (tcp->th_off << 2)); 1448207851Syongari if (m == NULL) { 1449207851Syongari *m_head = NULL; 1450207851Syongari return (ENOBUFS); 1451207851Syongari } 1452207851Syongari /* 1453207851Syongari * Reset IP checksum and recompute TCP pseudo 1454207851Syongari * checksum that NDIS specification requires. 1455207851Syongari */ 1456213844Syongari ip = (struct ip *)(mtod(m, char *) + ip_off); 1457207851Syongari ip->ip_sum = 0; 1458213844Syongari tcp = (struct tcphdr *)(mtod(m, char *) + poff); 1459207851Syongari tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, 1460207851Syongari htons(IPPROTO_TCP)); 1461207851Syongari *m_head = m; 1462207851Syongari } 1463207851Syongari 1464207628Syongari error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, 1465207628Syongari txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); 1466207628Syongari if (error == EFBIG) { 1467243857Sglebius m = m_collapse(*m_head, M_NOWAIT, SGE_MAXTXSEGS); 1468206625Syongari if (m == NULL) { 1469206625Syongari m_freem(*m_head); 1470206625Syongari *m_head = NULL; 1471206625Syongari return (ENOBUFS); 1472206625Syongari } 1473206625Syongari *m_head = m; 1474207628Syongari error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, 1475207628Syongari txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); 1476207628Syongari if (error != 0) { 1477207628Syongari m_freem(*m_head); 1478207628Syongari *m_head = NULL; 1479207628Syongari return (error); 1480207628Syongari } 1481207628Syongari } else if (error != 0) 1482206625Syongari return (error); 1483207628Syongari 1484207628Syongari KASSERT(nsegs != 0, ("zero segment returned")); 1485206625Syongari /* Check descriptor overrun. */ 1486206625Syongari if (sc->sge_cdata.sge_tx_cnt + nsegs >= SGE_TX_RING_CNT) { 1487207628Syongari bus_dmamap_unload(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap); 1488206625Syongari return (ENOBUFS); 1489206625Syongari } 1490207628Syongari bus_dmamap_sync(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap, 1491207545Syongari BUS_DMASYNC_PREWRITE); 1492206625Syongari 1493207628Syongari m = *m_head; 1494206625Syongari cflags = 0; 1495207851Syongari mss = 0; 1496207851Syongari if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) { 1497207851Syongari cflags |= TDC_LS; 1498207851Syongari mss = (uint32_t)m->m_pkthdr.tso_segsz; 1499207851Syongari mss <<= 16; 1500207851Syongari } else { 1501207851Syongari if (m->m_pkthdr.csum_flags & CSUM_IP) 1502207851Syongari cflags |= TDC_IP_CSUM; 1503207851Syongari if (m->m_pkthdr.csum_flags & CSUM_TCP) 1504207851Syongari cflags |= TDC_TCP_CSUM; 1505207851Syongari if (m->m_pkthdr.csum_flags & CSUM_UDP) 1506207851Syongari cflags |= TDC_UDP_CSUM; 1507207851Syongari } 1508207628Syongari for (i = 0; i < nsegs; i++) { 1509207628Syongari desc = &sc->sge_ldata.sge_tx_ring[prod]; 1510207628Syongari if (i == 0) { 1511207851Syongari desc->sge_sts_size = htole32(m->m_pkthdr.len | mss); 1512207628Syongari desc->sge_cmdsts = 0; 1513207628Syongari } else { 1514207628Syongari desc->sge_sts_size = 0; 1515207628Syongari desc->sge_cmdsts = htole32(TDC_OWN); 1516207628Syongari } 1517207628Syongari desc->sge_ptr = htole32(SGE_ADDR_LO(txsegs[i].ds_addr)); 1518207628Syongari desc->sge_flags = htole32(txsegs[i].ds_len); 1519207628Syongari if (prod == SGE_TX_RING_CNT - 1) 1520207628Syongari desc->sge_flags |= htole32(RING_END); 1521207628Syongari sc->sge_cdata.sge_tx_cnt++; 1522207628Syongari SGE_INC(prod, SGE_TX_RING_CNT); 1523207628Syongari } 1524207628Syongari /* Update producer index. */ 1525207628Syongari sc->sge_cdata.sge_tx_prod = prod; 1526207628Syongari 1527207628Syongari desc = &sc->sge_ldata.sge_tx_ring[si]; 1528207380Syongari /* Configure VLAN. */ 1529207628Syongari if((m->m_flags & M_VLANTAG) != 0) { 1530207628Syongari cflags |= m->m_pkthdr.ether_vtag; 1531207380Syongari desc->sge_sts_size |= htole32(TDS_INS_VLAN); 1532207380Syongari } 1533207628Syongari desc->sge_cmdsts |= htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags); 1534206625Syongari#if 1 1535206625Syongari if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0) 1536206625Syongari desc->sge_cmdsts |= htole32(TDC_BST); 1537206625Syongari#else 1538206625Syongari if ((sc->sge_flags & SGE_FLAG_FDX) == 0) { 1539206625Syongari desc->sge_cmdsts |= htole32(TDC_COL | TDC_CRS | TDC_BKF); 1540206625Syongari if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0) 1541206625Syongari desc->sge_cmdsts |= htole32(TDC_EXT | TDC_BST); 1542206625Syongari } 1543206625Syongari#endif 1544206625Syongari /* Request interrupt and give ownership to controller. */ 1545207628Syongari desc->sge_cmdsts |= htole32(TDC_OWN | TDC_INTR); 1546207628Syongari txd->tx_m = m; 1547207628Syongari txd->tx_ndesc = nsegs; 1548206625Syongari return (0); 1549206625Syongari} 1550206625Syongari 1551206625Syongaristatic void 1552206625Syongarisge_start(struct ifnet *ifp) 1553206625Syongari{ 1554206625Syongari struct sge_softc *sc; 1555206625Syongari 1556206625Syongari sc = ifp->if_softc; 1557206625Syongari SGE_LOCK(sc); 1558206625Syongari sge_start_locked(ifp); 1559206625Syongari SGE_UNLOCK(sc); 1560206625Syongari} 1561206625Syongari 1562206625Syongaristatic void 1563206625Syongarisge_start_locked(struct ifnet *ifp) 1564206625Syongari{ 1565206625Syongari struct sge_softc *sc; 1566206625Syongari struct mbuf *m_head; 1567206625Syongari int queued = 0; 1568206625Syongari 1569206625Syongari sc = ifp->if_softc; 1570206625Syongari SGE_LOCK_ASSERT(sc); 1571206625Syongari 1572206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0 || 1573206625Syongari (ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1574206625Syongari IFF_DRV_RUNNING) 1575206625Syongari return; 1576206625Syongari 1577206625Syongari for (queued = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) { 1578207628Syongari if (sc->sge_cdata.sge_tx_cnt > (SGE_TX_RING_CNT - 1579207628Syongari SGE_MAXTXSEGS)) { 1580206625Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1581206625Syongari break; 1582206625Syongari } 1583206625Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 1584206625Syongari if (m_head == NULL) 1585206625Syongari break; 1586206625Syongari if (sge_encap(sc, &m_head)) { 1587208806Syongari if (m_head == NULL) 1588208806Syongari break; 1589208806Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 1590206625Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1591206625Syongari break; 1592206625Syongari } 1593206625Syongari queued++; 1594206625Syongari /* 1595206625Syongari * If there's a BPF listener, bounce a copy of this frame 1596206625Syongari * to him. 1597206625Syongari */ 1598206625Syongari BPF_MTAP(ifp, m_head); 1599206625Syongari } 1600206625Syongari 1601206625Syongari if (queued > 0) { 1602206625Syongari bus_dmamap_sync(sc->sge_cdata.sge_tx_tag, 1603206625Syongari sc->sge_cdata.sge_tx_dmamap, 1604206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1605206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00 | TX_CTL_ENB | TX_CTL_POLL); 1606206625Syongari sc->sge_timer = 5; 1607206625Syongari } 1608206625Syongari} 1609206625Syongari 1610206625Syongaristatic void 1611206625Syongarisge_init(void *arg) 1612206625Syongari{ 1613206625Syongari struct sge_softc *sc; 1614206625Syongari 1615206625Syongari sc = arg; 1616206625Syongari SGE_LOCK(sc); 1617206625Syongari sge_init_locked(sc); 1618206625Syongari SGE_UNLOCK(sc); 1619206625Syongari} 1620206625Syongari 1621206625Syongaristatic void 1622206625Syongarisge_init_locked(struct sge_softc *sc) 1623206625Syongari{ 1624206625Syongari struct ifnet *ifp; 1625206625Syongari struct mii_data *mii; 1626207379Syongari uint16_t rxfilt; 1627206625Syongari int i; 1628206625Syongari 1629206625Syongari SGE_LOCK_ASSERT(sc); 1630206625Syongari ifp = sc->sge_ifp; 1631206625Syongari mii = device_get_softc(sc->sge_miibus); 1632206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1633206625Syongari return; 1634206625Syongari /* 1635206625Syongari * Cancel pending I/O and free all RX/TX buffers. 1636206625Syongari */ 1637206625Syongari sge_stop(sc); 1638206625Syongari sge_reset(sc); 1639206625Syongari 1640206625Syongari /* Init circular RX list. */ 1641206625Syongari if (sge_list_rx_init(sc) == ENOBUFS) { 1642206625Syongari device_printf(sc->sge_dev, "no memory for Rx buffers\n"); 1643206625Syongari sge_stop(sc); 1644206625Syongari return; 1645206625Syongari } 1646206625Syongari /* Init TX descriptors. */ 1647206625Syongari sge_list_tx_init(sc); 1648206625Syongari /* 1649206625Syongari * Load the address of the RX and TX lists. 1650206625Syongari */ 1651206625Syongari CSR_WRITE_4(sc, TX_DESC, SGE_ADDR_LO(sc->sge_ldata.sge_tx_paddr)); 1652206625Syongari CSR_WRITE_4(sc, RX_DESC, SGE_ADDR_LO(sc->sge_ldata.sge_rx_paddr)); 1653206625Syongari 1654206625Syongari CSR_WRITE_4(sc, TxMacControl, 0x60); 1655206625Syongari CSR_WRITE_4(sc, RxWakeOnLan, 0); 1656206625Syongari CSR_WRITE_4(sc, RxWakeOnLanData, 0); 1657206625Syongari /* Allow receiving VLAN frames. */ 1658207852Syongari CSR_WRITE_2(sc, RxMPSControl, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN + 1659207852Syongari SGE_RX_PAD_BYTES); 1660206625Syongari 1661206625Syongari for (i = 0; i < ETHER_ADDR_LEN; i++) 1662206625Syongari CSR_WRITE_1(sc, RxMacAddr + i, IF_LLADDR(ifp)[i]); 1663207379Syongari /* Configure RX MAC. */ 1664209818Syongari rxfilt = RXMAC_STRIP_FCS | RXMAC_PAD_ENB | RXMAC_CSUM_ENB; 1665207379Syongari CSR_WRITE_2(sc, RxMacControl, rxfilt); 1666206625Syongari sge_rxfilter(sc); 1667207380Syongari sge_setvlan(sc); 1668206625Syongari 1669206625Syongari /* Initialize default speed/duplex information. */ 1670206625Syongari if ((sc->sge_flags & SGE_FLAG_FASTETHER) == 0) 1671206625Syongari sc->sge_flags |= SGE_FLAG_SPEED_1000; 1672206625Syongari sc->sge_flags |= SGE_FLAG_FDX; 1673206625Syongari if ((sc->sge_flags & SGE_FLAG_RGMII) != 0) 1674206625Syongari CSR_WRITE_4(sc, StationControl, 0x04008001); 1675206625Syongari else 1676206625Syongari CSR_WRITE_4(sc, StationControl, 0x04000001); 1677206625Syongari /* 1678206625Syongari * XXX Try to mitigate interrupts. 1679206625Syongari */ 1680207071Syongari CSR_WRITE_4(sc, IntrControl, 0x08880000); 1681207071Syongari#ifdef notyet 1682206625Syongari if (sc->sge_intrcontrol != 0) 1683206625Syongari CSR_WRITE_4(sc, IntrControl, sc->sge_intrcontrol); 1684206625Syongari if (sc->sge_intrtimer != 0) 1685206625Syongari CSR_WRITE_4(sc, IntrTimer, sc->sge_intrtimer); 1686207071Syongari#endif 1687206625Syongari 1688206625Syongari /* 1689206625Syongari * Clear and enable interrupts. 1690206625Syongari */ 1691206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xFFFFFFFF); 1692206625Syongari CSR_WRITE_4(sc, IntrMask, SGE_INTRS); 1693206625Syongari 1694206625Syongari /* Enable receiver and transmitter. */ 1695206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00 | TX_CTL_ENB); 1696206625Syongari CSR_WRITE_4(sc, RX_CTL, 0x1a00 | 0x000c | RX_CTL_POLL | RX_CTL_ENB); 1697206625Syongari 1698206625Syongari ifp->if_drv_flags |= IFF_DRV_RUNNING; 1699206625Syongari ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1700206625Syongari 1701206625Syongari sc->sge_flags &= ~SGE_FLAG_LINK; 1702206625Syongari mii_mediachg(mii); 1703206625Syongari callout_reset(&sc->sge_stat_ch, hz, sge_tick, sc); 1704206625Syongari} 1705206625Syongari 1706206625Syongari/* 1707206625Syongari * Set media options. 1708206625Syongari */ 1709206625Syongaristatic int 1710206625Syongarisge_ifmedia_upd(struct ifnet *ifp) 1711206625Syongari{ 1712206625Syongari struct sge_softc *sc; 1713206625Syongari struct mii_data *mii; 1714221407Smarius struct mii_softc *miisc; 1715206625Syongari int error; 1716206625Syongari 1717206625Syongari sc = ifp->if_softc; 1718206625Syongari SGE_LOCK(sc); 1719206625Syongari mii = device_get_softc(sc->sge_miibus); 1720221407Smarius LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 1721221407Smarius PHY_RESET(miisc); 1722206625Syongari error = mii_mediachg(mii); 1723206625Syongari SGE_UNLOCK(sc); 1724206625Syongari 1725206625Syongari return (error); 1726206625Syongari} 1727206625Syongari 1728206625Syongari/* 1729206625Syongari * Report current media status. 1730206625Syongari */ 1731206625Syongaristatic void 1732206625Syongarisge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 1733206625Syongari{ 1734206625Syongari struct sge_softc *sc; 1735206625Syongari struct mii_data *mii; 1736206625Syongari 1737206625Syongari sc = ifp->if_softc; 1738206625Syongari SGE_LOCK(sc); 1739206625Syongari mii = device_get_softc(sc->sge_miibus); 1740206625Syongari if ((ifp->if_flags & IFF_UP) == 0) { 1741206625Syongari SGE_UNLOCK(sc); 1742206625Syongari return; 1743206625Syongari } 1744206625Syongari mii_pollstat(mii); 1745206625Syongari ifmr->ifm_active = mii->mii_media_active; 1746206625Syongari ifmr->ifm_status = mii->mii_media_status; 1747226478Syongari SGE_UNLOCK(sc); 1748206625Syongari} 1749206625Syongari 1750206625Syongaristatic int 1751206625Syongarisge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 1752206625Syongari{ 1753206625Syongari struct sge_softc *sc; 1754206625Syongari struct ifreq *ifr; 1755206625Syongari struct mii_data *mii; 1756207380Syongari int error = 0, mask, reinit; 1757206625Syongari 1758206625Syongari sc = ifp->if_softc; 1759206625Syongari ifr = (struct ifreq *)data; 1760206625Syongari 1761206625Syongari switch(command) { 1762206625Syongari case SIOCSIFFLAGS: 1763206625Syongari SGE_LOCK(sc); 1764206625Syongari if ((ifp->if_flags & IFF_UP) != 0) { 1765206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 1766206625Syongari ((ifp->if_flags ^ sc->sge_if_flags) & 1767206625Syongari (IFF_PROMISC | IFF_ALLMULTI)) != 0) 1768206625Syongari sge_rxfilter(sc); 1769206625Syongari else 1770206625Syongari sge_init_locked(sc); 1771206625Syongari } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1772206625Syongari sge_stop(sc); 1773206625Syongari sc->sge_if_flags = ifp->if_flags; 1774206625Syongari SGE_UNLOCK(sc); 1775206625Syongari break; 1776206625Syongari case SIOCSIFCAP: 1777206625Syongari SGE_LOCK(sc); 1778207380Syongari reinit = 0; 1779206625Syongari mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1780206625Syongari if ((mask & IFCAP_TXCSUM) != 0 && 1781206625Syongari (ifp->if_capabilities & IFCAP_TXCSUM) != 0) { 1782206625Syongari ifp->if_capenable ^= IFCAP_TXCSUM; 1783206625Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 1784206625Syongari ifp->if_hwassist |= SGE_CSUM_FEATURES; 1785206625Syongari else 1786206625Syongari ifp->if_hwassist &= ~SGE_CSUM_FEATURES; 1787206625Syongari } 1788206625Syongari if ((mask & IFCAP_RXCSUM) != 0 && 1789206625Syongari (ifp->if_capabilities & IFCAP_RXCSUM) != 0) 1790206625Syongari ifp->if_capenable ^= IFCAP_RXCSUM; 1791207380Syongari if ((mask & IFCAP_VLAN_HWCSUM) != 0 && 1792207380Syongari (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0) 1793207380Syongari ifp->if_capenable ^= IFCAP_VLAN_HWCSUM; 1794207851Syongari if ((mask & IFCAP_TSO4) != 0 && 1795207851Syongari (ifp->if_capabilities & IFCAP_TSO4) != 0) { 1796207851Syongari ifp->if_capenable ^= IFCAP_TSO4; 1797207851Syongari if ((ifp->if_capenable & IFCAP_TSO4) != 0) 1798207851Syongari ifp->if_hwassist |= CSUM_TSO; 1799207851Syongari else 1800207851Syongari ifp->if_hwassist &= ~CSUM_TSO; 1801207851Syongari } 1802207851Syongari if ((mask & IFCAP_VLAN_HWTSO) != 0 && 1803207851Syongari (ifp->if_capabilities & IFCAP_VLAN_HWTSO) != 0) 1804207851Syongari ifp->if_capenable ^= IFCAP_VLAN_HWTSO; 1805207380Syongari if ((mask & IFCAP_VLAN_HWTAGGING) != 0 && 1806207380Syongari (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) { 1807207380Syongari /* 1808207380Syongari * Due to unknown reason, toggling VLAN hardware 1809207380Syongari * tagging require interface reinitialization. 1810207380Syongari */ 1811207380Syongari ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 1812207851Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0) 1813207851Syongari ifp->if_capenable &= 1814207851Syongari ~(IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM); 1815207380Syongari reinit = 1; 1816207380Syongari } 1817207380Syongari if (reinit > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1818207380Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1819207380Syongari sge_init_locked(sc); 1820207380Syongari } 1821206625Syongari SGE_UNLOCK(sc); 1822207380Syongari VLAN_CAPABILITIES(ifp); 1823206625Syongari break; 1824206625Syongari case SIOCADDMULTI: 1825206625Syongari case SIOCDELMULTI: 1826206625Syongari SGE_LOCK(sc); 1827206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1828206625Syongari sge_rxfilter(sc); 1829206625Syongari SGE_UNLOCK(sc); 1830206625Syongari break; 1831206625Syongari case SIOCGIFMEDIA: 1832206625Syongari case SIOCSIFMEDIA: 1833206625Syongari mii = device_get_softc(sc->sge_miibus); 1834206625Syongari error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 1835206625Syongari break; 1836206625Syongari default: 1837206625Syongari error = ether_ioctl(ifp, command, data); 1838206625Syongari break; 1839206625Syongari } 1840206625Syongari 1841206625Syongari return (error); 1842206625Syongari} 1843206625Syongari 1844206625Syongaristatic void 1845206625Syongarisge_watchdog(struct sge_softc *sc) 1846206625Syongari{ 1847206625Syongari struct ifnet *ifp; 1848206625Syongari 1849206625Syongari SGE_LOCK_ASSERT(sc); 1850206625Syongari if (sc->sge_timer == 0 || --sc->sge_timer > 0) 1851206625Syongari return; 1852206625Syongari 1853206625Syongari ifp = sc->sge_ifp; 1854206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0) { 1855206625Syongari if (1 || bootverbose) 1856206625Syongari device_printf(sc->sge_dev, 1857206625Syongari "watchdog timeout (lost link)\n"); 1858271849Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1859206625Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1860206625Syongari sge_init_locked(sc); 1861206625Syongari return; 1862206625Syongari } 1863206625Syongari device_printf(sc->sge_dev, "watchdog timeout\n"); 1864271849Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1865206625Syongari 1866206625Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1867206625Syongari sge_init_locked(sc); 1868206625Syongari if (!IFQ_DRV_IS_EMPTY(&sc->sge_ifp->if_snd)) 1869206625Syongari sge_start_locked(ifp); 1870206625Syongari} 1871206625Syongari 1872206625Syongari/* 1873206625Syongari * Stop the adapter and free any mbufs allocated to the 1874206625Syongari * RX and TX lists. 1875206625Syongari */ 1876206625Syongaristatic void 1877206625Syongarisge_stop(struct sge_softc *sc) 1878206625Syongari{ 1879206625Syongari struct ifnet *ifp; 1880206625Syongari 1881206625Syongari ifp = sc->sge_ifp; 1882206625Syongari 1883206625Syongari SGE_LOCK_ASSERT(sc); 1884206625Syongari 1885206625Syongari sc->sge_timer = 0; 1886206625Syongari callout_stop(&sc->sge_stat_ch); 1887206625Syongari ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1888206625Syongari 1889206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 1890206625Syongari CSR_READ_4(sc, IntrMask); 1891206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 1892206625Syongari /* Stop TX/RX MAC. */ 1893206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00); 1894206625Syongari CSR_WRITE_4(sc, RX_CTL, 0x1a00); 1895206625Syongari /* XXX Can we assume active DMA cycles gone? */ 1896206625Syongari DELAY(2000); 1897206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 1898206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 1899206625Syongari 1900206625Syongari sc->sge_flags &= ~SGE_FLAG_LINK; 1901206625Syongari sge_list_rx_free(sc); 1902206625Syongari sge_list_tx_free(sc); 1903206625Syongari} 1904