⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtl8139.c

📁 ucos_ii基础上加上网络功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
 * $Id: rtl8139.c,v 1.10 2002/02/21 08:25:00 linfusheng Exp $
 */


#include "includes.h"
#include "ether.h"
#include "nic.h"
#include "pci.h"
#include "pci_ids.h"

#include "ucos_timer.h"
#include "interrupt.h"




//#define USE_IO_OPS
		

#ifdef USE_IO_OPS

#define RTL_R8(reg)		UCOS_INB (((unsigned long)ioaddr) + (reg))
#define RTL_R16(reg)		UCOS_INW (((unsigned long)ioaddr) + (reg))
#define RTL_R32(reg)		((unsigned long) UCOS_IND (((unsigned long)ioaddr) + (reg)))
#define RTL_W8(reg, val8)	UCOS_OUTB ((val8), ((unsigned long)ioaddr) + (reg))
#define RTL_W16(reg, val16)	UCOS_OUTW ((val16), ((unsigned long)ioaddr) + (reg))
#define RTL_W32(reg, val32)	UCOS_OUTD ((val32), ((unsigned long)ioaddr) + (reg))
#define RTL_W8_F		RTL_W8
#define RTL_W16_F		RTL_W16
#define RTL_W32_F		RTL_W32
#else
#define RTL_R8(reg)		readb(((unsigned long)ioaddr) + (reg))
#define RTL_R16(reg)		readw(((unsigned long)ioaddr) + (reg))
#define RTL_R32(reg)		((unsigned long) readl (((unsigned long)ioaddr) + (reg)))
#define RTL_W8(reg, val8)	writeb ((val8), ((unsigned long)ioaddr) + (reg))
#define RTL_W16(reg, val16)	writew ((val16), ((unsigned long)ioaddr) + (reg))
#define RTL_W32(reg, val32)	writel ((val32), ((unsigned long)ioaddr) + (reg))
#define RTL_W8_F		RTL_W8
#define RTL_W16_F		RTL_W16
#define RTL_W32_F		RTL_W32


#endif







#undef DEBUG_RTL8139

#define DEBUG_RTL8139




/* Symbolic offsets to registers. */
enum RTL8139_registers {
	MAC0=0,			/* Ethernet hardware address. */
	MAR0=8,			/* Multicast filter. */
	TxStatus0=0x10,		/* Transmit status (four 32bit registers). */
	TxAddr0=0x20,		/* Tx descriptors (also four 32bit). */
	RxBuf=0x30, RxEarlyCnt=0x34, RxEarlyStatus=0x36,
	ChipCmd=0x37, RxBufPtr=0x38, RxBufAddr=0x3A,
	IntrMask=0x3C, IntrStatus=0x3E,
	TxConfig=0x40, RxConfig=0x44,
	Timer=0x48,		/* general-purpose counter. */
	RxMissed=0x4C,		/* 24 bits valid, write clears. */
	Cfg9346=0x50, Config0=0x51, Config1=0x52,
	TimerIntrReg=0x54,	/* intr if gp counter reaches this value */
	MediaStatus=0x58,
	Config3=0x59,
	MultiIntr=0x5C,
	RevisionID=0x5E,	/* revision of the RTL8139 chip */
	TxSummary=0x60,
	MII_BMCR=0x62, MII_BMSR=0x64, NWayAdvert=0x66, NWayLPAR=0x68,
	NWayExpansion=0x6A,
	DisconnectCnt=0x6C, FalseCarrierCnt=0x6E,
	NWayTestReg=0x70,
	RxCnt=0x72,		/* packet received counter */
	CSCR=0x74,		/* chip status and configuration register */
	PhyParm1=0x78,TwisterParm=0x7c,PhyParm2=0x80,	/* undocumented */
	/* from 0x84 onwards are a number of power management/wakeup frame
	 * definitions we will probably never need to know about.  */
};


enum ClearBitMasks {
	MultiIntrClear = 0xF000,
	ChipCmdClear = 0xE2,
	Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1),
};


enum ChipCmdBits {
	CmdReset=0x10, CmdRxEnb=0x08, CmdTxEnb=0x04, RxBufEmpty=0x01, };

/* Interrupt register bits, using my own meaningful names. */
enum IntrStatusBits {
	PCIErr=0x8000, PCSTimeout=0x4000, CableLenChange= 0x2000,
	RxFIFOOver=0x40, RxUnderrun=0x20, RxOverflow=0x10,
	TxErr=0x08, TxOK=0x04, RxErr=0x02, RxOK=0x01,

	RxAckBits = RxFIFOOver | RxOverflow | RxOK,
};
enum TxStatusBits {
	TxHostOwns=0x2000, TxUnderrun=0x4000, TxStatOK=0x8000,
	TxOutOfWindow=0x20000000, TxAborted=0x40000000,
	TxCarrierLost=0x80000000,

};
enum RxStatusBits {
	RxMulticast=0x8000, RxPhysical=0x4000, RxBroadcast=0x2000,
	RxBadSymbol=0x0020, RxRunt=0x0010, RxTooLong=0x0008, RxCRCErr=0x0004,
	RxBadAlign=0x0002, RxStatusOK=0x0001,
};

enum MediaStatusBits {
	MSRTxFlowEnable=0x80, MSRRxFlowEnable=0x40, MSRSpeed10=0x08,
	MSRLinkFail=0x04, MSRRxPauseFlag=0x02, MSRTxPauseFlag=0x01,
};

enum MIIBMCRBits {
	BMCRReset=0x8000, BMCRSpeed100=0x2000, BMCRNWayEnable=0x1000,
	BMCRRestartNWay=0x0200, BMCRDuplex=0x0100,
};

enum CSCRBits {
	CSCR_LinkOKBit=0x0400, CSCR_LinkChangeBit=0x0800,
	CSCR_LinkStatusBits=0x0f000, CSCR_LinkDownOffCmd=0x003c0,
	CSCR_LinkDownCmd=0x0f3c0,
};

/* Bits in RxConfig. */
enum rx_mode_bits {
	RxCfgWrap=0x80,
	AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0x08,
	AcceptMulticast=0x04, AcceptMyPhys=0x02, AcceptAllPhys=0x01,
};


/* Bits in TxConfig. */
enum tx_config_bits {
	TxIFG1 = (1 << 25),	/* Interframe Gap Time */
	TxIFG0 = (1 << 24),	/* Enabling these bits violates IEEE 802.3 */
	TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
	TxCRC = (1 << 16),	/* DISABLE appending CRC to end of Tx packets */
	TxClearAbt = (1 << 0),	/* Clear abort (WO) */
	TxDMAShift = 8,		/* DMA burst value (0-7) is shifted this many bits */
	TxRetryShift = 4,	/* TXRR value (0-15) is shifted this many bits */

	TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
};

static const unsigned short rtl8139_intr_mask =
	PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
	TxErr | TxOK | RxErr | RxOK;

/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 20;








/* PCI Tuning Parameters
   Threshold is bytes transferred to chip before transmission starts. */
#define TX_FIFO_THRESH 256	/* In bytes, rounded down to 32 byte units. */
/* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024, 7==end of packet. */
#define RX_FIFO_THRESH	6	/* Rx buffer level before first PCI xfer.  */
#define RX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
#define TX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */


/* Number of Tx descriptor registers. */
#define NUM_TX_DESC	4
/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/
#define MAX_ETH_FRAME_SIZE	1536
/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
#define TX_BUF_SIZE	MAX_ETH_FRAME_SIZE
#define TX_BUF_TOT_LEN	(TX_BUF_SIZE * NUM_TX_DESC)



/* Size of the in-memory receive ring. */
#define RX_BUF_LEN_IDX	2	/* 0==8K, 1==16K, 2==32K, 3==64K */
#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
#define RX_BUF_PAD 16
#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)



/* Operational parameters that usually are not changed. */
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT  6  


/* The RTL8139 can only transmit from a contiguous, aligned memory block.  */
static unsigned char tx_buffer[TX_BUF_TOT_LEN];
static unsigned char rx_ring[RX_BUF_TOT_LEN];




struct rtl_private_data{
	struct nic *nic;
	unsigned long dirty_tx;	/* 以处理的tx中断的偏移 */ 
	unsigned int tx_flag;
	unsigned int cur_rx;	/* Index into the Rx buffer of next Rx pkt. */
	unsigned long cur_tx;   /* 1个表示一个发送单元,一共有4个,但是递加不采用求余方式进行保护,因为
				这里我们设定为无符号数 */
	unsigned char *tx_buf[NUM_TX_DESC];	/* Tx bounce buffers */

};


/* PCI Tuning Parameters
   Threshold is bytes transferred to chip before transmission starts. */
#define N_RTL8139	4
struct rtl_private_data private_datas[N_RTL8139];
static unsigned long  ioaddr;






int read_eeprom(int location);
static void rtl_reset(struct nic* nic);
static int rtl_recv(struct nic *nic,unsigned char *packet,int *packetlen);
static int rtl_transmit(struct nic *nic,  char *data,int len);
static int rtl_ioctl(struct nic *nic,u_long cmd,caddr_t data);








/* Serial EEPROM section. */

/*  EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK    0x04    /* EEPROM shift clock. */
#define EE_CS           0x08    /* EEPROM chip select. */
#define EE_DATA_WRITE   0x02    /* EEPROM chip data in. */
#define EE_WRITE_0      0x00
#define EE_WRITE_1      0x02
#define EE_DATA_READ    0x01    /* EEPROM chip data out. */
#define EE_ENB          (0x80 | EE_CS)

/*
	Delay between EEPROM clock transitions.
	No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
*/

#define eeprom_delay()  RTL_R8(Cfg9346)

/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD    (5 << 6)
#define EE_READ_CMD     (6 << 6)
#define EE_ERASE_CMD    (7 << 6)

static int read_eeprom(int location)
{
	int i;
	unsigned int retval = 0;
	long ee_addr = ioaddr + Cfg9346;
	int read_cmd = location | EE_READ_CMD;

	RTL_W8(Cfg9346,EE_ENB & ~EE_CS);
	RTL_W8(Cfg9346,EE_ENB);

	/* Shift the read command bits out. */
	for (i = 10; i >= 0; i--) {
		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
		RTL_W8(Cfg9346,EE_ENB | dataval);
		eeprom_delay();
		RTL_W8(Cfg9346,EE_ENB | dataval | EE_SHIFT_CLK);
		eeprom_delay();
	}
	RTL_W8(Cfg9346,EE_ENB);
	eeprom_delay();

	for (i = 16; i > 0; i--) {
		RTL_W8(Cfg9346,EE_ENB | EE_SHIFT_CLK);
		eeprom_delay();
		retval = (retval << 1) | ((RTL_R8(Cfg9346) & EE_DATA_READ) ? 1 : 0);
		RTL_W8(Cfg9346,EE_ENB);
		eeprom_delay();
	}

	/* Terminate the EEPROM access. */
	RTL_W8(Cfg9346,~EE_CS);

	return retval;
}


static void rtl8139_rx_interrupt (struct rtl_private_data *private_data)
{
	unsigned int cur_rx;
#ifdef	DEBUG_RTL8139
	debug_print("enter rx_interrupt process \r\n ! ");
#endif
#ifdef	DEBUG_RTL8139
	debug_print("In rtl8139_rx(), current %4.4x BufAddr %4.4x,"
		 " free to %4.4x, Cmd %2.2x.\r\n", cur_rx,
		 RTL_R16 (RxBufAddr),
		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
#endif
	cur_rx = private_data->cur_rx;

	
	while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
		int ring_offset = cur_rx % RX_BUF_LEN;
		DWORD rx_status;
		unsigned int rx_size;
		unsigned int pkt_size;

		/* read size+status of next frame from DMA ring buffer */
		rx_status = (*(DWORD *) (rx_ring + ring_offset));
		rx_size = rx_status >> 16;
		pkt_size = rx_size - 4;

#ifdef	DEBUG_RTL8139
		debug_print ("rtl8139_rx() status %4.4x, size %4.4x,"
			 " cur %4.4x.\r\n", rx_status,
			 rx_size, cur_rx);

#endif
		/* Packet copy from FIFO still in progress.
		 * Theoretically, this should never happen
		 * since EarlyRx is disabled.
		 */
		if (rx_size == 0xfff0) {
			break;

		}

		/* If Rx err or invalid rx_size/rx_status received
		 * (which happens if we get lost in the ring),
		 * Rx process gets reset, so we abort any further
		 * Rx processing.
		 */
		if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
		    (rx_size < 8) ||
		    (!(rx_status & RxStatusOK))) {
			return;
		}

		/* Malloc up new buffer, compatible with net-2e. */
		/* Omit the four octet CRC from the length. */

		/* TODO: consider allocating skb's outside of
		 * interrupt context, both to speed interrupt processing,
		 * and also to reduce the chances of having to
		 * drop packets here under memory pressure.
		 */
		netif_rx(&rx_ring[ring_offset + 4], pkt_size,private_data->nic);

		cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
		RTL_W16 (RxBufPtr, cur_rx - 16);

		if (RTL_R16 (IntrStatus) & RxAckBits)
			RTL_W16_F (IntrStatus, RxAckBits);
	}

	private_data->cur_rx = cur_rx;

	return;
}

static void rtl8139_weird_interrupt(struct rtl_private_data *private_data)
{
#ifdef	DEBUG_RTL8139
	debug_print("enter weird_interrupt process \r\n !");
#endif
	return;
}
static void rtl8139_tx_interrupt (struct rtl_private_data *private_data)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -