📄 cs8900.c
字号:
/*********************************************************** Copyright (c)* All rights reserved. ** 文件名称:cs8900.c* 文件标识:* 摘 要:本文件是对cs8900网络处理芯片的测试程序。* 当前版本:1.0* 作 者:刘征* 完成日期:2005.4.3** 取代版本:* 作 者:* 完成日期:**********************************************************//*********************************************************** 头文件**********************************************************/#include "cs8900.h"#include "Def.h"#include "option.h"#include "2410addr.h"#include "2410lib.h"#define DEBUGstatic unsigned short NetRxPackets[2*1024];static unsigned short dummy=0;/*********************************************************** 函数原型**********************************************************/static void Int_cs8900_init(void);static void __irq cs8000Int_Net(void);int eth_init (void);void eth_halt (void);int eth_rx (void);int eth_send (volatile void *packet, int length);/*********************************************************** 函数介绍:本函数是packet page register access functions。 * 输入参数:regno---register number* 输出参数:无* 返回值 :无**********************************************************/static unsigned short get_reg_init_bus (int regno){ /* force 16 bit busmode */ volatile unsigned char c=0; volatile unsigned short c1=0,c2=0; //init dummy = CS8900_BUS16_0; dummy = CS8900_BUS16_1; dummy = CS8900_BUS16_0; dummy = CS8900_BUS16_1; dummy = CS8900_BUS16_0; // TODO: check if this is correct and/or necessary// dummy = *(U8 *)(CS8900_BASE + 0x00) ; /* Dummy read, put chip in 16bit-mode */// dummy = *(U16 *)(CS8900_BASE + 0x00) ; CS8900_PPTR = regno;// c1 = (unsigned short) CS8900_PDATA; // CS8900_PPTR = regno+2;// c2 = (unsigned short) CS8900_PDATA; // return ((c2<<8) | c1); return (unsigned short) CS8900_PDATA;}/*********************************************************** 函数介绍:本函数是得到page register 的值。 * 输入参数:regno---register number* 输出参数:无* 返回值 :page register 的值**********************************************************/static unsigned short get_reg (int regno){ CS8900_PPTR = regno; return (unsigned short) CS8900_PDATA;}/*********************************************************** 函数介绍:本函数是设置page register 的值。 * 输入参数:regno---register number* val--- value* 输出参数:无* 返回值 :无**********************************************************/static void put_reg (int regno, unsigned short val){ CS8900_PPTR = regno; CS8900_PDATA = val;}/*********************************************************** 函数介绍:本函数是eth复位函数。 * 输入参数:无* 输出参数:无* 返回值 :无**********************************************************/static void eth_reset (void){ // set RESET bit CS8900_PPTR = PP_SelfCTL; // { the RESET bit will be cleared by the cs8900a // as a result of the reset } // RESET bit cleared? while((CS8900_PDATA & 0x0040) != 0); // TODO: add timeout // { after full initialization of the cs8900a // the INITD bit will be set } CS8900_PPTR = PP_SelfSTAT; // INITD bit still clear? while ((CS8900_PDATA & 0x0080) == 0); // TODO: add timeout // { INITD bit is set } }/*********************************************************** 函数介绍:本函数是eth register 复位函数。 * 输入参数:无* 输出参数:无* 返回值 :无**********************************************************/static void eth_reginit (void){ /* receive only error free packets addressed to this card */ put_reg (PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK); /* enable receive interrupt on receive operations */ put_reg (PP_RxCFG, 0x0003 | 0x0100/*RXIRQ*/); /* do not generate any interrupts on transmit operations */ put_reg (PP_TxCFG, 0x0007 | 0); /* use interrupt number 0*/ put_reg (PP_IntReg, PP_IntReg_IRQ0); /* interrupt before counter overflow on buffer operations */ put_reg (PP_BufCFG, 0x2000 | 0x1000); /* enable interrupt generation */ put_reg (PP_BusCTL, 0x0017 | 0x8000/*EnableIRQ*/); /* enable transmitter/receiver mode */ put_reg (PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);}/*********************************************************** 函数介绍:本函数是eth halt函数。 * 输入参数:无* 输出参数:无* 返回值 :无**********************************************************/void eth_halt (void){ /* disable transmitter/receiver mode */ put_reg (PP_LineCTL, 0); /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */ get_reg_init_bus (PP_ChipID);}/*********************************************************** 函数介绍:本函数是eth init函数。 * 输入参数:无* 输出参数:无* 返回值 :1--success* 0--failure**********************************************************/int eth_init (void){ U8 mac_addr[6]; volatile unsigned short uuuu = 0,uuuu1 = 0; //保证唯一的MAC地址 mac_addr[0] = 0x00; mac_addr[1] = 0x00; mac_addr[2] = 0x21; mac_addr[3] = 0xe1; mac_addr[4] = 0xc8; mac_addr[5] = 0xc2; uuuu = get_reg_init_bus (PP_ChipID); uuuu1 = get_reg_init_bus (PP_ChipID+2); uuuu1 = uuuu1 + uuuu; //uuuu = get_reg (PP_ChipID); /* verify chip id */ if (uuuu != 0x630e) { #ifdef DEBUG Uart_Printf ("CS8900 Ethernet chip not found?!\n"); #endif return 0; } else { #ifdef DEBUG Uart_Printf ("CS8900 Ethernet chip is 0x%6x!\n",get_reg_init_bus (PP_ChipID)); #endif } eth_reset (); /* set the ethernet address */ put_reg (PP_IA + 0, mac_addr[0] | (mac_addr[1] << 8)); put_reg (PP_IA + 2, mac_addr[2] | (mac_addr[3] << 8)); put_reg (PP_IA + 4, mac_addr[4] | (mac_addr[5] << 8)); eth_reginit (); return 1;}/*********************************************************** 函数介绍:本函数是Get a data block via Ethernet。 * 输入参数:无* 输出参数:无* 返回值 :rxlen--接收数据长度**********************************************************/int eth_rx (void){ int i; unsigned short rxlen; unsigned short *addr; unsigned short status; status = get_reg (PP_RER); if ((status & PP_RER_RxOK) == 0) return 0; status = CS8900_RTDATA; /* stat */ rxlen = CS8900_RTDATA; /* len */#ifdef DEBUG if (rxlen > PKTSIZE_ALIGN + PKTALIGN) Uart_Printf ("packet too big!\n");#endif /*NetRxPackets--接收数据的缓存区*/ for (addr = (unsigned short *) NetRxPackets[0], i = rxlen >> 1; i > 0;i--) { *addr++ = CS8900_RTDATA; } if (rxlen & 1) { *addr++ = CS8900_RTDATA; } /* Pass the packet up to the protocol layers. */// NetReceive (NetRxPackets[0], rxlen); return rxlen;}/*********************************************************** 函数介绍:本函数是Send a data block via Ethernet。 * 输入参数:packet--待发送数据包地址* length--长度* 输出参数:无* 返回值 :0**********************************************************/int eth_send (volatile void *packet, int length){ volatile unsigned short *addr; unsigned short s;retry: /* initiate a transmit sequence */ CS8900_TxCMD = PP_TxCmd_TxStart_Full; CS8900_TxLEN = length; /* Test to see if the chip has allocated memory for the packet */ if ((get_reg (PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) { /* Oops... this should not happen! */ #ifdef DEBUG Uart_Printf("cs: unable to send packet; retrying...\n"); #endif eth_reset (); eth_reginit (); goto retry; } /* Write the contents of the packet */ /* assume even number of bytes */ for (addr = packet; length > 0; length -= 2) { CS8900_RTDATA = *addr++; } /* wait for transfer to succeed */ while ((s = get_reg (PP_TER) & ~0x1F) == 0);//? /* nothing */ ; if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { #ifdef DEBUG Uart_Printf("\ntransmission error %#x\n", s); #endif } return 0;}/*********************************************************** 函数介绍:本函数是以太网接收、发送的中断处理函数。 * 输入参数:无* 输出参数:无* 返回值 :无**********************************************************/void cs8900_Isr(void){ // amount of ISQ's to handle (> 0) in one cs8900_service() call unsigned char events2service = 1; static unsigned short irq_status = 0x0000; // no unhandled irq_status left? if (irq_status == 0x0000) { // read ISQ register irq_status = get_reg (PP_ISQ); } // ISQ interrupt event, and allowed to service in this loop? while ((irq_status != 0x0000) && (events2service-- > 0)) { // investigate event if ((irq_status & 0x003f) == 0x0004/*Receiver Event*/) { // correctly received frame, either broadcast or individual address // TODO: think where these checks should appear: here or in cs8900_input() if ((irq_status & 0x0100/*RxOK*/) && (irq_status & 0x0c00/*Broadcast | Individual*/)) { // read the frame from the cs8900a eth_rx(); } else { // skip this frame put_reg (PP_RxCFG, 0x0040/*Skip_1*/); } } // read ISQ register irq_status = get_reg (PP_ISQ); }}/*********************************************************** 函数介绍:本函数被使用来做网络初始化,因为网络芯片中断* 触发脚接到2410的外部中断脚9,所以初始化时设置* 2410的外部中断9。而网络芯片产生高有效中断,因此* 要设置2410的外部中断9高有效。 * 输入参数:无* 输出参数:无* 返回值 :无**********************************************************/static void Int_cs8900_init(void){ rGPGCON = rGPGCON |(1<<3);//PG1 = EINT9 rEXTINT1 = rEXTINT1 | 0x1<<4; //EINT9 = high level triggered //设置中断入口函数 pISR_EINT8_23 = (U32)cs8000Int_Net; rEINTPEND = 0xffffff; ClearPending(BIT_EINT8_23); rINTMSK=~(BIT_EINT8_23);//开中断}/*********************************************************** 函数介绍:本函数是网络中断处理函数 * 输入参数:无* 输出参数:无* 返回值 :无**********************************************************/static void __irq cs8000Int_Net(void){ if(rEINTPEND==(1<<9)) { cs8900_Isr(); rEINTPEND=(1<<9); } ClearPending(BIT_EINT8_23);}/*********************************************************** 函数介绍:本函数是cs8900 init函数。 * 输入参数:无* 输出参数:无* 返回值 :无**********************************************************/void cs8900_Init(void){ unsigned char ru; ru = eth_init(); if (ru == 1)//init正确 { Uart_Printf("eth_init is ok!\n"); } else//init失败 { Uart_Printf("eth_init is not ok!\n"); return; } //网卡中断处理初始化函数 Int_cs8900_init(); }/*********************************************************** 函数介绍:本函数是cs8900 init函数。 * 输入参数:无* 输出参数:无* 返回值 :无**********************************************************/void Test_cs8900(void){ cs8900_Init(); while(1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -