Commit 4c2ca1d7 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

[PATCH] 2.5 cleanup + 2.4 merge of depca

Yes this is big but 2.4 has been indented, updated and there wasnt a
sane way to deal with it
parent e0209017
...@@ -267,8 +267,7 @@ ...@@ -267,8 +267,7 @@
#include "depca.h" #include "depca.h"
static char version[] __initdata = static char version[] __initdata = "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n";
"depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n";
#ifdef DEPCA_DEBUG #ifdef DEPCA_DEBUG
static int depca_debug = DEPCA_DEBUG; static int depca_debug = DEPCA_DEBUG;
...@@ -276,7 +275,7 @@ static int depca_debug = DEPCA_DEBUG; ...@@ -276,7 +275,7 @@ static int depca_debug = DEPCA_DEBUG;
static int depca_debug = 1; static int depca_debug = 1;
#endif #endif
#define DEPCA_NDA 0xffe0 /* No Device Address */ #define DEPCA_NDA 0xffe0 /* No Device Address */
#define TX_TIMEOUT (1*HZ) #define TX_TIMEOUT (1*HZ)
...@@ -293,15 +292,15 @@ static int depca_debug = 1; ...@@ -293,15 +292,15 @@ static int depca_debug = 1;
** **
** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ) ** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ)
*/ */
#define NUM_RX_DESC 8 /* Number of RX descriptors */ #define NUM_RX_DESC 8 /* Number of RX descriptors */
#define NUM_TX_DESC 8 /* Number of TX descriptors */ #define NUM_TX_DESC 8 /* Number of TX descriptors */
#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */ #define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */
#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */ #define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */
/* /*
** EISA bus defines ** EISA bus defines
*/ */
#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */ #define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */
#define MAX_EISA_SLOTS 16 #define MAX_EISA_SLOTS 16
#define EISA_SLOT_INC 0x1000 #define EISA_SLOT_INC 0x1000
...@@ -328,7 +327,7 @@ static short mem_chkd; ...@@ -328,7 +327,7 @@ static short mem_chkd;
"DE422",\ "DE422",\
""} ""}
static enum { static enum {
DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
} adapter; } adapter;
/* /*
...@@ -340,81 +339,81 @@ static enum { ...@@ -340,81 +339,81 @@ static enum {
/* /*
** Memory Alignment. Each descriptor is 4 longwords long. To force a ** Memory Alignment. Each descriptor is 4 longwords long. To force a
** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and ** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
** DESC_ALIGN. ALIGN aligns the start address of the private memory area ** DESC_ALIGN. DEPCA_ALIGN aligns the start address of the private memory area
** and hence the RX descriptor ring's first entry. ** and hence the RX descriptor ring's first entry.
*/ */
#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */ #define DEPCA_ALIGN4 ((u_long)4 - 1) /* 1 longword align */
#define ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */ #define DEPCA_ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */
#define ALIGN ALIGN8 /* Keep the LANCE happy... */ #define DEPCA_ALIGN DEPCA_ALIGN8 /* Keep the LANCE happy... */
/* /*
** The DEPCA Rx and Tx ring descriptors. ** The DEPCA Rx and Tx ring descriptors.
*/ */
struct depca_rx_desc { struct depca_rx_desc {
volatile s32 base; volatile s32 base;
s16 buf_length; /* This length is negative 2's complement! */ s16 buf_length; /* This length is negative 2's complement! */
s16 msg_length; /* This length is "normal". */ s16 msg_length; /* This length is "normal". */
}; };
struct depca_tx_desc { struct depca_tx_desc {
volatile s32 base; volatile s32 base;
s16 length; /* This length is negative 2's complement! */ s16 length; /* This length is negative 2's complement! */
s16 misc; /* Errors and TDR info */ s16 misc; /* Errors and TDR info */
}; };
#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM #define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM
to LANCE memory address space */ to LANCE memory address space */
/* /*
** The Lance initialization block, described in databook, in common memory. ** The Lance initialization block, described in databook, in common memory.
*/ */
struct depca_init { struct depca_init {
u16 mode; /* Mode register */ u16 mode; /* Mode register */
u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */ u8 phys_addr[ETH_ALEN]; /* Physical ethernet address */
u8 mcast_table[8]; /* Multicast Hash Table. */ u8 mcast_table[8]; /* Multicast Hash Table. */
u32 rx_ring; /* Rx ring base pointer & ring length */ u32 rx_ring; /* Rx ring base pointer & ring length */
u32 tx_ring; /* Tx ring base pointer & ring length */ u32 tx_ring; /* Tx ring base pointer & ring length */
}; };
#define DEPCA_PKT_STAT_SZ 16 #define DEPCA_PKT_STAT_SZ 16
#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you #define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you
increase DEPCA_PKT_STAT_SZ */ increase DEPCA_PKT_STAT_SZ */
struct depca_private { struct depca_private {
char devname[DEPCA_STRLEN]; /* Device Product String */ char devname[DEPCA_STRLEN]; /* Device Product String */
char adapter_name[DEPCA_STRLEN];/* /proc/ioports string */ char adapter_name[DEPCA_STRLEN]; /* /proc/ioports string */
char adapter; /* Adapter type */ char adapter; /* Adapter type */
char mca_slot; /* MCA slot, if MCA else -1 */ char mca_slot; /* MCA slot, if MCA else -1 */
struct depca_init init_block;/* Shadow Initialization block */ struct depca_init init_block; /* Shadow Initialization block */
/* CPU address space fields */ /* CPU address space fields */
struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */ struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */
struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */ struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */
void *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ void *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */
void *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ void *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */
void *sh_mem; /* CPU mapped virt address of device RAM */ void *sh_mem; /* CPU mapped virt address of device RAM */
/* Device address space fields */ /* Device address space fields */
u_long device_ram_start; /* Start of RAM in device addr space */ u_long device_ram_start; /* Start of RAM in device addr space */
/* Offsets used in both address spaces */ /* Offsets used in both address spaces */
u_long rx_ring_offset; /* Offset from start of RAM to rx_ring */ u_long rx_ring_offset; /* Offset from start of RAM to rx_ring */
u_long tx_ring_offset; /* Offset from start of RAM to tx_ring */ u_long tx_ring_offset; /* Offset from start of RAM to tx_ring */
u_long buffs_offset; /* LANCE Rx and Tx buffers start address. */ u_long buffs_offset; /* LANCE Rx and Tx buffers start address. */
/* Kernel-only (not device) fields */ /* Kernel-only (not device) fields */
int rx_new, tx_new; /* The next free ring entry */ int rx_new, tx_new; /* The next free ring entry */
int rx_old, tx_old; /* The ring entries to be free()ed. */ int rx_old, tx_old; /* The ring entries to be free()ed. */
struct net_device_stats stats; struct net_device_stats stats;
spinlock_t lock; spinlock_t lock;
struct { /* Private stats counters */ struct { /* Private stats counters */
u32 bins[DEPCA_PKT_STAT_SZ]; u32 bins[DEPCA_PKT_STAT_SZ];
u32 unicast; u32 unicast;
u32 multicast; u32 multicast;
u32 broadcast; u32 broadcast;
u32 excessive_collisions; u32 excessive_collisions;
u32 tx_underruns; u32 tx_underruns;
u32 excessive_underruns; u32 excessive_underruns;
} pktStats; } pktStats;
int txRingMask; /* TX ring mask */ int txRingMask; /* TX ring mask */
int rxRingMask; /* RX ring mask */ int rxRingMask; /* RX ring mask */
s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */ s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */
s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */ s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */
}; };
/* /*
...@@ -431,61 +430,61 @@ struct depca_private { ...@@ -431,61 +430,61 @@ struct depca_private {
/* /*
** Public Functions ** Public Functions
*/ */
static int depca_open(struct net_device *dev); static int depca_open(struct net_device *dev);
static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev); static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int depca_close(struct net_device *dev); static int depca_close(struct net_device *dev);
static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void depca_tx_timeout (struct net_device *dev); static void depca_tx_timeout(struct net_device *dev);
static struct net_device_stats *depca_get_stats(struct net_device *dev); static struct net_device_stats *depca_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev); static void set_multicast_list(struct net_device *dev);
/* /*
** Private functions ** Private functions
*/ */
static int depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot); static int depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot);
static void depca_init_ring(struct net_device *dev); static void depca_init_ring(struct net_device *dev);
static int depca_rx(struct net_device *dev); static int depca_rx(struct net_device *dev);
static int depca_tx(struct net_device *dev); static int depca_tx(struct net_device *dev);
static void LoadCSRs(struct net_device *dev); static void LoadCSRs(struct net_device *dev);
static int InitRestartDepca(struct net_device *dev); static int InitRestartDepca(struct net_device *dev);
static void DepcaSignature(char *name, u_long paddr); static void DepcaSignature(char *name, u_long paddr);
static int DevicePresent(u_long ioaddr); static int DevicePresent(u_long ioaddr);
static int get_hw_addr(struct net_device *dev); static int get_hw_addr(struct net_device *dev);
static int EISA_signature(char *name, s32 eisa_id); static int EISA_signature(char *name, s32 eisa_id);
static void SetMulticastFilter(struct net_device *dev); static void SetMulticastFilter(struct net_device *dev);
static void isa_probe(struct net_device *dev, u_long iobase); static void isa_probe(struct net_device *dev, u_long iobase);
static void eisa_probe(struct net_device *dev, u_long iobase); static void eisa_probe(struct net_device *dev, u_long iobase);
#ifdef CONFIG_MCA #ifdef CONFIG_MCA
static void mca_probe(struct net_device *dev, u_long iobase); static void mca_probe(struct net_device *dev, u_long iobase);
#endif #endif
static struct net_device *alloc_device(struct net_device *dev, u_long iobase); static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
static int depca_dev_index(char *s); static int depca_dev_index(char *s);
static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *)); static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *));
static int load_packet(struct net_device *dev, struct sk_buff *skb); static int load_packet(struct net_device *dev, struct sk_buff *skb);
static void depca_dbg_open(struct net_device *dev); static void depca_dbg_open(struct net_device *dev);
#ifdef MODULE #ifdef MODULE
int init_module(void); int init_module(void);
void cleanup_module(void); void cleanup_module(void);
static int autoprobed = 1, loading_module = 1; static int autoprobed = 1, loading_module = 1;
# else # else
static u_char de1xx_irq[] __initdata = {2,3,4,5,7,9,0}; static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 };
static u_char de2xx_irq[] __initdata = {5,9,10,11,15,0}; static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 };
static u_char de422_irq[] __initdata = {5,9,10,11,0}; static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 };
static u_char *depca_irq; static u_char *depca_irq;
static int autoprobed, loading_module; static int autoprobed, loading_module;
#endif /* MODULE */ #endif /* MODULE */
static char name[DEPCA_STRLEN]; static char name[DEPCA_STRLEN];
static int num_depcas, num_eth; static int num_depcas, num_eth;
static int mem; /* For loadable module assignment static int mem; /* For loadable module assignment
use insmod mem=0x????? .... */ use insmod mem=0x????? .... */
static char *adapter_name; /* = '\0'; If no PROM when loadable module static char *adapter_name; /* = '\0'; If no PROM when loadable module
use insmod adapter_name=DE??? ... use insmod adapter_name=DE??? ...
bss initializes this to zero bss initializes this to zero
*/ */
/* /*
** Miscellaneous defines... ** Miscellaneous defines...
*/ */
...@@ -493,49 +492,48 @@ static char *adapter_name; /* = '\0'; If no PROM when loadable module ...@@ -493,49 +492,48 @@ static char *adapter_name; /* = '\0'; If no PROM when loadable module
outw(CSR0, DEPCA_ADDR);\ outw(CSR0, DEPCA_ADDR);\
outw(STOP, DEPCA_DATA) outw(STOP, DEPCA_DATA)
int __init int __init depca_probe(struct net_device *dev)
depca_probe(struct net_device *dev)
{ {
int tmp = num_depcas, status = -ENODEV; int tmp = num_depcas, status = -ENODEV;
u_long iobase = dev->base_addr; u_long iobase = dev->base_addr;
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
if ((iobase == 0) && loading_module){ if ((iobase == 0) && loading_module) {
printk("Autoprobing is not supported when loading a module based driver.\n"); printk("Autoprobing is not supported when loading a module based driver.\n");
status = -EIO; status = -EIO;
} else { } else {
#ifdef CONFIG_MCA #ifdef CONFIG_MCA
mca_probe(dev, iobase); mca_probe(dev, iobase);
#endif #endif
isa_probe(dev, iobase); isa_probe(dev, iobase);
eisa_probe(dev, iobase); eisa_probe(dev, iobase);
if ((tmp == num_depcas) && (iobase != 0) && loading_module) { if ((tmp == num_depcas) && (iobase != 0) && loading_module) {
printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase);
iobase); }
}
/*
** Walk the device list to check that at least one device
** initialised OK
*/
for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next);
if (dev->priv) status = 0; /*
if (iobase == 0) autoprobed = 1; ** Walk the device list to check that at least one device
} ** initialised OK
*/
for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next);
if (dev->priv)
status = 0;
if (iobase == 0)
autoprobed = 1;
}
return status; return status;
} }
static int __init static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
{ {
struct depca_private *lp; struct depca_private *lp;
int i, j, offset, netRAM, mem_len, status=0; int i, j, offset, netRAM, mem_len, status = 0;
s16 nicsr; s16 nicsr;
u_long mem_start=0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
STOP_DEPCA; STOP_DEPCA;
...@@ -553,19 +551,17 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -553,19 +551,17 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
DepcaSignature(name, mem_start); DepcaSignature(name, mem_start);
} while (!mem && mem_base[mem_chkd] && (adapter == unknown)); } while (!mem && mem_base[mem_chkd] && (adapter == unknown));
if ((adapter == unknown) || !mem_start) { /* DEPCA device not found */ if ((adapter == unknown) || !mem_start) { /* DEPCA device not found */
return -ENXIO; return -ENXIO;
} }
dev->base_addr = ioaddr; dev->base_addr = ioaddr;
if (mca_slot != -1) { if (mca_slot != -1) {
printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot);
ioaddr, mca_slot); } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */
} else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f));
printk("%s: %s at 0x%04lx (EISA slot %d)", } else { /* ISA port address */
dev->name, name, ioaddr, (int)((ioaddr>>12)&0x0f));
} else { /* ISA port address */
printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); printk("%s: %s at 0x%04lx", dev->name, name, ioaddr);
} }
...@@ -575,7 +571,7 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -575,7 +571,7 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
printk(" which has an Ethernet PROM CRC error.\n"); printk(" which has an Ethernet PROM CRC error.\n");
return -ENXIO; return -ENXIO;
} }
for (i=0; i<ETH_ALEN - 1; i++) { /* get the ethernet address */ for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet address */
printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x:", dev->dev_addr[i]);
} }
printk("%2.2x", dev->dev_addr[i]); printk("%2.2x", dev->dev_addr[i]);
...@@ -586,19 +582,16 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -586,19 +582,16 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
netRAM = 128; netRAM = 128;
offset = 0x0000; offset = 0x0000;
/* Shared Memory Base Address */ /* Shared Memory Base Address */
if (nicsr & BUF) { if (nicsr & BUF) {
offset = 0x8000; /* 32kbyte RAM offset*/ offset = 0x8000; /* 32kbyte RAM offset */
nicsr &= ~BS; /* DEPCA RAM in top 32k */ nicsr &= ~BS; /* DEPCA RAM in top 32k */
netRAM -= 32; netRAM -= 32;
} }
mem_start += offset; /* (E)ISA start address */ mem_start += offset; /* (E)ISA start address */
if ((mem_len = (NUM_RX_DESC*(sizeof(struct depca_rx_desc)+RX_BUFF_SZ) + if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init)))
NUM_TX_DESC*(sizeof(struct depca_tx_desc)+TX_BUFF_SZ) + > (netRAM << 10)) {
sizeof(struct depca_init))) printk(",\n requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM);
> (netRAM<<10)) {
printk(",\n requests %dkB RAM: only %dkB is available!\n",
(mem_len >> 10), netRAM);
return -ENXIO; return -ENXIO;
} }
...@@ -609,21 +602,20 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -609,21 +602,20 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
nicsr |= SHE; nicsr |= SHE;
outb(nicsr, DEPCA_NICSR); outb(nicsr, DEPCA_NICSR);
} }
/* Define the device private memory */ /* Define the device private memory */
dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL);
if (dev->priv == NULL) if (dev->priv == NULL)
return -ENOMEM; return -ENOMEM;
lp = (struct depca_private *)dev->priv; lp = (struct depca_private *) dev->priv;
memset((char *)dev->priv, 0, sizeof(struct depca_private)); memset((char *) dev->priv, 0, sizeof(struct depca_private));
lp->adapter = adapter; lp->adapter = adapter;
lp->mca_slot = mca_slot; lp->mca_slot = mca_slot;
lp->lock = SPIN_LOCK_UNLOCKED; lp->lock = SPIN_LOCK_UNLOCKED;
sprintf(lp->adapter_name,"%s (%s)", name, dev->name); sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
status = -EBUSY; status = -EBUSY;
if (!request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name)) { if (!request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name)) {
printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n", printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n", DEPCA_TOTAL_SIZE, ioaddr);
DEPCA_TOTAL_SIZE, ioaddr);
goto out_priv; goto out_priv;
} }
...@@ -635,17 +627,17 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -635,17 +627,17 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
goto out_region; goto out_region;
} }
lp->device_ram_start = mem_start & LA_MASK; lp->device_ram_start = mem_start & LA_MASK;
offset = 0; offset = 0;
offset += sizeof(struct depca_init); offset += sizeof(struct depca_init);
/* Tx & Rx descriptors (aligned to a quadword boundary) */ /* Tx & Rx descriptors (aligned to a quadword boundary) */
offset = (offset + ALIGN) & ~ALIGN; offset = (offset + DEPCA_ALIGN) & ~DEPCA_ALIGN;
lp->rx_ring = (struct depca_rx_desc *)(lp->sh_mem + offset); lp->rx_ring = (struct depca_rx_desc *) (lp->sh_mem + offset);
lp->rx_ring_offset = offset; lp->rx_ring_offset = offset;
offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC); offset += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
lp->tx_ring = (struct depca_tx_desc *)(lp->sh_mem + offset); lp->tx_ring = (struct depca_tx_desc *) (lp->sh_mem + offset);
lp->tx_ring_offset = offset; lp->tx_ring_offset = offset;
offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC); offset += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
...@@ -657,14 +649,14 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -657,14 +649,14 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
lp->txRingMask = NUM_TX_DESC - 1; lp->txRingMask = NUM_TX_DESC - 1;
/* Calculate Tx/Rx RLEN size for the descriptors. */ /* Calculate Tx/Rx RLEN size for the descriptors. */
for (i=0, j = lp->rxRingMask; j>0; i++) { for (i = 0, j = lp->rxRingMask; j > 0; i++) {
j >>= 1; j >>= 1;
} }
lp->rx_rlen = (s32)(i << 29); lp->rx_rlen = (s32) (i << 29);
for (i=0, j = lp->txRingMask; j>0; i++) { for (i = 0, j = lp->txRingMask; j > 0; i++) {
j >>= 1; j >>= 1;
} }
lp->tx_rlen = (s32)(i << 29); lp->tx_rlen = (s32) (i << 29);
/* Load the initialisation block */ /* Load the initialisation block */
depca_init_ring(dev); depca_init_ring(dev);
...@@ -673,7 +665,7 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -673,7 +665,7 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
LoadCSRs(dev); LoadCSRs(dev);
/* Enable DEPCA board interrupts for autoprobing */ /* Enable DEPCA board interrupts for autoprobing */
nicsr = ((nicsr & ~IM)|IEN); nicsr = ((nicsr & ~IM) | IEN);
outb(nicsr, DEPCA_NICSR); outb(nicsr, DEPCA_NICSR);
/* To auto-IRQ we enable the initialization-done and DMA err, /* To auto-IRQ we enable the initialization-done and DMA err,
...@@ -706,9 +698,10 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -706,9 +698,10 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
/* Trigger an initialization just for the interrupt. */ /* Trigger an initialization just for the interrupt. */
outw(INEA | INIT, DEPCA_DATA); outw(INEA | INIT, DEPCA_DATA);
delay = jiffies + HZ/50; delay = jiffies + HZ/50;
while (time_before(jiffies, delay)) ; while (time_before(jiffies, delay))
yield();
irqnum = probe_irq_off(irq_mask); irqnum = probe_irq_off(irq_mask);
status = -ENXIO; status = -ENXIO;
...@@ -716,19 +709,19 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -716,19 +709,19 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
printk(" and failed to detect IRQ line.\n"); printk(" and failed to detect IRQ line.\n");
goto out_region; goto out_region;
} else { } else {
for (dev->irq=0,i=0; (depca_irq[i]) && (!dev->irq); i++) for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++)
if (irqnum == depca_irq[i]) { if (irqnum == depca_irq[i]) {
dev->irq = irqnum; dev->irq = irqnum;
printk(" and uses IRQ%d.\n", dev->irq); printk(" and uses IRQ%d.\n", dev->irq);
} }
status = -ENXIO; status = -ENXIO;
if (!dev->irq) { if (!dev->irq) {
printk(" but incorrect IRQ line detected.\n"); printk(" but incorrect IRQ line detected.\n");
goto out_region; goto out_region;
} }
} }
#endif /* MODULE */ #endif /* MODULE */
} else { } else {
printk(" and assigned IRQ%d.\n", dev->irq); printk(" and assigned IRQ%d.\n", dev->irq);
} }
...@@ -752,65 +745,63 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot) ...@@ -752,65 +745,63 @@ depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
/* Fill in the generic field of the device structure. */ /* Fill in the generic field of the device structure. */
ether_setup(dev); ether_setup(dev);
return 0; return 0;
out_region: out_region:
release_region(ioaddr, DEPCA_TOTAL_SIZE); release_region(ioaddr, DEPCA_TOTAL_SIZE);
out_priv: out_priv:
kfree(dev->priv); kfree(dev->priv);
dev->priv = NULL; dev->priv = NULL;
return status; return status;
} }
static int
depca_open(struct net_device *dev) static int depca_open(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
s16 nicsr; s16 nicsr;
int status = 0; int status = 0;
STOP_DEPCA; STOP_DEPCA;
nicsr = inb(DEPCA_NICSR); nicsr = inb(DEPCA_NICSR);
/* Make sure the shadow RAM is enabled */ /* Make sure the shadow RAM is enabled */
if (lp->adapter != DEPCA) { if (lp->adapter != DEPCA) {
nicsr |= SHE; nicsr |= SHE;
outb(nicsr, DEPCA_NICSR); outb(nicsr, DEPCA_NICSR);
} }
/* Re-initialize the DEPCA... */ /* Re-initialize the DEPCA... */
depca_init_ring(dev); depca_init_ring(dev);
LoadCSRs(dev); LoadCSRs(dev);
depca_dbg_open(dev); depca_dbg_open(dev);
if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) { if (request_irq(dev->irq, &depca_interrupt, 0, lp->adapter_name, dev)) {
printk("depca_open(): Requested IRQ%d is busy\n",dev->irq); printk("depca_open(): Requested IRQ%d is busy\n", dev->irq);
status = -EAGAIN; status = -EAGAIN;
} else { } else {
/* Enable DEPCA board interrupts and turn off LED */ /* Enable DEPCA board interrupts and turn off LED */
nicsr = ((nicsr & ~IM & ~LED)|IEN); nicsr = ((nicsr & ~IM & ~LED) | IEN);
outb(nicsr, DEPCA_NICSR); outb(nicsr, DEPCA_NICSR);
outw(CSR0,DEPCA_ADDR); outw(CSR0, DEPCA_ADDR);
netif_start_queue(dev); netif_start_queue(dev);
status = InitRestartDepca(dev); status = InitRestartDepca(dev);
if (depca_debug > 1){ if (depca_debug > 1) {
printk("CSR0: 0x%4.4x\n",inw(DEPCA_DATA)); printk("CSR0: 0x%4.4x\n", inw(DEPCA_DATA));
printk("nicsr: 0x%02x\n",inb(DEPCA_NICSR)); printk("nicsr: 0x%02x\n", inb(DEPCA_NICSR));
} }
} }
return status; return status;
} }
/* Initialize the lance Rx and Tx descriptor rings. */ /* Initialize the lance Rx and Tx descriptor rings. */
static void static void depca_init_ring(struct net_device *dev)
depca_init_ring(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
u_int i; u_int i;
u_long offset; u_long offset;
...@@ -822,17 +813,15 @@ depca_init_ring(struct net_device *dev) ...@@ -822,17 +813,15 @@ depca_init_ring(struct net_device *dev)
/* Initialize the base address and length of each buffer in the ring */ /* Initialize the base address and length of each buffer in the ring */
for (i = 0; i <= lp->rxRingMask; i++) { for (i = 0; i <= lp->rxRingMask; i++) {
offset = lp->buffs_offset + i*RX_BUFF_SZ; offset = lp->buffs_offset + i * RX_BUFF_SZ;
writel((lp->device_ram_start + offset) | R_OWN, writel((lp->device_ram_start + offset) | R_OWN, &lp->rx_ring[i].base);
&lp->rx_ring[i].base);
writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length); writew(-RX_BUFF_SZ, &lp->rx_ring[i].buf_length);
lp->rx_buff[i] = lp->sh_mem + offset; lp->rx_buff[i] = lp->sh_mem + offset;
} }
for (i = 0; i <= lp->txRingMask; i++) { for (i = 0; i <= lp->txRingMask; i++) {
offset = lp->buffs_offset + (i + lp->rxRingMask+1)*TX_BUFF_SZ; offset = lp->buffs_offset + (i + lp->rxRingMask + 1) * TX_BUFF_SZ;
writel((lp->device_ram_start + offset) & 0x00ffffff, writel((lp->device_ram_start + offset) & 0x00ffffff, &lp->tx_ring[i].base);
&lp->tx_ring[i].base);
lp->tx_buff[i] = lp->sh_mem + offset; lp->tx_buff[i] = lp->sh_mem + offset;
} }
...@@ -846,30 +835,29 @@ depca_init_ring(struct net_device *dev) ...@@ -846,30 +835,29 @@ depca_init_ring(struct net_device *dev)
lp->init_block.phys_addr[i] = dev->dev_addr[i]; lp->init_block.phys_addr[i] = dev->dev_addr[i];
} }
lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */
} }
static void depca_tx_timeout (struct net_device *dev) static void depca_tx_timeout(struct net_device *dev)
{ {
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
printk ("%s: transmit timed out, status %04x, resetting.\n", printk("%s: transmit timed out, status %04x, resetting.\n", dev->name, inw(DEPCA_DATA));
dev->name, inw (DEPCA_DATA));
STOP_DEPCA; STOP_DEPCA;
depca_init_ring (dev); depca_init_ring(dev);
LoadCSRs (dev); LoadCSRs(dev);
dev->trans_start = jiffies; dev->trans_start = jiffies;
netif_wake_queue (dev); netif_wake_queue(dev);
InitRestartDepca (dev); InitRestartDepca(dev);
} }
/* /*
** Writes a socket buffer to TX descriptor ring and starts transmission ** Writes a socket buffer to TX descriptor ring and starts transmission
*/ */
static int depca_start_xmit (struct sk_buff *skb, struct net_device *dev) static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *) dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
...@@ -879,32 +867,32 @@ static int depca_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -879,32 +867,32 @@ static int depca_start_xmit (struct sk_buff *skb, struct net_device *dev)
if (skb->len < 1) if (skb->len < 1)
goto out; goto out;
netif_stop_queue (dev); netif_stop_queue(dev);
if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */
status = load_packet (dev, skb); status = load_packet(dev, skb);
if (!status) { if (!status) {
/* Trigger an immediate send demand. */ /* Trigger an immediate send demand. */
outw (CSR0, DEPCA_ADDR); outw(CSR0, DEPCA_ADDR);
outw (INEA | TDMD, DEPCA_DATA); outw(INEA | TDMD, DEPCA_DATA);
dev->trans_start = jiffies; dev->trans_start = jiffies;
dev_kfree_skb (skb); dev_kfree_skb(skb);
} }
if (TX_BUFFS_AVAIL) if (TX_BUFFS_AVAIL)
netif_start_queue (dev); netif_start_queue(dev);
} else } else
status = -1; status = -1;
out: out:
return status; return status;
} }
/* /*
** The DEPCA interrupt handler. ** The DEPCA interrupt handler.
*/ */
static void depca_interrupt (int irq, void *dev_id, struct pt_regs *regs) static void depca_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
struct depca_private *lp; struct depca_private *lp;
...@@ -912,308 +900,301 @@ static void depca_interrupt (int irq, void *dev_id, struct pt_regs *regs) ...@@ -912,308 +900,301 @@ static void depca_interrupt (int irq, void *dev_id, struct pt_regs *regs)
u_long ioaddr; u_long ioaddr;
if (dev == NULL) { if (dev == NULL) {
printk ("depca_interrupt(): irq %d for unknown device.\n", irq); printk("depca_interrupt(): irq %d for unknown device.\n", irq);
return; return;
} }
lp = (struct depca_private *) dev->priv; lp = (struct depca_private *) dev->priv;
ioaddr = dev->base_addr; ioaddr = dev->base_addr;
spin_lock (&lp->lock); spin_lock(&lp->lock);
/* mask the DEPCA board interrupts and turn on the LED */ /* mask the DEPCA board interrupts and turn on the LED */
nicsr = inb (DEPCA_NICSR); nicsr = inb(DEPCA_NICSR);
nicsr |= (IM | LED); nicsr |= (IM | LED);
outb (nicsr, DEPCA_NICSR); outb(nicsr, DEPCA_NICSR);
outw (CSR0, DEPCA_ADDR); outw(CSR0, DEPCA_ADDR);
csr0 = inw (DEPCA_DATA); csr0 = inw(DEPCA_DATA);
/* Acknowledge all of the current interrupt sources ASAP. */ /* Acknowledge all of the current interrupt sources ASAP. */
outw (csr0 & INTE, DEPCA_DATA); outw(csr0 & INTE, DEPCA_DATA);
if (csr0 & RINT) /* Rx interrupt (packet arrived) */ if (csr0 & RINT) /* Rx interrupt (packet arrived) */
depca_rx (dev); depca_rx(dev);
if (csr0 & TINT) /* Tx interrupt (packet sent) */ if (csr0 & TINT) /* Tx interrupt (packet sent) */
depca_tx (dev); depca_tx(dev);
/* Any resources available? */ /* Any resources available? */
if ((TX_BUFFS_AVAIL >= 0) && netif_queue_stopped(dev)) { if ((TX_BUFFS_AVAIL >= 0) && netif_queue_stopped(dev)) {
netif_wake_queue (dev); netif_wake_queue(dev);
} }
/* Unmask the DEPCA board interrupts and turn off the LED */ /* Unmask the DEPCA board interrupts and turn off the LED */
nicsr = (nicsr & ~IM & ~LED); nicsr = (nicsr & ~IM & ~LED);
outb (nicsr, DEPCA_NICSR); outb(nicsr, DEPCA_NICSR);
spin_unlock (&lp->lock); spin_unlock(&lp->lock);
} }
static int static int depca_rx(struct net_device *dev)
depca_rx(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
int i, entry; int i, entry;
s32 status; s32 status;
for (entry=lp->rx_new; for (entry = lp->rx_new; !(readl(&lp->rx_ring[entry].base) & R_OWN); entry = lp->rx_new) {
!(readl(&lp->rx_ring[entry].base) & R_OWN); status = readl(&lp->rx_ring[entry].base) >> 16;
entry=lp->rx_new){ if (status & R_STP) { /* Remember start of frame */
status = readl(&lp->rx_ring[entry].base) >> 16 ; lp->rx_old = entry;
if (status & R_STP) { /* Remember start of frame */ }
lp->rx_old = entry; if (status & R_ENP) { /* Valid frame status */
} if (status & R_ERR) { /* There was an error. */
if (status & R_ENP) { /* Valid frame status */ lp->stats.rx_errors++; /* Update the error stats. */
if (status & R_ERR) { /* There was an error. */ if (status & R_FRAM)
lp->stats.rx_errors++; /* Update the error stats. */ lp->stats.rx_frame_errors++;
if (status & R_FRAM) lp->stats.rx_frame_errors++; if (status & R_OFLO)
if (status & R_OFLO) lp->stats.rx_over_errors++; lp->stats.rx_over_errors++;
if (status & R_CRC) lp->stats.rx_crc_errors++; if (status & R_CRC)
if (status & R_BUFF) lp->stats.rx_fifo_errors++; lp->stats.rx_crc_errors++;
} else { if (status & R_BUFF)
short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4; lp->stats.rx_fifo_errors++;
struct sk_buff *skb; } else {
short len, pkt_len = readw(&lp->rx_ring[entry].msg_length) - 4;
skb = dev_alloc_skb(pkt_len+2); struct sk_buff *skb;
if (skb != NULL) {
unsigned char *buf; skb = dev_alloc_skb(pkt_len + 2);
skb_reserve(skb,2); /* 16 byte align the IP header */ if (skb != NULL) {
buf = skb_put(skb,pkt_len); unsigned char *buf;
skb->dev = dev; skb_reserve(skb, 2); /* 16 byte align the IP header */
if (entry < lp->rx_old) { /* Wrapped buffer */ buf = skb_put(skb, pkt_len);
len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ; skb->dev = dev;
memcpy_fromio(buf, lp->rx_buff[lp->rx_old], len); if (entry < lp->rx_old) { /* Wrapped buffer */
memcpy_fromio(buf + len, lp->rx_buff[0], pkt_len-len); len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ;
} else { /* Linear buffer */ memcpy_fromio(buf, lp->rx_buff[lp->rx_old], len);
memcpy_fromio(buf, lp->rx_buff[lp->rx_old], pkt_len); memcpy_fromio(buf + len, lp->rx_buff[0], pkt_len - len);
} } else { /* Linear buffer */
memcpy_fromio(buf, lp->rx_buff[lp->rx_old], pkt_len);
/* }
** Notify the upper protocol layers that there is another
** packet to handle /*
*/ ** Notify the upper protocol layers that there is another
skb->protocol=eth_type_trans(skb,dev); ** packet to handle
netif_rx(skb); */
skb->protocol = eth_type_trans(skb, dev);
/* netif_rx(skb);
** Update stats
*/ /*
dev->last_rx = jiffies; ** Update stats
lp->stats.rx_packets++; */
lp->stats.rx_bytes += pkt_len; dev->last_rx = jiffies;
for (i=1; i<DEPCA_PKT_STAT_SZ-1; i++) { lp->stats.rx_packets++;
if (pkt_len < (i*DEPCA_PKT_BIN_SZ)) { lp->stats.rx_bytes += pkt_len;
lp->pktStats.bins[i]++; for (i = 1; i < DEPCA_PKT_STAT_SZ - 1; i++) {
i = DEPCA_PKT_STAT_SZ; if (pkt_len < (i * DEPCA_PKT_BIN_SZ)) {
} lp->pktStats.bins[i]++;
} i = DEPCA_PKT_STAT_SZ;
if (buf[0] & 0x01) { /* Multicast/Broadcast */ }
if ((*(s16 *)&buf[0] == -1) && }
(*(s16 *)&buf[2] == -1) && if (buf[0] & 0x01) { /* Multicast/Broadcast */
(*(s16 *)&buf[4] == -1)) { if ((*(s16 *) & buf[0] == -1) && (*(s16 *) & buf[2] == -1) && (*(s16 *) & buf[4] == -1)) {
lp->pktStats.broadcast++; lp->pktStats.broadcast++;
} else { } else {
lp->pktStats.multicast++; lp->pktStats.multicast++;
} }
} else if ((*(s16 *)&buf[0] == *(s16 *)&dev->dev_addr[0]) && } else if ((*(s16 *) & buf[0] == *(s16 *) & dev->dev_addr[0]) && (*(s16 *) & buf[2] == *(s16 *) & dev->dev_addr[2]) && (*(s16 *) & buf[4] == *(s16 *) & dev->dev_addr[4])) {
(*(s16 *)&buf[2] == *(s16 *)&dev->dev_addr[2]) && lp->pktStats.unicast++;
(*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) { }
lp->pktStats.unicast++;
} lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */
if (lp->pktStats.bins[0] == 0) { /* Reset counters */
lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ memset((char *) &lp->pktStats, 0, sizeof(lp->pktStats));
if (lp->pktStats.bins[0] == 0) { /* Reset counters */ }
memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats)); } else {
} printk("%s: Memory squeeze, deferring packet.\n", dev->name);
} else { lp->stats.rx_dropped++; /* Really, deferred. */
printk("%s: Memory squeeze, deferring packet.\n", dev->name); break;
lp->stats.rx_dropped++; /* Really, deferred. */ }
break; }
/* Change buffer ownership for this last frame, back to the adapter */
for (; lp->rx_old != entry; lp->rx_old = (++lp->rx_old) & lp->rxRingMask) {
writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, &lp->rx_ring[lp->rx_old].base);
}
writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base);
}
/*
** Update entry information
*/
lp->rx_new = (++lp->rx_new) & lp->rxRingMask;
} }
}
/* Change buffer ownership for this last frame, back to the adapter */ return 0;
for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)&lp->rxRingMask) {
writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN,
&lp->rx_ring[lp->rx_old].base);
}
writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base);
}
/*
** Update entry information
*/
lp->rx_new = (++lp->rx_new) & lp->rxRingMask;
}
return 0;
} }
/* /*
** Buffer sent - check for buffer errors. ** Buffer sent - check for buffer errors.
*/ */
static int static int depca_tx(struct net_device *dev)
depca_tx(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
int entry; int entry;
s32 status; s32 status;
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) {
status = readl(&lp->tx_ring[entry].base) >> 16 ; status = readl(&lp->tx_ring[entry].base) >> 16;
if (status < 0) { /* Packet not yet sent! */ if (status < 0) { /* Packet not yet sent! */
break; break;
} else if (status & T_ERR) { /* An error occurred. */ } else if (status & T_ERR) { /* An error occurred. */
status = readl(&lp->tx_ring[entry].misc); status = readl(&lp->tx_ring[entry].misc);
lp->stats.tx_errors++; lp->stats.tx_errors++;
if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++; if (status & TMD3_RTRY)
if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++; lp->stats.tx_aborted_errors++;
if (status & TMD3_LCOL) lp->stats.tx_window_errors++; if (status & TMD3_LCAR)
if (status & TMD3_UFLO) lp->stats.tx_fifo_errors++; lp->stats.tx_carrier_errors++;
if (status & (TMD3_BUFF | TMD3_UFLO)) { if (status & TMD3_LCOL)
/* Trigger an immediate send demand. */ lp->stats.tx_window_errors++;
outw(CSR0, DEPCA_ADDR); if (status & TMD3_UFLO)
outw(INEA | TDMD, DEPCA_DATA); lp->stats.tx_fifo_errors++;
} if (status & (TMD3_BUFF | TMD3_UFLO)) {
} else if (status & (T_MORE | T_ONE)) { /* Trigger an immediate send demand. */
lp->stats.collisions++; outw(CSR0, DEPCA_ADDR);
} else { outw(INEA | TDMD, DEPCA_DATA);
lp->stats.tx_packets++; }
} } else if (status & (T_MORE | T_ONE)) {
lp->stats.collisions++;
/* Update all the pointers */ } else {
lp->tx_old = (++lp->tx_old) & lp->txRingMask; lp->stats.tx_packets++;
} }
return 0; /* Update all the pointers */
lp->tx_old = (++lp->tx_old) & lp->txRingMask;
}
return 0;
} }
static int static int depca_close(struct net_device *dev)
depca_close(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
s16 nicsr; s16 nicsr;
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
netif_stop_queue(dev); netif_stop_queue(dev);
outw(CSR0, DEPCA_ADDR); outw(CSR0, DEPCA_ADDR);
if (depca_debug > 1) { if (depca_debug > 1) {
printk("%s: Shutting down ethercard, status was %2.2x.\n", printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inw(DEPCA_DATA));
dev->name, inw(DEPCA_DATA)); }
}
/*
/* ** We stop the DEPCA here -- it occasionally polls
** We stop the DEPCA here -- it occasionally polls ** memory if we don't.
** memory if we don't. */
*/ outw(STOP, DEPCA_DATA);
outw(STOP, DEPCA_DATA);
/*
/* ** Give back the ROM in case the user wants to go to DOS
** Give back the ROM in case the user wants to go to DOS */
*/ if (lp->adapter != DEPCA) {
if (lp->adapter != DEPCA) { nicsr = inb(DEPCA_NICSR);
nicsr = inb(DEPCA_NICSR); nicsr &= ~SHE;
nicsr &= ~SHE; outb(nicsr, DEPCA_NICSR);
outb(nicsr, DEPCA_NICSR); }
}
/*
/* ** Free the associated irq
** Free the associated irq */
*/ free_irq(dev->irq, dev);
free_irq(dev->irq, dev); return 0;
return 0;
} }
static void LoadCSRs(struct net_device *dev) static void LoadCSRs(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */
outw((u16)lp->device_ram_start, DEPCA_DATA); outw((u16) lp->device_ram_start, DEPCA_DATA);
outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */
outw((u16)(lp->device_ram_start >> 16), DEPCA_DATA); outw((u16) (lp->device_ram_start >> 16), DEPCA_DATA);
outw(CSR3, DEPCA_ADDR); /* ALE control */ outw(CSR3, DEPCA_ADDR); /* ALE control */
outw(ACON, DEPCA_DATA); outw(ACON, DEPCA_DATA);
outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */
return; return;
} }
static int InitRestartDepca(struct net_device *dev) static int InitRestartDepca(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
int i, status=0; int i, status = 0;
/* Copy the shadow init_block to shared memory */ /* Copy the shadow init_block to shared memory */
memcpy_toio(lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); memcpy_toio(lp->sh_mem, &lp->init_block, sizeof(struct depca_init));
outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */
outw(INIT, DEPCA_DATA); /* initialize DEPCA */ outw(INIT, DEPCA_DATA); /* initialize DEPCA */
/* wait for lance to complete initialisation */ /* wait for lance to complete initialisation */
for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++); for (i = 0; (i < 100) && !(inw(DEPCA_DATA) & IDON); i++);
if (i!=100) { if (i != 100) {
/* clear IDON by writing a "1", enable interrupts and start lance */ /* clear IDON by writing a "1", enable interrupts and start lance */
outw(IDON | INEA | STRT, DEPCA_DATA); outw(IDON | INEA | STRT, DEPCA_DATA);
if (depca_debug > 2) { if (depca_debug > 2) {
printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA));
dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA)); }
} } else {
} else { printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA));
printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", status = -1;
dev->name, i, virt_to_phys(lp->sh_mem), inw(DEPCA_DATA)); }
status = -1;
} return status;
return status;
} }
static struct net_device_stats * static struct net_device_stats *depca_get_stats(struct net_device *dev)
depca_get_stats(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
/* Null body since there is no framing error counter */ /* Null body since there is no framing error counter */
return &lp->stats; return &lp->stats;
} }
/* /*
** Set or clear the multicast filter for this adaptor. ** Set or clear the multicast filter for this adaptor.
*/ */
static void static void set_multicast_list(struct net_device *dev)
set_multicast_list(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
if (dev) { if (dev) {
netif_stop_queue(dev); netif_stop_queue(dev);
while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
STOP_DEPCA; /* Temporarily stop the depca. */ STOP_DEPCA; /* Temporarily stop the depca. */
depca_init_ring(dev); /* Initialize the descriptor rings */ depca_init_ring(dev); /* Initialize the descriptor rings */
if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */
lp->init_block.mode |= PROM; lp->init_block.mode |= PROM;
} else { } else {
SetMulticastFilter(dev); SetMulticastFilter(dev);
lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */
} }
LoadCSRs(dev); /* Reload CSR3 */ LoadCSRs(dev); /* Reload CSR3 */
InitRestartDepca(dev); /* Resume normal operation. */ InitRestartDepca(dev); /* Resume normal operation. */
netif_start_queue(dev); /* Unlock the TX ring */ netif_start_queue(dev); /* Unlock the TX ring */
} }
} }
/* /*
...@@ -1224,274 +1205,277 @@ set_multicast_list(struct net_device *dev) ...@@ -1224,274 +1205,277 @@ set_multicast_list(struct net_device *dev)
*/ */
static void SetMulticastFilter(struct net_device *dev) static void SetMulticastFilter(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
struct dev_mc_list *dmi=dev->mc_list; struct dev_mc_list *dmi = dev->mc_list;
char *addrs; char *addrs;
int i, j, bit, byte; int i, j, bit, byte;
u16 hashcode; u16 hashcode;
u32 crc; u32 crc;
if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */
for (i=0; i<(HASH_TABLE_LEN>>3); i++) { for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) {
lp->init_block.mcast_table[i] = (char)0xff; lp->init_block.mcast_table[i] = (char) 0xff;
} }
} else { } else {
for (i=0; i<(HASH_TABLE_LEN>>3); i++){ /* Clear the multicast table */ for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) { /* Clear the multicast table */
lp->init_block.mcast_table[i]=0; lp->init_block.mcast_table[i] = 0;
} }
/* Add multicast addresses */ /* Add multicast addresses */
for (i=0;i<dev->mc_count;i++) { /* for each address in the list */ for (i = 0; i < dev->mc_count; i++) { /* for each address in the list */
addrs=dmi->dmi_addr; addrs = dmi->dmi_addr;
dmi=dmi->next; dmi = dmi->next;
if ((*addrs & 0x01) == 1) { /* multicast address? */ if ((*addrs & 0x01) == 1) { /* multicast address? */
crc = ether_crc(ETH_ALEN, addrs); crc = ether_crc(ETH_ALEN, addrs);
hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */
for (j=0;j<5;j++) { /* ... in reverse order. */ for (j = 0; j < 5; j++) { /* ... in reverse order. */
hashcode = (hashcode << 1) | ((crc>>=1) & 1); hashcode = (hashcode << 1) | ((crc >>= 1) & 1);
} }
byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ byte = hashcode >> 3; /* bit[3-5] -> byte in filter */
bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */
lp->init_block.mcast_table[byte] |= bit; lp->init_block.mcast_table[byte] |= bit;
} }
} }
} }
return; return;
} }
#ifdef CONFIG_MCA #ifdef CONFIG_MCA
/* /*
** Microchannel bus I/O device probe ** Microchannel bus I/O device probe
*/ */
static void __init static void __init mca_probe(struct net_device *dev, u_long ioaddr)
mca_probe(struct net_device *dev, u_long ioaddr)
{ {
unsigned char pos[2]; unsigned char pos[2];
unsigned char where; unsigned char where;
unsigned long iobase; unsigned long iobase;
int irq; int irq;
int slot = 0; int slot = 0;
/*
** See if we've been here before.
*/
if ((!ioaddr && autoprobed) || (ioaddr && !loading_module)) return;
if (MCA_bus) {
/* /*
** Search for the adapter. If an address has been given, search ** See if we've been here before.
** specifically for the card at that address. Otherwise find the */
** first card in the system. if ((!ioaddr && autoprobed) || (ioaddr && !loading_module))
*/
while ((dev!=NULL) &&
((slot=mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) {
pos[0] = mca_read_stored_pos(slot, 2);
pos[1] = mca_read_stored_pos(slot, 3);
/*
** IO of card is handled by bits 1 and 2 of pos0.
**
** bit2 bit1 IO
** 0 0 0x2c00
** 0 1 0x2c10
** 1 0 0x2c20
** 1 1 0x2c30
*/
where = (pos[0] & 6) >> 1;
iobase = 0x2c00 + (0x10 * where);
if ((ioaddr) && (ioaddr != iobase)) {
/*
** Card was found, but not at the right IO location. Continue
** scanning from the next MCA slot up for another card.
*/
slot++;
continue;
}
/*
** Found the adapter we were looking for. Now start setting it up.
**
** First work on decoding the IRQ. It's stored in the lower 4 bits
** of pos1. Bits are as follows (from the ADF file):
**
** Bits
** 3 2 1 0 IRQ
** --------------------
** 0 0 1 0 5
** 0 0 0 1 9
** 0 1 0 0 10
** 1 0 0 0 11
**/
where = pos[1] & 0x0f;
switch(where) {
case 1:
irq = 9;
break;
case 2:
irq = 5;
break;
case 4:
irq = 10;
break;
case 8:
irq = 11;
break;
default:
printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where);
return; return;
}
if (MCA_bus) {
/*
** Shared memory address of adapter is stored in bits 3-5 of pos0.
** They are mapped as follows:
**
** Bit
** 5 4 3 Memory Addresses
** 0 0 0 C0000-CFFFF (64K)
** 1 0 0 C8000-CFFFF (32K)
** 0 0 1 D0000-DFFFF (64K)
** 1 0 1 D8000-DFFFF (32K)
** 0 1 0 E0000-EFFFF (64K)
** 1 1 0 E8000-EFFFF (32K)
*/
where = (pos[0] & 0x18) >> 3;
mem = 0xc0000 + (where * 0x10000);
if (pos[0] & 0x20) {
mem += 0x8000;
}
/*
** Get everything allocated and initialized... (almost just
** like the ISA and EISA probes)
*/
if (DevicePresent(iobase) != 0) {
/* /*
** If the MCA configuration says the card should be here, ** Search for the adapter. If an address has been given, search
** it really should be here. ** specifically for the card at that address. Otherwise find the
*/ ** first card in the system.
printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not */
responding.\n", dev->name, iobase); while ((dev != NULL) && ((slot = mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) {
} pos[0] = mca_read_stored_pos(slot, 2);
pos[1] = mca_read_stored_pos(slot, 3);
if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) {
if ((dev = alloc_device(dev, iobase)) != NULL) { /*
dev->irq = irq; ** IO of card is handled by bits 1 and 2 of pos0.
if (depca_hw_init(dev, iobase, slot) == 0) { **
** bit2 bit1 IO
** 0 0 0x2c00
** 0 1 0x2c10
** 1 0 0x2c20
** 1 1 0x2c30
*/
where = (pos[0] & 6) >> 1;
iobase = 0x2c00 + (0x10 * where);
if ((ioaddr) && (ioaddr != iobase)) {
/*
** Card was found, but not at the right IO location. Continue
** scanning from the next MCA slot up for another card.
*/
slot++;
continue;
}
/*
** Found the adapter we were looking for. Now start setting it up.
**
** First work on decoding the IRQ. It's stored in the lower 4 bits
** of pos1. Bits are as follows (from the ADF file):
**
** Bits
** 3 2 1 0 IRQ
** --------------------
** 0 0 1 0 5
** 0 0 0 1 9
** 0 1 0 0 10
** 1 0 0 0 11
* */
where = pos[1] & 0x0f;
switch (where) {
case 1:
irq = 9;
break;
case 2:
irq = 5;
break;
case 4:
irq = 10;
break;
case 8:
irq = 11;
break;
default:
printk("%s: mca_probe IRQ error. You should never get here (%d).\n", dev->name, where);
return;
}
/*
** Shared memory address of adapter is stored in bits 3-5 of pos0.
** They are mapped as follows:
**
** Bit
** 5 4 3 Memory Addresses
** 0 0 0 C0000-CFFFF (64K)
** 1 0 0 C8000-CFFFF (32K)
** 0 0 1 D0000-DFFFF (64K)
** 1 0 1 D8000-DFFFF (32K)
** 0 1 0 E0000-EFFFF (64K)
** 1 1 0 E8000-EFFFF (32K)
*/
where = (pos[0] & 0x18) >> 3;
mem = 0xc0000 + (where * 0x10000);
if (pos[0] & 0x20) {
mem += 0x8000;
}
/* /*
** Adapter initialized correctly: Name it in ** Get everything allocated and initialized... (almost just
** /proc/mca. ** like the ISA and EISA probes)
*/ */
mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); if (DevicePresent(iobase) != 0) {
mca_mark_as_used(slot); /*
num_depcas++; ** If the MCA configuration says the card should be here,
} ** it really should be here.
num_eth++; */
printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase);
}
if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) {
if ((dev = alloc_device(dev, iobase)) != NULL) {
dev->irq = irq;
if (depca_hw_init(dev, iobase, slot) == 0) {
/*
** Adapter initialized correctly: Name it in
** /proc/mca.
*/
mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter");
mca_mark_as_used(slot);
num_depcas++;
}
num_eth++;
}
} else if (autoprobed) {
printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
}
/*
** If this is a probe by a module, return after setting up the
** given card.
*/
if (ioaddr)
return;
/*
** Set up to check the next slot and loop.
*/
slot++;
} }
} else if (autoprobed) {
printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
}
/*
** If this is a probe by a module, return after setting up the
** given card.
*/
if (ioaddr) return;
/*
** Set up to check the next slot and loop.
*/
slot++;
} }
}
return; return;
} }
#endif #endif
/* /*
** ISA bus I/O device probe ** ISA bus I/O device probe
*/ */
static void __init static void __init isa_probe(struct net_device *dev, u_long ioaddr)
isa_probe(struct net_device *dev, u_long ioaddr)
{ {
int i = num_depcas, maxSlots; int i = num_depcas, maxSlots;
s32 ports[] = DEPCA_IO_PORTS; s32 ports[] = DEPCA_IO_PORTS;
if (!ioaddr && autoprobed) return ; /* Been here before ! */ if (!ioaddr && autoprobed)
if (ioaddr > 0x400) return; /* EISA Address */ return; /* Been here before ! */
if (i >= MAX_NUM_DEPCAS) return; /* Too many ISA adapters */ if (ioaddr > 0x400)
return; /* EISA Address */
if (ioaddr == 0) { /* Autoprobing */ if (i >= MAX_NUM_DEPCAS)
maxSlots = MAX_NUM_DEPCAS; return; /* Too many ISA adapters */
} else { /* Probe a specific location */
ports[i] = ioaddr; if (ioaddr == 0) { /* Autoprobing */
maxSlots = i + 1; maxSlots = MAX_NUM_DEPCAS;
} } else { /* Probe a specific location */
ports[i] = ioaddr;
for (; (i<maxSlots) && (dev!=NULL) && ports[i]; i++) { maxSlots = i + 1;
if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) {
if (DevicePresent(ports[i]) == 0) {
if ((dev = alloc_device(dev, ports[i])) != NULL) {
if (depca_hw_init(dev, ports[i], -1) == 0) {
num_depcas++;
}
num_eth++;
} }
}
} else if (autoprobed) {
printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]);
}
}
return; for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) {
if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) {
if (DevicePresent(ports[i]) == 0) {
if ((dev = alloc_device(dev, ports[i])) != NULL) {
if (depca_hw_init(dev, ports[i], -1) == 0) {
num_depcas++;
}
num_eth++;
}
}
} else if (autoprobed) {
printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]);
}
}
return;
} }
/* /*
** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
** the motherboard. Upto 15 EISA devices are supported. ** the motherboard. Upto 15 EISA devices are supported.
*/ */
static void __init static void __init eisa_probe(struct net_device *dev, u_long ioaddr)
eisa_probe(struct net_device *dev, u_long ioaddr)
{ {
int i, maxSlots; int i, maxSlots;
u_long iobase; u_long iobase;
char name[DEPCA_STRLEN]; char name[DEPCA_STRLEN];
if (!ioaddr && autoprobed) return ; /* Been here before ! */ if (!ioaddr && autoprobed)
if ((ioaddr < 0x400) && (ioaddr > 0)) return; /* ISA Address */ return; /* Been here before ! */
if ((ioaddr < 0x400) && (ioaddr > 0))
if (ioaddr == 0) { /* Autoprobing */ return; /* ISA Address */
iobase = EISA_SLOT_INC; /* Get the first slot address */
i = 1; if (ioaddr == 0) { /* Autoprobing */
maxSlots = MAX_EISA_SLOTS; iobase = EISA_SLOT_INC; /* Get the first slot address */
} else { /* Probe a specific location */ i = 1;
iobase = ioaddr; maxSlots = MAX_EISA_SLOTS;
i = (ioaddr >> 12); } else { /* Probe a specific location */
maxSlots = i + 1; iobase = ioaddr;
} i = (ioaddr >> 12);
if ((iobase & 0x0fff) == 0) iobase += DEPCA_EISA_IO_PORTS; maxSlots = i + 1;
}
for (; (i<maxSlots) && (dev!=NULL); i++, iobase+=EISA_SLOT_INC) { if ((iobase & 0x0fff) == 0)
if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { iobase += DEPCA_EISA_IO_PORTS;
if (EISA_signature(name, EISA_ID)) {
if (DevicePresent(iobase) == 0) { for (; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) {
if ((dev = alloc_device(dev, iobase)) != NULL) { if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) {
if (depca_hw_init(dev, iobase, -1) == 0) { if (EISA_signature(name, EISA_ID)) {
num_depcas++; if (DevicePresent(iobase) == 0) {
} if ((dev = alloc_device(dev, iobase)) != NULL) {
num_eth++; if (depca_hw_init(dev, iobase, -1) == 0) {
} num_depcas++;
}
num_eth++;
}
}
}
} else if (autoprobed) {
printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
}
} }
}
} else if (autoprobed) {
printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
}
}
return; return;
} }
/* /*
...@@ -1500,89 +1484,87 @@ eisa_probe(struct net_device *dev, u_long ioaddr) ...@@ -1500,89 +1484,87 @@ eisa_probe(struct net_device *dev, u_long ioaddr)
** are not available then insert a new device structure at the end of ** are not available then insert a new device structure at the end of
** the current list. ** the current list.
*/ */
static struct net_device * __init static struct net_device *__init alloc_device(struct net_device *dev, u_long iobase)
alloc_device(struct net_device *dev, u_long iobase)
{ {
struct net_device *adev = NULL; struct net_device *adev = NULL;
int fixed = 0, new_dev = 0; int fixed = 0, new_dev = 0;
num_eth = depca_dev_index(dev->name);
if (loading_module) return dev;
while (1) {
if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr==0)) && !adev) {
adev=dev;
} else if ((dev->priv == NULL) && (dev->base_addr==iobase)) {
fixed = 1;
} else {
if (dev->next == NULL) {
new_dev = 1;
} else if (strncmp(dev->next->name, "eth", 3) != 0) {
new_dev = 1;
}
}
if ((dev->next == NULL) || new_dev || fixed) break;
dev = dev->next;
num_eth++;
}
if (adev && !fixed) {
dev = adev;
num_eth = depca_dev_index(dev->name); num_eth = depca_dev_index(dev->name);
new_dev = 0; if (loading_module)
} return dev;
if (((dev->next == NULL) && while (1) {
((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0)) && !adev) {
new_dev) { adev = dev;
num_eth++; /* New device */ } else if ((dev->priv == NULL) && (dev->base_addr == iobase)) {
dev = insert_device(dev, iobase, depca_probe); fixed = 1;
} } else {
if (dev->next == NULL) {
return dev; new_dev = 1;
} else if (strncmp(dev->next->name, "eth", 3) != 0) {
new_dev = 1;
}
}
if ((dev->next == NULL) || new_dev || fixed)
break;
dev = dev->next;
num_eth++;
}
if (adev && !fixed) {
dev = adev;
num_eth = depca_dev_index(dev->name);
new_dev = 0;
}
if (((dev->next == NULL) && ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || new_dev) {
num_eth++; /* New device */
dev = insert_device(dev, iobase, depca_probe);
}
return dev;
} }
/* /*
** If at end of eth device list and can't use current entry, malloc ** If at end of eth device list and can't use current entry, malloc
** one up. If memory could not be allocated, print an error message. ** one up. If memory could not be allocated, print an error message.
*/ */
static struct net_device * __init static struct net_device *__init insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *))
insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *))
{ {
struct net_device *new; struct net_device *new;
new = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL); new = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL);
if (new == NULL) { if (new == NULL) {
printk("eth%d: Device not initialised, insufficient memory\n",num_eth); printk("eth%d: Device not initialised, insufficient memory\n", num_eth);
return NULL; return NULL;
} else {
new->next = dev->next;
dev->next = new;
dev = dev->next; /* point to the new device */
if (num_eth > 9999) {
sprintf(dev->name,"eth????");/* New device name */
} else { } else {
sprintf(dev->name,"eth%d", num_eth);/* New device name */ new->next = dev->next;
dev->next = new;
dev = dev->next; /* point to the new device */
if (num_eth > 9999) {
sprintf(dev->name, "eth????"); /* New device name */
} else {
sprintf(dev->name, "eth%d", num_eth); /* New device name */
}
dev->base_addr = iobase; /* assign the io address */
dev->init = init; /* initialisation routine */
} }
dev->base_addr = iobase; /* assign the io address */
dev->init = init; /* initialisation routine */
}
return dev; return dev;
} }
static int __init static int __init depca_dev_index(char *s)
depca_dev_index(char *s)
{ {
int i=0, j=0; int i = 0, j = 0;
for (;*s; s++) { for (; *s; s++) {
if (isdigit(*s)) { if (isdigit(*s)) {
j=1; j = 1;
i = (i * 10) + (*s - '0'); i = (i * 10) + (*s - '0');
} else if (j) break; } else if (j)
} break;
}
return i; return i;
} }
/* /*
...@@ -1590,50 +1572,51 @@ depca_dev_index(char *s) ...@@ -1590,50 +1572,51 @@ depca_dev_index(char *s)
** and Boot (readb) ROM. This will also give us a clue to the network RAM ** and Boot (readb) ROM. This will also give us a clue to the network RAM
** base address. ** base address.
*/ */
static void __init static void __init DepcaSignature(char *name, u_long paddr)
DepcaSignature(char *name, u_long paddr)
{ {
u_int i,j,k; u_int i, j, k;
const char *signatures[] = DEPCA_SIGNATURE; const char *signatures[] = DEPCA_SIGNATURE;
void *ptr; void *ptr;
char tmpstr[16]; char tmpstr[16];
/* Copy the first 16 bytes of ROM */ /* Copy the first 16 bytes of ROM */
ptr = ioremap(paddr + 0xc000, 16); ptr = ioremap(paddr + 0xc000, 16);
if (ptr == NULL) { if (ptr == NULL) {
printk(KERN_ERR "depca: I/O remap failed at %lx\n", paddr+0xc000); printk(KERN_ERR "depca: I/O remap failed at %lx\n", paddr + 0xc000);
adapter = unknown; adapter = unknown;
return; return;
} }
for (i=0;i<16;i++) { for (i = 0; i < 16; i++) {
tmpstr[i] = readb(ptr + i); tmpstr[i] = readb(ptr + i);
} }
iounmap(ptr); iounmap(ptr);
/* Check if PROM contains a valid string */ /* Check if PROM contains a valid string */
for (i=0;*signatures[i]!='\0';i++) { for (i = 0; *signatures[i] != '\0'; i++) {
for (j=0,k=0;j<16 && k<strlen(signatures[i]);j++) { for (j = 0, k = 0; j < 16 && k < strlen(signatures[i]); j++) {
if (signatures[i][k] == tmpstr[j]) { /* track signature */ if (signatures[i][k] == tmpstr[j]) { /* track signature */
k++; k++;
} else { /* lost signature; begin search again */ } else { /* lost signature; begin search again */
k=0; k = 0;
} }
} }
if (k == strlen(signatures[i])) break; if (k == strlen(signatures[i]))
} break;
}
/* Check if name string is valid, provided there's no PROM */
if (*name && (i == unknown)) { /* Check if name string is valid, provided there's no PROM */
for (i=0;*signatures[i]!='\0';i++) { if (*name && (i == unknown)) {
if (strcmp(name,signatures[i]) == 0) break; for (i = 0; *signatures[i] != '\0'; i++) {
} if (strcmp(name, signatures[i]) == 0)
} break;
}
/* Update search results */ }
strcpy(name,signatures[i]);
adapter = i; /* Update search results */
strcpy(name, signatures[i]);
return; adapter = i;
return;
} }
/* /*
...@@ -1651,52 +1634,52 @@ DepcaSignature(char *name, u_long paddr) ...@@ -1651,52 +1634,52 @@ DepcaSignature(char *name, u_long paddr)
** PROM address counter is correctly positioned at the start of the ** PROM address counter is correctly positioned at the start of the
** ethernet address for later read out. ** ethernet address for later read out.
*/ */
static int __init static int __init DevicePresent(u_long ioaddr)
DevicePresent(u_long ioaddr)
{ {
union { union {
struct { struct {
u32 a; u32 a;
u32 b; u32 b;
} llsig; } llsig;
char Sig[sizeof(u32) << 1]; char Sig[sizeof(u32) << 1];
} dev; }
short sigLength=0; dev;
s8 data; short sigLength = 0;
s16 nicsr; s8 data;
int i, j, status = 0; s16 nicsr;
int i, j, status = 0;
data = inb(DEPCA_PROM); /* clear counter on DEPCA */
data = inb(DEPCA_PROM); /* read data */ data = inb(DEPCA_PROM); /* clear counter on DEPCA */
data = inb(DEPCA_PROM); /* read data */
if (data == 0x08) { /* Enable counter on DEPCA */
nicsr = inb(DEPCA_NICSR); if (data == 0x08) { /* Enable counter on DEPCA */
nicsr |= AAC; nicsr = inb(DEPCA_NICSR);
outb(nicsr, DEPCA_NICSR); nicsr |= AAC;
} outb(nicsr, DEPCA_NICSR);
}
dev.llsig.a = ETH_PROM_SIG;
dev.llsig.b = ETH_PROM_SIG; dev.llsig.a = ETH_PROM_SIG;
sigLength = sizeof(u32) << 1; dev.llsig.b = ETH_PROM_SIG;
sigLength = sizeof(u32) << 1;
for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
data = inb(DEPCA_PROM); for (i = 0, j = 0; j < sigLength && i < PROBE_LENGTH + sigLength - 1; i++) {
if (dev.Sig[j] == data) { /* track signature */ data = inb(DEPCA_PROM);
j++; if (dev.Sig[j] == data) { /* track signature */
} else { /* lost signature; begin search again */ j++;
if (data == dev.Sig[0]) { /* rare case.... */ } else { /* lost signature; begin search again */
j=1; if (data == dev.Sig[0]) { /* rare case.... */
} else { j = 1;
j=0; } else {
} j = 0;
} }
} }
}
if (j!=sigLength) {
status = -ENODEV; /* search failed */ if (j != sigLength) {
} status = -ENODEV; /* search failed */
}
return status;
return status;
} }
/* /*
...@@ -1704,33 +1687,36 @@ DevicePresent(u_long ioaddr) ...@@ -1704,33 +1687,36 @@ DevicePresent(u_long ioaddr)
** reason: access the upper half of the PROM with x=0; access the lower half ** reason: access the upper half of the PROM with x=0; access the lower half
** with x=1. ** with x=1.
*/ */
static int __init static int __init get_hw_addr(struct net_device *dev)
get_hw_addr(struct net_device *dev)
{ {
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
int i, k, tmp, status = 0; int i, k, tmp, status = 0;
u_short j, x, chksum; u_short j, x, chksum;
x = (((adapter == de100) || (adapter == de101)) ? 1 : 0); x = (((adapter == de100) || (adapter == de101)) ? 1 : 0);
for (i=0,k=0,j=0;j<3;j++) { for (i = 0, k = 0, j = 0; j < 3; j++) {
k <<= 1 ; k <<= 1;
if (k > 0xffff) k-=0xffff; if (k > 0xffff)
k -= 0xffff;
k += (u_char) (tmp = inb(DEPCA_PROM + x)); k += (u_char) (tmp = inb(DEPCA_PROM + x));
dev->dev_addr[i++] = (u_char) tmp; dev->dev_addr[i++] = (u_char) tmp;
k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8); k += (u_short) ((tmp = inb(DEPCA_PROM + x)) << 8);
dev->dev_addr[i++] = (u_char) tmp; dev->dev_addr[i++] = (u_char) tmp;
if (k > 0xffff) k-=0xffff; if (k > 0xffff)
} k -= 0xffff;
if (k == 0xffff) k=0; }
if (k == 0xffff)
k = 0;
chksum = (u_char) inb(DEPCA_PROM + x); chksum = (u_char) inb(DEPCA_PROM + x);
chksum |= (u_short) (inb(DEPCA_PROM + x) << 8); chksum |= (u_short) (inb(DEPCA_PROM + x) << 8);
if (k != chksum) status = -1; if (k != chksum)
status = -1;
return status; return status;
} }
/* /*
...@@ -1738,165 +1724,161 @@ get_hw_addr(struct net_device *dev) ...@@ -1738,165 +1724,161 @@ get_hw_addr(struct net_device *dev)
*/ */
static int load_packet(struct net_device *dev, struct sk_buff *skb) static int load_packet(struct net_device *dev, struct sk_buff *skb)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
int i, entry, end, len, status = 0; int i, entry, end, len, status = 0;
entry = lp->tx_new; /* Ring around buffer number. */ entry = lp->tx_new; /* Ring around buffer number. */
end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask; end = (entry + (skb->len - 1) / TX_BUFF_SZ) & lp->txRingMask;
if (!(readl(&lp->tx_ring[end].base) & T_OWN)) {/* Enough room? */ if (!(readl(&lp->tx_ring[end].base) & T_OWN)) { /* Enough room? */
/* /*
** Caution: the write order is important here... don't set up the ** Caution: the write order is important here... don't set up the
** ownership rights until all the other information is in place. ** ownership rights until all the other information is in place.
*/ */
if (end < entry) { /* wrapped buffer */ if (end < entry) { /* wrapped buffer */
len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ; len = (lp->txRingMask - entry + 1) * TX_BUFF_SZ;
memcpy_toio(lp->tx_buff[entry], skb->data, len); memcpy_toio(lp->tx_buff[entry], skb->data, len);
memcpy_toio(lp->tx_buff[0], skb->data + len, skb->len - len); memcpy_toio(lp->tx_buff[0], skb->data + len, skb->len - len);
} else { /* linear buffer */ } else { /* linear buffer */
memcpy_toio(lp->tx_buff[entry], skb->data, skb->len); memcpy_toio(lp->tx_buff[entry], skb->data, skb->len);
} }
/* set up the buffer descriptors */ /* set up the buffer descriptors */
len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
for (i = entry; i != end; i = (++i) & lp->txRingMask) { for (i = entry; i != end; i = (++i) & lp->txRingMask) {
/* clean out flags */ /* clean out flags */
writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base); writel(readl(&lp->tx_ring[i].base) & ~T_FLAGS, &lp->tx_ring[i].base);
writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */ writew(0x0000, &lp->tx_ring[i].misc); /* clears other error flags */
writew(-TX_BUFF_SZ, &lp->tx_ring[i].length);/* packet length in buffer */ writew(-TX_BUFF_SZ, &lp->tx_ring[i].length); /* packet length in buffer */
len -= TX_BUFF_SZ; len -= TX_BUFF_SZ;
} }
/* clean out flags */ /* clean out flags */
writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base); writel(readl(&lp->tx_ring[end].base) & ~T_FLAGS, &lp->tx_ring[end].base);
writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */ writew(0x0000, &lp->tx_ring[end].misc); /* clears other error flags */
writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */ writew(-len, &lp->tx_ring[end].length); /* packet length in last buff */
/* start of packet */ /* start of packet */
writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base); writel(readl(&lp->tx_ring[entry].base) | T_STP, &lp->tx_ring[entry].base);
/* end of packet */ /* end of packet */
writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base); writel(readl(&lp->tx_ring[end].base) | T_ENP, &lp->tx_ring[end].base);
for (i=end; i!=entry; --i) { for (i = end; i != entry; --i) {
/* ownership of packet */ /* ownership of packet */
writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base); writel(readl(&lp->tx_ring[i].base) | T_OWN, &lp->tx_ring[i].base);
if (i == 0) i=lp->txRingMask+1; if (i == 0)
} i = lp->txRingMask + 1;
writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base); }
writel(readl(&lp->tx_ring[entry].base) | T_OWN, &lp->tx_ring[entry].base);
lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */
} else { lp->tx_new = (++end) & lp->txRingMask; /* update current pointers */
status = -1; } else {
} status = -1;
}
return status;
return status;
} }
/* /*
** Look for a particular board name in the EISA configuration space ** Look for a particular board name in the EISA configuration space
*/ */
static int __init static int __init EISA_signature(char *name, s32 eisa_id)
EISA_signature(char *name, s32 eisa_id)
{ {
u_int i; u_int i;
const char *signatures[] = DEPCA_SIGNATURE; const char *signatures[] = DEPCA_SIGNATURE;
char ManCode[DEPCA_STRLEN]; char ManCode[DEPCA_STRLEN];
union { union {
s32 ID; s32 ID;
char Id[4]; char Id[4];
} Eisa; } Eisa;
int status = 0; int status = 0;
*name = '\0'; *name = '\0';
Eisa.ID = inl(eisa_id); Eisa.ID = inl(eisa_id);
ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40); ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40);
ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40); ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40);
ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30); ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30);
ManCode[3]=(( Eisa.Id[2]&0x0f)+0x30); ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30);
ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30); ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30);
ManCode[5]='\0'; ManCode[5] = '\0';
for (i=0;(*signatures[i] != '\0') && (*name == '\0');i++) { for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) {
if (strstr(ManCode, signatures[i]) != NULL) { if (strstr(ManCode, signatures[i]) != NULL) {
strcpy(name,ManCode); strcpy(name, ManCode);
status = 1; status = 1;
} }
} }
return status; return status;
} }
static void depca_dbg_open(struct net_device *dev) static void depca_dbg_open(struct net_device *dev)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
struct depca_init *p = &lp->init_block; struct depca_init *p = &lp->init_block;
int i; int i;
if (depca_debug > 1){ if (depca_debug > 1) {
/* Do not copy the shadow init block into shared memory */ /* Do not copy the shadow init block into shared memory */
/* Debugging should not affect normal operation! */ /* Debugging should not affect normal operation! */
/* The shadow init block will get copied across during InitRestartDepca */ /* The shadow init block will get copied across during InitRestartDepca */
printk("%s: depca open with irq %d\n",dev->name,dev->irq); printk("%s: depca open with irq %d\n", dev->name, dev->irq);
printk("Descriptor head addresses (CPU):\n"); printk("Descriptor head addresses (CPU):\n");
printk(" 0x%lx 0x%lx\n",(u_long)lp->rx_ring, (u_long)lp->tx_ring); printk(" 0x%lx 0x%lx\n", (u_long) lp->rx_ring, (u_long) lp->tx_ring);
printk("Descriptor addresses (CPU):\nRX: "); printk("Descriptor addresses (CPU):\nRX: ");
for (i=0;i<lp->rxRingMask;i++){ for (i = 0; i < lp->rxRingMask; i++) {
if (i < 3) { if (i < 3) {
printk("0x%8.8lx ", (long) &lp->rx_ring[i].base); printk("0x%8.8lx ", (long) &lp->rx_ring[i].base);
} }
} }
printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base); printk("...0x%8.8lx\n", (long) &lp->rx_ring[i].base);
printk("TX: "); printk("TX: ");
for (i=0;i<lp->txRingMask;i++){ for (i = 0; i < lp->txRingMask; i++) {
if (i < 3) { if (i < 3) {
printk("0x%8.8lx ", (long) &lp->tx_ring[i].base); printk("0x%8.8lx ", (long) &lp->tx_ring[i].base);
} }
} }
printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base); printk("...0x%8.8lx\n", (long) &lp->tx_ring[i].base);
printk("\nDescriptor buffers (Device):\nRX: "); printk("\nDescriptor buffers (Device):\nRX: ");
for (i=0;i<lp->rxRingMask;i++){ for (i = 0; i < lp->rxRingMask; i++) {
if (i < 3) { if (i < 3) {
printk("0x%8.8x ", readl(&lp->rx_ring[i].base)); printk("0x%8.8x ", readl(&lp->rx_ring[i].base));
} }
} }
printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base)); printk("...0x%8.8x\n", readl(&lp->rx_ring[i].base));
printk("TX: "); printk("TX: ");
for (i=0;i<lp->txRingMask;i++){ for (i = 0; i < lp->txRingMask; i++) {
if (i < 3) { if (i < 3) {
printk("0x%8.8x ", readl(&lp->tx_ring[i].base)); printk("0x%8.8x ", readl(&lp->tx_ring[i].base));
} }
} }
printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base)); printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));
printk("Initialisation block at 0x%8.8lx(Phys)\n",virt_to_phys(lp->sh_mem)); printk("Initialisation block at 0x%8.8lx(Phys)\n", virt_to_phys(lp->sh_mem));
printk(" mode: 0x%4.4x\n",p->mode); printk(" mode: 0x%4.4x\n", p->mode);
printk(" physical address: "); printk(" physical address: ");
for (i=0;i<ETH_ALEN-1;i++){ for (i = 0; i < ETH_ALEN - 1; i++) {
printk("%2.2x:", p->phys_addr[i]); printk("%2.2x:", p->phys_addr[i]);
} }
printk("%2.2x\n", p->phys_addr[i]); printk("%2.2x\n", p->phys_addr[i]);
printk(" multicast hash table: "); printk(" multicast hash table: ");
for (i=0;i<(HASH_TABLE_LEN >> 3)-1;i++){ for (i = 0; i < (HASH_TABLE_LEN >> 3) - 1; i++) {
printk("%2.2x:", p->mcast_table[i]); printk("%2.2x:", p->mcast_table[i]);
} }
printk("%2.2x\n", p->mcast_table[i]); printk("%2.2x\n", p->mcast_table[i]);
printk(" rx_ring at: 0x%8.8x\n", p->rx_ring); printk(" rx_ring at: 0x%8.8x\n", p->rx_ring);
printk(" tx_ring at: 0x%8.8x\n", p->tx_ring); printk(" tx_ring at: 0x%8.8x\n", p->tx_ring);
printk("buffers (Phys): 0x%8.8lx\n",virt_to_phys(lp->sh_mem)+lp->buffs_offset); printk("buffers (Phys): 0x%8.8lx\n", virt_to_phys(lp->sh_mem) + lp->buffs_offset);
printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", printk("Ring size:\nRX: %d Log2(rxRingMask): 0x%8.8x\n", (int) lp->rxRingMask + 1, lp->rx_rlen);
(int)lp->rxRingMask + 1, printk("TX: %d Log2(txRingMask): 0x%8.8x\n", (int) lp->txRingMask + 1, lp->tx_rlen);
lp->rx_rlen); outw(CSR2, DEPCA_ADDR);
printk("TX: %d Log2(txRingMask): 0x%8.8x\n", printk("CSR2&1: 0x%4.4x", inw(DEPCA_DATA));
(int)lp->txRingMask + 1, outw(CSR1, DEPCA_ADDR);
lp->tx_rlen); printk("%4.4x\n", inw(DEPCA_DATA));
outw(CSR2,DEPCA_ADDR); outw(CSR3, DEPCA_ADDR);
printk("CSR2&1: 0x%4.4x",inw(DEPCA_DATA)); printk("CSR3: 0x%4.4x\n", inw(DEPCA_DATA));
outw(CSR1,DEPCA_ADDR); }
printk("%4.4x\n",inw(DEPCA_DATA));
outw(CSR3,DEPCA_ADDR); return;
printk("CSR3: 0x%4.4x\n",inw(DEPCA_DATA));
}
return;
} }
/* /*
...@@ -1906,177 +1888,196 @@ static void depca_dbg_open(struct net_device *dev) ...@@ -1906,177 +1888,196 @@ static void depca_dbg_open(struct net_device *dev)
*/ */
static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{ {
struct depca_private *lp = (struct depca_private *)dev->priv; struct depca_private *lp = (struct depca_private *) dev->priv;
struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data; struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_data;
int i, status = 0; int i, status = 0;
u_long ioaddr = dev->base_addr; u_long ioaddr = dev->base_addr;
union { union {
u8 addr[(HASH_TABLE_LEN * ETH_ALEN)]; u8 addr[(HASH_TABLE_LEN * ETH_ALEN)];
u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1]; u16 sval[(HASH_TABLE_LEN * ETH_ALEN) >> 1];
u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2]; u32 lval[(HASH_TABLE_LEN * ETH_ALEN) >> 2];
} tmp; } tmp;
unsigned long flags;
switch(ioc->cmd) { void *buf;
case DEPCA_GET_HWADDR: /* Get the hardware address */
for (i=0; i<ETH_ALEN; i++) { switch (ioc->cmd) {
tmp.addr[i] = dev->dev_addr[i]; case DEPCA_GET_HWADDR: /* Get the hardware address */
} for (i = 0; i < ETH_ALEN; i++) {
ioc->len = ETH_ALEN; tmp.addr[i] = dev->dev_addr[i];
if (copy_to_user(ioc->data, tmp.addr, ioc->len)) }
return -EFAULT; ioc->len = ETH_ALEN;
break; if (copy_to_user(ioc->data, tmp.addr, ioc->len))
return -EFAULT;
case DEPCA_SET_HWADDR: /* Set the hardware address */ break;
if (!capable(CAP_NET_ADMIN)) return -EPERM;
if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) case DEPCA_SET_HWADDR: /* Set the hardware address */
return -EFAULT; if (!capable(CAP_NET_ADMIN))
for (i=0; i<ETH_ALEN; i++) { return -EPERM;
dev->dev_addr[i] = tmp.addr[i]; if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN))
} return -EFAULT;
netif_stop_queue(dev); for (i = 0; i < ETH_ALEN; i++) {
while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ dev->dev_addr[i] = tmp.addr[i];
}
STOP_DEPCA; /* Temporarily stop the depca. */ netif_stop_queue(dev);
depca_init_ring(dev); /* Initialize the descriptor rings */ while (lp->tx_old != lp->tx_new)
LoadCSRs(dev); /* Reload CSR3 */ cpu_relax(); /* Wait for the ring to empty */
InitRestartDepca(dev); /* Resume normal operation. */
netif_start_queue(dev); /* Unlock the TX ring */ STOP_DEPCA; /* Temporarily stop the depca. */
break; depca_init_ring(dev); /* Initialize the descriptor rings */
LoadCSRs(dev); /* Reload CSR3 */
case DEPCA_SET_PROM: /* Set Promiscuous Mode */ InitRestartDepca(dev); /* Resume normal operation. */
if (!capable(CAP_NET_ADMIN)) return -EPERM; netif_start_queue(dev); /* Unlock the TX ring */
netif_stop_queue(dev); break;
while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */
case DEPCA_SET_PROM: /* Set Promiscuous Mode */
STOP_DEPCA; /* Temporarily stop the depca. */ if (!capable(CAP_NET_ADMIN))
depca_init_ring(dev); /* Initialize the descriptor rings */ return -EPERM;
lp->init_block.mode |= PROM; /* Set promiscuous mode */ netif_stop_queue(dev);
while (lp->tx_old != lp->tx_new)
LoadCSRs(dev); /* Reload CSR3 */ cpu_relax(); /* Wait for the ring to empty */
InitRestartDepca(dev); /* Resume normal operation. */
netif_start_queue(dev); /* Unlock the TX ring */ STOP_DEPCA; /* Temporarily stop the depca. */
break; depca_init_ring(dev); /* Initialize the descriptor rings */
lp->init_block.mode |= PROM; /* Set promiscuous mode */
case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */
if (!capable(CAP_NET_ADMIN)) return -EPERM; LoadCSRs(dev); /* Reload CSR3 */
netif_stop_queue(dev); InitRestartDepca(dev); /* Resume normal operation. */
while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ netif_start_queue(dev); /* Unlock the TX ring */
break;
STOP_DEPCA; /* Temporarily stop the depca. */
depca_init_ring(dev); /* Initialize the descriptor rings */ case DEPCA_CLR_PROM: /* Clear Promiscuous Mode */
lp->init_block.mode &= ~PROM; /* Clear promiscuous mode */ if (!capable(CAP_NET_ADMIN))
return -EPERM;
LoadCSRs(dev); /* Reload CSR3 */ netif_stop_queue(dev);
InitRestartDepca(dev); /* Resume normal operation. */ while (lp->tx_old != lp->tx_new)
netif_start_queue(dev); /* Unlock the TX ring */ cpu_relax(); /* Wait for the ring to empty */
break;
STOP_DEPCA; /* Temporarily stop the depca. */
case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */ depca_init_ring(dev); /* Initialize the descriptor rings */
printk("%s: Boo!\n", dev->name); lp->init_block.mode &= ~PROM; /* Clear promiscuous mode */
break;
LoadCSRs(dev); /* Reload CSR3 */
case DEPCA_GET_MCA: /* Get the multicast address table */ InitRestartDepca(dev); /* Resume normal operation. */
ioc->len = (HASH_TABLE_LEN >> 3); netif_start_queue(dev); /* Unlock the TX ring */
if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len)) break;
return -EFAULT;
break; case DEPCA_SAY_BOO: /* Say "Boo!" to the kernel log file */
if(!capable(CAP_NET_ADMIN))
case DEPCA_SET_MCA: /* Set a multicast address */ return -EPERM;
if (!capable(CAP_NET_ADMIN)) return -EPERM; printk("%s: Boo!\n", dev->name);
if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len)) break;
return -EFAULT;
set_multicast_list(dev); case DEPCA_GET_MCA: /* Get the multicast address table */
break; ioc->len = (HASH_TABLE_LEN >> 3);
if (copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len))
case DEPCA_CLR_MCA: /* Clear all multicast addresses */ return -EFAULT;
if (!capable(CAP_NET_ADMIN)) return -EPERM; break;
set_multicast_list(dev);
break; case DEPCA_SET_MCA: /* Set a multicast address */
if (!capable(CAP_NET_ADMIN))
case DEPCA_MCA_EN: /* Enable pass all multicast addressing */ return -EPERM;
if (!capable(CAP_NET_ADMIN)) return -EPERM; if (ioc->len >= HASH_TABLE_LEN)
set_multicast_list(dev); return -EINVAL;
break; if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len))
return -EFAULT;
case DEPCA_GET_STATS: /* Get the driver statistics */ set_multicast_list(dev);
cli(); break;
ioc->len = sizeof(lp->pktStats);
if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) case DEPCA_CLR_MCA: /* Clear all multicast addresses */
status = -EFAULT; if (!capable(CAP_NET_ADMIN))
sti(); return -EPERM;
break; set_multicast_list(dev);
break;
case DEPCA_CLR_STATS: /* Zero out the driver statistics */
if (!capable(CAP_NET_ADMIN)) return -EPERM; case DEPCA_MCA_EN: /* Enable pass all multicast addressing */
cli(); if (!capable(CAP_NET_ADMIN))
memset(&lp->pktStats, 0, sizeof(lp->pktStats)); return -EPERM;
sti(); set_multicast_list(dev);
break; break;
case DEPCA_GET_REG: /* Get the DEPCA Registers */ case DEPCA_GET_STATS: /* Get the driver statistics */
i=0; ioc->len = sizeof(lp->pktStats);
tmp.sval[i++] = inw(DEPCA_NICSR); buf = kmalloc(ioc->len, GFP_KERNEL);
outw(CSR0, DEPCA_ADDR); /* status register */ if(!buf)
tmp.sval[i++] = inw(DEPCA_DATA); return -ENOMEM;
memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init)); spin_lock_irqsave(&lp->lock, flags);
ioc->len = i+sizeof(struct depca_init); memcpy(buf, &lp->pktStats, ioc->len);
if (copy_to_user(ioc->data, tmp.addr, ioc->len)) spin_unlock_irqrestore(&lp->lock, flags);
return -EFAULT; if (copy_to_user(ioc->data, &lp->pktStats, ioc->len))
break; status = -EFAULT;
kfree(buf);
default: break;
return -EOPNOTSUPP;
} case DEPCA_CLR_STATS: /* Zero out the driver statistics */
if (!capable(CAP_NET_ADMIN))
return status; return -EPERM;
spin_lock_irqsave(&lp->lock, flags);
memset(&lp->pktStats, 0, sizeof(lp->pktStats));
spin_unlock_irqrestore(&lp->lock, flags);
break;
case DEPCA_GET_REG: /* Get the DEPCA Registers */
i = 0;
tmp.sval[i++] = inw(DEPCA_NICSR);
outw(CSR0, DEPCA_ADDR); /* status register */
tmp.sval[i++] = inw(DEPCA_DATA);
memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init));
ioc->len = i + sizeof(struct depca_init);
if (copy_to_user(ioc->data, tmp.addr, ioc->len))
return -EFAULT;
break;
default:
return -EOPNOTSUPP;
}
return status;
} }
#ifdef MODULE #ifdef MODULE
static struct net_device thisDepca; static struct net_device thisDepca;
static int irq=7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */ static int irq = 7; /* EDIT THESE LINE FOR YOUR CONFIGURATION */
static int io=0x200; /* Or use the irq= io= options to insmod */ static int io = 0x200; /* Or use the irq= io= options to insmod */
MODULE_PARM(irq, "i"); MODULE_PARM(irq, "i");
MODULE_PARM(io, "i"); MODULE_PARM(io, "i");
MODULE_PARM_DESC(irq, "DEPCA IRQ number"); MODULE_PARM_DESC(irq, "DEPCA IRQ number");
MODULE_PARM_DESC(io, "DEPCA I/O base address"); MODULE_PARM_DESC(io, "DEPCA I/O base address");
/* See depca_probe() for autoprobe messages when a module */ /* See depca_probe() for autoprobe messages when a module */
int int init_module(void)
init_module(void)
{ {
thisDepca.irq=irq; thisDepca.irq = irq;
thisDepca.base_addr=io; thisDepca.base_addr = io;
thisDepca.init = depca_probe; thisDepca.init = depca_probe;
if (register_netdev(&thisDepca) != 0) if (register_netdev(&thisDepca) != 0)
return -EIO; return -EIO;
return 0; return 0;
} }
void void cleanup_module(void)
cleanup_module(void)
{ {
struct depca_private *lp = thisDepca.priv; struct depca_private *lp = thisDepca.priv;
unregister_netdev(&thisDepca); unregister_netdev(&thisDepca);
if (lp) { if (lp) {
iounmap(lp->sh_mem); iounmap(lp->sh_mem);
#ifdef CONFIG_MCA #ifdef CONFIG_MCA
if(lp->mca_slot != -1) if (lp->mca_slot != -1)
mca_mark_as_unused(lp->mca_slot); mca_mark_as_unused(lp->mca_slot);
#endif #endif
kfree(lp); kfree(lp);
thisDepca.priv = NULL; thisDepca.priv = NULL;
} }
thisDepca.irq=0; thisDepca.irq = 0;
release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE); release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE);
} }
#endif /* MODULE */ #endif /* MODULE */
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
* Local variables: * Local variables:
* compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c" * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c"
......
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