📄 cs8900.c
字号:
#include "cs8900.h"
#include "s3c44b0.h"
#include "lib_44b0.h"
unsigned short ReadReg(unsigned short offset);
void WriteReg(unsigned short offset, unsigned short value);
int ChipReset(void);
void CopyTxFrameToChip(void);
/* Ethernet physical address of the chip*/
unsigned char gEtherAddr[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
int gPrevTxBidFail = 0;
int gRxLength;
int gTxLength;
unsigned char gRxDataBuf[1520];
unsigned char gTxDataBuf[1520];
/***********************************************************************/
/* ReadReg(): Read value from the Packet Pointer register at regOffset */
/***********************************************************************/
unsigned short ReadReg(unsigned short offset)
{
CS8900_PPTR = offset;
return (CS8900_PDATA);
}
/***********************************************************************/
/* WriteReg(): Write value to the Packet Pointer register at regOffset */
/***********************************************************************/
void WriteReg(unsigned short offset, unsigned short value)
{
CS8900_PPTR = offset;
CS8900_PDATA = value;
}
/********************************************/
/* DelayForAWhile(): Take ~2.0 microseconds */
/********************************************/
void DelayForAWhile(void)
{
unsigned int t;
t = (*(volatile unsigned int *)(0));
}
/***********************************************/
/* ChipReset(): Software reset the CS8900 chip */
/***********************************************/
int ChipReset(void)
{
int j;
unsigned short status;
/* Reset chip */
WriteReg(PP_SelfCtl, PP_SelfCtl_Reset);
/* Wait about 125 msec for chip resetting in progress */
for (j=0; j<100; j++)
{
DelayForAWhile();
}
/* check the PP_SelfStat_InitD bit if the chip successflly reset */
for (j=0; j<3000; j++)
{
status=(ReadReg(PP_SelfStat) & PP_SelfStat_InitD);
if ( status != 0 ) return 0 /* successful */;
}
return -1; /* fail */
}
/*********************************************************************/
/* CopyTxFrameToChip(): Copy Tx data from user buffer to CS8900 chip */
/*********************************************************************/
void CopyTxFrameToChip()
{
int len;
unsigned short *sdata;
sdata = (unsigned short *)gTxDataBuf;
len = gTxLength;
if (len > 0)
{
/* Output contiguous words, two bytes at a time */
while (len > 1)
{
CS8900_RTDATA = *sdata;
sdata++;
len -= 2;
}
/* If Odd bytes, copy the last one byte to chip */
if (len == 1)
{
CS8900_RTDATA = *sdata;
}
}
/* return and wait for TxEvent Interrupt */
}
/*****************************************************/
/* cs8900_poll_init(): Start up CS8900 for Poll Mode */
/*****************************************************/
int cs8900_poll_init()
{
unsigned short chip_id, ia0, ia1, ia2;
int status;
/* gData */
gPrevTxBidFail = 0;
/* detect chip */
chip_id = ReadReg(PP_ChipID);
if (chip_id != CS8900_ID) return -1;
/* software reset the chip */
status = ChipReset();
if (status != 0) return -1;
/* set up ethernet hardware address */
ia0=gEtherAddr[0]|(gEtherAddr[1]<<8);
ia1=gEtherAddr[2]|(gEtherAddr[3]<<8);
ia2=gEtherAddr[4]|(gEtherAddr[5]<<8);
WriteReg(PP_IA+0, ia0 );
WriteReg(PP_IA+2, ia1 );
WriteReg(PP_IA+4, ia2 );
/* set to Promiscuous mode to receive all network traffic */
//WriteReg(PP_RxCTL, PP_RxCTL_Promiscuous|PP_RxCTL_RxOK);
/* configure RxCTL to receive good frames for Indivual Addr, Broadcast, and Multicast */
WriteReg(PP_RxCTL, PP_RxCTL_RxOK | PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_Multicast);
/* configure TestCTL (mode) */
/* default: 0:half duplex; 0x4000=Full duplex*/
WriteReg(PP_TestCTL, PP_TestCTL_HDX);
/* set SerRxOn, SerTxOn in LineCTL ******/
WriteReg(PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
return 0;
}
/****************************************************/
/* cs8900_poll_recv(): Receive a frame in Poll mode */
/****************************************************/
int cs8900_poll_recv()
{
unsigned short status, val;
int len;
unsigned short *data;
unsigned char *cp;
/* Step 1: check RxEvent Register */
status = ReadReg(PP_RER);
/* Step 2: Determine if there is Rx event */
/* If nothing happened, then return. 0x0004 is the register ID.
If some bits in Bit 6 - Bit 15 are set, some Rx event happened. */
if ( status == 0x0004 ) return 0;
/* Step 3: Determine if there is Rx Error */
/* If RxOk bit is not set, Rx Error occurred */
if ( !(status & PP_RER_RxOK) )
{
/* Step 4: skip this received error frame */
/* Note: Must skip this received error frame. Otherwise, CS8900 hangs here */
/* Read the length of Rx frame */
ReadReg(PP_Rx_LENGTH);
/* Write Skip1 to RxCfg Register and also keep the current configuration.*/
val = ReadReg(PP_RxCFG);
val |= PP_RxCFG_Skip1;
WriteReg(PP_RxCFG, val);
/* return failed */
return -1;
}
/* Step 5: Read the length of Rx frame */
gRxLength = ReadReg(PP_Rx_LENGTH);
/* Step 6: Read the Rx data from Chip and store it to user buffer */
data = (unsigned short *)gRxDataBuf;
len = gRxLength;
/* read 2 bytes at a time */
while (len >= 2)
{
*data = CS8900_RTDATA;
data++;
len -= 2;
}
/* if odd bytes, read the last byte from chip */
if (len == 1)
{
/* Read the last byte from chip */
val = CS8900_RTDATA;
/* point to the last one byte of the user buffer */
cp = (unsigned char *)data;
/* truncate the word (2-bytes) read from chip to one byte */
*cp = (unsigned char)(val & 0xff);
}
len = gRxLength;
return len;
}
/*****************************************************/
/* cs8900_poll_send(): Transmit a frame in Poll mode */
/*****************************************************/
int cs8900_poll_send()
{
int len;
unsigned short *sdata;
unsigned short status;
unsigned long i;
/* Step 0: First thing to do is to disable all interrupts at processor level */
/* These steps: Write the TX command, Bid for Tx, and copy Tx data to chip must be atomic
Otherwise, CS8900 may hang if interrupts occurs in the middle of these steps */
INT_DISABLE(26);
/* Step 1: Write the TX command */
if ( gPrevTxBidFail )
{
/* Previous BidForTX has reserved the Tx FIFO on CS8900, must clear off it.*/
/* Setting PP_TxCmd_Force bit will cause CS8900 to release the previous reserved Tx buffer.*/
CS8900_TxCMD = PP_TxCmd_TxStart_Full | PP_TxCmd_Force;
gPrevTxBidFail = 0;
}
else
{
CS8900_TxCMD = PP_TxCmd_TxStart_Full;
}
/* Step 2: Bid for Tx */
/* Write the frame length (Number of bytes to TX) */
/* Note: After the frame length has been written, CS8900 reserves Tx buffer for this bid no
matter PP_BusStat_TxRDY is set or not.*/
CS8900_TxLEN = gTxLength;
/* Read BusST to verify it is set as Rdy4Tx. */
status = ReadReg(PP_BusStat);
/* Step 3: check if TxBidErr happens ******/
if ( status & PP_BusStat_TxBid )
{
/* TxBidErr happens only if Tx_length is too small or too large */
INT_ENABLE(26);
return -1;
}
/* Step 4: check if chip is ready for Tx now */
/* If Bid4Tx not ready, skip the frame */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -