📄 cs8900a.c
字号:
/*********************************************************************************************
* File: cs8900a.c
* Author: Embest
* Desc: cs8900a ethernet chip driver
* History:
*********************************************************************************************/
#include "2410lib.h"
#include "cs8900a.h"
/*------------------------------------------------------------------------------------------*/
/* macro define */
/*------------------------------------------------------------------------------------------*/
#define MEM_BASE 0x18000000 // nGCS3 -> net chip select
#define IO_BASE 0x19000300 // A24 should be '1', the cs8900a's I/O base address is 0x300
#define MAX_COUNT 0x00100000
#define io_write(addr, val) (*(volatile unsigned short *)(addr) = val)
#define io_read(addr) ((unsigned short)*(volatile unsigned short *)(addr))
/*------------------------------------------------------------------------------------------*/
/* inline functions define */
/*------------------------------------------------------------------------------------------*/
#ifdef MEM_MODE
inline void reg_write(unsigned short reg, unsigned short val)
{
io_write((MEM_BASE+reg), val);
}
inline unsigned short reg_read(unsigned short reg)
{
return io_read(MEM_BASE+reg);
}
#else // IO_MODE
void reg_write(unsigned short reg, unsigned short val)
{
io_write(IO_BASE+IO_PACKETPAGE_POINTER, reg);
io_write(IO_BASE+IO_PACKETPAGE_DATA0, val);
}
unsigned short reg_read(unsigned short reg)
{
io_write(IO_BASE+IO_PACKETPAGE_POINTER, reg);
return io_read(IO_BASE+IO_PACKETPAGE_DATA0);
}
#endif // MEM_MODE
/*------------------------------------------------------------------------------------------*/
/* global variables */
/*------------------------------------------------------------------------------------------*/
unsigned char mac_addr[6] = { 0x00,0x06,0x98,0x01,0x7E,0x8F};
unsigned char net_out_data[1536];
unsigned char net_in_data[1536];
int iReceiveData;
int iSendData;
/*********************************************************************************************
* name: CS_Probe
* func: probe 8019AS chip
* para: none
* ret: none
* modify:
* comment:
*********************************************************************************************/
int CS_Probe(void)
{
unsigned short id, sign;
#ifdef NDEBUG
while(1){
#endif
sign = io_read(IO_BASE+IO_PACKETPAGE_POINTER);
io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_Identification);
id = io_read(IO_BASE+IO_PACKETPAGE_DATA0);
#ifdef NDEBUG
uart_printf("\rsign=0x%x, id=0x%x",sign,id);
if(sign == ID_SIGNATURE || id == ID_CODE)
uart_printf(" success");
else
uart_printf(" fail!!!");
}
#endif
if(sign != ID_SIGNATURE || id != ID_CODE)
return 0;
return 1;
}
/*********************************************************************************************
* name: CS_SetupMemoryBase
* func: setup 8019AS chip memory map base address
* para: unsigned int base -- base address
* ret: none
* modify:
* comment:
*********************************************************************************************/
void CS_SetupMemoryBase(unsigned int base)
{
unsigned short temp;
// set memory map base address
io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_MemoryBaseAddress);
io_write(IO_BASE+IO_PACKETPAGE_DATA0, base & 0xffff);
io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_MemoryBaseAddress+2);
io_write(IO_BASE+IO_PACKETPAGE_DATA0, base >> 16);
// read bus control register
io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_BusCTL);
temp = io_read(IO_BASE+IO_PACKETPAGE_DATA0);
// enable memory map
temp |= MemoryE;
io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_BusCTL);
io_write(IO_BASE+IO_PACKETPAGE_DATA0, temp);
}
/*********************************************************************************************
* name: CS_Reset
* func: reset 8019AS chip
* para: unsigned int base -- base address
* ret: 1: reset success; 0: reset fail
* modify:
* comment:
*********************************************************************************************/
int CS_Reset(void)
{
int i;
unsigned short result;
// software reset
io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_SelfCTL);
io_write(IO_BASE+IO_PACKETPAGE_DATA0, RESET|SelfCTL_LOW);
// while INITD bit set
for(i=0; i<MAX_COUNT; i++)
{
io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_SelfST);
result = io_read(IO_BASE+IO_PACKETPAGE_DATA0);
if(result & INITD) break;
}
if(i >= MAX_COUNT)
return 0;
// while SIBUSY bit clean
for(i=0; i<MAX_COUNT; i++)
{
io_write(IO_BASE+IO_PACKETPAGE_POINTER, REG_SelfST);
result = io_read(IO_BASE+IO_PACKETPAGE_DATA0);
if((result & SIBUSY) == 0) break;
}
if(i >= MAX_COUNT)
return 0;
return 1;
}
/*********************************************************************************************
* name: CS_Identification
* func: Identification 8019AS chip
* para: unsigned short *rev -- pointer to return CS's identification
* ret: id: CS's ID
* modify:
* comment:
*********************************************************************************************/
unsigned short CS_Identification(unsigned short *rev)
{
unsigned int id;
id = reg_read(REG_Identification);
*rev = reg_read(REG_Identification+2);
return id;
}
/*********************************************************************************************
* name: CS_SetupMacAddr
* func: setup 8019AS chip's MAC
* para: unsigned char *mac -- pointer to MAC
* ret: none
* modify:
* comment:
*********************************************************************************************/
void CS_SetupMacAddr(unsigned char *mac)
{
reg_write(REG_IA, *(unsigned short *)(mac));
reg_write(REG_IA+2, *(unsigned short *)(mac+2));
reg_write(REG_IA+4, *(unsigned short *)(mac+4));
}
/*********************************************************************************************
* name: CS_EnableIrq
* func: enable 8019AS chip's interrupt
* para: int enable -- 0 or not
* ret: none
* modify:
* comment:
*********************************************************************************************/
void CS_EnableIrq(int enable)
{
unsigned short temp;
temp = reg_read(REG_BusCTL);
if(enable)
{
temp |= EnableIRQ;
reg_write(REG_InterruptNumber, INTRQ0);
}
else
{
temp &= ~EnableIRQ;
reg_write(REG_InterruptNumber, ALL_INTRQ_HI);
temp = reg_read(REG_ISQ);
temp &= LOW_BITS_MASK;
switch(temp)
{
case 0x04: reg_read(REG_RxEvent); break;
case 0x08: reg_read(REG_TxEvent); break;
case 0x0C: reg_read(REG_BufEvent); break;
case 0x10: reg_read(REG_RxMISS); break;
case 0x12: reg_read(REG_TxCOL); break;
}
}
}
/*********************************************************************************************
* name: CS_Configuration
* func: configure 8019AS chip
* para: none
* ret: none
* modify:
* comment:
*********************************************************************************************/
void CS_Configuration(void)
{
unsigned short temp;
// configure LineCTL
temp = reg_read(REG_LineCTL);
temp &= ~(AUIonly | AutoAUI_10BT);
temp |= (SerRxON | SerTxON | ModBackOffE);
reg_write(REG_LineCTL, temp);
// configure RxCTL
reg_write(REG_RxCTL, RxOKA | IdividualA | BroadcastA | RxCTL_LOW);
// configure RxCFG
reg_write(REG_RxCFG, RxCFG_LOW);
// configure TxCFG
reg_write(REG_TxCFG, TxCFG_LOW);
}
/*********************************************************************************************
* name: CS_Init
* func: initialize 8019AS chip
* para: none
* ret: 1: initialize success; 0: initialize fail
* modify:
* comment:
*********************************************************************************************/
int CS_Init(void)
{
unsigned short rev;
CS_Probe();
if(!CS_Reset())
{
uart_printf(" Reset CS8900A failed.\n");
return 0;
}
uart_printf(" Reset CS8900A successful, ");
#ifdef MEM_MODE
CS_SetupMemoryBase(MEM_BASE);
#endif
switch(rev)
{
case REV_B: uart_printf(" Rev B.\n"); break;
case REV_C: uart_printf(" Rev C.\n"); break;
case REV_D: uart_printf(" Rev D.\n"); break;
case REV_F: uart_printf(" Rev F.\n"); break;
}
CS_SetupMacAddr(mac_addr);
CS_EnableIrq(0);
CS_Configuration();
return 1;
}
/*********************************************************************************************
* name: CS_Close
* func: close 8019AS chip
* para: none
* ret: none
* modify:
* comment:
*********************************************************************************************/
void CS_Close(void)
{
CS_EnableIrq(0);
reg_read(REG_RxEvent);
reg_read(REG_TxEvent);
// cleanup LineCTL
reg_write(REG_LineCTL, LineCTL_LOW);
// cleanup RxCTL
reg_write(REG_RxCTL, RxCTL_LOW);
// cleanup RxCFG
reg_write(REG_RxCFG, RxCFG_LOW);
// cleanup TxCFG
reg_write(REG_TxCFG, TxCFG_LOW);
}
/*********************************************************************************************
* name: CS_ReceivePacket
* func: receive packet
* para: unsigned int tms -- periods
* ret: return the frame's length
* modify:
* comment:
*********************************************************************************************/
int CS_ReceivePacket(unsigned int tms)
{
int i, length;
unsigned short *buf;
tms *= 50;
while(tms)
{
unsigned short temp = reg_read(REG_ISQ);
temp = reg_read(REG_RxEvent);
if(temp & RxOK) break;
tms --;
}
if(tms == 0)
return 0;
// Discard RxStatus
reg_read(REG_RxStatus);
// Read the frame's length.
length = reg_read(REG_RxLength);
// Read frame
buf = (unsigned short *)net_in_data;
for(i=0; i<length; i+=2)
*buf++ = io_read(IO_BASE+IO_RX_TX_DATA0);
return length;
}
/*********************************************************************************************
* name: CS_TransmitPacket
* func: Transmit packet
* para: unsigned char *data -- data to be transmit
* int length -- length of data
* ret: 1: success 0: fail
* modify:
* comment:
*********************************************************************************************/
int CS_TransmitPacket(unsigned char *data, int length)
{
int i;
unsigned short *buf;
// Send Command
#ifdef MEM_MODE
reg_write(REG_TxCommand, TxStart | TxCMD_LOW);
reg_write(REG_TxLength, (unsigned short)length);
#else
io_write(IO_BASE+IO_TX_COMMAND, TxStart | TxCMD_LOW);
io_write(IO_BASE+IO_TX_LENGTH, (unsigned short)length);
#endif
// Wait
for(i = 0; i < MAX_COUNT; i++)
{
unsigned short temp = reg_read(REG_BusST);
if(temp & Rdy4TxNOW) break;
}
if(i >= MAX_COUNT)
return 0;
buf = (unsigned short *)data;
for(i=0; i<length; i+=2)
io_write(IO_BASE+IO_RX_TX_DATA0, *buf++);
iSendData = 0;
return 1;
}
/*********************************************************************************************
* name: NicInit
* func: initialize CS8900A chip
* para: none
* ret: none
* modify:
* comment:
*********************************************************************************************/
void NicInit(void)
{
CS_Init();
// delay some times
delay(100);
}
/*********************************************************************************************
* name: NicClose
* func: close CS8900A chip
* para: none
* ret: none
* modify:
* comment:
*********************************************************************************************/
void NicClose(void)
{
// close ethernet
CS_Close();
}
/*********************************************************************************************
* name: NicReset
* func: Reset CS8900A chip
* para: none
* ret: 0: success -1: fail
* modify:
* comment:
*********************************************************************************************/
int NicReset(void)
{
if(CS_Reset())
return 0;
return -1;
}
/*********************************************************************************************
* name: EtherOutput
* func: output data through ethernet CS8900A chip
* para: data -- data pointer
* len -- data length
* ret: 0: success -1: fail
* modify:
* comment:
*********************************************************************************************/
int EtherOutput(unsigned char *dmac, char* data, unsigned short len)
{
int i;
for(i=0; i<6; i++)
data[i] = dmac[i];
for(i=0; i<6; i++)
data[6+i] = mac_addr[i];
len += 14;
if(len < 60 )
len = 60;
if(len > 1518 )
{
uart_printf(" Cann't send data more than 1518 bytes!\n");
return -1;
}
if(!CS_TransmitPacket(data, len))
return -1;
iSendData = 0;
return 0;
}
/*********************************************************************************************
* name: EtherInput
* func: get data from ethernet CS8900A chip
* para: tms -- timeout value
* ret: none
* modify:
* comment:
*********************************************************************************************/
int EtherInput(unsigned short tms)
{
int length = CS_ReceivePacket(tms);
// Check frame length
if(length < 60 || length > 1518)
return 0;
iReceiveData = 1;
return length;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -