⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ethernet_cs8900a.c

📁 Intrisyc 公司的PXA255-bootloader,源码易懂
💻 C
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////////////////// Copyright(c) 2001 Intrinsyc Software Inc. All rights reserved.//// Module name:////      ethernet_cs8900a.c//// Description:////      Driver for the Crystal CS8900a ethernet chip.//// Author:////      Mike Kirkland//// Created:////      October 2001////////////////////////////////////////////////////////////////////////////////////We want failures to get to the user#define _DEBUG#define _DEBUG_FAIL#include <ethernet_cs8900a.h>#include <ethernet.h>#include <string.h>#include <util.h>#include <net.h>#include <types.h>#include <timer.h>#include <c_main.h>#include <messages.h>#include <debug.h>////////////////////////////////////////////////////////////////////////////////// readcs// PURPOSE: Reads data from a specified packetpage register on the CS89x0// PARAMS:  (IN) u16 csreg - register to read from// RETURNS:  u16 value of specified register////////////////////////////////////////////////////////////////////////////////inline static u16readcs(u16 csreg){   *(volatile u16 *)(BASE_ADDR + ADDRESS_PORT) = csreg;   return (*(volatile u16 *)(BASE_ADDR + DATA_PORT));}////////////////////////////////////////////////////////////////////////////////// writecs// PURPOSE: Writes a u16 to a specified packetpage register on the CS89x0// PARAMS:  (IN) u16 csreg - register to write to//          (IN) u16 lhv - data to write to register// RETURNS: Nothing.////////////////////////////////////////////////////////////////////////////////inline static voidwritecs(u16 csreg,        u16 lhv){   *(volatile u16 *)(BASE_ADDR + ADDRESS_PORT) = csreg;   *(volatile u16 *)(BASE_ADDR + DATA_PORT) = lhv;}////////////////////////////////////////////////////////////////////////////////// notbusy// PURPOSE: Wait for Crystal chip to stop being busy// PARAMS:  None.// RETURNS: None.////////////////////////////////////////////////////////////////////////////////static voidnotbusy(void){   while(readcs(SSR) & SSR_BUSY)   {      ; //do nothing   }}////////////////////////////////////////////////////////////////////////////////// probe_cs8900a// PURPOSE: Look for signs of a CS8900A at the given address// PARAMS:  (OUT) u16 * address to check// RETURNS: 1 for success, 0 for failure.// NOTE:    This function is safe to call even right after a reset////////////////////////////////////////////////////////////////////////////////static intprobe_cs8900a(char *address){/*   // The data sheet only says this is valid after a hard reset   if(((*(volatile u16 *)(address + ADDRESS_PORT)) & SCAN_MASK) != SCAN_SIG)   {      return 0;   }*/   // We are allowed to read this register even during a reset   // (so says Cirrus AN205)   if((readcs(SSR) & REG_NUMB_MASK) != 0x16)   {      return 0;   }   return 1;}////////////////////////////////////////////////////////////////////////////////// toggle_sbhe// PURPOSE: Toggle the /SBHE line on the CS8900// PARAMS:  None.// RETURNS: None.// NOTES:   This is really ugly, as we have to access PCMCIA I/O space in order//          to control A0, which is connected to /SBHE.////////////////////////////////////////////////////////////////////////////////static voidtoggle_sbhe(void){   u8 volatile temp;   temp = *(u8 volatile *)(PCMCIA_SOCKET_0_IO_BASE + 1);   temp = *(u8 volatile *)(PCMCIA_SOCKET_0_IO_BASE + 0);   temp = *(u8 volatile *)(PCMCIA_SOCKET_0_IO_BASE + 1);   temp = *(u8 volatile *)(PCMCIA_SOCKET_0_IO_BASE + 0);}////////////////////////////////////////////////////////////////////////////////// init_ethernet// PURPOSE: Initializes the cs8900a ethernet chip.// PARAMS:  (OUT) u16 * to return the MAC address.// RETURNS: 1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////intinit_ethernet(u16 *macaddr){   u16 mac[3];   DEBUG_4("Initializing CS8900\r\n");   // Toggle /SBHE before we try probing the chip   toggle_sbhe();   // Look for signs of a CS8900A before we start doing things to it   if (!probe_cs8900a((char *)BASE_ADDR))   {      error_print(CS_NOTFOUND_ERROR);      DEBUG_1("(at address %x)\r\n", BASE_ADDR);      return 0;   }   itc_printf("CS8900A found at 0x%x\r\n", BASE_ADDR);   // Reset CS8900 chip   writecs(SCR, readcs(SCR) | POWER_ON_RESET);   // Must delay for some time here or else the chip might never come alive.   // This seem to happen with certain invalid contents of the EEPROM.   udelay(10000);   // Must toggle /SBHE again after reset   toggle_sbhe();   //DEBUG_4("Waiting for CS8900...");   // Wait for chip to finish resetting (takes up to 10 ms)   while(!(readcs(SSR) & SSR_INITD))   {      ; //do nothing   }   DEBUG_4("CS8900 reset\r\n");   if(readcs(CS8900ID) != CS89x0_ISA_ID)   {      error_print(CS_ISAID_ERROR);      return 0;   }   if((readcs(PROD_ID) & PROD_ID_MASK) != CS8900ID)   {      error_print(CS_NOTCS_ERROR);      return 0;   }   if(((*(volatile u16 *)(BASE_ADDR + TX_CMD_PRT)) &      REG_NUMB_MASK) != REG_NUMB_TX_CMD)   {      error_print(CS_NOTX_ERROR);      return 0;   }   //check the Line Status Register to see if cabling is plugged in.   // NOTE: this might not be reliable unless we wait a bit first   if((readcs(LSR) & LSR_OK) == 0)   {      DEBUG_1("Link disconnected.\r\n");   }   else   {      DEBUG_2("Link connected\r\n");   }   if (!read_mac_ethernet(mac, 0))   {      error_print(CS_NOMAC_ERROR);      return 0;   }   macaddr[0] = mac[0];   macaddr[1] = mac[1];   macaddr[2] = mac[2];   //write MAC to the address reg   //this is already done if the EEPROM uses the reset configuration block   //but won't be if the MAC address was written with an old version of I-Boot   writecs(IAR, mac[0]);   writecs(IAR+2, mac[1]);   writecs(IAR+4, mac[2]);   //Take interrupt and DMA lines out of high impedance state   writecs(INR, 0);   writecs(DCR, 0);   //IO channel ready on   writecs(BCR, (readcs(BCR) | BCR_IO_CHN_ON));   //set Rx Config Register to defaults   writecs(RX_CONFIG_REG, RX_DEFAULT);   //set Tx Config Register to defaults   writecs(TX_CONFIG_REG, TX_DEFAULT);   //set Buffer Config Register to defaults   writecs(BUFFER_CONFIG_REG, BUF_CONFIG_DEFAULT);   //set up acceptance filter   writecs(RCR, (RCR_RX_IA | RCR_RX_BROADCAST | RCR_RX_MULTICAST | RCR_RX_OK));   //enable frame Rx and Tx   writecs(LCR, (readcs(LCR) | LCR_SERIAL_RX_ON | LCR_SERIAL_TX_ON));   writecs(TX_CMD_REQ, TX_AFTER_ALL | TX_PAD);   writecs(TX_LENGTH, 0);   while(!(readcs(BSR) & READY_FOR_TX_NOW));   readcs(TX_EVENT);   return 1;}////////////////////////////////////////////////////////////////////////////////// tx_packet_ethernet// PURPOSE: Transmits a packet.// PARAMS:  (IN) u16 * to return the MAC address.// RETURNS: 1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////inttx_packet_ethernet(u8 *data,                   u16 size){   int i = 0;   u16 temp = 0;   u32 time = get_time_timer();   //initiate tx sequence   writecs(TX_CMD_REQ, TX_AFTER_ALL | TX_PAD);   writecs(TX_LENGTH, size);   //wait for the chip to free room in it's internal buffer   while(!(readcs(BSR) & READY_FOR_TX_NOW))   {      if(time < get_time_timer() - NET_TIMEOUT)      {         return 0;      }   }   //give the packet to the chip   for(i = 0; i < (size / sizeof(u16));i++)   {      *(volatile u16 *)(BASE_ADDR + TX_FRAME_PORT) =  *(u16 *)data;      data += sizeof(u16);   }   //if we are sending a packet of uneven size, send the last byte.   if(size % sizeof(u16))   {      *(volatile u16 *)(BASE_ADDR + TX_FRAME_PORT) = *data;   }   //check for tx errors   temp = readcs(TX_EVENT);   if(temp &       (TX_EXCESSIVE_COL |       TX_JABBER |       TX_LOST_CRS |       TX_OUT_OF_WINDOW |       TX_SQE_ERROR))   {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -