📄 lan91c111.c
字号:
//The driver for Lan91c111 only ////Made by Ray.xian in 51Board co,,td////6/18/05//#include <types.h>#include <setup.h>#include <stdio.h>#include <string.h>#include <io.h>#include <network.h>#include <hardware.h>#include <netdev.h>#include <time.h>//#include <cs8900.h>#include <lan91c111.h>#define u16(x) (*(volatile unsigned short *)(x))#define u32(x) (*(volatile unsigned int * )(x))#define LAN91C111_BASE_ADDR (0x0c000300)#define LAN91C111_CHIP_ID 0x3390#define report(fmt, args...) printf(fmt, ##args)#define assert(fmt, args...) printf(fmt, ##args)#define failed(fmt, args...) printf(fmt, ##args)static bool lan91c111_init(void);static void lan91c111_exit(void);static int lan91c111_recv_packet(void);static bool lan91c111_send_packet(void *packet, int len);static void lan91c111_enable(void);static void lan91c111_disable(void);extern clock_t timeout;static const unsigned long base = LAN91C111_BASE_ADDR;void test_get_reg();void sec_sleep(int second){ unsigned long nx_timer; nx_timer = clock() + CLOCKS_PER_SEC * second/2 ; while( clock()<nx_timer ) {};}void delay(time){ int i, j; for(i=0; i<time; i++) for(j=0; j<1000; j++);}static unsigned charreadforbyte(int offset){ unsigned char * iobase; unsigned char val; int act_offset, temp=0; iobase = (unsigned char *) base ; temp = offset>>8; //Determine the high byte(1) or low byte(0) act_offset = offset & 0xf; if (temp) //Only LAN91C111_INTERRUPT_M or LAN91C111_ARR val = (unsigned char)(*(iobase + act_offset +1)); else //Only LAN91C111_INTERRUPT or LAN91C111_PNR val = (unsigned char)(*(iobase + act_offset)); return val;}static unsigned shortreadforword(int offset){/*unsigned short * iobase ; int temp=0; iobase = (unsigned short *)base; temp = offset; offset >>= 1; if(offset == 0x6) return u16(base + offset); if(temp & 0x2) return (*(iobase + offset)>>16); else return ((*(iobase + offset)<<16) >>16 ); */ unsigned short * iobase; int act_offset = offset & 0xf; iobase = (unsigned short *)base; return *(iobase + (act_offset>>1) );}static void writeforword(int offset, unsigned short val){ // int temp; unsigned short * iobase= (unsigned short *)base; offset &= 0xf; offset >>= 1; *(iobase + offset)=val; }static voidwriteforbyte(int offset, unsigned short val){ unsigned char * iobase; int temp=0; iobase = (unsigned char *)base; temp = offset>>8; //determine low byte(0) or high byte(1) if (offset == LAN91C111_ARR) { printf("LAN91C111_ARR(BANK 2 ,OFFSET 3) is not allowed writed, only READ ONLY\n"); return ; } if (temp) // only the LAN91C111_INTERRUPT_M { *(iobase + (offset & 0xf) +1 ) = (unsigned char )val; } else // only the LAN91C111_INTERRUPT or LAN91C111_PNR { *(iobase + (offset & 0xf) ) = (unsigned char)val; }}//To detemine the reg belong to which bank;static void selectbank(int reg){ char i,whichbank=0; char temp =0; unsigned short * iobase = (unsigned short *)base; temp = (reg & 0x0f0)>>4 ; for(i=1 ; i <temp; i<<=1 ) whichbank ++;#if DEBUG & 1 printf("whichbank is 0x%08x\n", whichbank);#endif *(iobase + ((LAN91C111_BANK & 0xf)>>1) ) = (whichbank); // u32(base + (LAN91C111_BANK & 0xf) -2 ) = (whichbank<<16);#if DEBUG & 1 printf("bank is 0x%08x\n", u16(base + (LAN91C111_BANK&0xf)));#endif }//The rutine is devoted to get the register value; static unsigned shortget_reg(int reg){ unsigned short val=0; selectbank(reg); if ((reg == LAN91C111_PNR) || (reg == LAN91C111_ARR)) val = readforbyte(reg); else if ((reg == LAN91C111_INTERRUPT) || (reg == LAN91C111_INTERRUPT_M)) val = readforbyte(reg); else val = readforword(reg);#if DEBUG & 2 printf("reg 0x%08x\n value is 0x%08x\n", reg, val );#endif return val ;}//The rutine is devoted to set the register value;static void put_reg(int reg, unsigned short val ){ unsigned int * iobase; iobase = (unsigned int *)base; selectbank(reg); if( (reg==LAN91C111_PNR) || (reg==LAN91C111_ARR) ) writeforbyte(reg, val); else if( (reg==LAN91C111_INTERRUPT) || (reg==LAN91C111_INTERRUPT_M) ) writeforbyte(reg, val ); else writeforword(reg, val);}static unsigned shortlan91c111_read_phy( char phyaddr, char phyreg ){ unsigned short phy_info[32], i=0, mgmt_cur, value=0, in_dex, info=0; int mask; //Get the current value of MGMT mgmt_cur = get_reg(LAN91C111_MGMT); //Get the reserved bit of the MGMT mgmt_cur &= ~(MGMT_MSK_CRS100| MGMT_MDOE | MGMT_MCLK | MGMT_MDI | MGMT_MDO); //start code 01] phy_info[ info++ ] = MGMT_MDOE ; phy_info[ info++ ] = MGMT_MDOE | MGMT_MDO;//Read Command[10] phy_info[ info++ ] = MGMT_MDOE | MGMT_MDO; phy_info[ info++ ] = MGMT_MDOE;//PHY Addr[phyaddr] for(mask = 0x10; mask>0; mask >>=1) { if (phyaddr & mask) phy_info[ info++ ] = MGMT_MDOE | MGMT_MDO; else phy_info[ info++ ] = MGMT_MDOE; } //PHY REGISTER[phyreg] for(mask = 0x10; mask>0; mask>>=1) { if (phyreg & mask) phy_info[ info++ ] = MGMT_MDOE | MGMT_MDO; else phy_info[ info++ ] = MGMT_MDOE; } //Turnaround Time[00] phy_info[ info++ ] = 0; in_dex = info ;//REGISTER VALUE for(i=0; i<16; i++) phy_info[ info++ ] =0;//put PHY into IDLE modle for(i=0; i<32; i++) { put_reg(LAN91C111_MGMT, mgmt_cur | MGMT_MDOE | MGMT_MDO ); delay(50); put_reg(LAN91C111_MGMT, mgmt_cur | MGMT_MDOE | MGMT_MDO | MGMT_MCLK ); delay(50); }//input the management infomation first 16 bits for(i=0; i<32; i++) { put_reg( LAN91C111_MGMT, mgmt_cur | phy_info[i] ); delay(50); put_reg( LAN91C111_MGMT, mgmt_cur | phy_info[i] | MGMT_MCLK ); delay(50); phy_info[i] |= get_reg( LAN91C111_MGMT ) & MGMT_MDI ; }//put the PHY into IDLE state put_reg(LAN91C111_MGMT, mgmt_cur ); delay(50);//read the input value for(value=0, i=0; i<16; ++i) { value <<=1; if(phy_info[in_dex++] & MGMT_MDI) value |= 1; } return value;}static voidlan91c111_write_phy(char phyaddr, char phyreg, unsigned short value ){ unsigned short phy_info[32], mgmt_cur=0; int i=0, info=0, mask; mgmt_cur = get_reg(LAN91C111_MGMT); mgmt_cur &= ~(MGMT_MSK_CRS100 | MGMT_MDOE | MGMT_MCLK | MGMT_MDI | MGMT_MDO); //start bit[01] phy_info[ info++ ] = MGMT_MDOE; phy_info[ info++ ] = MGMT_MDOE | MGMT_MDO; //READ AND WRITE BIT[01] phy_info[ info++ ] = MGMT_MDOE; phy_info[ info++ ] = MGMT_MDOE | MGMT_MDO; //Add phy addr bits[phyaddr] for(mask=0x10; mask>0; mask>>=1) { if (phyaddr & mask) phy_info[ info++ ] = MGMT_MDOE | MGMT_MDO; else phy_info[ info++ ] = MGMT_MDOE; } //Add phy register bits[phyreg] for(mask=0x10; mask>0; mask>>=1) { if (phyreg & mask) phy_info[ info++ ] = MGMT_MDOE | MGMT_MDO; else phy_info[ info++ ] = MGMT_MDOE; } //Tristate and turnaround[00] phy_info[ info++ ] = 0; phy_info[ info++ ] = 0; //Add value into the 16bits[value] for( mask=0x8000; mask>0; mask>>=1 ) { if (value & mask) phy_info[ info++ ] = MGMT_MDOE | MGMT_MDO; else phy_info[ info++ ] = MGMT_MDOE ; } //put the phy into the idle state for(i=0; i<32; i++) { put_reg(LAN91C111_MGMT, mgmt_cur | MGMT_MDOE | MGMT_MDO ); delay( 50 ); put_reg(LAN91C111_MGMT, mgmt_cur | MGMT_MDOE | MGMT_MDO | MGMT_MCLK); delay( 50 ); } //trans the management into for(i=0; i<32; i++) { put_reg(LAN91C111_MGMT, phy_info[i] | mgmt_cur ); delay( 50 ); put_reg(LAN91C111_MGMT, phy_info[i] | mgmt_cur | MGMT_MCLK); delay( 50 ); } put_reg(LAN91C111_MGMT, mgmt_cur ); delay(50);}extern bool eth_init(void){ return lan91c111_init();}extern void eth_exit(void){ lan91c111_exit(); return;}extern bool eth_recv_poll(void){ return lan91c111_recv_packet();}extern bool eth_send(void *packet, int length){ return lan91c111_send_packet(packet, length);}extern void eth_enable(void){ lan91c111_enable(); return;}extern void eth_disable(void){ lan91c111_disable(); return;}extern void eth_set_haddr(const void *haddr){ const uint16 *mac = haddr; put_reg(LAN91C111_IA01, *mac++ ); put_reg(LAN91C111_IA23, *mac++ ); put_reg(LAN91C111_IA45, *mac++ ); // test_get_reg(); return;}static void put_data(int value){ unsigned short * iobase = (unsigned short *)base; selectbank(LAN91C111_DATA_HIGH); *(iobase + ((LAN91C111_DATA_HIGH & 0xf)>>1)) = value; }static unsigned int get_data_32(){ int val=0, offset; unsigned short * iobase=(unsigned short *)base; offset = ((LAN91C111_DATA_HIGH & 0xf)>>1); val = *((unsigned int *)(iobase + offset )); return val;}/*staticvoid test_ram_buffer() { unsigned short val=0; int j=0;// unsigned short * iobase = (unsigned short *) base;// unsigned int * iobase_32 = (unsigned int *)base; put_reg(LAN91C111_MMU_COMMAND, 0x20); while(!(get_reg(LAN91C111_INTERRUPT) & 0x08)){}; val = get_reg(LAN91C111_ARR); put_reg(LAN91C111_PNR, (val & 0x3f)); put_reg(LAN91C111_POINTER, 0x4000); for(j=0; j<1024; j++) { // put_reg(LAN91C111_POINTER, (0x0+j*2)); // *(iobase + ((LAN91C111_DATA_HIGH & 0xf)>>1)) = j*2; put_data(j*2); } put_reg(LAN91C111_POINTER, 0x6000); for(j=0; j<1024; j++) { // put_reg(LAN91C111_POINTER, (0x2000+j*2)); val = get_data(); // val = *(unsigned short *)(iobase + ((LAN91C111_DATA_HIGH & 0xf)>>1)); printf(" test ram buffer 0x%08x is 0x%08x\n" , j, val); if (val!= j*2) printf("i 0x%08x occour erro\n", j); }}*//*void test_transmit(){ unsigned short val, i; put_reg(LAN91C111_MMU_COMMAND, 0x0020 ); while(!(get_reg(LAN91C111_INTERRUPT) & 0x08 )){}; val = get_reg(LAN91C111_ARR); put_reg(LAN91C111_PNR, (val & 0x3f)); put_reg(LAN91C111_POINTER, 0x4000); //write_data put_data(0x0000); put_data(0x46); put_data(0xffff); put_data(0xffff); put_data(0xffff); put_data(0x0); put_data(0x0); put_data(0x0); put_data(0x0040); for(i=0; i<46; i++); put_data(i); put_data(0x0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -