Commit f9ff0abb authored by Jeff Garzik's avatar Jeff Garzik

Merge mandrakesoft.com:/home/jgarzik/vanilla/linus-2.5

into mandrakesoft.com:/home/jgarzik/repo/net-drivers-2.5
parents 8cceac24 4008bc66
D-Link DL2000-based Gigabit Ethernet Adapter Installation
for Linux
Jan 02, 2002
Jan 29, 2002
Contents
========
......@@ -199,8 +199,8 @@ media=media_type - Specifies the media type the NIC operates at.
6 1000Mbps full duplex.
By default, the NIC operates at autosense.
Note that only 1000mbps_fd and 1000mbps_hd
types are available for fiber adapter.
1000mbps_fd and 1000mbps_hd types are only
available for fiber adapter.
vlan=[0|1] - Specifies the VLAN ID. If vlan=0, the
Virtual Local Area Network (VLAN) function is
......
......@@ -65,7 +65,10 @@
#include <linux/mm.h>
#include <linux/highmem.h>
#include <linux/sockios.h>
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#include <linux/if_vlan.h>
#endif
#ifdef SIOCETHTOOL
#include <linux/ethtool.h>
......@@ -320,9 +323,11 @@ static inline void tasklet_init(struct tasklet_struct *tasklet,
#if (defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)) && \
defined(NETIF_F_HW_VLAN_RX)
#define ACENIC_DO_VLAN 1
#define ACENIC_DO_VLAN 1
#define ACE_RCB_VLAN_FLAG RCB_FLG_VLAN_ASSIST
#else
#define ACENIC_DO_VLAN 0
#define ACENIC_DO_VLAN 0
#define ACE_RCB_VLAN_FLAG 0
#endif
#include "acenic.h"
......@@ -563,7 +568,7 @@ static int tx_ratio[ACE_MAX_MOD_PARMS];
static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
static char version[] __initdata =
"acenic.c: v0.88 03/14/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n"
"acenic.c: v0.89 03/15/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n"
" http://home.cern.ch/~jes/gige/acenic.html\n";
static struct net_device *root_dev;
......@@ -1461,10 +1466,8 @@ static int __init ace_init(struct net_device *dev)
set_aceaddr(&info->rx_std_ctrl.rngptr, ap->rx_ring_base_dma);
info->rx_std_ctrl.max_len = ACE_STD_MTU + ETH_HLEN + 4;
info->rx_std_ctrl.flags = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
#if ACENIC_DO_VLAN
info->rx_std_ctrl.flags |= RCB_FLG_VLAN_ASSIST;
#endif
info->rx_std_ctrl.flags =
RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
memset(ap->rx_std_ring, 0,
RX_STD_RING_ENTRIES * sizeof(struct rx_desc));
......@@ -1479,10 +1482,8 @@ static int __init ace_init(struct net_device *dev)
(ap->rx_ring_base_dma +
(sizeof(struct rx_desc) * RX_STD_RING_ENTRIES)));
info->rx_jumbo_ctrl.max_len = 0;
info->rx_jumbo_ctrl.flags = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
#if ACENIC_DO_VLAN
info->rx_jumbo_ctrl.flags |= RCB_FLG_VLAN_ASSIST;
#endif
info->rx_jumbo_ctrl.flags =
RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
memset(ap->rx_jumbo_ring, 0,
RX_JUMBO_RING_ENTRIES * sizeof(struct rx_desc));
......@@ -1504,10 +1505,7 @@ static int __init ace_init(struct net_device *dev)
RX_JUMBO_RING_ENTRIES))));
info->rx_mini_ctrl.max_len = ACE_MINI_SIZE;
info->rx_mini_ctrl.flags =
RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
#if ACENIC_DO_VLAN
info->rx_mini_ctrl.flags |= RCB_FLG_VLAN_ASSIST;
#endif
RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR|ACE_RCB_VLAN_FLAG;
for (i = 0; i < RX_MINI_RING_ENTRIES; i++)
ap->rx_mini_ring[i].flags =
......@@ -1554,7 +1552,7 @@ static int __init ace_init(struct net_device *dev)
}
info->tx_ctrl.max_len = ACE_TX_RING_ENTRIES(ap);
tmp = RCB_FLG_TCP_UDP_SUM|RCB_FLG_NO_PSEUDO_HDR;
tmp = RCB_FLG_TCP_UDP_SUM | RCB_FLG_NO_PSEUDO_HDR | ACE_RCB_VLAN_FLAG;
/*
* The Tigon I does not like having the TX ring in host memory ;-(
......@@ -1563,9 +1561,6 @@ static int __init ace_init(struct net_device *dev)
tmp |= RCB_FLG_TX_HOST_RING;
#if TX_COAL_INTS_ONLY
tmp |= RCB_FLG_COAL_INT_ONLY;
#endif
#if ACENIC_DO_VLAN
tmp |= RCB_FLG_VLAN_ASSIST;
#endif
info->tx_ctrl.flags = tmp;
......@@ -1592,7 +1587,7 @@ static int __init ace_init(struct net_device *dev)
ace_set_rxtx_parms(dev, 0);
if (board_idx == BOARD_IDX_OVERFLOW) {
printk(KERN_WARNING "%s: more then %i NICs detected, "
printk(KERN_WARNING "%s: more than %i NICs detected, "
"ignoring module parameters!\n",
dev->name, ACE_MAX_MOD_PARMS);
} else if (board_idx >= 0) {
......@@ -2181,14 +2176,6 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd)
}
#if ACENIC_DO_VLAN
static int ace_vlan_rx(struct ace_private *ap, struct sk_buff *skb, u16 vlan_tag)
{
return vlan_hwaccel_rx(skb, ap->vlgrp, vlan_tag);
}
#endif
static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
{
struct ace_private *ap = dev->priv;
......@@ -2274,11 +2261,9 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
}
/* send it up */
#if ACENIC_DO_VLAN
if (ap->vlgrp != NULL &&
(bd_flags & BD_FLG_VLAN_TAG)) {
ace_vlan_rx(ap, skb, retdesc->vlan);
if (ap->vlgrp && (bd_flags & BD_FLG_VLAN_TAG)) {
vlan_hwaccel_rx(skb, ap->vlgrp, retdesc->vlan);
} else
#endif
netif_rx(skb);
......
......@@ -642,10 +642,6 @@ struct ace_private
struct ace_skb *skb;
dma_addr_t info_dma; /* 32/64 bit */
#if ACENIC_DO_VLAN
struct vlan_group *vlgrp;
#endif
int version, link;
int promisc, mcast_all;
......@@ -655,7 +651,6 @@ struct ace_private
struct tx_desc *tx_ring;
u32 tx_prd;
volatile u32 tx_ret_csm;
struct timer_list timer;
int tx_ring_entries;
/*
......@@ -675,6 +670,10 @@ struct ace_private
struct rx_desc *rx_mini_ring;
struct rx_desc *rx_return_ring;
#if ACENIC_DO_VLAN
struct vlan_group *vlgrp;
#endif
int tasklet_pending, jumbo;
struct tasklet_struct ace_tasklet;
......
......@@ -449,11 +449,17 @@ static int de620_open(struct net_device *dev)
return ret;
}
if (adapter_init(dev))
return -EIO;
if (adapter_init(dev)) {
ret = -EIO;
goto out_free_irq;
}
netif_start_queue(dev);
return 0;
out_free_irq:
free_irq(dev->irq, dev);
return ret;
}
/************************************************
......@@ -850,7 +856,10 @@ int __init de620_probe(struct net_device *dev)
return -EBUSY;
}
#endif
request_region(dev->base_addr, 3, "de620");
if (!request_region(dev->base_addr, 3, "de620")) {
printk(KERN_ERR "io 0x%3lX, which is busy.\n", dev->base_addr);
return -EBUSY;
}
/* else, got it! */
printk(", Ethernet Address: %2.2X",
......
/* D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */
/*
Copyright (c) 2001 by D-Link Corporation
Copyright (c) 2001,2002 by D-Link Corporation
Written by Edward Peng.<edward_peng@dlink.com.tw>
Created 03-May-2001, base on Linux' sundance.c.
......@@ -27,12 +27,14 @@
Added tx_coalesce paramter.
1.07 2002/01/03 Fixed miscount of RX frame error.
1.08 2002/01/17 Fixed the multicast bug.
1.09 2002/03/07 Move rx-poll-now to re-fill loop.
Added rio_timer() to watch rx buffers.
*/
#include "dl2k.h"
static char version[] __devinitdata =
KERN_INFO "D-Link DL2000-based linux driver v1.08 2002/01/17\n";
KERN_INFO "D-Link DL2000-based linux driver v1.09 2002/03/07\n";
#define MAX_UNITS 8
static int mtu[MAX_UNITS];
......@@ -42,9 +44,10 @@ static char *media[MAX_UNITS];
static int tx_flow[MAX_UNITS];
static int rx_flow[MAX_UNITS];
static int copy_thresh;
static int rx_coalesce = DEFAULT_RXC;
static int rx_timeout = DEFAULT_RXT;
static int tx_coalesce = DEFAULT_TXC;
static int rx_coalesce; /* Rx frame count each interrupt */
static int rx_timeout; /* Rx DMA wait time in 64ns increments */
static int tx_coalesce = DEFAULT_TXC; /* HW xmit count each TxComplete [1-8] */
MODULE_AUTHOR ("Edward Peng");
MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
......@@ -71,6 +74,7 @@ static int max_intrloop = 50;
static int multicast_filter_limit = 0x40;
static int rio_open (struct net_device *dev);
static void rio_timer (unsigned long data);
static void tx_timeout (struct net_device *dev);
static void alloc_list (struct net_device *dev);
static int start_xmit (struct sk_buff *skb, struct net_device *dev);
......@@ -146,6 +150,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
np->chip_id = chip_idx;
np->pdev = pdev;
spin_lock_init (&np->lock);
spin_lock_init (&np->rx_lock);
/* Parse manual configuration */
np->an_enable = 1;
......@@ -260,6 +265,7 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
np->an_enable = 1;
mii_set_media (dev);
}
pci_read_config_byte(pdev, PCI_REVISION_ID, &np->pci_rev_id);
/* Reset all logic functions */
writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
......@@ -340,7 +346,7 @@ parse_eeprom (struct net_device *dev)
}
/* Check CRC */
crc = ~ether_crc_le(256 - 4, sromdata);
crc = ~ether_crc_le(256 - 4, sromdata);
if (psrom->crc != crc) {
printk (KERN_ERR "%s: EEPROM data CRC error.\n", dev->name);
return -1;
......@@ -421,8 +427,10 @@ rio_open (struct net_device *dev)
ioaddr + RxDMAIntCtrl);
}
/* Set RIO to poll every N*320nsec. */
writeb (0xff, ioaddr + RxDMAPollPeriod);
writeb (0x20, ioaddr + RxDMAPollPeriod);
writeb (0xff, ioaddr + TxDMAPollPeriod);
writeb (0x30, ioaddr + RxDMABurstThresh);
writeb (0x30, ioaddr + RxDMAUrgentThresh);
netif_start_queue (dev);
writel (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl);
/* VLAN supported */
......@@ -445,9 +453,59 @@ rio_open (struct net_device *dev)
/* clear statistics */
get_stats (dev);
init_timer (&np->timer);
np->timer.expires = jiffies + 1*HZ;
np->timer.data = (unsigned long) dev;
np->timer.function = &rio_timer;
add_timer (&np->timer);
return 0;
}
static void
rio_timer (unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct netdev_private *np = dev->priv;
unsigned int entry;
int next_tick = 1*HZ;
unsigned long flags;
/* Recover rx ring exhausted error */
if (np->cur_rx - np->old_rx >= RX_RING_SIZE) {
printk(KERN_INFO "Try to recover rx ring exhausted...\n");
spin_lock_irqsave(&np->rx_lock, flags);
/* Re-allocate skbuffs to fill the descriptor ring */
for (; np->cur_rx - np->old_rx > 0; np->old_rx++) {
struct sk_buff *skb;
entry = np->old_rx % RX_RING_SIZE;
/* Dropped packets don't need to re-allocate */
if (np->rx_skbuff[entry] == NULL) {
skb = dev_alloc_skb (np->rx_buf_sz);
if (skb == NULL) {
np->rx_ring[entry].fraginfo = 0;
printk (KERN_INFO
"%s: Still unable to re-allocate Rx skbuff.#%d\n",
dev->name, entry);
break;
}
np->rx_skbuff[entry] = skb;
skb->dev = dev;
/* 16 byte align the IP header */
skb_reserve (skb, 2);
np->rx_ring[entry].fraginfo =
cpu_to_le64 (pci_map_single
(np->pdev, skb->tail, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
}
np->rx_ring[entry].fraginfo |=
cpu_to_le64 (np->rx_buf_sz) << 48;
np->rx_ring[entry].status = 0;
} /* end for */
spin_unlock_irqrestore (&np->rx_lock, flags);
} /* end if */
np->timer.expires = jiffies + next_tick;
add_timer(&np->timer);
}
static void
tx_timeout (struct net_device *dev)
{
......@@ -499,16 +557,14 @@ alloc_list (struct net_device *dev)
np->tx_ring[i].status = cpu_to_le64 (TFDDone);
np->tx_ring[i].next_desc = cpu_to_le64 (np->tx_ring_dma +
((i+1)%TX_RING_SIZE) *
sizeof (struct
netdev_desc));
sizeof (struct netdev_desc));
}
/* Initialize Rx descriptors */
for (i = 0; i < RX_RING_SIZE; i++) {
np->rx_ring[i].next_desc = cpu_to_le64 (np->rx_ring_dma +
((i + 1) % RX_RING_SIZE) *
sizeof (struct
netdev_desc));
sizeof (struct netdev_desc));
np->rx_ring[i].status = 0;
np->rx_ring[i].fraginfo = 0;
np->rx_skbuff[i] = 0;
......@@ -529,8 +585,8 @@ alloc_list (struct net_device *dev)
skb_reserve (skb, 2); /* 16 byte align the IP header. */
/* Rubicon now supports 40 bits of addressing space. */
np->rx_ring[i].fraginfo =
cpu_to_le64 (pci_map_single
(np->pdev, skb->tail, np->rx_buf_sz,
cpu_to_le64 ( pci_map_single (
np->pdev, skb->tail, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
np->rx_ring[i].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48;
}
......@@ -773,6 +829,8 @@ receive_packet (struct net_device *dev)
int entry = np->cur_rx % RX_RING_SIZE;
int cnt = np->old_rx + RX_RING_SIZE - np->cur_rx;
int rx_shift;
spin_lock (&np->rx_lock);
if (np->old_rx > RX_RING_SIZE) {
rx_shift = RX_RING_SIZE;
np->old_rx -= rx_shift;
......@@ -828,12 +886,14 @@ receive_packet (struct net_device *dev)
skb_put (skb, pkt_len);
}
skb->protocol = eth_type_trans (skb, dev);
#if 0
#if 0
/* Checksum done by hw, but csum value unavailable. */
if (!(frame_status & (TCPError | UDPError | IPError))) {
if (np->pci_rev_id >= 0x0c &&
!(frame_status & (TCPError | UDPError | IPError))) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
}
#endif
netif_rx (skb);
dev->last_rx = jiffies;
}
......@@ -849,9 +909,10 @@ receive_packet (struct net_device *dev)
skb = dev_alloc_skb (np->rx_buf_sz);
if (skb == NULL) {
np->rx_ring[entry].fraginfo = 0;
printk (KERN_ERR
"%s: Allocate Rx buffer error!",
dev->name);
printk (KERN_INFO
"%s: receive_packet: "
"Unable to re-allocate Rx skbuff.#%d\n",
dev->name, entry);
break;
}
np->rx_skbuff[entry] = skb;
......@@ -866,13 +927,12 @@ receive_packet (struct net_device *dev)
np->rx_ring[entry].fraginfo |=
cpu_to_le64 (np->rx_buf_sz) << 48;
np->rx_ring[entry].status = 0;
/* RxDMAPollNow */
writel (readl (dev->base_addr + DMACtrl) | 0x00000010,
dev->base_addr + DMACtrl);
}
/* RxDMAPollNow */
writel (readl (dev->base_addr + DMACtrl) | 0x00000010,
dev->base_addr + DMACtrl);
DEBUG_RFD_DUMP (np, 2);
spin_unlock(&np->rx_lock);
return 0;
}
......@@ -1006,7 +1066,7 @@ set_multicast (struct net_device *dev)
hash_table[0] = hash_table[1] = 0;
/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
hash_table[1] |= 0x02000000;
hash_table[1] |= cpu_to_le32(0x02000000);
if (dev->flags & IFF_PROMISC) {
/* Receive all frames promiscuously. */
rx_mode = ReceiveAllFrames;
......@@ -1020,11 +1080,16 @@ set_multicast (struct net_device *dev)
rx_mode =
ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;
for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist=mclist->next) {
i++, mclist=mclist->next) {
crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr);
for (index=0, bit=0; bit<6; bit++, crc<<=1) {
if (crc & 0x80000000) index |= 1 << bit;
}
/* The inverted high significant 6 bits of CRC are
used as an index to hashtable */
for (index = 0, bit = 0; bit < 6; bit++)
if (test_bit(31 - bit, &crc))
set_bit(bit, &index);
hash_table[index / 32] |= (1 << (index % 32));
}
} else {
......@@ -1094,6 +1159,7 @@ rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
np->old_rx);
break;
case SIOCDEVPRIVATE + 8:
printk("TX ring:\n");
for (i = 0; i < TX_RING_SIZE; i++) {
desc = &np->tx_ring[i];
printk
......@@ -1629,7 +1695,8 @@ rio_close (struct net_device *dev)
writel (TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl);
synchronize_irq ();
free_irq (dev->irq, dev);
del_timer_sync (&np->timer);
/* Free all the skbuffs in the queue. */
for (i = 0; i < RX_RING_SIZE; i++) {
np->rx_ring[i].status = 0;
......@@ -1679,10 +1746,10 @@ rio_remove1 (struct pci_dev *pdev)
}
static struct pci_driver rio_driver = {
name:"dl2k",
id_table:rio_pci_tbl,
probe:rio_probe1,
remove: __devexit_p(rio_remove1),
name: "dl2k",
id_table: rio_pci_tbl,
probe: rio_probe1,
remove: __devexit_p(rio_remove1),
};
static int __init
......
/* D-Link DL2000-based Gigabit Ethernet Adapter Linux driver */
/*
Copyright (c) 2001 by D-Link Corporation
Copyright (c) 2001, 2002 by D-Link Corporation
Written by Edward Peng.<edward_peng@dlink.com.tw>
Created 03-May-2001, base on Linux' sundance.c.
......@@ -649,6 +649,7 @@ struct netdev_private {
dma_addr_t rx_ring_dma;
struct pci_dev *pdev;
spinlock_t lock;
spinlock_t rx_lock;
struct net_device_stats stats;
unsigned int rx_buf_sz; /* Based on MTU+slack. */
unsigned int speed; /* Operating speed */
......@@ -664,9 +665,11 @@ struct netdev_private {
unsigned int tx_flow:1; /* Tx flow control enable */
unsigned int rx_flow:1; /* Rx flow control enable */
unsigned int phy_media:1; /* 1: fiber, 0: copper */
unsigned char pci_rev_id; /* PCI revision ID */
struct netdev_desc *last_tx; /* Last Tx descriptor used. */
unsigned long cur_rx, old_rx; /* Producer/consumer ring indices */
unsigned long cur_tx, old_tx;
struct timer_list timer;
int wake_polarity;
char name[256]; /* net device description */
u8 duplex_polarity;
......
......@@ -10,7 +10,7 @@
O_TARGET := e100.o
obj-y := e100_main.o e100_config.o e100_proc.o e100_phy.o \
e100_eeprom.o
e100_eeprom.o e100_test.o
obj-m := $(O_TARGET)
include $(TOPDIR)/Rules.make
......@@ -899,6 +899,15 @@ struct cfg_params {
int PollingMaxWork;
u32 b_params;
};
#ifdef ETHTOOL_TEST
struct ethtool_lpbk_data{
dma_addr_t dma_handle;
tcb_t *tcb;
rfd_t *rfd;
};
#endif
struct e100_private {
u32 flags; /* board management flags */
......@@ -988,6 +997,9 @@ struct e100_private {
u32 wolopts;
u16 ip_lbytes;
#endif
#ifdef ETHTOOL_TEST
struct ethtool_lpbk_data loopback;
#endif
#ifdef CONFIG_PM
u32 pci_state[16];
......@@ -1028,4 +1040,23 @@ extern void e100_deisolate_driver(struct e100_private *bdp,
extern unsigned char e100_hw_reset_recover(struct e100_private *bdp,
u32 reset_cmd);
#ifdef ETHTOOL_TEST
#define ROM_TEST_FAIL 0x01
#define REGISTER_TEST_FAIL 0x02
#define SELF_TEST_FAIL 0x04
#define TEST_TIMEOUT 0x08
enum test_offsets {
E100_EEPROM_TEST_FAIL = 0,
E100_CHIP_TIMEOUT,
E100_ROM_TEST_FAIL,
E100_REG_TEST_FAIL,
E100_MAC_TEST_FAIL,
E100_LPBK_MAC_FAIL,
E100_LPBK_PHY_FAIL,
E100_MAX_TEST_RES
};
#endif
#endif
......@@ -593,3 +593,102 @@ e100_config_wol(struct e100_private *bdp)
}
#endif
#ifdef ETHTOOL_TEST
/**
* e100_config_loopback_mode
* @bdp: atapter's private data struct
* @mode: loopback mode(phy/mac/none)
*
*/
unsigned char
e100_config_loopback_mode(struct e100_private *bdp, u8 mode)
{
unsigned char bc_changed = false;
u8 config_byte;
spin_lock_bh(&(bdp->config_lock));
switch (mode) {
case NO_LOOPBACK:
config_byte = CB_CFIG_LOOPBACK_NORMAL;
break;
case MAC_LOOPBACK:
config_byte = CB_CFIG_LOOPBACK_INTERNAL;
break;
case PHY_LOOPBACK:
config_byte = CB_CFIG_LOOPBACK_EXTERNAL;
break;
default:
printk(KERN_NOTICE "e100_config_loopback_mode: "
"Invalid argument 'mode': %d\n", mode);
goto exit;
}
if ((bdp->config[10] & CB_CFIG_LOOPBACK_MODE) != config_byte) {
bdp->config[10] &= (~CB_CFIG_LOOPBACK_MODE);
bdp->config[10] |= config_byte;
E100_CONFIG(bdp, 10);
bc_changed = true;
}
exit:
spin_unlock_bh(&(bdp->config_lock));
return bc_changed;
}
unsigned char
e100_config_tcb_ext_enable(struct e100_private *bdp, unsigned char enable)
{
unsigned char bc_changed = false;
spin_lock_bh(&(bdp->config_lock));
if (enable) {
if (bdp->config[6] & CB_CFIG_EXT_TCB_DIS) {
bdp->config[6] &= (~CB_CFIG_EXT_TCB_DIS);
E100_CONFIG(bdp, 6);
bc_changed = true;
}
} else {
if (!(bdp->config[6] & CB_CFIG_EXT_TCB_DIS)) {
bdp->config[6] |= CB_CFIG_EXT_TCB_DIS;
E100_CONFIG(bdp, 6);
bc_changed = true;
}
}
spin_unlock_bh(&(bdp->config_lock));
return bc_changed;
}
unsigned char
e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable)
{
unsigned char bc_changed = false;
spin_lock_bh(&(bdp->config_lock));
if (enable) {
if (!(bdp->config[7] & CB_CFIG_DYNTBD_EN)) {
bdp->config[7] |= CB_CFIG_DYNTBD_EN;
E100_CONFIG(bdp, 7);
bc_changed = true;
}
} else {
if (bdp->config[7] & CB_CFIG_DYNTBD_EN) {
bdp->config[7] &= (~CB_CFIG_DYNTBD_EN);
E100_CONFIG(bdp, 7);
bc_changed = true;
}
}
spin_unlock_bh(&(bdp->config_lock));
return bc_changed;
}
#endif
......@@ -190,6 +190,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define CB_CFIG_LONG_RX_OK BIT_3
#define NO_LOOPBACK 0
#define MAC_LOOPBACK 0x01
#define PHY_LOOPBACK 0x02
/* function prototypes */
extern void e100_config_init(struct e100_private *bdp);
extern unsigned char e100_force_config(struct e100_private *bdp);
......@@ -201,5 +205,8 @@ extern void e100_config_mulcast_enbl(struct e100_private *bdp,
unsigned char enable);
extern void e100_config_ifs(struct e100_private *bdp);
extern void e100_config_force_dplx(struct e100_private *bdp);
extern u8 e100_config_loopback_mode(struct e100_private *bdp, u8 mode);
extern u8 e100_config_dynamic_tbd(struct e100_private *bdp, u8 enable);
extern u8 e100_config_tcb_ext_enable(struct e100_private *bdp, u8 enable);
#endif /* _E100_CONFIG_INC_ */
......@@ -146,6 +146,23 @@ static unsigned char e100_setup_filter(struct e100_private *bdp);
static void e100_do_wol(struct pci_dev *pcid, struct e100_private *bdp);
static u16 e100_get_ip_lbytes(struct net_device *dev);
extern void e100_config_wol(struct e100_private *bdp);
#endif
#ifdef ETHTOOL_TEST
extern u32 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags);
static int e100_ethtool_test(struct net_device *, struct ifreq *);
#endif
#ifdef ETHTOOL_GSTRINGS
static int e100_ethtool_gstrings(struct net_device *, struct ifreq *);
static char *test_strings[] = {
"E100_EEPROM_TEST_FAIL",
"E100_CHIP_TIMEOUT",
"E100_ROM_TEST_FAIL",
"E100_REG_TEST_FAIL",
"E100_MAC_TEST_FAIL",
"E100_LPBK_MAC_FAIL",
"E100_LPBK_PHY_FAIL"
};
#endif
#endif /*E100_ETHTOOL_IOCTL */
......@@ -165,7 +182,7 @@ static void e100_non_tx_background(unsigned long);
/* Global Data structures and variables */
char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation";
#define E100_VERSION "2.0.24-pre1"
#define E100_VERSION "2.0.25-pre1"
#define E100_FULL_DRIVER_NAME "Intel(R) PRO/100 Fast Ethernet Adapter - Loadable driver, ver "
......@@ -382,6 +399,7 @@ static void e100_set_multi_exec(struct net_device *dev);
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION(E100_FULL_DRIVER_NAME E100_VERSION);
MODULE_LICENSE("Dual BSD/GPL");
EXPORT_NO_SYMBOLS;
E100_PARAM(TxDescriptors, "Number of transmit descriptors");
E100_PARAM(RxDescriptors, "Number of receive descriptors");
......@@ -2715,8 +2733,10 @@ e100_exec_non_cu_cmd(struct e100_private *bdp, nxmit_cb_entry_t *command)
ntcb_hdr->cb_lnk_ptr = 0;
wmb();
if (in_interrupt())
return e100_delayed_exec_non_cu_cmd(bdp, command);
if (in_interrupt() || netif_running(bdp->device))
if (netif_running(bdp->device) && (!bdp->driver_isolated))
return e100_delayed_exec_non_cu_cmd(bdp, command);
spin_lock_bh(&(bdp->bd_non_tx_lock));
......@@ -3301,6 +3321,16 @@ e100_do_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
case ETHTOOL_SWOL:
rc = e100_ethtool_wol(dev, ifr);
break;
#endif
#ifdef ETHTOOL_TEST
case ETHTOOL_TEST:
rc = e100_ethtool_test(dev, ifr);
break;
#endif
#ifdef ETHTOOL_GSTRINGS
case ETHTOOL_GSTRINGS:
rc = e100_ethtool_gstrings(dev,ifr);
break;
#endif
default:
break;
......@@ -3464,6 +3494,36 @@ e100_ethtool_glink(struct net_device *dev, struct ifreq *ifr)
}
#endif
#ifdef ETHTOOL_TEST
static int
e100_ethtool_test(struct net_device *dev, struct ifreq *ifr)
{
struct ethtool_test *info;
int rc = -EFAULT;
info = kmalloc(sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64),
GFP_ATOMIC);
if (!info)
return -EFAULT;
memset((void *) info, 0, sizeof(*info) +
E100_MAX_TEST_RES * sizeof(u64));
if (copy_from_user(info, ifr->ifr_data, sizeof(*info)))
goto exit;
info->flags = e100_run_diag(dev, info->data, info->flags);
if (!copy_to_user(ifr->ifr_data, info,
sizeof(*info) + E100_MAX_TEST_RES * sizeof(u64)))
rc = 0;
exit:
kfree(info);
return rc;
}
#endif
#ifdef ETHTOOL_NWAY_RST
static int
e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr)
......@@ -3505,7 +3565,9 @@ e100_ethtool_get_drvinfo(struct net_device *dev, struct ifreq *ifr)
#ifdef ETHTOOL_GEEPROM
info.eedump_len = (bdp->eeprom_size << 1);
#endif
#ifdef ETHTOOL_TEST
info.testinfo_len = E100_MAX_TEST_RES;
#endif
if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
return -EFAULT;
......@@ -3737,6 +3799,51 @@ e100_ethtool_wol(struct net_device *dev, struct ifreq *ifr)
return res;
}
#endif
#ifdef ETHTOOL_GSTRINGS
static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr)
{
struct ethtool_gstrings info;
char *strings = NULL;
char *usr_strings;
int i;
memset((void *) &info, 0, sizeof(info));
usr_strings = (u8 *) (ifr->ifr_data +
offsetof(struct ethtool_gstrings, data));
if (copy_from_user(&info, ifr->ifr_data, sizeof (info)))
return -EFAULT;
switch (info.string_set) {
case ETH_SS_TEST:
if (info.len > E100_MAX_TEST_RES)
info.len = E100_MAX_TEST_RES;
strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC);
if (!strings)
return -EFAULT;
memset(strings, 0, info.len * ETH_GSTRING_LEN);
for (i = 0; i < info.len; i++) {
sprintf(strings + i * ETH_GSTRING_LEN, "%-31s",
test_strings[i]);
}
break;
default:
return -EOPNOTSUPP;
}
if (copy_to_user(ifr->ifr_data, &info, sizeof (info)))
return -EFAULT;
if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN))
return -EFAULT;
kfree(strings);
return 0;
}
#endif
#endif /*E100_ETHTOOL_IOCTL */
......
/*******************************************************************************
This software program is available to you under a choice of one of two
licenses. You may choose to be licensed under either the GNU General Public
License 2.0, June 1991, available at http://www.fsf.org/copyleft/gpl.html,
or the Intel BSD + Patent License, the text of which follows:
Recipient has requested a license and Intel Corporation ("Intel") is willing
to grant a license for the software entitled Linux Base Driver for the
Intel(R) PRO/100 Family of Adapters (e100) (the "Software") being provided
by Intel Corporation. The following definitions apply to this license:
"Licensed Patents" means patent claims licensable by Intel Corporation which
are necessarily infringed by the use of sale of the Software alone or when
combined with the operating system referred to below.
"Recipient" means the party to whom Intel delivers this Software.
"Licensee" means Recipient and those third parties that receive a license to
any operating system available under the GNU General Public License 2.0 or
later.
Copyright (c) 1999 - 2002 Intel Corporation.
All rights reserved.
The license is provided to Recipient and Recipient's Licensees under the
following terms.
Redistribution and use in source and binary forms of the Software, with or
without modification, are permitted provided that the following conditions
are met:
Redistributions of source code of the Software may retain the above
copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form of the Software may reproduce the above
copyright notice, this list of conditions and the following disclaimer in
the documentation and/or materials provided with the distribution.
Neither the name of Intel Corporation nor the names of its contributors
shall be used to endorse or promote products derived from this Software
without specific prior written permission.
Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
royalty-free patent license under Licensed Patents to make, use, sell, offer
to sell, import and otherwise transfer the Software, if any, in source code
and object code form. This license shall include changes to the Software
that are error corrections or other minor changes to the Software that do
not add functionality or features when the Software is incorporated in any
version of an operating system that has been distributed under the GNU
General Public License 2.0 or later. This patent license shall apply to the
combination of the Software and any operating system licensed under the GNU
General Public License 2.0 or later if, at the time Intel provides the
Software to Recipient, such addition of the Software to the then publicly
available versions of such operating systems available under the GNU General
Public License 2.0 or later (whether in gold, beta or alpha form) causes
such combination to be covered by the Licensed Patents. The patent license
shall not apply to any other combinations which include the Software. NO
hardware per se is licensed hereunder.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MECHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR IT CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
ANY LOSS OF USE; DATA, OR PROFITS; OR BUSINESS INTERUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include "e100.h"
#include "e100_config.h"
#ifdef ETHTOOL_TEST
extern u16 e100_eeprom_read(struct e100_private *, u16);
extern int e100_wait_exec_cmplx(struct e100_private *, u32,u8);
extern void e100_phy_reset(struct e100_private *bdp);
static u8 e100_diag_selftest(struct net_device *);
static u8 e100_diag_eeprom(struct net_device *);
static u8 e100_diag_loopback(struct net_device *);
static u8 e100_diag_one_loopback (struct net_device *, u8);
static u8 e100_diag_rcv_loopback_pkt(struct e100_private *);
static void e100_diag_config_loopback(struct e100_private *, u8, u8, u8 *,u8 *);
static u8 e100_diag_loopback_alloc(struct e100_private *);
static void e100_diag_loopback_cu_ru_exec(struct e100_private *);
static u8 e100_diag_check_pkt(u8 *);
static void e100_diag_loopback_free(struct e100_private *);
#define LB_PACKET_SIZE 1500
/**
* e100_run_diag - main test execution handler - checks mask of requests and calls the diag routines
* @dev: atapter's net device data struct
* @test_info: array with test request mask also used to store test results
*
* RETURNS: updated flags field of struct ethtool_test
*/
u32
e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
{
struct e100_private* bdp = dev->priv;
u8 test_result = true;
e100_isolate_driver(bdp);
if (flags & ETH_TEST_FL_OFFLINE) {
u8 fail_mask;
fail_mask = e100_diag_selftest(dev);
if (fail_mask) {
test_result = false;
if (fail_mask & REGISTER_TEST_FAIL)
test_info [E100_REG_TEST_FAIL] = true;
if (fail_mask & ROM_TEST_FAIL)
test_info [E100_ROM_TEST_FAIL] = true;
if (fail_mask & SELF_TEST_FAIL)
test_info [E100_MAC_TEST_FAIL] = true;
if (fail_mask & TEST_TIMEOUT)
test_info [E100_CHIP_TIMEOUT] = true;
}
fail_mask = e100_diag_loopback(dev);
if (fail_mask) {
test_result = false;
if (fail_mask & PHY_LOOPBACK)
test_info [E100_LPBK_PHY_FAIL] = true;
if (fail_mask & MAC_LOOPBACK)
test_info [E100_LPBK_MAC_FAIL] = true;
}
}
if (!e100_diag_eeprom(dev)) {
test_result = false;
test_info [E100_EEPROM_TEST_FAIL] = true;
}
/* fully recover only if the device is open*/
if (netif_running(dev)) {
e100_deisolate_driver(bdp, true, false);
} else {
e100_deisolate_driver(bdp, false, false);
}
/*Let card recover from the test*/
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ * 2);
return flags | (test_result ? 0 : ETH_TEST_FL_FAILED);
}
/**
* e100_diag_selftest - run hardware selftest
* @dev: atapter's net device data struct
*/
static u8
e100_diag_selftest(struct net_device *dev)
{
struct e100_private *bdp = dev->priv;
u32 st_timeout, st_result;
u8 retval = 0;
if (!e100_selftest(bdp, &st_timeout, &st_result)) {
if (!st_timeout) {
if (st_result & CB_SELFTEST_REGISTER_BIT)
retval |= REGISTER_TEST_FAIL;
if (st_result & CB_SELFTEST_DIAG_BIT)
retval |= SELF_TEST_FAIL;
if (st_result & CB_SELFTEST_ROM_BIT)
retval |= ROM_TEST_FAIL;
} else {
retval = TEST_TIMEOUT;
}
}
e100_hw_reset_recover(bdp,PORT_SOFTWARE_RESET);
return retval;
}
/**
* e100_diag_eeprom - validate eeprom checksum correctness
* @dev: atapter's net device data struct
*
*/
static u8
e100_diag_eeprom (struct net_device *dev)
{
struct e100_private *bdp = dev->priv;
u16 i, eeprom_sum, eeprom_actual_csm;
for (i = 0, eeprom_sum = 0; i < (bdp->eeprom_size - 1); i++) {
eeprom_sum += e100_eeprom_read(bdp, i);
}
eeprom_actual_csm = e100_eeprom_read(bdp, bdp->eeprom_size - 1);
if (eeprom_actual_csm == (u16)(EEPROM_SUM - eeprom_sum)) {
return true;
}
return false;
}
/**
* e100_diag_loopback - performs loopback test
* @dev: atapter's net device data struct
*/
static u8
e100_diag_loopback (struct net_device *dev)
{
u8 rc = 0;
if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) {
rc |= PHY_LOOPBACK;
}
if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) {
rc |= MAC_LOOPBACK;
}
return rc;
}
/**
* e100_diag_loopback - performs loopback test
* @dev: atapter's net device data struct
* @mode: lopback test type
*/
static u8
e100_diag_one_loopback (struct net_device *dev, u8 mode)
{
struct e100_private *bdp = dev->priv;
u8 res = false;
u8 saved_dynamic_tbd = false;
u8 saved_extended_tcb = false;
if (!e100_diag_loopback_alloc(bdp))
return false;
/* change the config block to standard tcb and the correct loopback */
e100_diag_config_loopback(bdp, true, mode,
&saved_extended_tcb, &saved_dynamic_tbd);
e100_diag_loopback_cu_ru_exec(bdp);
if (e100_diag_rcv_loopback_pkt(bdp)) {
res = true;
}
e100_diag_loopback_free(bdp);
/* change the config block to previous tcb mode and the no loopback */
e100_diag_config_loopback(bdp, false, mode,
&saved_extended_tcb, &saved_dynamic_tbd);
return res;
}
/**
* e100_diag_config_loopback - setup/clear loopback before/after lpbk test
* @bdp: atapter's private data struct
* @set_loopback: true if the function is called to set lb
* @loopback_mode: the loopback mode(MAC or PHY)
* @tcb_extended: true if need to set extended tcb mode after clean loopback
* @dynamic_tbd: true if needed to set dynamic tbd mode after clean loopback
*
*/
void
e100_diag_config_loopback(struct e100_private* bdp,
u8 set_loopback,
u8 loopback_mode,
u8* tcb_extended,
u8* dynamic_tbd)
{
/* if set_loopback == true - we want to clear tcb_extended/dynamic_tbd.
* the previous values are saved in the params tcb_extended/dynamic_tbd
* if set_loopback == false - we want to restore previous value.
*/
if (set_loopback || (*tcb_extended))
*tcb_extended = e100_config_tcb_ext_enable(bdp,*tcb_extended);
if (set_loopback || (*dynamic_tbd))
*dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd);
if (set_loopback) {
e100_config_loopback_mode(bdp,loopback_mode);
} else {
e100_config_loopback_mode(bdp,NO_LOOPBACK);
}
e100_config(bdp);
if (loopback_mode == PHY_LOOPBACK) {
unsigned long expires = jiffies + HZ * 5;
if (set_loopback)
e100_phy_reset(bdp);
/* wait up to 5 secs for PHY loopback ON/OFF to take effect */
while ((e100_get_link_state(bdp) != set_loopback) &&
time_before(jiffies, expires)) {
yield();
}
} else { /* For MAC loopback wait 500 msec to take effect */
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ / 2);
}
}
/**
* e100_diag_loopback_alloc - alloc & initate tcb and rfd for the loopback
* @bdp: atapter's private data struct
*
*/
static u8
e100_diag_loopback_alloc(struct e100_private *bdp)
{
dma_addr_t dma_handle;
tcb_t *tcb;
rfd_t *rfd;
tbd_t *tbd;
tcb = pci_alloc_consistent(bdp->pdev,
(sizeof (tcb_t) + sizeof (tbd_t) +
LB_PACKET_SIZE),
&dma_handle);
if (tcb == NULL)
return false;
memset(tcb, 0x00, sizeof (tcb_t) + LB_PACKET_SIZE);
tcb->tcb_phys = dma_handle;
tcb->tcb_hdr.cb_status = 0;
tcb->tcb_hdr.cb_cmd =
cpu_to_le16(CB_EL_BIT | CB_TRANSMIT | CB_TX_SF_BIT);
tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(tcb->tcb_phys);
tcb->tcb_tbd_ptr = cpu_to_le32(0xffffffff);
tcb->tcb_cnt = 0;
tcb->tcb_thrshld = bdp->tx_thld;
tcb->tcb_tbd_num = 1;
tcb->tcb_tbd_ptr = cpu_to_le32(tcb->tcb_phys + sizeof (tcb_t));
tbd = (tbd_t *) ((u8 *) tcb + sizeof (tcb_t));
tbd->tbd_buf_addr =
cpu_to_le32(le32_to_cpu(tcb->tcb_tbd_ptr) + sizeof (tbd_t));
tbd->tbd_buf_cnt = __constant_cpu_to_le16(1024);
memset((void *) ((u8 *) tbd + sizeof (tbd_t)), 0xFF, 1024);
memset((void *) ((u8 *) tbd + sizeof (tbd_t) + 512), 0xBA, 512);
wmb();
rfd = pci_alloc_consistent(bdp->pdev, sizeof (rfd_t), &dma_handle);
if (rfd == NULL) {
pci_free_consistent(bdp->pdev,
sizeof (tcb_t) + sizeof (tbd_t) +
LB_PACKET_SIZE, tcb, tcb->tcb_phys);
return false;
}
memset(rfd, 0x00, sizeof (rfd_t));
/* init all fields in rfd */
rfd->rfd_header.cb_status = 0;
rfd->rfd_header.cb_cmd = cpu_to_le16(RFD_EL_BIT);
rfd->rfd_act_cnt = 0;
rfd->rfd_sz = cpu_to_le16(ETH_FRAME_LEN + CHKSUM_SIZE);
bdp->loopback.dma_handle = dma_handle;
bdp->loopback.tcb = tcb;
bdp->loopback.rfd = rfd;
wmb();
return true;
}
/**
* e100_diag_loopback_cu_ru_exec - activates cu and ru to send & receive the pkt
* @bdp: atapter's private data struct
*
*/
static void
e100_diag_loopback_cu_ru_exec(struct e100_private *bdp)
{
/*load CU & RU base */
if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE))
printk("@@@ SCB_CUC_LOAD_BASE failed\n");
if(!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE))
printk("@@@ SCB_RUC_LOAD_BASE failed!\n");
if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START))
printk("@@@ SCB_RUC_START failed!\n");
bdp->next_cu_cmd = START_WAIT;
e100_start_cu(bdp, bdp->loopback.tcb);
bdp->last_tcb = NULL;
rmb();
}
/**
* e100_diag_check_pkt - checks if a given packet is a loopback packet
* @bdp: atapter's private data struct
*
* Returns true if OK false otherwise.
*/
static u8
e100_diag_check_pkt(u8 *datap)
{
if( (*datap)==0xFF) {
if(*(datap + 600) == 0xBA) {
return true;
}
}
return false;
}
/**
* e100_diag_rcv_loopback_pkt - waits for receive and checks lpbk packet
* @bdp: atapter's private data struct
*
* Returns true if OK false otherwise.
*/
static u8
e100_diag_rcv_loopback_pkt(struct e100_private* bdp)
{
rfd_t *rfdp;
u16 rfd_status;
unsigned long expires = jiffies + HZ * 2;
rfdp =bdp->loopback.rfd;
rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
while (!(rfd_status & RFD_STATUS_COMPLETE)) {
if (time_before(jiffies, expires)) {
yield();
rmb();
rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
} else {
break;
}
}
if (rfd_status & RFD_STATUS_COMPLETE)
return e100_diag_check_pkt(((u8 *)rfdp+bdp->rfd_size));
else
return false;
}
/**
* e100_diag_loopback_free - free data allocated for loopback pkt send/receive
* @bdp: atapter's private data struct
*
*/
static void
e100_diag_loopback_free (struct e100_private *bdp)
{
pci_free_consistent(bdp->pdev,
sizeof(tcb_t) + sizeof(tbd_t) + LB_PACKET_SIZE,
bdp->loopback.tcb, bdp->loopback.tcb->tcb_phys);
pci_free_consistent(bdp->pdev, sizeof(rfd_t), bdp->loopback.rfd,
bdp->loopback.dma_handle);
}
#endif
......@@ -60,11 +60,14 @@
LK1.1.12:
* fix power-up sequence
LK1.1.13:
* revert version 1.1.12, power-up sequence "fix"
*/
#define DRV_NAME "epic100"
#define DRV_VERSION "1.11+LK1.1.12"
#define DRV_RELDATE "Jan 18, 2002"
#define DRV_VERSION "1.11+LK1.1.13"
#define DRV_RELDATE "Mar 20, 2002"
/* The user-configurable values.
......@@ -678,8 +681,9 @@ static int epic_open(struct net_device *dev)
required by the details of which bits are reset and the transceiver
wiring on the Ositech CardBus card.
*/
outl(0x12, ioaddr + MIICfg);
#if 0
outl(dev->if_port == 1 ? 0x13 : 0x12, ioaddr + MIICfg);
#endif
if (ep->chip_flags & MII_PWRDWN)
outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
......
......@@ -267,21 +267,28 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
static struct pci_device_id orinoco_plx_pci_id_table[] __devinitdata = {
{0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,},
{0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */
#if 0
{0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga */
#endif
{0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* SMC EZConnect SMC2602W,
Eumitcom PCI WL11000,
Addtron AWA-100*/
{0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* Global Sun Tech GL24110P */
{0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,}, /* Reported working, but unknown */
{0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,}, /* Linksys WDT11 */
{0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,}, /* USR 2415 */
{0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,}, /* Belkin F5D6000 */
{0,},
};
MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table);
static struct pci_driver orinoco_plx_driver = {
name:"orinoco_plx",
id_table:orinoco_plx_pci_id_table,
probe:orinoco_plx_init_one,
remove:__devexit_p(orinoco_plx_remove_one),
suspend:0,
resume:0
name: "orinoco_plx",
id_table: orinoco_plx_pci_id_table,
probe: orinoco_plx_init_one,
remove: __devexit_p(orinoco_plx_remove_one),
};
static int __init orinoco_plx_init(void)
......
......@@ -36,7 +36,8 @@ struct ethtool_drvinfo {
char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */
/* For PCI devices, use pci_dev->slot_name. */
char reserved1[32];
char reserved2[24];
char reserved2[20];
u32 testinfo_len;
u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */
u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */
};
......@@ -210,6 +211,34 @@ struct ethtool_pauseparam {
u32 tx_pause;
};
#define ETH_GSTRING_LEN 32
enum ethtool_stringset {
ETH_SS_TEST = 0,
ETH_SS_STATS,
};
/* for passing string sets for data tagging */
struct ethtool_gstrings {
u32 cmd; /* ETHTOOL_GSTRINGS */
u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/
u32 len; /* number of strings in the string set */
u8 data[0];
};
enum ethtool_test_flags {
ETH_TEST_FL_OFFLINE = (1 << 0), /* online / offline */
ETH_TEST_FL_FAILED = (1 << 1), /* test passed / failed */
};
/* for requesting NIC test and getting results*/
struct ethtool_test {
u32 cmd; /* ETHTOOL_TEST */
u32 flags; /* ETH_TEST_FL_xxx */
u32 reserved;
u32 len; /* result length, in number of u64 elements */
u64 data[0];
};
/* CMDs currently supported */
#define ETHTOOL_GSET 0x00000001 /* Get settings. */
#define ETHTOOL_SSET 0x00000002 /* Set settings, privileged. */
......@@ -222,13 +251,13 @@ struct ethtool_pauseparam {
#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv. */
#define ETHTOOL_GLINK 0x0000000a /* Get link status (ethtool_value) */
#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */
#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */
#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data, priv. */
#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */
#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config */
#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config, priv. */
#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */
#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters */
#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */
#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */
#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters */
#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters, priv. */
#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */
#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */
#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */
......@@ -236,7 +265,9 @@ struct ethtool_pauseparam {
#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable
* (ethtool_value) */
#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable
* (ethtool_value) */
* (ethtool_value), priv. */
#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */
#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */
/* compatibility with older code */
#define SPARC_ETH_GSET ETHTOOL_GSET
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment