11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* de2104x.c: A Linux PCI Ethernet driver for Intel/Digital 21040/1 chips. */ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright 2001,2003 Jeff Garzik <jgarzik@pobox.com> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright 1994, 1995 Digital Equipment Corporation. [de4x5.c] 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Written/copyright 1994-2001 by Donald Becker. [tulip.c] 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This software may be used and distributed according to the terms of 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the GNU General Public License (GPL), incorporated herein by reference. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Drivers based on or derived from this code fall under the GPL and must 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retain the authorship, copyright and license notice. This file is not 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a complete program and may only be used when the entire operating 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds system is licensed under the GPL. 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds See the file COPYING in this distribution for more information. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TODO, in rough priority order: 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Support forcing media type with a module parameter, 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds like dl2k.c/sundance.c 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Constants (module parms?) for Rx work limit 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Complete reset on PciErr 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Jumbo frames / dev->change_mtu 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adjust Rx FIFO threshold and Max Rx DMA burst on Rx FIFO error 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Implement Tx software interrupt mitigation via 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Tx descriptor bit 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 30163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 31163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_NAME "de2104x" 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_VERSION "0.7" 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_RELDATE "Mar 17, 2004" 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 41a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/interrupt.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ethtool.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/compiler.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/rtnetlink.h> 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/crc32.h> 485a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/unaligned.h> 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These identify the driver base version and may not be removed. */ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char version[] = 571c3319fb69c29376fe23c1aa0cd7cb6df91c7883Joe Perches"PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")"; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>"); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Intel/Digital 21040/1 series PCI Ethernet driver"); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(DRV_VERSION); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug = -1; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param (debug, int, 0); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC (debug, "de2104x bitmapped message enable number"); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ 698e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) || \ 708e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches defined(CONFIG_SPARC) || defined(__ia64__) || \ 718e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches defined(__sh__) || defined(__mips__) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rx_copybreak = 1518; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rx_copybreak = 100; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param (rx_copybreak, int, 0); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copied"); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NETIF_MSG_PROBE | \ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NETIF_MSG_LINK | \ 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NETIF_MSG_IFDOWN | \ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NETIF_MSG_IFUP | \ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NETIF_MSG_RX_ERR | \ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NETIF_MSG_TX_ERR) 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 87b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen/* Descriptor skip length in 32 bit longwords. */ 88b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen#ifndef CONFIG_DE2104X_DSL 89b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen#define DSL 0 90b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen#else 91b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen#define DSL CONFIG_DE2104X_DSL 92b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen#endif 93b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_RX_RING_SIZE 64 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_TX_RING_SIZE 64 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_RING_BYTES \ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((sizeof(struct de_desc) * DE_RX_RING_SIZE) + \ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (sizeof(struct de_desc) * DE_TX_RING_SIZE)) 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NEXT_TX(N) (((N) + 1) & (DE_TX_RING_SIZE - 1)) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NEXT_RX(N) (((N) + 1) & (DE_RX_RING_SIZE - 1)) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_BUFFS_AVAIL(CP) \ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (((CP)->tx_tail <= (CP)->tx_head) ? \ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (CP)->tx_tail + (DE_TX_RING_SIZE - 1) - (CP)->tx_head : \ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (CP)->tx_tail - (CP)->tx_head - 1) 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_OFFSET 2 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_SETUP_SKB ((struct sk_buff *) 1) 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_DUMMY_SKB ((struct sk_buff *) 2) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_SETUP_FRAME_WORDS 96 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_EEPROM_WORDS 256 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_EEPROM_SIZE (DE_EEPROM_WORDS * sizeof(u16)) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_MAX_MEDIA 5 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_MEDIA_TP_AUTO 0 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_MEDIA_BNC 1 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_MEDIA_AUI 2 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_MEDIA_TP 3 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_MEDIA_TP_FD 4 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_MEDIA_INVALID DE_MAX_MEDIA 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_MEDIA_FIRST 0 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_MEDIA_LAST (DE_MAX_MEDIA - 1) 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_AUI_BNC (SUPPORTED_AUI | SUPPORTED_BNC) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_TIMER_LINK (60 * HZ) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_TIMER_NO_LINK (5 * HZ) 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_NUM_REGS 16 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_REGS_SIZE (DE_NUM_REGS * sizeof(u32)) 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DE_REGS_VER 1 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Time in jiffies before concluding the transmitter is hung. */ 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_TIMEOUT (6*HZ) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is a mysterious value that can be written to CSR11 in the 21040 (only) 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to support a pre-NWay full-duplex signaling mechanism using short frames. 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds No one knows what it should be, but if left at its default value some 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10base2(!) packets trigger a full-duplex-request interrupt. */ 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define FULL_DUPLEX_MAGIC 0x6969 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* NIC registers */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BusMode = 0x00, 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxPoll = 0x08, 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxPoll = 0x10, 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxRingAddr = 0x18, 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxRingAddr = 0x20, 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MacStatus = 0x28, 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MacMode = 0x30, 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IntrMask = 0x38, 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxMissed = 0x40, 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ROMCmd = 0x48, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CSR11 = 0x58, 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIAStatus = 0x60, 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CSR13 = 0x68, 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CSR14 = 0x70, 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CSR15 = 0x78, 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCIPM = 0x40, 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* BusMode bits */ 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CmdReset = (1 << 0), 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CacheAlign16 = 0x00008000, 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BurstLen4 = 0x00000400, 165b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen DescSkipLen = (DSL << 2), 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Rx/TxPoll bits */ 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NormalTxPoll = (1 << 0), 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NormalRxPoll = (1 << 0), 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Tx/Rx descriptor status bits */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DescOwn = (1 << 31), 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxError = (1 << 15), 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxErrLong = (1 << 7), 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxErrCRC = (1 << 1), 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxErrFIFO = (1 << 0), 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxErrRunt = (1 << 11), 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxErrFrame = (1 << 14), 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RingEnd = (1 << 25), 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FirstFrag = (1 << 29), 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LastFrag = (1 << 30), 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxError = (1 << 15), 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxFIFOUnder = (1 << 1), 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxLinkFail = (1 << 2) | (1 << 10) | (1 << 11), 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxMaxCol = (1 << 8), 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxOWC = (1 << 9), 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxJabber = (1 << 14), 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SetupFrame = (1 << 27), 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxSwInt = (1 << 31), 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* MacStatus bits */ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IntrOK = (1 << 16), 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IntrErr = (1 << 15), 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxIntr = (1 << 6), 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxEmpty = (1 << 7), 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxIntr = (1 << 0), 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxEmpty = (1 << 2), 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PciErr = (1 << 13), 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxState = (1 << 22) | (1 << 21) | (1 << 20), 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxState = (1 << 19) | (1 << 18) | (1 << 17), 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LinkFail = (1 << 12), 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LinkPass = (1 << 4), 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxStopped = (1 << 8), 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxStopped = (1 << 1), 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* MacMode bits */ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds TxEnable = (1 << 13), 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxEnable = (1 << 1), 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxTx = TxEnable | RxEnable, 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FullDuplex = (1 << 9), 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AcceptAllMulticast = (1 << 7), 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AcceptAllPhys = (1 << 6), 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BOCnt = (1 << 5), 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MacModeClear = (1<<12) | (1<<11) | (1<<10) | (1<<8) | (1<<3) | 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxTx | BOCnt | AcceptAllPhys | AcceptAllMulticast, 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ROMCmd bits */ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EE_SHIFT_CLK = 0x02, /* EEPROM shift clock. */ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EE_CS = 0x01, /* EEPROM chip select. */ 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EE_DATA_WRITE = 0x04, /* Data from the Tulip to EEPROM. */ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EE_WRITE_0 = 0x01, 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EE_WRITE_1 = 0x05, 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EE_DATA_READ = 0x08, /* Data from the EEPROM chip. */ 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EE_ENB = (0x4800 | EE_CS), 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The EEPROM commands include the alway-set leading bit. */ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EE_READ_CMD = 6, 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* RxMissed bits */ 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxMissedOver = (1 << 16), 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RxMissedMask = 0xffff, 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SROM-related bits */ 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SROMC0InfoLeaf = 27, 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MediaBlockMask = 0x3f, 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MediaCustomCSRs = (1 << 6), 237f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* PCIPM bits */ 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PM_Sleep = (1 << 31), 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PM_Snooze = (1 << 30), 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PM_Mask = PM_Sleep | PM_Snooze, 242f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SIAStatus bits */ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NWayState = (1 << 14) | (1 << 13) | (1 << 12), 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NWayRestart = (1 << 12), 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NonselPortActive = (1 << 9), 247ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary SelPortActive = (1 << 8), 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LinkFailStatus = (1 << 2), 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NetCxnErr = (1 << 1), 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const u32 de_intr_mask = 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds IntrOK | IntrErr | RxIntr | RxEmpty | TxIntr | TxEmpty | 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LinkPass | LinkFail | PciErr; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the programmable burst length to 4 longwords for all: 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMA errors result without these values. Cache align 16 long. 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 260b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominenstatic const u32 de_bus_mode = CacheAlign16 | BurstLen4 | DescSkipLen; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct de_srom_media_block { 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 opts; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 csr13; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 csr14; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 csr15; 267ba2d3587912f82d1ab4367975b1df460db60fb1eEric Dumazet} __packed; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct de_srom_info_leaf { 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 default_media; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 n_blocks; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 unused; 273ba2d3587912f82d1ab4367975b1df460db60fb1eEric Dumazet} __packed; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct de_desc { 276c559a5bc9417c00ba2df59397a27eaf8d8e52aecAl Viro __le32 opts1; 277c559a5bc9417c00ba2df59397a27eaf8d8e52aecAl Viro __le32 opts2; 278c559a5bc9417c00ba2df59397a27eaf8d8e52aecAl Viro __le32 addr1; 279c559a5bc9417c00ba2df59397a27eaf8d8e52aecAl Viro __le32 addr2; 280b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen#if DSL 281b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen __le32 skip[DSL]; 282b77e5228849fdcd7a5d73beb16b9ad99395236ecRisto Suominen#endif 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct media_info { 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 type; /* DE_MEDIA_xxx */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 csr13; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 csr14; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 csr15; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ring_info { 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t mapping; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct de_private { 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned tx_head; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned tx_tail; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned rx_tail; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *regs; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t lock; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_desc *rx_ring; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_desc *tx_ring; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ring_info tx_skb[DE_TX_RING_SIZE]; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ring_info rx_skb[DE_RX_RING_SIZE]; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned rx_buf_sz; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t ring_dma; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 msg_enable; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device_stats net_stats; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *pdev; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 setup_frame[DE_SETUP_FRAME_WORDS]; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 media_type; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 media_supported; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 media_advertise; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct media_info media[DE_MAX_MEDIA]; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct timer_list media_timer; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 *ee_data; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned board_idx; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned de21040 : 1; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned media_lock : 1; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_set_rx_mode (struct net_device *dev); 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_tx (struct de_private *de); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_clean_rings (struct de_private *de); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_media_interrupt (struct de_private *de, u32 status); 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de21040_media_timer (unsigned long data); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de21041_media_timer (unsigned long data); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media); 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 343a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(de_pci_tbl) = { 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP, 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS, 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { }, 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, de_pci_tbl); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char * const media_name[DE_MAX_MEDIA] = { 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "10baseT auto", 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "BNC", 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "AUI", 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "10baseT-HD", 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "10baseT-FD" 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21040 transceiver register settings: 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TP AUTO(unused), BNC(unused), AUI, TP, TP FD*/ 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 t21040_csr13[] = { 0, 0, 0x8F09, 0x8F01, 0x8F01, }; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 t21040_csr14[] = { 0, 0, 0x0705, 0xFFFF, 0xFFFD, }; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 t21040_csr15[] = { 0, 0, 0x0006, 0x0000, 0x0000, }; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/ 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; 368387a85628782690b56492dae4bbf544639f5d4a9Ondrej Zarystatic u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; 369e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86Ondrej Zary/* If on-chip autonegotiation is broken, use half-duplex (FF3F) instead */ 370387a85628782690b56492dae4bbf544639f5d4a9Ondrej Zarystatic u16 t21041_csr14_brk[] = { 0xFF3F, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 37484cc1535cb9043ea1921b81cb086138c0f2dc2b9Morten H. Larsen#define dr32(reg) ioread32(de->regs + (reg)) 37584cc1535cb9043ea1921b81cb086138c0f2dc2b9Morten H. Larsen#define dw32(reg, val) iowrite32((val), de->regs + (reg)) 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_rx_err_acct (struct de_private *de, unsigned rx_tail, 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status, u32 len) 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 381726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches netif_dbg(de, rx_err, de->dev, 382726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches "rx err, slot %d status 0x%x len %d\n", 383726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches rx_tail, status, len); 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((status & 0x38000300) != 0x0300) { 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Ingore earlier buffers. */ 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((status & 0xffff) != 0x7fff) { 388163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_warn(de, rx_err, de->dev, 389163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches "Oversized Ethernet frame spanned multiple buffers, status %08x!\n", 390163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches status); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.rx_length_errors++; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (status & RxError) { 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* There was a fatal error. */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.rx_errors++; /* end of a packet.*/ 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & 0x0890) de->net_stats.rx_length_errors++; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RxErrCRC) de->net_stats.rx_crc_errors++; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RxErrFIFO) de->net_stats.rx_fifo_errors++; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_rx (struct de_private *de) 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned rx_tail = de->rx_tail; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned rx_work = DE_RX_RING_SIZE; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned drop = 0; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40946578a6913e6f5e69229561736b94c18c2e88ae4Roel Kluin while (--rx_work) { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status, len; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_addr_t mapping; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb, *copy_skb; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned copying_skb, buflen; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = de->rx_skb[rx_tail].skb; 4167e0b58f32fb5e9c958078a6d722a7d0b230346a7Eric Sesterhenn / snakebyte BUG_ON(!skb); 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rmb(); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = le32_to_cpu(de->rx_ring[rx_tail].opts1); 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & DescOwn) 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = ((status >> 16) & 0x7ff) - 4; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mapping = de->rx_skb[rx_tail].mapping; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(drop)) { 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.rx_dropped++; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto rx_next; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely((status & 0x38008300) != 0x0300)) { 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_rx_err_acct(de, rx_tail, status, len); 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto rx_next; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds copying_skb = (len <= rx_copybreak); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 437726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches netif_dbg(de, rx_status, de->dev, 438726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches "rx slot %d status 0x%x len %d copying? %d\n", 439726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches rx_tail, status, len, copying_skb); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buflen = copying_skb ? (len + RX_OFFSET) : de->rx_buf_sz; 44221a4e46995fa1a76281ac0281ff837f706231a37Pradeep A Dalvi copy_skb = netdev_alloc_skb(de->dev, buflen); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(!copy_skb)) { 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.rx_dropped++; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drop = 1; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx_work = 100; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto rx_next; 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!copying_skb) { 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(de->pdev, mapping, 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buflen, PCI_DMA_FROMDEVICE); 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_put(skb, len); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mapping = 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_skb[rx_tail].mapping = 457689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller pci_map_single(de->pdev, copy_skb->data, 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buflen, PCI_DMA_FROMDEVICE); 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_skb[rx_tail].skb = copy_skb; 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dma_sync_single_for_cpu(de->pdev, mapping, len, PCI_DMA_FROMDEVICE); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve(copy_skb, RX_OFFSET); 463d626f62b11e00c16e81e4308ab93d3f13551812aArnaldo Carvalho de Melo skb_copy_from_linear_data(skb, skb_put(copy_skb, len), 464d626f62b11e00c16e81e4308ab93d3f13551812aArnaldo Carvalho de Melo len); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_dma_sync_single_for_device(de->pdev, mapping, len, PCI_DMA_FROMDEVICE); 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We'll reuse the original ring buffer. */ 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = copy_skb; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->protocol = eth_type_trans (skb, de->dev); 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.rx_packets++; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.rx_bytes += skb->len; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = netif_rx (skb); 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc == NET_RX_DROP) 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drop = 1; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrx_next: 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rx_tail == (DE_RX_RING_SIZE - 1)) 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring[rx_tail].opts2 = 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_to_le32(RingEnd | de->rx_buf_sz); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring[rx_tail].opts2 = cpu_to_le32(de->rx_buf_sz); 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring[rx_tail].addr1 = cpu_to_le32(mapping); 486b991d2bc4a6e1821555bdc2a682f9aed24650c98Risto Suominen wmb(); 487b991d2bc4a6e1821555bdc2a682f9aed24650c98Risto Suominen de->rx_ring[rx_tail].opts1 = cpu_to_le32(DescOwn); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx_tail = NEXT_RX(rx_tail); 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!rx_work) 492163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netdev_warn(de->dev, "rx work limit reached\n"); 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_tail = rx_tail; 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4977d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t de_interrupt (int irq, void *dev_instance) 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = dev_instance; 5008f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = dr32(MacStatus); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((!(status & (IntrOK|IntrErr))) || (status == 0xFFFF)) 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_NONE; 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 507726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches netif_dbg(de, intr, dev, "intr, status %08x mode %08x desc %u/%u/%u\n", 508726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches status, dr32(MacMode), 509726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches de->rx_tail, de->tx_head, de->tx_tail); 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(MacStatus, status); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (RxIntr | RxEmpty)) { 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_rx(de); 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & RxEmpty) 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(RxPoll, NormalRxPoll); 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock(&de->lock); 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (TxIntr | TxEmpty)) 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_tx(de); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (LinkPass | LinkFail)) 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_media_interrupt(de, status); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock(&de->lock); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & PciErr) { 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 pci_status; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_word(de->pdev, PCI_STATUS, &pci_status); 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(de->pdev, PCI_STATUS, pci_status); 534163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netdev_err(de->dev, 535163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches "PCI bus error, status=%08x, PCI status=%04x\n", 536163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches status, pci_status); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_tx (struct de_private *de) 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned tx_head = de->tx_head; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned tx_tail = de->tx_tail; 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (tx_tail != tx_head) { 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rmb(); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = le32_to_cpu(de->tx_ring[tx_tail].opts1); 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & DescOwn) 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = de->tx_skb[tx_tail].skb; 5577e0b58f32fb5e9c958078a6d722a7d0b230346a7Eric Sesterhenn / snakebyte BUG_ON(!skb); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(skb == DE_DUMMY_SKB)) 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto next; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(skb == DE_SETUP_SKB)) { 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(de->pdev, de->tx_skb[tx_tail].mapping, 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(de->setup_frame), PCI_DMA_TODEVICE); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto next; 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(de->pdev, de->tx_skb[tx_tail].mapping, 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->len, PCI_DMA_TODEVICE); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & LastFrag) { 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TxError) { 572726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches netif_dbg(de, tx_err, de->dev, 573726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches "tx err, status 0x%x\n", 574726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches status); 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.tx_errors++; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TxOWC) 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.tx_window_errors++; 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TxMaxCol) 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.tx_aborted_errors++; 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TxLinkFail) 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.tx_carrier_errors++; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & TxFIFOUnder) 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.tx_fifo_errors++; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.tx_packets++; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.tx_bytes += skb->len; 587726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches netif_dbg(de, tx_done, de->dev, 588726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches "tx done, slot %d\n", tx_tail); 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_irq(skb); 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnext: 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_skb[tx_tail].skb = NULL; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_tail = NEXT_TX(tx_tail); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_tail = tx_tail; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_queue_stopped(de->dev) && (TX_BUFFS_AVAIL(de) > (DE_TX_RING_SIZE / 4))) 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue(de->dev); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 605ad096463f7ff809389454ea4219058a36564d55eStephen Hemmingerstatic netdev_tx_t de_start_xmit (struct sk_buff *skb, 606ad096463f7ff809389454ea4219058a36564d55eStephen Hemminger struct net_device *dev) 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6088f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int entry, tx_free; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mapping, len, flags = FirstFrag | LastFrag; 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_desc *txd; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&de->lock); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_free = TX_BUFFS_AVAIL(de); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tx_free == 0) { 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&de->lock); 6195b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy return NETDEV_TX_BUSY; 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tx_free--; 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = de->tx_head; 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txd = &de->tx_ring[entry]; 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = skb->len; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mapping = pci_map_single(de->pdev, skb->data, len, PCI_DMA_TODEVICE); 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (entry == (DE_TX_RING_SIZE - 1)) 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags |= RingEnd; 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!tx_free || (tx_free == (DE_TX_RING_SIZE / 2))) 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags |= TxSwInt; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags |= len; 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txd->opts2 = cpu_to_le32(flags); 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txd->addr1 = cpu_to_le32(mapping); 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_skb[entry].skb = skb; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_skb[entry].mapping = mapping; 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txd->opts1 = cpu_to_le32(DescOwn); 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_head = NEXT_TX(entry); 645726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches netif_dbg(de, tx_queued, dev, "tx queued, slot %d, skblen %d\n", 646726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches entry, skb->len); 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tx_free == 0) 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&de->lock); 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Trigger an immediate transmit demand. */ 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(TxPoll, NormalTxPoll); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6566ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set or clear the multicast filter for this adaptor. 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Note that we only use exclusion around actually queueing the 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new frame, not around filling de->setup_frame. This is non-deterministic 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds when re-entered but still correct. */ 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef set_bit_le 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0) 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6698f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 hash_table[32]; 67122bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko struct netdev_hw_addr *ha; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 *eaddrs; 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(hash_table, 0, sizeof(hash_table)); 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit_le(255, hash_table); /* Broadcast entry */ 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This should work on big-endian machines as well. */ 67822bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko netdev_for_each_mc_addr(ha, dev) { 67922bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff; 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_bit_le(index, hash_table); 6824302b67e041ea81c8fc233bee1296516e1294a27Jiri Pirko } 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6844302b67e041ea81c8fc233bee1296516e1294a27Jiri Pirko for (i = 0; i < 32; i++) { 6854302b67e041ea81c8fc233bee1296516e1294a27Jiri Pirko *setup_frm++ = hash_table[i]; 6864302b67e041ea81c8fc233bee1296516e1294a27Jiri Pirko *setup_frm++ = hash_table[i]; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6884302b67e041ea81c8fc233bee1296516e1294a27Jiri Pirko setup_frm = &de->setup_frame[13*6]; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill the final entry with our physical address. */ 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eaddrs = (u16 *)dev->dev_addr; 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6998f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 70022bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko struct netdev_hw_addr *ha; 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 *eaddrs; 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We have <= 14 addresses so we can use the wonderful 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16 address perfect filtering of the Tulip. */ 70522bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko netdev_for_each_mc_addr(ha, dev) { 70622bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko eaddrs = (u16 *) ha->addr; 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill the unused entries with the broadcast address. */ 7124302b67e041ea81c8fc233bee1296516e1294a27Jiri Pirko memset(setup_frm, 0xff, (15 - netdev_mc_count(dev)) * 12); 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds setup_frm = &de->setup_frame[15*6]; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill the final entry with our physical address. */ 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eaddrs = (u16 *)dev->dev_addr; 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __de_set_rx_mode (struct net_device *dev) 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7258f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 macmode; 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int entry; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mapping; 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_desc *txd; 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_desc *dummy_txd = NULL; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds macmode = dr32(MacMode) & ~(AcceptAllMulticast | AcceptAllPhys); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds macmode |= AcceptAllMulticast | AcceptAllPhys; 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7394cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko if ((netdev_mc_count(dev) > 1000) || (dev->flags & IFF_ALLMULTI)) { 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Too many to filter well -- accept all multicasts. */ 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds macmode |= AcceptAllMulticast; 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Note that only the low-address shortword of setup_frame is valid! 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The values are doubled for big-endian architectures. */ 7474cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko if (netdev_mc_count(dev) > 14) /* Must use a multicast hash table. */ 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds build_setup_frame_hash (de->setup_frame, dev); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds build_setup_frame_perfect (de->setup_frame, dev); 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Now add this frame to the Tx list. 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = de->tx_head; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Avoid a chip errata by prefixing a dummy entry. */ 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (entry != 0) { 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_skb[entry].skb = DE_DUMMY_SKB; 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dummy_txd = &de->tx_ring[entry]; 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dummy_txd->opts2 = (entry == (DE_TX_RING_SIZE - 1)) ? 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_to_le32(RingEnd) : 0; 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dummy_txd->addr1 = 0; 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Must set DescOwned later to avoid race with chip */ 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = NEXT_TX(entry); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_skb[entry].skb = DE_SETUP_SKB; 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_skb[entry].mapping = mapping = 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_map_single (de->pdev, de->setup_frame, 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof (de->setup_frame), PCI_DMA_TODEVICE); 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Put the setup frame on the Tx list. */ 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txd = &de->tx_ring[entry]; 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (entry == (DE_TX_RING_SIZE - 1)) 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txd->opts2 = cpu_to_le32(SetupFrame | RingEnd | sizeof (de->setup_frame)); 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txd->opts2 = cpu_to_le32(SetupFrame | sizeof (de->setup_frame)); 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txd->addr1 = cpu_to_le32(mapping); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds txd->opts1 = cpu_to_le32(DescOwn); 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dummy_txd) { 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dummy_txd->opts1 = cpu_to_le32(DescOwn); 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_head = NEXT_TX(entry); 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (TX_BUFFS_AVAIL(de) == 0) 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Trigger an immediate transmit demand. */ 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(TxPoll, NormalTxPoll); 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (macmode != dr32(MacMode)) 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(MacMode, macmode); 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_set_rx_mode (struct net_device *dev) 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 8108f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave (&de->lock, flags); 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __de_set_rx_mode(dev); 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore (&de->lock, flags); 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void de_rx_missed(struct de_private *de, u32 rx_missed) 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(rx_missed & RxMissedOver)) 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.rx_missed_errors += RxMissedMask; 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.rx_missed_errors += (rx_missed & RxMissedMask); 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __de_get_stats(struct de_private *de) 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tmp = dr32(RxMissed); /* self-clearing */ 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_rx_missed(de, tmp); 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device_stats *de_get_stats(struct net_device *dev) 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8348f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The chip only need report frame silently dropped. */ 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&de->lock); 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_running(dev) && netif_device_present(dev)) 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __de_get_stats(de); 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&de->lock); 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return &de->net_stats; 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int de_is_running (struct de_private *de) 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (dr32(MacStatus) & (RxState | TxState)) ? 1 : 0; 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_stop_rxtx (struct de_private *de) 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 macmode; 85369cac988f2d8506d0b479c5ae7903b9067d7641dGrant Grundler unsigned int i = 1300/100; 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds macmode = dr32(MacMode); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (macmode & RxTx) { 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(MacMode, macmode & ~RxTx); 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dr32(MacMode); 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 86169cac988f2d8506d0b479c5ae7903b9067d7641dGrant Grundler /* wait until in-flight frame completes. 86269cac988f2d8506d0b479c5ae7903b9067d7641dGrant Grundler * Max time @ 10BT: 1500*8b/10Mbps == 1200us (+ 100us margin) 86369cac988f2d8506d0b479c5ae7903b9067d7641dGrant Grundler * Typically expect this loop to end in < 50 us on 100BT. 86469cac988f2d8506d0b479c5ae7903b9067d7641dGrant Grundler */ 86569cac988f2d8506d0b479c5ae7903b9067d7641dGrant Grundler while (--i) { 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!de_is_running(de)) 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 86869cac988f2d8506d0b479c5ae7903b9067d7641dGrant Grundler udelay(100); 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 870f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 871163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netdev_warn(de->dev, "timeout expired, stopping DMA\n"); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void de_start_rxtx (struct de_private *de) 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 macmode; 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds macmode = dr32(MacMode); 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((macmode & RxTx) != RxTx) { 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(MacMode, macmode | RxTx); 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dr32(MacMode); 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_stop_hw (struct de_private *de) 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(5); 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(IntrMask, 0); 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_stop_rxtx(de); 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(MacStatus, dr32(MacStatus)); 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(10); 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_tail = 0; 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_head = de->tx_tail = 0; 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_link_up(struct de_private *de) 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!netif_carrier_ok(de->dev)) { 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_carrier_on(de->dev); 905163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, link, de->dev, "link up, media %s\n", 906163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches media_name[de->media_type]); 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_link_down(struct de_private *de) 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_carrier_ok(de->dev)) { 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_carrier_off(de->dev); 914163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, link, de->dev, "link down\n"); 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_set_media (struct de_private *de) 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned media = de->media_type; 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 macmode = dr32(MacMode); 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 923f25f0f8dcd99e954dc0acf2fcb556cbcd7394549Ondrej Zary if (de_is_running(de)) 924163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netdev_warn(de->dev, "chip is running while changing media!\n"); 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->de21040) 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(CSR11, FULL_DUPLEX_MAGIC); 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(CSR13, 0); /* Reset phy */ 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(CSR14, de->media[media].csr14); 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(CSR15, de->media[media].csr15); 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(CSR13, de->media[media].csr13); 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* must delay 10ms before writing to other registers, 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * especially CSR6 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(10); 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (media == DE_MEDIA_TP_FD) 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds macmode |= FullDuplex; 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds macmode &= ~FullDuplex; 942f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 943163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, link, de->dev, "set link %s\n", media_name[media]); 944163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, hw, de->dev, "mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n", 945163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches dr32(MacMode), dr32(SIAStatus), 946163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches dr32(CSR13), dr32(CSR14), dr32(CSR15)); 947163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, hw, de->dev, "set mode 0x%x, set sia 0x%x,0x%x,0x%x\n", 948163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches macmode, de->media[media].csr13, 949163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches de->media[media].csr14, de->media[media].csr15); 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (macmode != dr32(MacMode)) 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(MacMode, macmode); 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 954215faf9c5f6e319e97edea9e178123e07825c14dJoe Perchesstatic void de_next_media (struct de_private *de, const u32 *media, 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int n_media) 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int i; 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < n_media; i++) { 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de_ok_to_advertise(de, media[i])) { 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_type = media[i]; 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de21040_media_timer (unsigned long data) 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_private *de = (struct de_private *) data; 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = de->dev; 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status = dr32(SIAStatus); 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int carrier; 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 974f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds carrier = (status & NetCxnErr) ? 0 : 1; 976f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (carrier) { 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media_type != DE_MEDIA_AUI && (status & LinkFailStatus)) 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto no_link_yet; 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_timer.expires = jiffies + DE_TIMER_LINK; 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&de->media_timer); 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!netif_carrier_ok(dev)) 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_link_up(de); 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 986163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, timer, dev, "%s link ok, status %x\n", 987163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches media_name[de->media_type], status); 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik de_link_down(de); 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media_lock) 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media_type == DE_MEDIA_AUI) { 997215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches static const u32 next_state = DE_MEDIA_TP; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_next_media(de, &next_state, 1); 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1000215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches static const u32 next_state = DE_MEDIA_AUI; 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_next_media(de, &next_state, 1); 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&de->lock, flags); 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_stop_rxtx(de); 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&de->lock, flags); 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_set_media(de); 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_start_rxtx(de); 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_link_yet: 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_timer.expires = jiffies + DE_TIMER_NO_LINK; 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&de->media_timer); 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1014163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, timer, dev, "no link, trying media %s, status %x\n", 1015163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches media_name[de->media_type], status); 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media) 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (new_media) { 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_TP_AUTO: 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(de->media_advertise & ADVERTISED_Autoneg)) 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(de->media_advertise & (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full))) 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_BNC: 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(de->media_advertise & ADVERTISED_BNC)) 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_AUI: 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(de->media_advertise & ADVERTISED_AUI)) 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_TP: 10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(de->media_advertise & ADVERTISED_10baseT_Half)) 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_TP_FD: 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(de->media_advertise & ADVERTISED_10baseT_Full)) 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1044f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de21041_media_timer (unsigned long data) 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_private *de = (struct de_private *) data; 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = de->dev; 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status = dr32(SIAStatus); 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int carrier; 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1055f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 1056ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary /* clear port active bits */ 1057ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary dw32(SIAStatus, NonselPortActive | SelPortActive); 1058ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds carrier = (status & NetCxnErr) ? 0 : 1; 1060f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (carrier) { 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((de->media_type == DE_MEDIA_TP_AUTO || 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_type == DE_MEDIA_TP || 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_type == DE_MEDIA_TP_FD) && 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (status & LinkFailStatus)) 10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto no_link_yet; 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_timer.expires = jiffies + DE_TIMER_LINK; 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&de->media_timer); 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!netif_carrier_ok(dev)) 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_link_up(de); 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1073163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, timer, dev, 1074163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches "%s link ok, mode %x status %x\n", 1075163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches media_name[de->media_type], 1076163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches dr32(MacMode), status); 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1080f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik de_link_down(de); 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if media type locked, don't switch media */ 10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media_lock) 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto set_media; 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if activity detected, use that as hint for new media type */ 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & NonselPortActive) { 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int have_media = 1; 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if AUI/BNC selected, then activity is on TP port */ 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media_type == DE_MEDIA_AUI || 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_type == DE_MEDIA_BNC) { 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de_ok_to_advertise(de, DE_MEDIA_TP_AUTO)) 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_type = DE_MEDIA_TP_AUTO; 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds have_media = 0; 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* TP selected. If there is only TP and BNC, then it's BNC */ 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_BNC) && 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_ok_to_advertise(de, DE_MEDIA_BNC)) 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_type = DE_MEDIA_BNC; 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* TP selected. If there is only TP and AUI, then it's AUI */ 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (((de->media_supported & DE_AUI_BNC) == SUPPORTED_AUI) && 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_ok_to_advertise(de, DE_MEDIA_AUI)) 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_type = DE_MEDIA_AUI; 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* otherwise, ignore the hint */ 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds have_media = 0; 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (have_media) 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto set_media; 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Absent or ambiguous activity hint, move to next advertised 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * media state. If de->media_type is left unchanged, this 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * simply resets the PHY and reloads the current media settings. 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media_type == DE_MEDIA_AUI) { 1123215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches static const u32 next_states[] = { 1124215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches DE_MEDIA_BNC, DE_MEDIA_TP_AUTO 1125215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches }; 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_next_media(de, next_states, ARRAY_SIZE(next_states)); 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (de->media_type == DE_MEDIA_BNC) { 1128215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches static const u32 next_states[] = { 1129215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches DE_MEDIA_TP_AUTO, DE_MEDIA_AUI 1130215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches }; 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_next_media(de, next_states, ARRAY_SIZE(next_states)); 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1133215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches static const u32 next_states[] = { 1134215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO 1135215faf9c5f6e319e97edea9e178123e07825c14dJoe Perches }; 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_next_media(de, next_states, ARRAY_SIZE(next_states)); 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1138f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_media: 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&de->lock, flags); 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_stop_rxtx(de); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&de->lock, flags); 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_set_media(de); 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_start_rxtx(de); 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsno_link_yet: 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_timer.expires = jiffies + DE_TIMER_NO_LINK; 11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds add_timer(&de->media_timer); 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1150163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, timer, dev, "no link, trying media %s, status %x\n", 1151163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches media_name[de->media_type], status); 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_media_interrupt (struct de_private *de, u32 status) 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & LinkPass) { 1157ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary /* Ignore if current media is AUI or BNC and we can't use TP */ 1158ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary if ((de->media_type == DE_MEDIA_AUI || 1159ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary de->media_type == DE_MEDIA_BNC) && 1160ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary (de->media_lock || 1161ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary !de_ok_to_advertise(de, DE_MEDIA_TP_AUTO))) 1162ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary return; 1163ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary /* If current media is not TP, change it to TP */ 1164ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary if ((de->media_type == DE_MEDIA_AUI || 1165ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary de->media_type == DE_MEDIA_BNC)) { 1166ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary de->media_type = DE_MEDIA_TP_AUTO; 1167ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary de_stop_rxtx(de); 1168ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary de_set_media(de); 1169ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary de_start_rxtx(de); 1170ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary } 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_link_up(de); 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK); 11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1175f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 11767e0b58f32fb5e9c958078a6d722a7d0b230346a7Eric Sesterhenn / snakebyte BUG_ON(!(status & LinkFail)); 1177ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary /* Mark the link as down only if current media is TP */ 1178ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary if (netif_carrier_ok(de->dev) && de->media_type != DE_MEDIA_AUI && 1179ca9a783575d2affed30ef27a3427a7705527ddacOndrej Zary de->media_type != DE_MEDIA_BNC) { 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_link_down(de); 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); 11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_reset_mac (struct de_private *de) 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status, tmp; 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reset MAC. de4x5.c and tulip.c examined for "advice" 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * in this area. 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dr32(BusMode) == 0xffffffff) 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32 (BusMode, CmdReset); 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay (1); 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32 (BusMode, de_bus_mode); 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay (1); 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (tmp = 0; tmp < 5; tmp++) { 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dr32 (BusMode); 12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay (1); 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay (1); 12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = dr32(MacStatus); 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & (RxState | TxState)) 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status == 0xffffffff) 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_adapter_wake (struct de_private *de) 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 pmctl; 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->de21040) 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword(de->pdev, PCIPM, &pmctl); 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pmctl & PM_Mask) { 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pmctl &= ~PM_Mask; 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_dword(de->pdev, PCIPM, pmctl); 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* de4x5.c delays, so we do too */ 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(10); 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_adapter_sleep (struct de_private *de) 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 pmctl; 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->de21040) 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1243b0255a02351b00ca55f4eb2588d05a5db9dd1a58Ondrej Zary dw32(CSR13, 0); /* Reset phy */ 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_dword(de->pdev, PCIPM, &pmctl); 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pmctl |= PM_Sleep; 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_dword(de->pdev, PCIPM, pmctl); 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_init_hw (struct de_private *de) 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = de->dev; 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 macmode; 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_adapter_wake(de); 1256f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds macmode = dr32(MacMode) & ~MacModeClear; 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = de_reset_mac(de); 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_set_media(de); /* reset phy */ 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(RxRingAddr, de->ring_dma); 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(TxRingAddr, de->ring_dma + (sizeof(struct de_desc) * DE_RX_RING_SIZE)); 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(MacMode, RxTx | macmode); 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dr32(RxMissed); /* self-clearing */ 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(IntrMask, de_intr_mask); 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_set_rx_mode(dev); 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_refill_rx (struct de_private *de) 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned i; 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < DE_RX_RING_SIZE; i++) { 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 128621a4e46995fa1a76281ac0281ff837f706231a37Pradeep A Dalvi skb = netdev_alloc_skb(de->dev, de->rx_buf_sz); 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!skb) 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out; 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_skb[i].mapping = pci_map_single(de->pdev, 1291689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller skb->data, de->rx_buf_sz, PCI_DMA_FROMDEVICE); 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_skb[i].skb = skb; 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring[i].opts1 = cpu_to_le32(DescOwn); 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == (DE_RX_RING_SIZE - 1)) 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring[i].opts2 = 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpu_to_le32(RingEnd | de->rx_buf_sz); 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring[i].opts2 = cpu_to_le32(de->rx_buf_sz); 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring[i].addr1 = cpu_to_le32(de->rx_skb[i].mapping); 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring[i].addr2 = 0; 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out: 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_clean_rings(de); 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_init_rings (struct de_private *de) 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(de->tx_ring, 0, sizeof(struct de_desc) * DE_TX_RING_SIZE); 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_ring[DE_TX_RING_SIZE - 1].opts2 = cpu_to_le32(RingEnd); 13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_tail = 0; 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_head = de->tx_tail = 0; 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return de_refill_rx (de); 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_alloc_rings (struct de_private *de) 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring = pci_alloc_consistent(de->pdev, DE_RING_BYTES, &de->ring_dma); 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!de->rx_ring) 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_ring = &de->rx_ring[DE_RX_RING_SIZE]; 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return de_init_rings(de); 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_clean_rings (struct de_private *de) 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned i; 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(de->rx_ring, 0, sizeof(struct de_desc) * DE_RX_RING_SIZE); 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring[DE_RX_RING_SIZE - 1].opts2 = cpu_to_le32(RingEnd); 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(de->tx_ring, 0, sizeof(struct de_desc) * DE_TX_RING_SIZE); 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_ring[DE_TX_RING_SIZE - 1].opts2 = cpu_to_le32(RingEnd); 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wmb(); 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < DE_RX_RING_SIZE; i++) { 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->rx_skb[i].skb) { 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(de->pdev, de->rx_skb[i].mapping, 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_buf_sz, PCI_DMA_FROMDEVICE); 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb(de->rx_skb[i].skb); 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < DE_TX_RING_SIZE; i++) { 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = de->tx_skb[i].skb; 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((skb) && (skb != DE_DUMMY_SKB)) { 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb != DE_SETUP_SKB) { 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->net_stats.tx_dropped++; 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(de->pdev, 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_skb[i].mapping, 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->len, PCI_DMA_TODEVICE); 13585185c7c20a4b88892f868ad8d92d1b640b1edba9Eric Sesterhenn dev_kfree_skb(skb); 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unmap_single(de->pdev, 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_skb[i].mapping, 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(de->setup_frame), 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds PCI_DMA_TODEVICE); 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&de->rx_skb, 0, sizeof(struct ring_info) * DE_RX_RING_SIZE); 13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&de->tx_skb, 0, sizeof(struct ring_info) * DE_TX_RING_SIZE); 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_free_rings (struct de_private *de) 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_clean_rings(de); 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_free_consistent(de->pdev, DE_RING_BYTES, de->rx_ring, de->ring_dma); 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_ring = NULL; 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->tx_ring = NULL; 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_open (struct net_device *dev) 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13828f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1385726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches netif_dbg(de, ifup, dev, "enabling interface\n"); 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = de_alloc_rings(de); 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 1391163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netdev_err(dev, "ring allocation failure, err=%d\n", rc); 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13953f735b76a4e654bee652cbbeb405b9b3ef950316Francois Romieu dw32(IntrMask, 0); 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13971fb9df5d3069064c037c81c0ab8bf783ffa5e373Thomas Gleixner rc = request_irq(dev->irq, de_interrupt, IRQF_SHARED, dev->name, dev); 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 1399163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netdev_err(dev, "IRQ %d request failure, err=%d\n", 1400163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches dev->irq, rc); 14013f735b76a4e654bee652cbbeb405b9b3ef950316Francois Romieu goto err_out_free; 14023f735b76a4e654bee652cbbeb405b9b3ef950316Francois Romieu } 14033f735b76a4e654bee652cbbeb405b9b3ef950316Francois Romieu 14043f735b76a4e654bee652cbbeb405b9b3ef950316Francois Romieu rc = de_init_hw(de); 14053f735b76a4e654bee652cbbeb405b9b3ef950316Francois Romieu if (rc) { 1406163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netdev_err(dev, "h/w init failure, err=%d\n", rc); 14073f735b76a4e654bee652cbbeb405b9b3ef950316Francois Romieu goto err_out_free_irq; 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue(dev); 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14153f735b76a4e654bee652cbbeb405b9b3ef950316Francois Romieuerr_out_free_irq: 14163f735b76a4e654bee652cbbeb405b9b3ef950316Francois Romieu free_irq(dev->irq, dev); 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free: 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_free_rings(de); 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_close (struct net_device *dev) 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14248f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1427726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches netif_dbg(de, ifdown, dev, "disabling interface\n"); 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer_sync(&de->media_timer); 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&de->lock, flags); 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_stop_hw(de); 14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_carrier_off(dev); 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&de->lock, flags); 1436f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq, dev); 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_free_rings(de); 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_adapter_sleep(de); 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_tx_timeout (struct net_device *dev) 14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14468f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1448726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches netdev_dbg(dev, "NIC status %08x mode %08x sia %08x desc %u/%u/%u\n", 1449726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches dr32(MacStatus), dr32(MacMode), dr32(SIAStatus), 1450726b65ad444dd142e34d0087fcbba03d16b34ca6Joe Perches de->rx_tail, de->tx_head, de->tx_tail); 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer_sync(&de->media_timer); 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disable_irq(dev->irq); 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&de->lock); 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_stop_hw(de); 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_carrier_off(dev); 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&de->lock); 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enable_irq(dev->irq); 1463f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Update the error counts. */ 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __de_get_stats(de); 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds synchronize_irq(dev->irq); 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_clean_rings(de); 14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 147039bf4295bb4bcb0c108f74b72dd2eb5b9b9dfaccFrancois Romieu de_init_rings(de); 147139bf4295bb4bcb0c108f74b72dd2eb5b9b9dfaccFrancois Romieu 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_init_hw(de); 1473f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue(dev); 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __de_get_regs(struct de_private *de, u8 *buf) 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 *rbuf = (u32 *)buf; 1481f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* read all CSRs */ 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < DE_NUM_REGS; i++) 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rbuf[i] = dr32(i * 8); 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* handle self-clearing RxMissed counter, CSR8 */ 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_rx_missed(de, rbuf[8]); 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __de_get_settings(struct de_private *de, struct ethtool_cmd *ecmd) 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->supported = de->media_supported; 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->transceiver = XCVR_INTERNAL; 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->phy_address = 0; 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->advertising = de->media_advertise; 1496f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (de->media_type) { 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_AUI: 14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->port = PORT_AUI; 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_BNC: 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->port = PORT_BNC; 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->port = PORT_TP; 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1508f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 1509fbef7139a8b89a7f49ba1410593ed894b4c8b017David Decotigny ethtool_cmd_speed_set(ecmd, 10); 1510fbef7139a8b89a7f49ba1410593ed894b4c8b017David Decotigny 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dr32(MacMode) & FullDuplex) 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->duplex = DUPLEX_FULL; 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->duplex = DUPLEX_HALF; 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media_lock) 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->autoneg = AUTONEG_DISABLE; 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ecmd->autoneg = AUTONEG_ENABLE; 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ignore maxtxpkt, maxrxpkt for now */ 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd) 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 new_media; 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int media_lock; 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531fbef7139a8b89a7f49ba1410593ed894b4c8b017David Decotigny if (ethtool_cmd_speed(ecmd) != 10) 15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ecmd->port != PORT_TP && ecmd->port != PORT_AUI && ecmd->port != PORT_BNC) 15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->de21040 && ecmd->port == PORT_BNC) 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ecmd->transceiver != XCVR_INTERNAL) 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ecmd->advertising & ~de->media_supported) 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ecmd->autoneg == AUTONEG_ENABLE && 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (!(ecmd->advertising & ADVERTISED_Autoneg))) 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1548f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ecmd->port) { 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PORT_AUI: 15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_media = DE_MEDIA_AUI; 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ecmd->advertising & ADVERTISED_AUI)) 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case PORT_BNC: 15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_media = DE_MEDIA_BNC; 15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ecmd->advertising & ADVERTISED_BNC)) 15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ecmd->autoneg == AUTONEG_ENABLE) 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_media = DE_MEDIA_TP_AUTO; 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (ecmd->duplex == DUPLEX_FULL) 15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_media = DE_MEDIA_TP_FD; 15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_media = DE_MEDIA_TP; 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ecmd->advertising & ADVERTISED_TP)) 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(ecmd->advertising & (ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half))) 15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1573f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds media_lock = (ecmd->autoneg == AUTONEG_ENABLE) ? 0 : 1; 1575f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((new_media == de->media_type) && 15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (media_lock == de->media_lock) && 15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (ecmd->advertising == de->media_advertise)) 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* nothing to change */ 1580f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_link_down(de); 1582387a85628782690b56492dae4bbf544639f5d4a9Ondrej Zary mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK); 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_stop_rxtx(de); 1584f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_type = new_media; 15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_lock = media_lock; 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_advertise = ecmd->advertising; 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_set_media(de); 1589387a85628782690b56492dae4bbf544639f5d4a9Ondrej Zary if (netif_running(de->dev)) 1590387a85628782690b56492dae4bbf544639f5d4a9Ondrej Zary de_start_rxtx(de); 1591f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_get_drvinfo (struct net_device *dev,struct ethtool_drvinfo *info) 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15978f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 159968aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 160068aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 160168aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones strlcpy(info->bus_info, pci_name(de->pdev), sizeof(info->bus_info)); 16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds info->eedump_len = DE_EEPROM_SIZE; 16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_get_regs_len(struct net_device *dev) 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return DE_REGS_SIZE; 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16128f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&de->lock); 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = __de_get_settings(de, ecmd); 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&de->lock); 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16248f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&de->lock); 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = __de_set_settings(de, ecmd); 16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&de->lock); 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 de_get_msglevel(struct net_device *dev) 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16368f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return de->msg_enable; 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_set_msglevel(struct net_device *dev, u32 msglvl) 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16438f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->msg_enable = msglvl; 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_get_eeprom(struct net_device *dev, 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_eeprom *eeprom, u8 *data) 16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16518f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!de->ee_data) 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((eeprom->offset != 0) || (eeprom->magic != 0) || 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (eeprom->len != DE_EEPROM_SIZE)) 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(data, de->ee_data, eeprom->len); 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_nway_reset(struct net_device *dev) 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16658f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 status; 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media_type != DE_MEDIA_TP_AUTO) 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_carrier_ok(de->dev)) 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_link_down(de); 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds status = dr32(SIAStatus); 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32(SIAStatus, (status & ~NWayState) | NWayRestart); 1675163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netif_info(de, link, dev, "link nway restart, status %x,%x\n", 1676163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches status, dr32(SIAStatus)); 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void de_get_regs(struct net_device *dev, struct ethtool_regs *regs, 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *data) 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16838f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->version = (DE_REGS_VER << 2) | de->de21040; 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&de->lock); 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __de_get_regs(de, data); 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&de->lock); 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16927282d491ecaee9883233a0e27283c4c79486279aJeff Garzikstatic const struct ethtool_ops de_ethtool_ops = { 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_link = ethtool_op_get_link, 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_drvinfo = de_get_drvinfo, 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_regs_len = de_get_regs_len, 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_settings = de_get_settings, 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_settings = de_set_settings, 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_msglevel = de_get_msglevel, 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_msglevel = de_set_msglevel, 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_eeprom = de_get_eeprom, 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .nway_reset = de_nway_reset, 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_regs = de_get_regs, 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17054c44fd009ae79fc04e2c049f708792ad83400ddePrarit Bhargavastatic void __devinit de21040_get_mac_address (struct de_private *de) 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned i; 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dw32 (ROMCmd, 0); /* Reset the pointer with a dummy write. */ 1710bc0da3fcec1cec11dc451b8fcb9c9ad7e4ca6e12Martin Langer udelay(5); 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) { 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int value, boguscnt = 100000; 1714ec1d1ebbb3bdc9807474be28c29efa155d15b850Hannes Eder do { 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = dr32(ROMCmd); 171684cc1535cb9043ea1921b81cb086138c0f2dc2b9Morten H. Larsen rmb(); 1717ec1d1ebbb3bdc9807474be28c29efa155d15b850Hannes Eder } while (value < 0 && --boguscnt > 0); 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->dev->dev_addr[i] = value; 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(1); 17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (boguscnt <= 0) 1721163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches pr_warn("timeout reading 21040 MAC address byte %u\n", 1722163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches i); 17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17264c44fd009ae79fc04e2c049f708792ad83400ddePrarit Bhargavastatic void __devinit de21040_get_media_info(struct de_private *de) 17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int i; 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_type = DE_MEDIA_TP; 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full | 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SUPPORTED_10baseT_Half | SUPPORTED_AUI; 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_advertise = de->media_supported; 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < DE_MAX_MEDIA; i++) { 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (i) { 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_AUI: 17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_TP: 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case DE_MEDIA_TP_FD: 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].type = i; 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].csr13 = t21040_csr13[i]; 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].csr14 = t21040_csr14[i]; 17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].csr15 = t21040_csr15[i]; 17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].type = DE_MEDIA_INVALID; 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Note: this routine returns extra data bits for size detection. */ 17534a1d2d81fa327d095a0a8a1f961bace5b0a2f7daHelge Dellerstatic unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, int addr_len) 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned retval = 0; 17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *ee_addr = regs + ROMCmd; 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int read_cmd = location | (EE_READ_CMD << addr_len); 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(EE_ENB & ~EE_CS, ee_addr); 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(EE_ENB, ee_addr); 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Shift the read command bits out. */ 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 4 + addr_len; i >= 0; i--) { 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(EE_ENB | dataval, ee_addr); 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readl(ee_addr); 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readl(ee_addr); 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0); 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(EE_ENB, ee_addr); 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readl(ee_addr); 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 16; i > 0; i--) { 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(EE_ENB | EE_SHIFT_CLK, ee_addr); 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readl(ee_addr); 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0); 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(EE_ENB, ee_addr); 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readl(ee_addr); 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Terminate the EEPROM access. */ 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(EE_ENB & ~EE_CS, ee_addr); 17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17884c44fd009ae79fc04e2c049f708792ad83400ddePrarit Bhargavastatic void __devinit de21041_get_srom_info (struct de_private *de) 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned i, sa_offset = 0, ofs; 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 ee_data[DE_EEPROM_SIZE + 6] = {}; 17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned ee_addr_size = tulip_read_eeprom(de->regs, 0xff, 8) & 0x40000 ? 8 : 6; 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_srom_info_leaf *il; 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *bufp; 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* download entire eeprom */ 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < DE_EEPROM_WORDS; i++) 1798c559a5bc9417c00ba2df59397a27eaf8d8e52aecAl Viro ((__le16 *)ee_data)[i] = 1799c559a5bc9417c00ba2df59397a27eaf8d8e52aecAl Viro cpu_to_le16(tulip_read_eeprom(de->regs, i, ee_addr_size)); 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* DEC now has a specification but early board makers 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds just put the address in the first EEPROM locations. */ 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This does memcmp(eedata, eedata+16, 8) */ 1804bc053d45cb0ca5daeaa69ae9ac43cdea42693f60Ralf Baechle 1805bc053d45cb0ca5daeaa69ae9ac43cdea42693f60Ralf Baechle#ifndef CONFIG_MIPS_COBALT 1806bc053d45cb0ca5daeaa69ae9ac43cdea42693f60Ralf Baechle 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 8; i ++) 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ee_data[i] != ee_data[16+i]) 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa_offset = 20; 18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811bc053d45cb0ca5daeaa69ae9ac43cdea42693f60Ralf Baechle#endif 1812bc053d45cb0ca5daeaa69ae9ac43cdea42693f60Ralf Baechle 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* store MAC address */ 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i ++) 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->dev->dev_addr[i] = ee_data[i + sa_offset]; 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get offset of controller 0 info leaf. ignore 2nd byte. */ 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ofs = ee_data[SROMC0InfoLeaf]; 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ofs >= (sizeof(ee_data) - sizeof(struct de_srom_info_leaf) - sizeof(struct de_srom_media_block))) 18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto bad_srom; 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get pointer to info leaf */ 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds il = (struct de_srom_info_leaf *) &ee_data[ofs]; 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* paranoia checks */ 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (il->n_blocks == 0) 18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto bad_srom; 18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sizeof(ee_data) - ofs) < 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (sizeof(struct de_srom_info_leaf) + (sizeof(struct de_srom_media_block) * il->n_blocks))) 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto bad_srom; 18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get default media type */ 1833445854f4c46ff1fa8f4605334914ecd1a1ae574dHarvey Harrison switch (get_unaligned(&il->default_media)) { 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0001: de->media_type = DE_MEDIA_BNC; break; 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0002: de->media_type = DE_MEDIA_AUI; break; 18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0204: de->media_type = DE_MEDIA_TP_FD; break; 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: de->media_type = DE_MEDIA_TP_AUTO; break; 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1839f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_msg_probe(de)) 1841f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches pr_info("de%d: SROM leaf offset %u, default media %s\n", 1842f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches de->board_idx, ofs, media_name[de->media_type]); 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* init SIA register values to defaults */ 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < DE_MAX_MEDIA; i++) { 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].type = DE_MEDIA_INVALID; 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].csr13 = 0xffff; 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].csr14 = 0xffff; 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].csr15 = 0xffff; 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* parse media blocks to see what medias are supported, 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and if any custom CSR values are provided 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufp = ((void *)il) + sizeof(*il); 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < il->n_blocks; i++) { 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_srom_media_block *ib = bufp; 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned idx; 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* index based on media type in media block */ 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(ib->opts & MediaBlockMask) { 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: /* 10baseT */ 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | SUPPORTED_Autoneg; 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx = DE_MEDIA_TP; 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[DE_MEDIA_TP_AUTO].type = DE_MEDIA_TP_AUTO; 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: /* BNC */ 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_supported |= SUPPORTED_BNC; 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx = DE_MEDIA_BNC; 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: /* AUI */ 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_supported |= SUPPORTED_AUI; 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx = DE_MEDIA_AUI; 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: /* 10baseT-FD */ 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full 18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | SUPPORTED_Autoneg; 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx = DE_MEDIA_TP_FD; 18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[DE_MEDIA_TP_AUTO].type = DE_MEDIA_TP_AUTO; 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto bad_srom; 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[idx].type = idx; 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_msg_probe(de)) 1889f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches pr_info("de%d: media block #%u: %s", 1890f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches de->board_idx, i, 1891f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches media_name[de->media[idx].type]); 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufp += sizeof (ib->opts); 18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ib->opts & MediaCustomCSRs) { 1896445854f4c46ff1fa8f4605334914ecd1a1ae574dHarvey Harrison de->media[idx].csr13 = get_unaligned(&ib->csr13); 1897445854f4c46ff1fa8f4605334914ecd1a1ae574dHarvey Harrison de->media[idx].csr14 = get_unaligned(&ib->csr14); 1898445854f4c46ff1fa8f4605334914ecd1a1ae574dHarvey Harrison de->media[idx].csr15 = get_unaligned(&ib->csr15); 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bufp += sizeof(ib->csr13) + sizeof(ib->csr14) + 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(ib->csr15); 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_msg_probe(de)) 1903f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches pr_cont(" (%x,%x,%x)\n", 1904f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches de->media[idx].csr13, 1905f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches de->media[idx].csr14, 1906f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches de->media[idx].csr15); 1907f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 1908163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches } else { 1909163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches if (netif_msg_probe(de)) 1910163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches pr_cont("\n"); 1911163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches } 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bufp > ((void *)&ee_data[DE_EEPROM_SIZE - 3])) 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_advertise = de->media_supported; 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfill_defaults: 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fill in defaults, for cases where custom CSRs not used */ 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < DE_MAX_MEDIA; i++) { 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media[i].csr13 == 0xffff) 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].csr13 = t21041_csr13[i]; 1924e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86Ondrej Zary if (de->media[i].csr14 == 0xffff) { 1925e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86Ondrej Zary /* autonegotiation is broken at least on some chip 1926e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86Ondrej Zary revisions - rev. 0x21 works, 0x11 does not */ 1927e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86Ondrej Zary if (de->pdev->revision < 0x20) 1928e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86Ondrej Zary de->media[i].csr14 = t21041_csr14_brk[i]; 1929e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86Ondrej Zary else 1930e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86Ondrej Zary de->media[i].csr14 = t21041_csr14[i]; 1931e0f9c4f332c99b213d4a0b7cd21dc0781ceb3d86Ondrej Zary } 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->media[i].csr15 == 0xffff) 19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].csr15 = t21041_csr15[i]; 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1936c3a9392e4f3b9d97803b067871d66bc143369dbfEric Sesterhenn de->ee_data = kmemdup(&ee_data[0], DE_EEPROM_SIZE, GFP_KERNEL); 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbad_srom: 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* for error cases, it's ok to assume we support all these */ 19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < DE_MAX_MEDIA; i++) 19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media[i].type = i; 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_supported = 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SUPPORTED_10baseT_Half | 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SUPPORTED_10baseT_Full | 19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SUPPORTED_Autoneg | 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SUPPORTED_TP | 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SUPPORTED_AUI | 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SUPPORTED_BNC; 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fill_defaults; 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 195490d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemmingerstatic const struct net_device_ops de_netdev_ops = { 195590d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger .ndo_open = de_open, 195690d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger .ndo_stop = de_close, 1957afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = de_set_rx_mode, 195890d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger .ndo_start_xmit = de_start_xmit, 195990d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger .ndo_get_stats = de_get_stats, 196090d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger .ndo_tx_timeout = de_tx_timeout, 196190d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger .ndo_change_mtu = eth_change_mtu, 196290d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger .ndo_set_mac_address = eth_mac_addr, 196390d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger .ndo_validate_addr = eth_validate_addr, 196490d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger}; 196590d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger 19664a1d2d81fa327d095a0a8a1f961bace5b0a2f7daHelge Dellerstatic int __devinit de_init_one (struct pci_dev *pdev, 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct pci_device_id *ent) 19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct de_private *de; 19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void __iomem *regs; 1973afc7097f45bdfddc2a0d375ef4a2c38b6e09c339Jeff Garzik unsigned long pciaddr; 19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int board_idx = -1; 19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board_idx++; 19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (board_idx == 0) 19801c3319fb69c29376fe23c1aa0cd7cb6df91c7883Joe Perches pr_info("%s\n", version); 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* allocate a new ethernet device structure, and fill in defaults */ 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = alloc_etherdev(sizeof(struct de_private)); 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 198890d8743d03593520ceb5e8fd8cf3b86072518f83Stephen Hemminger dev->netdev_ops = &de_netdev_ops; 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_NETDEV_DEV(dev, &pdev->dev); 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->ethtool_ops = &de_ethtool_ops; 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->watchdog_timeo = TX_TIMEOUT; 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19938f15ea42b64941001a401cf855a0869e24f3a845Wang Chen de = netdev_priv(dev); 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->de21040 = ent->driver_data == 0 ? 1 : 0; 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->pdev = pdev; 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->dev = dev; 19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->msg_enable = (debug < 0 ? DE_DEF_MSG_ENABLE : debug); 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->board_idx = board_idx; 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init (&de->lock); 20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds init_timer(&de->media_timer); 20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->de21040) 20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_timer.function = de21040_media_timer; 20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_timer.function = de21041_media_timer; 20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->media_timer.data = (unsigned long) de; 20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_carrier_off(dev); 20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* wake up device, assign resources */ 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = pci_enable_device(pdev); 20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free; 20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* reserve PCI resources to ensure driver atomicity */ 20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = pci_request_regions(pdev, DRV_NAME); 20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_disable; 20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check for invalid IRQ value */ 20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev->irq < 2) { 20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EIO; 2022163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches pr_err("invalid irq (%d) for pci dev %s\n", 20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->irq, pci_name(pdev)); 20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_res; 20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = pdev->irq; 20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* obtain and check validity of PCI I/O address */ 20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pciaddr = pci_resource_start(pdev, 1); 20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pciaddr) { 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EIO; 2033163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches pr_err("no MMIO resource for pci dev %s\n", pci_name(pdev)); 20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_res; 20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pci_resource_len(pdev, 1) < DE_REGS_SIZE) { 20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EIO; 2038163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches pr_err("MMIO resource (%llx) too small on pci dev %s\n", 2039f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches (unsigned long long)pci_resource_len(pdev, 1), 2040f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches pci_name(pdev)); 20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_res; 20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* remap CSR registers */ 20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs = ioremap_nocache(pciaddr, DE_REGS_SIZE); 20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!regs) { 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EIO; 2048163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches pr_err("Cannot map PCI MMIO (%llx@%lx) on pci dev %s\n", 2049f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches (unsigned long long)pci_resource_len(pdev, 1), 2050f639dc7dadcbd97f1d666d5ffe00eab1ea3c0f6dJoe Perches pciaddr, pci_name(pdev)); 20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_res; 20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->base_addr = (unsigned long) regs; 20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de->regs = regs; 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_adapter_wake(de); 20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* make sure hardware is not running */ 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = de_reset_mac(de); 20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 2061163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches pr_err("Cannot reset MAC, pci dev %s\n", pci_name(pdev)); 20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_iomap; 20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get MAC address, initialize default media type and 20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get list of supported media 20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (de->de21040) { 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de21040_get_mac_address(de); 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de21040_get_media_info(de); 20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de21041_get_srom_info(de); 20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* register new network interface with kernel */ 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = register_netdev(dev); 20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_iomap; 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* print info about board and interface just registered */ 2081163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netdev_info(dev, "%s at 0x%lx, %pM, IRQ %d\n", 2082163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches de->de21040 ? "21040" : "21041", 2083163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches dev->base_addr, 2084163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches dev->dev_addr, 2085163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches dev->irq); 20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_drvdata(pdev, dev); 20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* enable busmastering */ 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_master(pdev); 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* put adapter to sleep */ 20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_adapter_sleep(de); 20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_iomap: 2098b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl kfree(de->ee_data); 20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(regs); 21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_res: 21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_release_regions(pdev); 21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_disable: 21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_disable_device(pdev); 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free: 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21094a1d2d81fa327d095a0a8a1f961bace5b0a2f7daHelge Dellerstatic void __devexit de_remove_one (struct pci_dev *pdev) 21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = pci_get_drvdata(pdev); 21128f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21147e0b58f32fb5e9c958078a6d722a7d0b230346a7Eric Sesterhenn / snakebyte BUG_ON(!dev); 21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_netdev(dev); 2116b4558ea93d66a43f7990d26f145fd4c54a01c9bfJesper Juhl kfree(de->ee_data); 21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds iounmap(de->regs); 21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_release_regions(pdev); 21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_disable_device(pdev); 21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_drvdata(pdev, NULL); 21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 212605adc3b7458e97a1d0180828000207a403083389Pavel Machekstatic int de_suspend (struct pci_dev *pdev, pm_message_t state) 21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = pci_get_drvdata (pdev); 21298f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rtnl_lock(); 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_running (dev)) { 21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds del_timer_sync(&de->media_timer); 21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disable_irq(dev->irq); 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(&de->lock); 21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_stop_hw(de); 21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_device_detach(dev); 21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_carrier_off(dev); 21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(&de->lock); 21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enable_irq(dev->irq); 2145f3b197ac26ed0e57989856494c495818dcc7f9acJeff Garzik 21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Update the error counts. */ 21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __de_get_stats(de); 21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds synchronize_irq(dev->irq); 21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_clean_rings(de); 21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds de_adapter_sleep(de); 21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_disable_device(pdev); 21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_device_detach(dev); 21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rtnl_unlock(); 21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int de_resume (struct pci_dev *pdev) 21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = pci_get_drvdata (pdev); 21648f15ea42b64941001a401cf855a0869e24f3a845Wang Chen struct de_private *de = netdev_priv(dev); 21659f486ae1d9ea700a952b77a8881de05ebc1610c3Valerie Henson int retval = 0; 21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rtnl_lock(); 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_device_present(dev)) 21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 21709f486ae1d9ea700a952b77a8881de05ebc1610c3Valerie Henson if (!netif_running(dev)) 21719f486ae1d9ea700a952b77a8881de05ebc1610c3Valerie Henson goto out_attach; 21729f486ae1d9ea700a952b77a8881de05ebc1610c3Valerie Henson if ((retval = pci_enable_device(pdev))) { 2173163ef0b5922b14751e93218bdf2c9fe8f74b9c9dJoe Perches netdev_err(dev, "pci_enable_device failed in resume\n"); 21749f486ae1d9ea700a952b77a8881de05ebc1610c3Valerie Henson goto out; 21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2176b0255a02351b00ca55f4eb2588d05a5db9dd1a58Ondrej Zary pci_set_master(pdev); 2177b0255a02351b00ca55f4eb2588d05a5db9dd1a58Ondrej Zary de_init_rings(de); 21789f486ae1d9ea700a952b77a8881de05ebc1610c3Valerie Henson de_init_hw(de); 21799f486ae1d9ea700a952b77a8881de05ebc1610c3Valerie Hensonout_attach: 21809f486ae1d9ea700a952b77a8881de05ebc1610c3Valerie Henson netif_device_attach(dev); 21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rtnl_unlock(); 21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PM */ 21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver de_driver = { 21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = DRV_NAME, 21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = de_pci_tbl, 21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = de_init_one, 21924a1d2d81fa327d095a0a8a1f961bace5b0a2f7daHelge Deller .remove = __devexit_p(de_remove_one), 21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = de_suspend, 21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = de_resume, 21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init de_init (void) 22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 22021c3319fb69c29376fe23c1aa0cd7cb6df91c7883Joe Perches pr_info("%s\n", version); 22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2204299176206b266f204be859adf9e66efd06628ab2Jeff Garzik return pci_register_driver(&de_driver); 22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit de_exit (void) 22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unregister_driver (&de_driver); 22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(de_init); 22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(de_exit); 2214