This is a compatibility hardware problem.
Versions:
+ 0.13b basic ethtool support (aris, 09/13/2004)
0.13a in memory shortage, drop packets also in board
(Michael Westermann <mw@microdata-pos.de>, 07/30/2002)
0.13 irq sharing, rewrote probe function, fixed a nasty bug in
*/
static const char version[] =
- "eepro.c: v0.13 11/08/2001 aris@cathedrallabs.org\n";
+ "eepro.c: v0.13b 09/13/2004 aris@cathedrallabs.org\n";
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/bitops.h>
+#include <linux/ethtool.h>
#include <asm/system.h>
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#define DRV_NAME "eepro"
+#define DRV_VERSION "0.13c"
#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) )
/* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
#define SLOW_DOWN inb(0x80)
/* udelay(2) */
#define compat_init_data __initdata
-
+enum iftype { AUI=0, BNC=1, TPE=2 };
/* First, a few definitions that the brave might change. */
/* A zero-terminated list of I/O addresses to be probed. */
short rcv_lower_limit;
short rcv_upper_limit;
unsigned char eeprom_reg;
+ unsigned short word[8];
};
/* The station (ethernet) address prefix, used for IDing the board. */
static int eepro_probe1(struct net_device *dev, int autoprobe);
static int eepro_open(struct net_device *dev);
static int eepro_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t eepro_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t eepro_interrupt(int irq, void *dev_id);
static void eepro_rx(struct net_device *dev);
static void eepro_transmit_interrupt(struct net_device *dev);
static int eepro_close(struct net_device *dev);
{
unsigned short int WS[32]=WakeupSeq;
- if (check_region(WakeupPort, 2)==0) {
-
+ if (request_region(WakeupPort, 2, "eepro wakeup")) {
if (net_debug>5)
printk(KERN_DEBUG "Waking UP\n");
outb_p(WS[i],WakeupPort);
if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
}
- } else printk(KERN_WARNING "Checkregion Failed!\n");
+
+ release_region(WakeupPort, 2);
+ } else
+ printk(KERN_WARNING "PnP wakeup region busy!\n");
}
#endif
err = do_eepro_probe(dev);
if (err)
goto out;
- err = register_netdev(dev);
- if (err)
- goto out1;
return dev;
-out1:
- release_region(dev->base_addr, EEPRO_IO_EXTENT);
out:
free_netdev(dev);
return ERR_PTR(err);
}
#endif
-static void __init printEEPROMInfo(short ioaddr, struct net_device *dev)
+static void __init printEEPROMInfo(struct net_device *dev)
{
+ struct eepro_local *lp = (struct eepro_local *)dev->priv;
+ int ioaddr = dev->base_addr;
unsigned short Word;
int i,j;
- for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
- j+=read_eeprom(ioaddr,i,dev);
+ j = ee_Checksum;
+ for (i = 0; i < 8; i++)
+ j += lp->word[i];
+ for ( ; i < ee_SIZE; i++)
+ j += read_eeprom(ioaddr, i, dev);
+
printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff);
- Word=read_eeprom(ioaddr, 0, dev);
+ Word = lp->word[0];
printk(KERN_DEBUG "Word0:\n");
printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );
printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);
if (net_debug>4) {
- Word=read_eeprom(ioaddr, 1, dev);
+ Word = lp->word[1];
printk(KERN_DEBUG "Word1:\n");
printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask);
printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI));
printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
}
- Word=read_eeprom(ioaddr, 5, dev);
+ Word = lp->word[5];
printk(KERN_DEBUG "Word5:\n");
printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI ");
printk(KERN_DEBUG "port(s) \n");
- Word=read_eeprom(ioaddr, 6, dev);
+ Word = lp->word[6];
printk(KERN_DEBUG "Word6:\n");
printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
- Word=read_eeprom(ioaddr, 7, dev);
+ Word = lp->word[7];
printk(KERN_DEBUG "Word7:\n");
printk(KERN_DEBUG " INT to IRQ:\n");
dev->name, (unsigned)dev->base_addr);
break;
case LAN595FX:
- printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
+ printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
dev->name, (unsigned)dev->base_addr);
break;
case LAN595TX:
dev->name, (unsigned)dev->base_addr);
break;
case LAN595:
- printk("%s: Intel 82595-based lan card at %#x,",
+ printk("%s: Intel 82595-based lan card at %#x,",
dev->name, (unsigned)dev->base_addr);
}
if (dev->irq > 2)
printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]);
- else
+ else
printk(", %s.\n", ifmap[dev->if_port]);
if (net_debug > 3) {
- i = read_eeprom(dev->base_addr, 5, dev);
+ i = lp->word[5];
if (i & 0x2000) /* bit 13 of EEPROM word 5 */
printk(KERN_DEBUG "%s: Concurrent Processing is "
"enabled but not used!\n", dev->name);
/* Check the station address for the manufacturer's code */
if (net_debug>3)
- printEEPROMInfo(dev->base_addr, dev);
+ printEEPROMInfo(dev);
}
+static const struct ethtool_ops eepro_ethtool_ops;
+
/* This is the real probe routine. Linux has a history of friendly device
probes on the ISA bus. A good device probe avoids doing writes, and
verifies that the correct device exists and functions. */
static int __init eepro_probe1(struct net_device *dev, int autoprobe)
{
- unsigned short station_addr[6], id, counter;
+ unsigned short station_addr[3], id, counter;
int i;
struct eepro_local *lp;
- enum iftype { AUI=0, BNC=1, TPE=2 };
int ioaddr = dev->base_addr;
+ int err;
/* Grab the region so we can find another board if autoIRQ fails. */
- if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) {
+ if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) {
if (!autoprobe)
printk(KERN_WARNING "EEPRO: io-port 0x%04x in use \n",
ioaddr);
lp->xmt_bar = XMT_BAR_10;
station_addr[0] = read_eeprom(ioaddr, 2, dev);
}
- station_addr[1] = read_eeprom(ioaddr, 3, dev);
- station_addr[2] = read_eeprom(ioaddr, 4, dev);
+
+ /* get all words at once. will be used here and for ethtool */
+ for (i = 0; i < 8; i++) {
+ lp->word[i] = read_eeprom(ioaddr, i, dev);
+ }
+ station_addr[1] = lp->word[3];
+ station_addr[2] = lp->word[4];
if (!lp->eepro) {
- if (read_eeprom(ioaddr,7,dev)== ee_FX_INT2IRQ)
+ if (lp->word[7] == ee_FX_INT2IRQ)
lp->eepro = 2;
else if (station_addr[2] == SA_ADDR1)
lp->eepro = 1;
/* calculate {xmt,rcv}_{lower,upper}_limit */
eepro_recalc(dev);
- if (GetBit( read_eeprom(ioaddr, 5, dev),ee_BNC_TPE))
+ if (GetBit(lp->word[5], ee_BNC_TPE))
dev->if_port = BNC;
else
dev->if_port = TPE;
if (dev->irq < 2 && lp->eepro != 0) {
/* Mask off INT number */
- int count = read_eeprom(ioaddr, 1, dev) & 7;
- unsigned irqMask = read_eeprom(ioaddr, 7, dev);
-
+ int count = lp->word[1] & 7;
+ unsigned irqMask = lp->word[7];
+
while (count--)
irqMask &= irqMask - 1;
-
+
count = ffs(irqMask);
-
+
if (count)
dev->irq = count - 1;
-
+
if (dev->irq < 2) {
printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n");
goto exit;
dev->irq = 9;
}
}
-
+
dev->open = eepro_open;
dev->stop = eepro_close;
dev->hard_start_xmit = eepro_send_packet;
dev->set_multicast_list = &set_multicast_list;
dev->tx_timeout = eepro_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
-
+ dev->ethtool_ops = &eepro_ethtool_ops;
+
/* print boot time info */
eepro_print_info(dev);
/* reset 82595 */
eepro_reset(ioaddr);
+
+ err = register_netdev(dev);
+ if (err)
+ goto err;
return 0;
exit:
+ err = -ENODEV;
+err:
release_region(dev->base_addr, EEPRO_IO_EXTENT);
- return -ENODEV;
+ return err;
}
/* Open/initialize the board. This is called (in the current kernel)
eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
- if (request_irq (*irqp, NULL, SA_SHIRQ, "bogus", dev) != EBUSY) {
+ if (request_irq (*irqp, NULL, IRQF_SHARED, "bogus", dev) != EBUSY) {
unsigned long irq_mask;
/* Twinkle the interrupt, and check if it's seen */
irq_mask = probe_irq_on();
if (net_debug > 3)
printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
- irqMask = read_eeprom(ioaddr,7,dev);
+ irqMask = lp->word[7];
if (lp->eepro == LAN595FX_10ISA) {
if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n");
return -EAGAIN;
}
-#ifdef irq2dev_map
- if (((irq2dev_map[dev->irq] != 0)
- || (irq2dev_map[dev->irq] = dev) == 0) &&
- (irq2dev_map[dev->irq]!=dev)) {
- /* printk("%s: IRQ map wrong\n", dev->name); */
- free_irq(dev->irq, dev);
- return -EAGAIN;
- }
-#endif
-
/* Initialize the 82595. */
eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
/* Initialize the RCV and XMT upper and lower limits */
- outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG);
- outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG);
+ outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG);
+ outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG);
outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg);
outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg);
eepro_clear_int(ioaddr);
/* Initialize RCV */
- outw(lp->rcv_lower_limit, ioaddr + RCV_BAR);
+ outw(lp->rcv_lower_limit, ioaddr + RCV_BAR);
lp->rx_start = lp->rcv_lower_limit;
- outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP);
+ outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP);
/* Initialize XMT */
- outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar);
+ outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar);
lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
lp->tx_last = 0;
old9 = inb(ioaddr + 9);
if (irqMask==ee_FX_INT2IRQ) {
- enum iftype { AUI=0, BNC=1, TPE=2 };
-
if (net_debug > 3) {
printk(KERN_DEBUG "IrqMask: %#x\n",irqMask);
printk(KERN_DEBUG "i82595FX detected!\n");
printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name);
if (length < ETH_ZLEN) {
- skb = skb_padto(skb, ETH_ZLEN);
- if (skb == NULL)
+ if (skb_padto(skb, ETH_ZLEN))
return 0;
length = ETH_ZLEN;
}
Handle the network interface interrupts. */
static irqreturn_t
-eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+eepro_interrupt(int irq, void *dev_id)
{
- struct net_device *dev = (struct net_device *)dev_id;
- /* (struct net_device *)(irq2dev_map[irq]);*/
+ struct net_device *dev = dev_id;
struct eepro_local *lp;
int ioaddr, status, boguscount = 20;
int handled = 0;
- if (dev == NULL) {
- printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq);
- return IRQ_NONE;
- }
-
lp = netdev_priv(dev);
spin_lock(&lp->lock);
/* release the interrupt */
free_irq(dev->irq, dev);
-#ifdef irq2dev_map
- irq2dev_map[dev->irq] = 0;
-#endif
-
/* Update the statistics here. What statistics? */
return 0;
mode = inb(ioaddr + REG3);
outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
- printk(KERN_INFO "%s: promiscuous mode enabled.\n", dev->name);
}
else if (dev->mc_count==0 )
outb(0x08, ioaddr + STATUS_REG);
if (i & 0x20) { /* command ABORTed */
- printk(KERN_NOTICE "%s: multicast setup failed.\n",
+ printk(KERN_NOTICE "%s: multicast setup failed.\n",
dev->name);
break;
} else if ((i & 0x0f) == 0x03) { /* MC-Done */
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */
- if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
+ if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
/* Arrrr!!!, must keep the xmt header together,
several days were lost to chase this one down. */
last = lp->xmt_lower_limit;
else if (rcv_status & 0x0800)
lp->stats.rx_crc_errors++;
- printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
+ printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
}
{
struct eepro_local *lp = netdev_priv(dev);
short ioaddr = dev->base_addr;
- short boguscount = 25;
+ short boguscount = 25;
short xmt_status;
- while ((lp->tx_start != lp->tx_end) && boguscount--) {
+ while ((lp->tx_start != lp->tx_end) && boguscount--) {
outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
xmt_status = inw(ioaddr+IO_PORT);
}
}
+static int eepro_ethtool_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct eepro_local *lp = (struct eepro_local *)dev->priv;
+
+ cmd->supported = SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_Autoneg;
+ cmd->advertising = ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_Autoneg;
+
+ if (GetBit(lp->word[5], ee_PortTPE)) {
+ cmd->supported |= SUPPORTED_TP;
+ cmd->advertising |= ADVERTISED_TP;
+ }
+ if (GetBit(lp->word[5], ee_PortBNC)) {
+ cmd->supported |= SUPPORTED_BNC;
+ cmd->advertising |= ADVERTISED_BNC;
+ }
+ if (GetBit(lp->word[5], ee_PortAUI)) {
+ cmd->supported |= SUPPORTED_AUI;
+ cmd->advertising |= ADVERTISED_AUI;
+ }
+
+ cmd->speed = SPEED_10;
+
+ if (dev->if_port == TPE && lp->word[1] & ee_Duplex) {
+ cmd->duplex = DUPLEX_FULL;
+ }
+ else {
+ cmd->duplex = DUPLEX_HALF;
+ }
+
+ cmd->port = dev->if_port;
+ cmd->phy_address = dev->base_addr;
+ cmd->transceiver = XCVR_INTERNAL;
+
+ if (lp->word[0] & ee_AutoNeg) {
+ cmd->autoneg = 1;
+ }
+
+ return 0;
+}
+
+static void eepro_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strcpy(drvinfo->driver, DRV_NAME);
+ strcpy(drvinfo->version, DRV_VERSION);
+ sprintf(drvinfo->bus_info, "ISA 0x%lx", dev->base_addr);
+}
+
+static const struct ethtool_ops eepro_ethtool_ops = {
+ .get_settings = eepro_ethtool_get_settings,
+ .get_drvinfo = eepro_ethtool_get_drvinfo,
+};
+
#ifdef MODULE
#define MAX_EEPRO 8
static struct net_device *dev_eepro[MAX_EEPRO];
-static int io[MAX_EEPRO];
+static int io[MAX_EEPRO] = {
+ [0 ... MAX_EEPRO-1] = -1
+};
static int irq[MAX_EEPRO];
static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */
[0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024
static int n_eepro;
/* For linux 2.1.xx */
-MODULE_AUTHOR("Pascal Dupuis, and aris@cathedrallabs.org");
+MODULE_AUTHOR("Pascal Dupuis and others");
MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_EEPRO) "i");
-MODULE_PARM(autodetect, "1-" __MODULE_STRING(1) "i");
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+module_param(autodetect, int, 0);
MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base addres(es)");
MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
-int
-init_module(void)
+int __init init_module(void)
{
struct net_device *dev;
int i;
- if (io[0] == 0 && autodetect == 0) {
+ if (io[0] == -1 && autodetect == 0) {
printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");
printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n");
- return 1;
+ return -ENODEV;
}
else if (autodetect) {
/* if autodetect is set then we must force detection */
- io[0] = 0;
+ for (i = 0; i < MAX_EEPRO; i++) {
+ io[i] = 0;
+ }
printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
}
- for (i = 0; i < MAX_EEPRO; i++) {
+ for (i = 0; io[i] != -1 && i < MAX_EEPRO; i++) {
dev = alloc_etherdev(sizeof(struct eepro_local));
if (!dev)
break;
dev->irq = irq[i];
if (do_eepro_probe(dev) == 0) {
- if (register_netdev(dev) == 0) {
- dev_eepro[n_eepro++] = dev;
- continue;
- }
- release_region(dev->base_addr, EEPRO_IO_EXTENT);
+ dev_eepro[n_eepro++] = dev;
+ continue;
}
free_netdev(dev);
break;
return n_eepro ? 0 : -ENODEV;
}
-void
+void __exit
cleanup_module(void)
{
int i;