if_rl.c revision 130270
140516Swpaul/* 2119868Swpaul * Copyright (c) 1997, 1998 340516Swpaul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 440516Swpaul * 540516Swpaul * Redistribution and use in source and binary forms, with or without 640516Swpaul * modification, are permitted provided that the following conditions 740516Swpaul * are met: 840516Swpaul * 1. Redistributions of source code must retain the above copyright 940516Swpaul * notice, this list of conditions and the following disclaimer. 1040516Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1140516Swpaul * notice, this list of conditions and the following disclaimer in the 1240516Swpaul * documentation and/or other materials provided with the distribution. 1340516Swpaul * 3. All advertising materials mentioning features or use of this software 1440516Swpaul * must display the following acknowledgement: 1540516Swpaul * This product includes software developed by Bill Paul. 1640516Swpaul * 4. Neither the name of the author nor the names of any co-contributors 1740516Swpaul * may be used to endorse or promote products derived from this software 1840516Swpaul * without specific prior written permission. 1940516Swpaul * 2040516Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2140516Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2240516Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2340516Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 2440516Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2540516Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2640516Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2740516Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2840516Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2940516Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 3040516Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 3140516Swpaul */ 3240516Swpaul 33122678Sobrien#include <sys/cdefs.h> 34122678Sobrien__FBSDID("$FreeBSD: head/sys/pci/if_rl.c 130270 2004-06-09 14:34:04Z naddy $"); 35122678Sobrien 3640516Swpaul/* 37119868Swpaul * RealTek 8129/8139 PCI NIC driver 3840516Swpaul * 39119868Swpaul * Supports several extremely cheap PCI 10/100 adapters based on 40119868Swpaul * the RealTek chipset. Datasheets can be obtained from 4140516Swpaul * www.realtek.com.tw. 4240516Swpaul * 43119868Swpaul * Written by Bill Paul <wpaul@ctr.columbia.edu> 44119868Swpaul * Electrical Engineering Department 45119868Swpaul * Columbia University, New York City 4640516Swpaul */ 4740516Swpaul/* 4840516Swpaul * The RealTek 8139 PCI NIC redefines the meaning of 'low end.' This is 4940516Swpaul * probably the worst PCI ethernet controller ever made, with the possible 5040516Swpaul * exception of the FEAST chip made by SMC. The 8139 supports bus-master 5140516Swpaul * DMA, but it has a terrible interface that nullifies any performance 5240516Swpaul * gains that bus-master DMA usually offers. 5340516Swpaul * 5440516Swpaul * For transmission, the chip offers a series of four TX descriptor 5540516Swpaul * registers. Each transmit frame must be in a contiguous buffer, aligned 5641569Swpaul * on a longword (32-bit) boundary. This means we almost always have to 5740516Swpaul * do mbuf copies in order to transmit a frame, except in the unlikely 5840516Swpaul * case where a) the packet fits into a single mbuf, and b) the packet 5940516Swpaul * is 32-bit aligned within the mbuf's data area. The presence of only 6040516Swpaul * four descriptor registers means that we can never have more than four 6140516Swpaul * packets queued for transmission at any one time. 6240516Swpaul * 6340516Swpaul * Reception is not much better. The driver has to allocate a single large 6440516Swpaul * buffer area (up to 64K in size) into which the chip will DMA received 6540516Swpaul * frames. Because we don't know where within this region received packets 6640516Swpaul * will begin or end, we have no choice but to copy data from the buffer 6740516Swpaul * area into mbufs in order to pass the packets up to the higher protocol 6840516Swpaul * levels. 6940516Swpaul * 7040516Swpaul * It's impossible given this rotten design to really achieve decent 7140516Swpaul * performance at 100Mbps, unless you happen to have a 400Mhz PII or 7240516Swpaul * some equally overmuscled CPU to drive it. 7340516Swpaul * 7440516Swpaul * On the bright side, the 8139 does have a built-in PHY, although 7540516Swpaul * rather than using an MDIO serial interface like most other NICs, the 7640516Swpaul * PHY registers are directly accessible through the 8139's register 7740516Swpaul * space. The 8139 supports autonegotiation, as well as a 64-bit multicast 7840516Swpaul * filter. 7940516Swpaul * 8040516Swpaul * The 8129 chip is an older version of the 8139 that uses an external PHY 8140516Swpaul * chip. The 8129 has a serial MDIO interface for accessing the MII where 8240516Swpaul * the 8139 lets you directly access the on-board PHY registers. We need 8340516Swpaul * to select which interface to use depending on the chip type. 8440516Swpaul */ 8540516Swpaul 8640516Swpaul#include <sys/param.h> 87108729Sjake#include <sys/endian.h> 8840516Swpaul#include <sys/systm.h> 8940516Swpaul#include <sys/sockio.h> 9040516Swpaul#include <sys/mbuf.h> 9140516Swpaul#include <sys/malloc.h> 9240516Swpaul#include <sys/kernel.h> 93129878Sphk#include <sys/module.h> 9440516Swpaul#include <sys/socket.h> 9540516Swpaul 9640516Swpaul#include <net/if.h> 9740516Swpaul#include <net/if_arp.h> 9840516Swpaul#include <net/ethernet.h> 9940516Swpaul#include <net/if_dl.h> 10040516Swpaul#include <net/if_media.h> 10140516Swpaul 10240516Swpaul#include <net/bpf.h> 10340516Swpaul 10441569Swpaul#include <machine/bus_pio.h> 10541569Swpaul#include <machine/bus_memio.h> 10641569Swpaul#include <machine/bus.h> 10750703Swpaul#include <machine/resource.h> 10850703Swpaul#include <sys/bus.h> 10950703Swpaul#include <sys/rman.h> 11040516Swpaul 11150703Swpaul#include <dev/mii/mii.h> 11250703Swpaul#include <dev/mii/miivar.h> 11350703Swpaul 114119871Swpaul#include <dev/pci/pcireg.h> 115119871Swpaul#include <dev/pci/pcivar.h> 11640516Swpaul 117113506SmdoddMODULE_DEPEND(rl, pci, 1, 1, 1); 118113506SmdoddMODULE_DEPEND(rl, ether, 1, 1, 1); 11959758SpeterMODULE_DEPEND(rl, miibus, 1, 1, 1); 12059758Speter 12151089Speter/* "controller miibus0" required. See GENERIC if you get errors here. */ 12250703Swpaul#include "miibus_if.h" 12350703Swpaul 12440516Swpaul/* 12540516Swpaul * Default to using PIO access for this driver. On SMP systems, 12640516Swpaul * there appear to be problems with memory mapped mode: it looks like 12740516Swpaul * doing too many memory mapped access back to back in rapid succession 12840516Swpaul * can hang the bus. I'm inclined to blame this on crummy design/construction 12940516Swpaul * on the part of RealTek. Memory mapped mode does appear to work on 13040516Swpaul * uniprocessor systems though. 13140516Swpaul */ 13240516Swpaul#define RL_USEIOSPACE 13340516Swpaul 13440516Swpaul#include <pci/if_rlreg.h> 13540516Swpaul 13640516Swpaul/* 13740516Swpaul * Various supported device vendors/types and their names. 13840516Swpaul */ 13940516Swpaulstatic struct rl_type rl_devs[] = { 140117388Swpaul { RT_VENDORID, RT_DEVICEID_8129, RL_8129, 14140516Swpaul "RealTek 8129 10/100BaseTX" }, 142117388Swpaul { RT_VENDORID, RT_DEVICEID_8139, RL_8139, 14340516Swpaul "RealTek 8139 10/100BaseTX" }, 144117388Swpaul { RT_VENDORID, RT_DEVICEID_8138, RL_8139, 14567771Swpaul "RealTek 8139 10/100BaseTX CardBus" }, 146118978Swpaul { RT_VENDORID, RT_DEVICEID_8100, RL_8139, 147118978Swpaul "RealTek 8100 10/100BaseTX" }, 148117388Swpaul { ACCTON_VENDORID, ACCTON_DEVICEID_5030, RL_8139, 14941243Swpaul "Accton MPX 5030/5038 10/100BaseTX" }, 150117388Swpaul { DELTA_VENDORID, DELTA_DEVICEID_8139, RL_8139, 15144238Swpaul "Delta Electronics 8139 10/100BaseTX" }, 152117388Swpaul { ADDTRON_VENDORID, ADDTRON_DEVICEID_8139, RL_8139, 15344238Swpaul "Addtron Technolgy 8139 10/100BaseTX" }, 154117388Swpaul { DLINK_VENDORID, DLINK_DEVICEID_530TXPLUS, RL_8139, 15572813Swpaul "D-Link DFE-530TX+ 10/100BaseTX" }, 156117388Swpaul { DLINK_VENDORID, DLINK_DEVICEID_690TXD, RL_8139, 15796112Sjhb "D-Link DFE-690TXD 10/100BaseTX" }, 158117388Swpaul { NORTEL_VENDORID, ACCTON_DEVICEID_5030, RL_8139, 15994400Swpaul "Nortel Networks 10/100BaseTX" }, 160117388Swpaul { COREGA_VENDORID, COREGA_DEVICEID_FETHERCBTXD, RL_8139, 161103020Siwasaki "Corega FEther CB-TXD" }, 162117388Swpaul { COREGA_VENDORID, COREGA_DEVICEID_FETHERIICBTXD, RL_8139, 163109095Ssanpei "Corega FEtherII CB-TXD" }, 164117388Swpaul { PEPPERCON_VENDORID, PEPPERCON_DEVICEID_ROLF, RL_8139, 165111381Sdan "Peppercon AG ROL-F" }, 166117388Swpaul { PLANEX_VENDORID, PLANEX_DEVICEID_FNW3800TX, RL_8139, 167112379Ssanpei "Planex FNW-3800-TX" }, 168117388Swpaul { CP_VENDORID, RT_DEVICEID_8139, RL_8139, 169117388Swpaul "Compaq HNE-300" }, 170117388Swpaul { LEVEL1_VENDORID, LEVEL1_DEVICEID_FPC0106TX, RL_8139, 171117388Swpaul "LevelOne FPC-0106TX" }, 172117388Swpaul { EDIMAX_VENDORID, EDIMAX_DEVICEID_EP4103DL, RL_8139, 173117388Swpaul "Edimax EP-4103DL CardBus" }, 174123740Speter { 0, 0, 0, NULL } 17540516Swpaul}; 17640516Swpaul 17792739Salfredstatic int rl_probe (device_t); 17892739Salfredstatic int rl_attach (device_t); 17992739Salfredstatic int rl_detach (device_t); 18040516Swpaul 181119868Swpaulstatic int rl_encap (struct rl_softc *, struct mbuf * ); 18240516Swpaul 18392739Salfredstatic void rl_rxeof (struct rl_softc *); 18492739Salfredstatic void rl_txeof (struct rl_softc *); 18592739Salfredstatic void rl_intr (void *); 18692739Salfredstatic void rl_tick (void *); 18792739Salfredstatic void rl_start (struct ifnet *); 18892739Salfredstatic int rl_ioctl (struct ifnet *, u_long, caddr_t); 18992739Salfredstatic void rl_init (void *); 19092739Salfredstatic void rl_stop (struct rl_softc *); 19192739Salfredstatic void rl_watchdog (struct ifnet *); 19292739Salfredstatic int rl_suspend (device_t); 19392739Salfredstatic int rl_resume (device_t); 19492739Salfredstatic void rl_shutdown (device_t); 19592739Salfredstatic int rl_ifmedia_upd (struct ifnet *); 19692739Salfredstatic void rl_ifmedia_sts (struct ifnet *, struct ifmediareq *); 19740516Swpaul 19892739Salfredstatic void rl_eeprom_putbyte (struct rl_softc *, int); 19992739Salfredstatic void rl_eeprom_getword (struct rl_softc *, int, u_int16_t *); 20092739Salfredstatic void rl_read_eeprom (struct rl_softc *, caddr_t, int, int, int); 20192739Salfredstatic void rl_mii_sync (struct rl_softc *); 20292739Salfredstatic void rl_mii_send (struct rl_softc *, u_int32_t, int); 20392739Salfredstatic int rl_mii_readreg (struct rl_softc *, struct rl_mii_frame *); 20492739Salfredstatic int rl_mii_writereg (struct rl_softc *, struct rl_mii_frame *); 20540516Swpaul 20692739Salfredstatic int rl_miibus_readreg (device_t, int, int); 20792739Salfredstatic int rl_miibus_writereg (device_t, int, int, int); 20892739Salfredstatic void rl_miibus_statchg (device_t); 20940516Swpaul 21092739Salfredstatic void rl_setmulti (struct rl_softc *); 21192739Salfredstatic void rl_reset (struct rl_softc *); 21292739Salfredstatic int rl_list_tx_init (struct rl_softc *); 21340516Swpaul 21492739Salfredstatic void rl_dma_map_rxbuf (void *, bus_dma_segment_t *, int, int); 21592739Salfredstatic void rl_dma_map_txbuf (void *, bus_dma_segment_t *, int, int); 21681713Swpaul 21750703Swpaul#ifdef RL_USEIOSPACE 21850703Swpaul#define RL_RES SYS_RES_IOPORT 21950703Swpaul#define RL_RID RL_PCI_LOIO 22050703Swpaul#else 22150703Swpaul#define RL_RES SYS_RES_MEMORY 22250703Swpaul#define RL_RID RL_PCI_LOMEM 22350703Swpaul#endif 22450703Swpaul 22550703Swpaulstatic device_method_t rl_methods[] = { 22650703Swpaul /* Device interface */ 22750703Swpaul DEVMETHOD(device_probe, rl_probe), 22850703Swpaul DEVMETHOD(device_attach, rl_attach), 22950703Swpaul DEVMETHOD(device_detach, rl_detach), 23086822Siwasaki DEVMETHOD(device_suspend, rl_suspend), 23186822Siwasaki DEVMETHOD(device_resume, rl_resume), 23250703Swpaul DEVMETHOD(device_shutdown, rl_shutdown), 23350703Swpaul 23450703Swpaul /* bus interface */ 23550703Swpaul DEVMETHOD(bus_print_child, bus_generic_print_child), 23650703Swpaul DEVMETHOD(bus_driver_added, bus_generic_driver_added), 23750703Swpaul 23850703Swpaul /* MII interface */ 23950703Swpaul DEVMETHOD(miibus_readreg, rl_miibus_readreg), 24050703Swpaul DEVMETHOD(miibus_writereg, rl_miibus_writereg), 24150703Swpaul DEVMETHOD(miibus_statchg, rl_miibus_statchg), 24250703Swpaul 24350703Swpaul { 0, 0 } 24450703Swpaul}; 24550703Swpaul 24650703Swpaulstatic driver_t rl_driver = { 24751455Swpaul "rl", 24850703Swpaul rl_methods, 24950703Swpaul sizeof(struct rl_softc) 25050703Swpaul}; 25150703Swpaul 25250703Swpaulstatic devclass_t rl_devclass; 25350703Swpaul 254113506SmdoddDRIVER_MODULE(rl, pci, rl_driver, rl_devclass, 0, 0); 255123019SimpDRIVER_MODULE(rl, cardbus, rl_driver, rl_devclass, 0, 0); 25651473SwpaulDRIVER_MODULE(miibus, rl, miibus_driver, miibus_devclass, 0, 0); 25750703Swpaul 25840516Swpaul#define EE_SET(x) \ 25940516Swpaul CSR_WRITE_1(sc, RL_EECMD, \ 26040516Swpaul CSR_READ_1(sc, RL_EECMD) | x) 26140516Swpaul 26240516Swpaul#define EE_CLR(x) \ 26340516Swpaul CSR_WRITE_1(sc, RL_EECMD, \ 26440516Swpaul CSR_READ_1(sc, RL_EECMD) & ~x) 26540516Swpaul 26681713Swpaulstatic void 26781713Swpaulrl_dma_map_rxbuf(arg, segs, nseg, error) 26881713Swpaul void *arg; 26981713Swpaul bus_dma_segment_t *segs; 27081713Swpaul int nseg, error; 27181713Swpaul{ 27281713Swpaul struct rl_softc *sc; 27381713Swpaul 27481713Swpaul sc = arg; 27581713Swpaul CSR_WRITE_4(sc, RL_RXADDR, segs->ds_addr & 0xFFFFFFFF); 27681713Swpaul 27781713Swpaul return; 27881713Swpaul} 27981713Swpaul 28081713Swpaulstatic void 28181713Swpaulrl_dma_map_txbuf(arg, segs, nseg, error) 28281713Swpaul void *arg; 28381713Swpaul bus_dma_segment_t *segs; 28481713Swpaul int nseg, error; 28581713Swpaul{ 28681713Swpaul struct rl_softc *sc; 28781713Swpaul 28881713Swpaul sc = arg; 28981713Swpaul CSR_WRITE_4(sc, RL_CUR_TXADDR(sc), segs->ds_addr & 0xFFFFFFFF); 29081713Swpaul 29181713Swpaul return; 29281713Swpaul} 29381713Swpaul 29440516Swpaul/* 29540516Swpaul * Send a read command and address to the EEPROM, check for ACK. 29640516Swpaul */ 297102335Salfredstatic void 298102335Salfredrl_eeprom_putbyte(sc, addr) 29940516Swpaul struct rl_softc *sc; 30041656Swpaul int addr; 30140516Swpaul{ 30240516Swpaul register int d, i; 30340516Swpaul 30467931Swpaul d = addr | sc->rl_eecmd_read; 30540516Swpaul 30640516Swpaul /* 30755170Sbillf * Feed in each bit and strobe the clock. 30840516Swpaul */ 30940516Swpaul for (i = 0x400; i; i >>= 1) { 31040516Swpaul if (d & i) { 31140516Swpaul EE_SET(RL_EE_DATAIN); 31240516Swpaul } else { 31340516Swpaul EE_CLR(RL_EE_DATAIN); 31440516Swpaul } 31540516Swpaul DELAY(100); 31640516Swpaul EE_SET(RL_EE_CLK); 31740516Swpaul DELAY(150); 31840516Swpaul EE_CLR(RL_EE_CLK); 31940516Swpaul DELAY(100); 32040516Swpaul } 32140516Swpaul 32240516Swpaul return; 32340516Swpaul} 32440516Swpaul 32540516Swpaul/* 32640516Swpaul * Read a word of data stored in the EEPROM at address 'addr.' 32740516Swpaul */ 328102335Salfredstatic void 329102335Salfredrl_eeprom_getword(sc, addr, dest) 33040516Swpaul struct rl_softc *sc; 33141656Swpaul int addr; 33240516Swpaul u_int16_t *dest; 33340516Swpaul{ 33440516Swpaul register int i; 33540516Swpaul u_int16_t word = 0; 33640516Swpaul 33740516Swpaul /* Enter EEPROM access mode. */ 33840516Swpaul CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_PROGRAM|RL_EE_SEL); 33940516Swpaul 34040516Swpaul /* 34140516Swpaul * Send address of word we want to read. 34240516Swpaul */ 34340516Swpaul rl_eeprom_putbyte(sc, addr); 34440516Swpaul 34540516Swpaul CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_PROGRAM|RL_EE_SEL); 34640516Swpaul 34740516Swpaul /* 34840516Swpaul * Start reading bits from EEPROM. 34940516Swpaul */ 35040516Swpaul for (i = 0x8000; i; i >>= 1) { 35140516Swpaul EE_SET(RL_EE_CLK); 35240516Swpaul DELAY(100); 35340516Swpaul if (CSR_READ_1(sc, RL_EECMD) & RL_EE_DATAOUT) 35440516Swpaul word |= i; 35540516Swpaul EE_CLR(RL_EE_CLK); 35640516Swpaul DELAY(100); 35740516Swpaul } 35840516Swpaul 35940516Swpaul /* Turn off EEPROM access mode. */ 36040516Swpaul CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF); 36140516Swpaul 36240516Swpaul *dest = word; 36340516Swpaul 36440516Swpaul return; 36540516Swpaul} 36640516Swpaul 36740516Swpaul/* 36840516Swpaul * Read a sequence of words from the EEPROM. 36940516Swpaul */ 370102335Salfredstatic void 371102335Salfredrl_read_eeprom(sc, dest, off, cnt, swap) 37240516Swpaul struct rl_softc *sc; 37340516Swpaul caddr_t dest; 37440516Swpaul int off; 37540516Swpaul int cnt; 37640516Swpaul int swap; 37740516Swpaul{ 37840516Swpaul int i; 37940516Swpaul u_int16_t word = 0, *ptr; 38040516Swpaul 38140516Swpaul for (i = 0; i < cnt; i++) { 38240516Swpaul rl_eeprom_getword(sc, off + i, &word); 38340516Swpaul ptr = (u_int16_t *)(dest + (i * 2)); 38440516Swpaul if (swap) 38540516Swpaul *ptr = ntohs(word); 38640516Swpaul else 38740516Swpaul *ptr = word; 38840516Swpaul } 38940516Swpaul 39040516Swpaul return; 39140516Swpaul} 39240516Swpaul 39340516Swpaul 39440516Swpaul/* 39540516Swpaul * MII access routines are provided for the 8129, which 39640516Swpaul * doesn't have a built-in PHY. For the 8139, we fake things 39740516Swpaul * up by diverting rl_phy_readreg()/rl_phy_writereg() to the 39840516Swpaul * direct access PHY registers. 39940516Swpaul */ 40040516Swpaul#define MII_SET(x) \ 40140516Swpaul CSR_WRITE_1(sc, RL_MII, \ 402105221Sphk CSR_READ_1(sc, RL_MII) | (x)) 40340516Swpaul 40440516Swpaul#define MII_CLR(x) \ 40540516Swpaul CSR_WRITE_1(sc, RL_MII, \ 406105221Sphk CSR_READ_1(sc, RL_MII) & ~(x)) 40740516Swpaul 40840516Swpaul/* 40940516Swpaul * Sync the PHYs by setting data bit and strobing the clock 32 times. 41040516Swpaul */ 411102335Salfredstatic void 412102335Salfredrl_mii_sync(sc) 41340516Swpaul struct rl_softc *sc; 41440516Swpaul{ 41540516Swpaul register int i; 41640516Swpaul 41740516Swpaul MII_SET(RL_MII_DIR|RL_MII_DATAOUT); 41840516Swpaul 41940516Swpaul for (i = 0; i < 32; i++) { 42040516Swpaul MII_SET(RL_MII_CLK); 42140516Swpaul DELAY(1); 42240516Swpaul MII_CLR(RL_MII_CLK); 42340516Swpaul DELAY(1); 42440516Swpaul } 42540516Swpaul 42640516Swpaul return; 42740516Swpaul} 42840516Swpaul 42940516Swpaul/* 43040516Swpaul * Clock a series of bits through the MII. 43140516Swpaul */ 432102335Salfredstatic void 433102335Salfredrl_mii_send(sc, bits, cnt) 43440516Swpaul struct rl_softc *sc; 43540516Swpaul u_int32_t bits; 43640516Swpaul int cnt; 43740516Swpaul{ 43840516Swpaul int i; 43940516Swpaul 44040516Swpaul MII_CLR(RL_MII_CLK); 44140516Swpaul 44240516Swpaul for (i = (0x1 << (cnt - 1)); i; i >>= 1) { 443109109Sdes if (bits & i) { 44440516Swpaul MII_SET(RL_MII_DATAOUT); 445109109Sdes } else { 44640516Swpaul MII_CLR(RL_MII_DATAOUT); 447109109Sdes } 44840516Swpaul DELAY(1); 44940516Swpaul MII_CLR(RL_MII_CLK); 45040516Swpaul DELAY(1); 45140516Swpaul MII_SET(RL_MII_CLK); 45240516Swpaul } 45340516Swpaul} 45440516Swpaul 45540516Swpaul/* 45640516Swpaul * Read an PHY register through the MII. 45740516Swpaul */ 458102335Salfredstatic int 459102335Salfredrl_mii_readreg(sc, frame) 46040516Swpaul struct rl_softc *sc; 46140516Swpaul struct rl_mii_frame *frame; 462109109Sdes 46340516Swpaul{ 46467087Swpaul int i, ack; 46540516Swpaul 46667087Swpaul RL_LOCK(sc); 46740516Swpaul 46840516Swpaul /* 46940516Swpaul * Set up frame for RX. 47040516Swpaul */ 47140516Swpaul frame->mii_stdelim = RL_MII_STARTDELIM; 47240516Swpaul frame->mii_opcode = RL_MII_READOP; 47340516Swpaul frame->mii_turnaround = 0; 47440516Swpaul frame->mii_data = 0; 475109109Sdes 47640516Swpaul CSR_WRITE_2(sc, RL_MII, 0); 47740516Swpaul 47840516Swpaul /* 479109109Sdes * Turn on data xmit. 48040516Swpaul */ 48140516Swpaul MII_SET(RL_MII_DIR); 48240516Swpaul 48340516Swpaul rl_mii_sync(sc); 48440516Swpaul 48540516Swpaul /* 48640516Swpaul * Send command/address info. 48740516Swpaul */ 48840516Swpaul rl_mii_send(sc, frame->mii_stdelim, 2); 48940516Swpaul rl_mii_send(sc, frame->mii_opcode, 2); 49040516Swpaul rl_mii_send(sc, frame->mii_phyaddr, 5); 49140516Swpaul rl_mii_send(sc, frame->mii_regaddr, 5); 49240516Swpaul 49340516Swpaul /* Idle bit */ 49440516Swpaul MII_CLR((RL_MII_CLK|RL_MII_DATAOUT)); 49540516Swpaul DELAY(1); 49640516Swpaul MII_SET(RL_MII_CLK); 49740516Swpaul DELAY(1); 49840516Swpaul 49940516Swpaul /* Turn off xmit. */ 50040516Swpaul MII_CLR(RL_MII_DIR); 50140516Swpaul 50240516Swpaul /* Check for ack */ 50340516Swpaul MII_CLR(RL_MII_CLK); 50440516Swpaul DELAY(1); 505109058Smbr ack = CSR_READ_2(sc, RL_MII) & RL_MII_DATAIN; 50640516Swpaul MII_SET(RL_MII_CLK); 50740516Swpaul DELAY(1); 50840516Swpaul 50940516Swpaul /* 51040516Swpaul * Now try reading data bits. If the ack failed, we still 51140516Swpaul * need to clock through 16 cycles to keep the PHY(s) in sync. 51240516Swpaul */ 51340516Swpaul if (ack) { 51440516Swpaul for(i = 0; i < 16; i++) { 51540516Swpaul MII_CLR(RL_MII_CLK); 51640516Swpaul DELAY(1); 51740516Swpaul MII_SET(RL_MII_CLK); 51840516Swpaul DELAY(1); 51940516Swpaul } 52040516Swpaul goto fail; 52140516Swpaul } 52240516Swpaul 52340516Swpaul for (i = 0x8000; i; i >>= 1) { 52440516Swpaul MII_CLR(RL_MII_CLK); 52540516Swpaul DELAY(1); 52640516Swpaul if (!ack) { 52740516Swpaul if (CSR_READ_2(sc, RL_MII) & RL_MII_DATAIN) 52840516Swpaul frame->mii_data |= i; 52940516Swpaul DELAY(1); 53040516Swpaul } 53140516Swpaul MII_SET(RL_MII_CLK); 53240516Swpaul DELAY(1); 53340516Swpaul } 53440516Swpaul 53540516Swpaulfail: 53640516Swpaul 53740516Swpaul MII_CLR(RL_MII_CLK); 53840516Swpaul DELAY(1); 53940516Swpaul MII_SET(RL_MII_CLK); 54040516Swpaul DELAY(1); 54140516Swpaul 54267087Swpaul RL_UNLOCK(sc); 54340516Swpaul 54440516Swpaul if (ack) 54540516Swpaul return(1); 54640516Swpaul return(0); 54740516Swpaul} 54840516Swpaul 54940516Swpaul/* 55040516Swpaul * Write to a PHY register through the MII. 55140516Swpaul */ 552102335Salfredstatic int 553102335Salfredrl_mii_writereg(sc, frame) 55440516Swpaul struct rl_softc *sc; 55540516Swpaul struct rl_mii_frame *frame; 556109109Sdes 55740516Swpaul{ 55867087Swpaul RL_LOCK(sc); 55940516Swpaul 56040516Swpaul /* 56140516Swpaul * Set up frame for TX. 56240516Swpaul */ 56340516Swpaul 56440516Swpaul frame->mii_stdelim = RL_MII_STARTDELIM; 56540516Swpaul frame->mii_opcode = RL_MII_WRITEOP; 56640516Swpaul frame->mii_turnaround = RL_MII_TURNAROUND; 567109109Sdes 56840516Swpaul /* 569109109Sdes * Turn on data output. 57040516Swpaul */ 57140516Swpaul MII_SET(RL_MII_DIR); 57240516Swpaul 57340516Swpaul rl_mii_sync(sc); 57440516Swpaul 57540516Swpaul rl_mii_send(sc, frame->mii_stdelim, 2); 57640516Swpaul rl_mii_send(sc, frame->mii_opcode, 2); 57740516Swpaul rl_mii_send(sc, frame->mii_phyaddr, 5); 57840516Swpaul rl_mii_send(sc, frame->mii_regaddr, 5); 57940516Swpaul rl_mii_send(sc, frame->mii_turnaround, 2); 58040516Swpaul rl_mii_send(sc, frame->mii_data, 16); 58140516Swpaul 58240516Swpaul /* Idle bit. */ 58340516Swpaul MII_SET(RL_MII_CLK); 58440516Swpaul DELAY(1); 58540516Swpaul MII_CLR(RL_MII_CLK); 58640516Swpaul DELAY(1); 58740516Swpaul 58840516Swpaul /* 58940516Swpaul * Turn off xmit. 59040516Swpaul */ 59140516Swpaul MII_CLR(RL_MII_DIR); 59240516Swpaul 59367087Swpaul RL_UNLOCK(sc); 59440516Swpaul 59540516Swpaul return(0); 59640516Swpaul} 59740516Swpaul 598102335Salfredstatic int 599102335Salfredrl_miibus_readreg(dev, phy, reg) 60050703Swpaul device_t dev; 60150703Swpaul int phy, reg; 60250703Swpaul{ 60340516Swpaul struct rl_softc *sc; 60440516Swpaul struct rl_mii_frame frame; 60540516Swpaul u_int16_t rval = 0; 60640516Swpaul u_int16_t rl8139_reg = 0; 60740516Swpaul 60850703Swpaul sc = device_get_softc(dev); 60967087Swpaul RL_LOCK(sc); 61050703Swpaul 611119868Swpaul if (sc->rl_type == RL_8139) { 61250703Swpaul /* Pretend the internal PHY is only at address 0 */ 61367087Swpaul if (phy) { 61467087Swpaul RL_UNLOCK(sc); 61550703Swpaul return(0); 61667087Swpaul } 61740516Swpaul switch(reg) { 61850703Swpaul case MII_BMCR: 61940516Swpaul rl8139_reg = RL_BMCR; 62040516Swpaul break; 62150703Swpaul case MII_BMSR: 62240516Swpaul rl8139_reg = RL_BMSR; 62340516Swpaul break; 62450703Swpaul case MII_ANAR: 62540516Swpaul rl8139_reg = RL_ANAR; 62640516Swpaul break; 62750703Swpaul case MII_ANER: 62850703Swpaul rl8139_reg = RL_ANER; 62950703Swpaul break; 63050703Swpaul case MII_ANLPAR: 63140516Swpaul rl8139_reg = RL_LPAR; 63240516Swpaul break; 63350703Swpaul case MII_PHYIDR1: 63450703Swpaul case MII_PHYIDR2: 63567087Swpaul RL_UNLOCK(sc); 63650703Swpaul return(0); 63794149Swpaul /* 63894149Swpaul * Allow the rlphy driver to read the media status 63994149Swpaul * register. If we have a link partner which does not 64094149Swpaul * support NWAY, this is the register which will tell 64194149Swpaul * us the results of parallel detection. 64294149Swpaul */ 64394149Swpaul case RL_MEDIASTAT: 64494149Swpaul rval = CSR_READ_1(sc, RL_MEDIASTAT); 64594149Swpaul RL_UNLOCK(sc); 64694149Swpaul return(rval); 64740516Swpaul default: 64840516Swpaul printf("rl%d: bad phy register\n", sc->rl_unit); 64967087Swpaul RL_UNLOCK(sc); 65040516Swpaul return(0); 65140516Swpaul } 65240516Swpaul rval = CSR_READ_2(sc, rl8139_reg); 65367087Swpaul RL_UNLOCK(sc); 65440516Swpaul return(rval); 65540516Swpaul } 65640516Swpaul 65740516Swpaul bzero((char *)&frame, sizeof(frame)); 65840516Swpaul 65950703Swpaul frame.mii_phyaddr = phy; 66040516Swpaul frame.mii_regaddr = reg; 66140516Swpaul rl_mii_readreg(sc, &frame); 66267087Swpaul RL_UNLOCK(sc); 66340516Swpaul 66440516Swpaul return(frame.mii_data); 66540516Swpaul} 66640516Swpaul 667102335Salfredstatic int 668102335Salfredrl_miibus_writereg(dev, phy, reg, data) 66950703Swpaul device_t dev; 67050703Swpaul int phy, reg, data; 67150703Swpaul{ 67240516Swpaul struct rl_softc *sc; 67340516Swpaul struct rl_mii_frame frame; 67440516Swpaul u_int16_t rl8139_reg = 0; 67540516Swpaul 67650703Swpaul sc = device_get_softc(dev); 67767087Swpaul RL_LOCK(sc); 67850703Swpaul 679119868Swpaul if (sc->rl_type == RL_8139) { 68050703Swpaul /* Pretend the internal PHY is only at address 0 */ 68167087Swpaul if (phy) { 68267087Swpaul RL_UNLOCK(sc); 68350703Swpaul return(0); 68467087Swpaul } 68540516Swpaul switch(reg) { 68650703Swpaul case MII_BMCR: 68740516Swpaul rl8139_reg = RL_BMCR; 68840516Swpaul break; 68950703Swpaul case MII_BMSR: 69040516Swpaul rl8139_reg = RL_BMSR; 69140516Swpaul break; 69250703Swpaul case MII_ANAR: 69340516Swpaul rl8139_reg = RL_ANAR; 69440516Swpaul break; 69550703Swpaul case MII_ANER: 69650703Swpaul rl8139_reg = RL_ANER; 69750703Swpaul break; 69850703Swpaul case MII_ANLPAR: 69940516Swpaul rl8139_reg = RL_LPAR; 70040516Swpaul break; 70150703Swpaul case MII_PHYIDR1: 70250703Swpaul case MII_PHYIDR2: 70367087Swpaul RL_UNLOCK(sc); 70450703Swpaul return(0); 70550703Swpaul break; 70640516Swpaul default: 70740516Swpaul printf("rl%d: bad phy register\n", sc->rl_unit); 70867087Swpaul RL_UNLOCK(sc); 70950703Swpaul return(0); 71040516Swpaul } 71140516Swpaul CSR_WRITE_2(sc, rl8139_reg, data); 71267087Swpaul RL_UNLOCK(sc); 71350703Swpaul return(0); 71440516Swpaul } 71540516Swpaul 71640516Swpaul bzero((char *)&frame, sizeof(frame)); 71740516Swpaul 71850703Swpaul frame.mii_phyaddr = phy; 71940516Swpaul frame.mii_regaddr = reg; 72040516Swpaul frame.mii_data = data; 72140516Swpaul 72240516Swpaul rl_mii_writereg(sc, &frame); 72340516Swpaul 72467087Swpaul RL_UNLOCK(sc); 72550703Swpaul return(0); 72650703Swpaul} 72750703Swpaul 728102335Salfredstatic void 729102335Salfredrl_miibus_statchg(dev) 73050703Swpaul device_t dev; 73150703Swpaul{ 73240516Swpaul return; 73340516Swpaul} 73440516Swpaul 73540516Swpaul/* 73640516Swpaul * Program the 64-bit multicast hash filter. 73740516Swpaul */ 738102335Salfredstatic void 739102335Salfredrl_setmulti(sc) 74040516Swpaul struct rl_softc *sc; 74140516Swpaul{ 74240516Swpaul struct ifnet *ifp; 74340516Swpaul int h = 0; 74440516Swpaul u_int32_t hashes[2] = { 0, 0 }; 74540516Swpaul struct ifmultiaddr *ifma; 74640516Swpaul u_int32_t rxfilt; 74740516Swpaul int mcnt = 0; 74840516Swpaul 74940516Swpaul ifp = &sc->arpcom.ac_if; 75040516Swpaul 75140516Swpaul rxfilt = CSR_READ_4(sc, RL_RXCFG); 75240516Swpaul 75343062Swpaul if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 75440516Swpaul rxfilt |= RL_RXCFG_RX_MULTI; 75540516Swpaul CSR_WRITE_4(sc, RL_RXCFG, rxfilt); 75640516Swpaul CSR_WRITE_4(sc, RL_MAR0, 0xFFFFFFFF); 75740516Swpaul CSR_WRITE_4(sc, RL_MAR4, 0xFFFFFFFF); 75840516Swpaul return; 75940516Swpaul } 76040516Swpaul 76140516Swpaul /* first, zot all the existing hash bits */ 76240516Swpaul CSR_WRITE_4(sc, RL_MAR0, 0); 76340516Swpaul CSR_WRITE_4(sc, RL_MAR4, 0); 76440516Swpaul 76540516Swpaul /* now program new ones */ 76672084Sphk TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 76740516Swpaul if (ifma->ifma_addr->sa_family != AF_LINK) 76840516Swpaul continue; 769130270Snaddy h = ether_crc32_be(LLADDR((struct sockaddr_dl *) 770130270Snaddy ifma->ifma_addr), ETHER_ADDR_LEN) >> 26; 77140516Swpaul if (h < 32) 77240516Swpaul hashes[0] |= (1 << h); 77340516Swpaul else 77440516Swpaul hashes[1] |= (1 << (h - 32)); 77540516Swpaul mcnt++; 77640516Swpaul } 77740516Swpaul 77840516Swpaul if (mcnt) 77940516Swpaul rxfilt |= RL_RXCFG_RX_MULTI; 78040516Swpaul else 78140516Swpaul rxfilt &= ~RL_RXCFG_RX_MULTI; 78240516Swpaul 78340516Swpaul CSR_WRITE_4(sc, RL_RXCFG, rxfilt); 78440516Swpaul CSR_WRITE_4(sc, RL_MAR0, hashes[0]); 78540516Swpaul CSR_WRITE_4(sc, RL_MAR4, hashes[1]); 78640516Swpaul 78740516Swpaul return; 78840516Swpaul} 78940516Swpaul 790102335Salfredstatic void 791102335Salfredrl_reset(sc) 79240516Swpaul struct rl_softc *sc; 79340516Swpaul{ 79440516Swpaul register int i; 79540516Swpaul 79640516Swpaul CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_RESET); 79740516Swpaul 79840516Swpaul for (i = 0; i < RL_TIMEOUT; i++) { 79940516Swpaul DELAY(10); 80040516Swpaul if (!(CSR_READ_1(sc, RL_COMMAND) & RL_CMD_RESET)) 80140516Swpaul break; 80240516Swpaul } 80340516Swpaul if (i == RL_TIMEOUT) 80440516Swpaul printf("rl%d: reset never completed!\n", sc->rl_unit); 80540516Swpaul 806109109Sdes return; 80740516Swpaul} 80840516Swpaul 80940516Swpaul/* 81040516Swpaul * Probe for a RealTek 8129/8139 chip. Check the PCI vendor and device 81140516Swpaul * IDs against our list and return a device name if we find a match. 81240516Swpaul */ 813102335Salfredstatic int 814102335Salfredrl_probe(dev) 81550703Swpaul device_t dev; 81640516Swpaul{ 81740516Swpaul struct rl_type *t; 818119868Swpaul struct rl_softc *sc; 819117388Swpaul int rid; 820117388Swpaul u_int32_t hwrev; 82140516Swpaul 82240516Swpaul t = rl_devs; 823117388Swpaul sc = device_get_softc(dev); 82440516Swpaul 82540516Swpaul while(t->rl_name != NULL) { 82650703Swpaul if ((pci_get_vendor(dev) == t->rl_vid) && 82750703Swpaul (pci_get_device(dev) == t->rl_did)) { 828117388Swpaul 829117388Swpaul /* 830117388Swpaul * Temporarily map the I/O space 831117388Swpaul * so we can read the chip ID register. 832117388Swpaul */ 833117388Swpaul rid = RL_RID; 834127135Snjl sc->rl_res = bus_alloc_resource_any(dev, RL_RES, &rid, 835127135Snjl RF_ACTIVE); 836117388Swpaul if (sc->rl_res == NULL) { 837117388Swpaul device_printf(dev, 838117388Swpaul "couldn't map ports/memory\n"); 839117388Swpaul return(ENXIO); 840117388Swpaul } 841117388Swpaul sc->rl_btag = rman_get_bustag(sc->rl_res); 842117388Swpaul sc->rl_bhandle = rman_get_bushandle(sc->rl_res); 843117388Swpaul mtx_init(&sc->rl_mtx, 844117388Swpaul device_get_nameunit(dev), 845117388Swpaul MTX_NETWORK_LOCK, MTX_DEF); 846119868Swpaul RL_LOCK(sc); 847119868Swpaul hwrev = CSR_READ_4(sc, RL_TXCFG) & RL_TXCFG_HWREV; 848119868Swpaul bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res); 849117388Swpaul RL_UNLOCK(sc); 850117388Swpaul mtx_destroy(&sc->rl_mtx); 851119868Swpaul 852119868Swpaul /* Don't attach to 8139C+ or 8169/8110 chips. */ 853119868Swpaul if (hwrev == RL_HWREV_8139CPLUS || 854124076Swpaul (hwrev == RL_HWREV_8169 && 855124076Swpaul t->rl_did == RT_DEVICEID_8169) || 856119954Swpaul hwrev == RL_HWREV_8169S || 857119954Swpaul hwrev == RL_HWREV_8110S) { 858119868Swpaul t++; 859119868Swpaul continue; 860119868Swpaul } 861119868Swpaul 862119868Swpaul device_set_desc(dev, t->rl_name); 86350703Swpaul return(0); 86440516Swpaul } 86540516Swpaul t++; 86640516Swpaul } 86740516Swpaul 86850703Swpaul return(ENXIO); 86940516Swpaul} 87040516Swpaul 87140516Swpaul/* 87240516Swpaul * Attach the interface. Allocate softc structures, do ifmedia 87340516Swpaul * setup and ethernet/BPF attach. 87440516Swpaul */ 875102335Salfredstatic int 876102335Salfredrl_attach(dev) 87750703Swpaul device_t dev; 87840516Swpaul{ 87940516Swpaul u_char eaddr[ETHER_ADDR_LEN]; 880108729Sjake u_int16_t as[3]; 88140516Swpaul struct rl_softc *sc; 88240516Swpaul struct ifnet *ifp; 883119868Swpaul u_int16_t rl_did = 0; 884117388Swpaul struct rl_type *t; 885108729Sjake int unit, error = 0, rid, i; 88640516Swpaul 88750703Swpaul sc = device_get_softc(dev); 88850703Swpaul unit = device_get_unit(dev); 88940516Swpaul 89093818Sjhb mtx_init(&sc->rl_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 89193818Sjhb MTX_DEF | MTX_RECURSE); 892117208Simp#ifndef BURN_BRIDGES 89340516Swpaul /* 89440516Swpaul * Handle power management nonsense. 89540516Swpaul */ 89640516Swpaul 89770167Swpaul if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 89870167Swpaul u_int32_t iobase, membase, irq; 89940516Swpaul 90070167Swpaul /* Save important PCI config data. */ 90170167Swpaul iobase = pci_read_config(dev, RL_PCI_LOIO, 4); 90270167Swpaul membase = pci_read_config(dev, RL_PCI_LOMEM, 4); 90370167Swpaul irq = pci_read_config(dev, RL_PCI_INTLINE, 4); 90440516Swpaul 90570167Swpaul /* Reset the power state. */ 90670167Swpaul printf("rl%d: chip is is in D%d power mode " 90770167Swpaul "-- setting to D0\n", unit, 90870167Swpaul pci_get_powerstate(dev)); 90940516Swpaul 91070167Swpaul pci_set_powerstate(dev, PCI_POWERSTATE_D0); 91140516Swpaul 91270167Swpaul /* Restore PCI config data. */ 91370167Swpaul pci_write_config(dev, RL_PCI_LOIO, iobase, 4); 91470167Swpaul pci_write_config(dev, RL_PCI_LOMEM, membase, 4); 91570167Swpaul pci_write_config(dev, RL_PCI_INTLINE, irq, 4); 91640516Swpaul } 917117208Simp#endif 91840516Swpaul /* 91940516Swpaul * Map control/status registers. 92040516Swpaul */ 92172813Swpaul pci_enable_busmaster(dev); 92240516Swpaul 923109109Sdes rid = RL_RID; 924127135Snjl sc->rl_res = bus_alloc_resource_any(dev, RL_RES, &rid, RF_ACTIVE); 92550703Swpaul 92650703Swpaul if (sc->rl_res == NULL) { 92750703Swpaul printf ("rl%d: couldn't map ports/memory\n", unit); 92850703Swpaul error = ENXIO; 92940516Swpaul goto fail; 93040516Swpaul } 93140516Swpaul 932117388Swpaul#ifdef notdef 93369127Sroger /* Detect the Realtek 8139B. For some reason, this chip is very 93469127Sroger * unstable when left to autoselect the media 93569127Sroger * The best workaround is to set the device to the required 93669127Sroger * media type or to set it to the 10 Meg speed. 93769127Sroger */ 93869127Sroger 93969127Sroger if ((rman_get_end(sc->rl_res)-rman_get_start(sc->rl_res))==0xff) { 940119868Swpaul printf("rl%d: Realtek 8139B detected. Warning, " 941119868Swpaul "this may be unstable in autoselect mode\n", unit); 94269127Sroger } 943117388Swpaul#endif 94469127Sroger 94550703Swpaul sc->rl_btag = rman_get_bustag(sc->rl_res); 94650703Swpaul sc->rl_bhandle = rman_get_bushandle(sc->rl_res); 94750703Swpaul 948112872Snjl /* Allocate interrupt */ 94950703Swpaul rid = 0; 950127135Snjl sc->rl_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 95150703Swpaul RF_SHAREABLE | RF_ACTIVE); 95250703Swpaul 95350703Swpaul if (sc->rl_irq == NULL) { 95440516Swpaul printf("rl%d: couldn't map interrupt\n", unit); 95550703Swpaul error = ENXIO; 95640516Swpaul goto fail; 95740516Swpaul } 95840516Swpaul 95940516Swpaul /* Reset the adapter. */ 96040516Swpaul rl_reset(sc); 96167931Swpaul sc->rl_eecmd_read = RL_EECMD_READ_6BIT; 96267931Swpaul rl_read_eeprom(sc, (caddr_t)&rl_did, 0, 1, 0); 96368215Swpaul if (rl_did != 0x8129) 96467931Swpaul sc->rl_eecmd_read = RL_EECMD_READ_8BIT; 96540516Swpaul 96640516Swpaul /* 96740516Swpaul * Get station address from the EEPROM. 96840516Swpaul */ 969108729Sjake rl_read_eeprom(sc, (caddr_t)as, RL_EE_EADDR, 3, 0); 970108729Sjake for (i = 0; i < 3; i++) { 971108729Sjake eaddr[(i * 2) + 0] = as[i] & 0xff; 972108729Sjake eaddr[(i * 2) + 1] = as[i] >> 8; 973108729Sjake } 97440516Swpaul 97540516Swpaul sc->rl_unit = unit; 97640516Swpaul bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); 97740516Swpaul 97840516Swpaul /* 97940516Swpaul * Now read the exact device type from the EEPROM to find 98040516Swpaul * out if it's an 8129 or 8139. 98140516Swpaul */ 98240516Swpaul rl_read_eeprom(sc, (caddr_t)&rl_did, RL_EE_PCI_DID, 1, 0); 98340516Swpaul 984117388Swpaul t = rl_devs; 985119868Swpaul sc->rl_type = 0; 986117388Swpaul while(t->rl_name != NULL) { 987117388Swpaul if (rl_did == t->rl_did) { 988117388Swpaul sc->rl_type = t->rl_basetype; 989117388Swpaul break; 990117388Swpaul } 991117388Swpaul t++; 992117388Swpaul } 993119868Swpaul 994119868Swpaul if (sc->rl_type == 0) { 99540516Swpaul printf("rl%d: unknown device ID: %x\n", unit, rl_did); 99650703Swpaul error = ENXIO; 99740516Swpaul goto fail; 99840516Swpaul } 99940516Swpaul 100081713Swpaul /* 100181713Swpaul * Allocate the parent bus DMA tag appropriate for PCI. 100281713Swpaul */ 100381713Swpaul#define RL_NSEG_NEW 32 1004109109Sdes error = bus_dma_tag_create(NULL, /* parent */ 100581713Swpaul 1, 0, /* alignment, boundary */ 100681713Swpaul BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 100781713Swpaul BUS_SPACE_MAXADDR, /* highaddr */ 100881713Swpaul NULL, NULL, /* filter, filterarg */ 100981713Swpaul MAXBSIZE, RL_NSEG_NEW, /* maxsize, nsegments */ 1010109109Sdes BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ 101181713Swpaul BUS_DMA_ALLOCNOW, /* flags */ 1012117126Sscottl NULL, NULL, /* lockfunc, lockarg */ 101381713Swpaul &sc->rl_parent_tag); 1014112872Snjl if (error) 1015112872Snjl goto fail; 101640516Swpaul 101781713Swpaul /* 1018119868Swpaul * Now allocate a tag for the DMA descriptor lists. 1019119868Swpaul * All of our lists are allocated as a contiguous block 1020119868Swpaul * of memory. 102181713Swpaul */ 1022119868Swpaul error = bus_dma_tag_create(sc->rl_parent_tag, /* parent */ 1023119868Swpaul 1, 0, /* alignment, boundary */ 1024119868Swpaul BUS_SPACE_MAXADDR, /* lowaddr */ 1025119868Swpaul BUS_SPACE_MAXADDR, /* highaddr */ 1026119868Swpaul NULL, NULL, /* filter, filterarg */ 1027119868Swpaul RL_RXBUFLEN + 1518, 1, /* maxsize,nsegments */ 1028119868Swpaul BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ 1029119868Swpaul BUS_DMA_ALLOCNOW, /* flags */ 1030119868Swpaul NULL, NULL, /* lockfunc, lockarg */ 1031119868Swpaul &sc->rl_tag); 1032112872Snjl if (error) 1033112872Snjl goto fail; 103481713Swpaul 1035119868Swpaul /* 1036119868Swpaul * Now allocate a chunk of DMA-able memory based on the 1037119868Swpaul * tag we just created. 1038119868Swpaul */ 1039119868Swpaul error = bus_dmamem_alloc(sc->rl_tag, 1040119868Swpaul (void **)&sc->rl_cdata.rl_rx_buf, BUS_DMA_NOWAIT | BUS_DMA_ZERO, 1041119868Swpaul &sc->rl_cdata.rl_rx_dmamap); 1042119868Swpaul 1043119868Swpaul if (error) { 1044119868Swpaul printf("rl%d: no memory for list buffers!\n", unit); 1045119868Swpaul bus_dma_tag_destroy(sc->rl_tag); 1046119868Swpaul sc->rl_tag = NULL; 1047119868Swpaul goto fail; 1048119868Swpaul } 1049119868Swpaul 1050119868Swpaul /* Leave a few bytes before the start of the RX ring buffer. */ 1051119868Swpaul sc->rl_cdata.rl_rx_buf_ptr = sc->rl_cdata.rl_rx_buf; 1052119868Swpaul sc->rl_cdata.rl_rx_buf += sizeof(u_int64_t); 1053119868Swpaul 105450703Swpaul /* Do MII setup */ 105550703Swpaul if (mii_phy_probe(dev, &sc->rl_miibus, 105650703Swpaul rl_ifmedia_upd, rl_ifmedia_sts)) { 105750703Swpaul printf("rl%d: MII without any phy!\n", sc->rl_unit); 105850703Swpaul error = ENXIO; 105950703Swpaul goto fail; 106050703Swpaul } 106150703Swpaul 106240516Swpaul ifp = &sc->arpcom.ac_if; 106340516Swpaul ifp->if_softc = sc; 1064121816Sbrooks if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 106540516Swpaul ifp->if_mtu = ETHERMTU; 106640516Swpaul ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 106740516Swpaul ifp->if_ioctl = rl_ioctl; 1068119868Swpaul ifp->if_start = rl_start; 106940516Swpaul ifp->if_watchdog = rl_watchdog; 107040516Swpaul ifp->if_init = rl_init; 107140516Swpaul ifp->if_baudrate = 10000000; 1072119976Swpaul ifp->if_capabilities = IFCAP_VLAN_MTU; 1073128121Sru#ifdef DEVICE_POLLING 1074128121Sru ifp->if_capabilities |= IFCAP_POLLING; 1075128121Sru#endif 1076119977Swpaul ifp->if_capenable = ifp->if_capabilities; 1077119868Swpaul ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 1078119976Swpaul 1079112872Snjl callout_handle_init(&sc->rl_stat_ch); 1080112872Snjl 108140516Swpaul /* 108263090Sarchie * Call MI attach routine. 108340516Swpaul */ 1084106936Ssam ether_ifattach(ifp, eaddr); 1085106157Simp 1086113609Snjl /* Hook interrupt last to avoid having to lock softc */ 1087106157Simp error = bus_setup_intr(dev, sc->rl_irq, INTR_TYPE_NET, 1088119868Swpaul rl_intr, sc, &sc->rl_intrhand); 1089106157Simp 1090106157Simp if (error) { 1091106157Simp printf("rl%d: couldn't set up irq\n", unit); 1092113609Snjl ether_ifdetach(ifp); 1093106157Simp goto fail; 1094106157Simp } 1095106157Simp 109640516Swpaulfail: 1097112872Snjl if (error) 1098112872Snjl rl_detach(dev); 1099112872Snjl 1100110601Snjl return (error); 110140516Swpaul} 110240516Swpaul 1103113609Snjl/* 1104113609Snjl * Shutdown hardware and free up resources. This can be called any 1105113609Snjl * time after the mutex has been initialized. It is called in both 1106113609Snjl * the error case in attach and the normal detach case so it needs 1107113609Snjl * to be careful about only freeing resources that have actually been 1108113609Snjl * allocated. 1109113609Snjl */ 1110102335Salfredstatic int 1111102335Salfredrl_detach(dev) 111250703Swpaul device_t dev; 111350703Swpaul{ 111450703Swpaul struct rl_softc *sc; 111550703Swpaul struct ifnet *ifp; 111650703Swpaul 111750703Swpaul sc = device_get_softc(dev); 1118112880Sjhb KASSERT(mtx_initialized(&sc->rl_mtx), ("rl mutex not initialized")); 111967087Swpaul RL_LOCK(sc); 112050703Swpaul ifp = &sc->arpcom.ac_if; 112150703Swpaul 1122113609Snjl /* These should only be active if attach succeeded */ 1123113812Simp if (device_is_attached(dev)) { 1124113609Snjl rl_stop(sc); 1125112872Snjl ether_ifdetach(ifp); 1126113609Snjl } 1127113609Snjl if (sc->rl_miibus) 1128112872Snjl device_delete_child(dev, sc->rl_miibus); 1129113609Snjl bus_generic_detach(dev); 113050703Swpaul 1131112872Snjl if (sc->rl_intrhand) 1132112872Snjl bus_teardown_intr(dev, sc->rl_irq, sc->rl_intrhand); 1133112872Snjl if (sc->rl_irq) 1134112872Snjl bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_irq); 1135112872Snjl if (sc->rl_res) 1136112872Snjl bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res); 113750703Swpaul 1138119868Swpaul if (sc->rl_tag) { 1139119868Swpaul bus_dmamap_unload(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap); 1140119868Swpaul bus_dmamem_free(sc->rl_tag, sc->rl_cdata.rl_rx_buf, 1141119868Swpaul sc->rl_cdata.rl_rx_dmamap); 1142119868Swpaul bus_dma_tag_destroy(sc->rl_tag); 1143112872Snjl } 1144112872Snjl if (sc->rl_parent_tag) 1145112872Snjl bus_dma_tag_destroy(sc->rl_parent_tag); 114650703Swpaul 114767087Swpaul RL_UNLOCK(sc); 114867087Swpaul mtx_destroy(&sc->rl_mtx); 114950703Swpaul 115050703Swpaul return(0); 115150703Swpaul} 115250703Swpaul 115340516Swpaul/* 115440516Swpaul * Initialize the transmit descriptors. 115540516Swpaul */ 1156102335Salfredstatic int 1157102335Salfredrl_list_tx_init(sc) 115840516Swpaul struct rl_softc *sc; 115940516Swpaul{ 116040516Swpaul struct rl_chain_data *cd; 116140516Swpaul int i; 116240516Swpaul 116340516Swpaul cd = &sc->rl_cdata; 116440516Swpaul for (i = 0; i < RL_TX_LIST_CNT; i++) { 116545633Swpaul cd->rl_tx_chain[i] = NULL; 116648028Swpaul CSR_WRITE_4(sc, 116748028Swpaul RL_TXADDR0 + (i * sizeof(u_int32_t)), 0x0000000); 116840516Swpaul } 116940516Swpaul 117045633Swpaul sc->rl_cdata.cur_tx = 0; 117145633Swpaul sc->rl_cdata.last_tx = 0; 117240516Swpaul 117340516Swpaul return(0); 117440516Swpaul} 117540516Swpaul 117640516Swpaul/* 117740516Swpaul * A frame has been uploaded: pass the resulting mbuf chain up to 117840516Swpaul * the higher level protocols. 117940516Swpaul * 118040516Swpaul * You know there's something wrong with a PCI bus-master chip design 118140516Swpaul * when you have to use m_devget(). 118240516Swpaul * 118340516Swpaul * The receive operation is badly documented in the datasheet, so I'll 118440516Swpaul * attempt to document it here. The driver provides a buffer area and 118540516Swpaul * places its base address in the RX buffer start address register. 118640516Swpaul * The chip then begins copying frames into the RX buffer. Each frame 118772645Sasmodai * is preceded by a 32-bit RX status word which specifies the length 118840516Swpaul * of the frame and certain other status bits. Each frame (starting with 118940516Swpaul * the status word) is also 32-bit aligned. The frame length is in the 119040516Swpaul * first 16 bits of the status word; the lower 15 bits correspond with 119140516Swpaul * the 'rx status register' mentioned in the datasheet. 119248028Swpaul * 119348028Swpaul * Note: to make the Alpha happy, the frame payload needs to be aligned 119478508Sbmilekic * on a 32-bit boundary. To achieve this, we pass RL_ETHER_ALIGN (2 bytes) 1195109109Sdes * as the offset argument to m_devget(). 119640516Swpaul */ 1197102335Salfredstatic void 1198102335Salfredrl_rxeof(sc) 119940516Swpaul struct rl_softc *sc; 120040516Swpaul{ 1201109109Sdes struct mbuf *m; 1202109109Sdes struct ifnet *ifp; 120340516Swpaul int total_len = 0; 120440516Swpaul u_int32_t rxstat; 120540516Swpaul caddr_t rxbufpos; 120640516Swpaul int wrap = 0; 120740516Swpaul u_int16_t cur_rx; 120840516Swpaul u_int16_t limit; 120940516Swpaul u_int16_t rx_bytes = 0, max_bytes; 121040516Swpaul 1211122689Ssam RL_LOCK_ASSERT(sc); 1212122689Ssam 121340516Swpaul ifp = &sc->arpcom.ac_if; 121440516Swpaul 121581713Swpaul bus_dmamap_sync(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap, 1216108729Sjake BUS_DMASYNC_POSTREAD); 121781713Swpaul 121840516Swpaul cur_rx = (CSR_READ_2(sc, RL_CURRXADDR) + 16) % RL_RXBUFLEN; 121940516Swpaul 122040516Swpaul /* Do not try to read past this point. */ 122140516Swpaul limit = CSR_READ_2(sc, RL_CURRXBUF) % RL_RXBUFLEN; 122240516Swpaul 122340516Swpaul if (limit < cur_rx) 122440516Swpaul max_bytes = (RL_RXBUFLEN - cur_rx) + limit; 122540516Swpaul else 122640516Swpaul max_bytes = limit - cur_rx; 122740516Swpaul 122842738Swpaul while((CSR_READ_1(sc, RL_COMMAND) & RL_CMD_EMPTY_RXBUF) == 0) { 122994883Sluigi#ifdef DEVICE_POLLING 1230102052Ssobomax if (ifp->if_flags & IFF_POLLING) { 123194883Sluigi if (sc->rxcycles <= 0) 123294883Sluigi break; 123394883Sluigi sc->rxcycles--; 123494883Sluigi } 123594883Sluigi#endif /* DEVICE_POLLING */ 123640516Swpaul rxbufpos = sc->rl_cdata.rl_rx_buf + cur_rx; 1237108729Sjake rxstat = le32toh(*(u_int32_t *)rxbufpos); 123840516Swpaul 123940516Swpaul /* 124040516Swpaul * Here's a totally undocumented fact for you. When the 124140516Swpaul * RealTek chip is in the process of copying a packet into 124240516Swpaul * RAM for you, the length will be 0xfff0. If you spot a 124340516Swpaul * packet header with this value, you need to stop. The 124440516Swpaul * datasheet makes absolutely no mention of this and 124540516Swpaul * RealTek should be shot for this. 124640516Swpaul */ 124740516Swpaul if ((u_int16_t)(rxstat >> 16) == RL_RXSTAT_UNFINISHED) 124840516Swpaul break; 1249109109Sdes 125040516Swpaul if (!(rxstat & RL_RXSTAT_RXOK)) { 125140516Swpaul ifp->if_ierrors++; 125250703Swpaul rl_init(sc); 125350703Swpaul return; 125440516Swpaul } 125540516Swpaul 1256109109Sdes /* No errors; receive the packet. */ 125740516Swpaul total_len = rxstat >> 16; 125840516Swpaul rx_bytes += total_len + 4; 125940516Swpaul 126040516Swpaul /* 126142051Swpaul * XXX The RealTek chip includes the CRC with every 126242051Swpaul * received frame, and there's no way to turn this 126342051Swpaul * behavior off (at least, I can't find anything in 1264109109Sdes * the manual that explains how to do it) so we have 126542051Swpaul * to trim off the CRC manually. 126642051Swpaul */ 126742051Swpaul total_len -= ETHER_CRC_LEN; 126842051Swpaul 126942051Swpaul /* 127040516Swpaul * Avoid trying to read more bytes than we know 127140516Swpaul * the chip has prepared for us. 127240516Swpaul */ 127340516Swpaul if (rx_bytes > max_bytes) 127440516Swpaul break; 127540516Swpaul 127640516Swpaul rxbufpos = sc->rl_cdata.rl_rx_buf + 127740516Swpaul ((cur_rx + sizeof(u_int32_t)) % RL_RXBUFLEN); 127840516Swpaul 127940516Swpaul if (rxbufpos == (sc->rl_cdata.rl_rx_buf + RL_RXBUFLEN)) 128040516Swpaul rxbufpos = sc->rl_cdata.rl_rx_buf; 128140516Swpaul 128240516Swpaul wrap = (sc->rl_cdata.rl_rx_buf + RL_RXBUFLEN) - rxbufpos; 128340516Swpaul 128440516Swpaul if (total_len > wrap) { 128578508Sbmilekic m = m_devget(rxbufpos, total_len, RL_ETHER_ALIGN, ifp, 128678508Sbmilekic NULL); 128740516Swpaul if (m == NULL) { 128840516Swpaul ifp->if_ierrors++; 128952426Swpaul } else { 129040516Swpaul m_copyback(m, wrap, total_len - wrap, 129140516Swpaul sc->rl_cdata.rl_rx_buf); 129248028Swpaul } 129342051Swpaul cur_rx = (total_len - wrap + ETHER_CRC_LEN); 129440516Swpaul } else { 129578508Sbmilekic m = m_devget(rxbufpos, total_len, RL_ETHER_ALIGN, ifp, 129678508Sbmilekic NULL); 129740516Swpaul if (m == NULL) { 129840516Swpaul ifp->if_ierrors++; 129978508Sbmilekic } 130042051Swpaul cur_rx += total_len + 4 + ETHER_CRC_LEN; 130140516Swpaul } 130240516Swpaul 130340516Swpaul /* 130440516Swpaul * Round up to 32-bit boundary. 130540516Swpaul */ 130640516Swpaul cur_rx = (cur_rx + 3) & ~3; 130740516Swpaul CSR_WRITE_2(sc, RL_CURRXADDR, cur_rx - 16); 130840516Swpaul 130940516Swpaul if (m == NULL) 131040516Swpaul continue; 131140516Swpaul 131240516Swpaul ifp->if_ipackets++; 1313122689Ssam RL_UNLOCK(sc); 1314106936Ssam (*ifp->if_input)(ifp, m); 1315122689Ssam RL_LOCK(sc); 131640516Swpaul } 131740516Swpaul 131840516Swpaul return; 131940516Swpaul} 132040516Swpaul 132140516Swpaul/* 132240516Swpaul * A frame was downloaded to the chip. It's safe for us to clean up 132340516Swpaul * the list buffers. 132440516Swpaul */ 1325102335Salfredstatic void 1326102335Salfredrl_txeof(sc) 132740516Swpaul struct rl_softc *sc; 132840516Swpaul{ 132940516Swpaul struct ifnet *ifp; 133040516Swpaul u_int32_t txstat; 133140516Swpaul 133240516Swpaul ifp = &sc->arpcom.ac_if; 133340516Swpaul 133440516Swpaul /* 133540516Swpaul * Go through our tx list and free mbufs for those 133640516Swpaul * frames that have been uploaded. 133740516Swpaul */ 133845633Swpaul do { 1339127783Sru if (RL_LAST_TXMBUF(sc) == NULL) 1340127783Sru break; 134145633Swpaul txstat = CSR_READ_4(sc, RL_LAST_TXSTAT(sc)); 134245633Swpaul if (!(txstat & (RL_TXSTAT_TX_OK| 134345633Swpaul RL_TXSTAT_TX_UNDERRUN|RL_TXSTAT_TXABRT))) 134440516Swpaul break; 134540516Swpaul 134645633Swpaul ifp->if_collisions += (txstat & RL_TXSTAT_COLLCNT) >> 24; 134740516Swpaul 1348127783Sru bus_dmamap_unload(sc->rl_tag, RL_LAST_DMAMAP(sc)); 1349127783Sru bus_dmamap_destroy(sc->rl_tag, RL_LAST_DMAMAP(sc)); 1350127783Sru m_freem(RL_LAST_TXMBUF(sc)); 1351127783Sru RL_LAST_TXMBUF(sc) = NULL; 135245633Swpaul if (txstat & RL_TXSTAT_TX_OK) 135345633Swpaul ifp->if_opackets++; 135445633Swpaul else { 135552426Swpaul int oldthresh; 135645633Swpaul ifp->if_oerrors++; 135745633Swpaul if ((txstat & RL_TXSTAT_TXABRT) || 135845633Swpaul (txstat & RL_TXSTAT_OUTOFWIN)) 135945633Swpaul CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG); 136052426Swpaul oldthresh = sc->rl_txthresh; 136152426Swpaul /* error recovery */ 136252426Swpaul rl_reset(sc); 136352426Swpaul rl_init(sc); 136452426Swpaul /* 136552426Swpaul * If there was a transmit underrun, 136652426Swpaul * bump the TX threshold. 136752426Swpaul */ 136852426Swpaul if (txstat & RL_TXSTAT_TX_UNDERRUN) 136952426Swpaul sc->rl_txthresh = oldthresh + 32; 137052426Swpaul return; 137145633Swpaul } 137245633Swpaul RL_INC(sc->rl_cdata.last_tx); 137345633Swpaul ifp->if_flags &= ~IFF_OACTIVE; 137445633Swpaul } while (sc->rl_cdata.last_tx != sc->rl_cdata.cur_tx); 137540516Swpaul 1376127783Sru if (RL_LAST_TXMBUF(sc) == NULL) 1377127783Sru ifp->if_timer = 0; 1378127783Sru else if (ifp->if_timer == 0) 1379127783Sru ifp->if_timer = 5; 138099165Sluigi 138150703Swpaul return; 138250703Swpaul} 138340516Swpaul 1384102335Salfredstatic void 1385102335Salfredrl_tick(xsc) 138650703Swpaul void *xsc; 138750703Swpaul{ 138850703Swpaul struct rl_softc *sc; 138950703Swpaul struct mii_data *mii; 139050703Swpaul 139150703Swpaul sc = xsc; 139267087Swpaul RL_LOCK(sc); 139350703Swpaul mii = device_get_softc(sc->rl_miibus); 139450703Swpaul 139550703Swpaul mii_tick(mii); 139650703Swpaul 139750703Swpaul sc->rl_stat_ch = timeout(rl_tick, sc, hz); 139867087Swpaul RL_UNLOCK(sc); 139950703Swpaul 140040516Swpaul return; 140140516Swpaul} 140240516Swpaul 140394883Sluigi#ifdef DEVICE_POLLING 140494883Sluigistatic void 140594883Sluigirl_poll (struct ifnet *ifp, enum poll_cmd cmd, int count) 140694883Sluigi{ 140794883Sluigi struct rl_softc *sc = ifp->if_softc; 140894883Sluigi 140994883Sluigi RL_LOCK(sc); 1410128121Sru if (!(ifp->if_capenable & IFCAP_POLLING)) { 1411128121Sru ether_poll_deregister(ifp); 1412128121Sru cmd = POLL_DEREGISTER; 1413128121Sru } 141494883Sluigi if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ 1415119868Swpaul CSR_WRITE_2(sc, RL_IMR, RL_INTRS); 141694883Sluigi goto done; 141794883Sluigi } 141894883Sluigi 141994883Sluigi sc->rxcycles = count; 1420119868Swpaul rl_rxeof(sc); 1421119868Swpaul rl_txeof(sc); 142294883Sluigi if (ifp->if_snd.ifq_head != NULL) 1423119868Swpaul rl_start(ifp); 142494883Sluigi 142594883Sluigi if (cmd == POLL_AND_CHECK_STATUS) { /* also check status register */ 142694883Sluigi u_int16_t status; 142794883Sluigi 142894883Sluigi status = CSR_READ_2(sc, RL_ISR); 1429100957Sjhb if (status == 0xffff) 1430100957Sjhb goto done; 143194883Sluigi if (status) 143294883Sluigi CSR_WRITE_2(sc, RL_ISR, status); 143394883Sluigi 143494883Sluigi /* 143594883Sluigi * XXX check behaviour on receiver stalls. 143694883Sluigi */ 143794883Sluigi 143894883Sluigi if (status & RL_ISR_SYSTEM_ERR) { 143994883Sluigi rl_reset(sc); 144094883Sluigi rl_init(sc); 144194883Sluigi } 144294883Sluigi } 144394883Sluigidone: 144494883Sluigi RL_UNLOCK(sc); 144594883Sluigi} 144694883Sluigi#endif /* DEVICE_POLLING */ 144794883Sluigi 1448102335Salfredstatic void 1449102335Salfredrl_intr(arg) 145040516Swpaul void *arg; 145140516Swpaul{ 145240516Swpaul struct rl_softc *sc; 145340516Swpaul struct ifnet *ifp; 145440516Swpaul u_int16_t status; 145540516Swpaul 145640516Swpaul sc = arg; 145786822Siwasaki 145886822Siwasaki if (sc->suspended) { 145986822Siwasaki return; 146086822Siwasaki } 146186822Siwasaki 146267087Swpaul RL_LOCK(sc); 146340516Swpaul ifp = &sc->arpcom.ac_if; 146440516Swpaul 146594883Sluigi#ifdef DEVICE_POLLING 1466102052Ssobomax if (ifp->if_flags & IFF_POLLING) 146794883Sluigi goto done; 1468128121Sru if ((ifp->if_capenable & IFCAP_POLLING) && 1469128121Sru ether_poll_register(rl_poll, ifp)) { /* ok, disable interrupts */ 147094883Sluigi CSR_WRITE_2(sc, RL_IMR, 0x0000); 147194883Sluigi rl_poll(ifp, 0, 1); 147294883Sluigi goto done; 147394883Sluigi } 147494883Sluigi#endif /* DEVICE_POLLING */ 147540516Swpaul 147640516Swpaul for (;;) { 147740516Swpaul 147840516Swpaul status = CSR_READ_2(sc, RL_ISR); 1479100957Sjhb /* If the card has gone away the read returns 0xffff. */ 1480100957Sjhb if (status == 0xffff) 1481100957Sjhb break; 148240516Swpaul if (status) 148340516Swpaul CSR_WRITE_2(sc, RL_ISR, status); 148440516Swpaul 148540516Swpaul if ((status & RL_INTRS) == 0) 148640516Swpaul break; 148740516Swpaul 148840516Swpaul if (status & RL_ISR_RX_OK) 148940516Swpaul rl_rxeof(sc); 149040516Swpaul 149140516Swpaul if (status & RL_ISR_RX_ERR) 149240516Swpaul rl_rxeof(sc); 149340516Swpaul 149445633Swpaul if ((status & RL_ISR_TX_OK) || (status & RL_ISR_TX_ERR)) 149540516Swpaul rl_txeof(sc); 149640516Swpaul 149740516Swpaul if (status & RL_ISR_SYSTEM_ERR) { 149840516Swpaul rl_reset(sc); 149940516Swpaul rl_init(sc); 150040516Swpaul } 150140516Swpaul 150240516Swpaul } 150340516Swpaul 150452426Swpaul if (ifp->if_snd.ifq_head != NULL) 1505119868Swpaul rl_start(ifp); 150640516Swpaul 150794883Sluigi#ifdef DEVICE_POLLING 150894883Sluigidone: 150994883Sluigi#endif 151067087Swpaul RL_UNLOCK(sc); 151167087Swpaul 151240516Swpaul return; 151340516Swpaul} 151440516Swpaul 151540516Swpaul/* 151640516Swpaul * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data 151740516Swpaul * pointers to the fragment pointers. 151840516Swpaul */ 1519102335Salfredstatic int 1520102335Salfredrl_encap(sc, m_head) 152140516Swpaul struct rl_softc *sc; 152240516Swpaul struct mbuf *m_head; 152340516Swpaul{ 152441243Swpaul struct mbuf *m_new = NULL; 152540516Swpaul 152640516Swpaul /* 152745633Swpaul * The RealTek is brain damaged and wants longword-aligned 152845633Swpaul * TX buffers, plus we can only have one fragment buffer 152945633Swpaul * per packet. We have to copy pretty much all the time. 153040516Swpaul */ 1531112839Ssilby m_new = m_defrag(m_head, M_DONTWAIT); 153240516Swpaul 1533113496Ssilby if (m_new == NULL) { 1534113496Ssilby m_freem(m_head); 153541243Swpaul return(1); 1536113496Ssilby } 153741243Swpaul m_head = m_new; 153840516Swpaul 153940516Swpaul /* Pad frames to at least 60 bytes. */ 154041243Swpaul if (m_head->m_pkthdr.len < RL_MIN_FRAMELEN) { 154155058Swpaul /* 154255058Swpaul * Make security concious people happy: zero out the 154355058Swpaul * bytes in the pad area, since we don't know what 154455058Swpaul * this mbuf cluster buffer's previous user might 154555058Swpaul * have left in it. 1546109109Sdes */ 154755058Swpaul bzero(mtod(m_head, char *) + m_head->m_pkthdr.len, 154855058Swpaul RL_MIN_FRAMELEN - m_head->m_pkthdr.len); 154940516Swpaul m_head->m_pkthdr.len += 155052426Swpaul (RL_MIN_FRAMELEN - m_head->m_pkthdr.len); 155141243Swpaul m_head->m_len = m_head->m_pkthdr.len; 155241243Swpaul } 155340516Swpaul 155445633Swpaul RL_CUR_TXMBUF(sc) = m_head; 155540516Swpaul 155640516Swpaul return(0); 155740516Swpaul} 155840516Swpaul 155940516Swpaul/* 156040516Swpaul * Main transmit routine. 156140516Swpaul */ 156240516Swpaul 1563102335Salfredstatic void 1564102335Salfredrl_start(ifp) 156540516Swpaul struct ifnet *ifp; 156640516Swpaul{ 156740516Swpaul struct rl_softc *sc; 156840516Swpaul struct mbuf *m_head = NULL; 156940516Swpaul 157040516Swpaul sc = ifp->if_softc; 157167087Swpaul RL_LOCK(sc); 157240516Swpaul 157345633Swpaul while(RL_CUR_TXMBUF(sc) == NULL) { 157440516Swpaul IF_DEQUEUE(&ifp->if_snd, m_head); 157540516Swpaul if (m_head == NULL) 157640516Swpaul break; 157740516Swpaul 157858801Swpaul if (rl_encap(sc, m_head)) { 157958801Swpaul break; 158058801Swpaul } 158140516Swpaul 158240516Swpaul /* 158340516Swpaul * If there's a BPF listener, bounce a copy of this frame 158440516Swpaul * to him. 158540516Swpaul */ 1586106936Ssam BPF_MTAP(ifp, RL_CUR_TXMBUF(sc)); 158751583Swpaul 158840516Swpaul /* 158940516Swpaul * Transmit the frame. 1590109109Sdes */ 159181713Swpaul bus_dmamap_create(sc->rl_tag, 0, &RL_CUR_DMAMAP(sc)); 159281713Swpaul bus_dmamap_load(sc->rl_tag, RL_CUR_DMAMAP(sc), 159381713Swpaul mtod(RL_CUR_TXMBUF(sc), void *), 1594119868Swpaul RL_CUR_TXMBUF(sc)->m_pkthdr.len, rl_dma_map_txbuf, sc, 0); 159581713Swpaul bus_dmamap_sync(sc->rl_tag, RL_CUR_DMAMAP(sc), 159681713Swpaul BUS_DMASYNC_PREREAD); 159745633Swpaul CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc), 159852426Swpaul RL_TXTHRESH(sc->rl_txthresh) | 159952426Swpaul RL_CUR_TXMBUF(sc)->m_pkthdr.len); 160045633Swpaul 160145633Swpaul RL_INC(sc->rl_cdata.cur_tx); 1602113237Ssilby 1603113237Ssilby /* 1604113237Ssilby * Set a timeout in case the chip goes out to lunch. 1605113237Ssilby */ 1606113237Ssilby ifp->if_timer = 5; 160740516Swpaul } 160840516Swpaul 160940516Swpaul /* 161045633Swpaul * We broke out of the loop because all our TX slots are 161145633Swpaul * full. Mark the NIC as busy until it drains some of the 161245633Swpaul * packets from the queue. 161345633Swpaul */ 161445633Swpaul if (RL_CUR_TXMBUF(sc) != NULL) 161545633Swpaul ifp->if_flags |= IFF_OACTIVE; 161645633Swpaul 161767087Swpaul RL_UNLOCK(sc); 161840516Swpaul 161940516Swpaul return; 162040516Swpaul} 162140516Swpaul 1622102335Salfredstatic void 1623102335Salfredrl_init(xsc) 162440516Swpaul void *xsc; 162540516Swpaul{ 162640516Swpaul struct rl_softc *sc = xsc; 162740516Swpaul struct ifnet *ifp = &sc->arpcom.ac_if; 162850703Swpaul struct mii_data *mii; 162940516Swpaul u_int32_t rxcfg = 0; 163040516Swpaul 163167087Swpaul RL_LOCK(sc); 163250703Swpaul mii = device_get_softc(sc->rl_miibus); 163340516Swpaul 163440516Swpaul /* 163540516Swpaul * Cancel pending I/O and free all RX/TX buffers. 163640516Swpaul */ 163740516Swpaul rl_stop(sc); 163840516Swpaul 1639117029Swpaul /* 1640117029Swpaul * Init our MAC address. Even though the chipset 1641117029Swpaul * documentation doesn't mention it, we need to enter "Config 1642117029Swpaul * register write enable" mode to modify the ID registers. 1643117029Swpaul */ 1644117029Swpaul CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_WRITECFG); 1645119738Stmm CSR_WRITE_STREAM_4(sc, RL_IDR0, 1646119738Stmm *(u_int32_t *)(&sc->arpcom.ac_enaddr[0])); 1647119738Stmm CSR_WRITE_STREAM_4(sc, RL_IDR4, 1648119738Stmm *(u_int32_t *)(&sc->arpcom.ac_enaddr[4])); 1649117029Swpaul CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF); 165040516Swpaul 1651119868Swpaul /* Init the RX buffer pointer register. */ 1652119868Swpaul bus_dmamap_load(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap, 1653119868Swpaul sc->rl_cdata.rl_rx_buf, RL_RXBUFLEN, rl_dma_map_rxbuf, sc, 0); 1654119868Swpaul bus_dmamap_sync(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap, 1655119868Swpaul BUS_DMASYNC_PREWRITE); 165640516Swpaul 1657119868Swpaul /* Init TX descriptors. */ 1658119868Swpaul rl_list_tx_init(sc); 165940516Swpaul 166040516Swpaul /* 166140516Swpaul * Enable transmit and receive. 166240516Swpaul */ 166340516Swpaul CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB); 166440516Swpaul 166540516Swpaul /* 166645633Swpaul * Set the initial TX and RX configuration. 166740516Swpaul */ 166845633Swpaul CSR_WRITE_4(sc, RL_TXCFG, RL_TXCFG_CONFIG); 166940516Swpaul CSR_WRITE_4(sc, RL_RXCFG, RL_RXCFG_CONFIG); 167040516Swpaul 167140516Swpaul /* Set the individual bit to receive frames for this host only. */ 167240516Swpaul rxcfg = CSR_READ_4(sc, RL_RXCFG); 167340516Swpaul rxcfg |= RL_RXCFG_RX_INDIV; 167440516Swpaul 167540516Swpaul /* If we want promiscuous mode, set the allframes bit. */ 167640516Swpaul if (ifp->if_flags & IFF_PROMISC) { 167740516Swpaul rxcfg |= RL_RXCFG_RX_ALLPHYS; 167840516Swpaul CSR_WRITE_4(sc, RL_RXCFG, rxcfg); 167940516Swpaul } else { 168040516Swpaul rxcfg &= ~RL_RXCFG_RX_ALLPHYS; 168140516Swpaul CSR_WRITE_4(sc, RL_RXCFG, rxcfg); 168240516Swpaul } 168340516Swpaul 168440516Swpaul /* 168540516Swpaul * Set capture broadcast bit to capture broadcast frames. 168640516Swpaul */ 168740516Swpaul if (ifp->if_flags & IFF_BROADCAST) { 168840516Swpaul rxcfg |= RL_RXCFG_RX_BROAD; 168940516Swpaul CSR_WRITE_4(sc, RL_RXCFG, rxcfg); 169040516Swpaul } else { 169140516Swpaul rxcfg &= ~RL_RXCFG_RX_BROAD; 169240516Swpaul CSR_WRITE_4(sc, RL_RXCFG, rxcfg); 169340516Swpaul } 169440516Swpaul 169540516Swpaul /* 169640516Swpaul * Program the multicast filter, if necessary. 169740516Swpaul */ 169840516Swpaul rl_setmulti(sc); 169940516Swpaul 170094883Sluigi#ifdef DEVICE_POLLING 170140516Swpaul /* 170294883Sluigi * Disable interrupts if we are polling. 170394883Sluigi */ 1704102052Ssobomax if (ifp->if_flags & IFF_POLLING) 170594883Sluigi CSR_WRITE_2(sc, RL_IMR, 0); 170694883Sluigi else /* otherwise ... */ 170794883Sluigi#endif /* DEVICE_POLLING */ 170894883Sluigi /* 170940516Swpaul * Enable interrupts. 171040516Swpaul */ 1711119868Swpaul CSR_WRITE_2(sc, RL_IMR, RL_INTRS); 171240516Swpaul 171352426Swpaul /* Set initial TX threshold */ 171452426Swpaul sc->rl_txthresh = RL_TX_THRESH_INIT; 171552426Swpaul 171640516Swpaul /* Start RX/TX process. */ 171740516Swpaul CSR_WRITE_4(sc, RL_MISSEDPKT, 0); 1718119868Swpaul 171940516Swpaul /* Enable receiver and transmitter. */ 172040516Swpaul CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB); 172140516Swpaul 172250703Swpaul mii_mediachg(mii); 172340516Swpaul 172440516Swpaul CSR_WRITE_1(sc, RL_CFG1, RL_CFG1_DRVLOAD|RL_CFG1_FULLDUPLEX); 172540516Swpaul 172640516Swpaul ifp->if_flags |= IFF_RUNNING; 172740516Swpaul ifp->if_flags &= ~IFF_OACTIVE; 172840516Swpaul 172950703Swpaul sc->rl_stat_ch = timeout(rl_tick, sc, hz); 173067087Swpaul RL_UNLOCK(sc); 173150703Swpaul 173240516Swpaul return; 173340516Swpaul} 173440516Swpaul 173540516Swpaul/* 173640516Swpaul * Set media options. 173740516Swpaul */ 1738102335Salfredstatic int 1739102335Salfredrl_ifmedia_upd(ifp) 174040516Swpaul struct ifnet *ifp; 174140516Swpaul{ 174240516Swpaul struct rl_softc *sc; 174350703Swpaul struct mii_data *mii; 174440516Swpaul 174540516Swpaul sc = ifp->if_softc; 174650703Swpaul mii = device_get_softc(sc->rl_miibus); 174750703Swpaul mii_mediachg(mii); 174840516Swpaul 174940516Swpaul return(0); 175040516Swpaul} 175140516Swpaul 175240516Swpaul/* 175340516Swpaul * Report current media status. 175440516Swpaul */ 1755102335Salfredstatic void 1756102335Salfredrl_ifmedia_sts(ifp, ifmr) 175740516Swpaul struct ifnet *ifp; 175840516Swpaul struct ifmediareq *ifmr; 175940516Swpaul{ 176040516Swpaul struct rl_softc *sc; 176150703Swpaul struct mii_data *mii; 176240516Swpaul 176340516Swpaul sc = ifp->if_softc; 176450703Swpaul mii = device_get_softc(sc->rl_miibus); 176540516Swpaul 176650703Swpaul mii_pollstat(mii); 176750703Swpaul ifmr->ifm_active = mii->mii_media_active; 176850703Swpaul ifmr->ifm_status = mii->mii_media_status; 176940516Swpaul 177040516Swpaul return; 177140516Swpaul} 177240516Swpaul 1773102335Salfredstatic int 1774102335Salfredrl_ioctl(ifp, command, data) 177540516Swpaul struct ifnet *ifp; 177640516Swpaul u_long command; 177740516Swpaul caddr_t data; 177840516Swpaul{ 177940516Swpaul struct rl_softc *sc = ifp->if_softc; 178040516Swpaul struct ifreq *ifr = (struct ifreq *) data; 178150703Swpaul struct mii_data *mii; 178267087Swpaul int error = 0; 178340516Swpaul 178467087Swpaul RL_LOCK(sc); 178540516Swpaul 178640516Swpaul switch(command) { 178740516Swpaul case SIOCSIFFLAGS: 178840516Swpaul if (ifp->if_flags & IFF_UP) { 178940516Swpaul rl_init(sc); 179040516Swpaul } else { 179140516Swpaul if (ifp->if_flags & IFF_RUNNING) 179240516Swpaul rl_stop(sc); 179340516Swpaul } 179440516Swpaul error = 0; 179540516Swpaul break; 179640516Swpaul case SIOCADDMULTI: 179740516Swpaul case SIOCDELMULTI: 179840516Swpaul rl_setmulti(sc); 179940516Swpaul error = 0; 180040516Swpaul break; 180140516Swpaul case SIOCGIFMEDIA: 180240516Swpaul case SIOCSIFMEDIA: 180350703Swpaul mii = device_get_softc(sc->rl_miibus); 180450703Swpaul error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 180540516Swpaul break; 1806128121Sru case SIOCSIFCAP: 1807129633Syar ifp->if_capenable &= ~IFCAP_POLLING; 1808129633Syar ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING; 1809128121Sru break; 181040516Swpaul default: 1811106936Ssam error = ether_ioctl(ifp, command, data); 181240516Swpaul break; 181340516Swpaul } 181440516Swpaul 181567087Swpaul RL_UNLOCK(sc); 181640516Swpaul 181740516Swpaul return(error); 181840516Swpaul} 181940516Swpaul 1820102335Salfredstatic void 1821102335Salfredrl_watchdog(ifp) 182240516Swpaul struct ifnet *ifp; 182340516Swpaul{ 182440516Swpaul struct rl_softc *sc; 182540516Swpaul 182640516Swpaul sc = ifp->if_softc; 182767087Swpaul RL_LOCK(sc); 182840516Swpaul printf("rl%d: watchdog timeout\n", sc->rl_unit); 182940516Swpaul ifp->if_oerrors++; 183050703Swpaul 1831119868Swpaul rl_txeof(sc); 1832119868Swpaul rl_rxeof(sc); 183340516Swpaul rl_init(sc); 183467087Swpaul RL_UNLOCK(sc); 183540516Swpaul 183640516Swpaul return; 183740516Swpaul} 183840516Swpaul 183940516Swpaul/* 184040516Swpaul * Stop the adapter and free any mbufs allocated to the 184140516Swpaul * RX and TX lists. 184240516Swpaul */ 1843102335Salfredstatic void 1844102335Salfredrl_stop(sc) 184540516Swpaul struct rl_softc *sc; 184640516Swpaul{ 184740516Swpaul register int i; 184840516Swpaul struct ifnet *ifp; 184940516Swpaul 185067087Swpaul RL_LOCK(sc); 185140516Swpaul ifp = &sc->arpcom.ac_if; 185240516Swpaul ifp->if_timer = 0; 185340516Swpaul 185450703Swpaul untimeout(rl_tick, sc, sc->rl_stat_ch); 185594883Sluigi ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 185694883Sluigi#ifdef DEVICE_POLLING 185794883Sluigi ether_poll_deregister(ifp); 185894883Sluigi#endif /* DEVICE_POLLING */ 185950703Swpaul 186040516Swpaul CSR_WRITE_1(sc, RL_COMMAND, 0x00); 186140516Swpaul CSR_WRITE_2(sc, RL_IMR, 0x0000); 1862119868Swpaul bus_dmamap_unload(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap); 186340516Swpaul 1864119868Swpaul /* 1865119868Swpaul * Free the TX list buffers. 1866119868Swpaul */ 1867119868Swpaul for (i = 0; i < RL_TX_LIST_CNT; i++) { 1868119868Swpaul if (sc->rl_cdata.rl_tx_chain[i] != NULL) { 1869119868Swpaul bus_dmamap_unload(sc->rl_tag, 1870119868Swpaul sc->rl_cdata.rl_tx_dmamap[i]); 1871119868Swpaul bus_dmamap_destroy(sc->rl_tag, 1872119868Swpaul sc->rl_cdata.rl_tx_dmamap[i]); 1873119868Swpaul m_freem(sc->rl_cdata.rl_tx_chain[i]); 1874119868Swpaul sc->rl_cdata.rl_tx_chain[i] = NULL; 1875124816Swpaul CSR_WRITE_4(sc, RL_TXADDR0 + (i * sizeof(u_int32_t)), 1876124816Swpaul 0x0000000); 187740516Swpaul } 187840516Swpaul } 187940516Swpaul 188067087Swpaul RL_UNLOCK(sc); 188140516Swpaul return; 188240516Swpaul} 188340516Swpaul 188440516Swpaul/* 188586822Siwasaki * Device suspend routine. Stop the interface and save some PCI 188686822Siwasaki * settings in case the BIOS doesn't restore them properly on 188786822Siwasaki * resume. 188886822Siwasaki */ 1889102335Salfredstatic int 1890102335Salfredrl_suspend(dev) 189186822Siwasaki device_t dev; 189286822Siwasaki{ 1893129672Sjhb#ifndef BURN_BRIDGES 189486822Siwasaki register int i; 1895129672Sjhb#endif 189686822Siwasaki struct rl_softc *sc; 189786822Siwasaki 189886822Siwasaki sc = device_get_softc(dev); 189986822Siwasaki 190086822Siwasaki rl_stop(sc); 190186822Siwasaki 1902129672Sjhb#ifndef BURN_BRIDGES 190386822Siwasaki for (i = 0; i < 5; i++) 1904119868Swpaul sc->saved_maps[i] = pci_read_config(dev, PCIR_MAPS + i * 4, 4); 190586822Siwasaki sc->saved_biosaddr = pci_read_config(dev, PCIR_BIOS, 4); 190686822Siwasaki sc->saved_intline = pci_read_config(dev, PCIR_INTLINE, 1); 190786822Siwasaki sc->saved_cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1); 190886822Siwasaki sc->saved_lattimer = pci_read_config(dev, PCIR_LATTIMER, 1); 1909129672Sjhb#endif 191086822Siwasaki 191186822Siwasaki sc->suspended = 1; 191286822Siwasaki 191386822Siwasaki return (0); 191486822Siwasaki} 191586822Siwasaki 191686822Siwasaki/* 191786822Siwasaki * Device resume routine. Restore some PCI settings in case the BIOS 191886822Siwasaki * doesn't, re-enable busmastering, and restart the interface if 191986822Siwasaki * appropriate. 192086822Siwasaki */ 1921102335Salfredstatic int 1922102335Salfredrl_resume(dev) 192386822Siwasaki device_t dev; 192486822Siwasaki{ 1925129672Sjhb#ifndef BURN_BRIDGES 192686822Siwasaki register int i; 1927129672Sjhb#endif 192886822Siwasaki struct rl_softc *sc; 192986822Siwasaki struct ifnet *ifp; 193086822Siwasaki 193186822Siwasaki sc = device_get_softc(dev); 193286822Siwasaki ifp = &sc->arpcom.ac_if; 193386822Siwasaki 1934129672Sjhb#ifndef BURN_BRIDGES 193586822Siwasaki /* better way to do this? */ 193686822Siwasaki for (i = 0; i < 5; i++) 1937119868Swpaul pci_write_config(dev, PCIR_MAPS + i * 4, sc->saved_maps[i], 4); 193886822Siwasaki pci_write_config(dev, PCIR_BIOS, sc->saved_biosaddr, 4); 193986822Siwasaki pci_write_config(dev, PCIR_INTLINE, sc->saved_intline, 1); 194086822Siwasaki pci_write_config(dev, PCIR_CACHELNSZ, sc->saved_cachelnsz, 1); 194186822Siwasaki pci_write_config(dev, PCIR_LATTIMER, sc->saved_lattimer, 1); 194286822Siwasaki 194386822Siwasaki /* reenable busmastering */ 194486822Siwasaki pci_enable_busmaster(dev); 194586822Siwasaki pci_enable_io(dev, RL_RES); 1946129672Sjhb#endif 194786822Siwasaki 1948109109Sdes /* reinitialize interface if necessary */ 1949109109Sdes if (ifp->if_flags & IFF_UP) 1950109109Sdes rl_init(sc); 195186822Siwasaki 195286822Siwasaki sc->suspended = 0; 195386822Siwasaki 195486822Siwasaki return (0); 195586822Siwasaki} 195686822Siwasaki 195786822Siwasaki/* 195840516Swpaul * Stop all chip I/O so that the kernel's probe routines don't 195940516Swpaul * get confused by errant DMAs when rebooting. 196040516Swpaul */ 1961102335Salfredstatic void 1962102335Salfredrl_shutdown(dev) 196350703Swpaul device_t dev; 196440516Swpaul{ 196550703Swpaul struct rl_softc *sc; 196640516Swpaul 196750703Swpaul sc = device_get_softc(dev); 196850703Swpaul 196940516Swpaul rl_stop(sc); 197040516Swpaul 197140516Swpaul return; 197240516Swpaul} 1973