#include <asm/uaccess.h>
+#define DRV_NAME "acenic"
+
#undef INDEX_DEBUG
#ifdef CONFIG_ACENIC_OMIT_TIGON_I
MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
-static char version[] __initdata =
+static char version[] =
"acenic.c: v0.92 08/05/2002 Jes Sorensen, linux-acenic@SunSITE.dk\n"
" http://home.cern.ch/~jes/gige/acenic.html\n";
+static int ace_get_settings(struct net_device *, struct ethtool_cmd *);
+static int ace_set_settings(struct net_device *, struct ethtool_cmd *);
+static void ace_get_drvinfo(struct net_device *, struct ethtool_drvinfo *);
+
+static struct ethtool_ops ace_ethtool_ops = {
+ .get_settings = ace_get_settings,
+ .set_settings = ace_set_settings,
+ .get_drvinfo = ace_get_drvinfo,
+};
+
static int __devinit acenic_probe_one(struct pci_dev *pdev,
const struct pci_device_id *id)
{
dev->hard_start_xmit = &ace_start_xmit;
dev->get_stats = &ace_get_stats;
dev->set_multicast_list = &ace_set_multicast_list;
- dev->do_ioctl = &ace_ioctl;
+ SET_ETHTOOL_OPS(dev, &ace_ethtool_ops);
dev->set_mac_address = &ace_set_mac_addr;
dev->change_mtu = &ace_change_mtu;
}
ecode = request_irq(pdev->irq, ace_interrupt, SA_SHIRQ,
- dev->name, dev);
+ DRV_NAME, dev);
if (ecode) {
printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
- dev->name, pdev->irq);
+ DRV_NAME, pdev->irq);
goto init_error;
} else
dev->irq = pdev->irq;
cur_size = atomic_read(&ap->cur_rx_bufs);
if ((cur_size < RX_LOW_STD_THRES) &&
!test_and_set_bit(0, &ap->std_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("refilling buffers (current %i)\n", cur_size);
#endif
ace_load_std_rx_ring(ap, RX_RING_SIZE - cur_size);
cur_size = atomic_read(&ap->cur_mini_bufs);
if ((cur_size < RX_LOW_MINI_THRES) &&
!test_and_set_bit(0, &ap->mini_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("refilling mini buffers (current %i)\n",
cur_size);
#endif
cur_size = atomic_read(&ap->cur_jumbo_bufs);
if (ap->jumbo && (cur_size < RX_LOW_JUMBO_THRES) &&
!test_and_set_bit(0, &ap->jumbo_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("refilling jumbo buffers (current %i)\n", cur_size);
#endif
ace_load_jumbo_rx_ring(ap, RX_JUMBO_SIZE - cur_size);
int bd_flags, desc_type, mapsize;
u16 csum;
+
+ /* make sure the rx descriptor isn't read before rxretprd */
+ if (idx == rxretcsm)
+ rmb();
+
retdesc = &ap->rx_return_ring[idx];
skbidx = retdesc->idx;
bd_flags = retdesc->flags;
if (cur_size < RX_LOW_STD_THRES) {
if ((cur_size < RX_PANIC_STD_THRES) &&
!test_and_set_bit(0, &ap->std_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("low on std buffers %i\n", cur_size);
#endif
ace_load_std_rx_ring(ap,
if ((cur_size < RX_PANIC_MINI_THRES) &&
!test_and_set_bit(0,
&ap->mini_refill_busy)) {
-#if DEBUG
+#ifdef DEBUG
printk("low on mini buffers %i\n",
cur_size);
#endif
if ((cur_size < RX_PANIC_JUMBO_THRES) &&
!test_and_set_bit(0,
&ap->jumbo_refill_busy)){
-#if DEBUG
+#ifdef DEBUG
printk("low on jumbo buffers %i\n",
cur_size);
#endif
return 0;
}
-
-static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int ace_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
struct ace_private *ap = dev->priv;
struct ace_regs *regs = ap->regs;
-#ifdef SIOCETHTOOL
- struct ethtool_cmd ecmd;
- u32 link, speed;
+ u32 link;
- if (cmd != SIOCETHTOOL)
- return -EOPNOTSUPP;
- if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
- return -EFAULT;
- switch (ecmd.cmd) {
- case ETHTOOL_GSET:
- ecmd.supported =
- (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
- SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
- SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-
- ecmd.port = PORT_FIBRE;
- ecmd.transceiver = XCVR_INTERNAL;
- ecmd.phy_address = 0;
-
- link = readl(®s->GigLnkState);
- if (link & LNK_1000MB)
- ecmd.speed = SPEED_1000;
- else {
- link = readl(®s->FastLnkState);
- if (link & LNK_100MB)
- ecmd.speed = SPEED_100;
- else if (link & LNK_100MB)
- ecmd.speed = SPEED_10;
- else
- ecmd.speed = 0;
- }
- if (link & LNK_FULL_DUPLEX)
- ecmd.duplex = DUPLEX_FULL;
- else
- ecmd.duplex = DUPLEX_HALF;
+ memset(ecmd, 0, sizeof(struct ethtool_cmd));
+ ecmd->supported =
+ (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full |
+ SUPPORTED_Autoneg | SUPPORTED_FIBRE);
- if (link & LNK_NEGOTIATE)
- ecmd.autoneg = AUTONEG_ENABLE;
+ ecmd->port = PORT_FIBRE;
+ ecmd->transceiver = XCVR_INTERNAL;
+
+ link = readl(®s->GigLnkState);
+ if (link & LNK_1000MB)
+ ecmd->speed = SPEED_1000;
+ else {
+ link = readl(®s->FastLnkState);
+ if (link & LNK_100MB)
+ ecmd->speed = SPEED_100;
+ else if (link & LNK_10MB)
+ ecmd->speed = SPEED_10;
else
- ecmd.autoneg = AUTONEG_DISABLE;
+ ecmd->speed = 0;
+ }
+ if (link & LNK_FULL_DUPLEX)
+ ecmd->duplex = DUPLEX_FULL;
+ else
+ ecmd->duplex = DUPLEX_HALF;
+
+ if (link & LNK_NEGOTIATE)
+ ecmd->autoneg = AUTONEG_ENABLE;
+ else
+ ecmd->autoneg = AUTONEG_DISABLE;
#if 0
- /*
- * Current struct ethtool_cmd is insufficient
- */
- ecmd.trace = readl(®s->TuneTrace);
+ /*
+ * Current struct ethtool_cmd is insufficient
+ */
+ ecmd->trace = readl(®s->TuneTrace);
- ecmd.txcoal = readl(®s->TuneTxCoalTicks);
- ecmd.rxcoal = readl(®s->TuneRxCoalTicks);
+ ecmd->txcoal = readl(®s->TuneTxCoalTicks);
+ ecmd->rxcoal = readl(®s->TuneRxCoalTicks);
#endif
- ecmd.maxtxpkt = readl(®s->TuneMaxTxDesc);
- ecmd.maxrxpkt = readl(®s->TuneMaxRxDesc);
+ ecmd->maxtxpkt = readl(®s->TuneMaxTxDesc);
+ ecmd->maxrxpkt = readl(®s->TuneMaxRxDesc);
- if(copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd)))
- return -EFAULT;
- return 0;
+ return 0;
+}
- case ETHTOOL_SSET:
- link = readl(®s->GigLnkState);
- if (link & LNK_1000MB)
- speed = SPEED_1000;
- else {
- link = readl(®s->FastLnkState);
- if (link & LNK_100MB)
- speed = SPEED_100;
- else if (link & LNK_100MB)
- speed = SPEED_10;
- else
- speed = SPEED_100;
- }
+static int ace_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct ace_private *ap = dev->priv;
+ struct ace_regs *regs = ap->regs;
+ u32 link, speed;
- link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB |
- LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL;
- if (!ACE_IS_TIGON_I(ap))
- link |= LNK_TX_FLOW_CTL_Y;
- if (ecmd.autoneg == AUTONEG_ENABLE)
- link |= LNK_NEGOTIATE;
- if (ecmd.speed != speed) {
- link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB);
- switch (speed) {
- case SPEED_1000:
- link |= LNK_1000MB;
- break;
- case SPEED_100:
- link |= LNK_100MB;
- break;
- case SPEED_10:
- link |= LNK_10MB;
- break;
- }
+ link = readl(®s->GigLnkState);
+ if (link & LNK_1000MB)
+ speed = SPEED_1000;
+ else {
+ link = readl(®s->FastLnkState);
+ if (link & LNK_100MB)
+ speed = SPEED_100;
+ else if (link & LNK_10MB)
+ speed = SPEED_10;
+ else
+ speed = SPEED_100;
+ }
+
+ link = LNK_ENABLE | LNK_1000MB | LNK_100MB | LNK_10MB |
+ LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL;
+ if (!ACE_IS_TIGON_I(ap))
+ link |= LNK_TX_FLOW_CTL_Y;
+ if (ecmd->autoneg == AUTONEG_ENABLE)
+ link |= LNK_NEGOTIATE;
+ if (ecmd->speed != speed) {
+ link &= ~(LNK_1000MB | LNK_100MB | LNK_10MB);
+ switch (speed) {
+ case SPEED_1000:
+ link |= LNK_1000MB;
+ break;
+ case SPEED_100:
+ link |= LNK_100MB;
+ break;
+ case SPEED_10:
+ link |= LNK_10MB;
+ break;
}
- if (ecmd.duplex == DUPLEX_FULL)
- link |= LNK_FULL_DUPLEX;
+ }
- if (link != ap->link) {
- struct cmd cmd;
- printk(KERN_INFO "%s: Renegotiating link state\n",
- dev->name);
+ if (ecmd->duplex == DUPLEX_FULL)
+ link |= LNK_FULL_DUPLEX;
- ap->link = link;
- writel(link, ®s->TuneLink);
- if (!ACE_IS_TIGON_I(ap))
- writel(link, ®s->TuneFastLink);
- wmb();
+ if (link != ap->link) {
+ struct cmd cmd;
+ printk(KERN_INFO "%s: Renegotiating link state\n",
+ dev->name);
- cmd.evt = C_LNK_NEGOTIATION;
- cmd.code = 0;
- cmd.idx = 0;
- ace_issue_cmd(regs, &cmd);
- }
- return 0;
-
- case ETHTOOL_GDRVINFO: {
- struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
- strncpy(info.driver, "acenic", sizeof(info.driver) - 1);
- sprintf(info.fw_version, "%i.%i.%i",
- tigonFwReleaseMajor, tigonFwReleaseMinor,
- tigonFwReleaseFix);
- strncpy(info.version, version, sizeof(info.version) - 1);
- if (ap && ap->pdev)
- strcpy(info.bus_info, pci_name(ap->pdev));
- if (copy_to_user(ifr->ifr_data, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
- default:
- break;
- }
-
-#endif
+ ap->link = link;
+ writel(link, ®s->TuneLink);
+ if (!ACE_IS_TIGON_I(ap))
+ writel(link, ®s->TuneFastLink);
+ wmb();
- return -EOPNOTSUPP;
+ cmd.evt = C_LNK_NEGOTIATION;
+ cmd.code = 0;
+ cmd.idx = 0;
+ ace_issue_cmd(regs, &cmd);
+ }
+ return 0;
}
+static void ace_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct ace_private *ap = dev->priv;
+
+ strlcpy(info->driver, "acenic", sizeof(info->driver));
+ snprintf(info->version, sizeof(info->version), "%i.%i.%i",
+ tigonFwReleaseMajor, tigonFwReleaseMinor,
+ tigonFwReleaseFix);
+
+ if (ap->pdev)
+ strlcpy(info->bus_info, pci_name(ap->pdev),
+ sizeof(info->bus_info));
+
+}
/*
* Set the hardware MAC address.