/*
* ni6510 (am7990 'lance' chip) driver for Linux-net-3
* BETAcode v0.71 (96/09/29) for 2.0.0 (or later)
* copyrights (c) 1994,1995,1996 by M.Hipp
*
* This driver can handle the old ni6510 board and the newer ni6510
* EtherBlaster. (probably it also works with every full NE2100
* compatible card)
*
* To compile as module, type:
* gcc -O2 -fomit-frame-pointer -m486 -D__KERNEL__ -DMODULE -c ni65.c
* driver probes: io: 0x360,0x300,0x320,0x340 / dma: 3,5,6,7
*
* This is an extension to the Linux operating system, and is covered by the
* same GNU General Public License that covers the Linux-kernel.
*
* comments/bugs/suggestions can be sent to:
* Michael Hipp
* email: hippm@informatik.uni-tuebingen.de
*
* sources:
* some things are from the 'ni6510-packet-driver for dos by Russ Nelson'
* and from the original drivers by D.Becker
*
* known problems:
* - on some PCI boards (including my own) the card/board/ISA-bridge has
* problems with bus master DMA. This results in lotsa overruns.
* It may help to '#define RCV_PARANOIA_CHECK' or try to #undef
* the XMT and RCV_VIA_SKB option .. this reduces driver performance.
* Or just play with your BIOS options to optimize ISA-DMA access.
* Maybe you also wanna play with the LOW_PERFORAMCE and MID_PERFORMANCE
* defines -> please report me your experience then
* - Harald reported for ASUS SP3G mainboards, that you should use
* the 'optimal settings' from the user's manual on page 3-12!
*
* credits:
* thanx to Jason Sullivan for sending me a ni6510 card!
* lot of debug runs with ASUS SP3G Boards (Intel Saturn) by Harald Koenig
*
* simple performance test: (486DX-33/Ni6510-EB receives from 486DX4-100/Ni6510-EB)
* average: FTP -> 8384421 bytes received in 8.5 seconds
* (no RCV_VIA_SKB,no XMT_VIA_SKB,PARANOIA_CHECK,4 XMIT BUFS, 8 RCV_BUFFS)
* peak: FTP -> 8384421 bytes received in 7.5 seconds
* (RCV_VIA_SKB,XMT_VIA_SKB,no PARANOIA_CHECK,1(!) XMIT BUF, 16 RCV BUFFS)
*/
/*
* 99.Jun.8: added support for /proc/net/dev byte count for xosview (HK)
* 96.Sept.29: virt_to_bus stuff added for new memory modell
* 96.April.29: Added Harald Koenig's Patches (MH)
* 96.April.13: enhanced error handling .. more tests (MH)
* 96.April.5/6: a lot of performance tests. Got it stable now (hopefully) (MH)
* 96.April.1: (no joke ;) .. added EtherBlaster and Module support (MH)
* 96.Feb.19: fixed a few bugs .. cleanups .. tested for 1.3.66 (MH)
* hopefully no more 16MB limit
*
* 95.Nov.18: multicast tweaked (AC).
*
* 94.Aug.22: changes in xmit_intr (ack more than one xmitted-packet), ni65_send_packet (p->lock) (MH)
*
* 94.July.16: fixed bugs in recv_skb and skb-alloc stuff (MH)
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/module.h>
#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#include "ni65.h"
/*
* the current setting allows an acceptable performance
* for 'RCV_PARANOIA_CHECK' read the 'known problems' part in
* the header of this file
* 'invert' the defines for max. performance. This may cause DMA problems
* on some boards (e.g on my ASUS SP3G)
*/
#undef XMT_VIA_SKB
#undef RCV_VIA_SKB
#define RCV_PARANOIA_CHECK
#define MID_PERFORMANCE
#if defined( LOW_PERFORMANCE )
static int isa0=7,isa1=7,csr80=0x0c10;
#elif defined( MID_PERFORMANCE )
static int isa0=5,isa1=5,csr80=0x2810;
#else /* high performance */
static int isa0=4,isa1=4,csr80=0x0017;
#endif
/*
* a few card/vendor specific defines
*/
#define NI65_ID0 0x00
#define NI65_ID1 0x55
#define NI65_EB_ID0 0x52
#define NI65_EB_ID1 0x44
#define NE2100_ID0 0x57
#define NE2100_ID1 0x57
#define PORT p->cmdr_addr
/*
* buffer configuration
*/
#if 1
#define RMDNUM 16
#define RMDNUMMASK 0x80000000
#else
#define RMDNUM 8
#define RMDNUMMASK 0x60000000 /* log2(RMDNUM)<<29 */
#endif
#if 0
#define TMDNUM 1
#define TMDNUMMASK 0x00000000
#else
#define TMDNUM 4
#define TMDNUMMASK 0x40000000 /* log2(TMDNUM)<<29 */
#endif
/* slightly oversized */
#define R_BUF_SIZE 1544
#define T_BUF_SIZE 1544
/*
* lance register defines
*/
#define L_DATAREG 0x00
#define L_ADDRREG 0x02
#define L_RESET 0x04
#define L_CONFIG 0x05
#define L_BUSIF 0x06
/*
* to access the lance/am7990-regs, you have to write
* reg-number into L_ADDRREG, then you can access it using L_DATAREG
*/
#define CSR0 0x00
#define CSR1 0x01
#define CSR2 0x02
#define CSR3 0x03
#define INIT_RING_BEFORE_START 0x1
#define FULL_RESET_ON_ERROR 0x2
#if 0
#define writereg(val,reg) {outw(reg,PORT+L_ADDRREG);inw(PORT+L_ADDRREG); \
outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);}
#define readreg(reg) (outw(reg,PORT+L_ADDRREG),inw(PORT+L_ADDRREG),\
inw(PORT+L_DATAREG))
#if 0
#define writedatareg(val) {outw(val,PORT+L_DATAREG);inw(PORT+L_DATAREG);}
#else
#define writedatareg(val) { writereg(val,CSR0); }
#endif
#else
#define writereg(val,reg) {outw(reg,PORT+L_ADDRREG);outw(val,PORT+L_DATAREG);}
#define readreg(reg) (outw(reg,PORT+L_ADDRREG),inw(PORT+L_DATAREG))
#define writedatareg(val) { writereg(val,CSR0); }
#endif
static unsigned char ni_vendor[] = { 0x02,0x07,0x01 };
static struct card {
unsigned char id0,id1;
short id_offset;
short total_size;
short cmd_offset;
short addr_offset;
unsigned char *vendor_id;
char *cardname;
un