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 + |