patch-2.3.27 linux/drivers/net/82596.c
Next file: linux/drivers/net/8390.c
Previous file: linux/drivers/net/3c59x.c
Back to the patch index
Back to the overall index
- Lines: 890
- Date:
Mon Nov 8 11:03:20 1999
- Orig file:
v2.3.26/linux/drivers/net/82596.c
- Orig date:
Mon Oct 4 15:49:29 1999
diff -u --recursive --new-file v2.3.26/linux/drivers/net/82596.c linux/drivers/net/82596.c
@@ -11,10 +11,15 @@
by Richard Hirst <richard@sleepie.demon.co.uk>
Renamed to be 82596.c
- *** Untested on Apricot hardware, and may require some hacking
- *** to make it work. The old 82596.c reported hasn't worked
- *** since 1.3.xx anyway. I have been unable to find any users
- *** of Apricot hardware to test this on.
+ 980825: Changed to receive directly in to sk_buffs which are
+ allocated at open() time. Eliminates copy on incoming frames
+ (small ones are still copied). Shared data now held in a
+ non-cached page, so we can run on 68060 in copyback mode.
+
+ TBD:
+ * look at deferring rx frames rather than discarding (as per tulip)
+ * handle tx ring full as per tulip
+ * performace test to tune rx_copybreak
Most of my modifications relate to the braindead big-endian
implementation by Intel. When the i596 is operating in
@@ -57,12 +62,22 @@
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
-#include <asm/pgtable.h> /*?? */
+#include <asm/pgtable.h>
-#ifdef CONFIG_MVME16x_NET
+#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_MVME16x_NET_MODULE)
+#define ENABLE_MVME16x_NET
+#endif
+#if defined(CONFIG_BVME6000_NET) || defined(CONFIG_BVME6000_NET_MODULE)
+#define ENABLE_BVME6000_NET
+#endif
+#if defined(CONFIG_APRICOT) || defined(CONFIG_APRICOT_MODULE)
+#define ENABLE_APRICOT
+#endif
+
+#ifdef ENABLE_MVME16x_NET
#include <asm/mvme16xhw.h>
#endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
#include <asm/bvme6000hw.h>
#endif
@@ -83,11 +98,12 @@
#define MACH_IS_APRICOT 0
#else
#define WSWAPrfd(x) x
+#define WSWAPrbd(x) ((struct i596_rbd *)(x))
#define WSWAPiscp(x) ((struct i596_iscp *)(x))
#define WSWAPscb(x) ((struct i596_scb *)(x))
#define WSWAPcmd(x) x
#define WSWAPtbd(x) x
-#define WSWAPchar(x) x
+#define WSWAPchar(x) ((char *)(x))
#define ISCP_BUSY 0x0001
#define MACH_IS_APRICOT 1
#endif
@@ -103,19 +119,22 @@
#define PORT_ALTSCP 0x02 /* alternate SCB address */
#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */
-#ifndef HAVE_ALLOC_SKB
-#define alloc_skb(size, priority) (struct sk_buff *) kmalloc(size,priority)
-#define kfree_skbmem(buff, size) kfree_s(buff,size)
-#endif
-
-#define APRICOT_DEBUG 2
+#define I82596_DEBUG 1
-#ifdef APRICOT_DEBUG
-int i596_debug = APRICOT_DEBUG;
+#ifdef I82596_DEBUG
+int i596_debug = I82596_DEBUG;
#else
int i596_debug = 1;
#endif
+/* Copy frames shorter than rx_copybreak, otherwise pass on up in
+ * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha).
+ */
+static int rx_copybreak = 100;
+
+#define PKT_BUF_SZ 1536
+#define MAX_MC_CNT 64
+
#define I596_TOTAL_SIZE 17
#define I596_NULL -1
@@ -179,12 +198,22 @@
unsigned short stat;
unsigned short cmd;
struct i596_rfd *next;
- long rbd;
+ struct i596_rbd *rbd;
unsigned short count;
unsigned short size;
- char data[1532];
};
+struct i596_rbd {
+ unsigned short count;
+ unsigned short zero1;
+ struct i596_rbd *next;
+ char *data;
+ unsigned short size;
+ unsigned short zero2;
+ struct sk_buff *skb;
+};
+
+#define TX_RING_SIZE 16
#define RX_RING_SIZE 16
struct i596_scb {
@@ -222,6 +251,9 @@
struct i596_cmd set_conf;
char i596_config[16];
struct i596_cmd tdr;
+ struct i596_cmd mc_cmd; /* Keep these three together!!! */
+ short mc_cnt; /* Keep these three together!!! */
+ char mc_addrs[MAX_MC_CNT*6]; /* Keep these three together!!! */
unsigned long stat;
int last_restart __attribute__((aligned(4)));
struct i596_rfd *rx_tail;
@@ -230,6 +262,11 @@
int cmd_backlog;
unsigned long last_cmd;
struct net_device_stats stats;
+ struct i596_rfd rfds[RX_RING_SIZE];
+ struct i596_rbd rbds[RX_RING_SIZE];
+ struct tx_cmd tx_cmds[TX_RING_SIZE];
+ struct i596_tbd tbds[TX_RING_SIZE];
+ int next_tx_cmd;
};
char init_setup[] =
@@ -262,23 +299,24 @@
static void print_eth(char *);
static void set_multicast_list(struct net_device *dev);
+static int rx_ring_size = RX_RING_SIZE;
static int ticks_limit = 25;
static int max_cmd_backlog = 16;
static inline void CA(struct net_device *dev)
{
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
if (MACH_IS_MVME16x) {
((struct i596_reg *) dev->base_addr)->ca = 1;
}
#endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
if (MACH_IS_BVME6000) {
volatile u32 i = *(volatile u32 *) (dev->base_addr);
}
#endif
-#ifdef CONFIG_APRICOT_i596
+#ifdef ENABLE_APRICOT
if (MACH_IS_APRICOT) {
outw(0, (short) (dev->base_addr) + 4);
}
@@ -288,14 +326,14 @@
static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x)
{
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
if (MACH_IS_MVME16x) {
struct i596_reg *p = (struct i596_reg *) (dev->base_addr);
p->porthi = ((c) | (u32) (x)) & 0xffff;
p->portlo = ((c) | (u32) (x)) >> 16;
}
#endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
if (MACH_IS_BVME6000) {
u32 v = (u32) (c) | (u32) (x);
v = ((u32) (v) << 16) | ((u32) (v) >> 16);
@@ -307,7 +345,7 @@
}
-#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET)
+#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
static void i596_error(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
@@ -333,77 +371,88 @@
}
#endif
-static inline int init_rx_bufs(struct net_device *dev, int num)
+static inline void init_rx_bufs(struct net_device *dev)
{
- struct i596_private *lp = (struct i596_private *) dev->priv;
+ struct i596_private *lp = (struct i596_private *)dev->priv;
int i;
struct i596_rfd *rfd;
-
- lp->scb.rfd = (struct i596_rfd *) I596_NULL;
+ struct i596_rbd *rbd;
if (i596_debug > 1)
- printk("%s: init_rx_bufs %d.\n", dev->name, num);
+ printk ("%s: init_rx_bufs %d.\n", dev->name, rx_ring_size);
- for (i = 0; i < num; i++) {
- if (!(rfd = (struct i596_rfd *) kmalloc(sizeof(struct i596_rfd), GFP_KERNEL)))
- break;
+ /* First build the Receive Buffer Descriptor List */
- rfd->stat = 0x0000;
- rfd->rbd = I596_NULL;
- rfd->count = 0;
- rfd->size = 1532;
- if (i == 0) {
- rfd->cmd = CMD_EOL;
- lp->rx_tail = rfd;
- } else
- rfd->cmd = 0x0000;
+ for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
+ struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ);
- rfd->next = lp->scb.rfd;
- lp->scb.rfd = WSWAPrfd(rfd);
+ if (skb == NULL)
+ panic("82596: alloc_skb() failed");
+ skb->dev = dev;
+ rbd->next = WSWAPrbd(rbd+1);
+ rbd->skb = skb;
+ rbd->data = WSWAPchar(skb->tail);
+ rbd->size = PKT_BUF_SZ;
+#ifdef __mc68000__
+ cache_clear(virt_to_phys(skb->tail), PKT_BUF_SZ);
+#endif
}
+ lp->rbds[rx_ring_size-1].next = WSWAPrbd(lp->rbds);
- if (i != 0)
- lp->rx_tail->next = lp->scb.rfd;
+ /* Now build the Receive Frame Descriptor List */
- return (i);
+ for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
+ rfd->rbd = (struct i596_rbd *)I596_NULL;
+ rfd->next = WSWAPrfd(rfd+1);
+ rfd->cmd = CMD_FLEX;
+ }
+ lp->scb.rfd = WSWAPrfd(lp->rfds);
+ lp->rfds[0].rbd = WSWAPrbd(lp->rbds);
+ rfd = lp->rfds + rx_ring_size - 1;
+ lp->rx_tail = rfd;
+ rfd->next = WSWAPrfd(lp->rfds);
+ rfd->cmd = CMD_EOL|CMD_FLEX;
}
static inline void remove_rx_bufs(struct net_device *dev)
{
- struct i596_private *lp = (struct i596_private *) dev->priv;
- struct i596_rfd *rfd = WSWAPrfd(lp->scb.rfd);
-
- lp->rx_tail->next = (struct i596_rfd *) I596_NULL;
+ struct i596_private *lp = (struct i596_private *)dev->priv;
+ struct i596_rbd *rbd;
+ int i;
- do {
- lp->scb.rfd = rfd->next;
- kfree(rfd);
- rfd = WSWAPrfd(lp->scb.rfd);
+ for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
+ if (rbd->skb == NULL)
+ break;
+ dev_kfree_skb(rbd->skb);
}
- while (rfd != lp->rx_tail);
}
static inline void init_i596_mem(struct net_device *dev)
{
struct i596_private *lp = (struct i596_private *) dev->priv;
-#if !defined(CONFIG_MVME16x_NET) && !defined(CONFIG_BVME6000_NET)
+#if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET)
short ioaddr = dev->base_addr;
#endif
int boguscnt = 100000;
unsigned long flags;
+ int i;
-#if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET)
-#ifdef CONFIG_MVME16x_NET
+#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
+#ifdef ENABLE_MVME16x_NET
if (MACH_IS_MVME16x) {
volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
/* Disable all ints for now */
pcc2[0x28] = 1;
pcc2[0x2a] = 0x40;
- pcc2[0x2b] = 0x40; /* Set snooping bits now! */
+ /* Following disables snooping. Snooping is not required
+ * as we make appropriate use of non-cached pages for
+ * shared data, and cache_push/cache_clear.
+ */
+ pcc2[0x2b] = 0x00;
}
#endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
if (MACH_IS_BVME6000) {
volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
@@ -419,7 +468,7 @@
MPU_PORT(dev, PORT_ALTSCP, &lp->scp);
-#else
+#elif defined(ENABLE_APRICOT)
/* change the scp address */
outw(0, ioaddr);
@@ -431,15 +480,15 @@
lp->last_cmd = jiffies;
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
if (MACH_IS_MVME16x)
lp->scp.sysbus = 0x00000054;
#endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
if (MACH_IS_BVME6000)
lp->scp.sysbus = 0x0000004c;
#endif
-#ifdef CONFIG_APRICOT_i596
+#ifdef ENABLE_APRICOT
if (MACH_IS_APRICOT)
lp->scp.sysbus = 0x00440000;
#endif
@@ -454,7 +503,7 @@
if (i596_debug > 1)
printk("%s: starting i82596.\n", dev->name);
-#if !defined(CONFIG_MVME16x_NET) && !defined(CONFIG_BVME6000_NET)
+#if defined(ENABLE_APRICOT)
(void) inb(ioaddr + 0x10);
outb(4, ioaddr + 0xf);
#endif
@@ -466,9 +515,22 @@
dev->name, lp->scb.status, lp->scb.command);
break;
}
+
+ /* Ensure rx frame/buffer descriptors are tidy */
+ /* Bit naff doing this here as well as in init_rx_bufs() */
+
+ for (i = 0; i < rx_ring_size; i++) {
+ lp->rfds[i].rbd = (struct i596_rbd *)I596_NULL;
+ lp->rfds[i].cmd = CMD_FLEX;
+ }
+ lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
+ lp->scb.rfd = WSWAPrfd(lp->rfds);
+ lp->rfds[0].rbd = WSWAPrbd(lp->rbds);
+ lp->rx_tail = lp->rfds + rx_ring_size - 1;
+
lp->scb.command = 0;
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
if (MACH_IS_MVME16x) {
volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
@@ -478,7 +540,7 @@
pcc2[0x2b] = 0x55;
}
#endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
if (MACH_IS_BVME6000) {
volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
@@ -525,38 +587,88 @@
static inline int i596_rx(struct net_device *dev)
{
- struct i596_private *lp = (struct i596_private *) dev->priv;
+ struct i596_private *lp = (struct i596_private *)dev->priv;
struct i596_rfd *rfd;
+ struct i596_rbd *rbd;
int frames = 0;
if (i596_debug > 3)
- printk("i596_rx()\n");
+ printk ("i596_rx()\n");
- rfd = WSWAPrfd(lp->scb.rfd); /* Reference next frame descriptor to check */
+ rfd = WSWAPrfd(lp->scb.rfd); /* Ref next frame to check */
- while ((rfd->stat) & STAT_C) { /* Loop while we have complete frames */
- if (i596_debug > 2)
- print_eth(rfd->data);
+ while ((rfd->stat) & STAT_C) { /* Loop while complete frames */
+ rbd = WSWAPrbd(rfd->rbd); /* Ref associated buffer desc */
+
+ if (i596_debug >2)
+ print_eth(WSWAPchar(rbd->data));
if ((rfd->stat) & STAT_OK) {
/* a good frame */
- int pkt_len = rfd->count & 0x3fff;
- struct sk_buff *skb = dev_alloc_skb(pkt_len);
+ int pkt_len = rbd->count & 0x3fff;
+ struct sk_buff *skb = rbd->skb;
+ int rx_in_place = 0;
frames++;
+ /* Check if the packet is long enough to just accept
+ * without copying to a properly sized skbuff.
+ */
+
+ if (pkt_len > rx_copybreak) {
+ struct sk_buff *newskb;
+ char *temp;
+
+ /* Get fresh skbuff to replace filled one. */
+ newskb = dev_alloc_skb(PKT_BUF_SZ);
+ if (newskb == NULL) {
+ skb = NULL; /* drop pkt */
+ goto memory_squeeze;
+ }
+ /* Pass up the skb already on the Rx ring. */
+ temp = skb_put(skb, pkt_len);
+ if (WSWAPchar(rbd->data) != temp)
+ printk(KERN_ERR "%s: Internal consistency error "
+ "-- the skbuff addresses do not match"
+ " in i596_rx: %p vs. %p / %p.\n", dev->name,
+ WSWAPchar(rbd->data),
+ skb->head, temp);
+ rx_in_place = 1;
+ rbd->skb = newskb;
+ newskb->dev = dev;
+ rbd->data = WSWAPchar(newskb->tail);
+#ifdef __mc68000__
+ cache_clear(virt_to_phys(newskb->tail), PKT_BUF_SZ);
+#endif
+ }
+ else
+ skb = dev_alloc_skb(pkt_len + 2);
+memory_squeeze:
if (skb == NULL) {
- printk("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
+ /* XXX tulip.c can defer packets here!! */
+ printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
- } else {
+ }
+ else {
skb->dev = dev;
- memcpy(skb_put(skb, pkt_len), rfd->data, pkt_len);
- skb->protocol = eth_type_trans(skb, dev);
+ if (!rx_in_place) {
+ /* 16 byte align the data fields */
+ skb_reserve(skb, 2);
+ memcpy(skb_put(skb,pkt_len),
+ WSWAPchar(rbd->data), pkt_len);
+ }
+ skb->protocol=eth_type_trans(skb,dev);
+ skb->len = pkt_len;
+#ifdef __mc68000__
+ cache_clear(virt_to_phys(rbd->skb->tail),
+ pkt_len);
+#endif
netif_rx(skb);
lp->stats.rx_packets++;
- lp->stats.rx_bytes += pkt_len;
+ lp->stats.rx_bytes+=pkt_len;
}
- } else {
+ }
+ else {
lp->stats.rx_errors++;
if ((rfd->stat) & 0x0001)
lp->stats.collisions++;
@@ -576,21 +688,40 @@
/* Clear the buffer descriptor count and EOF + F flags */
+ if (rbd != (struct i596_rbd *)I596_NULL)
+ rbd->count=0;
+ else
+ printk("%s: Null rbd - oops!\n", dev->name);
+
+ /* Tidy the frame descriptor, marking it as end of list */
+
+ rfd->rbd = (struct i596_rbd *)I596_NULL;
rfd->stat = 0;
+ rfd->cmd = CMD_EOL|CMD_FLEX;
rfd->count = 0;
- rfd->cmd = CMD_EOL;
- lp->rx_tail->cmd = 0;
+
+ /* Remove end-of-list from old end descriptor */
+
+ lp->rx_tail->cmd = CMD_FLEX;
+
+ /* Update last frame descriptor to reference the one just
+ * processed */
+
lp->rx_tail = rfd;
+
+ /* Update record of next frame descriptor to process */
+
lp->scb.rfd = rfd->next;
- rfd = WSWAPrfd(lp->scb.rfd); /* Next frame descriptor to check */
+ rfd = WSWAPrfd(lp->scb.rfd); /* Next frame desc. to check */
}
if (i596_debug > 3)
- printk("frames %d\n", frames);
+ printk ("frames %d\n", frames);
return 0;
}
+
static inline void i596_cleanup_cmd(struct i596_private *lp)
{
struct i596_cmd *ptr;
@@ -617,13 +748,12 @@
lp->stats.tx_aborted_errors++;
ptr->next = (struct i596_cmd *) I596_NULL;
- kfree(tx_cmd);
+ tx_cmd->cmd.command = 0; /* Mark as free */
break;
}
case CmdMulticastList:
{
ptr->next = (struct i596_cmd *) I596_NULL;
- kfree(ptr);
break;
}
default:
@@ -743,26 +873,19 @@
static int i596_open(struct net_device *dev)
{
- int i;
-
if (i596_debug > 1)
printk("%s: i596_open() irq %d.\n", dev->name, dev->irq);
- if (request_irq(dev->irq, &i596_interrupt, 0, "apricot", dev))
+ if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev))
return -EAGAIN;
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
if (MACH_IS_MVME16x) {
- if (request_irq(0x56, &i596_error, 0, "apricot_error", dev))
+ if (request_irq(0x56, &i596_error, 0, "i82596_error", dev))
return -EAGAIN;
}
#endif
- if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE)
- printk("%s: only able to allocate %d receive buffers\n", dev->name, i);
+ init_rx_bufs(dev);
- if (i < 4) {
- free_irq(dev->irq, dev);
- return -EAGAIN;
- }
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
@@ -779,6 +902,7 @@
struct i596_private *lp = (struct i596_private *) dev->priv;
int ioaddr = dev->base_addr;
struct tx_cmd *tx_cmd;
+ struct i596_tbd *tbd;
if (i596_debug > 2)
printk("%s: 82596 start xmit\n", dev->name);
@@ -810,7 +934,8 @@
dev->trans_start = jiffies;
}
if (i596_debug > 3)
- printk("%s: i596_start_xmit() called\n", dev->name);
+ printk("%s: i596_start_xmit(%x,%x) called\n", dev->name,
+ skb->len, (unsigned int)skb->data);
/* Block a timer-based transmit from overlapping. This could better be
done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
@@ -820,14 +945,18 @@
short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
dev->trans_start = jiffies;
- tx_cmd = (struct tx_cmd *) kmalloc((sizeof(struct tx_cmd) + sizeof(struct i596_tbd)), GFP_ATOMIC);
- if (tx_cmd == NULL) {
- printk("%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
+ tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
+ tbd = lp->tbds + lp->next_tx_cmd;
+
+ if (tx_cmd->cmd.command) {
+ printk ("%s: xmit ring full, dropping packet.\n",
+ dev->name);
lp->stats.tx_dropped++;
dev_kfree_skb(skb);
} else {
- struct i596_tbd *tbd = (struct i596_tbd *) (tx_cmd + 1);
+ if (++lp->next_tx_cmd == TX_RING_SIZE)
+ lp->next_tx_cmd = 0;
tx_cmd->tbd = WSWAPtbd(tbd);
tbd->next = (struct i596_tbd *) I596_NULL;
@@ -841,6 +970,9 @@
tbd->data = WSWAPchar(skb->data);
+#ifdef __mc68000__
+ cache_push(virt_to_phys(skb->data), length);
+#endif
if (i596_debug > 3)
print_eth(skb->data);
i596_add_cmd(dev, (struct i596_cmd *) tx_cmd);
@@ -854,7 +986,6 @@
return 0;
}
-
static void print_eth(char *add)
{
@@ -879,14 +1010,15 @@
struct i596_private *lp;
char eth_addr[6];
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
if (MACH_IS_MVME16x) {
static int probed = 0;
-
+#ifdef XXX_FIXME
if (mvme16x_config & MVME16x_CONFIG_NO_ETHERNET) {
printk("Ethernet probe disabled - chip not present\n");
return ENODEV;
}
+#endif
if (probed)
return ENODEV;
probed++;
@@ -895,7 +1027,7 @@
dev->irq = (unsigned) MVME16x_IRQ_I596;
}
#endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
if (MACH_IS_BVME6000) {
volatile unsigned char *rtc = (unsigned char *) BVME_RTC_BASE;
unsigned char msr = rtc[3];
@@ -909,7 +1041,7 @@
dev->irq = (unsigned) BVME_IRQ_I596;
}
#endif
-#ifdef CONFIG_APRICOT_INTEL
+#ifdef ENABLE_APRICOT
int checksum = 0;
int ioaddr = 0x300;
@@ -953,22 +1085,28 @@
if (i596_debug > 0)
printk(version);
- /* The APRICOT-specific entries in the device structure. */
+ /* The 82596-specific entries in the device structure. */
dev->open = &i596_open;
dev->stop = &i596_close;
dev->hard_start_xmit = &i596_start_xmit;
dev->get_stats = &i596_get_stats;
dev->set_multicast_list = &set_multicast_list;
- dev->mem_start = (int) kmalloc(sizeof(struct i596_private) + 0x0f, GFP_KERNEL);
- /* align for scp */
- dev->priv = (void *) ((dev->mem_start + 0xf) & 0xfffffff0);
+ dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0);
+ dev->priv = (void *)(dev->mem_start);
lp = (struct i596_private *) dev->priv;
if (i596_debug)
- printk("%s: lp at 0x%08lx, lp->scb at 0x%08lx\n"
- ,dev->name, (unsigned long) lp, (unsigned long) &lp->scb);
+ printk ("%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n",
+ dev->name, (unsigned long)lp,
+ sizeof(struct i596_private), (unsigned long)&lp->scb);
memset((void *) lp, 0, sizeof(struct i596_private));
+
+#ifdef __mc68000__
+ cache_push(virt_to_phys((void *)(dev->mem_start)), 4096);
+ cache_clear(virt_to_phys((void *)(dev->mem_start)), 4096);
+ kernel_set_cachemode((void *)(dev->mem_start), 4096, IOMAP_NOCACHE_SER);
+#endif
lp->scb.command = 0;
lp->scb.cmd = (struct i596_cmd *) I596_NULL;
lp->scb.rfd = (struct i596_rfd *) I596_NULL;
@@ -984,7 +1122,7 @@
int boguscnt = 2000;
unsigned short status, ack_cmd = 0;
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
if (MACH_IS_BVME6000) {
if (*(char *) BVME_LOCAL_IRQ_STAT & BVME_ETHERR) {
i596_error(BVME_IRQ_I596, NULL, NULL);
@@ -1063,13 +1201,12 @@
dev_kfree_skb(skb);
ptr->next = (struct i596_cmd *) I596_NULL;
- kfree(tx_cmd);
+ tx_cmd->cmd.command = 0; /* Mark free */
break;
}
case CmdMulticastList:
{
ptr->next = (struct i596_cmd *) I596_NULL;
- kfree(ptr);
break;
}
case CmdTDR:
@@ -1141,7 +1278,7 @@
}
lp->scb.command = ack_cmd;
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
if (MACH_IS_MVME16x) {
/* Ack the interrupt */
@@ -1150,7 +1287,7 @@
pcc2[0x2a] |= 0x08;
}
#endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
if (MACH_IS_BVME6000) {
volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
@@ -1158,7 +1295,7 @@
*ethirq = 3;
}
#endif
-#ifdef CONFIG_APRICOT_INTEL
+#ifdef ENABLE_APRICOT
(void) inb(ioaddr + 0x10);
outb(4, ioaddr + 0xf);
#endif
@@ -1208,7 +1345,7 @@
i596_cleanup_cmd(lp);
-#ifdef CONFIG_MVME16x_NET
+#ifdef ENABLE_MVME16x_NET
if (MACH_IS_MVME16x) {
volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
@@ -1218,7 +1355,7 @@
pcc2[0x2b] = 0x40; /* Set snooping bits now! */
}
#endif
-#ifdef CONFIG_BVME6000_NET
+#ifdef ENABLE_BVME6000_NET
if (MACH_IS_BVME6000) {
volatile unsigned char *ethirq = (unsigned char *) BVME_ETHIRQ_REG;
@@ -1249,7 +1386,7 @@
{
struct i596_private *lp = (struct i596_private *) dev->priv;
struct i596_cmd *cmd;
- int config = 0;
+ int config = 0, cnt;
if (i596_debug > 1)
printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF");
@@ -1279,18 +1416,24 @@
i596_add_cmd(dev, &lp->set_conf);
}
}
+
+ cnt = dev->mc_count;
+ if (cnt > MAX_MC_CNT)
+ {
+ cnt = MAX_MC_CNT;
+ printk("%s: Only %d multicast addresses supported",
+ dev->name, cnt);
+ }
+
if (dev->mc_count > 0) {
struct dev_mc_list *dmi;
unsigned char *cp;
- cmd = (struct i596_cmd *) kmalloc(sizeof(struct i596_cmd) + 2 + dev->mc_count * 6, GFP_ATOMIC);
- if (cmd == NULL) {
- printk("%s: set_multicast Memory squeeze.\n", dev->name);
- return;
- }
+
+ cmd = &lp->mc_cmd;
cmd->command = CmdMulticastList;
*((unsigned short *) (cmd + 1)) = dev->mc_count * 6;
cp = ((unsigned char *) (cmd + 1)) + 2;
- for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
+ for(dmi=dev->mc_list;cnt && dmi!=NULL;dmi=dmi->next,cnt--) {
memcpy(cp, dmi->dmi_addr, 6);
if (i596_debug > 1)
printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, *(cp + 0), *(cp + 1), *(cp + 2), *(cp + 3), *(cp + 4), *(cp + 5));
@@ -1306,40 +1449,58 @@
static unsigned int i596_portlist[] __initdata =
{0x300, 0};
struct netdev_entry i596_drv =
-{"apricot", i82596_probe, I596_TOTAL_SIZE, apricot_portlist};
+{"i82596", i82596_probe, I596_TOTAL_SIZE, i596_portlist};
#endif
#ifdef MODULE
static char devicename[9] =
{0,};
-static struct net_device dev_apricot =
+static struct net_device dev_82596 =
{
- devicename, /* device name inserted by /linux/drivers/net/net_init.c */
+ devicename, /* device name inserted by drivers/net/net_init.c */
0, 0, 0, 0,
- 0x300, 10,
+ 0, 0, /* base, irq */
0, 0, 0, NULL, i82596_probe};
+#ifdef ENABLE_APRICOT
static int io = 0x300;
static int irq = 10;
MODULE_PARM(irq, "i");
+#endif
+
+MODULE_PARM(debug, "i");
+static int debug = -1;
int init_module(void)
{
- dev_apricot.base_addr = io;
- dev_apricot.irq = irq;
- if (register_netdev(&dev_apricot) != 0)
+#ifdef ENABLE_APRICOT
+ dev_82596.base_addr = io;
+ dev_82596.irq = irq;
+#endif
+ if (debug >= 0)
+ i596_debug = debug;
+ if (register_netdev(&dev_82596) != 0)
return -EIO;
return 0;
}
void cleanup_module(void)
{
- unregister_netdev(&dev_apricot);
- kfree((void *) dev_apricot.mem_start);
- dev_apricot.priv = NULL;
+ unregister_netdev(&dev_82596);
+#ifdef __mc68000__
+ /* XXX This assumes default cache mode to be IOMAP_FULL_CACHING,
+ * XXX which may be invalid (CONFIG_060_WRITETHROUGH)
+ */
+ kernel_set_cachemode((u32)(dev_82596.mem_start), 4096,
+ IOMAP_FULL_CACHING);
+#endif
+ free_page ((u32)(dev_82596.mem_start));
+ dev_82596.priv = NULL;
+#ifdef ENABLE_APRICOT
/* If we don't do this, we can't re-insmod it later. */
- release_region(dev_apricot.base_addr, I596_TOTAL_SIZE);
+ release_region(dev_82596.base_addr, I596_TOTAL_SIZE);
+#endif
}
#endif /* MODULE */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)