📄 atarilance.c
字号:
/* atarilance.c: Ethernet driver for VME Lance cards on the Atari *//* Written 1995/96 by Roman Hodek (Roman.Hodek@informatik.uni-erlangen.de) This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. This drivers was written with the following sources of reference: - The driver for the Riebl Lance card by the TU Vienna. - The modified TUW driver for PAM's VME cards - The PC-Linux driver for Lance cards (but this is for bus master cards, not the shared memory ones) - The Amiga Ariadne driver v1.0: (in 1.2.13pl4/0.9.13) Initial version v1.1: (in 1.2.13pl5) more comments deleted some debugging stuff optimized register access (keep AREG pointing to CSR0) following AMD, CSR0_STRT should be set only after IDON is detected use memcpy() for data transfers, that also employs long word moves better probe procedure for 24-bit systems non-VME-RieblCards need extra delays in memcpy must also do write test, since 0xfxe00000 may hit ROM use 8/32 tx/rx buffers, which should give better NFS performance; this is made possible by shifting the last packet buffer after the RieblCard reserved area v1.2: (in 1.2.13pl8) again fixed probing for the Falcon; 0xfe01000 hits phys. 0x00010000 and thus RAM, in case of no Lance found all memory contents have to be restored! Now possible to compile as module. v1.3: 03/30/96 Jes Sorensen, Roman (in 1.3) Several little 1.3 adaptions When the lance is stopped it jumps back into little-endian mode. It is therefore necessary to put it back where it belongs, in big endian mode, in order to make things work. This might be the reason why multicast-mode didn't work before, but I'm not able to test it as I only got an Amiga (we had similar problems with the A2065 driver).*/static char *version = "atarilance.c: v1.3 04/04/96 " "Roman.Hodek@informatik.uni-erlangen.de\n";#include <linux/module.h>#include <linux/stddef.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/ptrace.h>#include <linux/errno.h>#include <linux/malloc.h>#include <linux/interrupt.h>#include <linux/init.h>#include <asm/setup.h>#include <asm/irq.h>#include <asm/atarihw.h>#include <asm/atariints.h>#include <asm/bitops.h>#include <asm/io.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>/* Debug level: * 0 = silent, print only serious errors * 1 = normal, print error messages * 2 = debug, print debug infos * 3 = debug, print even more debug infos (packet data) */#define LANCE_DEBUG 1#ifdef LANCE_DEBUGstatic int lance_debug = LANCE_DEBUG;#elsestatic int lance_debug = 1;#endifMODULE_PARM(lance_debug, "i");/* Print debug messages on probing? */#undef LANCE_DEBUG_PROBE#define DPRINTK(n,a) \ do { \ if (lance_debug >= n) \ printk a; \ } while( 0 )#ifdef LANCE_DEBUG_PROBE# define PROBE_PRINT(a) printk a#else# define PROBE_PRINT(a)#endif/* These define the number of Rx and Tx buffers as log2. (Only powers * of two are valid) * Much more rx buffers (32) are reserved than tx buffers (8), since receiving * is more time critical then sending and packets may have to remain in the * board's memory when main memory is low. */#define TX_LOG_RING_SIZE 3#define RX_LOG_RING_SIZE 5/* These are the derived values */#define TX_RING_SIZE (1 << TX_LOG_RING_SIZE)#define TX_RING_LEN_BITS (TX_LOG_RING_SIZE << 5)#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)#define RX_RING_SIZE (1 << RX_LOG_RING_SIZE)#define RX_RING_LEN_BITS (RX_LOG_RING_SIZE << 5)#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)/* The LANCE Rx and Tx ring descriptors. */struct lance_rx_head { unsigned short base; /* Low word of base addr */ volatile unsigned char flag; unsigned char base_hi; /* High word of base addr (unused) */ short buf_length; /* This length is 2s complement! */ volatile short msg_length; /* This length is "normal". */};struct lance_tx_head { unsigned short base; /* Low word of base addr */ volatile unsigned char flag; unsigned char base_hi; /* High word of base addr (unused) */ short length; /* Length is 2s complement! */ volatile short misc;};struct ringdesc { unsigned short adr_lo; /* Low 16 bits of address */ unsigned char len; /* Length bits */ unsigned char adr_hi; /* High 8 bits of address (unused) */};/* The LANCE initialization block, described in databook. */struct lance_init_block { unsigned short mode; /* Pre-set mode */ unsigned char hwaddr[6]; /* Physical ethernet address */ unsigned filter[2]; /* Multicast filter (unused). */ /* Receive and transmit ring base, along with length bits. */ struct ringdesc rx_ring; struct ringdesc tx_ring;};/* The whole layout of the Lance shared memory */struct lance_memory { struct lance_init_block init; struct lance_tx_head tx_head[TX_RING_SIZE]; struct lance_rx_head rx_head[RX_RING_SIZE]; char packet_area[0]; /* packet data follow after the * init block and the ring * descriptors and are located * at runtime */};/* RieblCard specifics: * The original TOS driver for these cards reserves the area from offset * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the * Ethernet address there, and the magic for verifying the data's validity. * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe * is reserved for the interrupt vector number. */#define RIEBL_RSVD_START 0xee70#define RIEBL_RSVD_END 0xeec0#define RIEBL_MAGIC 0x09051990#define RIEBL_MAGIC_ADDR ((unsigned long *)(((char *)MEM) + 0xee8a))#define RIEBL_HWADDR_ADDR ((unsigned char *)(((char *)MEM) + 0xee8e))#define RIEBL_IVEC_ADDR ((unsigned short *)(((char *)MEM) + 0xfffe))/* This is a default address for the old RieblCards without a battery * that have no ethernet address at boot time. 00:00:36:04 is the * prefix for Riebl cards, the 00:00 at the end is arbitrary. */static unsigned char OldRieblDefHwaddr[6] = { 0x00, 0x00, 0x36, 0x04, 0x00, 0x00};/* I/O registers of the Lance chip */struct lance_ioreg {/* base+0x0 */ volatile unsigned short data;/* base+0x2 */ volatile unsigned short addr; unsigned char _dummy1[3];/* base+0x7 */ volatile unsigned char ivec; unsigned char _dummy2[5];/* base+0xd */ volatile unsigned char eeprom; unsigned char _dummy3;/* base+0xf */ volatile unsigned char mem;};/* Types of boards this driver supports */enum lance_type { OLD_RIEBL, /* old Riebl card without battery */ NEW_RIEBL, /* new Riebl card with battery */ PAM_CARD /* PAM card with EEPROM */};static char *lance_names[] = { "Riebl-Card (without battery)", "Riebl-Card (with battery)", "PAM intern card"};/* The driver's private device structure */struct lance_private { enum lance_type cardtype; struct lance_ioreg *iobase; struct lance_memory *mem; int cur_rx, cur_tx; /* The next free ring entry */ int dirty_tx; /* Ring entries to be freed. */ /* copy function */ void *(*memcpy_f)( void *, const void *, size_t ); struct net_device_stats stats;/* These two must be ints for set_bit() */ int tx_full; int lock;};/* I/O register access macros */#define MEM lp->mem#define DREG IO->data#define AREG IO->addr#define REGA(a) ( AREG = (a), DREG )/* Definitions for packet buffer access: */#define PKT_BUF_SZ 1544/* Get the address of a packet buffer corresponding to a given buffer head */#define PKTBUF_ADDR(head) (((unsigned char *)(MEM)) + (head)->base)/* Possible memory/IO addresses for probing */struct lance_addr { unsigned long memaddr; unsigned long ioaddr; int slow_flag;} lance_addr_list[] = { { 0xfe010000, 0xfe00fff0, 0 }, /* RieblCard VME in TT */ { 0xffc10000, 0xffc0fff0, 0 }, /* RieblCard VME in MegaSTE (highest byte stripped) */ { 0xffe00000, 0xffff7000, 1 }, /* RieblCard in ST (highest byte stripped) */ { 0xffd00000, 0xffff7000, 1 }, /* RieblCard in ST with hw modif. to avoid conflict with ROM (highest byte stripped) */ { 0xffcf0000, 0xffcffff0, 0 }, /* PAMCard VME in TT and MSTE (highest byte stripped) */ { 0xfecf0000, 0xfecffff0, 0 }, /* Rhotron's PAMCard VME in TT and MSTE (highest byte stripped) */};#define N_LANCE_ADDR (sizeof(lance_addr_list)/sizeof(*lance_addr_list))/* Definitions for the Lance *//* tx_head flags */#define TMD1_ENP 0x01 /* end of packet */#define TMD1_STP 0x02 /* start of packet */#define TMD1_DEF 0x04 /* deferred */#define TMD1_ONE 0x08 /* one retry needed */#define TMD1_MORE 0x10 /* more than one retry needed */#define TMD1_ERR 0x40 /* error summary */#define TMD1_OWN 0x80 /* ownership (set: chip owns) */#define TMD1_OWN_CHIP TMD1_OWN#define TMD1_OWN_HOST 0/* tx_head misc field */#define TMD3_TDR 0x03FF /* Time Domain Reflectometry counter */#define TMD3_RTRY 0x0400 /* failed after 16 retries */#define TMD3_LCAR 0x0800 /* carrier lost */#define TMD3_LCOL 0x1000 /* late collision */#define TMD3_UFLO 0x4000 /* underflow (late memory) */#define TMD3_BUFF 0x8000 /* buffering error (no ENP) *//* rx_head flags */#define RMD1_ENP 0x01 /* end of packet */#define RMD1_STP 0x02 /* start of packet */#define RMD1_BUFF 0x04 /* buffer error */#define RMD1_CRC 0x08 /* CRC error */#define RMD1_OFLO 0x10 /* overflow */#define RMD1_FRAM 0x20 /* framing error */#define RMD1_ERR 0x40 /* error summary */#define RMD1_OWN 0x80 /* ownership (set: ship owns) */#define RMD1_OWN_CHIP RMD1_OWN#define RMD1_OWN_HOST 0/* register names */#define CSR0 0 /* mode/status */#define CSR1 1 /* init block addr (low) */#define CSR2 2 /* init block addr (high) */#define CSR3 3 /* misc */#define CSR8 8 /* address filter */#define CSR15 15 /* promiscuous mode *//* CSR0 *//* (R=readable, W=writeable, S=set on write, C=clear on write) */#define CSR0_INIT 0x0001 /* initialize (RS) */#define CSR0_STRT 0x0002 /* start (RS) */#define CSR0_STOP 0x0004 /* stop (RS) */#define CSR0_TDMD 0x0008 /* transmit demand (RS) */#define CSR0_TXON 0x0010 /* transmitter on (R) */#define CSR0_RXON 0x0020 /* receiver on (R) */#define CSR0_INEA 0x0040 /* interrupt enable (RW) */#define CSR0_INTR 0x0080 /* interrupt active (R) */#define CSR0_IDON 0x0100 /* initialization done (RC) */#define CSR0_TINT 0x0200 /* transmitter interrupt (RC) */#define CSR0_RINT 0x0400 /* receiver interrupt (RC) */#define CSR0_MERR 0x0800 /* memory error (RC) */#define CSR0_MISS 0x1000 /* missed frame (RC) */#define CSR0_CERR 0x2000 /* carrier error (no heartbeat :-) (RC) */#define CSR0_BABL 0x4000 /* babble: tx-ed too many bits (RC) */#define CSR0_ERR 0x8000 /* error (RC) *//* CSR3 */#define CSR3_BCON 0x0001 /* byte control */#define CSR3_ACON 0x0002 /* ALE control */#define CSR3_BSWP 0x0004 /* byte swap (1=big endian) *//***************************** Prototypes *****************************/static int addr_accessible( volatile void *regp, int wordflag, int writeflag );static unsigned long lance_probe1( struct device *dev, struct lance_addr *init_rec );static int lance_open( struct device *dev );static void lance_init_ring( struct device *dev );static int lance_start_xmit( struct sk_buff *skb, struct device *dev );static void lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );static int lance_rx( struct device *dev );static int lance_close( struct device *dev );static struct net_device_stats *lance_get_stats( struct device *dev );static void set_multicast_list( struct device *dev );static int lance_set_mac_address( struct device *dev, void *addr );/************************* End of Prototypes **************************/void *slow_memcpy( void *dst, const void *src, size_t len ){ char *cto = dst; const char *cfrom = src; while( len-- ) { *cto++ = *cfrom++; MFPDELAY(); } return( dst );}__initfunc(int atarilance_probe( struct device *dev )){ int i; static int found = 0; if (!MACH_IS_ATARI || found) /* Assume there's only one board possible... That seems true, since * the Riebl/PAM board's address cannot be changed. */ return( ENODEV ); for( i = 0; i < N_LANCE_ADDR; ++i ) { if (lance_probe1( dev, &lance_addr_list[i] )) { found = 1; return( 0 ); } } return( ENODEV );}/* Derived from hwreg_present() in atari/config.c: */__initfunc(static int addr_accessible( volatile void *regp, int wordflag, int writeflag )){ int ret;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -