if_ste.c revision 51455
1194676Sthompsa/* 2194676Sthompsa * Copyright (c) 1997, 1998, 1999 3194676Sthompsa * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4195957Salfred * 5194676Sthompsa * Redistribution and use in source and binary forms, with or without 6194676Sthompsa * modification, are permitted provided that the following conditions 7194676Sthompsa * are met: 8194676Sthompsa * 1. Redistributions of source code must retain the above copyright 9194676Sthompsa * notice, this list of conditions and the following disclaimer. 10194676Sthompsa * 2. Redistributions in binary form must reproduce the above copyright 11194676Sthompsa * notice, this list of conditions and the following disclaimer in the 12194676Sthompsa * documentation and/or other materials provided with the distribution. 13194676Sthompsa * 3. All advertising materials mentioning features or use of this software 14194676Sthompsa * must display the following acknowledgement: 15194676Sthompsa * This product includes software developed by Bill Paul. 16194676Sthompsa * 4. Neither the name of the author nor the names of any co-contributors 17194676Sthompsa * may be used to endorse or promote products derived from this software 18194676Sthompsa * without specific prior written permission. 19194676Sthompsa * 20194676Sthompsa * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21194676Sthompsa * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22194676Sthompsa * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23194676Sthompsa * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24194676Sthompsa * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25194676Sthompsa * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26194676Sthompsa * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27194676Sthompsa * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28194676Sthompsa * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29194676Sthompsa * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30194676Sthompsa * THE POSSIBILITY OF SUCH DAMAGE. 31194676Sthompsa * 32194676Sthompsa * $FreeBSD: head/sys/pci/if_ste.c 51455 1999-09-20 08:47:11Z wpaul $ 33194676Sthompsa */ 34194676Sthompsa 35195957Salfred 36195957Salfred#include "bpf.h" 37195957Salfred 38199055Sthompsa#include <sys/param.h> 39194676Sthompsa#include <sys/systm.h> 40194676Sthompsa#include <sys/sockio.h> 41194676Sthompsa#include <sys/mbuf.h> 42194676Sthompsa#include <sys/malloc.h> 43194676Sthompsa#include <sys/kernel.h> 44194676Sthompsa#include <sys/socket.h> 45194676Sthompsa 46194676Sthompsa#include <net/if.h> 47194676Sthompsa#include <net/if_arp.h> 48194676Sthompsa#include <net/ethernet.h> 49195957Salfred#include <net/if_dl.h> 50195957Salfred#include <net/if_media.h> 51195957Salfred 52195957Salfred#if NBPF > 0 53195957Salfred#include <net/bpf.h> 54195957Salfred#endif 55195957Salfred 56195957Salfred#include "opt_bdg.h" 57195957Salfred#ifdef BRIDGE 58195957Salfred#include <net/bridge.h> 59195957Salfred#endif 60195957Salfred 61194676Sthompsa#include <vm/vm.h> /* for vtophys */ 62194676Sthompsa#include <vm/pmap.h> /* for vtophys */ 63194676Sthompsa#include <machine/clock.h> /* for DELAY */ 64195957Salfred#include <machine/bus_memio.h> 65194676Sthompsa#include <machine/bus_pio.h> 66195957Salfred#include <machine/bus.h> 67194676Sthompsa#include <machine/resource.h> 68194676Sthompsa#include <sys/bus.h> 69194676Sthompsa#include <sys/rman.h> 70194676Sthompsa 71194676Sthompsa#include <dev/mii/mii.h> 72195957Salfred#include <dev/mii/miivar.h> 73194676Sthompsa 74194676Sthompsa#include <pci/pcireg.h> 75195957Salfred#include <pci/pcivar.h> 76194676Sthompsa 77194676Sthompsa/* "controller miibus0" required. See GENERIC if you get errors here. */ 78194676Sthompsa#include "miibus_if.h" 79194676Sthompsa 80194676Sthompsa#define STE_USEIOSPACE 81194676Sthompsa 82194676Sthompsa#include <pci/if_stereg.h> 83194676Sthompsa 84194676Sthompsa#if !defined(lint) 85194676Sthompsastatic const char rcsid[] = 86194676Sthompsa "$FreeBSD: head/sys/pci/if_ste.c 51455 1999-09-20 08:47:11Z wpaul $"; 87194676Sthompsa#endif 88194676Sthompsa 89194676Sthompsa/* 90195957Salfred * Various supported device vendors/types and their names. 91195957Salfred */ 92194676Sthompsastatic struct ste_type ste_devs[] = { 93195957Salfred { ST_VENDORID, ST_DEVICEID_ST201, "Sundance ST201 10/100BaseTX" }, 94195957Salfred { DL_VENDORID, DL_DEVICEID_550TX, "D-Link DFE-550TX 10/100BaseTX" }, 95194676Sthompsa { 0, 0, NULL } 96195957Salfred}; 97194676Sthompsa 98194676Sthompsastatic int ste_probe __P((device_t)); 99194676Sthompsastatic int ste_attach __P((device_t)); 100195957Salfredstatic int ste_detach __P((device_t)); 101195957Salfredstatic void ste_init __P((void *)); 102194676Sthompsastatic void ste_intr __P((void *)); 103194676Sthompsastatic void ste_rxeof __P((struct ste_softc *)); 104194676Sthompsastatic void ste_txeoc __P((struct ste_softc *)); 105195957Salfredstatic void ste_txeof __P((struct ste_softc *)); 106195957Salfredstatic void ste_stats_update __P((void *)); 107195957Salfredstatic void ste_stop __P((struct ste_softc *)); 108195957Salfredstatic void ste_reset __P((struct ste_softc *)); 109195957Salfredstatic int ste_ioctl __P((struct ifnet *, u_long, caddr_t)); 110194676Sthompsastatic int ste_encap __P((struct ste_softc *, struct ste_chain *, 111195957Salfred struct mbuf *)); 112194676Sthompsastatic void ste_start __P((struct ifnet *)); 113194676Sthompsastatic void ste_watchdog __P((struct ifnet *)); 114194676Sthompsastatic void ste_shutdown __P((device_t)); 115194676Sthompsastatic int ste_newbuf __P((struct ste_softc *, 116194676Sthompsa struct ste_chain_onefrag *, 117194676Sthompsa struct mbuf *)); 118194676Sthompsastatic int ste_ifmedia_upd __P((struct ifnet *)); 119194676Sthompsastatic void ste_ifmedia_sts __P((struct ifnet *, struct ifmediareq *)); 120194676Sthompsa 121194676Sthompsastatic void ste_mii_sync __P((struct ste_softc *)); 122195957Salfredstatic void ste_mii_send __P((struct ste_softc *, u_int32_t, int)); 123195957Salfredstatic int ste_mii_readreg __P((struct ste_softc *, 124194676Sthompsa struct ste_mii_frame *)); 125194676Sthompsastatic int ste_mii_writereg __P((struct ste_softc *, 126194676Sthompsa struct ste_mii_frame *)); 127194676Sthompsastatic int ste_miibus_readreg __P((device_t, int, int)); 128195957Salfredstatic int ste_miibus_writereg __P((device_t, int, int, int)); 129194676Sthompsastatic void ste_miibus_statchg __P((device_t)); 130195957Salfred 131194676Sthompsastatic int ste_eeprom_wait __P((struct ste_softc *)); 132195957Salfredstatic int ste_read_eeprom __P((struct ste_softc *, caddr_t, int, 133195957Salfred int, int)); 134195957Salfredstatic void ste_wait __P((struct ste_softc *)); 135195957Salfredstatic u_int8_t ste_calchash __P((caddr_t)); 136195957Salfredstatic void ste_setmulti __P((struct ste_softc *)); 137195957Salfredstatic int ste_init_rx_list __P((struct ste_softc *)); 138194676Sthompsastatic void ste_init_tx_list __P((struct ste_softc *)); 139194676Sthompsa 140195957Salfred#ifdef STE_USEIOSPACE 141195957Salfred#define STE_RES SYS_RES_IOPORT 142194676Sthompsa#define STE_RID STE_PCI_LOIO 143194676Sthompsa#else 144194676Sthompsa#define STE_RES SYS_RES_MEMORY 145194676Sthompsa#define STE_RID STE_PCI_LOMEM 146194676Sthompsa#endif 147194676Sthompsa 148194676Sthompsastatic device_method_t ste_methods[] = { 149194676Sthompsa /* Device interface */ 150194676Sthompsa DEVMETHOD(device_probe, ste_probe), 151194676Sthompsa DEVMETHOD(device_attach, ste_attach), 152194676Sthompsa DEVMETHOD(device_detach, ste_detach), 153194676Sthompsa DEVMETHOD(device_shutdown, ste_shutdown), 154194676Sthompsa 155195957Salfred /* bus interface */ 156194676Sthompsa DEVMETHOD(bus_print_child, bus_generic_print_child), 157195957Salfred DEVMETHOD(bus_driver_added, bus_generic_driver_added), 158194676Sthompsa 159194676Sthompsa /* MII interface */ 160194676Sthompsa DEVMETHOD(miibus_readreg, ste_miibus_readreg), 161194676Sthompsa DEVMETHOD(miibus_writereg, ste_miibus_writereg), 162195957Salfred DEVMETHOD(miibus_statchg, ste_miibus_statchg), 163194676Sthompsa 164195957Salfred { 0, 0 } 165195957Salfred}; 166195957Salfred 167195957Salfredstatic driver_t ste_driver = { 168195957Salfred "ste", 169195957Salfred ste_methods, 170194676Sthompsa sizeof(struct ste_softc) 171194676Sthompsa}; 172195957Salfred 173194676Sthompsastatic devclass_t ste_devclass; 174195957Salfred 175194676SthompsaDRIVER_MODULE(if_ste, pci, ste_driver, ste_devclass, 0, 0); 176194676SthompsaDRIVER_MODULE(miibus, if_ste, miibus_driver, miibus_devclass, 0, 0); 177194676Sthompsa 178194676Sthompsa#define STE_SETBIT4(sc, reg, x) \ 179194676Sthompsa CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | x) 180195957Salfred 181194676Sthompsa#define STE_CLRBIT4(sc, reg, x) \ 182194676Sthompsa CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) & ~x) 183194676Sthompsa 184194676Sthompsa#define STE_SETBIT2(sc, reg, x) \ 185194676Sthompsa CSR_WRITE_2(sc, reg, CSR_READ_2(sc, reg) | x) 186195957Salfred 187194676Sthompsa#define STE_CLRBIT2(sc, reg, x) \ 188194676Sthompsa CSR_WRITE_2(sc, reg, CSR_READ_2(sc, reg) & ~x) 189194676Sthompsa 190194676Sthompsa#define STE_SETBIT1(sc, reg, x) \ 191194676Sthompsa CSR_WRITE_1(sc, reg, CSR_READ_1(sc, reg) | x) 192195560Sthompsa 193195560Sthompsa#define STE_CLRBIT1(sc, reg, x) \ 194195560Sthompsa CSR_WRITE_1(sc, reg, CSR_READ_1(sc, reg) & ~x) 195195560Sthompsa 196194676Sthompsa 197195957Salfred#define MII_SET(x) STE_SETBIT1(sc, STE_PHYCTL, x) 198194676Sthompsa#define MII_CLR(x) STE_CLRBIT1(sc, STE_PHYCTL, x) 199194676Sthompsa 200194676Sthompsa/* 201199055Sthompsa * Sync the PHYs by setting data bit and strobing the clock 32 times. 202199055Sthompsa */ 203199055Sthompsastatic void ste_mii_sync(sc) 204199055Sthompsa struct ste_softc *sc; 205194676Sthompsa{ 206194676Sthompsa register int i; 207195957Salfred 208195957Salfred MII_SET(STE_PHYCTL_MDIR|STE_PHYCTL_MDATA); 209195957Salfred 210195957Salfred for (i = 0; i < 32; i++) { 211194676Sthompsa MII_SET(STE_PHYCTL_MCLK); 212194676Sthompsa DELAY(1); 213194676Sthompsa MII_CLR(STE_PHYCTL_MCLK); 214194676Sthompsa DELAY(1); 215195957Salfred } 216194676Sthompsa 217194676Sthompsa return; 218194676Sthompsa} 219194676Sthompsa 220194676Sthompsa/* 221194676Sthompsa * Clock a series of bits through the MII. 222194676Sthompsa */ 223194676Sthompsastatic void ste_mii_send(sc, bits, cnt) 224194676Sthompsa struct ste_softc *sc; 225194676Sthompsa u_int32_t bits; 226194676Sthompsa int cnt; 227194676Sthompsa{ 228194676Sthompsa int i; 229194676Sthompsa 230194676Sthompsa MII_CLR(STE_PHYCTL_MCLK); 231194676Sthompsa 232195957Salfred for (i = (0x1 << (cnt - 1)); i; i >>= 1) { 233194676Sthompsa if (bits & i) { 234194676Sthompsa MII_SET(STE_PHYCTL_MDATA); 235194676Sthompsa } else { 236194676Sthompsa MII_CLR(STE_PHYCTL_MDATA); 237194676Sthompsa } 238194676Sthompsa DELAY(1); 239194676Sthompsa MII_CLR(STE_PHYCTL_MCLK); 240194676Sthompsa DELAY(1); 241194676Sthompsa MII_SET(STE_PHYCTL_MCLK); 242195957Salfred } 243194676Sthompsa} 244194676Sthompsa 245195957Salfred/* 246195957Salfred * Read an PHY register through the MII. 247194676Sthompsa */ 248194676Sthompsastatic int ste_mii_readreg(sc, frame) 249194676Sthompsa struct ste_softc *sc; 250195957Salfred struct ste_mii_frame *frame; 251194676Sthompsa 252194676Sthompsa{ 253195957Salfred int i, ack, s; 254195957Salfred 255194676Sthompsa s = splimp(); 256194676Sthompsa 257194676Sthompsa /* 258195957Salfred * Set up frame for RX. 259194676Sthompsa */ 260194676Sthompsa frame->mii_stdelim = STE_MII_STARTDELIM; 261194676Sthompsa frame->mii_opcode = STE_MII_READOP; 262194676Sthompsa frame->mii_turnaround = 0; 263194676Sthompsa frame->mii_data = 0; 264195957Salfred 265195957Salfred CSR_WRITE_2(sc, STE_PHYCTL, 0); 266195957Salfred /* 267195957Salfred * Turn on data xmit. 268194676Sthompsa */ 269194676Sthompsa MII_SET(STE_PHYCTL_MDIR); 270194676Sthompsa 271194676Sthompsa ste_mii_sync(sc); 272195957Salfred 273195957Salfred /* 274195957Salfred * Send command/address info. 275195957Salfred */ 276194676Sthompsa ste_mii_send(sc, frame->mii_stdelim, 2); 277195957Salfred ste_mii_send(sc, frame->mii_opcode, 2); 278194676Sthompsa ste_mii_send(sc, frame->mii_phyaddr, 5); 279195957Salfred ste_mii_send(sc, frame->mii_regaddr, 5); 280194676Sthompsa 281195957Salfred /* Turn off xmit. */ 282194676Sthompsa MII_CLR(STE_PHYCTL_MDIR); 283194676Sthompsa 284194676Sthompsa /* Idle bit */ 285194676Sthompsa MII_CLR((STE_PHYCTL_MCLK|STE_PHYCTL_MDATA)); 286194676Sthompsa DELAY(1); 287194676Sthompsa MII_SET(STE_PHYCTL_MCLK); 288194676Sthompsa DELAY(1); 289194676Sthompsa 290194676Sthompsa /* Check for ack */ 291194676Sthompsa MII_CLR(STE_PHYCTL_MCLK); 292194676Sthompsa DELAY(1); 293194676Sthompsa MII_SET(STE_PHYCTL_MCLK); 294194676Sthompsa DELAY(1); 295194676Sthompsa ack = CSR_READ_2(sc, STE_PHYCTL) & STE_PHYCTL_MDATA; 296194676Sthompsa 297195957Salfred /* 298194676Sthompsa * Now try reading data bits. If the ack failed, we still 299194676Sthompsa * need to clock through 16 cycles to keep the PHY(s) in sync. 300195957Salfred */ 301194676Sthompsa if (ack) { 302195957Salfred for(i = 0; i < 16; i++) { 303194676Sthompsa MII_CLR(STE_PHYCTL_MCLK); 304195957Salfred DELAY(1); 305194676Sthompsa MII_SET(STE_PHYCTL_MCLK); 306194676Sthompsa DELAY(1); 307194676Sthompsa } 308194676Sthompsa goto fail; 309194676Sthompsa } 310195957Salfred 311194676Sthompsa for (i = 0x8000; i; i >>= 1) { 312194676Sthompsa MII_CLR(STE_PHYCTL_MCLK); 313195957Salfred DELAY(1); 314194676Sthompsa if (!ack) { 315195957Salfred if (CSR_READ_2(sc, STE_PHYCTL) & STE_PHYCTL_MDATA) 316194676Sthompsa frame->mii_data |= i; 317195957Salfred DELAY(1); 318194676Sthompsa } 319194676Sthompsa MII_SET(STE_PHYCTL_MCLK); 320194676Sthompsa DELAY(1); 321194676Sthompsa } 322194676Sthompsa 323194676Sthompsafail: 324194676Sthompsa 325194676Sthompsa MII_CLR(STE_PHYCTL_MCLK); 326195957Salfred DELAY(1); 327194676Sthompsa MII_SET(STE_PHYCTL_MCLK); 328194676Sthompsa DELAY(1); 329194676Sthompsa 330195957Salfred splx(s); 331194676Sthompsa 332194676Sthompsa if (ack) 333194676Sthompsa return(1); 334194676Sthompsa return(0); 335194676Sthompsa} 336195957Salfred 337195957Salfred/* 338194676Sthompsa * Write to a PHY register through the MII. 339195957Salfred */ 340195957Salfredstatic int ste_mii_writereg(sc, frame) 341195957Salfred struct ste_softc *sc; 342195957Salfred struct ste_mii_frame *frame; 343194676Sthompsa 344194676Sthompsa{ 345195957Salfred int s; 346194676Sthompsa 347194676Sthompsa s = splimp(); 348195957Salfred /* 349194676Sthompsa * Set up frame for TX. 350194676Sthompsa */ 351195957Salfred 352195957Salfred frame->mii_stdelim = STE_MII_STARTDELIM; 353194676Sthompsa frame->mii_opcode = STE_MII_WRITEOP; 354195957Salfred frame->mii_turnaround = STE_MII_TURNAROUND; 355195957Salfred 356195957Salfred /* 357194676Sthompsa * Turn on data output. 358195957Salfred */ 359194676Sthompsa MII_SET(STE_PHYCTL_MDIR); 360194676Sthompsa 361194676Sthompsa ste_mii_sync(sc); 362194676Sthompsa 363194676Sthompsa ste_mii_send(sc, frame->mii_stdelim, 2); 364195957Salfred ste_mii_send(sc, frame->mii_opcode, 2); 365194676Sthompsa ste_mii_send(sc, frame->mii_phyaddr, 5); 366194676Sthompsa ste_mii_send(sc, frame->mii_regaddr, 5); 367194676Sthompsa ste_mii_send(sc, frame->mii_turnaround, 2); 368194676Sthompsa ste_mii_send(sc, frame->mii_data, 16); 369194676Sthompsa 370195957Salfred /* Idle bit. */ 371195957Salfred MII_SET(STE_PHYCTL_MCLK); 372194676Sthompsa DELAY(1); 373195957Salfred MII_CLR(STE_PHYCTL_MCLK); 374195957Salfred DELAY(1); 375195957Salfred 376195957Salfred /* 377195560Sthompsa * Turn off xmit. 378194676Sthompsa */ 379194676Sthompsa MII_CLR(STE_PHYCTL_MDIR); 380194676Sthompsa 381194676Sthompsa splx(s); 382195957Salfred 383195957Salfred return(0); 384194676Sthompsa} 385195957Salfred 386194676Sthompsastatic int ste_miibus_readreg(dev, phy, reg) 387195957Salfred device_t dev; 388195957Salfred int phy, reg; 389195957Salfred{ 390195957Salfred struct ste_softc *sc; 391195957Salfred struct ste_mii_frame frame; 392194676Sthompsa 393195560Sthompsa sc = device_get_softc(dev); 394195957Salfred 395195957Salfred bzero((char *)&frame, sizeof(frame)); 396195957Salfred 397195560Sthompsa frame.mii_phyaddr = phy; 398194676Sthompsa frame.mii_regaddr = reg; 399194676Sthompsa ste_mii_readreg(sc, &frame); 400194676Sthompsa 401195560Sthompsa return(frame.mii_data); 402195957Salfred} 403194676Sthompsa 404194676Sthompsastatic int ste_miibus_writereg(dev, phy, reg, data) 405194676Sthompsa device_t dev; 406195957Salfred int phy, reg, data; 407194676Sthompsa{ 408194676Sthompsa struct ste_softc *sc; 409195957Salfred struct ste_mii_frame frame; 410195957Salfred 411194676Sthompsa sc = device_get_softc(dev); 412194676Sthompsa bzero((char *)&frame, sizeof(frame)); 413195957Salfred 414195957Salfred frame.mii_phyaddr = phy; 415194676Sthompsa frame.mii_regaddr = reg; 416195957Salfred frame.mii_data = data; 417195957Salfred 418194676Sthompsa ste_mii_writereg(sc, &frame); 419195957Salfred 420194676Sthompsa return(0); 421195957Salfred} 422199055Sthompsa 423199055Sthompsastatic void ste_miibus_statchg(dev) 424195957Salfred device_t dev; 425194676Sthompsa{ 426195957Salfred struct ste_softc *sc; 427195957Salfred struct mii_data *mii; 428194676Sthompsa 429195957Salfred sc = device_get_softc(dev); 430195957Salfred mii = device_get_softc(sc->ste_miibus); 431195957Salfred 432194676Sthompsa if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { 433194676Sthompsa STE_SETBIT2(sc, STE_MACCTL0, STE_MACCTL0_FULLDUPLEX); 434194676Sthompsa } else { 435194676Sthompsa STE_CLRBIT2(sc, STE_MACCTL0, STE_MACCTL0_FULLDUPLEX); 436195957Salfred } 437194676Sthompsa 438195957Salfred return; 439194676Sthompsa} 440195957Salfred 441194676Sthompsastatic int ste_ifmedia_upd(ifp) 442194676Sthompsa struct ifnet *ifp; 443194676Sthompsa{ 444195957Salfred struct ste_softc *sc; 445194676Sthompsa struct mii_data *mii; 446195957Salfred 447194676Sthompsa sc = ifp->if_softc; 448195957Salfred mii = device_get_softc(sc->ste_miibus); 449194676Sthompsa mii_mediachg(mii); 450194676Sthompsa 451195957Salfred return(0); 452195957Salfred} 453195957Salfred 454194676Sthompsastatic void ste_ifmedia_sts(ifp, ifmr) 455195957Salfred struct ifnet *ifp; 456195957Salfred struct ifmediareq *ifmr; 457195957Salfred{ 458195957Salfred struct ste_softc *sc; 459194676Sthompsa struct mii_data *mii; 460194676Sthompsa 461194676Sthompsa sc = ifp->if_softc; 462194676Sthompsa mii = device_get_softc(sc->ste_miibus); 463195957Salfred 464194676Sthompsa mii_pollstat(mii); 465195957Salfred ifmr->ifm_active = mii->mii_media_active; 466195957Salfred ifmr->ifm_status = mii->mii_media_status; 467195957Salfred 468195957Salfred return; 469194676Sthompsa} 470195957Salfred 471194676Sthompsastatic void ste_wait(sc) 472195957Salfred struct ste_softc *sc; 473194676Sthompsa{ 474194676Sthompsa register int i; 475195957Salfred 476195957Salfred for (i = 0; i < STE_TIMEOUT; i++) { 477195957Salfred if (!(CSR_READ_4(sc, STE_DMACTL) & STE_DMACTL_DMA_HALTINPROG)) 478195957Salfred break; 479195957Salfred } 480195957Salfred 481194676Sthompsa if (i == STE_TIMEOUT) 482195957Salfred printf("ste%d: command never completed!\n", sc->ste_unit); 483195957Salfred 484195957Salfred return; 485195957Salfred} 486195957Salfred 487195957Salfred/* 488195957Salfred * The EEPROM is slow: give it time to come ready after issuing 489195957Salfred * it a command. 490195957Salfred */ 491195957Salfredstatic int ste_eeprom_wait(sc) 492195957Salfred struct ste_softc *sc; 493195957Salfred{ 494195957Salfred int i; 495195957Salfred 496195957Salfred DELAY(1000); 497195957Salfred 498195957Salfred for (i = 0; i < 100; i++) { 499195957Salfred if (CSR_READ_2(sc, STE_EEPROM_CTL) & STE_EECTL_BUSY) 500195957Salfred DELAY(1000); 501195957Salfred else 502195957Salfred break; 503195957Salfred } 504195957Salfred 505195957Salfred if (i == 100) { 506195957Salfred printf("ste%d: eeprom failed to come ready\n", sc->ste_unit); 507194676Sthompsa return(1); 508194676Sthompsa } 509194676Sthompsa 510195957Salfred return(0); 511194676Sthompsa} 512195957Salfred 513195957Salfred/* 514194676Sthompsa * Read a sequence of words from the EEPROM. Note that ethernet address 515195957Salfred * data is stored in the EEPROM in network byte order. 516194676Sthompsa */ 517194676Sthompsastatic int ste_read_eeprom(sc, dest, off, cnt, swap) 518194676Sthompsa struct ste_softc *sc; 519195957Salfred caddr_t dest; 520194676Sthompsa int off; 521194676Sthompsa int cnt; 522195957Salfred int swap; 523194676Sthompsa{ 524195957Salfred int err = 0, i; 525194676Sthompsa u_int16_t word = 0, *ptr; 526195957Salfred 527194676Sthompsa if (ste_eeprom_wait(sc)) 528195957Salfred return(1); 529195957Salfred 530194676Sthompsa for (i = 0; i < cnt; i++) { 531194676Sthompsa CSR_WRITE_2(sc, STE_EEPROM_CTL, STE_EEOPCODE_READ | (off + i)); 532194676Sthompsa err = ste_eeprom_wait(sc); 533195957Salfred if (err) 534194676Sthompsa break; 535195957Salfred word = CSR_READ_2(sc, STE_EEPROM_DATA); 536195957Salfred ptr = (u_int16_t *)(dest + (i * 2)); 537194676Sthompsa if (swap) 538195957Salfred *ptr = ntohs(word); 539194676Sthompsa else 540194676Sthompsa *ptr = word; 541194676Sthompsa } 542195957Salfred 543194676Sthompsa return(err ? 1 : 0); 544194676Sthompsa} 545195957Salfred 546194676Sthompsastatic u_int8_t ste_calchash(addr) 547195957Salfred caddr_t addr; 548194676Sthompsa{ 549195957Salfred 550194676Sthompsa u_int32_t crc, carry; 551195957Salfred int i, j; 552195957Salfred u_int8_t c; 553194676Sthompsa 554194676Sthompsa /* Compute CRC for the address value. */ 555194676Sthompsa crc = 0xFFFFFFFF; /* initial value */ 556195957Salfred 557194676Sthompsa for (i = 0; i < 6; i++) { 558194676Sthompsa c = *(addr + i); 559195957Salfred for (j = 0; j < 8; j++) { 560195957Salfred carry = ((crc & 0x80000000) ? 1 : 0) ^ (c & 0x01); 561194676Sthompsa crc <<= 1; 562195957Salfred c >>= 1; 563194676Sthompsa if (carry) 564194676Sthompsa crc = (crc ^ 0x04c11db6) | carry; 565194676Sthompsa } 566195957Salfred } 567194676Sthompsa 568194676Sthompsa /* return the filter bit position */ 569195957Salfred return(crc & 0x0000003F); 570195957Salfred} 571195957Salfred 572195957Salfredstatic void ste_setmulti(sc) 573194676Sthompsa struct ste_softc *sc; 574195957Salfred{ 575195957Salfred struct ifnet *ifp; 576195957Salfred int h = 0; 577195957Salfred u_int32_t hashes[2] = { 0, 0 }; 578195957Salfred struct ifmultiaddr *ifma; 579195957Salfred 580195957Salfred ifp = &sc->arpcom.ac_if; 581195957Salfred if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 582195957Salfred STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI); 583195957Salfred STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH); 584195957Salfred return; 585195957Salfred } 586195957Salfred 587195957Salfred /* first, zot all the existing hash bits */ 588195957Salfred CSR_WRITE_4(sc, STE_MAR0, 0); 589194676Sthompsa CSR_WRITE_4(sc, STE_MAR1, 0); 590194676Sthompsa 591195957Salfred /* now program new ones */ 592195957Salfred for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL; 593195957Salfred ifma = ifma->ifma_link.le_next) { 594195957Salfred if (ifma->ifma_addr->sa_family != AF_LINK) 595195957Salfred continue; 596195957Salfred h = ste_calchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); 597195957Salfred if (h < 32) 598195957Salfred hashes[0] |= (1 << h); 599195957Salfred else 600195957Salfred hashes[1] |= (1 << (h - 32)); 601195957Salfred } 602195957Salfred 603195957Salfred CSR_WRITE_4(sc, STE_MAR0, hashes[0]); 604195957Salfred CSR_WRITE_4(sc, STE_MAR1, hashes[1]); 605195957Salfred STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_ALLMULTI); 606194676Sthompsa STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_MULTIHASH); 607195957Salfred 608194676Sthompsa return; 609194676Sthompsa} 610195957Salfred 611195957Salfredstatic void ste_intr(xsc) 612194676Sthompsa void *xsc; 613195957Salfred{ 614195560Sthompsa struct ste_softc *sc; 615195957Salfred struct ifnet *ifp; 616194676Sthompsa u_int16_t status; 617195957Salfred 618195957Salfred sc = xsc; 619195957Salfred ifp = &sc->arpcom.ac_if; 620195957Salfred 621195957Salfred /* See if this is really our interrupt. */ 622195957Salfred if (!(CSR_READ_2(sc, STE_ISR) & STE_ISR_INTLATCH)) 623195957Salfred return; 624194676Sthompsa 625194676Sthompsa for (;;) { 626194676Sthompsa status = CSR_READ_2(sc, STE_ISR_ACK); 627195957Salfred 628195957Salfred if (!(status & STE_INTRS)) 629195957Salfred break; 630195957Salfred 631194676Sthompsa if (status & STE_ISR_RX_DMADONE) 632195957Salfred ste_rxeof(sc); 633195957Salfred 634195957Salfred if (status & STE_ISR_TX_DMADONE) 635194676Sthompsa ste_txeof(sc); 636194676Sthompsa 637194676Sthompsa if (status & STE_ISR_TX_DONE) 638195957Salfred ste_txeoc(sc); 639194676Sthompsa 640195957Salfred if (status & STE_ISR_STATS_OFLOW) { 641195957Salfred untimeout(ste_stats_update, sc, sc->ste_stat_ch); 642194676Sthompsa ste_stats_update(sc); 643195957Salfred } 644194676Sthompsa 645194676Sthompsa if (status & STE_ISR_HOSTERR) { 646194676Sthompsa ste_reset(sc); 647195957Salfred ste_init(sc); 648195957Salfred } 649195957Salfred } 650195957Salfred 651195957Salfred /* Re-enable interrupts */ 652195957Salfred CSR_WRITE_2(sc, STE_IMR, STE_INTRS); 653195957Salfred 654195957Salfred if (ifp->if_snd.ifq_head != NULL) 655195957Salfred ste_start(ifp); 656195957Salfred 657195957Salfred return; 658194676Sthompsa} 659194676Sthompsa 660194676Sthompsa/* 661195957Salfred * A frame has been uploaded: pass the resulting mbuf chain up to 662194676Sthompsa * the higher level protocols. 663195957Salfred */ 664194676Sthompsastatic void ste_rxeof(sc) 665194676Sthompsa struct ste_softc *sc; 666195957Salfred{ 667195957Salfred struct ether_header *eh; 668194676Sthompsa struct mbuf *m; 669194676Sthompsa struct ifnet *ifp; 670194676Sthompsa struct ste_chain_onefrag *cur_rx; 671195957Salfred int total_len = 0; 672194676Sthompsa u_int32_t rxstat; 673195957Salfred 674194676Sthompsa ifp = &sc->arpcom.ac_if; 675195957Salfred 676194676Sthompsaagain: 677194676Sthompsa 678195957Salfred while((rxstat = sc->ste_cdata.ste_rx_head->ste_ptr->ste_status)) { 679195957Salfred cur_rx = sc->ste_cdata.ste_rx_head; 680194676Sthompsa sc->ste_cdata.ste_rx_head = cur_rx->ste_next; 681195957Salfred 682194676Sthompsa /* 683194676Sthompsa * If an error occurs, update stats, clear the 684194676Sthompsa * status word and leave the mbuf cluster in place: 685195957Salfred * it should simply get re-used next time this descriptor 686194676Sthompsa * comes up in the ring. 687195957Salfred */ 688194676Sthompsa if (rxstat & STE_RXSTAT_FRAME_ERR) { 689195957Salfred ifp->if_ierrors++; 690194676Sthompsa cur_rx->ste_ptr->ste_status = 0; 691194676Sthompsa continue; 692194676Sthompsa } 693194676Sthompsa 694194676Sthompsa /* 695194676Sthompsa * If there error bit was not set, the upload complete 696194676Sthompsa * bit should be set which means we have a valid packet. 697194676Sthompsa * If not, something truly strange has happened. 698195957Salfred */ 699195957Salfred if (!(rxstat & STE_RXSTAT_DMADONE)) { 700194676Sthompsa printf("ste%d: bad receive status -- packet dropped", 701194676Sthompsa sc->ste_unit); 702194676Sthompsa ifp->if_ierrors++; 703195957Salfred cur_rx->ste_ptr->ste_status = 0; 704194676Sthompsa continue; 705194676Sthompsa } 706195957Salfred 707195957Salfred /* No errors; receive the packet. */ 708194676Sthompsa m = cur_rx->ste_mbuf; 709194676Sthompsa total_len = cur_rx->ste_ptr->ste_status & STE_RXSTAT_FRAMELEN; 710195957Salfred 711194676Sthompsa /* 712195957Salfred * Try to conjure up a new mbuf cluster. If that 713195957Salfred * fails, it means we have an out of memory condition and 714194676Sthompsa * should leave the buffer in place and continue. This will 715195957Salfred * result in a lost packet, but there's little else we 716195957Salfred * can do in this situation. 717195957Salfred */ 718195957Salfred if (ste_newbuf(sc, cur_rx, NULL) == ENOBUFS) { 719194676Sthompsa ifp->if_ierrors++; 720194676Sthompsa cur_rx->ste_ptr->ste_status = 0; 721194676Sthompsa continue; 722195957Salfred } 723194676Sthompsa 724195957Salfred ifp->if_ipackets++; 725194676Sthompsa eh = mtod(m, struct ether_header *); 726195957Salfred m->m_pkthdr.rcvif = ifp; 727195957Salfred m->m_pkthdr.len = m->m_len = total_len; 728194676Sthompsa 729195957Salfred#if NBPF > 0 730195957Salfred /* Handle BPF listeners. Let the BPF user see the packet. */ 731194676Sthompsa if (ifp->if_bpf) 732195957Salfred bpf_mtap(ifp, m); 733194676Sthompsa#endif 734194676Sthompsa 735195560Sthompsa#ifdef BRIDGE 736195957Salfred if (do_bridge) { 737195560Sthompsa struct ifnet *bdg_ifp ; 738195560Sthompsa bdg_ifp = bridge_in(m); 739195560Sthompsa if (bdg_ifp != BDG_LOCAL && bdg_ifp != BDG_DROP) 740195560Sthompsa bdg_forward(&m, bdg_ifp); 741195560Sthompsa if (((bdg_ifp != BDG_LOCAL) && (bdg_ifp != BDG_BCAST) && 742195560Sthompsa (bdg_ifp != BDG_MCAST)) || bdg_ifp == BDG_DROP) { 743195560Sthompsa m_freem(m); 744195560Sthompsa continue; 745195560Sthompsa } 746195560Sthompsa } 747195560Sthompsa#endif 748195560Sthompsa 749195957Salfred#if NBPF > 0 750195957Salfred /* 751195560Sthompsa * Don't pass packet up to the ether_input() layer unless it's 752195957Salfred * a broadcast packet, multicast packet, matches our ethernet 753195560Sthompsa * address or the interface is in promiscuous mode. 754195957Salfred */ 755195560Sthompsa if (ifp->if_bpf) { 756195560Sthompsa if (ifp->if_flags & IFF_PROMISC && 757195957Salfred (bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr, 758195560Sthompsa ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)){ 759195560Sthompsa m_freem(m); 760195957Salfred continue; 761195560Sthompsa } 762195957Salfred } 763195560Sthompsa#endif 764195560Sthompsa 765195560Sthompsa /* Remove header from mbuf and pass it on. */ 766195957Salfred m_adj(m, sizeof(struct ether_header)); 767195560Sthompsa ether_input(ifp, eh, m); 768195560Sthompsa } 769195560Sthompsa 770195560Sthompsa /* 771195560Sthompsa * Handle the 'end of channel' condition. When the upload 772195560Sthompsa * engine hits the end of the RX ring, it will stall. This 773195560Sthompsa * is our cue to flush the RX ring, reload the uplist pointer 774195560Sthompsa * register and unstall the engine. 775195957Salfred * XXX This is actually a little goofy. With the ThunderLAN 776195957Salfred * chip, you get an interrupt when the receiver hits the end 777195560Sthompsa * of the receive ring, which tells you exactly when you 778195957Salfred * you need to reload the ring pointer. Here we have to 779195957Salfred * fake it. I'm mad at myself for not being clever enough 780195957Salfred * to avoid the use of a goto here. 781195560Sthompsa */ 782195957Salfred if (CSR_READ_4(sc, STE_RX_DMALIST_PTR) == 0 || 783195957Salfred CSR_READ_4(sc, STE_DMACTL) & STE_DMACTL_RXDMA_STOPPED) { 784195957Salfred STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL); 785195957Salfred ste_wait(sc); 786195957Salfred CSR_WRITE_4(sc, STE_RX_DMALIST_PTR, 787195957Salfred vtophys(&sc->ste_ldata->ste_rx_list[0])); 788195957Salfred sc->ste_cdata.ste_rx_head = &sc->ste_cdata.ste_rx_chain[0]; 789195957Salfred STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_UNSTALL); 790195957Salfred goto again; 791195560Sthompsa } 792195957Salfred 793195560Sthompsa return; 794195957Salfred} 795195560Sthompsa 796195560Sthompsastatic void ste_txeoc(sc) 797195957Salfred struct ste_softc *sc; 798195957Salfred{ 799195957Salfred u_int8_t txstat; 800195957Salfred struct ifnet *ifp; 801195957Salfred 802195957Salfred ifp = &sc->arpcom.ac_if; 803195957Salfred 804195957Salfred while ((txstat = CSR_READ_1(sc, STE_TX_STATUS)) & 805195957Salfred STE_TXSTATUS_TXDONE) { 806195957Salfred if (txstat & STE_TXSTATUS_UNDERRUN || 807195957Salfred txstat & STE_TXSTATUS_EXCESSCOLLS || 808195957Salfred txstat & STE_TXSTATUS_RECLAIMERR) { 809195957Salfred ifp->if_oerrors++; 810195957Salfred printf("ste%d: transmission error: %x\n", 811195957Salfred sc->ste_unit, txstat); 812195957Salfred STE_SETBIT4(sc, STE_ASICCTL, STE_ASICCTL_TX_RESET); 813195957Salfred 814195957Salfred if (sc->ste_cdata.ste_tx_head != NULL) 815195957Salfred CSR_WRITE_4(sc, STE_TX_DMALIST_PTR, 816195957Salfred vtophys(sc->ste_cdata.ste_tx_head->ste_ptr)); 817195957Salfred if (txstat & STE_TXSTATUS_UNDERRUN && 818195957Salfred sc->ste_tx_thresh < STE_PACKET_SIZE) { 819195957Salfred sc->ste_tx_thresh += STE_MIN_FRAMELEN; 820195957Salfred printf("ste%d: tx underrun, increasing tx" 821195957Salfred " start threshold to %d bytes\n", 822195957Salfred sc->ste_unit, sc->ste_tx_thresh); 823194676Sthompsa } 824195957Salfred CSR_WRITE_2(sc, STE_TX_STARTTHRESH, sc->ste_tx_thresh); 825195957Salfred CSR_WRITE_2(sc, STE_TX_RECLAIM_THRESH, 826194676Sthompsa (STE_PACKET_SIZE >> 4)); 827195957Salfred } 828195957Salfred ste_init(sc); 829195957Salfred CSR_WRITE_2(sc, STE_TX_STATUS, txstat); 830195957Salfred } 831195957Salfred 832195957Salfred return; 833195957Salfred} 834195957Salfred 835195957Salfredstatic void ste_txeof(sc) 836199575Sthompsa struct ste_softc *sc; 837195957Salfred{ 838195957Salfred struct ste_chain *cur_tx; 839199575Sthompsa struct ifnet *ifp; 840199575Sthompsa 841199575Sthompsa ifp = &sc->arpcom.ac_if; 842195957Salfred 843195957Salfred /* Clear the timeout timer. */ 844195957Salfred ifp->if_timer = 0; 845195957Salfred 846195957Salfred while(sc->ste_cdata.ste_tx_head != NULL) { 847195957Salfred cur_tx = sc->ste_cdata.ste_tx_head; 848195957Salfred if (!(cur_tx->ste_ptr->ste_ctl & STE_TXCTL_DMADONE)) 849195957Salfred break; 850195957Salfred sc->ste_cdata.ste_tx_head = cur_tx->ste_next; 851195957Salfred 852195957Salfred m_freem(cur_tx->ste_mbuf); 853195957Salfred cur_tx->ste_mbuf = NULL; 854195957Salfred ifp->if_opackets++; 855195957Salfred 856195957Salfred cur_tx->ste_next = sc->ste_cdata.ste_tx_free; 857194676Sthompsa sc->ste_cdata.ste_tx_free = cur_tx; 858195957Salfred } 859194676Sthompsa 860195957Salfred if (sc->ste_cdata.ste_tx_head == NULL) { 861195957Salfred ifp->if_flags &= ~IFF_OACTIVE; 862195957Salfred sc->ste_cdata.ste_tx_tail = NULL; 863195957Salfred } else { 864194676Sthompsa if (CSR_READ_4(sc, STE_DMACTL) & STE_DMACTL_TXDMA_STOPPED || 865195957Salfred !CSR_READ_4(sc, STE_TX_DMALIST_PTR)) { 866195957Salfred CSR_WRITE_4(sc, STE_TX_DMALIST_PTR, 867195957Salfred vtophys(sc->ste_cdata.ste_tx_head->ste_ptr)); 868195957Salfred CSR_WRITE_4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL); 869195957Salfred } 870195957Salfred } 871195957Salfred 872195957Salfred return; 873195957Salfred} 874195957Salfred 875195957Salfredstatic void ste_stats_update(xsc) 876195957Salfred void *xsc; 877195957Salfred{ 878195957Salfred struct ste_softc *sc; 879195957Salfred struct ste_stats stats; 880195957Salfred struct ifnet *ifp; 881195957Salfred struct mii_data *mii; 882194676Sthompsa int i, s; 883194676Sthompsa u_int8_t *p; 884195560Sthompsa 885195957Salfred s = splimp(); 886195957Salfred 887195957Salfred sc = xsc; 888195957Salfred ifp = &sc->arpcom.ac_if; 889195957Salfred mii = device_get_softc(sc->ste_miibus); 890195957Salfred 891195957Salfred p = (u_int8_t *)&stats; 892195957Salfred 893195560Sthompsa for (i = 0; i < sizeof(stats); i++) { 894194676Sthompsa *p = CSR_READ_1(sc, STE_STATS + i); 895195957Salfred p++; 896195957Salfred } 897195957Salfred 898195957Salfred ifp->if_collisions += stats.ste_single_colls + 899195957Salfred stats.ste_multi_colls + stats.ste_late_colls; 900195957Salfred 901195957Salfred mii_tick(mii); 902195957Salfred 903194676Sthompsa sc->ste_stat_ch = timeout(ste_stats_update, sc, hz); 904195957Salfred splx(s); 905195957Salfred 906195957Salfred return; 907195957Salfred} 908195957Salfred 909195957Salfred 910195957Salfred/* 911195957Salfred * Probe for a Sundance ST201 chip. Check the PCI vendor and device 912195957Salfred * IDs against our list and return a device name if we find a match. 913195957Salfred */ 914195957Salfredstatic int ste_probe(dev) 915194676Sthompsa device_t dev; 916195957Salfred{ 917195957Salfred struct ste_type *t; 918194676Sthompsa 919195957Salfred t = ste_devs; 920194676Sthompsa 921195957Salfred while(t->ste_name != NULL) { 922195957Salfred if ((pci_get_vendor(dev) == t->ste_vid) && 923195957Salfred (pci_get_device(dev) == t->ste_did)) { 924195957Salfred device_set_desc(dev, t->ste_name); 925195957Salfred return(0); 926195957Salfred } 927195957Salfred t++; 928195957Salfred } 929195957Salfred 930195957Salfred return(ENXIO); 931195957Salfred} 932195957Salfred 933195957Salfred/* 934195957Salfred * Attach the interface. Allocate softc structures, do ifmedia 935195957Salfred * setup and ethernet/BPF attach. 936195957Salfred */ 937195957Salfredstatic int ste_attach(dev) 938195957Salfred device_t dev; 939195957Salfred{ 940195957Salfred int s; 941195957Salfred u_int32_t command; 942195957Salfred struct ste_softc *sc; 943195957Salfred struct ifnet *ifp; 944195957Salfred int unit, error = 0, rid; 945195957Salfred 946194676Sthompsa s = splimp(); 947194676Sthompsa 948195957Salfred sc = device_get_softc(dev); 949195957Salfred unit = device_get_unit(dev); 950195957Salfred bzero(sc, sizeof(struct ste_softc)); 951195957Salfred 952195957Salfred /* 953195957Salfred * Handle power management nonsense. 954195957Salfred */ 955195957Salfred command = pci_read_config(dev, STE_PCI_CAPID, 4) & 0x000000FF; 956195957Salfred if (command == 0x01) { 957195957Salfred 958195957Salfred command = pci_read_config(dev, STE_PCI_PWRMGMTCTRL, 4); 959195957Salfred if (command & STE_PSTATE_MASK) { 960195957Salfred u_int32_t iobase, membase, irq; 961195957Salfred 962195957Salfred /* Save important PCI config data. */ 963195957Salfred iobase = pci_read_config(dev, STE_PCI_LOIO, 4); 964195957Salfred membase = pci_read_config(dev, STE_PCI_LOMEM, 4); 965195957Salfred irq = pci_read_config(dev, STE_PCI_INTLINE, 4); 966195957Salfred 967195957Salfred /* Reset the power state. */ 968195957Salfred printf("ste%d: chip is in D%d power mode " 969195957Salfred "-- setting to D0\n", unit, command & STE_PSTATE_MASK); 970195957Salfred command &= 0xFFFFFFFC; 971195957Salfred pci_write_config(dev, STE_PCI_PWRMGMTCTRL, command, 4); 972195957Salfred 973195957Salfred /* Restore PCI config data. */ 974195957Salfred pci_write_config(dev, STE_PCI_LOIO, iobase, 4); 975195957Salfred pci_write_config(dev, STE_PCI_LOMEM, membase, 4); 976195957Salfred pci_write_config(dev, STE_PCI_INTLINE, irq, 4); 977195957Salfred } 978195957Salfred } 979195957Salfred 980195957Salfred /* 981195957Salfred * Map control/status registers. 982195957Salfred */ 983195957Salfred command = pci_read_config(dev, PCI_COMMAND_STATUS_REG, 4); 984195957Salfred command |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); 985195957Salfred pci_write_config(dev, PCI_COMMAND_STATUS_REG, command, 4); 986195957Salfred command = pci_read_config(dev, PCI_COMMAND_STATUS_REG, 4); 987195957Salfred 988195957Salfred#ifdef STE_USEIOSPACE 989195957Salfred if (!(command & PCIM_CMD_PORTEN)) { 990194676Sthompsa printf("ste%d: failed to enable I/O ports!\n", unit); 991194676Sthompsa error = ENXIO; 992194676Sthompsa goto fail; 993195957Salfred } 994195957Salfred#else 995195957Salfred if (!(command & PCIM_CMD_MEMEN)) { 996195957Salfred printf("ste%d: failed to enable memory mapping!\n", unit); 997194676Sthompsa error = ENXIO; 998195957Salfred goto fail; 999195957Salfred } 1000195957Salfred#endif 1001195957Salfred 1002195957Salfred rid = STE_RID; 1003195957Salfred sc->ste_res = bus_alloc_resource(dev, STE_RES, &rid, 1004194676Sthompsa 0, ~0, 1, RF_ACTIVE); 1005195957Salfred 1006195957Salfred if (sc->ste_res == NULL) { 1007195957Salfred printf ("ste%d: couldn't map ports/memory\n", unit); 1008195957Salfred error = ENXIO; 1009194676Sthompsa goto fail; 1010195957Salfred } 1011195957Salfred 1012194676Sthompsa sc->ste_btag = rman_get_bustag(sc->ste_res); 1013195957Salfred sc->ste_bhandle = rman_get_bushandle(sc->ste_res); 1014195957Salfred 1015194676Sthompsa rid = 0; 1016195957Salfred sc->ste_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 1017194676Sthompsa RF_SHAREABLE | RF_ACTIVE); 1018195957Salfred 1019195957Salfred if (sc->ste_irq == NULL) { 1020194676Sthompsa printf("ste%d: couldn't map interrupt\n", unit); 1021195957Salfred bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res); 1022195957Salfred error = ENXIO; 1023195957Salfred goto fail; 1024195957Salfred } 1025195957Salfred 1026195957Salfred error = bus_setup_intr(dev, sc->ste_irq, INTR_TYPE_NET, 1027195957Salfred ste_intr, sc, &sc->ste_intrhand); 1028195957Salfred 1029195957Salfred if (error) { 1030195957Salfred bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq); 1031195957Salfred bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res); 1032195957Salfred printf("ste%d: couldn't set up irq\n", unit); 1033195957Salfred goto fail; 1034194676Sthompsa } 1035195957Salfred 1036195957Salfred callout_handle_init(&sc->ste_stat_ch); 1037195957Salfred 1038195957Salfred /* Reset the adapter. */ 1039195957Salfred ste_reset(sc); 1040195957Salfred 1041194676Sthompsa /* 1042195957Salfred * Get station address from the EEPROM. 1043195957Salfred */ 1044195957Salfred if (ste_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr, 1045195957Salfred STE_EEADDR_NODE0, 3, 0)) { 1046195957Salfred printf("ste%d: failed to read station address\n", unit); 1047195957Salfred bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand); 1048195957Salfred bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq); 1049195957Salfred bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res); 1050195957Salfred error = ENXIO;; 1051195957Salfred goto fail; 1052195957Salfred } 1053195957Salfred 1054195957Salfred /* 1055195957Salfred * A Sundance chip was detected. Inform the world. 1056195957Salfred */ 1057195957Salfred printf("ste%d: Ethernet address: %6D\n", unit, 1058195957Salfred sc->arpcom.ac_enaddr, ":"); 1059195957Salfred 1060195957Salfred sc->ste_unit = unit; 1061195957Salfred 1062195957Salfred /* Allocate the descriptor queues. */ 1063195957Salfred sc->ste_ldata = contigmalloc(sizeof(struct ste_list_data), M_DEVBUF, 1064195957Salfred M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0); 1065195957Salfred 1066195957Salfred if (sc->ste_ldata == NULL) { 1067195957Salfred printf("ste%d: no memory for list buffers!\n", unit); 1068195957Salfred bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand); 1069195957Salfred bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq); 1070195957Salfred bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res); 1071195957Salfred error = ENXIO; 1072195957Salfred goto fail; 1073195957Salfred } 1074195957Salfred 1075195957Salfred bzero(sc->ste_ldata, sizeof(struct ste_list_data)); 1076195957Salfred 1077195957Salfred /* Do MII setup. */ 1078195957Salfred if (mii_phy_probe(dev, &sc->ste_miibus, 1079194676Sthompsa ste_ifmedia_upd, ste_ifmedia_sts)) { 1080195957Salfred printf("ste%d: MII without any phy!\n", sc->ste_unit); 1081195957Salfred bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand); 1082195957Salfred bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq); 1083195957Salfred bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res); 1084195957Salfred free(sc->ste_ldata, M_DEVBUF); 1085195957Salfred error = ENXIO; 1086195957Salfred goto fail; 1087195957Salfred } 1088195957Salfred 1089195957Salfred ifp = &sc->arpcom.ac_if; 1090195957Salfred ifp->if_softc = sc; 1091195957Salfred ifp->if_unit = unit; 1092195957Salfred ifp->if_name = "ste"; 1093195957Salfred ifp->if_mtu = ETHERMTU; 1094195957Salfred ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 1095195957Salfred ifp->if_ioctl = ste_ioctl; 1096195957Salfred ifp->if_output = ether_output; 1097195957Salfred ifp->if_start = ste_start; 1098195957Salfred ifp->if_watchdog = ste_watchdog; 1099195957Salfred ifp->if_init = ste_init; 1100195957Salfred ifp->if_baudrate = 10000000; 1101195957Salfred ifp->if_snd.ifq_maxlen = STE_TX_LIST_CNT - 1; 1102195957Salfred 1103195957Salfred /* 1104195957Salfred * Call MI attach routines. 1105195957Salfred */ 1106195957Salfred 1107195957Salfred if_attach(ifp); 1108195957Salfred ether_ifattach(ifp); 1109195957Salfred 1110195957Salfred#if NBPF > 0 1111195957Salfred bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); 1112195957Salfred#endif 1113195957Salfred 1114195957Salfredfail: 1115195957Salfred splx(s); 1116195957Salfred return(error); 1117195957Salfred} 1118199575Sthompsa 1119199575Sthompsastatic int ste_detach(dev) 1120195957Salfred device_t dev; 1121195957Salfred{ 1122195957Salfred struct ste_softc *sc; 1123195957Salfred struct ifnet *ifp; 1124195957Salfred int s; 1125195957Salfred 1126195957Salfred s = splimp(); 1127199575Sthompsa 1128199575Sthompsa sc = device_get_softc(dev); 1129195957Salfred ifp = &sc->arpcom.ac_if; 1130195957Salfred 1131195957Salfred ste_stop(sc); 1132195957Salfred if_detach(ifp); 1133195957Salfred 1134195957Salfred bus_generic_detach(dev); 1135195957Salfred device_delete_child(dev, sc->ste_miibus); 1136194676Sthompsa 1137195957Salfred bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand); 1138195957Salfred bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq); 1139195957Salfred bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res); 1140195957Salfred 1141195957Salfred free(sc->ste_ldata, M_DEVBUF); 1142195957Salfred 1143195957Salfred splx(s); 1144195957Salfred 1145195957Salfred return(0); 1146195957Salfred} 1147195957Salfred 1148194676Sthompsastatic int ste_newbuf(sc, c, m) 1149195957Salfred struct ste_softc *sc; 1150195957Salfred struct ste_chain_onefrag *c; 1151194676Sthompsa struct mbuf *m; 1152195957Salfred{ 1153194676Sthompsa struct mbuf *m_new = NULL; 1154195957Salfred 1155195957Salfred if (m == NULL) { 1156194676Sthompsa MGETHDR(m_new, M_DONTWAIT, MT_DATA); 1157195957Salfred if (m_new == NULL) { 1158195957Salfred printf("ste%d: no memory for rx list -- " 1159195957Salfred "packet dropped\n", sc->ste_unit); 1160195957Salfred return(ENOBUFS); 1161194676Sthompsa } 1162195957Salfred MCLGET(m_new, M_DONTWAIT); 1163195957Salfred if (!(m_new->m_flags & M_EXT)) { 1164195957Salfred printf("ste%d: no memory for rx list -- " 1165195957Salfred "packet dropped\n", sc->ste_unit); 1166195957Salfred m_freem(m_new); 1167195957Salfred return(ENOBUFS); 1168195957Salfred } 1169195957Salfred m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 1170195957Salfred } else { 1171195957Salfred m_new = m; 1172195957Salfred m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; 1173195957Salfred m_new->m_data = m_new->m_ext.ext_buf; 1174194676Sthompsa } 1175195957Salfred 1176195957Salfred m_adj(m_new, ETHER_ALIGN); 1177195957Salfred 1178195957Salfred c->ste_mbuf = m_new; 1179195957Salfred c->ste_ptr->ste_status = 0; 1180195957Salfred c->ste_ptr->ste_frag.ste_addr = vtophys(mtod(m_new, caddr_t)); 1181195560Sthompsa c->ste_ptr->ste_frag.ste_len = 1536 | STE_FRAG_LAST; 1182195957Salfred 1183195957Salfred return(0); 1184195957Salfred} 1185195957Salfred 1186195957Salfredstatic int ste_init_rx_list(sc) 1187195957Salfred struct ste_softc *sc; 1188195957Salfred{ 1189195957Salfred struct ste_chain_data *cd; 1190194676Sthompsa struct ste_list_data *ld; 1191195957Salfred int i; 1192195957Salfred 1193194676Sthompsa cd = &sc->ste_cdata; 1194195957Salfred ld = sc->ste_ldata; 1195195957Salfred 1196194676Sthompsa for (i = 0; i < STE_RX_LIST_CNT; i++) { 1197195957Salfred cd->ste_rx_chain[i].ste_ptr = &ld->ste_rx_list[i]; 1198195957Salfred if (ste_newbuf(sc, &cd->ste_rx_chain[i], NULL) == ENOBUFS) 1199195957Salfred return(ENOBUFS); 1200195957Salfred if (i == (STE_RX_LIST_CNT - 1)) { 1201194676Sthompsa cd->ste_rx_chain[i].ste_next = 1202195957Salfred &cd->ste_rx_chain[0]; 1203194676Sthompsa ld->ste_rx_list[i].ste_next = 1204195957Salfred vtophys(&ld->ste_rx_list[0]); 1205195957Salfred } else { 1206195957Salfred cd->ste_rx_chain[i].ste_next = 1207195957Salfred &cd->ste_rx_chain[i + 1]; 1208195957Salfred ld->ste_rx_list[i].ste_next = 1209195957Salfred vtophys(&ld->ste_rx_list[i + 1]); 1210195957Salfred } 1211199055Sthompsa 1212195957Salfred } 1213195957Salfred 1214195957Salfred cd->ste_rx_head = &cd->ste_rx_chain[0]; 1215195957Salfred 1216195957Salfred return(0); 1217195957Salfred} 1218195957Salfred 1219195957Salfredstatic void ste_init_tx_list(sc) 1220195957Salfred struct ste_softc *sc; 1221195957Salfred{ 1222195957Salfred struct ste_chain_data *cd; 1223195957Salfred struct ste_list_data *ld; 1224195957Salfred int i; 1225195957Salfred 1226195957Salfred cd = &sc->ste_cdata; 1227195957Salfred ld = sc->ste_ldata; 1228195957Salfred for (i = 0; i < STE_TX_LIST_CNT; i++) { 1229195957Salfred cd->ste_tx_chain[i].ste_ptr = &ld->ste_tx_list[i]; 1230195957Salfred if (i == (STE_TX_LIST_CNT - 1)) 1231195957Salfred cd->ste_tx_chain[i].ste_next = NULL; 1232195957Salfred else 1233195957Salfred cd->ste_tx_chain[i].ste_next = 1234195957Salfred &cd->ste_tx_chain[i + 1]; 1235195957Salfred } 1236195957Salfred 1237195957Salfred cd->ste_tx_free = &cd->ste_tx_chain[0]; 1238195957Salfred cd->ste_tx_tail = cd->ste_tx_head = NULL; 1239195957Salfred 1240199575Sthompsa return; 1241195957Salfred} 1242195957Salfred 1243195957Salfredstatic void ste_init(xsc) 1244199575Sthompsa void *xsc; 1245199575Sthompsa{ 1246199575Sthompsa struct ste_softc *sc; 1247199575Sthompsa int i, s; 1248199575Sthompsa struct ifnet *ifp; 1249195957Salfred struct mii_data *mii; 1250195957Salfred 1251199575Sthompsa s = splimp(); 1252195957Salfred 1253195957Salfred sc = xsc; 1254195957Salfred ifp = &sc->arpcom.ac_if; 1255195957Salfred mii = device_get_softc(sc->ste_miibus); 1256195957Salfred 1257195957Salfred ste_stop(sc); 1258195957Salfred 1259195957Salfred /* Init our MAC address */ 1260195957Salfred for (i = 0; i < ETHER_ADDR_LEN; i++) { 1261195957Salfred CSR_WRITE_1(sc, STE_PAR0 + i, sc->arpcom.ac_enaddr[i]); 1262195957Salfred } 1263194676Sthompsa 1264194676Sthompsa /* Init RX list */ 1265195957Salfred if (ste_init_rx_list(sc) == ENOBUFS) { 1266195957Salfred printf("ste%d: initialization failed: no " 1267194676Sthompsa "memory for RX buffers\n", sc->ste_unit); 1268195957Salfred ste_stop(sc); 1269194676Sthompsa splx(s); 1270195957Salfred return; 1271195957Salfred } 1272195957Salfred 1273195957Salfred /* Init TX descriptors */ 1274199055Sthompsa ste_init_tx_list(sc); 1275199575Sthompsa 1276194676Sthompsa /* Set the TX freethresh value */ 1277195957Salfred CSR_WRITE_1(sc, STE_TX_DMABURST_THRESH, STE_PACKET_SIZE >> 8); 1278195957Salfred 1279194676Sthompsa /* Set the TX start threshold for best performance. */ 1280199575Sthompsa sc->ste_tx_thresh = STE_MIN_FRAMELEN; 1281195957Salfred CSR_WRITE_2(sc, STE_TX_STARTTHRESH, sc->ste_tx_thresh); 1282199575Sthompsa 1283194676Sthompsa /* Set the TX reclaim threshold. */ 1284195957Salfred CSR_WRITE_1(sc, STE_TX_RECLAIM_THRESH, (STE_PACKET_SIZE >> 4)); 1285194676Sthompsa 1286195957Salfred /* Set up the RX filter. */ 1287195957Salfred CSR_WRITE_1(sc, STE_RX_MODE, STE_RXMODE_UNICAST); 1288195957Salfred 1289195957Salfred /* If we want promiscuous mode, set the allframes bit. */ 1290195957Salfred if (ifp->if_flags & IFF_PROMISC) { 1291195957Salfred STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_PROMISC); 1292195957Salfred } else { 1293195957Salfred STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_PROMISC); 1294195957Salfred } 1295195957Salfred 1296199575Sthompsa /* Set capture broadcast bit to accept broadcast frames. */ 1297199575Sthompsa if (ifp->if_flags & IFF_BROADCAST) { 1298195957Salfred STE_SETBIT1(sc, STE_RX_MODE, STE_RXMODE_BROADCAST); 1299195957Salfred } else { 1300195957Salfred STE_CLRBIT1(sc, STE_RX_MODE, STE_RXMODE_BROADCAST); 1301195957Salfred } 1302195957Salfred 1303199575Sthompsa ste_setmulti(sc); 1304199575Sthompsa 1305199575Sthompsa /* Load the address of the RX list. */ 1306199575Sthompsa STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL); 1307199575Sthompsa ste_wait(sc); 1308195957Salfred CSR_WRITE_4(sc, STE_RX_DMALIST_PTR, 1309195957Salfred vtophys(&sc->ste_ldata->ste_rx_list[0])); 1310195957Salfred STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_UNSTALL); 1311199575Sthompsa STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_UNSTALL); 1312199575Sthompsa 1313195957Salfred /* Enable receiver and transmitter */ 1314195957Salfred CSR_WRITE_2(sc, STE_MACCTL0, 0); 1315199575Sthompsa STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_TX_ENABLE); 1316195957Salfred STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_RX_ENABLE); 1317199575Sthompsa 1318199575Sthompsa /* Enable stats counters. */ 1319195957Salfred STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_STATS_ENABLE); 1320195957Salfred 1321195957Salfred /* Enable interrupts. */ 1322195957Salfred CSR_WRITE_2(sc, STE_ISR, 0xFFFF); 1323195957Salfred CSR_WRITE_2(sc, STE_IMR, STE_INTRS); 1324199575Sthompsa 1325199575Sthompsa mii_mediachg(mii); 1326195957Salfred 1327195957Salfred ifp->if_flags |= IFF_RUNNING; 1328195957Salfred ifp->if_flags &= ~IFF_OACTIVE; 1329195957Salfred 1330195957Salfred splx(s); 1331195957Salfred 1332199575Sthompsa sc->ste_stat_ch = timeout(ste_stats_update, sc, hz); 1333195957Salfred 1334195957Salfred return; 1335195957Salfred} 1336195957Salfred 1337195957Salfredstatic void ste_stop(sc) 1338195957Salfred struct ste_softc *sc; 1339199575Sthompsa{ 1340194676Sthompsa int i; 1341194676Sthompsa struct ifnet *ifp; 1342195957Salfred 1343195957Salfred ifp = &sc->arpcom.ac_if; 1344195957Salfred 1345195957Salfred untimeout(ste_stats_update, sc, sc->ste_stat_ch); 1346195957Salfred 1347199055Sthompsa CSR_WRITE_2(sc, STE_IMR, 0); 1348199055Sthompsa STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_TX_DISABLE); 1349199055Sthompsa STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_RX_DISABLE); 1350199055Sthompsa STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_STATS_DISABLE); 1351199055Sthompsa STE_SETBIT2(sc, STE_DMACTL, STE_DMACTL_TXDMA_STALL); 1352199055Sthompsa STE_SETBIT2(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL); 1353199055Sthompsa ste_wait(sc); 1354199055Sthompsa 1355199055Sthompsa for (i = 0; i < STE_RX_LIST_CNT; i++) { 1356199055Sthompsa if (sc->ste_cdata.ste_rx_chain[i].ste_mbuf != NULL) { 1357199055Sthompsa m_freem(sc->ste_cdata.ste_rx_chain[i].ste_mbuf); 1358199055Sthompsa sc->ste_cdata.ste_rx_chain[i].ste_mbuf = NULL; 1359199055Sthompsa } 1360 } 1361 1362 for (i = 0; i < STE_TX_LIST_CNT; i++) { 1363 if (sc->ste_cdata.ste_tx_chain[i].ste_mbuf != NULL) { 1364 m_freem(sc->ste_cdata.ste_tx_chain[i].ste_mbuf); 1365 sc->ste_cdata.ste_tx_chain[i].ste_mbuf = NULL; 1366 } 1367 } 1368 1369 ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); 1370 1371 return; 1372} 1373 1374static void ste_reset(sc) 1375 struct ste_softc *sc; 1376{ 1377 int i; 1378 1379 STE_SETBIT4(sc, STE_ASICCTL, 1380 STE_ASICCTL_GLOBAL_RESET|STE_ASICCTL_RX_RESET| 1381 STE_ASICCTL_TX_RESET|STE_ASICCTL_DMA_RESET| 1382 STE_ASICCTL_FIFO_RESET|STE_ASICCTL_NETWORK_RESET| 1383 STE_ASICCTL_AUTOINIT_RESET|STE_ASICCTL_HOST_RESET| 1384 STE_ASICCTL_EXTRESET_RESET); 1385 1386 DELAY(100000); 1387 1388 for (i = 0; i < STE_TIMEOUT; i++) { 1389 if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_RESET_BUSY)) 1390 break; 1391 } 1392 1393 if (i == STE_TIMEOUT) 1394 printf("ste%d: global reset never completed\n", sc->ste_unit); 1395 1396#ifdef foo 1397 STE_SETBIT4(sc, STE_ASICCTL, STE_ASICCTL_RX_RESET); 1398 for (i = 0; i < STE_TIMEOUT; i++) { 1399 if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_RX_RESET)) 1400 break; 1401 } 1402 1403 if (i == STE_TIMEOUT) 1404 printf("ste%d: RX reset never completed\n", sc->ste_unit); 1405 1406 DELAY(100000); 1407 1408 STE_SETBIT4(sc, STE_ASICCTL, STE_ASICCTL_TX_RESET); 1409 for (i = 0; i < STE_TIMEOUT; i++) { 1410 if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_TX_RESET)) 1411 break; 1412 } 1413 1414 if (i == STE_TIMEOUT) 1415 printf("ste%d: TX reset never completed\n", sc->ste_unit); 1416 1417 DELAY(100000); 1418#endif 1419 1420 return; 1421} 1422 1423static int ste_ioctl(ifp, command, data) 1424 struct ifnet *ifp; 1425 u_long command; 1426 caddr_t data; 1427{ 1428 struct ste_softc *sc; 1429 struct ifreq *ifr; 1430 struct mii_data *mii; 1431 int error = 0, s; 1432 1433 s = splimp(); 1434 1435 sc = ifp->if_softc; 1436 ifr = (struct ifreq *)data; 1437 1438 switch(command) { 1439 case SIOCSIFADDR: 1440 case SIOCGIFADDR: 1441 case SIOCSIFMTU: 1442 error = ether_ioctl(ifp, command, data); 1443 break; 1444 case SIOCSIFFLAGS: 1445 if (ifp->if_flags & IFF_UP) { 1446 ste_init(sc); 1447 } else { 1448 if (ifp->if_flags & IFF_RUNNING) 1449 ste_stop(sc); 1450 } 1451 error = 0; 1452 break; 1453 case SIOCADDMULTI: 1454 case SIOCDELMULTI: 1455 ste_setmulti(sc); 1456 error = 0; 1457 break; 1458 case SIOCGIFMEDIA: 1459 case SIOCSIFMEDIA: 1460 mii = device_get_softc(sc->ste_miibus); 1461 error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 1462 break; 1463 default: 1464 error = EINVAL; 1465 break; 1466 } 1467 1468 splx(s); 1469 1470 return(error); 1471} 1472 1473static int ste_encap(sc, c, m_head) 1474 struct ste_softc *sc; 1475 struct ste_chain *c; 1476 struct mbuf *m_head; 1477{ 1478 int frag = 0; 1479 struct ste_frag *f = NULL; 1480 int total_len; 1481 struct mbuf *m; 1482 1483 m = m_head; 1484 total_len = 0; 1485 1486 for (m = m_head, frag = 0; m != NULL; m = m->m_next) { 1487 if (m->m_len != 0) { 1488 if (frag == STE_MAXFRAGS) 1489 break; 1490 total_len += m->m_len; 1491 f = &c->ste_ptr->ste_frags[frag]; 1492 f->ste_addr = vtophys(mtod(m, vm_offset_t)); 1493 f->ste_len = m->m_len; 1494 frag++; 1495 } 1496 } 1497 1498 if (m != NULL) { 1499 struct mbuf *m_new = NULL; 1500 1501 MGETHDR(m_new, M_DONTWAIT, MT_DATA); 1502 if (m_new == NULL) { 1503 printf("ste%d: no memory for " 1504 "tx list", sc->ste_unit); 1505 return(1); 1506 } 1507 if (m_head->m_pkthdr.len > MHLEN) { 1508 MCLGET(m_new, M_DONTWAIT); 1509 if (!(m_new->m_flags & M_EXT)) { 1510 m_freem(m_new); 1511 printf("ste%d: no memory for " 1512 "tx list", sc->ste_unit); 1513 return(1); 1514 } 1515 } 1516 m_copydata(m_head, 0, m_head->m_pkthdr.len, 1517 mtod(m_new, caddr_t)); 1518 m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len; 1519 m_freem(m_head); 1520 m_head = m_new; 1521 f = &c->ste_ptr->ste_frags[0]; 1522 f->ste_addr = vtophys(mtod(m_new, caddr_t)); 1523 f->ste_len = total_len = m_new->m_len; 1524 frag = 1; 1525 } 1526 1527 c->ste_mbuf = m_head; 1528 c->ste_ptr->ste_frags[frag - 1].ste_len |= STE_FRAG_LAST; 1529 c->ste_ptr->ste_ctl = total_len; 1530 c->ste_ptr->ste_next = 0; 1531 1532 return(0); 1533} 1534 1535static void ste_start(ifp) 1536 struct ifnet *ifp; 1537{ 1538 struct ste_softc *sc; 1539 struct mbuf *m_head = NULL; 1540 struct ste_chain *prev = NULL, *cur_tx = NULL, *start_tx; 1541 1542 sc = ifp->if_softc; 1543 1544 if (sc->ste_cdata.ste_tx_free == NULL) { 1545 ifp->if_flags |= IFF_OACTIVE; 1546 return; 1547 } 1548 1549 start_tx = sc->ste_cdata.ste_tx_free; 1550 1551 while(sc->ste_cdata.ste_tx_free != NULL) { 1552 IF_DEQUEUE(&ifp->if_snd, m_head); 1553 if (m_head == NULL) 1554 break; 1555 1556 cur_tx = sc->ste_cdata.ste_tx_free; 1557 sc->ste_cdata.ste_tx_free = cur_tx->ste_next; 1558 1559 cur_tx->ste_next = NULL; 1560 1561 ste_encap(sc, cur_tx, m_head); 1562 1563 if (prev != NULL) { 1564 prev->ste_next = cur_tx; 1565 prev->ste_ptr->ste_next = vtophys(cur_tx->ste_ptr); 1566 } 1567 prev = cur_tx; 1568 1569#if NBPF > 0 1570 /* 1571 * If there's a BPF listener, bounce a copt of this frame 1572 * to him. 1573 */ 1574 if (ifp->if_bpf) 1575 bpf_mtap(ifp, cur_tx->ste_mbuf); 1576#endif 1577 } 1578 1579 if (cur_tx == NULL) 1580 return; 1581 1582 cur_tx->ste_ptr->ste_ctl |= STE_TXCTL_DMAINTR; 1583 1584 STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_STALL); 1585 ste_wait(sc); 1586 1587 if (sc->ste_cdata.ste_tx_head != NULL) { 1588 sc->ste_cdata.ste_tx_tail->ste_next = start_tx; 1589 sc->ste_cdata.ste_tx_tail->ste_ptr->ste_next = 1590 vtophys(start_tx->ste_ptr); 1591 sc->ste_cdata.ste_tx_tail->ste_ptr->ste_ctl &= 1592 ~STE_TXCTL_DMAINTR; 1593 sc->ste_cdata.ste_tx_tail = cur_tx; 1594 } else { 1595 sc->ste_cdata.ste_tx_head = start_tx; 1596 sc->ste_cdata.ste_tx_tail = cur_tx; 1597 } 1598 1599 if (!CSR_READ_4(sc, STE_TX_DMALIST_PTR)) 1600 CSR_WRITE_4(sc, STE_TX_DMALIST_PTR, 1601 vtophys(start_tx->ste_ptr)); 1602 STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL); 1603 1604 ifp->if_timer = 5; 1605 1606 return; 1607} 1608 1609static void ste_watchdog(ifp) 1610 struct ifnet *ifp; 1611{ 1612 struct ste_softc *sc; 1613 1614 sc = ifp->if_softc; 1615 1616 ifp->if_oerrors++; 1617 printf("ste%d: watchdog timeout\n", sc->ste_unit); 1618 1619#ifdef foo 1620 if (sc->ste_pinfo != NULL) { 1621 if (!(ste_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT)) 1622 printf("ste%d: no carrier - transceiver " 1623 "cable problem?\n", sc->ste_unit); 1624 } 1625#endif 1626 1627 ste_txeoc(sc); 1628 ste_txeof(sc); 1629 ste_rxeof(sc); 1630 ste_reset(sc); 1631 ste_init(sc); 1632 1633 if (ifp->if_snd.ifq_head != NULL) 1634 ste_start(ifp); 1635 1636 return; 1637} 1638 1639static void ste_shutdown(dev) 1640 device_t dev; 1641{ 1642 struct ste_softc *sc; 1643 1644 sc = device_get_softc(dev); 1645 1646 ste_stop(sc); 1647 1648 return; 1649} 1650