patch-2.1.48 linux/arch/m68k/boot/atari/ethlance.c
Next file: linux/arch/m68k/boot/atari/ethlance.h
Previous file: linux/arch/m68k/boot/atari/bootstrap.h
Back to the patch index
Back to the overall index
- Lines: 436
- Date:
Wed Dec 31 16:00:00 1969
- Orig file:
v2.1.47/linux/arch/m68k/boot/atari/ethlance.c
- Orig date:
Wed Sep 25 00:47:39 1996
diff -u --recursive --new-file v2.1.47/linux/arch/m68k/boot/atari/ethlance.c linux/arch/m68k/boot/atari/ethlance.c
@@ -1,435 +0,0 @@
-
-#include <stdio.h>
-#include <string.h>
-
-#include "bootp.h"
-#include "ethlance.h"
-
-
-struct {
- volatile unsigned short *memaddr;
- volatile unsigned short *ioaddr;
-} lance_addr_list[] = {
- { (void *)0xfe010000, (void *)0xfe00fff0 }, /* RieblCard VME in TT */
- { (void *)0xfec10000, (void *)0xfec0fff0 }, /* RieblCard VME in MegaSTE
- (highest byte stripped) */
- { (void *)0xfee00000, (void *)0xfeff7000 }, /* RieblCard in ST
- (highest byte stripped) */
- { (void *)0xfecf0000, (void *)0xfecffff0 }, /* PAMCard VME in TT and MSTE
- (highest byte stripped) */
-};
-
-#define N_LANCE_ADDR (sizeof(lance_addr_list)/sizeof(*lance_addr_list))
-
-#define TX_RING_SIZE 1
-#define TX_RING_LEN_BITS 0
-
-#define RX_RING_SIZE 16
-#define RX_RING_LEN_BITS (4 << 5)
-
-#define offsetof(type,elt) ((unsigned long)(&(((type *)0)->elt)))
-
-/* 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! */
- 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) */
-};
-
-struct lance_packet {
- volatile unsigned char data[PKTLEN];
-};
-
-/* 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];
- struct lance_packet tx_packet[TX_RING_SIZE];
- struct lance_packet rx_packet[TX_RING_SIZE];
-};
-
-#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))
-
-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;
-};
-
-enum lance_type {
- OLD_RIEBL, /* old Riebl card without battery */
- NEW_RIEBL, /* new Riebl card with battery */
- PAM_CARD /* PAM card with EEPROM */
-} CardType;
-
-HWADDR dev_addr;
-
-/* 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.
- */
-
-HWADDR OldRieblDefHwaddr = {
- 0x00, 0x00, 0x36, 0x04, 0x00, 0x00
-};
-
-struct lance_ioreg *IO;
-struct lance_memory *MEM;
-
-#define DREG IO->data
-#define AREG IO->addr
-#define REGA(a) ( AREG = (a), DREG )
-
-int CurRx;
-
-
-/* Definitions for the Lance */
-
-/* tx_head flags */
-#define TMD1_ENP 0x01
-#define TMD1_STP 0x02
-#define TMD1_DEF 0x04
-#define TMD1_ONE 0x08
-#define TMD1_MORE 0x10
-#define TMD1_ERR 0x40
-#define TMD1_OWN 0x80
-
-#define TMD1_OWN_CHIP TMD1_OWN
-#define TMD1_OWN_HOST 0
-
-/* tx_head misc field */
-#define TMD3_TDR 0x03FF
-#define TMD3_RTRY 0x0400
-#define TMD3_LCAR 0x0800
-#define TMD3_LCOL 0x1000
-#define TMD3_UFLO 0x4000
-#define TMD3_BUFF3 0x8000
-
-/* rx_head flags */
-#define RMD1_ENP 0x01
-#define RMD1_STP 0x02
-#define RMD1_BUFF 0x04
-#define RMD1_CRC 0x08
-#define RMD1_OFLO 0x10
-#define RMD1_FRAM 0x20
-#define RMD1_ERR 0x40
-#define RMD1_OWN 0x80
-
-#define RMD1_OWN_CHIP RMD1_OWN
-#define RMD1_OWN_HOST 0
-
-/* register names */
-#define CSR0 0
-#define CSR1 1
-#define CSR2 2
-#define CSR3 3
-
-/* CSR0 */
-#define CSR0_INIT 0x0001 /* initialize */
-#define CSR0_STRT 0x0002 /* start */
-#define CSR0_STOP 0x0004 /* stop */
-#define CSR0_TDMD 0x0008 /* transmit demand */
-#define CSR0_TXON 0x0010 /* transmitter on */
-#define CSR0_RXON 0x0020 /* receiver on */
-#define CSR0_INEA 0x0040 /* interrupt enable */
-#define CSR0_INTR 0x0080 /* interrupt active */
-#define CSR0_IDON 0x0100 /* initialization done */
-#define CSR0_TINT 0x0200 /* transmitter interrupt */
-#define CSR0_RINT 0x0400 /* receiver interrupt */
-#define CSR0_MERR 0x0800 /* memory error */
-#define CSR0_MISS 0x1000 /* missed frame */
-#define CSR0_CERR 0x2000 /* carrier error (no heartbeat :-) */
-#define CSR0_BABL 0x4000 /* babble: tx-ed too many bits */
-#define CSR0_ERR 0x8000 /* error */
-
-/* CSR3 */
-#define CSR3_BCON 0x0001
-#define CSR3_ACON 0x0002
-#define CSR3_BSWP 0x0004
-
-
-#define HZ 200
-#define _hz_200 (*(volatile unsigned long *)0x4ba)
-
-
-
-
-/***************************** Prototypes *****************************/
-
-static int lance_probe( void );
-static int addr_readable( volatile void *regp, int wordflag );
-static int lance_init( void );
-static void lance_get_hwaddr( HWADDR *addr );
-static int lance_snd( Packet *pkt, int len );
-static int lance_rcv( Packet *pkt, int *len );
-
-/************************* End of Prototypes **************************/
-
-
-
-ETHIF_SWITCH LanceSwitch = {
- lance_probe, lance_init, lance_get_hwaddr,
- lance_snd, lance_rcv
-};
-
-
-static int lance_probe( void )
-
-{ int i;
-
- for( i = 0; i < N_LANCE_ADDR; ++i ) {
- if (addr_readable( lance_addr_list[i].memaddr, 1 ) &&
- (lance_addr_list[i].memaddr[0] = 1,
- lance_addr_list[i].memaddr[0] == 1) &&
- (lance_addr_list[i].memaddr[0] = 0,
- lance_addr_list[i].memaddr[0] == 0) &&
- addr_readable( lance_addr_list[i].ioaddr, 1 )) {
- break;
- }
- }
- if (i == N_LANCE_ADDR) return( -1 );
-
- IO = (struct lance_ioreg *)lance_addr_list[i].ioaddr;
- MEM = (struct lance_memory *)lance_addr_list[i].memaddr;
- REGA( CSR0 ) = CSR0_STOP;
-
- return( 0 );
-}
-
-
-static int addr_readable( volatile void *regp, int wordflag )
-
-{ int ret;
- long *vbr, save_berr;
-
- __asm__ __volatile__ ( "movec %/vbr,%0" : "=r" (vbr) : );
- save_berr = vbr[2];
-
- __asm__ __volatile__
- ( "movel %/sp,%/d1\n\t"
- "movel #Lberr,%2@\n\t"
- "moveq #0,%0\n\t"
- "tstl %3\n\t"
- "bne 1f\n\t"
- "tstb %1@\n\t"
- "bra 2f\n"
-"1: tstw %1@\n"
-"2: moveq #1,%0\n"
-"Lberr: movel %/d1,%/sp"
- : "=&d" (ret)
- : "a" (regp), "a" (&vbr[2]), "rm" (wordflag)
- : "d1", "memory"
- );
-
- vbr[2] = save_berr;
-
- return( ret );
-}
-
-
-static int lance_init( void )
-
-{ int i;
-
- /* Now test for type: If the eeprom I/O port is readable, it is a
- * PAM card */
- if (addr_readable( &(IO->eeprom), 0 )) {
- /* Switch back to Ram */
- i = IO->mem;
- CardType = PAM_CARD;
- }
- else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) {
- CardType = NEW_RIEBL;
- }
- else
- CardType = OLD_RIEBL;
-
- /* Get the ethernet address */
- switch( CardType ) {
- case OLD_RIEBL:
- /* No ethernet address! (Set some default address) */
- memcpy( dev_addr, OldRieblDefHwaddr, ETHADDRLEN );
- break;
- case NEW_RIEBL:
- memcpy( dev_addr, RIEBL_HWADDR_ADDR, ETHADDRLEN );
- break;
- case PAM_CARD:
- i = IO->eeprom;
- for( i = 0; i < ETHADDRLEN; ++i )
- dev_addr[i] =
- ((((unsigned short *)MEM)[i*2] & 0x0f) << 4) |
- ((((unsigned short *)MEM)[i*2+1] & 0x0f));
- i = IO->mem;
- break;
- }
-
- MEM->init.mode = 0x0000; /* Disable Rx and Tx. */
- for( i = 0; i < ETHADDRLEN; i++ )
- MEM->init.hwaddr[i] = dev_addr[i^1]; /* <- 16 bit swap! */
- MEM->init.filter[0] = 0x00000000;
- MEM->init.filter[1] = 0x00000000;
- MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head );
- MEM->init.rx_ring.adr_hi = 0;
- MEM->init.rx_ring.len = RX_RING_LEN_BITS;
- MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head );
- MEM->init.tx_ring.adr_hi = 0;
- MEM->init.tx_ring.len = TX_RING_LEN_BITS;
-
- REGA( CSR3 ) = CSR3_BSWP | (CardType == PAM_CARD ? CSR3_ACON : 0);
- REGA( CSR2 ) = 0;
- REGA( CSR1 ) = 0;
- REGA( CSR0 ) = CSR0_INIT | CSR0_STRT;
-
- i = 1000000;
- while( i-- > 0 )
- if (DREG & CSR0_IDON)
- break;
- if (i < 0 || (DREG & CSR0_ERR)) {
- DREG = CSR0_STOP;
- return( -1 );
- }
- DREG = CSR0_IDON;
-
- for (i = 0; i < TX_RING_SIZE; i++) {
- MEM->tx_head[i].base = offsetof( struct lance_memory, tx_packet[i] );
- MEM->tx_head[i].flag = TMD1_OWN_HOST;
- MEM->tx_head[i].base_hi = 0;
- MEM->tx_head[i].length = 0;
- MEM->tx_head[i].misc = 0;
- }
-
- for (i = 0; i < RX_RING_SIZE; i++) {
- MEM->rx_head[i].base = offsetof( struct lance_memory, rx_packet[i] );
- MEM->rx_head[i].flag = TMD1_OWN_CHIP;
- MEM->rx_head[i].base_hi = 0;
- MEM->rx_head[i].buf_length = -PKTLEN;
- MEM->rx_head[i].msg_length = 0;
- }
- CurRx = 0;
-
- return( 0 );
-}
-
-
-static void lance_get_hwaddr( HWADDR *addr )
-
-{
- memcpy( addr, dev_addr, ETHADDRLEN );
-}
-
-
-static int lance_snd( Packet *pkt, int len )
-
-{ unsigned long timeout;
-
- /* The old LANCE chips doesn't automatically pad buffers to min. size. */
- len = (len < 60) ? 60 : len;
- /* PAM-Card has a bug: Can only send packets with even number of bytes! */
- if (CardType == PAM_CARD && (len & 1))
- ++len;
-
- MEM->tx_head[0].length = -len;
- MEM->tx_head[0].misc = 0;
- memcpy( (void *)&MEM->tx_packet[0].data, pkt, len );
- MEM->tx_head[0].base = offsetof(struct lance_memory, tx_packet[0]);
- MEM->tx_head[0].base_hi = 0;
- MEM->tx_head[0].flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
-
- /* Trigger an immediate send poll. */
- REGA( CSR0 ) = CSR0_TDMD;
-
- /* Wait for packet being sent */
- timeout = _hz_200 + 3*HZ;
- while( (MEM->tx_head[0].flag & TMD1_OWN_CHIP) &&
- !MEM->tx_head[0].misc &&
- _hz_200 < timeout )
- ;
-
- if ((MEM->tx_head[0].flag & TMD1_OWN) == TMD1_OWN_HOST &&
- !(MEM->tx_head[0].misc & TMD1_ERR))
- /* sent ok */
- return( 0 );
-
- /* failure */
- if (_hz_200 >= timeout)
- return( ETIMEO );
- if (MEM->tx_head[0].misc & TMD3_UFLO) {
- /* On FIFO errors, must re-turn on TX! */
- DREG = CSR0_STRT;
- }
-
- return( ESEND );
-}
-
-
-static int lance_rcv( Packet *pkt, int *len )
-
-{ unsigned long timeout;
- int stat;
-
- /* Wait for a packet */
- timeout = _hz_200 + 4*HZ;
- while( (MEM->rx_head[CurRx].flag & TMD1_OWN_CHIP) &&
- _hz_200 < timeout )
- ;
- /* Not ours -> was a timeout */
- if (((stat = MEM->rx_head[CurRx].flag) & TMD1_OWN) == TMD1_OWN_CHIP)
- return( ETIMEO );
-
- /* Check for errors */
- if (stat != (RMD1_ENP|RMD1_STP)) {
- MEM->rx_head[CurRx].flag &= (RMD1_ENP|RMD1_STP);
- if (stat & RMD1_FRAM) return( EFRAM );
- if (stat & RMD1_OFLO) return( EOVERFL );
- if (stat & RMD1_CRC) return( ECRC );
- return( ERCV );
- }
-
- /* Get the packet */
- *len = MEM->rx_head[CurRx].msg_length & 0xfff;
- memcpy( pkt, (void *)&MEM->rx_packet[CurRx].data, *len );
-
- /* Give the buffer back to the chip */
- MEM->rx_head[CurRx].buf_length = -PKTLEN;
- MEM->rx_head[CurRx].flag |= RMD1_OWN_CHIP;
- CurRx = (CurRx + 1) % RX_RING_SIZE;
-
- return( 0 );
-}
-
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov