if_sge.c revision 208806
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: head/sys/dev/sge/if_sge.c 208806 2010-06-04 17:11:33Z yongari $"); 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> 68206625Syongari#include <net/if_arp.h> 69206625Syongari#include <net/ethernet.h> 70206625Syongari#include <net/if_dl.h> 71206625Syongari#include <net/if_media.h> 72206625Syongari#include <net/if_types.h> 73206625Syongari#include <net/if_vlan_var.h> 74206625Syongari 75207851Syongari#include <netinet/in.h> 76207851Syongari#include <netinet/in_systm.h> 77207851Syongari#include <netinet/ip.h> 78207851Syongari#include <netinet/tcp.h> 79207851Syongari 80206625Syongari#include <machine/bus.h> 81207851Syongari#include <machine/in_cksum.h> 82206625Syongari 83206625Syongari#include <dev/mii/mii.h> 84206625Syongari#include <dev/mii/miivar.h> 85206625Syongari 86206625Syongari#include <dev/pci/pcireg.h> 87206625Syongari#include <dev/pci/pcivar.h> 88206625Syongari 89206672Syongari#include <dev/sge/if_sgereg.h> 90206625Syongari 91206625SyongariMODULE_DEPEND(sge, pci, 1, 1, 1); 92206625SyongariMODULE_DEPEND(sge, ether, 1, 1, 1); 93206625SyongariMODULE_DEPEND(sge, miibus, 1, 1, 1); 94206625Syongari 95206625Syongari/* "device miibus0" required. See GENERIC if you get errors here. */ 96206625Syongari#include "miibus_if.h" 97206625Syongari 98206625Syongari/* 99206625Syongari * Various supported device vendors/types and their names. 100206625Syongari */ 101206625Syongaristatic struct sge_type sge_devs[] = { 102206625Syongari { SIS_VENDORID, SIS_DEVICEID_190, "SiS190 Fast Ethernet" }, 103206625Syongari { SIS_VENDORID, SIS_DEVICEID_191, "SiS191 Fast/Gigabit Ethernet" }, 104206625Syongari { 0, 0, NULL } 105206625Syongari}; 106206625Syongari 107206625Syongaristatic int sge_probe(device_t); 108206625Syongaristatic int sge_attach(device_t); 109206625Syongaristatic int sge_detach(device_t); 110206625Syongaristatic int sge_shutdown(device_t); 111206625Syongaristatic int sge_suspend(device_t); 112206625Syongaristatic int sge_resume(device_t); 113206625Syongari 114206625Syongaristatic int sge_miibus_readreg(device_t, int, int); 115206625Syongaristatic int sge_miibus_writereg(device_t, int, int, int); 116206625Syongaristatic void sge_miibus_statchg(device_t); 117206625Syongari 118206625Syongaristatic int sge_newbuf(struct sge_softc *, int); 119206625Syongaristatic int sge_encap(struct sge_softc *, struct mbuf **); 120206625Syongaristatic __inline void 121206625Syongari sge_discard_rxbuf(struct sge_softc *, int); 122206625Syongaristatic void sge_rxeof(struct sge_softc *); 123206625Syongaristatic void sge_txeof(struct sge_softc *); 124206625Syongaristatic void sge_intr(void *); 125206625Syongaristatic void sge_tick(void *); 126206625Syongaristatic void sge_start(struct ifnet *); 127206625Syongaristatic void sge_start_locked(struct ifnet *); 128206625Syongaristatic int sge_ioctl(struct ifnet *, u_long, caddr_t); 129206625Syongaristatic void sge_init(void *); 130206625Syongaristatic void sge_init_locked(struct sge_softc *); 131206625Syongaristatic void sge_stop(struct sge_softc *); 132206625Syongaristatic void sge_watchdog(struct sge_softc *); 133206625Syongaristatic int sge_ifmedia_upd(struct ifnet *); 134206625Syongaristatic void sge_ifmedia_sts(struct ifnet *, struct ifmediareq *); 135206625Syongari 136206625Syongaristatic int sge_get_mac_addr_apc(struct sge_softc *, uint8_t *); 137206625Syongaristatic int sge_get_mac_addr_eeprom(struct sge_softc *, uint8_t *); 138206625Syongaristatic uint16_t sge_read_eeprom(struct sge_softc *, int); 139206625Syongari 140206625Syongaristatic void sge_rxfilter(struct sge_softc *); 141207380Syongaristatic void sge_setvlan(struct sge_softc *); 142206625Syongaristatic void sge_reset(struct sge_softc *); 143206625Syongaristatic int sge_list_rx_init(struct sge_softc *); 144206625Syongaristatic int sge_list_rx_free(struct sge_softc *); 145206625Syongaristatic int sge_list_tx_init(struct sge_softc *); 146206625Syongaristatic int sge_list_tx_free(struct sge_softc *); 147206625Syongari 148206625Syongaristatic int sge_dma_alloc(struct sge_softc *); 149206625Syongaristatic void sge_dma_free(struct sge_softc *); 150206625Syongaristatic void sge_dma_map_addr(void *, bus_dma_segment_t *, int, int); 151206625Syongari 152206625Syongaristatic device_method_t sge_methods[] = { 153206625Syongari /* Device interface */ 154206625Syongari DEVMETHOD(device_probe, sge_probe), 155206625Syongari DEVMETHOD(device_attach, sge_attach), 156206625Syongari DEVMETHOD(device_detach, sge_detach), 157206625Syongari DEVMETHOD(device_suspend, sge_suspend), 158206625Syongari DEVMETHOD(device_resume, sge_resume), 159206625Syongari DEVMETHOD(device_shutdown, sge_shutdown), 160206625Syongari 161206625Syongari /* Bus interface */ 162206625Syongari DEVMETHOD(bus_print_child, bus_generic_print_child), 163206625Syongari DEVMETHOD(bus_driver_added, bus_generic_driver_added), 164206625Syongari 165206625Syongari /* MII interface */ 166206625Syongari DEVMETHOD(miibus_readreg, sge_miibus_readreg), 167206625Syongari DEVMETHOD(miibus_writereg, sge_miibus_writereg), 168206625Syongari DEVMETHOD(miibus_statchg, sge_miibus_statchg), 169206625Syongari 170206625Syongari KOBJMETHOD_END 171206625Syongari}; 172206625Syongari 173206625Syongaristatic driver_t sge_driver = { 174206625Syongari "sge", sge_methods, sizeof(struct sge_softc) 175206625Syongari}; 176206625Syongari 177206625Syongaristatic devclass_t sge_devclass; 178206625Syongari 179206625SyongariDRIVER_MODULE(sge, pci, sge_driver, sge_devclass, 0, 0); 180206625SyongariDRIVER_MODULE(miibus, sge, miibus_driver, miibus_devclass, 0, 0); 181206625Syongari 182206625Syongari/* 183206625Syongari * Register space access macros. 184206625Syongari */ 185206625Syongari#define CSR_WRITE_4(sc, reg, val) bus_write_4(sc->sge_res, reg, val) 186206625Syongari#define CSR_WRITE_2(sc, reg, val) bus_write_2(sc->sge_res, reg, val) 187206625Syongari#define CSR_WRITE_1(cs, reg, val) bus_write_1(sc->sge_res, reg, val) 188206625Syongari 189206625Syongari#define CSR_READ_4(sc, reg) bus_read_4(sc->sge_res, reg) 190206625Syongari#define CSR_READ_2(sc, reg) bus_read_2(sc->sge_res, reg) 191206625Syongari#define CSR_READ_1(sc, reg) bus_read_1(sc->sge_res, reg) 192206625Syongari 193206625Syongari/* Define to show Tx/Rx error status. */ 194206625Syongari#undef SGE_SHOW_ERRORS 195206625Syongari 196206625Syongari#define SGE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 197206625Syongari 198206625Syongaristatic void 199206625Syongarisge_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 200206625Syongari{ 201206625Syongari bus_addr_t *p; 202206625Syongari 203206625Syongari if (error != 0) 204206625Syongari return; 205206625Syongari KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 206206625Syongari p = arg; 207206625Syongari *p = segs->ds_addr; 208206625Syongari} 209206625Syongari 210206625Syongari/* 211206625Syongari * Read a sequence of words from the EEPROM. 212206625Syongari */ 213206625Syongaristatic uint16_t 214206625Syongarisge_read_eeprom(struct sge_softc *sc, int offset) 215206625Syongari{ 216206625Syongari uint32_t val; 217206625Syongari int i; 218206625Syongari 219206625Syongari KASSERT(offset <= EI_OFFSET, ("EEPROM offset too big")); 220206625Syongari CSR_WRITE_4(sc, ROMInterface, 221206625Syongari EI_REQ | EI_OP_RD | (offset << EI_OFFSET_SHIFT)); 222206625Syongari DELAY(500); 223206625Syongari for (i = 0; i < SGE_TIMEOUT; i++) { 224206625Syongari val = CSR_READ_4(sc, ROMInterface); 225206625Syongari if ((val & EI_REQ) == 0) 226206625Syongari break; 227206625Syongari DELAY(100); 228206625Syongari } 229206625Syongari if (i == SGE_TIMEOUT) { 230206625Syongari device_printf(sc->sge_dev, 231206625Syongari "EEPROM read timeout : 0x%08x\n", val); 232206625Syongari return (0xffff); 233206625Syongari } 234206625Syongari 235206625Syongari return ((val & EI_DATA) >> EI_DATA_SHIFT); 236206625Syongari} 237206625Syongari 238206625Syongaristatic int 239206625Syongarisge_get_mac_addr_eeprom(struct sge_softc *sc, uint8_t *dest) 240206625Syongari{ 241206625Syongari uint16_t val; 242206625Syongari int i; 243206625Syongari 244206625Syongari val = sge_read_eeprom(sc, EEPROMSignature); 245206625Syongari if (val == 0xffff || val == 0) { 246206625Syongari device_printf(sc->sge_dev, 247206625Syongari "invalid EEPROM signature : 0x%04x\n", val); 248206625Syongari return (EINVAL); 249206625Syongari } 250206625Syongari 251206625Syongari for (i = 0; i < ETHER_ADDR_LEN; i += 2) { 252206625Syongari val = sge_read_eeprom(sc, EEPROMMACAddr + i / 2); 253206625Syongari dest[i + 0] = (uint8_t)val; 254206625Syongari dest[i + 1] = (uint8_t)(val >> 8); 255206625Syongari } 256206625Syongari 257206625Syongari if ((sge_read_eeprom(sc, EEPROMInfo) & 0x80) != 0) 258206625Syongari sc->sge_flags |= SGE_FLAG_RGMII; 259206625Syongari return (0); 260206625Syongari} 261206625Syongari 262206625Syongari/* 263206625Syongari * For SiS96x, APC CMOS RAM is used to store ethernet address. 264206625Syongari * APC CMOS RAM is accessed through ISA bridge. 265206625Syongari */ 266206625Syongaristatic int 267206625Syongarisge_get_mac_addr_apc(struct sge_softc *sc, uint8_t *dest) 268206625Syongari{ 269206625Syongari#if defined(__amd64__) || defined(__i386__) 270206625Syongari devclass_t pci; 271206625Syongari device_t bus, dev = NULL; 272206625Syongari device_t *kids; 273206625Syongari struct apc_tbl { 274206625Syongari uint16_t vid; 275206625Syongari uint16_t did; 276206625Syongari } *tp, apc_tbls[] = { 277206625Syongari { SIS_VENDORID, 0x0965 }, 278206625Syongari { SIS_VENDORID, 0x0966 }, 279206625Syongari { SIS_VENDORID, 0x0968 } 280206625Syongari }; 281206625Syongari uint8_t reg; 282206625Syongari int busnum, cnt, i, j, numkids; 283206625Syongari 284206625Syongari cnt = sizeof(apc_tbls) / sizeof(apc_tbls[0]); 285206625Syongari pci = devclass_find("pci"); 286206625Syongari for (busnum = 0; busnum < devclass_get_maxunit(pci); busnum++) { 287206625Syongari bus = devclass_get_device(pci, busnum); 288206625Syongari if (!bus) 289206625Syongari continue; 290206625Syongari if (device_get_children(bus, &kids, &numkids) != 0) 291206625Syongari continue; 292206625Syongari for (i = 0; i < numkids; i++) { 293206625Syongari dev = kids[i]; 294206625Syongari if (pci_get_class(dev) == PCIC_BRIDGE && 295206625Syongari pci_get_subclass(dev) == PCIS_BRIDGE_ISA) { 296206625Syongari tp = apc_tbls; 297206625Syongari for (j = 0; j < cnt; j++) { 298206625Syongari if (pci_get_vendor(dev) == tp->vid && 299206625Syongari pci_get_device(dev) == tp->did) { 300206625Syongari free(kids, M_TEMP); 301206625Syongari goto apc_found; 302206625Syongari } 303206625Syongari tp++; 304206625Syongari } 305206625Syongari } 306206625Syongari } 307206625Syongari free(kids, M_TEMP); 308206625Syongari } 309206625Syongari device_printf(sc->sge_dev, "couldn't find PCI-ISA bridge\n"); 310206625Syongari return (EINVAL); 311206625Syongariapc_found: 312206625Syongari /* Enable port 0x78 and 0x79 to access APC registers. */ 313206625Syongari reg = pci_read_config(dev, 0x48, 1); 314206625Syongari pci_write_config(dev, 0x48, reg & ~0x02, 1); 315206625Syongari DELAY(50); 316206625Syongari pci_read_config(dev, 0x48, 1); 317206625Syongari /* Read stored ethernet address. */ 318206625Syongari for (i = 0; i < ETHER_ADDR_LEN; i++) { 319206625Syongari outb(0x78, 0x09 + i); 320206625Syongari dest[i] = inb(0x79); 321206625Syongari } 322206625Syongari outb(0x78, 0x12); 323206625Syongari if ((inb(0x79) & 0x80) != 0) 324206625Syongari sc->sge_flags |= SGE_FLAG_RGMII; 325206625Syongari /* Restore access to APC registers. */ 326206625Syongari pci_write_config(dev, 0x48, reg, 1); 327206625Syongari 328206625Syongari return (0); 329206625Syongari#else 330206625Syongari return (EINVAL); 331206625Syongari#endif 332206625Syongari} 333206625Syongari 334206625Syongaristatic int 335206625Syongarisge_miibus_readreg(device_t dev, int phy, int reg) 336206625Syongari{ 337206625Syongari struct sge_softc *sc; 338206625Syongari uint32_t val; 339206625Syongari int i; 340206625Syongari 341206625Syongari sc = device_get_softc(dev); 342206625Syongari CSR_WRITE_4(sc, GMIIControl, (phy << GMI_PHY_SHIFT) | 343206625Syongari (reg << GMI_REG_SHIFT) | GMI_OP_RD | GMI_REQ); 344206625Syongari DELAY(10); 345206625Syongari for (i = 0; i < SGE_TIMEOUT; i++) { 346206625Syongari val = CSR_READ_4(sc, GMIIControl); 347206625Syongari if ((val & GMI_REQ) == 0) 348206625Syongari break; 349206625Syongari DELAY(10); 350206625Syongari } 351206625Syongari if (i == SGE_TIMEOUT) { 352206625Syongari device_printf(sc->sge_dev, "PHY read timeout : %d\n", reg); 353206625Syongari return (0); 354206625Syongari } 355206625Syongari return ((val & GMI_DATA) >> GMI_DATA_SHIFT); 356206625Syongari} 357206625Syongari 358206625Syongaristatic int 359206625Syongarisge_miibus_writereg(device_t dev, int phy, int reg, int data) 360206625Syongari{ 361206625Syongari struct sge_softc *sc; 362206625Syongari uint32_t val; 363206625Syongari int i; 364206625Syongari 365206625Syongari sc = device_get_softc(dev); 366206625Syongari CSR_WRITE_4(sc, GMIIControl, (phy << GMI_PHY_SHIFT) | 367206625Syongari (reg << GMI_REG_SHIFT) | (data << GMI_DATA_SHIFT) | 368206625Syongari GMI_OP_WR | GMI_REQ); 369206625Syongari DELAY(10); 370206625Syongari for (i = 0; i < SGE_TIMEOUT; i++) { 371206625Syongari val = CSR_READ_4(sc, GMIIControl); 372206625Syongari if ((val & GMI_REQ) == 0) 373206625Syongari break; 374206625Syongari DELAY(10); 375206625Syongari } 376206625Syongari if (i == SGE_TIMEOUT) 377206625Syongari device_printf(sc->sge_dev, "PHY write timeout : %d\n", reg); 378206625Syongari return (0); 379206625Syongari} 380206625Syongari 381206625Syongaristatic void 382206625Syongarisge_miibus_statchg(device_t dev) 383206625Syongari{ 384206625Syongari struct sge_softc *sc; 385206625Syongari struct mii_data *mii; 386206625Syongari struct ifnet *ifp; 387206625Syongari uint32_t ctl, speed; 388206625Syongari 389206625Syongari sc = device_get_softc(dev); 390206625Syongari mii = device_get_softc(sc->sge_miibus); 391206625Syongari ifp = sc->sge_ifp; 392206625Syongari if (mii == NULL || ifp == NULL || 393206625Syongari (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 394206625Syongari return; 395206625Syongari speed = 0; 396206625Syongari sc->sge_flags &= ~SGE_FLAG_LINK; 397206625Syongari if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 398206625Syongari (IFM_ACTIVE | IFM_AVALID)) { 399206625Syongari switch (IFM_SUBTYPE(mii->mii_media_active)) { 400206625Syongari case IFM_10_T: 401206625Syongari sc->sge_flags |= SGE_FLAG_LINK; 402206625Syongari speed = SC_SPEED_10; 403206625Syongari break; 404206625Syongari case IFM_100_TX: 405206625Syongari sc->sge_flags |= SGE_FLAG_LINK; 406206625Syongari speed = SC_SPEED_100; 407206625Syongari break; 408206625Syongari case IFM_1000_T: 409206625Syongari if ((sc->sge_flags & SGE_FLAG_FASTETHER) == 0) { 410206625Syongari sc->sge_flags |= SGE_FLAG_LINK; 411206625Syongari speed = SC_SPEED_1000; 412206625Syongari } 413206625Syongari break; 414206625Syongari default: 415206625Syongari break; 416206625Syongari } 417206625Syongari } 418206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0) 419206625Syongari return; 420206625Syongari /* Reprogram MAC to resolved speed/duplex/flow-control parameters. */ 421206625Syongari ctl = CSR_READ_4(sc, StationControl); 422206625Syongari ctl &= ~(0x0f000000 | SC_FDX | SC_SPEED_MASK); 423206625Syongari if (speed == SC_SPEED_1000) { 424206625Syongari ctl |= 0x07000000; 425206625Syongari sc->sge_flags |= SGE_FLAG_SPEED_1000; 426206625Syongari } else { 427206625Syongari ctl |= 0x04000000; 428206625Syongari sc->sge_flags &= ~SGE_FLAG_SPEED_1000; 429206625Syongari } 430206625Syongari#ifdef notyet 431206625Syongari if ((sc->sge_flags & SGE_FLAG_GMII) != 0) 432206625Syongari ctl |= 0x03000000; 433206625Syongari#endif 434206625Syongari ctl |= speed; 435206625Syongari if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) { 436206625Syongari ctl |= SC_FDX; 437206625Syongari sc->sge_flags |= SGE_FLAG_FDX; 438206625Syongari } else 439206625Syongari sc->sge_flags &= ~SGE_FLAG_FDX; 440206625Syongari CSR_WRITE_4(sc, StationControl, ctl); 441206625Syongari if ((sc->sge_flags & SGE_FLAG_RGMII) != 0) { 442206625Syongari CSR_WRITE_4(sc, RGMIIDelay, 0x0441); 443206625Syongari CSR_WRITE_4(sc, RGMIIDelay, 0x0440); 444206625Syongari } 445206625Syongari} 446206625Syongari 447206625Syongaristatic void 448206625Syongarisge_rxfilter(struct sge_softc *sc) 449206625Syongari{ 450206625Syongari struct ifnet *ifp; 451206625Syongari struct ifmultiaddr *ifma; 452206625Syongari uint32_t crc, hashes[2]; 453206625Syongari uint16_t rxfilt; 454206625Syongari 455206625Syongari SGE_LOCK_ASSERT(sc); 456206625Syongari 457206625Syongari ifp = sc->sge_ifp; 458207375Syongari rxfilt = CSR_READ_2(sc, RxMacControl); 459207375Syongari rxfilt &= ~(AcceptBroadcast | AcceptAllPhys | AcceptMulticast); 460207375Syongari rxfilt |= AcceptMyPhys; 461206625Syongari if ((ifp->if_flags & IFF_BROADCAST) != 0) 462206625Syongari rxfilt |= AcceptBroadcast; 463206625Syongari if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { 464206625Syongari if ((ifp->if_flags & IFF_PROMISC) != 0) 465206625Syongari rxfilt |= AcceptAllPhys; 466206625Syongari rxfilt |= AcceptMulticast; 467206625Syongari hashes[0] = 0xFFFFFFFF; 468206625Syongari hashes[1] = 0xFFFFFFFF; 469207375Syongari } else { 470207375Syongari rxfilt |= AcceptMulticast; 471207375Syongari hashes[0] = hashes[1] = 0; 472207375Syongari /* Now program new ones. */ 473207375Syongari if_maddr_rlock(ifp); 474207375Syongari TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 475207375Syongari if (ifma->ifma_addr->sa_family != AF_LINK) 476207375Syongari continue; 477207375Syongari crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) 478207375Syongari ifma->ifma_addr), ETHER_ADDR_LEN); 479207375Syongari hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); 480207375Syongari } 481207375Syongari if_maddr_runlock(ifp); 482206625Syongari } 483206625Syongari CSR_WRITE_2(sc, RxMacControl, rxfilt | 0x02); 484206625Syongari CSR_WRITE_4(sc, RxHashTable, hashes[0]); 485206625Syongari CSR_WRITE_4(sc, RxHashTable2, hashes[1]); 486206625Syongari} 487206625Syongari 488206625Syongaristatic void 489207380Syongarisge_setvlan(struct sge_softc *sc) 490207380Syongari{ 491207380Syongari struct ifnet *ifp; 492207380Syongari uint16_t rxfilt; 493207380Syongari 494207380Syongari SGE_LOCK_ASSERT(sc); 495207380Syongari 496207380Syongari ifp = sc->sge_ifp; 497207380Syongari if ((ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0) 498207380Syongari return; 499207380Syongari rxfilt = CSR_READ_2(sc, RxMacControl); 500207380Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 501207380Syongari rxfilt |= RXMAC_STRIP_VLAN; 502207380Syongari else 503207380Syongari rxfilt &= ~RXMAC_STRIP_VLAN; 504207380Syongari CSR_WRITE_2(sc, RxMacControl, rxfilt); 505207380Syongari} 506207380Syongari 507207380Syongaristatic void 508206625Syongarisge_reset(struct sge_softc *sc) 509206625Syongari{ 510206625Syongari 511206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 512206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 513206625Syongari 514206625Syongari /* Soft reset. */ 515206625Syongari CSR_WRITE_4(sc, IntrControl, 0x8000); 516206625Syongari CSR_READ_4(sc, IntrControl); 517206625Syongari DELAY(100); 518206625Syongari CSR_WRITE_4(sc, IntrControl, 0); 519206625Syongari /* Stop MAC. */ 520206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00); 521206625Syongari CSR_WRITE_4(sc, RX_CTL, 0x1a00); 522206625Syongari 523206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 524206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 525206625Syongari 526206625Syongari CSR_WRITE_4(sc, GMIIControl, 0); 527206625Syongari} 528206625Syongari 529206625Syongari/* 530206625Syongari * Probe for an SiS chip. Check the PCI vendor and device 531206625Syongari * IDs against our list and return a device name if we find a match. 532206625Syongari */ 533206625Syongaristatic int 534206625Syongarisge_probe(device_t dev) 535206625Syongari{ 536206625Syongari struct sge_type *t; 537206625Syongari 538206625Syongari t = sge_devs; 539206625Syongari while (t->sge_name != NULL) { 540206625Syongari if ((pci_get_vendor(dev) == t->sge_vid) && 541206625Syongari (pci_get_device(dev) == t->sge_did)) { 542206625Syongari device_set_desc(dev, t->sge_name); 543206625Syongari return (BUS_PROBE_DEFAULT); 544206625Syongari } 545206625Syongari t++; 546206625Syongari } 547206625Syongari 548206625Syongari return (ENXIO); 549206625Syongari} 550206625Syongari 551206625Syongari/* 552206625Syongari * Attach the interface. Allocate softc structures, do ifmedia 553206625Syongari * setup and ethernet/BPF attach. 554206625Syongari */ 555206625Syongaristatic int 556206625Syongarisge_attach(device_t dev) 557206625Syongari{ 558206625Syongari struct sge_softc *sc; 559206625Syongari struct ifnet *ifp; 560206625Syongari uint8_t eaddr[ETHER_ADDR_LEN]; 561206625Syongari int error = 0, rid; 562206625Syongari 563206625Syongari sc = device_get_softc(dev); 564206625Syongari sc->sge_dev = dev; 565206625Syongari 566206625Syongari mtx_init(&sc->sge_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 567206625Syongari MTX_DEF); 568206625Syongari callout_init_mtx(&sc->sge_stat_ch, &sc->sge_mtx, 0); 569206625Syongari 570206625Syongari /* 571206625Syongari * Map control/status registers. 572206625Syongari */ 573206625Syongari pci_enable_busmaster(dev); 574206625Syongari 575206625Syongari /* Allocate resources. */ 576206625Syongari sc->sge_res_id = PCIR_BAR(0); 577206625Syongari sc->sge_res_type = SYS_RES_MEMORY; 578206625Syongari sc->sge_res = bus_alloc_resource_any(dev, sc->sge_res_type, 579206625Syongari &sc->sge_res_id, RF_ACTIVE); 580206625Syongari if (sc->sge_res == NULL) { 581206625Syongari device_printf(dev, "couldn't allocate resource\n"); 582206625Syongari error = ENXIO; 583206625Syongari goto fail; 584206625Syongari } 585206625Syongari 586206625Syongari rid = 0; 587206625Syongari sc->sge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 588206625Syongari RF_SHAREABLE | RF_ACTIVE); 589206625Syongari if (sc->sge_irq == NULL) { 590206625Syongari device_printf(dev, "couldn't allocate IRQ resources\n"); 591206625Syongari error = ENXIO; 592206625Syongari goto fail; 593206625Syongari } 594206625Syongari sc->sge_rev = pci_get_revid(dev); 595206625Syongari if (pci_get_device(dev) == SIS_DEVICEID_190) 596207377Syongari sc->sge_flags |= SGE_FLAG_FASTETHER | SGE_FLAG_SIS190; 597206625Syongari /* Reset the adapter. */ 598206625Syongari sge_reset(sc); 599206625Syongari 600206625Syongari /* Get MAC address from the EEPROM. */ 601206625Syongari if ((pci_read_config(dev, 0x73, 1) & 0x01) != 0) 602206625Syongari sge_get_mac_addr_apc(sc, eaddr); 603206625Syongari else 604206625Syongari sge_get_mac_addr_eeprom(sc, eaddr); 605206625Syongari 606206625Syongari if ((error = sge_dma_alloc(sc)) != 0) 607206625Syongari goto fail; 608206625Syongari 609206625Syongari ifp = sc->sge_ifp = if_alloc(IFT_ETHER); 610206625Syongari if (ifp == NULL) { 611206625Syongari device_printf(dev, "cannot allocate ifnet structure.\n"); 612206625Syongari error = ENOSPC; 613206625Syongari goto fail; 614206625Syongari } 615206625Syongari ifp->if_softc = sc; 616206625Syongari if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 617206625Syongari ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 618206625Syongari ifp->if_ioctl = sge_ioctl; 619206625Syongari ifp->if_start = sge_start; 620206625Syongari ifp->if_init = sge_init; 621206625Syongari ifp->if_snd.ifq_drv_maxlen = SGE_TX_RING_CNT - 1; 622206625Syongari IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 623206625Syongari IFQ_SET_READY(&ifp->if_snd); 624207851Syongari ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_RXCSUM | IFCAP_TSO4; 625207851Syongari ifp->if_hwassist = SGE_CSUM_FEATURES | CSUM_TSO; 626206625Syongari ifp->if_capenable = ifp->if_capabilities; 627206625Syongari /* 628206625Syongari * Do MII setup. 629206625Syongari */ 630206625Syongari if (mii_phy_probe(dev, &sc->sge_miibus, sge_ifmedia_upd, 631206625Syongari sge_ifmedia_sts)) { 632206625Syongari device_printf(dev, "no PHY found!\n"); 633206625Syongari error = ENXIO; 634206625Syongari goto fail; 635206625Syongari } 636206625Syongari 637206625Syongari /* 638206625Syongari * Call MI attach routine. 639206625Syongari */ 640206625Syongari ether_ifattach(ifp, eaddr); 641206625Syongari 642206625Syongari /* VLAN setup. */ 643207852Syongari ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM | 644207852Syongari IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU; 645206625Syongari ifp->if_capenable = ifp->if_capabilities; 646206625Syongari /* Tell the upper layer(s) we support long frames. */ 647206625Syongari ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 648206625Syongari 649206625Syongari /* Hook interrupt last to avoid having to lock softc */ 650206625Syongari error = bus_setup_intr(dev, sc->sge_irq, INTR_TYPE_NET | INTR_MPSAFE, 651206625Syongari NULL, sge_intr, sc, &sc->sge_intrhand); 652206625Syongari if (error) { 653206625Syongari device_printf(dev, "couldn't set up irq\n"); 654206625Syongari ether_ifdetach(ifp); 655206625Syongari goto fail; 656206625Syongari } 657206625Syongari 658206625Syongarifail: 659206625Syongari if (error) 660206625Syongari sge_detach(dev); 661206625Syongari 662206625Syongari return (error); 663206625Syongari} 664206625Syongari 665206625Syongari/* 666206625Syongari * Shutdown hardware and free up resources. This can be called any 667206625Syongari * time after the mutex has been initialized. It is called in both 668206625Syongari * the error case in attach and the normal detach case so it needs 669206625Syongari * to be careful about only freeing resources that have actually been 670206625Syongari * allocated. 671206625Syongari */ 672206625Syongaristatic int 673206625Syongarisge_detach(device_t dev) 674206625Syongari{ 675206625Syongari struct sge_softc *sc; 676206625Syongari struct ifnet *ifp; 677206625Syongari 678206625Syongari sc = device_get_softc(dev); 679206625Syongari ifp = sc->sge_ifp; 680206625Syongari /* These should only be active if attach succeeded. */ 681206625Syongari if (device_is_attached(dev)) { 682206625Syongari ether_ifdetach(ifp); 683206625Syongari SGE_LOCK(sc); 684206625Syongari sge_stop(sc); 685206625Syongari SGE_UNLOCK(sc); 686206625Syongari callout_drain(&sc->sge_stat_ch); 687206625Syongari } 688206625Syongari if (sc->sge_miibus) 689206625Syongari device_delete_child(dev, sc->sge_miibus); 690206625Syongari bus_generic_detach(dev); 691206625Syongari 692206625Syongari if (sc->sge_intrhand) 693206625Syongari bus_teardown_intr(dev, sc->sge_irq, sc->sge_intrhand); 694206625Syongari if (sc->sge_irq) 695206625Syongari bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sge_irq); 696206625Syongari if (sc->sge_res) 697206625Syongari bus_release_resource(dev, sc->sge_res_type, sc->sge_res_id, 698206625Syongari sc->sge_res); 699206625Syongari if (ifp) 700206625Syongari if_free(ifp); 701206625Syongari sge_dma_free(sc); 702206625Syongari mtx_destroy(&sc->sge_mtx); 703206625Syongari 704206625Syongari return (0); 705206625Syongari} 706206625Syongari 707206625Syongari/* 708206625Syongari * Stop all chip I/O so that the kernel's probe routines don't 709206625Syongari * get confused by errant DMAs when rebooting. 710206625Syongari */ 711206625Syongaristatic int 712206625Syongarisge_shutdown(device_t dev) 713206625Syongari{ 714206625Syongari struct sge_softc *sc; 715206625Syongari 716206625Syongari sc = device_get_softc(dev); 717206625Syongari SGE_LOCK(sc); 718206625Syongari sge_stop(sc); 719206625Syongari SGE_UNLOCK(sc); 720206625Syongari return (0); 721206625Syongari} 722206625Syongari 723206625Syongaristatic int 724206625Syongarisge_suspend(device_t dev) 725206625Syongari{ 726206625Syongari struct sge_softc *sc; 727206625Syongari struct ifnet *ifp; 728206625Syongari 729206625Syongari sc = device_get_softc(dev); 730206625Syongari SGE_LOCK(sc); 731206625Syongari ifp = sc->sge_ifp; 732206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 733206625Syongari sge_stop(sc); 734206625Syongari SGE_UNLOCK(sc); 735206625Syongari return (0); 736206625Syongari} 737206625Syongari 738206625Syongaristatic int 739206625Syongarisge_resume(device_t dev) 740206625Syongari{ 741206625Syongari struct sge_softc *sc; 742206625Syongari struct ifnet *ifp; 743206625Syongari 744206625Syongari sc = device_get_softc(dev); 745206625Syongari SGE_LOCK(sc); 746206625Syongari ifp = sc->sge_ifp; 747206625Syongari if ((ifp->if_flags & IFF_UP) != 0) 748206625Syongari sge_init_locked(sc); 749206625Syongari SGE_UNLOCK(sc); 750206625Syongari return (0); 751206625Syongari} 752206625Syongari 753206625Syongaristatic int 754206625Syongarisge_dma_alloc(struct sge_softc *sc) 755206625Syongari{ 756206625Syongari struct sge_chain_data *cd; 757206625Syongari struct sge_list_data *ld; 758207628Syongari struct sge_rxdesc *rxd; 759207628Syongari struct sge_txdesc *txd; 760206625Syongari int error, i; 761206625Syongari 762206625Syongari cd = &sc->sge_cdata; 763206625Syongari ld = &sc->sge_ldata; 764206625Syongari error = bus_dma_tag_create(bus_get_dma_tag(sc->sge_dev), 765206625Syongari 1, 0, /* alignment, boundary */ 766206625Syongari BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 767206625Syongari BUS_SPACE_MAXADDR, /* highaddr */ 768206625Syongari NULL, NULL, /* filter, filterarg */ 769206625Syongari BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 770206625Syongari 1, /* nsegments */ 771206625Syongari BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 772206625Syongari 0, /* flags */ 773206625Syongari NULL, /* lockfunc */ 774206625Syongari NULL, /* lockarg */ 775206625Syongari &cd->sge_tag); 776206625Syongari if (error != 0) { 777206625Syongari device_printf(sc->sge_dev, 778206625Syongari "could not create parent DMA tag.\n"); 779206625Syongari goto fail; 780206625Syongari } 781206625Syongari 782206625Syongari /* RX descriptor ring */ 783206625Syongari error = bus_dma_tag_create(cd->sge_tag, 784206625Syongari SGE_DESC_ALIGN, 0, /* alignment, boundary */ 785206625Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 786206625Syongari BUS_SPACE_MAXADDR, /* highaddr */ 787206625Syongari NULL, NULL, /* filter, filterarg */ 788206625Syongari SGE_RX_RING_SZ, 1, /* maxsize,nsegments */ 789206625Syongari SGE_RX_RING_SZ, /* maxsegsize */ 790206625Syongari 0, /* flags */ 791206625Syongari NULL, /* lockfunc */ 792206625Syongari NULL, /* lockarg */ 793206625Syongari &cd->sge_rx_tag); 794206625Syongari if (error != 0) { 795206625Syongari device_printf(sc->sge_dev, 796206625Syongari "could not create Rx ring DMA tag.\n"); 797206625Syongari goto fail; 798206625Syongari } 799206625Syongari /* Allocate DMA'able memory and load DMA map for RX ring. */ 800206625Syongari error = bus_dmamem_alloc(cd->sge_rx_tag, (void **)&ld->sge_rx_ring, 801206625Syongari BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, 802206625Syongari &cd->sge_rx_dmamap); 803206625Syongari if (error != 0) { 804206625Syongari device_printf(sc->sge_dev, 805206625Syongari "could not allocate DMA'able memory for Rx ring.\n"); 806206625Syongari goto fail; 807206625Syongari } 808206625Syongari error = bus_dmamap_load(cd->sge_rx_tag, cd->sge_rx_dmamap, 809206625Syongari ld->sge_rx_ring, SGE_RX_RING_SZ, sge_dma_map_addr, 810206625Syongari &ld->sge_rx_paddr, BUS_DMA_NOWAIT); 811206625Syongari if (error != 0) { 812206625Syongari device_printf(sc->sge_dev, 813206625Syongari "could not load DMA'able memory for Rx ring.\n"); 814206625Syongari } 815206625Syongari 816206625Syongari /* TX descriptor ring */ 817206625Syongari error = bus_dma_tag_create(cd->sge_tag, 818206625Syongari SGE_DESC_ALIGN, 0, /* alignment, boundary */ 819206625Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 820206625Syongari BUS_SPACE_MAXADDR, /* highaddr */ 821206625Syongari NULL, NULL, /* filter, filterarg */ 822206625Syongari SGE_TX_RING_SZ, 1, /* maxsize,nsegments */ 823206625Syongari SGE_TX_RING_SZ, /* maxsegsize */ 824206625Syongari 0, /* flags */ 825206625Syongari NULL, /* lockfunc */ 826206625Syongari NULL, /* lockarg */ 827206625Syongari &cd->sge_tx_tag); 828206625Syongari if (error != 0) { 829206625Syongari device_printf(sc->sge_dev, 830206625Syongari "could not create Rx ring DMA tag.\n"); 831206625Syongari goto fail; 832206625Syongari } 833206625Syongari /* Allocate DMA'able memory and load DMA map for TX ring. */ 834206625Syongari error = bus_dmamem_alloc(cd->sge_tx_tag, (void **)&ld->sge_tx_ring, 835206625Syongari BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, 836206625Syongari &cd->sge_tx_dmamap); 837206625Syongari if (error != 0) { 838206625Syongari device_printf(sc->sge_dev, 839206625Syongari "could not allocate DMA'able memory for Tx ring.\n"); 840206625Syongari goto fail; 841206625Syongari } 842206625Syongari error = bus_dmamap_load(cd->sge_tx_tag, cd->sge_tx_dmamap, 843206625Syongari ld->sge_tx_ring, SGE_TX_RING_SZ, sge_dma_map_addr, 844206625Syongari &ld->sge_tx_paddr, BUS_DMA_NOWAIT); 845206625Syongari if (error != 0) { 846206625Syongari device_printf(sc->sge_dev, 847206625Syongari "could not load DMA'able memory for Rx ring.\n"); 848206625Syongari goto fail; 849206625Syongari } 850206625Syongari 851206625Syongari /* Create DMA tag for Tx buffers. */ 852206625Syongari error = bus_dma_tag_create(cd->sge_tag, 1, 0, BUS_SPACE_MAXADDR, 853207851Syongari BUS_SPACE_MAXADDR, NULL, NULL, SGE_TSO_MAXSIZE, SGE_MAXTXSEGS, 854207851Syongari SGE_TSO_MAXSEGSIZE, 0, NULL, NULL, &cd->sge_txmbuf_tag); 855206625Syongari if (error != 0) { 856206625Syongari device_printf(sc->sge_dev, 857206625Syongari "could not create Tx mbuf DMA tag.\n"); 858206625Syongari goto fail; 859206625Syongari } 860206625Syongari 861206625Syongari /* Create DMA tag for Rx buffers. */ 862206625Syongari error = bus_dma_tag_create(cd->sge_tag, SGE_RX_BUF_ALIGN, 0, 863206625Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, 864206625Syongari MCLBYTES, 0, NULL, NULL, &cd->sge_rxmbuf_tag); 865206625Syongari if (error != 0) { 866206625Syongari device_printf(sc->sge_dev, 867206625Syongari "could not create Rx mbuf DMA tag.\n"); 868206625Syongari goto fail; 869206625Syongari } 870206625Syongari 871206625Syongari /* Create DMA maps for Tx buffers. */ 872206625Syongari for (i = 0; i < SGE_TX_RING_CNT; i++) { 873207628Syongari txd = &cd->sge_txdesc[i]; 874207628Syongari txd->tx_m = NULL; 875207628Syongari txd->tx_dmamap = NULL; 876207628Syongari txd->tx_ndesc = 0; 877206625Syongari error = bus_dmamap_create(cd->sge_txmbuf_tag, 0, 878207628Syongari &txd->tx_dmamap); 879206625Syongari if (error != 0) { 880206625Syongari device_printf(sc->sge_dev, 881206625Syongari "could not create Tx DMA map.\n"); 882206625Syongari goto fail; 883206625Syongari } 884206625Syongari } 885206625Syongari /* Create spare DMA map for Rx buffer. */ 886206625Syongari error = bus_dmamap_create(cd->sge_rxmbuf_tag, 0, &cd->sge_rx_spare_map); 887206625Syongari if (error != 0) { 888206625Syongari device_printf(sc->sge_dev, 889206625Syongari "could not create spare Rx DMA map.\n"); 890206625Syongari goto fail; 891206625Syongari } 892206625Syongari /* Create DMA maps for Rx buffers. */ 893206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 894207628Syongari rxd = &cd->sge_rxdesc[i]; 895207628Syongari rxd->rx_m = NULL; 896207628Syongari rxd->rx_dmamap = NULL; 897206625Syongari error = bus_dmamap_create(cd->sge_rxmbuf_tag, 0, 898207628Syongari &rxd->rx_dmamap); 899206625Syongari if (error) { 900206625Syongari device_printf(sc->sge_dev, 901206625Syongari "could not create Rx DMA map.\n"); 902206625Syongari goto fail; 903206625Syongari } 904206625Syongari } 905206625Syongarifail: 906206625Syongari return (error); 907206625Syongari} 908206625Syongari 909206625Syongaristatic void 910206625Syongarisge_dma_free(struct sge_softc *sc) 911206625Syongari{ 912206625Syongari struct sge_chain_data *cd; 913206625Syongari struct sge_list_data *ld; 914207628Syongari struct sge_rxdesc *rxd; 915207628Syongari struct sge_txdesc *txd; 916206625Syongari int i; 917206625Syongari 918206625Syongari cd = &sc->sge_cdata; 919206625Syongari ld = &sc->sge_ldata; 920206625Syongari /* Rx ring. */ 921206625Syongari if (cd->sge_rx_tag != NULL) { 922206625Syongari if (cd->sge_rx_dmamap != NULL) 923206625Syongari bus_dmamap_unload(cd->sge_rx_tag, cd->sge_rx_dmamap); 924206625Syongari if (cd->sge_rx_dmamap != NULL && ld->sge_rx_ring != NULL) 925206625Syongari bus_dmamem_free(cd->sge_rx_tag, ld->sge_rx_ring, 926206625Syongari cd->sge_rx_dmamap); 927206625Syongari ld->sge_rx_ring = NULL; 928206625Syongari cd->sge_rx_dmamap = NULL; 929206625Syongari bus_dma_tag_destroy(cd->sge_rx_tag); 930206625Syongari cd->sge_rx_tag = NULL; 931206625Syongari } 932206625Syongari /* Tx ring. */ 933206625Syongari if (cd->sge_tx_tag != NULL) { 934206625Syongari if (cd->sge_tx_dmamap != NULL) 935206625Syongari bus_dmamap_unload(cd->sge_tx_tag, cd->sge_tx_dmamap); 936206625Syongari if (cd->sge_tx_dmamap != NULL && ld->sge_tx_ring != NULL) 937206625Syongari bus_dmamem_free(cd->sge_tx_tag, ld->sge_tx_ring, 938206625Syongari cd->sge_tx_dmamap); 939206625Syongari ld->sge_tx_ring = NULL; 940206625Syongari cd->sge_tx_dmamap = NULL; 941206625Syongari bus_dma_tag_destroy(cd->sge_tx_tag); 942206625Syongari cd->sge_tx_tag = NULL; 943206625Syongari } 944206625Syongari /* Rx buffers. */ 945206625Syongari if (cd->sge_rxmbuf_tag != NULL) { 946206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 947207628Syongari rxd = &cd->sge_rxdesc[i]; 948207628Syongari if (rxd->rx_dmamap != NULL) { 949206625Syongari bus_dmamap_destroy(cd->sge_rxmbuf_tag, 950207628Syongari rxd->rx_dmamap); 951207628Syongari rxd->rx_dmamap = NULL; 952206625Syongari } 953206625Syongari } 954206625Syongari if (cd->sge_rx_spare_map != NULL) { 955206625Syongari bus_dmamap_destroy(cd->sge_rxmbuf_tag, 956206625Syongari cd->sge_rx_spare_map); 957206625Syongari cd->sge_rx_spare_map = NULL; 958206625Syongari } 959206625Syongari bus_dma_tag_destroy(cd->sge_rxmbuf_tag); 960206625Syongari cd->sge_rxmbuf_tag = NULL; 961206625Syongari } 962206625Syongari /* Tx buffers. */ 963206625Syongari if (cd->sge_txmbuf_tag != NULL) { 964206625Syongari for (i = 0; i < SGE_TX_RING_CNT; i++) { 965207628Syongari txd = &cd->sge_txdesc[i]; 966207628Syongari if (txd->tx_dmamap != NULL) { 967206625Syongari bus_dmamap_destroy(cd->sge_txmbuf_tag, 968207628Syongari txd->tx_dmamap); 969207628Syongari txd->tx_dmamap = NULL; 970206625Syongari } 971206625Syongari } 972206625Syongari bus_dma_tag_destroy(cd->sge_txmbuf_tag); 973206625Syongari cd->sge_txmbuf_tag = NULL; 974206625Syongari } 975206625Syongari if (cd->sge_tag != NULL) 976206625Syongari bus_dma_tag_destroy(cd->sge_tag); 977206625Syongari cd->sge_tag = NULL; 978206625Syongari} 979206625Syongari 980206625Syongari/* 981206625Syongari * Initialize the TX descriptors. 982206625Syongari */ 983206625Syongaristatic int 984206625Syongarisge_list_tx_init(struct sge_softc *sc) 985206625Syongari{ 986206625Syongari struct sge_list_data *ld; 987206625Syongari struct sge_chain_data *cd; 988206625Syongari 989206625Syongari SGE_LOCK_ASSERT(sc); 990206625Syongari ld = &sc->sge_ldata; 991206625Syongari cd = &sc->sge_cdata; 992206625Syongari bzero(ld->sge_tx_ring, SGE_TX_RING_SZ); 993206625Syongari ld->sge_tx_ring[SGE_TX_RING_CNT - 1].sge_flags = htole32(RING_END); 994206625Syongari bus_dmamap_sync(cd->sge_tx_tag, cd->sge_tx_dmamap, 995206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 996206625Syongari cd->sge_tx_prod = 0; 997206625Syongari cd->sge_tx_cons = 0; 998206625Syongari cd->sge_tx_cnt = 0; 999206625Syongari return (0); 1000206625Syongari} 1001206625Syongari 1002206625Syongaristatic int 1003206625Syongarisge_list_tx_free(struct sge_softc *sc) 1004206625Syongari{ 1005206625Syongari struct sge_chain_data *cd; 1006207628Syongari struct sge_txdesc *txd; 1007206625Syongari int i; 1008206625Syongari 1009206625Syongari SGE_LOCK_ASSERT(sc); 1010206625Syongari cd = &sc->sge_cdata; 1011206625Syongari for (i = 0; i < SGE_TX_RING_CNT; i++) { 1012207628Syongari txd = &cd->sge_txdesc[i]; 1013207628Syongari if (txd->tx_m != NULL) { 1014207628Syongari bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap, 1015207628Syongari BUS_DMASYNC_POSTWRITE); 1016207628Syongari bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap); 1017207635Syongari m_freem(txd->tx_m); 1018207628Syongari txd->tx_m = NULL; 1019207628Syongari txd->tx_ndesc = 0; 1020206625Syongari } 1021206625Syongari } 1022206625Syongari 1023206625Syongari return (0); 1024206625Syongari} 1025206625Syongari 1026206625Syongari/* 1027206625Syongari * Initialize the RX descriptors and allocate mbufs for them. Note that 1028206625Syongari * we arrange the descriptors in a closed ring, so that the last descriptor 1029206625Syongari * has RING_END flag set. 1030206625Syongari */ 1031206625Syongaristatic int 1032206625Syongarisge_list_rx_init(struct sge_softc *sc) 1033206625Syongari{ 1034206625Syongari struct sge_chain_data *cd; 1035206625Syongari int i; 1036206625Syongari 1037206625Syongari SGE_LOCK_ASSERT(sc); 1038206625Syongari cd = &sc->sge_cdata; 1039206625Syongari cd->sge_rx_cons = 0; 1040206625Syongari bzero(sc->sge_ldata.sge_rx_ring, SGE_RX_RING_SZ); 1041206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 1042206625Syongari if (sge_newbuf(sc, i) != 0) 1043206625Syongari return (ENOBUFS); 1044206625Syongari } 1045206625Syongari bus_dmamap_sync(cd->sge_rx_tag, cd->sge_rx_dmamap, 1046206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1047206625Syongari return (0); 1048206625Syongari} 1049206625Syongari 1050206625Syongaristatic int 1051206625Syongarisge_list_rx_free(struct sge_softc *sc) 1052206625Syongari{ 1053206625Syongari struct sge_chain_data *cd; 1054207628Syongari struct sge_rxdesc *rxd; 1055206625Syongari int i; 1056206625Syongari 1057206625Syongari SGE_LOCK_ASSERT(sc); 1058206625Syongari cd = &sc->sge_cdata; 1059206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 1060207628Syongari rxd = &cd->sge_rxdesc[i]; 1061207628Syongari if (rxd->rx_m != NULL) { 1062207628Syongari bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, 1063206625Syongari BUS_DMASYNC_POSTREAD); 1064206625Syongari bus_dmamap_unload(cd->sge_rxmbuf_tag, 1065207628Syongari rxd->rx_dmamap); 1066207635Syongari m_freem(rxd->rx_m); 1067207628Syongari rxd->rx_m = NULL; 1068206625Syongari } 1069206625Syongari } 1070206625Syongari return (0); 1071206625Syongari} 1072206625Syongari 1073206625Syongari/* 1074206625Syongari * Initialize an RX descriptor and attach an MBUF cluster. 1075206625Syongari */ 1076206625Syongaristatic int 1077206625Syongarisge_newbuf(struct sge_softc *sc, int prod) 1078206625Syongari{ 1079206625Syongari struct mbuf *m; 1080206625Syongari struct sge_desc *desc; 1081206625Syongari struct sge_chain_data *cd; 1082207628Syongari struct sge_rxdesc *rxd; 1083206625Syongari bus_dma_segment_t segs[1]; 1084206625Syongari bus_dmamap_t map; 1085206625Syongari int error, nsegs; 1086206625Syongari 1087206625Syongari SGE_LOCK_ASSERT(sc); 1088206625Syongari 1089206625Syongari cd = &sc->sge_cdata; 1090206625Syongari m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 1091206625Syongari if (m == NULL) 1092206625Syongari return (ENOBUFS); 1093206625Syongari m->m_len = m->m_pkthdr.len = MCLBYTES; 1094206625Syongari m_adj(m, SGE_RX_BUF_ALIGN); 1095206625Syongari error = bus_dmamap_load_mbuf_sg(cd->sge_rxmbuf_tag, 1096206625Syongari cd->sge_rx_spare_map, m, segs, &nsegs, 0); 1097206625Syongari if (error != 0) { 1098206625Syongari m_freem(m); 1099206625Syongari return (error); 1100206625Syongari } 1101206625Syongari KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 1102207628Syongari rxd = &cd->sge_rxdesc[prod]; 1103207628Syongari if (rxd->rx_m != NULL) { 1104207628Syongari bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, 1105206625Syongari BUS_DMASYNC_POSTREAD); 1106207628Syongari bus_dmamap_unload(cd->sge_rxmbuf_tag, rxd->rx_dmamap); 1107206625Syongari } 1108207628Syongari map = rxd->rx_dmamap; 1109207628Syongari rxd->rx_dmamap = cd->sge_rx_spare_map; 1110206625Syongari cd->sge_rx_spare_map = map; 1111207628Syongari bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, 1112206625Syongari BUS_DMASYNC_PREREAD); 1113207628Syongari rxd->rx_m = m; 1114206625Syongari 1115206625Syongari desc = &sc->sge_ldata.sge_rx_ring[prod]; 1116206625Syongari desc->sge_sts_size = 0; 1117206625Syongari desc->sge_ptr = htole32(SGE_ADDR_LO(segs[0].ds_addr)); 1118206625Syongari desc->sge_flags = htole32(segs[0].ds_len); 1119206625Syongari if (prod == SGE_RX_RING_CNT - 1) 1120206625Syongari desc->sge_flags |= htole32(RING_END); 1121206625Syongari desc->sge_cmdsts = htole32(RDC_OWN | RDC_INTR | RDC_IP_CSUM | 1122206625Syongari RDC_TCP_CSUM | RDC_UDP_CSUM); 1123206625Syongari return (0); 1124206625Syongari} 1125206625Syongari 1126206625Syongaristatic __inline void 1127206625Syongarisge_discard_rxbuf(struct sge_softc *sc, int index) 1128206625Syongari{ 1129206625Syongari struct sge_desc *desc; 1130206625Syongari 1131206625Syongari desc = &sc->sge_ldata.sge_rx_ring[index]; 1132206625Syongari desc->sge_sts_size = 0; 1133206625Syongari desc->sge_flags = htole32(MCLBYTES - SGE_RX_BUF_ALIGN); 1134206625Syongari if (index == SGE_RX_RING_CNT - 1) 1135206625Syongari desc->sge_flags |= htole32(RING_END); 1136206625Syongari desc->sge_cmdsts = htole32(RDC_OWN | RDC_INTR | RDC_IP_CSUM | 1137206625Syongari RDC_TCP_CSUM | RDC_UDP_CSUM); 1138206625Syongari} 1139206625Syongari 1140206625Syongari/* 1141206625Syongari * A frame has been uploaded: pass the resulting mbuf chain up to 1142206625Syongari * the higher level protocols. 1143206625Syongari */ 1144206625Syongaristatic void 1145206625Syongarisge_rxeof(struct sge_softc *sc) 1146206625Syongari{ 1147206625Syongari struct ifnet *ifp; 1148206625Syongari struct mbuf *m; 1149206625Syongari struct sge_chain_data *cd; 1150206625Syongari struct sge_desc *cur_rx; 1151206625Syongari uint32_t rxinfo, rxstat; 1152206625Syongari int cons, prog; 1153206625Syongari 1154206625Syongari SGE_LOCK_ASSERT(sc); 1155206625Syongari 1156206625Syongari ifp = sc->sge_ifp; 1157206625Syongari cd = &sc->sge_cdata; 1158206625Syongari 1159206625Syongari bus_dmamap_sync(cd->sge_rx_tag, cd->sge_rx_dmamap, 1160206625Syongari BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1161206625Syongari cons = cd->sge_rx_cons; 1162206625Syongari for (prog = 0; prog < SGE_RX_RING_CNT; prog++, 1163206625Syongari SGE_INC(cons, SGE_RX_RING_CNT)) { 1164206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1165206625Syongari break; 1166206625Syongari cur_rx = &sc->sge_ldata.sge_rx_ring[cons]; 1167206625Syongari rxinfo = le32toh(cur_rx->sge_cmdsts); 1168206625Syongari if ((rxinfo & RDC_OWN) != 0) 1169206625Syongari break; 1170206625Syongari rxstat = le32toh(cur_rx->sge_sts_size); 1171207379Syongari if ((rxstat & RDS_CRCOK) == 0 || SGE_RX_ERROR(rxstat) != 0 || 1172207379Syongari SGE_RX_NSEGS(rxstat) != 1) { 1173206625Syongari /* XXX We don't support multi-segment frames yet. */ 1174206625Syongari#ifdef SGE_SHOW_ERRORS 1175206625Syongari device_printf(sc->sge_dev, "Rx error : 0x%b\n", rxstat, 1176206625Syongari RX_ERR_BITS); 1177206625Syongari#endif 1178206625Syongari sge_discard_rxbuf(sc, cons); 1179206625Syongari ifp->if_ierrors++; 1180206625Syongari continue; 1181206625Syongari } 1182207628Syongari m = cd->sge_rxdesc[cons].rx_m; 1183206625Syongari if (sge_newbuf(sc, cons) != 0) { 1184206625Syongari sge_discard_rxbuf(sc, cons); 1185206625Syongari ifp->if_iqdrops++; 1186206625Syongari continue; 1187206625Syongari } 1188206625Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) { 1189206625Syongari if ((rxinfo & RDC_IP_CSUM) != 0 && 1190206625Syongari (rxinfo & RDC_IP_CSUM_OK) != 0) 1191206625Syongari m->m_pkthdr.csum_flags |= 1192206625Syongari CSUM_IP_CHECKED | CSUM_IP_VALID; 1193206625Syongari if (((rxinfo & RDC_TCP_CSUM) != 0 && 1194206625Syongari (rxinfo & RDC_TCP_CSUM_OK) != 0) || 1195206625Syongari ((rxinfo & RDC_UDP_CSUM) != 0 && 1196206625Syongari (rxinfo & RDC_UDP_CSUM_OK) != 0)) { 1197206625Syongari m->m_pkthdr.csum_flags |= 1198206625Syongari CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 1199206625Syongari m->m_pkthdr.csum_data = 0xffff; 1200206625Syongari } 1201206625Syongari } 1202207380Syongari /* Check for VLAN tagged frame. */ 1203207380Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && 1204207380Syongari (rxstat & RDS_VLAN) != 0) { 1205207380Syongari m->m_pkthdr.ether_vtag = rxinfo & RDC_VLAN_MASK; 1206207380Syongari m->m_flags |= M_VLANTAG; 1207207380Syongari } 1208207852Syongari /* 1209207852Syongari * Account for 10bytes auto padding which is used 1210207852Syongari * to align IP header on 32bit boundary. Also note, 1211207852Syongari * CRC bytes is automatically removed by the 1212207852Syongari * hardware. 1213207852Syongari */ 1214207852Syongari m->m_data += SGE_RX_PAD_BYTES; 1215207852Syongari m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) - 1216207852Syongari SGE_RX_PAD_BYTES; 1217206625Syongari m->m_pkthdr.rcvif = ifp; 1218206625Syongari ifp->if_ipackets++; 1219206625Syongari SGE_UNLOCK(sc); 1220206625Syongari (*ifp->if_input)(ifp, m); 1221206625Syongari SGE_LOCK(sc); 1222206625Syongari } 1223206625Syongari 1224206625Syongari if (prog > 0) { 1225206625Syongari bus_dmamap_sync(cd->sge_rx_tag, cd->sge_rx_dmamap, 1226206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1227206625Syongari cd->sge_rx_cons = cons; 1228206625Syongari } 1229206625Syongari} 1230206625Syongari 1231206625Syongari/* 1232206625Syongari * A frame was downloaded to the chip. It's safe for us to clean up 1233206625Syongari * the list buffers. 1234206625Syongari */ 1235206625Syongaristatic void 1236206625Syongarisge_txeof(struct sge_softc *sc) 1237206625Syongari{ 1238206625Syongari struct ifnet *ifp; 1239206625Syongari struct sge_list_data *ld; 1240206625Syongari struct sge_chain_data *cd; 1241207628Syongari struct sge_txdesc *txd; 1242206625Syongari uint32_t txstat; 1243207628Syongari int cons, nsegs, prod; 1244206625Syongari 1245206625Syongari SGE_LOCK_ASSERT(sc); 1246206625Syongari 1247206625Syongari ifp = sc->sge_ifp; 1248206625Syongari ld = &sc->sge_ldata; 1249206625Syongari cd = &sc->sge_cdata; 1250206625Syongari 1251206625Syongari if (cd->sge_tx_cnt == 0) 1252206625Syongari return; 1253206625Syongari bus_dmamap_sync(cd->sge_tx_tag, cd->sge_tx_dmamap, 1254206625Syongari BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1255206625Syongari cons = cd->sge_tx_cons; 1256206625Syongari prod = cd->sge_tx_prod; 1257207628Syongari for (; cons != prod;) { 1258206625Syongari txstat = le32toh(ld->sge_tx_ring[cons].sge_cmdsts); 1259206625Syongari if ((txstat & TDC_OWN) != 0) 1260206625Syongari break; 1261207628Syongari /* 1262207628Syongari * Only the first descriptor of multi-descriptor transmission 1263207628Syongari * is updated by controller. Driver should skip entire 1264207628Syongari * chained buffers for the transmitted frame. In other words 1265207628Syongari * TDC_OWN bit is valid only at the first descriptor of a 1266207628Syongari * multi-descriptor transmission. 1267207628Syongari */ 1268207628Syongari if (SGE_TX_ERROR(txstat) != 0) { 1269206625Syongari#ifdef SGE_SHOW_ERRORS 1270207628Syongari device_printf(sc->sge_dev, "Tx error : 0x%b\n", 1271207628Syongari txstat, TX_ERR_BITS); 1272206625Syongari#endif 1273207628Syongari ifp->if_oerrors++; 1274207628Syongari } else { 1275206625Syongari#ifdef notyet 1276207628Syongari ifp->if_collisions += (txstat & 0xFFFF) - 1; 1277206625Syongari#endif 1278207628Syongari ifp->if_opackets++; 1279206625Syongari } 1280207628Syongari txd = &cd->sge_txdesc[cons]; 1281207628Syongari for (nsegs = 0; nsegs < txd->tx_ndesc; nsegs++) { 1282207628Syongari ld->sge_tx_ring[cons].sge_cmdsts = 0; 1283207628Syongari SGE_INC(cons, SGE_TX_RING_CNT); 1284207628Syongari } 1285207628Syongari /* Reclaim transmitted mbuf. */ 1286207628Syongari KASSERT(txd->tx_m != NULL, 1287207628Syongari ("%s: freeing NULL mbuf\n", __func__)); 1288207628Syongari bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap, 1289207628Syongari BUS_DMASYNC_POSTWRITE); 1290207628Syongari bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap); 1291207628Syongari m_freem(txd->tx_m); 1292207628Syongari txd->tx_m = NULL; 1293207628Syongari cd->sge_tx_cnt -= txd->tx_ndesc; 1294207628Syongari KASSERT(cd->sge_tx_cnt >= 0, 1295207628Syongari ("%s: Active Tx desc counter was garbled\n", __func__)); 1296207628Syongari txd->tx_ndesc = 0; 1297207628Syongari ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1298206625Syongari } 1299206625Syongari cd->sge_tx_cons = cons; 1300206625Syongari if (cd->sge_tx_cnt == 0) 1301206625Syongari sc->sge_timer = 0; 1302206625Syongari} 1303206625Syongari 1304206625Syongaristatic void 1305206625Syongarisge_tick(void *arg) 1306206625Syongari{ 1307206625Syongari struct sge_softc *sc; 1308206625Syongari struct mii_data *mii; 1309206625Syongari struct ifnet *ifp; 1310206625Syongari 1311206625Syongari sc = arg; 1312206625Syongari SGE_LOCK_ASSERT(sc); 1313206625Syongari 1314206625Syongari ifp = sc->sge_ifp; 1315206625Syongari mii = device_get_softc(sc->sge_miibus); 1316206625Syongari mii_tick(mii); 1317206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0) { 1318206625Syongari sge_miibus_statchg(sc->sge_dev); 1319206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) != 0 && 1320206625Syongari !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1321206625Syongari sge_start_locked(ifp); 1322206625Syongari } 1323206625Syongari /* 1324206625Syongari * Reclaim transmitted frames here as we do not request 1325206625Syongari * Tx completion interrupt for every queued frames to 1326206625Syongari * reduce excessive interrupts. 1327206625Syongari */ 1328206625Syongari sge_txeof(sc); 1329206625Syongari sge_watchdog(sc); 1330206625Syongari callout_reset(&sc->sge_stat_ch, hz, sge_tick, sc); 1331206625Syongari} 1332206625Syongari 1333206625Syongaristatic void 1334206625Syongarisge_intr(void *arg) 1335206625Syongari{ 1336206625Syongari struct sge_softc *sc; 1337206625Syongari struct ifnet *ifp; 1338206625Syongari uint32_t status; 1339206625Syongari 1340206625Syongari sc = arg; 1341206625Syongari SGE_LOCK(sc); 1342206625Syongari ifp = sc->sge_ifp; 1343206625Syongari 1344206625Syongari status = CSR_READ_4(sc, IntrStatus); 1345206625Syongari if (status == 0xFFFFFFFF || (status & SGE_INTRS) == 0) { 1346206625Syongari /* Not ours. */ 1347206625Syongari SGE_UNLOCK(sc); 1348206625Syongari return; 1349206625Syongari } 1350206625Syongari /* Acknowledge interrupts. */ 1351206625Syongari CSR_WRITE_4(sc, IntrStatus, status); 1352206625Syongari /* Disable further interrupts. */ 1353206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 1354206625Syongari /* 1355206625Syongari * It seems the controller supports some kind of interrupt 1356206625Syongari * moderation mechanism but we still don't know how to 1357206625Syongari * enable that. To reduce number of generated interrupts 1358206625Syongari * under load we check pending interrupts in a loop. This 1359206625Syongari * will increase number of register access and is not correct 1360206625Syongari * way to handle interrupt moderation but there seems to be 1361206625Syongari * no other way at this time. 1362206625Syongari */ 1363206625Syongari for (;;) { 1364206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1365206625Syongari break; 1366206625Syongari if ((status & (INTR_RX_DONE | INTR_RX_IDLE)) != 0) { 1367206625Syongari sge_rxeof(sc); 1368206625Syongari /* Wakeup Rx MAC. */ 1369206625Syongari if ((status & INTR_RX_IDLE) != 0) 1370206625Syongari CSR_WRITE_4(sc, RX_CTL, 1371206625Syongari 0x1a00 | 0x000c | RX_CTL_POLL | RX_CTL_ENB); 1372206625Syongari } 1373206625Syongari if ((status & (INTR_TX_DONE | INTR_TX_IDLE)) != 0) 1374206625Syongari sge_txeof(sc); 1375206625Syongari status = CSR_READ_4(sc, IntrStatus); 1376206625Syongari if ((status & SGE_INTRS) == 0) 1377206625Syongari break; 1378206625Syongari /* Acknowledge interrupts. */ 1379206625Syongari CSR_WRITE_4(sc, IntrStatus, status); 1380206625Syongari } 1381206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1382206625Syongari /* Re-enable interrupts */ 1383206625Syongari CSR_WRITE_4(sc, IntrMask, SGE_INTRS); 1384206625Syongari if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1385206625Syongari sge_start_locked(ifp); 1386206625Syongari } 1387206625Syongari SGE_UNLOCK(sc); 1388206625Syongari} 1389206625Syongari 1390206625Syongari/* 1391206625Syongari * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data 1392206625Syongari * pointers to the fragment pointers. 1393206625Syongari */ 1394206625Syongaristatic int 1395206625Syongarisge_encap(struct sge_softc *sc, struct mbuf **m_head) 1396206625Syongari{ 1397206625Syongari struct mbuf *m; 1398206625Syongari struct sge_desc *desc; 1399207628Syongari struct sge_txdesc *txd; 1400206625Syongari bus_dma_segment_t txsegs[SGE_MAXTXSEGS]; 1401207851Syongari uint32_t cflags, mss; 1402207628Syongari int error, i, nsegs, prod, si; 1403206625Syongari 1404206625Syongari SGE_LOCK_ASSERT(sc); 1405206625Syongari 1406207628Syongari si = prod = sc->sge_cdata.sge_tx_prod; 1407207628Syongari txd = &sc->sge_cdata.sge_txdesc[prod]; 1408207851Syongari if (((*m_head)->m_pkthdr.csum_flags & CSUM_TSO) != 0) { 1409207851Syongari struct ether_header *eh; 1410207851Syongari struct ip *ip; 1411207851Syongari struct tcphdr *tcp; 1412207851Syongari uint32_t ip_off, poff; 1413207851Syongari 1414207851Syongari if (M_WRITABLE(*m_head) == 0) { 1415207851Syongari /* Get a writable copy. */ 1416207851Syongari m = m_dup(*m_head, M_DONTWAIT); 1417207851Syongari m_freem(*m_head); 1418207851Syongari if (m == NULL) { 1419207851Syongari *m_head = NULL; 1420207851Syongari return (ENOBUFS); 1421207851Syongari } 1422207851Syongari *m_head = m; 1423207851Syongari } 1424207851Syongari ip_off = sizeof(struct ether_header); 1425207851Syongari m = m_pullup(*m_head, ip_off); 1426207851Syongari if (m == NULL) { 1427207851Syongari *m_head = NULL; 1428207851Syongari return (ENOBUFS); 1429207851Syongari } 1430207851Syongari eh = mtod(m, struct ether_header *); 1431207851Syongari /* Check the existence of VLAN tag. */ 1432207851Syongari if (eh->ether_type == htons(ETHERTYPE_VLAN)) { 1433207851Syongari ip_off = sizeof(struct ether_vlan_header); 1434207851Syongari m = m_pullup(m, ip_off); 1435207851Syongari if (m == NULL) { 1436207851Syongari *m_head = NULL; 1437207851Syongari return (ENOBUFS); 1438207851Syongari } 1439207851Syongari } 1440207851Syongari m = m_pullup(m, ip_off + sizeof(struct ip)); 1441207851Syongari if (m == NULL) { 1442207851Syongari *m_head = NULL; 1443207851Syongari return (ENOBUFS); 1444207851Syongari } 1445207851Syongari ip = (struct ip *)(mtod(m, char *) + ip_off); 1446207851Syongari poff = ip_off + (ip->ip_hl << 2); 1447207851Syongari m = m_pullup(m, poff + sizeof(struct tcphdr)); 1448207851Syongari if (m == NULL) { 1449207851Syongari *m_head = NULL; 1450207851Syongari return (ENOBUFS); 1451207851Syongari } 1452207851Syongari tcp = (struct tcphdr *)(mtod(m, char *) + poff); 1453207851Syongari m = m_pullup(m, poff + (tcp->th_off << 2)); 1454207851Syongari if (m == NULL) { 1455207851Syongari *m_head = NULL; 1456207851Syongari return (ENOBUFS); 1457207851Syongari } 1458207851Syongari /* 1459207851Syongari * Reset IP checksum and recompute TCP pseudo 1460207851Syongari * checksum that NDIS specification requires. 1461207851Syongari */ 1462207851Syongari ip->ip_sum = 0; 1463207851Syongari tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, 1464207851Syongari htons(IPPROTO_TCP)); 1465207851Syongari *m_head = m; 1466207851Syongari } 1467207851Syongari 1468207628Syongari error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, 1469207628Syongari txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); 1470207628Syongari if (error == EFBIG) { 1471207628Syongari m = m_collapse(*m_head, M_DONTWAIT, SGE_MAXTXSEGS); 1472206625Syongari if (m == NULL) { 1473206625Syongari m_freem(*m_head); 1474206625Syongari *m_head = NULL; 1475206625Syongari return (ENOBUFS); 1476206625Syongari } 1477206625Syongari *m_head = m; 1478207628Syongari error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, 1479207628Syongari txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); 1480207628Syongari if (error != 0) { 1481207628Syongari m_freem(*m_head); 1482207628Syongari *m_head = NULL; 1483207628Syongari return (error); 1484207628Syongari } 1485207628Syongari } else if (error != 0) 1486206625Syongari return (error); 1487207628Syongari 1488207628Syongari KASSERT(nsegs != 0, ("zero segment returned")); 1489206625Syongari /* Check descriptor overrun. */ 1490206625Syongari if (sc->sge_cdata.sge_tx_cnt + nsegs >= SGE_TX_RING_CNT) { 1491207628Syongari bus_dmamap_unload(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap); 1492206625Syongari return (ENOBUFS); 1493206625Syongari } 1494207628Syongari bus_dmamap_sync(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap, 1495207545Syongari BUS_DMASYNC_PREWRITE); 1496206625Syongari 1497207628Syongari m = *m_head; 1498206625Syongari cflags = 0; 1499207851Syongari mss = 0; 1500207851Syongari if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) { 1501207851Syongari cflags |= TDC_LS; 1502207851Syongari mss = (uint32_t)m->m_pkthdr.tso_segsz; 1503207851Syongari mss <<= 16; 1504207851Syongari } else { 1505207851Syongari if (m->m_pkthdr.csum_flags & CSUM_IP) 1506207851Syongari cflags |= TDC_IP_CSUM; 1507207851Syongari if (m->m_pkthdr.csum_flags & CSUM_TCP) 1508207851Syongari cflags |= TDC_TCP_CSUM; 1509207851Syongari if (m->m_pkthdr.csum_flags & CSUM_UDP) 1510207851Syongari cflags |= TDC_UDP_CSUM; 1511207851Syongari } 1512207628Syongari for (i = 0; i < nsegs; i++) { 1513207628Syongari desc = &sc->sge_ldata.sge_tx_ring[prod]; 1514207628Syongari if (i == 0) { 1515207851Syongari desc->sge_sts_size = htole32(m->m_pkthdr.len | mss); 1516207628Syongari desc->sge_cmdsts = 0; 1517207628Syongari } else { 1518207628Syongari desc->sge_sts_size = 0; 1519207628Syongari desc->sge_cmdsts = htole32(TDC_OWN); 1520207628Syongari } 1521207628Syongari desc->sge_ptr = htole32(SGE_ADDR_LO(txsegs[i].ds_addr)); 1522207628Syongari desc->sge_flags = htole32(txsegs[i].ds_len); 1523207628Syongari if (prod == SGE_TX_RING_CNT - 1) 1524207628Syongari desc->sge_flags |= htole32(RING_END); 1525207628Syongari sc->sge_cdata.sge_tx_cnt++; 1526207628Syongari SGE_INC(prod, SGE_TX_RING_CNT); 1527207628Syongari } 1528207628Syongari /* Update producer index. */ 1529207628Syongari sc->sge_cdata.sge_tx_prod = prod; 1530207628Syongari 1531207628Syongari desc = &sc->sge_ldata.sge_tx_ring[si]; 1532207380Syongari /* Configure VLAN. */ 1533207628Syongari if((m->m_flags & M_VLANTAG) != 0) { 1534207628Syongari cflags |= m->m_pkthdr.ether_vtag; 1535207380Syongari desc->sge_sts_size |= htole32(TDS_INS_VLAN); 1536207380Syongari } 1537207628Syongari desc->sge_cmdsts |= htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags); 1538206625Syongari#if 1 1539206625Syongari if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0) 1540206625Syongari desc->sge_cmdsts |= htole32(TDC_BST); 1541206625Syongari#else 1542206625Syongari if ((sc->sge_flags & SGE_FLAG_FDX) == 0) { 1543206625Syongari desc->sge_cmdsts |= htole32(TDC_COL | TDC_CRS | TDC_BKF); 1544206625Syongari if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0) 1545206625Syongari desc->sge_cmdsts |= htole32(TDC_EXT | TDC_BST); 1546206625Syongari } 1547206625Syongari#endif 1548206625Syongari /* Request interrupt and give ownership to controller. */ 1549207628Syongari desc->sge_cmdsts |= htole32(TDC_OWN | TDC_INTR); 1550207628Syongari txd->tx_m = m; 1551207628Syongari txd->tx_ndesc = nsegs; 1552206625Syongari return (0); 1553206625Syongari} 1554206625Syongari 1555206625Syongaristatic void 1556206625Syongarisge_start(struct ifnet *ifp) 1557206625Syongari{ 1558206625Syongari struct sge_softc *sc; 1559206625Syongari 1560206625Syongari sc = ifp->if_softc; 1561206625Syongari SGE_LOCK(sc); 1562206625Syongari sge_start_locked(ifp); 1563206625Syongari SGE_UNLOCK(sc); 1564206625Syongari} 1565206625Syongari 1566206625Syongaristatic void 1567206625Syongarisge_start_locked(struct ifnet *ifp) 1568206625Syongari{ 1569206625Syongari struct sge_softc *sc; 1570206625Syongari struct mbuf *m_head; 1571206625Syongari int queued = 0; 1572206625Syongari 1573206625Syongari sc = ifp->if_softc; 1574206625Syongari SGE_LOCK_ASSERT(sc); 1575206625Syongari 1576206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0 || 1577206625Syongari (ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1578206625Syongari IFF_DRV_RUNNING) 1579206625Syongari return; 1580206625Syongari 1581206625Syongari for (queued = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) { 1582207628Syongari if (sc->sge_cdata.sge_tx_cnt > (SGE_TX_RING_CNT - 1583207628Syongari SGE_MAXTXSEGS)) { 1584206625Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1585206625Syongari break; 1586206625Syongari } 1587206625Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 1588206625Syongari if (m_head == NULL) 1589206625Syongari break; 1590206625Syongari if (sge_encap(sc, &m_head)) { 1591208806Syongari if (m_head == NULL) 1592208806Syongari break; 1593208806Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 1594206625Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1595206625Syongari break; 1596206625Syongari } 1597206625Syongari queued++; 1598206625Syongari /* 1599206625Syongari * If there's a BPF listener, bounce a copy of this frame 1600206625Syongari * to him. 1601206625Syongari */ 1602206625Syongari BPF_MTAP(ifp, m_head); 1603206625Syongari } 1604206625Syongari 1605206625Syongari if (queued > 0) { 1606206625Syongari bus_dmamap_sync(sc->sge_cdata.sge_tx_tag, 1607206625Syongari sc->sge_cdata.sge_tx_dmamap, 1608206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1609206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00 | TX_CTL_ENB | TX_CTL_POLL); 1610206625Syongari sc->sge_timer = 5; 1611206625Syongari } 1612206625Syongari} 1613206625Syongari 1614206625Syongaristatic void 1615206625Syongarisge_init(void *arg) 1616206625Syongari{ 1617206625Syongari struct sge_softc *sc; 1618206625Syongari 1619206625Syongari sc = arg; 1620206625Syongari SGE_LOCK(sc); 1621206625Syongari sge_init_locked(sc); 1622206625Syongari SGE_UNLOCK(sc); 1623206625Syongari} 1624206625Syongari 1625206625Syongaristatic void 1626206625Syongarisge_init_locked(struct sge_softc *sc) 1627206625Syongari{ 1628206625Syongari struct ifnet *ifp; 1629206625Syongari struct mii_data *mii; 1630207379Syongari uint16_t rxfilt; 1631206625Syongari int i; 1632206625Syongari 1633206625Syongari SGE_LOCK_ASSERT(sc); 1634206625Syongari ifp = sc->sge_ifp; 1635206625Syongari mii = device_get_softc(sc->sge_miibus); 1636206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1637206625Syongari return; 1638206625Syongari /* 1639206625Syongari * Cancel pending I/O and free all RX/TX buffers. 1640206625Syongari */ 1641206625Syongari sge_stop(sc); 1642206625Syongari sge_reset(sc); 1643206625Syongari 1644206625Syongari /* Init circular RX list. */ 1645206625Syongari if (sge_list_rx_init(sc) == ENOBUFS) { 1646206625Syongari device_printf(sc->sge_dev, "no memory for Rx buffers\n"); 1647206625Syongari sge_stop(sc); 1648206625Syongari return; 1649206625Syongari } 1650206625Syongari /* Init TX descriptors. */ 1651206625Syongari sge_list_tx_init(sc); 1652206625Syongari /* 1653206625Syongari * Load the address of the RX and TX lists. 1654206625Syongari */ 1655206625Syongari CSR_WRITE_4(sc, TX_DESC, SGE_ADDR_LO(sc->sge_ldata.sge_tx_paddr)); 1656206625Syongari CSR_WRITE_4(sc, RX_DESC, SGE_ADDR_LO(sc->sge_ldata.sge_rx_paddr)); 1657206625Syongari 1658206625Syongari CSR_WRITE_4(sc, TxMacControl, 0x60); 1659206625Syongari CSR_WRITE_4(sc, RxWakeOnLan, 0); 1660206625Syongari CSR_WRITE_4(sc, RxWakeOnLanData, 0); 1661206625Syongari /* Allow receiving VLAN frames. */ 1662207852Syongari CSR_WRITE_2(sc, RxMPSControl, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN + 1663207852Syongari SGE_RX_PAD_BYTES); 1664206625Syongari 1665206625Syongari for (i = 0; i < ETHER_ADDR_LEN; i++) 1666206625Syongari CSR_WRITE_1(sc, RxMacAddr + i, IF_LLADDR(ifp)[i]); 1667207379Syongari /* Configure RX MAC. */ 1668207852Syongari rxfilt = RXMAC_STRIP_FCS | RXMAC_PAD_ENB; 1669207379Syongari CSR_WRITE_2(sc, RxMacControl, rxfilt); 1670206625Syongari sge_rxfilter(sc); 1671207380Syongari sge_setvlan(sc); 1672206625Syongari 1673206625Syongari /* Initialize default speed/duplex information. */ 1674206625Syongari if ((sc->sge_flags & SGE_FLAG_FASTETHER) == 0) 1675206625Syongari sc->sge_flags |= SGE_FLAG_SPEED_1000; 1676206625Syongari sc->sge_flags |= SGE_FLAG_FDX; 1677206625Syongari if ((sc->sge_flags & SGE_FLAG_RGMII) != 0) 1678206625Syongari CSR_WRITE_4(sc, StationControl, 0x04008001); 1679206625Syongari else 1680206625Syongari CSR_WRITE_4(sc, StationControl, 0x04000001); 1681206625Syongari /* 1682206625Syongari * XXX Try to mitigate interrupts. 1683206625Syongari */ 1684207071Syongari CSR_WRITE_4(sc, IntrControl, 0x08880000); 1685207071Syongari#ifdef notyet 1686206625Syongari if (sc->sge_intrcontrol != 0) 1687206625Syongari CSR_WRITE_4(sc, IntrControl, sc->sge_intrcontrol); 1688206625Syongari if (sc->sge_intrtimer != 0) 1689206625Syongari CSR_WRITE_4(sc, IntrTimer, sc->sge_intrtimer); 1690207071Syongari#endif 1691206625Syongari 1692206625Syongari /* 1693206625Syongari * Clear and enable interrupts. 1694206625Syongari */ 1695206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xFFFFFFFF); 1696206625Syongari CSR_WRITE_4(sc, IntrMask, SGE_INTRS); 1697206625Syongari 1698206625Syongari /* Enable receiver and transmitter. */ 1699206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00 | TX_CTL_ENB); 1700206625Syongari CSR_WRITE_4(sc, RX_CTL, 0x1a00 | 0x000c | RX_CTL_POLL | RX_CTL_ENB); 1701206625Syongari 1702206625Syongari ifp->if_drv_flags |= IFF_DRV_RUNNING; 1703206625Syongari ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1704206625Syongari 1705206625Syongari sc->sge_flags &= ~SGE_FLAG_LINK; 1706206625Syongari mii_mediachg(mii); 1707206625Syongari callout_reset(&sc->sge_stat_ch, hz, sge_tick, sc); 1708206625Syongari} 1709206625Syongari 1710206625Syongari/* 1711206625Syongari * Set media options. 1712206625Syongari */ 1713206625Syongaristatic int 1714206625Syongarisge_ifmedia_upd(struct ifnet *ifp) 1715206625Syongari{ 1716206625Syongari struct sge_softc *sc; 1717206625Syongari struct mii_data *mii; 1718206625Syongari int error; 1719206625Syongari 1720206625Syongari sc = ifp->if_softc; 1721206625Syongari SGE_LOCK(sc); 1722206625Syongari mii = device_get_softc(sc->sge_miibus); 1723206625Syongari if (mii->mii_instance) { 1724206625Syongari struct mii_softc *miisc; 1725206625Syongari LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 1726206625Syongari mii_phy_reset(miisc); 1727206625Syongari } 1728206625Syongari error = mii_mediachg(mii); 1729206625Syongari SGE_UNLOCK(sc); 1730206625Syongari 1731206625Syongari return (error); 1732206625Syongari} 1733206625Syongari 1734206625Syongari/* 1735206625Syongari * Report current media status. 1736206625Syongari */ 1737206625Syongaristatic void 1738206625Syongarisge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 1739206625Syongari{ 1740206625Syongari struct sge_softc *sc; 1741206625Syongari struct mii_data *mii; 1742206625Syongari 1743206625Syongari sc = ifp->if_softc; 1744206625Syongari SGE_LOCK(sc); 1745206625Syongari mii = device_get_softc(sc->sge_miibus); 1746206625Syongari if ((ifp->if_flags & IFF_UP) == 0) { 1747206625Syongari SGE_UNLOCK(sc); 1748206625Syongari return; 1749206625Syongari } 1750206625Syongari mii_pollstat(mii); 1751206625Syongari SGE_UNLOCK(sc); 1752206625Syongari ifmr->ifm_active = mii->mii_media_active; 1753206625Syongari ifmr->ifm_status = mii->mii_media_status; 1754206625Syongari} 1755206625Syongari 1756206625Syongaristatic int 1757206625Syongarisge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 1758206625Syongari{ 1759206625Syongari struct sge_softc *sc; 1760206625Syongari struct ifreq *ifr; 1761206625Syongari struct mii_data *mii; 1762207380Syongari int error = 0, mask, reinit; 1763206625Syongari 1764206625Syongari sc = ifp->if_softc; 1765206625Syongari ifr = (struct ifreq *)data; 1766206625Syongari 1767206625Syongari switch(command) { 1768206625Syongari case SIOCSIFFLAGS: 1769206625Syongari SGE_LOCK(sc); 1770206625Syongari if ((ifp->if_flags & IFF_UP) != 0) { 1771206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 1772206625Syongari ((ifp->if_flags ^ sc->sge_if_flags) & 1773206625Syongari (IFF_PROMISC | IFF_ALLMULTI)) != 0) 1774206625Syongari sge_rxfilter(sc); 1775206625Syongari else 1776206625Syongari sge_init_locked(sc); 1777206625Syongari } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1778206625Syongari sge_stop(sc); 1779206625Syongari sc->sge_if_flags = ifp->if_flags; 1780206625Syongari SGE_UNLOCK(sc); 1781206625Syongari break; 1782206625Syongari case SIOCSIFCAP: 1783206625Syongari SGE_LOCK(sc); 1784207380Syongari reinit = 0; 1785206625Syongari mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1786206625Syongari if ((mask & IFCAP_TXCSUM) != 0 && 1787206625Syongari (ifp->if_capabilities & IFCAP_TXCSUM) != 0) { 1788206625Syongari ifp->if_capenable ^= IFCAP_TXCSUM; 1789206625Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 1790206625Syongari ifp->if_hwassist |= SGE_CSUM_FEATURES; 1791206625Syongari else 1792206625Syongari ifp->if_hwassist &= ~SGE_CSUM_FEATURES; 1793206625Syongari } 1794206625Syongari if ((mask & IFCAP_RXCSUM) != 0 && 1795206625Syongari (ifp->if_capabilities & IFCAP_RXCSUM) != 0) 1796206625Syongari ifp->if_capenable ^= IFCAP_RXCSUM; 1797207380Syongari if ((mask & IFCAP_VLAN_HWCSUM) != 0 && 1798207380Syongari (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0) 1799207380Syongari ifp->if_capenable ^= IFCAP_VLAN_HWCSUM; 1800207851Syongari if ((mask & IFCAP_TSO4) != 0 && 1801207851Syongari (ifp->if_capabilities & IFCAP_TSO4) != 0) { 1802207851Syongari ifp->if_capenable ^= IFCAP_TSO4; 1803207851Syongari if ((ifp->if_capenable & IFCAP_TSO4) != 0) 1804207851Syongari ifp->if_hwassist |= CSUM_TSO; 1805207851Syongari else 1806207851Syongari ifp->if_hwassist &= ~CSUM_TSO; 1807207851Syongari } 1808207851Syongari if ((mask & IFCAP_VLAN_HWTSO) != 0 && 1809207851Syongari (ifp->if_capabilities & IFCAP_VLAN_HWTSO) != 0) 1810207851Syongari ifp->if_capenable ^= IFCAP_VLAN_HWTSO; 1811207380Syongari if ((mask & IFCAP_VLAN_HWTAGGING) != 0 && 1812207380Syongari (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) { 1813207380Syongari /* 1814207380Syongari * Due to unknown reason, toggling VLAN hardware 1815207380Syongari * tagging require interface reinitialization. 1816207380Syongari */ 1817207380Syongari ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 1818207851Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) == 0) 1819207851Syongari ifp->if_capenable &= 1820207851Syongari ~(IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM); 1821207380Syongari reinit = 1; 1822207380Syongari } 1823207380Syongari if (reinit > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1824207380Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1825207380Syongari sge_init_locked(sc); 1826207380Syongari } 1827206625Syongari SGE_UNLOCK(sc); 1828207380Syongari VLAN_CAPABILITIES(ifp); 1829206625Syongari break; 1830206625Syongari case SIOCADDMULTI: 1831206625Syongari case SIOCDELMULTI: 1832206625Syongari SGE_LOCK(sc); 1833206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1834206625Syongari sge_rxfilter(sc); 1835206625Syongari SGE_UNLOCK(sc); 1836206625Syongari break; 1837206625Syongari case SIOCGIFMEDIA: 1838206625Syongari case SIOCSIFMEDIA: 1839206625Syongari mii = device_get_softc(sc->sge_miibus); 1840206625Syongari error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 1841206625Syongari break; 1842206625Syongari default: 1843206625Syongari error = ether_ioctl(ifp, command, data); 1844206625Syongari break; 1845206625Syongari } 1846206625Syongari 1847206625Syongari return (error); 1848206625Syongari} 1849206625Syongari 1850206625Syongaristatic void 1851206625Syongarisge_watchdog(struct sge_softc *sc) 1852206625Syongari{ 1853206625Syongari struct ifnet *ifp; 1854206625Syongari 1855206625Syongari SGE_LOCK_ASSERT(sc); 1856206625Syongari if (sc->sge_timer == 0 || --sc->sge_timer > 0) 1857206625Syongari return; 1858206625Syongari 1859206625Syongari ifp = sc->sge_ifp; 1860206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0) { 1861206625Syongari if (1 || bootverbose) 1862206625Syongari device_printf(sc->sge_dev, 1863206625Syongari "watchdog timeout (lost link)\n"); 1864206625Syongari ifp->if_oerrors++; 1865206625Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1866206625Syongari sge_init_locked(sc); 1867206625Syongari return; 1868206625Syongari } 1869206625Syongari device_printf(sc->sge_dev, "watchdog timeout\n"); 1870206625Syongari ifp->if_oerrors++; 1871206625Syongari 1872206625Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1873206625Syongari sge_init_locked(sc); 1874206625Syongari if (!IFQ_DRV_IS_EMPTY(&sc->sge_ifp->if_snd)) 1875206625Syongari sge_start_locked(ifp); 1876206625Syongari} 1877206625Syongari 1878206625Syongari/* 1879206625Syongari * Stop the adapter and free any mbufs allocated to the 1880206625Syongari * RX and TX lists. 1881206625Syongari */ 1882206625Syongaristatic void 1883206625Syongarisge_stop(struct sge_softc *sc) 1884206625Syongari{ 1885206625Syongari struct ifnet *ifp; 1886206625Syongari 1887206625Syongari ifp = sc->sge_ifp; 1888206625Syongari 1889206625Syongari SGE_LOCK_ASSERT(sc); 1890206625Syongari 1891206625Syongari sc->sge_timer = 0; 1892206625Syongari callout_stop(&sc->sge_stat_ch); 1893206625Syongari ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1894206625Syongari 1895206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 1896206625Syongari CSR_READ_4(sc, IntrMask); 1897206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 1898206625Syongari /* Stop TX/RX MAC. */ 1899206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00); 1900206625Syongari CSR_WRITE_4(sc, RX_CTL, 0x1a00); 1901206625Syongari /* XXX Can we assume active DMA cycles gone? */ 1902206625Syongari DELAY(2000); 1903206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 1904206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 1905206625Syongari 1906206625Syongari sc->sge_flags &= ~SGE_FLAG_LINK; 1907206625Syongari sge_list_rx_free(sc); 1908206625Syongari sge_list_tx_free(sc); 1909206625Syongari} 1910