if_sge.c revision 207628
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 207628 2010-05-04 19:04:51Z 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 75206625Syongari#include <machine/bus.h> 76206625Syongari#include <machine/resource.h> 77206625Syongari 78206625Syongari#include <dev/mii/mii.h> 79206625Syongari#include <dev/mii/miivar.h> 80206625Syongari 81206625Syongari#include <dev/pci/pcireg.h> 82206625Syongari#include <dev/pci/pcivar.h> 83206625Syongari 84206672Syongari#include <dev/sge/if_sgereg.h> 85206625Syongari 86206625SyongariMODULE_DEPEND(sge, pci, 1, 1, 1); 87206625SyongariMODULE_DEPEND(sge, ether, 1, 1, 1); 88206625SyongariMODULE_DEPEND(sge, miibus, 1, 1, 1); 89206625Syongari 90206625Syongari/* "device miibus0" required. See GENERIC if you get errors here. */ 91206625Syongari#include "miibus_if.h" 92206625Syongari 93206625Syongari/* 94206625Syongari * Various supported device vendors/types and their names. 95206625Syongari */ 96206625Syongaristatic struct sge_type sge_devs[] = { 97206625Syongari { SIS_VENDORID, SIS_DEVICEID_190, "SiS190 Fast Ethernet" }, 98206625Syongari { SIS_VENDORID, SIS_DEVICEID_191, "SiS191 Fast/Gigabit Ethernet" }, 99206625Syongari { 0, 0, NULL } 100206625Syongari}; 101206625Syongari 102206625Syongaristatic int sge_probe(device_t); 103206625Syongaristatic int sge_attach(device_t); 104206625Syongaristatic int sge_detach(device_t); 105206625Syongaristatic int sge_shutdown(device_t); 106206625Syongaristatic int sge_suspend(device_t); 107206625Syongaristatic int sge_resume(device_t); 108206625Syongari 109206625Syongaristatic int sge_miibus_readreg(device_t, int, int); 110206625Syongaristatic int sge_miibus_writereg(device_t, int, int, int); 111206625Syongaristatic void sge_miibus_statchg(device_t); 112206625Syongari 113206625Syongaristatic int sge_newbuf(struct sge_softc *, int); 114206625Syongaristatic int sge_encap(struct sge_softc *, struct mbuf **); 115206625Syongari#ifndef __NO_STRICT_ALIGNMENT 116206625Syongaristatic __inline void 117206625Syongari sge_fixup_rx(struct mbuf *); 118206625Syongari#endif 119206625Syongaristatic __inline void 120206625Syongari sge_discard_rxbuf(struct sge_softc *, int); 121206625Syongaristatic void sge_rxeof(struct sge_softc *); 122206625Syongaristatic void sge_txeof(struct sge_softc *); 123206625Syongaristatic void sge_intr(void *); 124206625Syongaristatic void sge_tick(void *); 125206625Syongaristatic void sge_start(struct ifnet *); 126206625Syongaristatic void sge_start_locked(struct ifnet *); 127206625Syongaristatic int sge_ioctl(struct ifnet *, u_long, caddr_t); 128206625Syongaristatic void sge_init(void *); 129206625Syongaristatic void sge_init_locked(struct sge_softc *); 130206625Syongaristatic void sge_stop(struct sge_softc *); 131206625Syongaristatic void sge_watchdog(struct sge_softc *); 132206625Syongaristatic int sge_ifmedia_upd(struct ifnet *); 133206625Syongaristatic void sge_ifmedia_sts(struct ifnet *, struct ifmediareq *); 134206625Syongari 135206625Syongaristatic int sge_get_mac_addr_apc(struct sge_softc *, uint8_t *); 136206625Syongaristatic int sge_get_mac_addr_eeprom(struct sge_softc *, uint8_t *); 137206625Syongaristatic uint16_t sge_read_eeprom(struct sge_softc *, int); 138206625Syongari 139206625Syongaristatic void sge_rxfilter(struct sge_softc *); 140207380Syongaristatic void sge_setvlan(struct sge_softc *); 141206625Syongaristatic void sge_reset(struct sge_softc *); 142206625Syongaristatic int sge_list_rx_init(struct sge_softc *); 143206625Syongaristatic int sge_list_rx_free(struct sge_softc *); 144206625Syongaristatic int sge_list_tx_init(struct sge_softc *); 145206625Syongaristatic int sge_list_tx_free(struct sge_softc *); 146206625Syongari 147206625Syongaristatic int sge_dma_alloc(struct sge_softc *); 148206625Syongaristatic void sge_dma_free(struct sge_softc *); 149206625Syongaristatic void sge_dma_map_addr(void *, bus_dma_segment_t *, int, int); 150206625Syongari 151206625Syongaristatic device_method_t sge_methods[] = { 152206625Syongari /* Device interface */ 153206625Syongari DEVMETHOD(device_probe, sge_probe), 154206625Syongari DEVMETHOD(device_attach, sge_attach), 155206625Syongari DEVMETHOD(device_detach, sge_detach), 156206625Syongari DEVMETHOD(device_suspend, sge_suspend), 157206625Syongari DEVMETHOD(device_resume, sge_resume), 158206625Syongari DEVMETHOD(device_shutdown, sge_shutdown), 159206625Syongari 160206625Syongari /* Bus interface */ 161206625Syongari DEVMETHOD(bus_print_child, bus_generic_print_child), 162206625Syongari DEVMETHOD(bus_driver_added, bus_generic_driver_added), 163206625Syongari 164206625Syongari /* MII interface */ 165206625Syongari DEVMETHOD(miibus_readreg, sge_miibus_readreg), 166206625Syongari DEVMETHOD(miibus_writereg, sge_miibus_writereg), 167206625Syongari DEVMETHOD(miibus_statchg, sge_miibus_statchg), 168206625Syongari 169206625Syongari KOBJMETHOD_END 170206625Syongari}; 171206625Syongari 172206625Syongaristatic driver_t sge_driver = { 173206625Syongari "sge", sge_methods, sizeof(struct sge_softc) 174206625Syongari}; 175206625Syongari 176206625Syongaristatic devclass_t sge_devclass; 177206625Syongari 178206625SyongariDRIVER_MODULE(sge, pci, sge_driver, sge_devclass, 0, 0); 179206625SyongariDRIVER_MODULE(miibus, sge, miibus_driver, miibus_devclass, 0, 0); 180206625Syongari 181206625Syongari/* 182206625Syongari * Register space access macros. 183206625Syongari */ 184206625Syongari#define CSR_WRITE_4(sc, reg, val) bus_write_4(sc->sge_res, reg, val) 185206625Syongari#define CSR_WRITE_2(sc, reg, val) bus_write_2(sc->sge_res, reg, val) 186206625Syongari#define CSR_WRITE_1(cs, reg, val) bus_write_1(sc->sge_res, reg, val) 187206625Syongari 188206625Syongari#define CSR_READ_4(sc, reg) bus_read_4(sc->sge_res, reg) 189206625Syongari#define CSR_READ_2(sc, reg) bus_read_2(sc->sge_res, reg) 190206625Syongari#define CSR_READ_1(sc, reg) bus_read_1(sc->sge_res, reg) 191206625Syongari 192206625Syongari/* Define to show Tx/Rx error status. */ 193206625Syongari#undef SGE_SHOW_ERRORS 194206625Syongari 195206625Syongari#define SGE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 196206625Syongari 197206625Syongaristatic void 198206625Syongarisge_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 199206625Syongari{ 200206625Syongari bus_addr_t *p; 201206625Syongari 202206625Syongari if (error != 0) 203206625Syongari return; 204206625Syongari KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 205206625Syongari p = arg; 206206625Syongari *p = segs->ds_addr; 207206625Syongari} 208206625Syongari 209206625Syongari/* 210206625Syongari * Read a sequence of words from the EEPROM. 211206625Syongari */ 212206625Syongaristatic uint16_t 213206625Syongarisge_read_eeprom(struct sge_softc *sc, int offset) 214206625Syongari{ 215206625Syongari uint32_t val; 216206625Syongari int i; 217206625Syongari 218206625Syongari KASSERT(offset <= EI_OFFSET, ("EEPROM offset too big")); 219206625Syongari CSR_WRITE_4(sc, ROMInterface, 220206625Syongari EI_REQ | EI_OP_RD | (offset << EI_OFFSET_SHIFT)); 221206625Syongari DELAY(500); 222206625Syongari for (i = 0; i < SGE_TIMEOUT; i++) { 223206625Syongari val = CSR_READ_4(sc, ROMInterface); 224206625Syongari if ((val & EI_REQ) == 0) 225206625Syongari break; 226206625Syongari DELAY(100); 227206625Syongari } 228206625Syongari if (i == SGE_TIMEOUT) { 229206625Syongari device_printf(sc->sge_dev, 230206625Syongari "EEPROM read timeout : 0x%08x\n", val); 231206625Syongari return (0xffff); 232206625Syongari } 233206625Syongari 234206625Syongari return ((val & EI_DATA) >> EI_DATA_SHIFT); 235206625Syongari} 236206625Syongari 237206625Syongaristatic int 238206625Syongarisge_get_mac_addr_eeprom(struct sge_softc *sc, uint8_t *dest) 239206625Syongari{ 240206625Syongari uint16_t val; 241206625Syongari int i; 242206625Syongari 243206625Syongari val = sge_read_eeprom(sc, EEPROMSignature); 244206625Syongari if (val == 0xffff || val == 0) { 245206625Syongari device_printf(sc->sge_dev, 246206625Syongari "invalid EEPROM signature : 0x%04x\n", val); 247206625Syongari return (EINVAL); 248206625Syongari } 249206625Syongari 250206625Syongari for (i = 0; i < ETHER_ADDR_LEN; i += 2) { 251206625Syongari val = sge_read_eeprom(sc, EEPROMMACAddr + i / 2); 252206625Syongari dest[i + 0] = (uint8_t)val; 253206625Syongari dest[i + 1] = (uint8_t)(val >> 8); 254206625Syongari } 255206625Syongari 256206625Syongari if ((sge_read_eeprom(sc, EEPROMInfo) & 0x80) != 0) 257206625Syongari sc->sge_flags |= SGE_FLAG_RGMII; 258206625Syongari return (0); 259206625Syongari} 260206625Syongari 261206625Syongari/* 262206625Syongari * For SiS96x, APC CMOS RAM is used to store ethernet address. 263206625Syongari * APC CMOS RAM is accessed through ISA bridge. 264206625Syongari */ 265206625Syongaristatic int 266206625Syongarisge_get_mac_addr_apc(struct sge_softc *sc, uint8_t *dest) 267206625Syongari{ 268206625Syongari#if defined(__amd64__) || defined(__i386__) 269206625Syongari devclass_t pci; 270206625Syongari device_t bus, dev = NULL; 271206625Syongari device_t *kids; 272206625Syongari struct apc_tbl { 273206625Syongari uint16_t vid; 274206625Syongari uint16_t did; 275206625Syongari } *tp, apc_tbls[] = { 276206625Syongari { SIS_VENDORID, 0x0965 }, 277206625Syongari { SIS_VENDORID, 0x0966 }, 278206625Syongari { SIS_VENDORID, 0x0968 } 279206625Syongari }; 280206625Syongari uint8_t reg; 281206625Syongari int busnum, cnt, i, j, numkids; 282206625Syongari 283206625Syongari cnt = sizeof(apc_tbls) / sizeof(apc_tbls[0]); 284206625Syongari pci = devclass_find("pci"); 285206625Syongari for (busnum = 0; busnum < devclass_get_maxunit(pci); busnum++) { 286206625Syongari bus = devclass_get_device(pci, busnum); 287206625Syongari if (!bus) 288206625Syongari continue; 289206625Syongari if (device_get_children(bus, &kids, &numkids) != 0) 290206625Syongari continue; 291206625Syongari for (i = 0; i < numkids; i++) { 292206625Syongari dev = kids[i]; 293206625Syongari if (pci_get_class(dev) == PCIC_BRIDGE && 294206625Syongari pci_get_subclass(dev) == PCIS_BRIDGE_ISA) { 295206625Syongari tp = apc_tbls; 296206625Syongari for (j = 0; j < cnt; j++) { 297206625Syongari if (pci_get_vendor(dev) == tp->vid && 298206625Syongari pci_get_device(dev) == tp->did) { 299206625Syongari free(kids, M_TEMP); 300206625Syongari goto apc_found; 301206625Syongari } 302206625Syongari tp++; 303206625Syongari } 304206625Syongari } 305206625Syongari } 306206625Syongari free(kids, M_TEMP); 307206625Syongari } 308206625Syongari device_printf(sc->sge_dev, "couldn't find PCI-ISA bridge\n"); 309206625Syongari return (EINVAL); 310206625Syongariapc_found: 311206625Syongari /* Enable port 0x78 and 0x79 to access APC registers. */ 312206625Syongari reg = pci_read_config(dev, 0x48, 1); 313206625Syongari pci_write_config(dev, 0x48, reg & ~0x02, 1); 314206625Syongari DELAY(50); 315206625Syongari pci_read_config(dev, 0x48, 1); 316206625Syongari /* Read stored ethernet address. */ 317206625Syongari for (i = 0; i < ETHER_ADDR_LEN; i++) { 318206625Syongari outb(0x78, 0x09 + i); 319206625Syongari dest[i] = inb(0x79); 320206625Syongari } 321206625Syongari outb(0x78, 0x12); 322206625Syongari if ((inb(0x79) & 0x80) != 0) 323206625Syongari sc->sge_flags |= SGE_FLAG_RGMII; 324206625Syongari /* Restore access to APC registers. */ 325206625Syongari pci_write_config(dev, 0x48, reg, 1); 326206625Syongari 327206625Syongari return (0); 328206625Syongari#else 329206625Syongari return (EINVAL); 330206625Syongari#endif 331206625Syongari} 332206625Syongari 333206625Syongaristatic int 334206625Syongarisge_miibus_readreg(device_t dev, int phy, int reg) 335206625Syongari{ 336206625Syongari struct sge_softc *sc; 337206625Syongari uint32_t val; 338206625Syongari int i; 339206625Syongari 340206625Syongari sc = device_get_softc(dev); 341206625Syongari CSR_WRITE_4(sc, GMIIControl, (phy << GMI_PHY_SHIFT) | 342206625Syongari (reg << GMI_REG_SHIFT) | GMI_OP_RD | GMI_REQ); 343206625Syongari DELAY(10); 344206625Syongari for (i = 0; i < SGE_TIMEOUT; i++) { 345206625Syongari val = CSR_READ_4(sc, GMIIControl); 346206625Syongari if ((val & GMI_REQ) == 0) 347206625Syongari break; 348206625Syongari DELAY(10); 349206625Syongari } 350206625Syongari if (i == SGE_TIMEOUT) { 351206625Syongari device_printf(sc->sge_dev, "PHY read timeout : %d\n", reg); 352206625Syongari return (0); 353206625Syongari } 354206625Syongari return ((val & GMI_DATA) >> GMI_DATA_SHIFT); 355206625Syongari} 356206625Syongari 357206625Syongaristatic int 358206625Syongarisge_miibus_writereg(device_t dev, int phy, int reg, int data) 359206625Syongari{ 360206625Syongari struct sge_softc *sc; 361206625Syongari uint32_t val; 362206625Syongari int i; 363206625Syongari 364206625Syongari sc = device_get_softc(dev); 365206625Syongari CSR_WRITE_4(sc, GMIIControl, (phy << GMI_PHY_SHIFT) | 366206625Syongari (reg << GMI_REG_SHIFT) | (data << GMI_DATA_SHIFT) | 367206625Syongari GMI_OP_WR | GMI_REQ); 368206625Syongari DELAY(10); 369206625Syongari for (i = 0; i < SGE_TIMEOUT; i++) { 370206625Syongari val = CSR_READ_4(sc, GMIIControl); 371206625Syongari if ((val & GMI_REQ) == 0) 372206625Syongari break; 373206625Syongari DELAY(10); 374206625Syongari } 375206625Syongari if (i == SGE_TIMEOUT) 376206625Syongari device_printf(sc->sge_dev, "PHY write timeout : %d\n", reg); 377206625Syongari return (0); 378206625Syongari} 379206625Syongari 380206625Syongaristatic void 381206625Syongarisge_miibus_statchg(device_t dev) 382206625Syongari{ 383206625Syongari struct sge_softc *sc; 384206625Syongari struct mii_data *mii; 385206625Syongari struct ifnet *ifp; 386206625Syongari uint32_t ctl, speed; 387206625Syongari 388206625Syongari sc = device_get_softc(dev); 389206625Syongari mii = device_get_softc(sc->sge_miibus); 390206625Syongari ifp = sc->sge_ifp; 391206625Syongari if (mii == NULL || ifp == NULL || 392206625Syongari (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 393206625Syongari return; 394206625Syongari speed = 0; 395206625Syongari sc->sge_flags &= ~SGE_FLAG_LINK; 396206625Syongari if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 397206625Syongari (IFM_ACTIVE | IFM_AVALID)) { 398206625Syongari switch (IFM_SUBTYPE(mii->mii_media_active)) { 399206625Syongari case IFM_10_T: 400206625Syongari sc->sge_flags |= SGE_FLAG_LINK; 401206625Syongari speed = SC_SPEED_10; 402206625Syongari break; 403206625Syongari case IFM_100_TX: 404206625Syongari sc->sge_flags |= SGE_FLAG_LINK; 405206625Syongari speed = SC_SPEED_100; 406206625Syongari break; 407206625Syongari case IFM_1000_T: 408206625Syongari if ((sc->sge_flags & SGE_FLAG_FASTETHER) == 0) { 409206625Syongari sc->sge_flags |= SGE_FLAG_LINK; 410206625Syongari speed = SC_SPEED_1000; 411206625Syongari } 412206625Syongari break; 413206625Syongari default: 414206625Syongari break; 415206625Syongari } 416206625Syongari } 417206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0) 418206625Syongari return; 419206625Syongari /* Reprogram MAC to resolved speed/duplex/flow-control parameters. */ 420206625Syongari ctl = CSR_READ_4(sc, StationControl); 421206625Syongari ctl &= ~(0x0f000000 | SC_FDX | SC_SPEED_MASK); 422206625Syongari if (speed == SC_SPEED_1000) { 423206625Syongari ctl |= 0x07000000; 424206625Syongari sc->sge_flags |= SGE_FLAG_SPEED_1000; 425206625Syongari } else { 426206625Syongari ctl |= 0x04000000; 427206625Syongari sc->sge_flags &= ~SGE_FLAG_SPEED_1000; 428206625Syongari } 429206625Syongari#ifdef notyet 430206625Syongari if ((sc->sge_flags & SGE_FLAG_GMII) != 0) 431206625Syongari ctl |= 0x03000000; 432206625Syongari#endif 433206625Syongari ctl |= speed; 434206625Syongari if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) { 435206625Syongari ctl |= SC_FDX; 436206625Syongari sc->sge_flags |= SGE_FLAG_FDX; 437206625Syongari } else 438206625Syongari sc->sge_flags &= ~SGE_FLAG_FDX; 439206625Syongari CSR_WRITE_4(sc, StationControl, ctl); 440206625Syongari if ((sc->sge_flags & SGE_FLAG_RGMII) != 0) { 441206625Syongari CSR_WRITE_4(sc, RGMIIDelay, 0x0441); 442206625Syongari CSR_WRITE_4(sc, RGMIIDelay, 0x0440); 443206625Syongari } 444206625Syongari} 445206625Syongari 446206625Syongaristatic void 447206625Syongarisge_rxfilter(struct sge_softc *sc) 448206625Syongari{ 449206625Syongari struct ifnet *ifp; 450206625Syongari struct ifmultiaddr *ifma; 451206625Syongari uint32_t crc, hashes[2]; 452206625Syongari uint16_t rxfilt; 453206625Syongari 454206625Syongari SGE_LOCK_ASSERT(sc); 455206625Syongari 456206625Syongari ifp = sc->sge_ifp; 457207375Syongari rxfilt = CSR_READ_2(sc, RxMacControl); 458207375Syongari rxfilt &= ~(AcceptBroadcast | AcceptAllPhys | AcceptMulticast); 459207375Syongari rxfilt |= AcceptMyPhys; 460206625Syongari if ((ifp->if_flags & IFF_BROADCAST) != 0) 461206625Syongari rxfilt |= AcceptBroadcast; 462206625Syongari if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { 463206625Syongari if ((ifp->if_flags & IFF_PROMISC) != 0) 464206625Syongari rxfilt |= AcceptAllPhys; 465206625Syongari rxfilt |= AcceptMulticast; 466206625Syongari hashes[0] = 0xFFFFFFFF; 467206625Syongari hashes[1] = 0xFFFFFFFF; 468207375Syongari } else { 469207375Syongari rxfilt |= AcceptMulticast; 470207375Syongari hashes[0] = hashes[1] = 0; 471207375Syongari /* Now program new ones. */ 472207375Syongari if_maddr_rlock(ifp); 473207375Syongari TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 474207375Syongari if (ifma->ifma_addr->sa_family != AF_LINK) 475207375Syongari continue; 476207375Syongari crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) 477207375Syongari ifma->ifma_addr), ETHER_ADDR_LEN); 478207375Syongari hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); 479207375Syongari } 480207375Syongari if_maddr_runlock(ifp); 481206625Syongari } 482206625Syongari CSR_WRITE_2(sc, RxMacControl, rxfilt | 0x02); 483206625Syongari CSR_WRITE_4(sc, RxHashTable, hashes[0]); 484206625Syongari CSR_WRITE_4(sc, RxHashTable2, hashes[1]); 485206625Syongari} 486206625Syongari 487206625Syongaristatic void 488207380Syongarisge_setvlan(struct sge_softc *sc) 489207380Syongari{ 490207380Syongari struct ifnet *ifp; 491207380Syongari uint16_t rxfilt; 492207380Syongari 493207380Syongari SGE_LOCK_ASSERT(sc); 494207380Syongari 495207380Syongari ifp = sc->sge_ifp; 496207380Syongari if ((ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0) 497207380Syongari return; 498207380Syongari rxfilt = CSR_READ_2(sc, RxMacControl); 499207380Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 500207380Syongari rxfilt |= RXMAC_STRIP_VLAN; 501207380Syongari else 502207380Syongari rxfilt &= ~RXMAC_STRIP_VLAN; 503207380Syongari CSR_WRITE_2(sc, RxMacControl, rxfilt); 504207380Syongari} 505207380Syongari 506207380Syongaristatic void 507206625Syongarisge_reset(struct sge_softc *sc) 508206625Syongari{ 509206625Syongari 510206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 511206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 512206625Syongari 513206625Syongari /* Soft reset. */ 514206625Syongari CSR_WRITE_4(sc, IntrControl, 0x8000); 515206625Syongari CSR_READ_4(sc, IntrControl); 516206625Syongari DELAY(100); 517206625Syongari CSR_WRITE_4(sc, IntrControl, 0); 518206625Syongari /* Stop MAC. */ 519206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00); 520206625Syongari CSR_WRITE_4(sc, RX_CTL, 0x1a00); 521206625Syongari 522206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 523206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 524206625Syongari 525206625Syongari CSR_WRITE_4(sc, GMIIControl, 0); 526206625Syongari} 527206625Syongari 528206625Syongari/* 529206625Syongari * Probe for an SiS chip. Check the PCI vendor and device 530206625Syongari * IDs against our list and return a device name if we find a match. 531206625Syongari */ 532206625Syongaristatic int 533206625Syongarisge_probe(device_t dev) 534206625Syongari{ 535206625Syongari struct sge_type *t; 536206625Syongari 537206625Syongari t = sge_devs; 538206625Syongari while (t->sge_name != NULL) { 539206625Syongari if ((pci_get_vendor(dev) == t->sge_vid) && 540206625Syongari (pci_get_device(dev) == t->sge_did)) { 541206625Syongari device_set_desc(dev, t->sge_name); 542206625Syongari return (BUS_PROBE_DEFAULT); 543206625Syongari } 544206625Syongari t++; 545206625Syongari } 546206625Syongari 547206625Syongari return (ENXIO); 548206625Syongari} 549206625Syongari 550206625Syongari/* 551206625Syongari * Attach the interface. Allocate softc structures, do ifmedia 552206625Syongari * setup and ethernet/BPF attach. 553206625Syongari */ 554206625Syongaristatic int 555206625Syongarisge_attach(device_t dev) 556206625Syongari{ 557206625Syongari struct sge_softc *sc; 558206625Syongari struct ifnet *ifp; 559206625Syongari uint8_t eaddr[ETHER_ADDR_LEN]; 560206625Syongari int error = 0, rid; 561206625Syongari 562206625Syongari sc = device_get_softc(dev); 563206625Syongari sc->sge_dev = dev; 564206625Syongari 565206625Syongari mtx_init(&sc->sge_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 566206625Syongari MTX_DEF); 567206625Syongari callout_init_mtx(&sc->sge_stat_ch, &sc->sge_mtx, 0); 568206625Syongari 569206625Syongari /* 570206625Syongari * Map control/status registers. 571206625Syongari */ 572206625Syongari pci_enable_busmaster(dev); 573206625Syongari 574206625Syongari /* Allocate resources. */ 575206625Syongari sc->sge_res_id = PCIR_BAR(0); 576206625Syongari sc->sge_res_type = SYS_RES_MEMORY; 577206625Syongari sc->sge_res = bus_alloc_resource_any(dev, sc->sge_res_type, 578206625Syongari &sc->sge_res_id, RF_ACTIVE); 579206625Syongari if (sc->sge_res == NULL) { 580206625Syongari device_printf(dev, "couldn't allocate resource\n"); 581206625Syongari error = ENXIO; 582206625Syongari goto fail; 583206625Syongari } 584206625Syongari 585206625Syongari rid = 0; 586206625Syongari sc->sge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 587206625Syongari RF_SHAREABLE | RF_ACTIVE); 588206625Syongari if (sc->sge_irq == NULL) { 589206625Syongari device_printf(dev, "couldn't allocate IRQ resources\n"); 590206625Syongari error = ENXIO; 591206625Syongari goto fail; 592206625Syongari } 593206625Syongari sc->sge_rev = pci_get_revid(dev); 594206625Syongari if (pci_get_device(dev) == SIS_DEVICEID_190) 595207377Syongari sc->sge_flags |= SGE_FLAG_FASTETHER | SGE_FLAG_SIS190; 596206625Syongari /* Reset the adapter. */ 597206625Syongari sge_reset(sc); 598206625Syongari 599206625Syongari /* Get MAC address from the EEPROM. */ 600206625Syongari if ((pci_read_config(dev, 0x73, 1) & 0x01) != 0) 601206625Syongari sge_get_mac_addr_apc(sc, eaddr); 602206625Syongari else 603206625Syongari sge_get_mac_addr_eeprom(sc, eaddr); 604206625Syongari 605206625Syongari if ((error = sge_dma_alloc(sc)) != 0) 606206625Syongari goto fail; 607206625Syongari 608206625Syongari ifp = sc->sge_ifp = if_alloc(IFT_ETHER); 609206625Syongari if (ifp == NULL) { 610206625Syongari device_printf(dev, "cannot allocate ifnet structure.\n"); 611206625Syongari error = ENOSPC; 612206625Syongari goto fail; 613206625Syongari } 614206625Syongari ifp->if_softc = sc; 615206625Syongari if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 616206625Syongari ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 617206625Syongari ifp->if_ioctl = sge_ioctl; 618206625Syongari ifp->if_start = sge_start; 619206625Syongari ifp->if_init = sge_init; 620206625Syongari ifp->if_snd.ifq_drv_maxlen = SGE_TX_RING_CNT - 1; 621206625Syongari IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); 622206625Syongari IFQ_SET_READY(&ifp->if_snd); 623206625Syongari ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_RXCSUM; 624206625Syongari ifp->if_hwassist = SGE_CSUM_FEATURES; 625206625Syongari ifp->if_capenable = ifp->if_capabilities; 626206625Syongari /* 627206625Syongari * Do MII setup. 628206625Syongari */ 629206625Syongari if (mii_phy_probe(dev, &sc->sge_miibus, sge_ifmedia_upd, 630206625Syongari sge_ifmedia_sts)) { 631206625Syongari device_printf(dev, "no PHY found!\n"); 632206625Syongari error = ENXIO; 633206625Syongari goto fail; 634206625Syongari } 635206625Syongari 636206625Syongari /* 637206625Syongari * Call MI attach routine. 638206625Syongari */ 639206625Syongari ether_ifattach(ifp, eaddr); 640206625Syongari 641206625Syongari /* VLAN setup. */ 642207380Syongari if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) 643207380Syongari ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | 644207380Syongari IFCAP_VLAN_HWCSUM; 645206625Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU; 646206625Syongari ifp->if_capenable = ifp->if_capabilities; 647206625Syongari /* Tell the upper layer(s) we support long frames. */ 648206625Syongari ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 649206625Syongari 650206625Syongari /* Hook interrupt last to avoid having to lock softc */ 651206625Syongari error = bus_setup_intr(dev, sc->sge_irq, INTR_TYPE_NET | INTR_MPSAFE, 652206625Syongari NULL, sge_intr, sc, &sc->sge_intrhand); 653206625Syongari if (error) { 654206625Syongari device_printf(dev, "couldn't set up irq\n"); 655206625Syongari ether_ifdetach(ifp); 656206625Syongari goto fail; 657206625Syongari } 658206625Syongari 659206625Syongarifail: 660206625Syongari if (error) 661206625Syongari sge_detach(dev); 662206625Syongari 663206625Syongari return (error); 664206625Syongari} 665206625Syongari 666206625Syongari/* 667206625Syongari * Shutdown hardware and free up resources. This can be called any 668206625Syongari * time after the mutex has been initialized. It is called in both 669206625Syongari * the error case in attach and the normal detach case so it needs 670206625Syongari * to be careful about only freeing resources that have actually been 671206625Syongari * allocated. 672206625Syongari */ 673206625Syongaristatic int 674206625Syongarisge_detach(device_t dev) 675206625Syongari{ 676206625Syongari struct sge_softc *sc; 677206625Syongari struct ifnet *ifp; 678206625Syongari 679206625Syongari sc = device_get_softc(dev); 680206625Syongari ifp = sc->sge_ifp; 681206625Syongari /* These should only be active if attach succeeded. */ 682206625Syongari if (device_is_attached(dev)) { 683206625Syongari ether_ifdetach(ifp); 684206625Syongari SGE_LOCK(sc); 685206625Syongari sge_stop(sc); 686206625Syongari SGE_UNLOCK(sc); 687206625Syongari callout_drain(&sc->sge_stat_ch); 688206625Syongari } 689206625Syongari if (sc->sge_miibus) 690206625Syongari device_delete_child(dev, sc->sge_miibus); 691206625Syongari bus_generic_detach(dev); 692206625Syongari 693206625Syongari if (sc->sge_intrhand) 694206625Syongari bus_teardown_intr(dev, sc->sge_irq, sc->sge_intrhand); 695206625Syongari if (sc->sge_irq) 696206625Syongari bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sge_irq); 697206625Syongari if (sc->sge_res) 698206625Syongari bus_release_resource(dev, sc->sge_res_type, sc->sge_res_id, 699206625Syongari sc->sge_res); 700206625Syongari if (ifp) 701206625Syongari if_free(ifp); 702206625Syongari sge_dma_free(sc); 703206625Syongari mtx_destroy(&sc->sge_mtx); 704206625Syongari 705206625Syongari return (0); 706206625Syongari} 707206625Syongari 708206625Syongari/* 709206625Syongari * Stop all chip I/O so that the kernel's probe routines don't 710206625Syongari * get confused by errant DMAs when rebooting. 711206625Syongari */ 712206625Syongaristatic int 713206625Syongarisge_shutdown(device_t dev) 714206625Syongari{ 715206625Syongari struct sge_softc *sc; 716206625Syongari 717206625Syongari sc = device_get_softc(dev); 718206625Syongari SGE_LOCK(sc); 719206625Syongari sge_stop(sc); 720206625Syongari SGE_UNLOCK(sc); 721206625Syongari return (0); 722206625Syongari} 723206625Syongari 724206625Syongaristatic int 725206625Syongarisge_suspend(device_t dev) 726206625Syongari{ 727206625Syongari struct sge_softc *sc; 728206625Syongari struct ifnet *ifp; 729206625Syongari 730206625Syongari sc = device_get_softc(dev); 731206625Syongari SGE_LOCK(sc); 732206625Syongari ifp = sc->sge_ifp; 733206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 734206625Syongari sge_stop(sc); 735206625Syongari SGE_UNLOCK(sc); 736206625Syongari return (0); 737206625Syongari} 738206625Syongari 739206625Syongaristatic int 740206625Syongarisge_resume(device_t dev) 741206625Syongari{ 742206625Syongari struct sge_softc *sc; 743206625Syongari struct ifnet *ifp; 744206625Syongari 745206625Syongari sc = device_get_softc(dev); 746206625Syongari SGE_LOCK(sc); 747206625Syongari ifp = sc->sge_ifp; 748206625Syongari if ((ifp->if_flags & IFF_UP) != 0) 749206625Syongari sge_init_locked(sc); 750206625Syongari SGE_UNLOCK(sc); 751206625Syongari return (0); 752206625Syongari} 753206625Syongari 754206625Syongaristatic int 755206625Syongarisge_dma_alloc(struct sge_softc *sc) 756206625Syongari{ 757206625Syongari struct sge_chain_data *cd; 758206625Syongari struct sge_list_data *ld; 759207628Syongari struct sge_rxdesc *rxd; 760207628Syongari struct sge_txdesc *txd; 761206625Syongari int error, i; 762206625Syongari 763206625Syongari cd = &sc->sge_cdata; 764206625Syongari ld = &sc->sge_ldata; 765206625Syongari error = bus_dma_tag_create(bus_get_dma_tag(sc->sge_dev), 766206625Syongari 1, 0, /* alignment, boundary */ 767206625Syongari BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 768206625Syongari BUS_SPACE_MAXADDR, /* highaddr */ 769206625Syongari NULL, NULL, /* filter, filterarg */ 770206625Syongari BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 771206625Syongari 1, /* nsegments */ 772206625Syongari BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 773206625Syongari 0, /* flags */ 774206625Syongari NULL, /* lockfunc */ 775206625Syongari NULL, /* lockarg */ 776206625Syongari &cd->sge_tag); 777206625Syongari if (error != 0) { 778206625Syongari device_printf(sc->sge_dev, 779206625Syongari "could not create parent DMA tag.\n"); 780206625Syongari goto fail; 781206625Syongari } 782206625Syongari 783206625Syongari /* RX descriptor ring */ 784206625Syongari error = bus_dma_tag_create(cd->sge_tag, 785206625Syongari SGE_DESC_ALIGN, 0, /* alignment, boundary */ 786206625Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 787206625Syongari BUS_SPACE_MAXADDR, /* highaddr */ 788206625Syongari NULL, NULL, /* filter, filterarg */ 789206625Syongari SGE_RX_RING_SZ, 1, /* maxsize,nsegments */ 790206625Syongari SGE_RX_RING_SZ, /* maxsegsize */ 791206625Syongari 0, /* flags */ 792206625Syongari NULL, /* lockfunc */ 793206625Syongari NULL, /* lockarg */ 794206625Syongari &cd->sge_rx_tag); 795206625Syongari if (error != 0) { 796206625Syongari device_printf(sc->sge_dev, 797206625Syongari "could not create Rx ring DMA tag.\n"); 798206625Syongari goto fail; 799206625Syongari } 800206625Syongari /* Allocate DMA'able memory and load DMA map for RX ring. */ 801206625Syongari error = bus_dmamem_alloc(cd->sge_rx_tag, (void **)&ld->sge_rx_ring, 802206625Syongari BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, 803206625Syongari &cd->sge_rx_dmamap); 804206625Syongari if (error != 0) { 805206625Syongari device_printf(sc->sge_dev, 806206625Syongari "could not allocate DMA'able memory for Rx ring.\n"); 807206625Syongari goto fail; 808206625Syongari } 809206625Syongari error = bus_dmamap_load(cd->sge_rx_tag, cd->sge_rx_dmamap, 810206625Syongari ld->sge_rx_ring, SGE_RX_RING_SZ, sge_dma_map_addr, 811206625Syongari &ld->sge_rx_paddr, BUS_DMA_NOWAIT); 812206625Syongari if (error != 0) { 813206625Syongari device_printf(sc->sge_dev, 814206625Syongari "could not load DMA'able memory for Rx ring.\n"); 815206625Syongari } 816206625Syongari 817206625Syongari /* TX descriptor ring */ 818206625Syongari error = bus_dma_tag_create(cd->sge_tag, 819206625Syongari SGE_DESC_ALIGN, 0, /* alignment, boundary */ 820206625Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 821206625Syongari BUS_SPACE_MAXADDR, /* highaddr */ 822206625Syongari NULL, NULL, /* filter, filterarg */ 823206625Syongari SGE_TX_RING_SZ, 1, /* maxsize,nsegments */ 824206625Syongari SGE_TX_RING_SZ, /* maxsegsize */ 825206625Syongari 0, /* flags */ 826206625Syongari NULL, /* lockfunc */ 827206625Syongari NULL, /* lockarg */ 828206625Syongari &cd->sge_tx_tag); 829206625Syongari if (error != 0) { 830206625Syongari device_printf(sc->sge_dev, 831206625Syongari "could not create Rx ring DMA tag.\n"); 832206625Syongari goto fail; 833206625Syongari } 834206625Syongari /* Allocate DMA'able memory and load DMA map for TX ring. */ 835206625Syongari error = bus_dmamem_alloc(cd->sge_tx_tag, (void **)&ld->sge_tx_ring, 836206625Syongari BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, 837206625Syongari &cd->sge_tx_dmamap); 838206625Syongari if (error != 0) { 839206625Syongari device_printf(sc->sge_dev, 840206625Syongari "could not allocate DMA'able memory for Tx ring.\n"); 841206625Syongari goto fail; 842206625Syongari } 843206625Syongari error = bus_dmamap_load(cd->sge_tx_tag, cd->sge_tx_dmamap, 844206625Syongari ld->sge_tx_ring, SGE_TX_RING_SZ, sge_dma_map_addr, 845206625Syongari &ld->sge_tx_paddr, BUS_DMA_NOWAIT); 846206625Syongari if (error != 0) { 847206625Syongari device_printf(sc->sge_dev, 848206625Syongari "could not load DMA'able memory for Rx ring.\n"); 849206625Syongari goto fail; 850206625Syongari } 851206625Syongari 852206625Syongari /* Create DMA tag for Tx buffers. */ 853206625Syongari error = bus_dma_tag_create(cd->sge_tag, 1, 0, BUS_SPACE_MAXADDR, 854206625Syongari BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES * SGE_MAXTXSEGS, 855206625Syongari SGE_MAXTXSEGS, MCLBYTES, 0, NULL, NULL, &cd->sge_txmbuf_tag); 856206625Syongari if (error != 0) { 857206625Syongari device_printf(sc->sge_dev, 858206625Syongari "could not create Tx mbuf DMA tag.\n"); 859206625Syongari goto fail; 860206625Syongari } 861206625Syongari 862206625Syongari /* Create DMA tag for Rx buffers. */ 863206625Syongari error = bus_dma_tag_create(cd->sge_tag, SGE_RX_BUF_ALIGN, 0, 864206625Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, 865206625Syongari MCLBYTES, 0, NULL, NULL, &cd->sge_rxmbuf_tag); 866206625Syongari if (error != 0) { 867206625Syongari device_printf(sc->sge_dev, 868206625Syongari "could not create Rx mbuf DMA tag.\n"); 869206625Syongari goto fail; 870206625Syongari } 871206625Syongari 872206625Syongari /* Create DMA maps for Tx buffers. */ 873206625Syongari for (i = 0; i < SGE_TX_RING_CNT; i++) { 874207628Syongari txd = &cd->sge_txdesc[i]; 875207628Syongari txd->tx_m = NULL; 876207628Syongari txd->tx_dmamap = NULL; 877207628Syongari txd->tx_ndesc = 0; 878206625Syongari error = bus_dmamap_create(cd->sge_txmbuf_tag, 0, 879207628Syongari &txd->tx_dmamap); 880206625Syongari if (error != 0) { 881206625Syongari device_printf(sc->sge_dev, 882206625Syongari "could not create Tx DMA map.\n"); 883206625Syongari goto fail; 884206625Syongari } 885206625Syongari } 886206625Syongari /* Create spare DMA map for Rx buffer. */ 887206625Syongari error = bus_dmamap_create(cd->sge_rxmbuf_tag, 0, &cd->sge_rx_spare_map); 888206625Syongari if (error != 0) { 889206625Syongari device_printf(sc->sge_dev, 890206625Syongari "could not create spare Rx DMA map.\n"); 891206625Syongari goto fail; 892206625Syongari } 893206625Syongari /* Create DMA maps for Rx buffers. */ 894206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 895207628Syongari rxd = &cd->sge_rxdesc[i]; 896207628Syongari rxd->rx_m = NULL; 897207628Syongari rxd->rx_dmamap = NULL; 898206625Syongari error = bus_dmamap_create(cd->sge_rxmbuf_tag, 0, 899207628Syongari &rxd->rx_dmamap); 900206625Syongari if (error) { 901206625Syongari device_printf(sc->sge_dev, 902206625Syongari "could not create Rx DMA map.\n"); 903206625Syongari goto fail; 904206625Syongari } 905206625Syongari } 906206625Syongarifail: 907206625Syongari return (error); 908206625Syongari} 909206625Syongari 910206625Syongaristatic void 911206625Syongarisge_dma_free(struct sge_softc *sc) 912206625Syongari{ 913206625Syongari struct sge_chain_data *cd; 914206625Syongari struct sge_list_data *ld; 915207628Syongari struct sge_rxdesc *rxd; 916207628Syongari struct sge_txdesc *txd; 917206625Syongari int i; 918206625Syongari 919206625Syongari cd = &sc->sge_cdata; 920206625Syongari ld = &sc->sge_ldata; 921206625Syongari /* Rx ring. */ 922206625Syongari if (cd->sge_rx_tag != NULL) { 923206625Syongari if (cd->sge_rx_dmamap != NULL) 924206625Syongari bus_dmamap_unload(cd->sge_rx_tag, cd->sge_rx_dmamap); 925206625Syongari if (cd->sge_rx_dmamap != NULL && ld->sge_rx_ring != NULL) 926206625Syongari bus_dmamem_free(cd->sge_rx_tag, ld->sge_rx_ring, 927206625Syongari cd->sge_rx_dmamap); 928206625Syongari ld->sge_rx_ring = NULL; 929206625Syongari cd->sge_rx_dmamap = NULL; 930206625Syongari bus_dma_tag_destroy(cd->sge_rx_tag); 931206625Syongari cd->sge_rx_tag = NULL; 932206625Syongari } 933206625Syongari /* Tx ring. */ 934206625Syongari if (cd->sge_tx_tag != NULL) { 935206625Syongari if (cd->sge_tx_dmamap != NULL) 936206625Syongari bus_dmamap_unload(cd->sge_tx_tag, cd->sge_tx_dmamap); 937206625Syongari if (cd->sge_tx_dmamap != NULL && ld->sge_tx_ring != NULL) 938206625Syongari bus_dmamem_free(cd->sge_tx_tag, ld->sge_tx_ring, 939206625Syongari cd->sge_tx_dmamap); 940206625Syongari ld->sge_tx_ring = NULL; 941206625Syongari cd->sge_tx_dmamap = NULL; 942206625Syongari bus_dma_tag_destroy(cd->sge_tx_tag); 943206625Syongari cd->sge_tx_tag = NULL; 944206625Syongari } 945206625Syongari /* Rx buffers. */ 946206625Syongari if (cd->sge_rxmbuf_tag != NULL) { 947206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 948207628Syongari rxd = &cd->sge_rxdesc[i]; 949207628Syongari if (rxd->rx_dmamap != NULL) { 950206625Syongari bus_dmamap_destroy(cd->sge_rxmbuf_tag, 951207628Syongari rxd->rx_dmamap); 952207628Syongari rxd->rx_dmamap = NULL; 953206625Syongari } 954206625Syongari } 955206625Syongari if (cd->sge_rx_spare_map != NULL) { 956206625Syongari bus_dmamap_destroy(cd->sge_rxmbuf_tag, 957206625Syongari cd->sge_rx_spare_map); 958206625Syongari cd->sge_rx_spare_map = NULL; 959206625Syongari } 960206625Syongari bus_dma_tag_destroy(cd->sge_rxmbuf_tag); 961206625Syongari cd->sge_rxmbuf_tag = NULL; 962206625Syongari } 963206625Syongari /* Tx buffers. */ 964206625Syongari if (cd->sge_txmbuf_tag != NULL) { 965206625Syongari for (i = 0; i < SGE_TX_RING_CNT; i++) { 966207628Syongari txd = &cd->sge_txdesc[i]; 967207628Syongari if (txd->tx_dmamap != NULL) { 968206625Syongari bus_dmamap_destroy(cd->sge_txmbuf_tag, 969207628Syongari txd->tx_dmamap); 970207628Syongari txd->tx_dmamap = NULL; 971206625Syongari } 972206625Syongari } 973206625Syongari bus_dma_tag_destroy(cd->sge_txmbuf_tag); 974206625Syongari cd->sge_txmbuf_tag = NULL; 975206625Syongari } 976206625Syongari if (cd->sge_tag != NULL) 977206625Syongari bus_dma_tag_destroy(cd->sge_tag); 978206625Syongari cd->sge_tag = NULL; 979206625Syongari} 980206625Syongari 981206625Syongari/* 982206625Syongari * Initialize the TX descriptors. 983206625Syongari */ 984206625Syongaristatic int 985206625Syongarisge_list_tx_init(struct sge_softc *sc) 986206625Syongari{ 987206625Syongari struct sge_list_data *ld; 988206625Syongari struct sge_chain_data *cd; 989206625Syongari 990206625Syongari SGE_LOCK_ASSERT(sc); 991206625Syongari ld = &sc->sge_ldata; 992206625Syongari cd = &sc->sge_cdata; 993206625Syongari bzero(ld->sge_tx_ring, SGE_TX_RING_SZ); 994206625Syongari ld->sge_tx_ring[SGE_TX_RING_CNT - 1].sge_flags = htole32(RING_END); 995206625Syongari bus_dmamap_sync(cd->sge_tx_tag, cd->sge_tx_dmamap, 996206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 997206625Syongari cd->sge_tx_prod = 0; 998206625Syongari cd->sge_tx_cons = 0; 999206625Syongari cd->sge_tx_cnt = 0; 1000206625Syongari return (0); 1001206625Syongari} 1002206625Syongari 1003206625Syongaristatic int 1004206625Syongarisge_list_tx_free(struct sge_softc *sc) 1005206625Syongari{ 1006206625Syongari struct sge_chain_data *cd; 1007207628Syongari struct sge_txdesc *txd; 1008206625Syongari int i; 1009206625Syongari 1010206625Syongari SGE_LOCK_ASSERT(sc); 1011206625Syongari cd = &sc->sge_cdata; 1012206625Syongari for (i = 0; i < SGE_TX_RING_CNT; i++) { 1013207628Syongari txd = &cd->sge_txdesc[i]; 1014207628Syongari if (txd->tx_m != NULL) { 1015207628Syongari bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap, 1016207628Syongari BUS_DMASYNC_POSTWRITE); 1017207628Syongari bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap); 1018207628Syongari m_free(txd->tx_m); 1019207628Syongari txd->tx_m = NULL; 1020207628Syongari txd->tx_ndesc = 0; 1021206625Syongari } 1022206625Syongari } 1023206625Syongari 1024206625Syongari return (0); 1025206625Syongari} 1026206625Syongari 1027206625Syongari/* 1028206625Syongari * Initialize the RX descriptors and allocate mbufs for them. Note that 1029206625Syongari * we arrange the descriptors in a closed ring, so that the last descriptor 1030206625Syongari * has RING_END flag set. 1031206625Syongari */ 1032206625Syongaristatic int 1033206625Syongarisge_list_rx_init(struct sge_softc *sc) 1034206625Syongari{ 1035206625Syongari struct sge_chain_data *cd; 1036206625Syongari int i; 1037206625Syongari 1038206625Syongari SGE_LOCK_ASSERT(sc); 1039206625Syongari cd = &sc->sge_cdata; 1040206625Syongari cd->sge_rx_cons = 0; 1041206625Syongari bzero(sc->sge_ldata.sge_rx_ring, SGE_RX_RING_SZ); 1042206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 1043206625Syongari if (sge_newbuf(sc, i) != 0) 1044206625Syongari return (ENOBUFS); 1045206625Syongari } 1046206625Syongari bus_dmamap_sync(cd->sge_rx_tag, cd->sge_rx_dmamap, 1047206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1048206625Syongari return (0); 1049206625Syongari} 1050206625Syongari 1051206625Syongaristatic int 1052206625Syongarisge_list_rx_free(struct sge_softc *sc) 1053206625Syongari{ 1054206625Syongari struct sge_chain_data *cd; 1055207628Syongari struct sge_rxdesc *rxd; 1056206625Syongari int i; 1057206625Syongari 1058206625Syongari SGE_LOCK_ASSERT(sc); 1059206625Syongari cd = &sc->sge_cdata; 1060206625Syongari for (i = 0; i < SGE_RX_RING_CNT; i++) { 1061207628Syongari rxd = &cd->sge_rxdesc[i]; 1062207628Syongari if (rxd->rx_m != NULL) { 1063207628Syongari bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, 1064206625Syongari BUS_DMASYNC_POSTREAD); 1065206625Syongari bus_dmamap_unload(cd->sge_rxmbuf_tag, 1066207628Syongari rxd->rx_dmamap); 1067207628Syongari m_free(rxd->rx_m); 1068207628Syongari rxd->rx_m = NULL; 1069206625Syongari } 1070206625Syongari } 1071206625Syongari return (0); 1072206625Syongari} 1073206625Syongari 1074206625Syongari/* 1075206625Syongari * Initialize an RX descriptor and attach an MBUF cluster. 1076206625Syongari */ 1077206625Syongaristatic int 1078206625Syongarisge_newbuf(struct sge_softc *sc, int prod) 1079206625Syongari{ 1080206625Syongari struct mbuf *m; 1081206625Syongari struct sge_desc *desc; 1082206625Syongari struct sge_chain_data *cd; 1083207628Syongari struct sge_rxdesc *rxd; 1084206625Syongari bus_dma_segment_t segs[1]; 1085206625Syongari bus_dmamap_t map; 1086206625Syongari int error, nsegs; 1087206625Syongari 1088206625Syongari SGE_LOCK_ASSERT(sc); 1089206625Syongari 1090206625Syongari cd = &sc->sge_cdata; 1091206625Syongari m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 1092206625Syongari if (m == NULL) 1093206625Syongari return (ENOBUFS); 1094206625Syongari m->m_len = m->m_pkthdr.len = MCLBYTES; 1095206625Syongari m_adj(m, SGE_RX_BUF_ALIGN); 1096206625Syongari error = bus_dmamap_load_mbuf_sg(cd->sge_rxmbuf_tag, 1097206625Syongari cd->sge_rx_spare_map, m, segs, &nsegs, 0); 1098206625Syongari if (error != 0) { 1099206625Syongari m_freem(m); 1100206625Syongari return (error); 1101206625Syongari } 1102206625Syongari KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 1103207628Syongari rxd = &cd->sge_rxdesc[prod]; 1104207628Syongari if (rxd->rx_m != NULL) { 1105207628Syongari bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, 1106206625Syongari BUS_DMASYNC_POSTREAD); 1107207628Syongari bus_dmamap_unload(cd->sge_rxmbuf_tag, rxd->rx_dmamap); 1108206625Syongari } 1109207628Syongari map = rxd->rx_dmamap; 1110207628Syongari rxd->rx_dmamap = cd->sge_rx_spare_map; 1111206625Syongari cd->sge_rx_spare_map = map; 1112207628Syongari bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, 1113206625Syongari BUS_DMASYNC_PREREAD); 1114207628Syongari rxd->rx_m = m; 1115206625Syongari 1116206625Syongari desc = &sc->sge_ldata.sge_rx_ring[prod]; 1117206625Syongari desc->sge_sts_size = 0; 1118206625Syongari desc->sge_ptr = htole32(SGE_ADDR_LO(segs[0].ds_addr)); 1119206625Syongari desc->sge_flags = htole32(segs[0].ds_len); 1120206625Syongari if (prod == SGE_RX_RING_CNT - 1) 1121206625Syongari desc->sge_flags |= htole32(RING_END); 1122206625Syongari desc->sge_cmdsts = htole32(RDC_OWN | RDC_INTR | RDC_IP_CSUM | 1123206625Syongari RDC_TCP_CSUM | RDC_UDP_CSUM); 1124206625Syongari return (0); 1125206625Syongari} 1126206625Syongari 1127206625Syongari#ifndef __NO_STRICT_ALIGNMENT 1128206625Syongaristatic __inline void 1129206625Syongarisge_fixup_rx(struct mbuf *m) 1130206625Syongari{ 1131206625Syongari int i; 1132206625Syongari uint16_t *src, *dst; 1133206625Syongari 1134206625Syongari src = mtod(m, uint16_t *); 1135206625Syongari dst = src - 3; 1136206625Syongari 1137206625Syongari for (i = 0; i < (m->m_len / sizeof(uint16_t) + 1); i++) 1138206625Syongari *dst++ = *src++; 1139206625Syongari 1140206625Syongari m->m_data -= (SGE_RX_BUF_ALIGN - ETHER_ALIGN); 1141206625Syongari} 1142206625Syongari#endif 1143206625Syongari 1144206625Syongaristatic __inline void 1145206625Syongarisge_discard_rxbuf(struct sge_softc *sc, int index) 1146206625Syongari{ 1147206625Syongari struct sge_desc *desc; 1148206625Syongari 1149206625Syongari desc = &sc->sge_ldata.sge_rx_ring[index]; 1150206625Syongari desc->sge_sts_size = 0; 1151206625Syongari desc->sge_flags = htole32(MCLBYTES - SGE_RX_BUF_ALIGN); 1152206625Syongari if (index == SGE_RX_RING_CNT - 1) 1153206625Syongari desc->sge_flags |= htole32(RING_END); 1154206625Syongari desc->sge_cmdsts = htole32(RDC_OWN | RDC_INTR | RDC_IP_CSUM | 1155206625Syongari RDC_TCP_CSUM | RDC_UDP_CSUM); 1156206625Syongari} 1157206625Syongari 1158206625Syongari/* 1159206625Syongari * A frame has been uploaded: pass the resulting mbuf chain up to 1160206625Syongari * the higher level protocols. 1161206625Syongari */ 1162206625Syongaristatic void 1163206625Syongarisge_rxeof(struct sge_softc *sc) 1164206625Syongari{ 1165206625Syongari struct ifnet *ifp; 1166206625Syongari struct mbuf *m; 1167206625Syongari struct sge_chain_data *cd; 1168206625Syongari struct sge_desc *cur_rx; 1169206625Syongari uint32_t rxinfo, rxstat; 1170206625Syongari int cons, prog; 1171206625Syongari 1172206625Syongari SGE_LOCK_ASSERT(sc); 1173206625Syongari 1174206625Syongari ifp = sc->sge_ifp; 1175206625Syongari cd = &sc->sge_cdata; 1176206625Syongari 1177206625Syongari bus_dmamap_sync(cd->sge_rx_tag, cd->sge_rx_dmamap, 1178206625Syongari BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1179206625Syongari cons = cd->sge_rx_cons; 1180206625Syongari for (prog = 0; prog < SGE_RX_RING_CNT; prog++, 1181206625Syongari SGE_INC(cons, SGE_RX_RING_CNT)) { 1182206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1183206625Syongari break; 1184206625Syongari cur_rx = &sc->sge_ldata.sge_rx_ring[cons]; 1185206625Syongari rxinfo = le32toh(cur_rx->sge_cmdsts); 1186206625Syongari if ((rxinfo & RDC_OWN) != 0) 1187206625Syongari break; 1188206625Syongari rxstat = le32toh(cur_rx->sge_sts_size); 1189207379Syongari if ((rxstat & RDS_CRCOK) == 0 || SGE_RX_ERROR(rxstat) != 0 || 1190207379Syongari SGE_RX_NSEGS(rxstat) != 1) { 1191206625Syongari /* XXX We don't support multi-segment frames yet. */ 1192206625Syongari#ifdef SGE_SHOW_ERRORS 1193206625Syongari device_printf(sc->sge_dev, "Rx error : 0x%b\n", rxstat, 1194206625Syongari RX_ERR_BITS); 1195206625Syongari#endif 1196206625Syongari sge_discard_rxbuf(sc, cons); 1197206625Syongari ifp->if_ierrors++; 1198206625Syongari continue; 1199206625Syongari } 1200207628Syongari m = cd->sge_rxdesc[cons].rx_m; 1201206625Syongari if (sge_newbuf(sc, cons) != 0) { 1202206625Syongari sge_discard_rxbuf(sc, cons); 1203206625Syongari ifp->if_iqdrops++; 1204206625Syongari continue; 1205206625Syongari } 1206206625Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) { 1207206625Syongari if ((rxinfo & RDC_IP_CSUM) != 0 && 1208206625Syongari (rxinfo & RDC_IP_CSUM_OK) != 0) 1209206625Syongari m->m_pkthdr.csum_flags |= 1210206625Syongari CSUM_IP_CHECKED | CSUM_IP_VALID; 1211206625Syongari if (((rxinfo & RDC_TCP_CSUM) != 0 && 1212206625Syongari (rxinfo & RDC_TCP_CSUM_OK) != 0) || 1213206625Syongari ((rxinfo & RDC_UDP_CSUM) != 0 && 1214206625Syongari (rxinfo & RDC_UDP_CSUM_OK) != 0)) { 1215206625Syongari m->m_pkthdr.csum_flags |= 1216206625Syongari CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 1217206625Syongari m->m_pkthdr.csum_data = 0xffff; 1218206625Syongari } 1219206625Syongari } 1220207380Syongari /* Check for VLAN tagged frame. */ 1221207380Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && 1222207380Syongari (rxstat & RDS_VLAN) != 0) { 1223207380Syongari m->m_pkthdr.ether_vtag = rxinfo & RDC_VLAN_MASK; 1224207380Syongari m->m_flags |= M_VLANTAG; 1225207380Syongari } 1226207379Syongari if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) { 1227207379Syongari /* 1228207379Syongari * Account for 10bytes auto padding which is used 1229207379Syongari * to align IP header on 32bit boundary. Also note, 1230207379Syongari * CRC bytes is automatically removed by the 1231207379Syongari * hardware. 1232207379Syongari */ 1233207379Syongari m->m_data += SGE_RX_PAD_BYTES; 1234207379Syongari m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) - 1235207379Syongari SGE_RX_PAD_BYTES; 1236207379Syongari } else { 1237207379Syongari m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) - 1238207379Syongari ETHER_CRC_LEN; 1239206625Syongari#ifndef __NO_STRICT_ALIGNMENT 1240207379Syongari sge_fixup_rx(m); 1241206625Syongari#endif 1242207379Syongari } 1243206625Syongari m->m_pkthdr.rcvif = ifp; 1244206625Syongari ifp->if_ipackets++; 1245206625Syongari SGE_UNLOCK(sc); 1246206625Syongari (*ifp->if_input)(ifp, m); 1247206625Syongari SGE_LOCK(sc); 1248206625Syongari } 1249206625Syongari 1250206625Syongari if (prog > 0) { 1251206625Syongari bus_dmamap_sync(cd->sge_rx_tag, cd->sge_rx_dmamap, 1252206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1253206625Syongari cd->sge_rx_cons = cons; 1254206625Syongari } 1255206625Syongari} 1256206625Syongari 1257206625Syongari/* 1258206625Syongari * A frame was downloaded to the chip. It's safe for us to clean up 1259206625Syongari * the list buffers. 1260206625Syongari */ 1261206625Syongaristatic void 1262206625Syongarisge_txeof(struct sge_softc *sc) 1263206625Syongari{ 1264206625Syongari struct ifnet *ifp; 1265206625Syongari struct sge_list_data *ld; 1266206625Syongari struct sge_chain_data *cd; 1267207628Syongari struct sge_txdesc *txd; 1268206625Syongari uint32_t txstat; 1269207628Syongari int cons, nsegs, prod; 1270206625Syongari 1271206625Syongari SGE_LOCK_ASSERT(sc); 1272206625Syongari 1273206625Syongari ifp = sc->sge_ifp; 1274206625Syongari ld = &sc->sge_ldata; 1275206625Syongari cd = &sc->sge_cdata; 1276206625Syongari 1277206625Syongari if (cd->sge_tx_cnt == 0) 1278206625Syongari return; 1279206625Syongari bus_dmamap_sync(cd->sge_tx_tag, cd->sge_tx_dmamap, 1280206625Syongari BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1281206625Syongari cons = cd->sge_tx_cons; 1282206625Syongari prod = cd->sge_tx_prod; 1283207628Syongari for (; cons != prod;) { 1284206625Syongari txstat = le32toh(ld->sge_tx_ring[cons].sge_cmdsts); 1285206625Syongari if ((txstat & TDC_OWN) != 0) 1286206625Syongari break; 1287207628Syongari /* 1288207628Syongari * Only the first descriptor of multi-descriptor transmission 1289207628Syongari * is updated by controller. Driver should skip entire 1290207628Syongari * chained buffers for the transmitted frame. In other words 1291207628Syongari * TDC_OWN bit is valid only at the first descriptor of a 1292207628Syongari * multi-descriptor transmission. 1293207628Syongari */ 1294207628Syongari if (SGE_TX_ERROR(txstat) != 0) { 1295206625Syongari#ifdef SGE_SHOW_ERRORS 1296207628Syongari device_printf(sc->sge_dev, "Tx error : 0x%b\n", 1297207628Syongari txstat, TX_ERR_BITS); 1298206625Syongari#endif 1299207628Syongari ifp->if_oerrors++; 1300207628Syongari } else { 1301206625Syongari#ifdef notyet 1302207628Syongari ifp->if_collisions += (txstat & 0xFFFF) - 1; 1303206625Syongari#endif 1304207628Syongari ifp->if_opackets++; 1305206625Syongari } 1306207628Syongari txd = &cd->sge_txdesc[cons]; 1307207628Syongari for (nsegs = 0; nsegs < txd->tx_ndesc; nsegs++) { 1308207628Syongari ld->sge_tx_ring[cons].sge_cmdsts = 0; 1309207628Syongari SGE_INC(cons, SGE_TX_RING_CNT); 1310207628Syongari } 1311207628Syongari /* Reclaim transmitted mbuf. */ 1312207628Syongari KASSERT(txd->tx_m != NULL, 1313207628Syongari ("%s: freeing NULL mbuf\n", __func__)); 1314207628Syongari bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap, 1315207628Syongari BUS_DMASYNC_POSTWRITE); 1316207628Syongari bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap); 1317207628Syongari m_freem(txd->tx_m); 1318207628Syongari txd->tx_m = NULL; 1319207628Syongari cd->sge_tx_cnt -= txd->tx_ndesc; 1320207628Syongari KASSERT(cd->sge_tx_cnt >= 0, 1321207628Syongari ("%s: Active Tx desc counter was garbled\n", __func__)); 1322207628Syongari txd->tx_ndesc = 0; 1323207628Syongari ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1324206625Syongari } 1325206625Syongari cd->sge_tx_cons = cons; 1326206625Syongari if (cd->sge_tx_cnt == 0) 1327206625Syongari sc->sge_timer = 0; 1328206625Syongari} 1329206625Syongari 1330206625Syongaristatic void 1331206625Syongarisge_tick(void *arg) 1332206625Syongari{ 1333206625Syongari struct sge_softc *sc; 1334206625Syongari struct mii_data *mii; 1335206625Syongari struct ifnet *ifp; 1336206625Syongari 1337206625Syongari sc = arg; 1338206625Syongari SGE_LOCK_ASSERT(sc); 1339206625Syongari 1340206625Syongari ifp = sc->sge_ifp; 1341206625Syongari mii = device_get_softc(sc->sge_miibus); 1342206625Syongari mii_tick(mii); 1343206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0) { 1344206625Syongari sge_miibus_statchg(sc->sge_dev); 1345206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) != 0 && 1346206625Syongari !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1347206625Syongari sge_start_locked(ifp); 1348206625Syongari } 1349206625Syongari /* 1350206625Syongari * Reclaim transmitted frames here as we do not request 1351206625Syongari * Tx completion interrupt for every queued frames to 1352206625Syongari * reduce excessive interrupts. 1353206625Syongari */ 1354206625Syongari sge_txeof(sc); 1355206625Syongari sge_watchdog(sc); 1356206625Syongari callout_reset(&sc->sge_stat_ch, hz, sge_tick, sc); 1357206625Syongari} 1358206625Syongari 1359206625Syongaristatic void 1360206625Syongarisge_intr(void *arg) 1361206625Syongari{ 1362206625Syongari struct sge_softc *sc; 1363206625Syongari struct ifnet *ifp; 1364206625Syongari uint32_t status; 1365206625Syongari 1366206625Syongari sc = arg; 1367206625Syongari SGE_LOCK(sc); 1368206625Syongari ifp = sc->sge_ifp; 1369206625Syongari 1370206625Syongari status = CSR_READ_4(sc, IntrStatus); 1371206625Syongari if (status == 0xFFFFFFFF || (status & SGE_INTRS) == 0) { 1372206625Syongari /* Not ours. */ 1373206625Syongari SGE_UNLOCK(sc); 1374206625Syongari return; 1375206625Syongari } 1376206625Syongari /* Acknowledge interrupts. */ 1377206625Syongari CSR_WRITE_4(sc, IntrStatus, status); 1378206625Syongari /* Disable further interrupts. */ 1379206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 1380206625Syongari /* 1381206625Syongari * It seems the controller supports some kind of interrupt 1382206625Syongari * moderation mechanism but we still don't know how to 1383206625Syongari * enable that. To reduce number of generated interrupts 1384206625Syongari * under load we check pending interrupts in a loop. This 1385206625Syongari * will increase number of register access and is not correct 1386206625Syongari * way to handle interrupt moderation but there seems to be 1387206625Syongari * no other way at this time. 1388206625Syongari */ 1389206625Syongari for (;;) { 1390206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1391206625Syongari break; 1392206625Syongari if ((status & (INTR_RX_DONE | INTR_RX_IDLE)) != 0) { 1393206625Syongari sge_rxeof(sc); 1394206625Syongari /* Wakeup Rx MAC. */ 1395206625Syongari if ((status & INTR_RX_IDLE) != 0) 1396206625Syongari CSR_WRITE_4(sc, RX_CTL, 1397206625Syongari 0x1a00 | 0x000c | RX_CTL_POLL | RX_CTL_ENB); 1398206625Syongari } 1399206625Syongari if ((status & (INTR_TX_DONE | INTR_TX_IDLE)) != 0) 1400206625Syongari sge_txeof(sc); 1401206625Syongari status = CSR_READ_4(sc, IntrStatus); 1402206625Syongari if ((status & SGE_INTRS) == 0) 1403206625Syongari break; 1404206625Syongari /* Acknowledge interrupts. */ 1405206625Syongari CSR_WRITE_4(sc, IntrStatus, status); 1406206625Syongari } 1407206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1408206625Syongari /* Re-enable interrupts */ 1409206625Syongari CSR_WRITE_4(sc, IntrMask, SGE_INTRS); 1410206625Syongari if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1411206625Syongari sge_start_locked(ifp); 1412206625Syongari } 1413206625Syongari SGE_UNLOCK(sc); 1414206625Syongari} 1415206625Syongari 1416206625Syongari/* 1417206625Syongari * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data 1418206625Syongari * pointers to the fragment pointers. 1419206625Syongari */ 1420206625Syongaristatic int 1421206625Syongarisge_encap(struct sge_softc *sc, struct mbuf **m_head) 1422206625Syongari{ 1423206625Syongari struct mbuf *m; 1424206625Syongari struct sge_desc *desc; 1425207628Syongari struct sge_txdesc *txd; 1426206625Syongari bus_dma_segment_t txsegs[SGE_MAXTXSEGS]; 1427206625Syongari uint32_t cflags; 1428207628Syongari int error, i, nsegs, prod, si; 1429206625Syongari 1430206625Syongari SGE_LOCK_ASSERT(sc); 1431206625Syongari 1432207628Syongari si = prod = sc->sge_cdata.sge_tx_prod; 1433207628Syongari txd = &sc->sge_cdata.sge_txdesc[prod]; 1434207628Syongari error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, 1435207628Syongari txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); 1436207628Syongari if (error == EFBIG) { 1437207628Syongari m = m_collapse(*m_head, M_DONTWAIT, SGE_MAXTXSEGS); 1438206625Syongari if (m == NULL) { 1439206625Syongari m_freem(*m_head); 1440206625Syongari *m_head = NULL; 1441206625Syongari return (ENOBUFS); 1442206625Syongari } 1443206625Syongari *m_head = m; 1444207628Syongari error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, 1445207628Syongari txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); 1446207628Syongari if (error != 0) { 1447207628Syongari m_freem(*m_head); 1448207628Syongari *m_head = NULL; 1449207628Syongari return (error); 1450207628Syongari } 1451207628Syongari } else if (error != 0) 1452206625Syongari return (error); 1453207628Syongari 1454207628Syongari KASSERT(nsegs != 0, ("zero segment returned")); 1455206625Syongari /* Check descriptor overrun. */ 1456206625Syongari if (sc->sge_cdata.sge_tx_cnt + nsegs >= SGE_TX_RING_CNT) { 1457207628Syongari bus_dmamap_unload(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap); 1458206625Syongari return (ENOBUFS); 1459206625Syongari } 1460207628Syongari bus_dmamap_sync(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap, 1461207545Syongari BUS_DMASYNC_PREWRITE); 1462206625Syongari 1463207628Syongari m = *m_head; 1464206625Syongari cflags = 0; 1465207628Syongari if (m->m_pkthdr.csum_flags & CSUM_IP) 1466206625Syongari cflags |= TDC_IP_CSUM; 1467207628Syongari if (m->m_pkthdr.csum_flags & CSUM_TCP) 1468206625Syongari cflags |= TDC_TCP_CSUM; 1469207628Syongari if (m->m_pkthdr.csum_flags & CSUM_UDP) 1470206625Syongari cflags |= TDC_UDP_CSUM; 1471207628Syongari for (i = 0; i < nsegs; i++) { 1472207628Syongari desc = &sc->sge_ldata.sge_tx_ring[prod]; 1473207628Syongari if (i == 0) { 1474207628Syongari desc->sge_sts_size = htole32(m->m_pkthdr.len); 1475207628Syongari desc->sge_cmdsts = 0; 1476207628Syongari } else { 1477207628Syongari desc->sge_sts_size = 0; 1478207628Syongari desc->sge_cmdsts = htole32(TDC_OWN); 1479207628Syongari } 1480207628Syongari desc->sge_ptr = htole32(SGE_ADDR_LO(txsegs[i].ds_addr)); 1481207628Syongari desc->sge_flags = htole32(txsegs[i].ds_len); 1482207628Syongari if (prod == SGE_TX_RING_CNT - 1) 1483207628Syongari desc->sge_flags |= htole32(RING_END); 1484207628Syongari sc->sge_cdata.sge_tx_cnt++; 1485207628Syongari SGE_INC(prod, SGE_TX_RING_CNT); 1486207628Syongari } 1487207628Syongari /* Update producer index. */ 1488207628Syongari sc->sge_cdata.sge_tx_prod = prod; 1489207628Syongari 1490207628Syongari desc = &sc->sge_ldata.sge_tx_ring[si]; 1491207380Syongari /* Configure VLAN. */ 1492207628Syongari if((m->m_flags & M_VLANTAG) != 0) { 1493207628Syongari cflags |= m->m_pkthdr.ether_vtag; 1494207380Syongari desc->sge_sts_size |= htole32(TDS_INS_VLAN); 1495207380Syongari } 1496207628Syongari desc->sge_cmdsts |= htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags); 1497206625Syongari#if 1 1498206625Syongari if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0) 1499206625Syongari desc->sge_cmdsts |= htole32(TDC_BST); 1500206625Syongari#else 1501206625Syongari if ((sc->sge_flags & SGE_FLAG_FDX) == 0) { 1502206625Syongari desc->sge_cmdsts |= htole32(TDC_COL | TDC_CRS | TDC_BKF); 1503206625Syongari if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0) 1504206625Syongari desc->sge_cmdsts |= htole32(TDC_EXT | TDC_BST); 1505206625Syongari } 1506206625Syongari#endif 1507206625Syongari /* Request interrupt and give ownership to controller. */ 1508207628Syongari desc->sge_cmdsts |= htole32(TDC_OWN | TDC_INTR); 1509207628Syongari txd->tx_m = m; 1510207628Syongari txd->tx_ndesc = nsegs; 1511206625Syongari return (0); 1512206625Syongari} 1513206625Syongari 1514206625Syongaristatic void 1515206625Syongarisge_start(struct ifnet *ifp) 1516206625Syongari{ 1517206625Syongari struct sge_softc *sc; 1518206625Syongari 1519206625Syongari sc = ifp->if_softc; 1520206625Syongari SGE_LOCK(sc); 1521206625Syongari sge_start_locked(ifp); 1522206625Syongari SGE_UNLOCK(sc); 1523206625Syongari} 1524206625Syongari 1525206625Syongaristatic void 1526206625Syongarisge_start_locked(struct ifnet *ifp) 1527206625Syongari{ 1528206625Syongari struct sge_softc *sc; 1529206625Syongari struct mbuf *m_head; 1530206625Syongari int queued = 0; 1531206625Syongari 1532206625Syongari sc = ifp->if_softc; 1533206625Syongari SGE_LOCK_ASSERT(sc); 1534206625Syongari 1535206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0 || 1536206625Syongari (ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1537206625Syongari IFF_DRV_RUNNING) 1538206625Syongari return; 1539206625Syongari 1540206625Syongari for (queued = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) { 1541207628Syongari if (sc->sge_cdata.sge_tx_cnt > (SGE_TX_RING_CNT - 1542207628Syongari SGE_MAXTXSEGS)) { 1543206625Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1544206625Syongari break; 1545206625Syongari } 1546206625Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 1547206625Syongari if (m_head == NULL) 1548206625Syongari break; 1549206625Syongari if (sge_encap(sc, &m_head)) { 1550206625Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 1551206625Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1552206625Syongari break; 1553206625Syongari } 1554206625Syongari queued++; 1555206625Syongari /* 1556206625Syongari * If there's a BPF listener, bounce a copy of this frame 1557206625Syongari * to him. 1558206625Syongari */ 1559206625Syongari BPF_MTAP(ifp, m_head); 1560206625Syongari } 1561206625Syongari 1562206625Syongari if (queued > 0) { 1563206625Syongari bus_dmamap_sync(sc->sge_cdata.sge_tx_tag, 1564206625Syongari sc->sge_cdata.sge_tx_dmamap, 1565206625Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1566206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00 | TX_CTL_ENB | TX_CTL_POLL); 1567206625Syongari sc->sge_timer = 5; 1568206625Syongari } 1569206625Syongari} 1570206625Syongari 1571206625Syongaristatic void 1572206625Syongarisge_init(void *arg) 1573206625Syongari{ 1574206625Syongari struct sge_softc *sc; 1575206625Syongari 1576206625Syongari sc = arg; 1577206625Syongari SGE_LOCK(sc); 1578206625Syongari sge_init_locked(sc); 1579206625Syongari SGE_UNLOCK(sc); 1580206625Syongari} 1581206625Syongari 1582206625Syongaristatic void 1583206625Syongarisge_init_locked(struct sge_softc *sc) 1584206625Syongari{ 1585206625Syongari struct ifnet *ifp; 1586206625Syongari struct mii_data *mii; 1587207379Syongari uint16_t rxfilt; 1588206625Syongari int i; 1589206625Syongari 1590206625Syongari SGE_LOCK_ASSERT(sc); 1591206625Syongari ifp = sc->sge_ifp; 1592206625Syongari mii = device_get_softc(sc->sge_miibus); 1593206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1594206625Syongari return; 1595206625Syongari /* 1596206625Syongari * Cancel pending I/O and free all RX/TX buffers. 1597206625Syongari */ 1598206625Syongari sge_stop(sc); 1599206625Syongari sge_reset(sc); 1600206625Syongari 1601206625Syongari /* Init circular RX list. */ 1602206625Syongari if (sge_list_rx_init(sc) == ENOBUFS) { 1603206625Syongari device_printf(sc->sge_dev, "no memory for Rx buffers\n"); 1604206625Syongari sge_stop(sc); 1605206625Syongari return; 1606206625Syongari } 1607206625Syongari /* Init TX descriptors. */ 1608206625Syongari sge_list_tx_init(sc); 1609206625Syongari /* 1610206625Syongari * Load the address of the RX and TX lists. 1611206625Syongari */ 1612206625Syongari CSR_WRITE_4(sc, TX_DESC, SGE_ADDR_LO(sc->sge_ldata.sge_tx_paddr)); 1613206625Syongari CSR_WRITE_4(sc, RX_DESC, SGE_ADDR_LO(sc->sge_ldata.sge_rx_paddr)); 1614206625Syongari 1615206625Syongari CSR_WRITE_4(sc, TxMacControl, 0x60); 1616206625Syongari CSR_WRITE_4(sc, RxWakeOnLan, 0); 1617206625Syongari CSR_WRITE_4(sc, RxWakeOnLanData, 0); 1618206625Syongari /* Allow receiving VLAN frames. */ 1619207379Syongari if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) 1620207379Syongari CSR_WRITE_2(sc, RxMPSControl, 1621207379Syongari ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN + SGE_RX_PAD_BYTES); 1622207379Syongari else 1623207379Syongari CSR_WRITE_2(sc, RxMPSControl, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN); 1624206625Syongari 1625206625Syongari for (i = 0; i < ETHER_ADDR_LEN; i++) 1626206625Syongari CSR_WRITE_1(sc, RxMacAddr + i, IF_LLADDR(ifp)[i]); 1627207379Syongari /* Configure RX MAC. */ 1628207379Syongari rxfilt = 0; 1629207379Syongari if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) 1630207379Syongari rxfilt |= RXMAC_STRIP_FCS | RXMAC_PAD_ENB; 1631207379Syongari CSR_WRITE_2(sc, RxMacControl, rxfilt); 1632206625Syongari sge_rxfilter(sc); 1633207380Syongari sge_setvlan(sc); 1634206625Syongari 1635206625Syongari /* Initialize default speed/duplex information. */ 1636206625Syongari if ((sc->sge_flags & SGE_FLAG_FASTETHER) == 0) 1637206625Syongari sc->sge_flags |= SGE_FLAG_SPEED_1000; 1638206625Syongari sc->sge_flags |= SGE_FLAG_FDX; 1639206625Syongari if ((sc->sge_flags & SGE_FLAG_RGMII) != 0) 1640206625Syongari CSR_WRITE_4(sc, StationControl, 0x04008001); 1641206625Syongari else 1642206625Syongari CSR_WRITE_4(sc, StationControl, 0x04000001); 1643206625Syongari /* 1644206625Syongari * XXX Try to mitigate interrupts. 1645206625Syongari */ 1646207071Syongari CSR_WRITE_4(sc, IntrControl, 0x08880000); 1647207071Syongari#ifdef notyet 1648206625Syongari if (sc->sge_intrcontrol != 0) 1649206625Syongari CSR_WRITE_4(sc, IntrControl, sc->sge_intrcontrol); 1650206625Syongari if (sc->sge_intrtimer != 0) 1651206625Syongari CSR_WRITE_4(sc, IntrTimer, sc->sge_intrtimer); 1652207071Syongari#endif 1653206625Syongari 1654206625Syongari /* 1655206625Syongari * Clear and enable interrupts. 1656206625Syongari */ 1657206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xFFFFFFFF); 1658206625Syongari CSR_WRITE_4(sc, IntrMask, SGE_INTRS); 1659206625Syongari 1660206625Syongari /* Enable receiver and transmitter. */ 1661206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00 | TX_CTL_ENB); 1662206625Syongari CSR_WRITE_4(sc, RX_CTL, 0x1a00 | 0x000c | RX_CTL_POLL | RX_CTL_ENB); 1663206625Syongari 1664206625Syongari ifp->if_drv_flags |= IFF_DRV_RUNNING; 1665206625Syongari ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1666206625Syongari 1667206625Syongari sc->sge_flags &= ~SGE_FLAG_LINK; 1668206625Syongari mii_mediachg(mii); 1669206625Syongari callout_reset(&sc->sge_stat_ch, hz, sge_tick, sc); 1670206625Syongari} 1671206625Syongari 1672206625Syongari/* 1673206625Syongari * Set media options. 1674206625Syongari */ 1675206625Syongaristatic int 1676206625Syongarisge_ifmedia_upd(struct ifnet *ifp) 1677206625Syongari{ 1678206625Syongari struct sge_softc *sc; 1679206625Syongari struct mii_data *mii; 1680206625Syongari int error; 1681206625Syongari 1682206625Syongari sc = ifp->if_softc; 1683206625Syongari SGE_LOCK(sc); 1684206625Syongari mii = device_get_softc(sc->sge_miibus); 1685206625Syongari if (mii->mii_instance) { 1686206625Syongari struct mii_softc *miisc; 1687206625Syongari LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 1688206625Syongari mii_phy_reset(miisc); 1689206625Syongari } 1690206625Syongari error = mii_mediachg(mii); 1691206625Syongari SGE_UNLOCK(sc); 1692206625Syongari 1693206625Syongari return (error); 1694206625Syongari} 1695206625Syongari 1696206625Syongari/* 1697206625Syongari * Report current media status. 1698206625Syongari */ 1699206625Syongaristatic void 1700206625Syongarisge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 1701206625Syongari{ 1702206625Syongari struct sge_softc *sc; 1703206625Syongari struct mii_data *mii; 1704206625Syongari 1705206625Syongari sc = ifp->if_softc; 1706206625Syongari SGE_LOCK(sc); 1707206625Syongari mii = device_get_softc(sc->sge_miibus); 1708206625Syongari if ((ifp->if_flags & IFF_UP) == 0) { 1709206625Syongari SGE_UNLOCK(sc); 1710206625Syongari return; 1711206625Syongari } 1712206625Syongari mii_pollstat(mii); 1713206625Syongari SGE_UNLOCK(sc); 1714206625Syongari ifmr->ifm_active = mii->mii_media_active; 1715206625Syongari ifmr->ifm_status = mii->mii_media_status; 1716206625Syongari} 1717206625Syongari 1718206625Syongaristatic int 1719206625Syongarisge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 1720206625Syongari{ 1721206625Syongari struct sge_softc *sc; 1722206625Syongari struct ifreq *ifr; 1723206625Syongari struct mii_data *mii; 1724207380Syongari int error = 0, mask, reinit; 1725206625Syongari 1726206625Syongari sc = ifp->if_softc; 1727206625Syongari ifr = (struct ifreq *)data; 1728206625Syongari 1729206625Syongari switch(command) { 1730206625Syongari case SIOCSIFFLAGS: 1731206625Syongari SGE_LOCK(sc); 1732206625Syongari if ((ifp->if_flags & IFF_UP) != 0) { 1733206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 1734206625Syongari ((ifp->if_flags ^ sc->sge_if_flags) & 1735206625Syongari (IFF_PROMISC | IFF_ALLMULTI)) != 0) 1736206625Syongari sge_rxfilter(sc); 1737206625Syongari else 1738206625Syongari sge_init_locked(sc); 1739206625Syongari } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1740206625Syongari sge_stop(sc); 1741206625Syongari sc->sge_if_flags = ifp->if_flags; 1742206625Syongari SGE_UNLOCK(sc); 1743206625Syongari break; 1744206625Syongari case SIOCSIFCAP: 1745206625Syongari SGE_LOCK(sc); 1746207380Syongari reinit = 0; 1747206625Syongari mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1748206625Syongari if ((mask & IFCAP_TXCSUM) != 0 && 1749206625Syongari (ifp->if_capabilities & IFCAP_TXCSUM) != 0) { 1750206625Syongari ifp->if_capenable ^= IFCAP_TXCSUM; 1751206625Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 1752206625Syongari ifp->if_hwassist |= SGE_CSUM_FEATURES; 1753206625Syongari else 1754206625Syongari ifp->if_hwassist &= ~SGE_CSUM_FEATURES; 1755206625Syongari } 1756206625Syongari if ((mask & IFCAP_RXCSUM) != 0 && 1757206625Syongari (ifp->if_capabilities & IFCAP_RXCSUM) != 0) 1758206625Syongari ifp->if_capenable ^= IFCAP_RXCSUM; 1759207380Syongari if ((mask & IFCAP_VLAN_HWCSUM) != 0 && 1760207380Syongari (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0) 1761207380Syongari ifp->if_capenable ^= IFCAP_VLAN_HWCSUM; 1762207380Syongari if ((mask & IFCAP_VLAN_HWTAGGING) != 0 && 1763207380Syongari (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) { 1764207380Syongari /* 1765207380Syongari * Due to unknown reason, toggling VLAN hardware 1766207380Syongari * tagging require interface reinitialization. 1767207380Syongari */ 1768207380Syongari ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 1769207380Syongari reinit = 1; 1770207380Syongari } 1771207380Syongari if (reinit > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1772207380Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1773207380Syongari sge_init_locked(sc); 1774207380Syongari } 1775206625Syongari SGE_UNLOCK(sc); 1776207380Syongari VLAN_CAPABILITIES(ifp); 1777206625Syongari break; 1778206625Syongari case SIOCADDMULTI: 1779206625Syongari case SIOCDELMULTI: 1780206625Syongari SGE_LOCK(sc); 1781206625Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1782206625Syongari sge_rxfilter(sc); 1783206625Syongari SGE_UNLOCK(sc); 1784206625Syongari break; 1785206625Syongari case SIOCGIFMEDIA: 1786206625Syongari case SIOCSIFMEDIA: 1787206625Syongari mii = device_get_softc(sc->sge_miibus); 1788206625Syongari error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 1789206625Syongari break; 1790206625Syongari default: 1791206625Syongari error = ether_ioctl(ifp, command, data); 1792206625Syongari break; 1793206625Syongari } 1794206625Syongari 1795206625Syongari return (error); 1796206625Syongari} 1797206625Syongari 1798206625Syongaristatic void 1799206625Syongarisge_watchdog(struct sge_softc *sc) 1800206625Syongari{ 1801206625Syongari struct ifnet *ifp; 1802206625Syongari 1803206625Syongari SGE_LOCK_ASSERT(sc); 1804206625Syongari if (sc->sge_timer == 0 || --sc->sge_timer > 0) 1805206625Syongari return; 1806206625Syongari 1807206625Syongari ifp = sc->sge_ifp; 1808206625Syongari if ((sc->sge_flags & SGE_FLAG_LINK) == 0) { 1809206625Syongari if (1 || bootverbose) 1810206625Syongari device_printf(sc->sge_dev, 1811206625Syongari "watchdog timeout (lost link)\n"); 1812206625Syongari ifp->if_oerrors++; 1813206625Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1814206625Syongari sge_init_locked(sc); 1815206625Syongari return; 1816206625Syongari } 1817206625Syongari device_printf(sc->sge_dev, "watchdog timeout\n"); 1818206625Syongari ifp->if_oerrors++; 1819206625Syongari 1820206625Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1821206625Syongari sge_init_locked(sc); 1822206625Syongari if (!IFQ_DRV_IS_EMPTY(&sc->sge_ifp->if_snd)) 1823206625Syongari sge_start_locked(ifp); 1824206625Syongari} 1825206625Syongari 1826206625Syongari/* 1827206625Syongari * Stop the adapter and free any mbufs allocated to the 1828206625Syongari * RX and TX lists. 1829206625Syongari */ 1830206625Syongaristatic void 1831206625Syongarisge_stop(struct sge_softc *sc) 1832206625Syongari{ 1833206625Syongari struct ifnet *ifp; 1834206625Syongari 1835206625Syongari ifp = sc->sge_ifp; 1836206625Syongari 1837206625Syongari SGE_LOCK_ASSERT(sc); 1838206625Syongari 1839206625Syongari sc->sge_timer = 0; 1840206625Syongari callout_stop(&sc->sge_stat_ch); 1841206625Syongari ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 1842206625Syongari 1843206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 1844206625Syongari CSR_READ_4(sc, IntrMask); 1845206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 1846206625Syongari /* Stop TX/RX MAC. */ 1847206625Syongari CSR_WRITE_4(sc, TX_CTL, 0x1a00); 1848206625Syongari CSR_WRITE_4(sc, RX_CTL, 0x1a00); 1849206625Syongari /* XXX Can we assume active DMA cycles gone? */ 1850206625Syongari DELAY(2000); 1851206625Syongari CSR_WRITE_4(sc, IntrMask, 0); 1852206625Syongari CSR_WRITE_4(sc, IntrStatus, 0xffffffff); 1853206625Syongari 1854206625Syongari sc->sge_flags &= ~SGE_FLAG_LINK; 1855206625Syongari sge_list_rx_free(sc); 1856206625Syongari sge_list_tx_free(sc); 1857206625Syongari} 1858