the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
-/*
- Rev Date Description
- ==========================================================================
- 0.01 2001/05/03 Created DL2000-based linux driver
- 0.02 2001/05/21 Added VLAN and hardware checksum support.
- 1.00 2001/06/26 Added jumbo frame support.
- 1.01 2001/08/21 Added two parameters, rx_coalesce and rx_timeout.
- 1.02 2001/10/08 Supported fiber media.
- Added flow control parameters.
- 1.03 2001/10/12 Changed the default media to 1000mbps_fd for
- the fiber devices.
- 1.04 2001/11/08 Fixed Tx stopped when tx very busy.
- 1.05 2001/11/22 Fixed Tx stopped when unidirectional tx busy.
- 1.06 2001/12/13 Fixed disconnect bug at 10Mbps mode.
- Fixed tx_full flag incorrect.
- 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.
- 1.10 2002/04/16 Fixed miscount of carrier error.
- 1.11 2002/05/23 Added ISR schedule scheme
- Fixed miscount of rx frame error for DGE-550SX.
- Fixed VLAN bug.
- 1.12 2002/06/13 Lock tx_coalesce=1 on 10/100Mbps mode.
- 1.13 2002/08/13 1. Fix disconnection (many tx:carrier/rx:frame
- errs) with some mainboards.
- 2. Use definition "DRV_NAME" "DRV_VERSION"
- "DRV_RELDATE" for flexibility.
- 1.14 2002/08/14 Support ethtool.
- 1.15 2002/08/27 Changed the default media to Auto-Negotiation
- for the fiber devices.
- 1.16 2002/09/04 More power down time for fiber devices auto-
- negotiation.
- Fix disconnect bug after ifup and ifdown.
- 1.17 2002/10/03 Fix RMON statistics overflow.
- Always use I/O mapping to access eeprom,
- avoid system freezing with some chipsets.
-*/
#define DRV_NAME "D-Link DL2000-based linux driver"
-#define DRV_VERSION "v1.17a"
-#define DRV_RELDATE "2002/10/04"
+#define DRV_VERSION "v1.18"
+#define DRV_RELDATE "2006/06/27"
#include "dl2k.h"
+#include <linux/dma-mapping.h>
static char version[] __devinitdata =
- KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";
+ KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";
#define MAX_UNITS 8
static int mtu[MAX_UNITS];
static int vlan[MAX_UNITS];
MODULE_AUTHOR ("Edward Peng");
MODULE_DESCRIPTION ("D-Link DL2000-based Gigabit Ethernet Adapter");
MODULE_LICENSE("GPL");
-MODULE_PARM (mtu, "1-" __MODULE_STRING (MAX_UNITS) "i");
-MODULE_PARM (media, "1-" __MODULE_STRING (MAX_UNITS) "s");
-MODULE_PARM (vlan, "1-" __MODULE_STRING (MAX_UNITS) "i");
-MODULE_PARM (jumbo, "1-" __MODULE_STRING (MAX_UNITS) "i");
-MODULE_PARM (tx_flow, "i");
-MODULE_PARM (rx_flow, "i");
-MODULE_PARM (copy_thresh, "i");
-MODULE_PARM (rx_coalesce, "i"); /* Rx frame count each interrupt */
-MODULE_PARM (rx_timeout, "i"); /* Rx DMA wait time in 64ns increments */
-MODULE_PARM (tx_coalesce, "i"); /* HW xmit count each TxDMAComplete */
+module_param_array(mtu, int, NULL, 0);
+module_param_array(media, charp, NULL, 0);
+module_param_array(vlan, int, NULL, 0);
+module_param_array(jumbo, int, NULL, 0);
+module_param(tx_flow, int, 0);
+module_param(rx_flow, int, 0);
+module_param(copy_thresh, int, 0);
+module_param(rx_coalesce, int, 0); /* Rx frame count each interrupt */
+module_param(rx_timeout, int, 0); /* Rx DMA wait time in 64ns increments */
+module_param(tx_coalesce, int, 0); /* HW xmit count each TxDMAComplete */
/* Enable the default interrupts */
#define EnableInt() \
writew(DEFAULT_INTR, ioaddr + IntEnable)
-static int max_intrloop = 50;
-static int multicast_filter_limit = 0x40;
+static const int max_intrloop = 50;
+static const int multicast_filter_limit = 0x40;
static int rio_open (struct net_device *dev);
static void rio_timer (unsigned long data);
static void rio_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);
-static irqreturn_t rio_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t rio_interrupt (int irq, void *dev_instance);
static void rio_free_tx (struct net_device *dev, int irq);
static void tx_error (struct net_device *dev, int tx_status);
static int receive_packet (struct net_device *dev);
static void set_multicast (struct net_device *dev);
static struct net_device_stats *get_stats (struct net_device *dev);
static int clear_stats (struct net_device *dev);
-static int rio_ethtool_ioctl (struct net_device *dev, void *useraddr);
static int rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
static int rio_close (struct net_device *dev);
static int find_miiphy (struct net_device *dev);
static int mii_write (struct net_device *dev, int phy_addr, int reg_num,
u16 data);
+static const struct ethtool_ops ethtool_ops;
+
static int __devinit
rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
{
#endif
dev->base_addr = ioaddr;
dev->irq = irq;
- np = dev->priv;
+ np = netdev_priv(dev);
np->chip_id = chip_idx;
np->pdev = pdev;
spin_lock_init (&np->tx_lock);
if (media[card_idx] != NULL) {
np->an_enable = 0;
if (strcmp (media[card_idx], "auto") == 0 ||
- strcmp (media[card_idx], "autosense") == 0 ||
+ strcmp (media[card_idx], "autosense") == 0 ||
strcmp (media[card_idx], "0") == 0 ) {
- np->an_enable = 2;
+ np->an_enable = 2;
} else if (strcmp (media[card_idx], "100mbps_fd") == 0 ||
strcmp (media[card_idx], "4") == 0) {
np->speed = 100;
dev->tx_timeout = &rio_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
dev->change_mtu = &change_mtu;
+ SET_ETHTOOL_OPS(dev, ðtool_ops);
#if 0
dev->features = NETIF_F_IP_CSUM;
#endif
err = find_miiphy (dev);
if (err)
goto err_out_unmap_rx;
-
+
/* Fiber device? */
np->phy_media = (readw(ioaddr + ASICCtrl) & PhyMedia) ? 1 : 0;
np->link_status = 0;
dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], irq);
if (tx_coalesce > 1)
- printk(KERN_INFO "tx_coalesce:\t%d packets\n",
+ printk(KERN_INFO "tx_coalesce:\t%d packets\n",
tx_coalesce);
if (np->coalesce)
printk(KERN_INFO "rx_coalesce:\t%d packets\n"
- KERN_INFO "rx_timeout: \t%d ns\n",
+ KERN_INFO "rx_timeout: \t%d ns\n",
np->rx_coalesce, np->rx_timeout*640);
if (np->vlan)
printk(KERN_INFO "vlan(id):\t%d\n", np->vlan);
int i, phy_found = 0;
struct netdev_private *np;
long ioaddr;
- np = dev->priv;
+ np = netdev_priv(dev);
ioaddr = dev->base_addr;
np->phy_addr = 1;
u8 *psib;
u32 crc;
PSROM_t psrom = (PSROM_t) sromdata;
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
int cid, next;
}
#ifdef MEM_MAPPING
ioaddr = dev->base_addr;
-#endif
+#endif
/* Check CRC */
crc = ~ether_crc_le (256 - 4, sromdata);
if (psrom->crc != crc) {
for (i = 0; i < 6; i++)
dev->dev_addr[i] = psrom->mac_addr[i];
- /* Parse Software Infomation Block */
+ /* Parse Software Information Block */
i = 0x30;
psib = (u8 *) sromdata;
do {
static int
rio_open (struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
long ioaddr = dev->base_addr;
int i;
u16 macctrl;
-
- i = request_irq (dev->irq, &rio_interrupt, SA_SHIRQ, dev->name, dev);
+
+ i = request_irq (dev->irq, &rio_interrupt, IRQF_SHARED, dev->name, dev);
if (i)
return i;
-
+
/* Reset all logic functions */
writew (GlobalReset | DMAReset | FIFOReset | NetworkReset | HostReset,
ioaddr + ASICCtrl + 2);
mdelay(10);
-
+
/* DebugCtrl bit 4, 5, 9 must set */
writel (readl (ioaddr + DebugCtrl) | 0x0230, ioaddr + DebugCtrl);
/* VLAN supported */
if (np->vlan) {
/* priority field in RxDMAIntCtrl */
- writel (readl(ioaddr + RxDMAIntCtrl) | 0x7 << 10,
+ writel (readl(ioaddr + RxDMAIntCtrl) | 0x7 << 10,
ioaddr + RxDMAIntCtrl);
/* VLANId */
writew (np->vlan, ioaddr + VLANId);
add_timer (&np->timer);
/* Start Tx/Rx */
- writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable,
+ writel (readl (ioaddr + MACCtrl) | StatsEnable | RxEnable | TxEnable,
ioaddr + MACCtrl);
-
+
macctrl = 0;
macctrl |= (np->vlan) ? AutoVLANuntagging : 0;
macctrl |= (np->full_duplex) ? DuplexSelect : 0;
writew(macctrl, ioaddr + MACCtrl);
netif_start_queue (dev);
-
+
/* Enable default interrupts */
EnableInt ();
return 0;
}
-static void
+static void
rio_timer (unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
unsigned int entry;
int next_tick = 1*HZ;
unsigned long flags;
skb_reserve (skb, 2);
np->rx_ring[entry].fraginfo =
cpu_to_le64 (pci_map_single
- (np->pdev, skb->tail, np->rx_buf_sz,
+ (np->pdev, skb->data, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
}
np->rx_ring[entry].fraginfo |=
np->timer.expires = jiffies + next_tick;
add_timer(&np->timer);
}
-
+
static void
rio_tx_timeout (struct net_device *dev)
{
static void
alloc_list (struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
int i;
np->cur_rx = np->cur_tx = 0;
/* Initialize Tx descriptors, TFDListPtr leaves in start_xmit(). */
for (i = 0; i < TX_RING_SIZE; i++) {
- np->tx_skbuff[i] = 0;
+ np->tx_skbuff[i] = NULL;
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));
np->rx_ring[i].status = 0;
np->rx_ring[i].fraginfo = 0;
- np->rx_skbuff[i] = 0;
+ np->rx_skbuff[i] = NULL;
}
/* Allocate the rx buffers */
/* 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,
+ np->pdev, skb->data, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
np->rx_ring[i].fraginfo |= cpu_to_le64 (np->rx_buf_sz) << 48;
}
static int
start_xmit (struct sk_buff *skb, struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
struct netdev_desc *txdesc;
unsigned entry;
u32 ioaddr;
txdesc = &np->tx_ring[entry];
#if 0
- if (skb->ip_summed == CHECKSUM_HW) {
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
txdesc->status |=
cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable |
IPChecksumEnable);
* Work around: Always use 1 descriptor in 10Mbps mode */
if (entry % np->tx_coalesce == 0 || np->speed == 10)
txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag |
- WordAlignDisable |
+ WordAlignDisable |
TxDMAIndicate |
(1 << FragCountShift));
else
txdesc->status = cpu_to_le64 (entry | tfc_vlan_tag |
- WordAlignDisable |
+ WordAlignDisable |
(1 << FragCountShift));
/* TxDMAPollNow */
dev->base_addr + TFDListPtr0);
writel (0, dev->base_addr + TFDListPtr1);
}
-
+
/* NETDEV WATCHDOG timer */
dev->trans_start = jiffies;
return 0;
}
static irqreturn_t
-rio_interrupt (int irq, void *dev_instance, struct pt_regs *rgs)
+rio_interrupt (int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
struct netdev_private *np;
int handled = 0;
ioaddr = dev->base_addr;
- np = dev->priv;
+ np = netdev_priv(dev);
while (1) {
- int_status = readw (ioaddr + IntStatus);
+ int_status = readw (ioaddr + IntStatus);
writew (int_status, ioaddr + IntStatus);
int_status &= DEFAULT_INTR;
if (int_status == 0 || --cnt < 0)
if (tx_status & 0x01)
tx_error (dev, tx_status);
/* Free used tx skbuffs */
- rio_free_tx (dev, 1);
+ rio_free_tx (dev, 1);
}
/* Handle uncommon events */
return IRQ_RETVAL(handled);
}
-static void
-rio_free_tx (struct net_device *dev, int irq)
+static void
+rio_free_tx (struct net_device *dev, int irq)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
int entry = np->old_tx % TX_RING_SIZE;
int tx_use = 0;
unsigned long flag = 0;
-
+
if (irq)
spin_lock(&np->tx_lock);
else
spin_lock_irqsave(&np->tx_lock, flag);
-
+
/* Free used tx skbuffs */
while (entry != np->cur_tx) {
struct sk_buff *skb;
break;
skb = np->tx_skbuff[entry];
pci_unmap_single (np->pdev,
- np->tx_ring[entry].fraginfo,
+ np->tx_ring[entry].fraginfo & DMA_48BIT_MASK,
skb->len, PCI_DMA_TODEVICE);
if (irq)
dev_kfree_skb_irq (skb);
else
dev_kfree_skb (skb);
- np->tx_skbuff[entry] = 0;
+ np->tx_skbuff[entry] = NULL;
entry = (entry + 1) % TX_RING_SIZE;
tx_use++;
}
spin_unlock_irqrestore(&np->tx_lock, flag);
np->old_tx = entry;
- /* If the ring is no longer full, clear tx_full and
+ /* If the ring is no longer full, clear tx_full and
call netif_wake_queue() */
if (netif_queue_stopped(dev) &&
- ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE
+ ((np->cur_tx - np->old_tx + TX_RING_SIZE) % TX_RING_SIZE
< TX_QUEUE_LEN - 1 || np->speed == 10)) {
netif_wake_queue (dev);
}
int frame_id;
int i;
- np = dev->priv;
+ np = netdev_priv(dev);
frame_id = (tx_status & 0xffff0000);
printk (KERN_ERR "%s: Transmit error, TxStatus %4.4x, FrameId %d.\n",
/* Let TxStartThresh stay default value */
}
/* Maximum Collisions */
-#ifdef ETHER_STATS
- if (tx_status & 0x08)
+#ifdef ETHER_STATS
+ if (tx_status & 0x08)
np->stats.collisions16++;
#else
- if (tx_status & 0x08)
+ if (tx_status & 0x08)
np->stats.collisions++;
#endif
/* Restart the Tx */
static int
receive_packet (struct net_device *dev)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
int entry = np->cur_rx % RX_RING_SIZE;
int cnt = 30;
/* Small skbuffs for short packets */
if (pkt_len > copy_thresh) {
- pci_unmap_single (np->pdev, desc->fraginfo,
+ pci_unmap_single (np->pdev,
+ desc->fraginfo & DMA_48BIT_MASK,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
skb_put (skb = np->rx_skbuff[entry], pkt_len);
np->rx_skbuff[entry] = NULL;
} else if ((skb = dev_alloc_skb (pkt_len + 2)) != NULL) {
pci_dma_sync_single_for_cpu(np->pdev,
- desc->fraginfo,
+ desc->fraginfo &
+ DMA_48BIT_MASK,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
skb->dev = dev;
/* 16 byte align the IP header */
skb_reserve (skb, 2);
eth_copy_and_sum (skb,
- np->rx_skbuff[entry]->tail,
+ np->rx_skbuff[entry]->data,
pkt_len, 0);
skb_put (skb, pkt_len);
pci_dma_sync_single_for_device(np->pdev,
- desc->fraginfo,
+ desc->fraginfo &
+ DMA_48BIT_MASK,
np->rx_buf_sz,
PCI_DMA_FROMDEVICE);
}
skb->protocol = eth_type_trans (skb, dev);
-#if 0
+#if 0
/* Checksum done by hw, but csum value unavailable. */
- if (np->pci_rev_id >= 0x0c &&
+ if (np->pci_rev_id >= 0x0c &&
!(frame_status & (TCPError | UDPError | IPError))) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
- }
+ }
#endif
netif_rx (skb);
dev->last_rx = jiffies;
skb_reserve (skb, 2);
np->rx_ring[entry].fraginfo =
cpu_to_le64 (pci_map_single
- (np->pdev, skb->tail, np->rx_buf_sz,
+ (np->pdev, skb->data, np->rx_buf_sz,
PCI_DMA_FROMDEVICE));
}
np->rx_ring[entry].fraginfo |=
rio_error (struct net_device *dev, int int_status)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
u16 macctrl;
/* Link change event */
mii_get_media (dev);
if (np->speed == 1000)
np->tx_coalesce = tx_coalesce;
- else
+ else
np->tx_coalesce = 1;
macctrl = 0;
macctrl |= (np->vlan) ? AutoVLANuntagging : 0;
macctrl |= (np->full_duplex) ? DuplexSelect : 0;
- macctrl |= (np->tx_flow) ?
+ macctrl |= (np->tx_flow) ?
TxFlowControlEnable : 0;
- macctrl |= (np->rx_flow) ?
+ macctrl |= (np->rx_flow) ?
RxFlowControlEnable : 0;
writew(macctrl, ioaddr + MACCtrl);
np->link_status = 1;
get_stats (dev);
}
- /* PCI Error, a catastronphic error related to the bus interface
+ /* PCI Error, a catastronphic error related to the bus interface
occurs, set GlobalReset and HostReset to reset. */
if (int_status & HostError) {
printk (KERN_ERR "%s: HostError! IntStatus %4.4x.\n",
get_stats (struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
#ifdef MEM_MAPPING
int i;
#endif
/* All statistics registers need to be acknowledged,
else statistic overflow could cause problems */
-
+
np->stats.rx_packets += readl (ioaddr + FramesRcvOk);
np->stats.tx_packets += readl (ioaddr + FramesXmtOk);
np->stats.rx_bytes += readl (ioaddr + OctetRcvOk);
np->stats.tx_bytes += readl (ioaddr + OctetXmtOk);
np->stats.multicast = readl (ioaddr + McstFramesRcvdOk);
- np->stats.collisions += readl (ioaddr + SingleColFrames)
- + readl (ioaddr + MultiColFrames);
-
+ np->stats.collisions += readl (ioaddr + SingleColFrames)
+ + readl (ioaddr + MultiColFrames);
+
/* detailed tx errors */
stat_reg = readw (ioaddr + FramesAbortXSColls);
np->stats.tx_aborted_errors += stat_reg;
long ioaddr = dev->base_addr;
#ifdef MEM_MAPPING
int i;
-#endif
+#endif
/* All statistics registers need to be acknowledged,
else statistic overflow could cause problems */
readl (ioaddr + SingleColFrames);
readl (ioaddr + MultiColFrames);
readl (ioaddr + LateCollisions);
- /* detailed rx errors */
+ /* detailed rx errors */
readw (ioaddr + FrameTooLongErrors);
readw (ioaddr + InRangeLengthErrors);
readw (ioaddr + FramesCheckSeqErrors);
#ifdef MEM_MAPPING
for (i = 0x100; i <= 0x150; i += 4)
readl (ioaddr + i);
-#endif
+#endif
readw (ioaddr + TxJumboFrames);
readw (ioaddr + RxJumboFrames);
readw (ioaddr + TCPCheckSumErrors);
int
change_mtu (struct net_device *dev, int new_mtu)
{
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
int max = (np->jumbo) ? MAX_JUMBO : 1536;
if ((new_mtu < 68) || (new_mtu > max)) {
long ioaddr = dev->base_addr;
u32 hash_table[2];
u16 rx_mode = 0;
- struct netdev_private *np = dev->priv;
-
+ struct netdev_private *np = netdev_priv(dev);
+
hash_table[0] = hash_table[1] = 0;
/* RxFlowcontrol DA: 01-80-C2-00-00-01. Hash index=0x39 */
hash_table[1] |= cpu_to_le32(0x02000000);
if (dev->flags & IFF_PROMISC) {
/* Receive all frames promiscuously. */
rx_mode = ReceiveAllFrames;
- } else if ((dev->flags & IFF_ALLMULTI) ||
+ } else if ((dev->flags & IFF_ALLMULTI) ||
(dev->mc_count > multicast_filter_limit)) {
/* Receive broadcast and multicast frames */
rx_mode = ReceiveBroadcast | ReceiveMulticast | ReceiveUnicast;
} else if (dev->mc_count > 0) {
int i;
struct dev_mc_list *mclist;
- /* Receive broadcast frames and multicast frames filtering
+ /* Receive broadcast frames and multicast frames filtering
by Hashtable */
rx_mode =
ReceiveBroadcast | ReceiveMulticastHash | ReceiveUnicast;
- for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count;
- i++, mclist=mclist->next)
+ for (i=0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+ i++, mclist=mclist->next)
{
int bit, index = 0;
int crc = ether_crc_le (ETH_ALEN, mclist->dmi_addr);
writew (rx_mode, ioaddr + ReceiveMode);
}
-static int
-rio_ethtool_ioctl (struct net_device *dev, void *useraddr)
+static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ strcpy(info->driver, "dl2k");
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, pci_name(np->pdev));
+}
+
+static int rio_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ if (np->phy_media) {
+ /* fiber device */
+ cmd->supported = SUPPORTED_Autoneg | SUPPORTED_FIBRE;
+ cmd->advertising= ADVERTISED_Autoneg | ADVERTISED_FIBRE;
+ cmd->port = PORT_FIBRE;
+ cmd->transceiver = XCVR_INTERNAL;
+ } else {
+ /* copper device */
+ cmd->supported = SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_MII;
+ cmd->advertising = ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full|
+ ADVERTISED_Autoneg | ADVERTISED_MII;
+ cmd->port = PORT_MII;
+ cmd->transceiver = XCVR_INTERNAL;
+ }
+ if ( np->link_status ) {
+ cmd->speed = np->speed;
+ cmd->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+ } else {
+ cmd->speed = -1;
+ cmd->duplex = -1;
+ }
+ if ( np->an_enable)
+ cmd->autoneg = AUTONEG_ENABLE;
+ else
+ cmd->autoneg = AUTONEG_DISABLE;
+
+ cmd->phy_address = np->phy_addr;
+ return 0;
+}
+
+static int rio_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct netdev_private *np = dev->priv;
- u32 ethcmd;
-
- if (copy_from_user (ðcmd, useraddr, sizeof (ethcmd)))
- return -EFAULT;
- switch (ethcmd) {
- case ETHTOOL_GDRVINFO: {
- struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
- strcpy(info.driver, "DL2K");
- strcpy(info.version, DRV_VERSION);
- strcpy(info.bus_info, pci_name(np->pdev));
- memset(&info.fw_version, 0, sizeof(info.fw_version));
- if (copy_to_user(useraddr, &info, sizeof(info)))
- return -EFAULT;
+ struct netdev_private *np = netdev_priv(dev);
+ netif_carrier_off(dev);
+ if (cmd->autoneg == AUTONEG_ENABLE) {
+ if (np->an_enable)
+ return 0;
+ else {
+ np->an_enable = 1;
+ mii_set_media(dev);
return 0;
- }
-
- case ETHTOOL_GSET: {
- struct ethtool_cmd cmd = { ETHTOOL_GSET };
- if (np->phy_media) {
- /* fiber device */
- cmd.supported = SUPPORTED_Autoneg |
- SUPPORTED_FIBRE;
- cmd.advertising= ADVERTISED_Autoneg |
- ADVERTISED_FIBRE;
- cmd.port = PORT_FIBRE;
- cmd.transceiver = XCVR_INTERNAL;
- } else {
- /* copper device */
- cmd.supported = SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full |
- SUPPORTED_Autoneg | SUPPORTED_MII;
- cmd.advertising = ADVERTISED_10baseT_Half |
- ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half |
- ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Full|
- ADVERTISED_Autoneg | ADVERTISED_MII;
- cmd.port = PORT_MII;
- cmd.transceiver = XCVR_INTERNAL;
- }
- if ( np->link_status ) {
- cmd.speed = np->speed;
- cmd.duplex = np->full_duplex ?
- DUPLEX_FULL : DUPLEX_HALF;
- } else {
- cmd.speed = -1;
- cmd.duplex = -1;
- }
- if ( np->an_enable)
- cmd.autoneg = AUTONEG_ENABLE;
- else
- cmd.autoneg = AUTONEG_DISABLE;
-
- cmd.phy_address = np->phy_addr;
-
- if (copy_to_user(useraddr, &cmd,
- sizeof(cmd)))
- return -EFAULT;
- return 0;
}
- case ETHTOOL_SSET: {
- struct ethtool_cmd cmd;
- if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
- return -EFAULT;
- netif_carrier_off(dev);
- if (cmd.autoneg == AUTONEG_ENABLE) {
- if (np->an_enable)
- return 0;
- else {
- np->an_enable = 1;
- mii_set_media(dev);
- return 0;
- }
- } else {
- np->an_enable = 0;
- if (np->speed == 1000){
- cmd.speed = SPEED_100;
- cmd.duplex = DUPLEX_FULL;
- printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manul 100Mbps, Full duplex.\n");
- }
- switch(cmd.speed + cmd.duplex){
-
- case SPEED_10 + DUPLEX_HALF:
- np->speed = 10;
- np->full_duplex = 0;
- break;
-
- case SPEED_10 + DUPLEX_FULL:
- np->speed = 10;
- np->full_duplex = 1;
- break;
- case SPEED_100 + DUPLEX_HALF:
- np->speed = 100;
- np->full_duplex = 0;
- break;
- case SPEED_100 + DUPLEX_FULL:
- np->speed = 100;
- np->full_duplex = 1;
- break;
- case SPEED_1000 + DUPLEX_HALF:/* not supported */
- case SPEED_1000 + DUPLEX_FULL:/* not supported */
- default:
- return -EINVAL;
- }
- mii_set_media(dev);
- }
- return 0;
+ } else {
+ np->an_enable = 0;
+ if (np->speed == 1000) {
+ cmd->speed = SPEED_100;
+ cmd->duplex = DUPLEX_FULL;
+ printk("Warning!! Can't disable Auto negotiation in 1000Mbps, change to Manual 100Mbps, Full duplex.\n");
}
-#ifdef ETHTOOL_GLINK
- case ETHTOOL_GLINK:{
- struct ethtool_value link = { ETHTOOL_GLINK };
- link.data = np->link_status;
- if (copy_to_user(useraddr, &link, sizeof(link)))
- return -EFAULT;
- return 0;
- }
-#endif
+ switch(cmd->speed + cmd->duplex) {
+
+ case SPEED_10 + DUPLEX_HALF:
+ np->speed = 10;
+ np->full_duplex = 0;
+ break;
+
+ case SPEED_10 + DUPLEX_FULL:
+ np->speed = 10;
+ np->full_duplex = 1;
+ break;
+ case SPEED_100 + DUPLEX_HALF:
+ np->speed = 100;
+ np->full_duplex = 0;
+ break;
+ case SPEED_100 + DUPLEX_FULL:
+ np->speed = 100;
+ np->full_duplex = 1;
+ break;
+ case SPEED_1000 + DUPLEX_HALF:/* not supported */
+ case SPEED_1000 + DUPLEX_FULL:/* not supported */
default:
- return -EOPNOTSUPP;
- }
+ return -EINVAL;
+ }
+ mii_set_media(dev);
+ }
+ return 0;
}
+static u32 rio_get_link(struct net_device *dev)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ return np->link_status;
+}
+
+static const struct ethtool_ops ethtool_ops = {
+ .get_drvinfo = rio_get_drvinfo,
+ .get_settings = rio_get_settings,
+ .set_settings = rio_set_settings,
+ .get_link = rio_get_link,
+};
static int
rio_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
{
int phy_addr;
- struct netdev_private *np = dev->priv;
- struct mii_data *miidata = (struct mii_data *) &rq->ifr_data;
-
+ struct netdev_private *np = netdev_priv(dev);
+ struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru;
+
struct netdev_desc *desc;
int i;
phy_addr = np->phy_addr;
switch (cmd) {
- case SIOCETHTOOL:
- return rio_ethtool_ioctl (dev, (void *) rq->ifr_data);
case SIOCDEVPRIVATE:
break;
-
+
case SIOCDEVPRIVATE + 1:
miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num);
break;
int phy_addr;
struct netdev_private *np;
- np = dev->priv;
+ np = netdev_priv(dev);
phy_addr = np->phy_addr;
do {
int phy_addr;
struct netdev_private *np;
- np = dev->priv;
+ np = netdev_priv(dev);
phy_addr = np->phy_addr;
bmsr.image = mii_read (dev, phy_addr, MII_BMSR);
/* Auto-Negotiation not completed */
return -1;
}
- negotiate.image = mii_read (dev, phy_addr, MII_ANAR) &
+ negotiate.image = mii_read (dev, phy_addr, MII_ANAR) &
mii_read (dev, phy_addr, MII_ANLPAR);
mscr.image = mii_read (dev, phy_addr, MII_MSCR);
mssr.image = mii_read (dev, phy_addr, MII_MSSR);
printk ("Half duplex\n");
}
}
- if (np->tx_flow)
+ if (np->tx_flow)
printk(KERN_INFO "Enable Tx Flow Control\n");
- else
+ else
printk(KERN_INFO "Disable Tx Flow Control\n");
if (np->rx_flow)
printk(KERN_INFO "Enable Rx Flow Control\n");
ANAR_t anar;
int phy_addr;
struct netdev_private *np;
- np = dev->priv;
+ np = netdev_priv(dev);
phy_addr = np->phy_addr;
/* Does user set speed? */
pscr.image = mii_read (dev, phy_addr, MII_PHY_SCR);
pscr.bits.mdi_crossover_mode = 3; /* 11'b */
mii_write (dev, phy_addr, MII_PHY_SCR, pscr.image);
-
+
/* Soft reset PHY */
mii_write (dev, phy_addr, MII_BMCR, MII_BMCR_RESET);
bmcr.image = 0;
int phy_addr;
struct netdev_private *np;
- np = dev->priv;
+ np = netdev_priv(dev);
phy_addr = np->phy_addr;
bmsr.image = mii_read (dev, phy_addr, PCS_BMSR);
/* Auto-Negotiation not completed */
return -1;
}
- negotiate.image = mii_read (dev, phy_addr, PCS_ANAR) &
+ negotiate.image = mii_read (dev, phy_addr, PCS_ANAR) &
mii_read (dev, phy_addr, PCS_ANLPAR);
np->speed = 1000;
if (negotiate.bits.full_duplex) {
printk ("Half duplex\n");
}
}
- if (np->tx_flow)
+ if (np->tx_flow)
printk(KERN_INFO "Enable Tx Flow Control\n");
- else
+ else
printk(KERN_INFO "Disable Tx Flow Control\n");
if (np->rx_flow)
printk(KERN_INFO "Enable Rx Flow Control\n");
ANAR_PCS_t anar;
int phy_addr;
struct netdev_private *np;
- np = dev->priv;
+ np = netdev_priv(dev);
phy_addr = np->phy_addr;
/* Auto-Negotiation? */
/* Advertise capabilities */
esr.image = mii_read (dev, phy_addr, PCS_ESR);
anar.image = mii_read (dev, phy_addr, MII_ANAR);
- anar.bits.half_duplex =
+ anar.bits.half_duplex =
esr.bits.media_1000BT_HD | esr.bits.media_1000BX_HD;
- anar.bits.full_duplex =
+ anar.bits.full_duplex =
esr.bits.media_1000BT_FD | esr.bits.media_1000BX_FD;
anar.bits.pause = 1;
anar.bits.asymmetric = 1;
rio_close (struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
struct sk_buff *skb;
int i;
synchronize_irq (dev->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;
np->rx_ring[i].fraginfo = 0;
skb = np->rx_skbuff[i];
if (skb) {
- pci_unmap_single (np->pdev, np->rx_ring[i].fraginfo,
- skb->len, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(np->pdev,
+ np->rx_ring[i].fraginfo & DMA_48BIT_MASK,
+ skb->len, PCI_DMA_FROMDEVICE);
dev_kfree_skb (skb);
- np->rx_skbuff[i] = 0;
+ np->rx_skbuff[i] = NULL;
}
}
for (i = 0; i < TX_RING_SIZE; i++) {
skb = np->tx_skbuff[i];
if (skb) {
- pci_unmap_single (np->pdev, np->tx_ring[i].fraginfo,
- skb->len, PCI_DMA_TODEVICE);
+ pci_unmap_single(np->pdev,
+ np->tx_ring[i].fraginfo & DMA_48BIT_MASK,
+ skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb (skb);
- np->tx_skbuff[i] = 0;
+ np->tx_skbuff[i] = NULL;
}
}
struct net_device *dev = pci_get_drvdata (pdev);
if (dev) {
- struct netdev_private *np = dev->priv;
+ struct netdev_private *np = netdev_priv(dev);
unregister_netdev (dev);
pci_free_consistent (pdev, RX_TOTAL_SIZE, np->rx_ring,
static int __init
rio_init (void)
{
- return pci_module_init (&rio_driver);
+ return pci_register_driver(&rio_driver);
}
static void __exit
module_exit (rio_exit);
/*
-
-Compile command:
-
+
+Compile command:
+
gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -c dl2k.c
Read Documentation/networking/dl2k.txt for details.