?? cs8900a.c
字號:
/*********************************************************************************************
* File: cs8900a.c
* Author: Embest
* Desc: cs8900a ethernet chip driver
* History:
*********************************************************************************************/
#include "cs8900a.h"
#define MEM_BASE 0x06000000
#define IO_BASE 0x07000300
#define MAX_COUNT 0x00100000
#define io_write(addr, val) (*(volatile unsigned short *)(addr) = val)
#define io_read(addr) ((unsigned short)*(volatile unsigned short *)(addr))
#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 */
inline 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);
}
inline 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 */
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;
int CS_Probe(void)
{
unsigned short id, sign;
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);
if(sign != ID_SIGNATURE || id != ID_CODE)
return 0;
return 1;
}
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);
}
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;
}
unsigned short CS_Identification(unsigned short *rev)
{
unsigned int id;
id = reg_read(REG_Identification);
*rev = reg_read(REG_Identification+2);
return id;
}
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));
}
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;
}
}
}
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);
}
int CS_Init(void)
{
unsigned short id, 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
id = CS_Identification(&rev);
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;
}
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);
}
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);
#ifdef MEM_MODE
#else
*(volatile unsigned char *)(IO_BASE+IO_RX_TX_DATA0);
#endif
/* 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;
}
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;
}
/*
* extern functions
*/
/*********************************************************************************************
* 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 + -