|
From: Kenn H. <ke...@us...> - 2001-03-07 02:13:56
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/net
In directory usw-pr-cvs1:/tmp/cvs-serv18727
Modified Files:
vaxlance.c
Log Message:
Make it work on KA43. Major cleanups and simplifications.
Index: vaxlance.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/net/vaxlance.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- vaxlance.c 2001/03/04 23:54:44 1.9
+++ vaxlance.c 2001/03/07 02:15:34 1.10
@@ -22,39 +22,19 @@
static char *lancestr = "LANCE";
#include <linux/init.h>
-#include <linux/kernel.h>
#include <linux/netdevice.h>
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/hdreg.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/utsname.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
#include <linux/delay.h>
-#include <asm/io.h>
#include <linux/etherdevice.h>
+#include <linux/ioport.h> /* for autoirq_setup/_report */
+
+#include <asm/pgalloc.h> /* for __flush_tlb_one */
#include <asm/vsa.h>
+/* Ugly kludge to deal with KA43 weirdness */
#include <asm/mv.h>
#include <asm/ka43.h>
extern struct vax_mv mv_ka43;
-#ifndef CONFIG_TC
-unsigned long system_base = 0;
-unsigned long dmaptr;
-#endif
-static int type;
-
#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
@@ -129,25 +109,11 @@
#define PKT_BUF_SZ 1536
#define RX_BUFF_SIZE PKT_BUF_SZ
#define TX_BUFF_SIZE PKT_BUF_SZ
-
-#undef TEST_HITS
-#define DEBUG_VAX_DRIVER 0
-#define ZERO 0
+#undef VAX_LANCE_DEBUG
+#undef VAX_LANCE_DEBUG_BUFFERS
+#define VAX_LANCE_AUTOPROBE_IRQ
-/* The DS2000/3000 have a linear 64 KB buffer.
-
- * The PMAD-AA has 128 kb buffer on-board.
- *
- * The IOASIC LANCE devices use a shared memory region. This region as seen
- * from the CPU is (max) 128 KB long and has to be on an 128 KB boundary.
- * The LANCE sees this as a 64 KB long continuous memory region.
- *
- * The LANCE's DMA address is used as an index in this buffer and DMA takes
- * place in bursts of eight 16-Bit words which are packed into four 32-Bit words
- * by the IOASIC. This leads to a strange padding: 16 bytes of valid data followed
- * by a 16 byte gap :-(.
- */
struct lance_rx_desc {
unsigned short rmd0; /* low address of packet */
@@ -189,32 +155,36 @@
short gap0[4];
/* The buffer descriptors */
- struct lance_rx_desc brx_ring[RX_RING_SIZE];
- struct lance_tx_desc btx_ring[TX_RING_SIZE];
+ struct lance_rx_desc brx_ring[RX_RING_SIZE];
+ struct lance_tx_desc btx_ring[TX_RING_SIZE];
};
-#define BUF_OFFSET_CPU sizeof(struct lance_init_block)
-/*#define BUF_OFFSET_LNC (sizeof(struct lance_init_block)>>1)*/
-#define BUF_OFFSET_LNC (sizeof(struct lance_init_block))
+#define BUF_OFFSET_CPU (offsetof(struct lance_shared_mem, rx_buf))
+#define BUF_OFFSET_LNC BUF_OFFSET_CPU
-#define libdesc_offset(rt, elem) \
-((__u32)(((unsigned long)(&(((struct lance_init_block *)0)->rt[elem])))))
+/* This is how our shared memory block is layed out */
-#define libvaxdesc_offset(rt, elem) \
-((__u32)(((unsigned long)(&(ib->rt[elem])))))
-/*
- * This works *only* for the ring descriptors
- */
-#define LANCE_ADDR(x) (x & 0xFFFFFF)
-/*(PHYSADDR(x))*/
+struct lance_shared_mem {
+ struct lance_init_block init_block; /* Includes RX/TX descriptors */
+ char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE];
+ char tx_buf[RX_RING_SIZE][RX_BUFF_SIZE];
+};
+
struct lance_private {
char *name;
+
+ /* virtual addr of registers */
volatile struct lance_regs *ll;
+
+ /* virtual addr of shared memory block */
+ volatile struct lance_shared_mem *lance_mem;
+
+ /* virtual addr of block inside shared mem block */
volatile struct lance_init_block *init_block;
- volatile unsigned long *dma_ptr_reg;
+
unsigned char vsbus_int;
spinlock_t lock;
@@ -228,26 +198,14 @@
struct net_device *dev; /* Backpointer */
struct lance_private *next_module;
struct timer_list multicast_timer;
-
- /* Pointers to the ring buffers as seen from the CPU */
- char *rx_buf_ptr_cpu[RX_RING_SIZE];
- char *tx_buf_ptr_cpu[TX_RING_SIZE];
-
- /* Pointers to the ring buffers as seen from the LANCE */
- char *rx_buf_ptr_lnc[RX_RING_SIZE];
- char *tx_buf_ptr_lnc[TX_RING_SIZE];
-
- /* Virtual addr of buffer memory */
- char *buf_va;
};
#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
lp->tx_old+TX_RING_MOD_MASK-lp->tx_new:\
lp->tx_old - lp->tx_new-1)
-/* The lance control ports are at an absolute address, machine and tc-slot
- * dependant.
- * DECstations do only 32-bit access and the LANCE uses 16 bit addresses,
+/* The lance control ports are at an absolute address, machine dependent.
+ * VAXstations align the two 16-bit registers on 32-bit boundaries
* so we have to give the structure an extra member making rap pointing
* at the right address
*/
@@ -257,38 +215,83 @@
volatile unsigned short rap; /* register address port */
};
-int vax_lance_debug = 2;
-/*
- #ifdef MODULE
- static struct lance_private *root_lance_dev = NULL;
- #endif
- */
+/* Communication with the LANCE takes place via four channels:
+
+ 1. The RDP and RAP ports (which live at 200e0000 physical on
+ VS3100-family machines). Through these two ports we can
+ access the LANCE's 4 registers: CSR0, CSR1, CSR2 and CSR3
+ (very imaginatively named...)
+
+ 2. The LANCE init block which we allocate. We tell the LANCE where the
+ init block lives in memory via the CSR1 and CSR2 registers. The init
+ block contains the ethernet address, multi-cast address filter and
+ contains the physical addresses of the RX and TX buffer descriptors.
+ The init block must be word aligned.
+
+ 3. The RX and TX buffer descriptors are pointed to by the init block and
+ in turn contain the physical addresses of the RX and TX buffers.
+ The buffer descriptors must be quadword aligned.
+
+ 4. The RX and TX buffers themselves. These buffers have no alignment
+ requirement.
+
+ To keep things simple, we allocate a single 64K chunk of memory which
+ contains the init block, followed by the buffer descriptors and then
+ the buffers.
+
+ For most CPUs, the physical addresses used by the LANCE and the
+ virtual addresses used by the CPU follow the usual virt = phys+0x80000000
+ convention.
+
+ However, the KA43 has an unusual requirement. Physical memory on the
+ KA43 is accessible from address 0 upwards as normal, but is also visible
+ in the region starting a 0x28000000. This region is called the DIAGMEM
+ region. What's different about it, I don't know, but it's probably
+ something to do with caching.
+
+ So, after allocating the 64KB chunk, but before we tell the LANCE
+ about it, we tweak the PTEs behind these pages to map to physical
+ addresses in the DIAGMEM region.
+
+ As of 2001-03-06, the closest data sheet I can find is the AM79C90 (aka
+ C-LANCE) on AMD's site at http://www.amd.com/products/npd/techdocs/17881.pdf.
+*/
+
+
+
static inline void writereg(volatile unsigned short *regptr, short value)
{
*regptr = value;
}
+static inline void writecsr0(volatile struct lance_regs *ll, unsigned short value)
+{
+ writereg(&ll->rap, LE_CSR0);
+ writereg(&ll->rdp, value);
+}
+
+static inline void lance_stop(volatile struct lance_regs *ll)
+{
+ writecsr0(ll, LE_C0_STOP);
+
+ /* Is this needed? NetBSD does it sometimes */
+ udelay(100);
+}
+
/* Load the CSR registers */
static void load_csrs(struct lance_private *lp)
{
volatile struct lance_regs *ll = lp->ll;
unsigned long leptr;
- leptr = (unsigned long)lp->init_block;
+ leptr = virt_to_phys(lp->init_block);
- /* FIXME: This function needs a re-write for VAX,
- need to figure out init block address and
- pass it to the lance - ai...@li... 14 Aug */
writereg(&ll->rap, LE_CSR1);
writereg(&ll->rdp, (leptr & 0xFFFF));
writereg(&ll->rap, LE_CSR2);
writereg(&ll->rdp, (leptr >> 16) & 0xFF);
- /*
- writereg(&ll->rdp, (leptr & 0xFFFF));*/
- /* writereg(&ll->rap, LE_CSR2);
- writereg(&ll->rdp, leptr >> 16);*/
writereg(&ll->rap, LE_CSR3);
writereg(&ll->rdp, lp->busmaster_regval);
@@ -296,16 +299,17 @@
writereg(&ll->rap, LE_CSR0);
}
+
/*
* Our specialized copy routines
*
*/
-void cp_to_buf(void *to, const void *from, __kernel_size_t len)
+static inline void cp_to_buf(void *to, const void *from, __kernel_size_t len)
{
memcpy(to, from, len);
}
-void cp_from_buf(void *to, unsigned char *from, int len)
+static inline void cp_from_buf(void *to, unsigned char *from, int len)
{
memcpy(to, from, len);
}
@@ -314,13 +318,10 @@
static void lance_init_ring(struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
- volatile struct lance_init_block *ib;
- int leptr;
+ volatile struct lance_init_block *ib = lp->init_block;
+ unsigned long leptr;
int i;
- ib = (struct lance_init_block *) (dev->mem_start);
- lp->init_block=ib;
-
/* Lock out other processes while setting up hardware */
netif_stop_queue(dev);
@@ -338,54 +339,61 @@
ib->phys_addr[5] = dev->dev_addr[5];
/* Setup the initialization block */
-
-#if 1
/* Setup rx descriptor pointer */
- /* leptr = LANCE_ADDR(libdesc_offset(brx_ring, 0));*/
- leptr = LANCE_ADDR(libvaxdesc_offset(brx_ring, 0));
+
+ /* Calculate the physical address of the first receive descriptor */
+ leptr = virt_to_phys(ib->brx_ring);
ib->rx_len = (LANCE_LOG_RX_BUFFERS << 13) | (leptr >> 16);
ib->rx_ptr = leptr;
- if (ZERO)
- printk("RX ptr: %8.8x(%8.8x)\n", leptr, libvaxdesc_offset(brx_ring, 0));
-
+
+#ifdef VAX_LANCE_DEBUG
+ printk("RX ptr: %8.8lx(%8.8x)\n", leptr, libdesc_offset(brx_ring, 0));
+#endif
/* Setup tx descriptor pointer */
- /* leptr = LANCE_ADDR(libdesc_offset(btx_ring, 0));*/
- leptr = LANCE_ADDR(libvaxdesc_offset(btx_ring, 0));
+
+ /* Calculate the physical address of the first transmit descriptor */
+ leptr = virt_to_phys(ib->btx_ring);
ib->tx_len = (LANCE_LOG_TX_BUFFERS << 13) | (leptr >> 16);
ib->tx_ptr = leptr;
- if (ZERO)
- printk("TX ptr: %8.8x(%8.8x)\n", leptr, libvaxdesc_offset(btx_ring, 0));
-#endif
- if (ZERO)
- printk("TX rings:\n");
-#if 1
+#ifdef VAX_LANCE_DEBUG
+ printk("TX ptr: %8.8lx(%8.8x)\n", leptr, libdesc_offset(btx_ring, 0));
+
+ printk("TX rings:\n");
+#endif
/* Setup the Tx ring entries */
for (i = 0; i < TX_RING_SIZE; i++) {
- leptr = (int) lp->tx_buf_ptr_lnc[i];
+ leptr = virt_to_phys(lp->lance_mem->tx_buf[i]) & 0xffffff;
+
ib->btx_ring[i].tmd0 = leptr;
ib->btx_ring[i].tmd1_hadr = leptr >> 16;
ib->btx_ring[i].tmd1_bits = 0;
ib->btx_ring[i].length = 0xf000; /* The ones required by tmd2 */
ib->btx_ring[i].misc = 0;
- if (i < 3 && ZERO)
- printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->tx_buf_ptr_cpu[i]);
+
+#ifdef VAX_LANCE_DEBUG
+ if (i < 3)
+ printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, (int) lp->lance_mem->tx_buf[i]);
+#endif
}
/* Setup the Rx ring entries */
- if (ZERO)
- printk("RX rings:\n");
+#ifdef VAX_LANCE_DEBUG
+ printk("RX rings:\n");
+#endif
for (i = 0; i < RX_RING_SIZE; i++) {
- leptr = (int) lp->rx_buf_ptr_lnc[i];
+ leptr = virt_to_phys(lp->lance_mem->rx_buf[i]) & 0xffffff;
+
ib->brx_ring[i].rmd0 = leptr;
ib->brx_ring[i].rmd1_hadr = leptr >> 16;
ib->brx_ring[i].rmd1_bits = LE_R1_OWN;
ib->brx_ring[i].length = -RX_BUFF_SIZE | 0xf000;
ib->brx_ring[i].mblength = 0;
- if (i < 3 && ZERO)
- printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]);
- }
+#ifdef VAX_LANCE_DEBUG
+ if (i < 3)
+ printk("%d: 0x%8.8lx(0x%8.8x)\n", i, leptr, (int) lp->lance_mem->rx_buf[i]);
#endif
+ }
}
static int init_restart_lance(struct lance_private *lp)
@@ -393,43 +401,58 @@
volatile struct lance_regs *ll = lp->ll;
int i;
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_INIT);
+ /* Is this needed? NetBSD does it. */
+ udelay(100);
+
+ writecsr0(ll, LE_C0_INIT);
/* Wait for the lance to complete initialization */
for (i = 0; (i < 100) && !(ll->rdp & LE_C0_IDON); i++) {
+#ifdef VAX_LANCE_DEBUG
printk("LANCE opened maybe %d\n", i);
+#endif
udelay(10);
}
if ((i == 100) || (ll->rdp & LE_C0_ERR)) {
+#ifdef VAX_LANCE_DEBUG
printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp);
+#endif
return -1;
}
if ((ll->rdp & LE_C0_ERR)) {
+#ifdef VAX_LANCE_DEBUG
printk("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp);
+#endif
return -1;
}
+#ifdef VAX_LANCE_DEBUG
printk("LANCE opened maybe\n");
- writereg(&ll->rdp, LE_C0_IDON);
- writereg(&ll->rdp, LE_C0_INEA|LE_C0_STRT);
- /* writereg(&ll->rdp, LE_C0_INEA);*/
+#endif
+ writecsr0(ll, LE_C0_IDON);
+ writecsr0(ll, LE_C0_INEA | LE_C0_STRT);
+ /* AM79C90 datasheet describes a problem in the original AM7990
+ whereby INEA cannot be set while STOP is set. What is not
+ clear is if setting INEA at the same time is STRT is OK.
+ So, just in case, we might need to set INEA again */
+ /* writecsr0(ll, LE_C0_INEA); */
+
return 0;
}
static int lance_rx(struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
- volatile struct lance_init_block *ib;
+ volatile struct lance_init_block *ib = lp->init_block;
volatile struct lance_rx_desc *rd = 0;
unsigned char bits;
int len = 0;
-#ifdef TEST_HITS
+#ifdef VAX_LANCE_DEBUG_BUFFERS
int i;
#endif
struct sk_buff *skb = 0;
- ib = (struct lance_init_block *) (dev->mem_start);
-#ifdef TEST_HITS
+
+#ifdef VAX_LANCE_DEBUG_BUFFERS
printk("[");
for (i = 0; i < RX_RING_SIZE; i++) {
@@ -484,7 +507,7 @@
skb_reserve(skb, 2); /* 16 byte align */
skb_put(skb, len); /* make room */
cp_from_buf(skb->data,
- (char *) lp->rx_buf_ptr_cpu[lp->rx_new],
+ (char *) lp->lance_mem->rx_buf[lp->rx_new],
len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
@@ -504,12 +527,11 @@
static void lance_tx(struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
- volatile struct lance_init_block *ib;
+ volatile struct lance_init_block *ib = lp->init_block;
volatile struct lance_regs *ll = lp->ll;
volatile struct lance_tx_desc *td;
int i, j;
int status;
- ib = (struct lance_init_block *) (dev->mem_start);
j = lp->tx_old;
spin_lock(&lp->lock);
@@ -532,9 +554,8 @@
if (status & LE_T3_CLOS) {
lp->stats.tx_carrier_errors++;
printk("%s: Carrier Lost", dev->name);
- /* Stop the lance */
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_STOP);
+
+ lance_stop(ll);
lance_init_ring(dev);
load_csrs(lp);
init_restart_lance(lp);
@@ -548,9 +569,8 @@
printk("%s: Tx: ERR_BUF|ERR_UFL, restarting\n",
dev->name);
- /* Stop the lance */
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_STOP);
+
+ lance_stop(ll);
lance_init_ring(dev);
load_csrs(lp);
init_restart_lance(lp);
@@ -590,17 +610,32 @@
volatile struct lance_regs *ll = lp->ll;
int csr0;
-printk("lance_interrupt: entered\n");
writereg(&ll->rap, LE_CSR0);
csr0 = ll->rdp;
+
+ if ((csr0 & LE_C0_INTR) == 0) {
+ /* Hmmm, not for us... */
+ return;
+ }
vsbus_clear_int(lp->vsbus_int);
- /* Acknowledge all the interrupt sources ASAP */
- writereg(&ll->rdp, csr0 & (LE_C0_INTR | LE_C0_TINT | LE_C0_RINT));
-
+
+ /* According to NetBSD, we need to temporarily disable the
+ interrupts here to get things to work properly all the
+ time */
+
+ /* temporarily disable interrupts from LANCE */
+ csr0 &= ~LE_C0_INEA;
+
+ /* Acknowledge all the interrupt sources */
+ writecsr0(ll, csr0);
+
+ /* re-enable interrupts from LANCE */
+ writecsr0(ll, LE_C0_INEA);
+
if ((csr0 & LE_C0_ERR)) {
/* Clear the error condition */
- writereg(&ll->rdp, LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
- LE_C0_CERR | LE_C0_MERR);
+ writecsr0(ll, LE_C0_BABL | LE_C0_ERR | LE_C0_MISS |
+ LE_C0_CERR | LE_C0_MERR);
}
if (csr0 & LE_C0_RINT)
lance_rx(dev);
@@ -616,36 +651,25 @@
if (csr0 & LE_C0_MERR) {
printk("%s: Memory error, status %04x", dev->name, csr0);
-#if 0
- volatile unsigned long int_stat = *(unsigned long *) (system_base + IOCTL + SIR);
- printk("%s: Memory error, status %04x", dev->name, csr0);
- if (int_stat & LANCE_DMA_MEMRDERR) {
- printk("%s: DMA error\n", dev->name);
- int_stat |= LANCE_DMA_MEMRDERR;
- /*
- * re-enable LANCE DMA
- */
- *(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
- }
-#endif
- writereg(&ll->rdp, LE_C0_STOP);
+ lance_stop(ll);
lance_init_ring(dev);
load_csrs(lp);
init_restart_lance(lp);
netif_wake_queue(dev);
}
- writereg(&ll->rdp, LE_C0_INEA);
- writereg(&ll->rdp, LE_C0_INEA);
+
+ /* FIXME: why is this really needed? */
+ writecsr0(ll, LE_C0_INEA);
}
struct net_device *last_dev = 0;
static int lance_open(struct net_device *dev)
{
- volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
struct lance_private *lp = (struct lance_private *) dev->priv;
+ volatile struct lance_init_block *ib = lp->init_block;
volatile struct lance_regs *ll = lp->ll;
int status = 0;
@@ -660,9 +684,7 @@
/* this is just a hack for now */
vsbus_enable_int(lp->vsbus_int);
- /* Stop the Lance */
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_STOP);
+ lance_stop(ll);
/* Clear the multicast filter */
ib->mode=0;
@@ -694,9 +716,7 @@
netif_stop_queue(dev);
del_timer_sync(&lp->multicast_timer);
- /* Stop the card */
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_STOP);
+ lance_stop(ll);
free_irq(dev->irq, (void *) dev);
/*
@@ -711,15 +731,13 @@
volatile struct lance_regs *ll = lp->ll;
int status;
- /* Stop the lance */
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_STOP);
+ lance_stop(ll);
lance_init_ring(dev);
load_csrs(lp);
dev->trans_start = jiffies;
status = init_restart_lance(lp);
-#ifdef DEBUG_DRIVER
+#ifdef VAX_LANCE_DEBUG
printk("Lance restart=%d\n", status);
#endif
return status;
@@ -740,7 +758,7 @@
{
struct lance_private *lp = (struct lance_private *) dev->priv;
volatile struct lance_regs *ll = lp->ll;
- volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
+ volatile struct lance_init_block *ib = lp->init_block;
int entry, skblen, len;
skblen = skb->len;
@@ -755,7 +773,7 @@
ib->btx_ring[entry].length = (-len) | 0xf000;
ib->btx_ring[entry].misc = 0;
- cp_to_buf((char *) lp->tx_buf_ptr_cpu[entry], skb->data, skblen);
+ cp_to_buf((char *) lp->lance_mem->tx_buf[entry], skb->data, skblen);
/* Clear the slack of the packet, do I need this? */
/* For a firewall its a good idea - AC */
@@ -771,7 +789,7 @@
netif_stop_queue(dev);
/* Kick the lance: transmit now */
- writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
+ writecsr0(ll, LE_C0_INEA | LE_C0_TDMD);
spin_unlock_irq(&lp->lock);
@@ -790,7 +808,8 @@
static void lance_load_multicast(struct net_device *dev)
{
- volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
+ struct lance_private *lp = (struct lance_private *) dev->priv;
+ volatile struct lance_init_block *ib = lp->init_block;
volatile u16 *mcast_table = (u16 *)&ib->filter;
struct dev_mc_list *dmi = dev->mc_list;
char *addrs;
@@ -842,11 +861,9 @@
static void lance_set_multicast(struct net_device *dev)
{
struct lance_private *lp = (struct lance_private *) dev->priv;
- volatile struct lance_init_block *ib;
+ volatile struct lance_init_block *ib = lp->init_block;
volatile struct lance_regs *ll = lp->ll;
- ib = (struct lance_init_block *) (dev->mem_start);
-
if (!netif_running(dev))
return;
@@ -858,8 +875,7 @@
netif_stop_queue(dev);
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_STOP);
+ lance_stop(ll);
lance_init_ring(dev);
@@ -883,7 +899,7 @@
volatile void *base_addr=NULL;
-static int __init vax_lance_init(struct net_device *dev, const int type)
+static int __init vax_lance_init(struct net_device *dev)
{
static unsigned version_printed = 0;
struct lance_private *lp;
@@ -895,11 +911,9 @@
unsigned long lance_phys_addr=KA43_LAN_BASE;
unsigned long esar_phys_addr=KA43_NWA_BASE;
- base_addr=ioremap(lance_phys_addr, 0x8);
- esar=ioremap(esar_phys_addr, 0x80);
- if (vax_lance_debug && version_printed++ == 0)
- printk(version);
-#if 1
+ if (version_printed++ == 0)
+ printk(version);
+
if (dev == NULL) {
dev = init_etherdev(0, sizeof(struct lance_private) + 8);
} else {
@@ -912,26 +926,31 @@
}
/* Make certain the data structures used by the LANCE are aligned. */
dev->priv = (void *) (((unsigned long) dev->priv + 7) & ~7);
-#else
- /* If this is dead code, let's remove it... - KPH 2001-03-04 */
- dev = init_etherdev(0, sizeof(struct lance_private));
- if (!dev)
- return -ENOMEM;
-#endif
lp = (struct lance_private *) dev->priv;
+
spin_lock_init(&lp->lock);
- /* Need to kmalloc a block of 64k */
- lp->buf_va = kmalloc(65536 + 7, GFP_KERNEL);
- if (lp->buf_va == NULL) {
- /* Should be free dev->priv here if dev was non-NULL on entry? */
+ /* Need a block of 64KB */
+ dev->mem_start = __get_free_pages(GFP_KERNEL, 4);
+ if (!dev->mem_start) {
+ /* Shouldn't we free dev->priv here if dev was non-NULL on entry? */
return -ENOMEM;
}
- /* Ensure alignment */
- lp->buf_va = (char *) (((unsigned long) lp->buf_va + 7) & ~7);
if (mv == &mv_ka43) {
+
+ /* FIXME:
+ We need to check if this block straddles the 16MB boundary. If
+ it does, then we can't use it for DMA. Instead we allocate
+ another 64KB block (which obviously cannot straddle the 16MB
+ boundary as well) and free the first.
+
+ We also need to set the magic bit in PARCTL if we are above
+ the 16MB boundary.
+
+ */
+
/* KA43 only.
*
* The KA43 seems to be nicely fscked up... All physical memory
@@ -942,57 +961,37 @@
* caches or something... If you don't do this you get evil
* "memory read parity error" machine checks.
*
- * We really need a cleaner way to do this, for two reasons:
- *
- * 1. This is wasteful of SPTEs since the region ends up
- * double-mapped
- * 2. I think other drivers (SCSI?) will need this too
*/
- dev->mem_start = (unsigned long) ioremap(virt_to_phys(lp->buf_va)|KA43_DIAGMEM, 65536);
- } else {
- /* other CPUs */
- dev->mem_start = (unsigned long) lp->buf_va;
+
+ /* You MUST remember to clear the DIAGMEM bits in these PTEs
+ before giving the pages back to free_pages() */
+
+ pte_t *p = GET_SPTE_VIRT(dev->mem_start);
+ for (i=0; i<(65536>>PAGE_SHIFT); i++, p++) {
+ set_pte(p, __pte(pte_val(*p) | (KA43_DIAGMEM >> PAGELET_SHIFT)));
+ __flush_tlb_one(dev->mem_start + i * PAGE_SIZE);
+ }
}
dev->mem_end = dev->mem_start + 65536;
+
+ /* FIXME: check this for NULL */
+ base_addr=ioremap(lance_phys_addr, 0x8);
+
dev->base_addr=(unsigned long)base_addr;
+ lp->lance_mem = (volatile struct lance_shared_mem *)(dev->mem_start);
+ lp->init_block = &(lp->lance_mem->init_block);
+
/* need something meaningful in here */
dev->irq = 0;
+ ll = (struct lance_regs *) base_addr;
- for (i = 0; i < RX_RING_SIZE; i++) {
- lp->rx_buf_ptr_cpu[i] =
- (char *) (dev->mem_start + BUF_OFFSET_CPU
- + i * RX_BUFF_SIZE);
-
- lp->rx_buf_ptr_lnc[i] =
- (char *) ((dev->mem_start + BUF_OFFSET_LNC
- + i * RX_BUFF_SIZE) & 0xFFFFFF);
-
- }
- for (i = 0; i < TX_RING_SIZE; i++) {
- lp->tx_buf_ptr_cpu[i] =
- (char *) (dev->mem_start + BUF_OFFSET_CPU
- + RX_RING_SIZE * RX_BUFF_SIZE
- + i * TX_BUFF_SIZE);
- lp->tx_buf_ptr_lnc[i] =
- (char *) ((dev->mem_start + BUF_OFFSET_LNC
- + RX_RING_SIZE * RX_BUFF_SIZE
- + i * TX_BUFF_SIZE) & 0xFFFFFF);
- }
+ /* FIXME: deal with failure here */
+ esar=ioremap(esar_phys_addr, 0x80);
- ll = (struct lance_regs *) base_addr;
-#if DEBUG_VAX_DRIVER
- printk("Hello %p\n",esar);
- {
- unsigned int x;
- for (x=0x50; x<0x7E; x++)
- printk("%02X %d \n", x, esar[x]);
- }
- printk("\nHello2 \n");
-#endif
/* prom checks */
#if 0
/* If this is dead code, let's remove it... - KPH 2001-03-04 */
@@ -1019,22 +1018,32 @@
* lance initialization block so the lance gets it every time it's
* (re)initialized.
*/
+ printk("Ethernet address in ROM: ");
for (i = 0; i < 6; i++) {
dev->dev_addr[i] = esar[i * 4];
- printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ',' : ':');
+ printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
}
+
+ /* Don't need this any more */
+ iounmap(esar);
+
lp->vsbus_int=5;
+
+#ifdef VAX_LANCE_AUTOPROBE_IRQ
+
+ printk("Autoprobing LANCE interrupt vector...");
-#if 1
vsbus_enable_int(lp->vsbus_int);
autoirq_setup(0);
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_STOP);
-
+ lance_stop(ll);
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_INEA|LE_C0_INIT);
+ /* Shouldn't we really load CSR1/2 with the address of a
+ reasonable init block, just in case the LANCE goes and
+ does something wild with whatever garbage it's currently
+ pointing to? - KPH 2001-03-06 */
+
+ writecsr0(ll, LE_C0_INEA|LE_C0_INIT);
dev->irq = autoirq_report(100);
@@ -1042,7 +1051,7 @@
vsbus_clear_int(lp->vsbus_int);
if (dev->irq)
- printk(" probed IRQ %d", dev->irq);
+ printk(" probed IRQ %d\n", dev->irq);
else
{
dev->irq=0x94;
@@ -1051,8 +1060,8 @@
/* Fill the dev fields */
#else
dev->irq=0x94;
+ printk("Using LANCE interrupt vector %d", dev->irq);
#endif
- printk(" irq = %d\n", dev->irq);
dev->open = &lance_open;
dev->stop = &lance_close;
dev->hard_start_xmit = &lance_start_xmit;
@@ -1093,20 +1102,6 @@
*/
#endif
-#if 0
- vsbus_enable_int(lp->vsbus_int);
- writereg(&ll->rap, LE_CSR0);
- writereg(&ll->rdp, LE_C0_STOP);
- lp->busmaster_regval=0;
- lance_init_ring(dev);
-
- netif_start_queue(dev);
- load_csrs(lp);
- init_restart_lance(lp);
-
- /* I'll try fecking something out from the card here soon - D.A. */
- vax_lance_test_xmit(dev);
-#endif
return 0;
err_out:
@@ -1125,7 +1120,7 @@
if (!called)
{
called=1;
- return vax_lance_init(dev, type);
+ return vax_lance_init(dev);
}
else
return -ENODEV;
@@ -1133,19 +1128,17 @@
__initcall(vax_lance_probe);
-/*
- #ifdef MODULE
- int
- init_module(void)
- {
+#ifdef MODULE
+
+int init_module(void)
+{
root_lance_dev = NULL;
return vax_lance_probe(NULL);
- }
+}
- void
- cleanup_module(void)
- {
+void cleanup_module(void)
+{
struct lance_private *lp;
while (root_lance_dev) {
@@ -1155,54 +1148,7 @@
kfree(root_lance_dev->dev);
root_lance_dev = lp;
}
- }
-
- #endif -* MODULE */
-unsigned char tx_block[30];
-
-#if 0
-static int vax_lance_test_xmit(struct net_device *dev)
-{
- struct lance_private *lp = (struct lance_private *) dev->priv;
- volatile struct lance_regs *ll = lp->ll;
- volatile struct lance_init_block *ib;
- unsigned long flags;
- int entry, skblen, len;
- int status = 0, i;
- static int outs;
-
- ib = (struct lance_init_block *) (dev->mem_start);
- printk("Attempt TX\n");
-
- // memset(tx_block, 0, 30);
- for (i=5; i<25; i++)
- tx_block[i-5]=i;
-
- skblen = 16;
- save_flags(flags);
- cli();
- len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
-
- lp->stats.tx_bytes += len;
-
- entry = lp->tx_new & TX_RING_MOD_MASK;
- ib->btx_ring[entry].length = (-len) | 0xf000;
- ib->btx_ring[entry].misc = 0;
-
- cp_to_buf((char *) lp->tx_buf_ptr_cpu[entry], tx_block, skblen);
-
- /* Now, give the packet to the lance */
- ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
- lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK;
-
- /* Kick the lance: transmit now */
- writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
- dev->trans_start = jiffies;
-
- if (TX_BUFFS_AVAIL<=0)
- netif_stop_queue(dev);
-
- restore_flags(flags);
- return status;
}
+
#endif
+
|