📄 lan91c111.c
字号:
/*********************************************************************************
Copyright(c) 2004 Analog Devices, Inc. All Rights Reserved.
This software is proprietary and confidential. By using this software you agree
to the terms of the associated Analog Devices License Agreement.
*********************************************************************************/
// USE_16BIT has to be defined since the transmitable data will start on a half word boundary
#define USE_16_BIT
#ifdef __ADSPBF535__
#include <cdefbf535.h>
#endif /* __ADSPBF535__ */
#ifdef __ADSPBF533__
#include <cdefbf533.h>
#endif /* __ADSPBF533__ */
#include <string.h>
#include <sys/exception.h>
#include <services/services.h>
#include <drivers/adi_dev.h>
#include <services/adi_dcb.h>
#include <services/adi_dma.h>
#include <services/adi_int.h>
#include <services/adi_ebiu.h>
#include "lan91c111.h"
#include "io_sprt.h"
#include "cs8900a.h"
#include <ADI_ETHER_USBLAN.h>
#include "stdio.h"
#include "vdk.h"
// Acknowledge the LAN interrupt by clearing associated PF
//
#define ACK_LAN_INT(pf) ((*pFIO_FLAG_C = pf))
#define MAX_RCVE_FRAME 1560
static void *CriticalHandle;
#define ENTER_CRITICAL_REGION() (CriticalHandle=adi_int_EnterCriticalRegion(dev->CriticalData))
#define EXIT_CRTICIAL_REGION() (adi_int_ExitCriticalRegion(CriticalHandle))
#define LAN91C111_LOG_NET_ERRORS 1
/* The transmission attempt failed due to lack of memory - so queue and retry next time */
#define LAN91C111_TX_RETRY 1
/* The transmission attempt is an unrecoverable error - free the packet, drop it */
#define LAN91C111_TX_ERROR 2
/* The transmission attempt completed successfully */
#define LAN91C111_TX_SUCCESS 3
/* global static data */
static ADI_ETHER_LAN91C111_DATA EtherDev={0};
/* function prototypes */
int StartMac(ADI_ETHER_LAN91C111_DATA *dev);
int SetDevicePFConfig (ADI_ETHER_LAN91C111_DATA *dev);
int QueueNewRcvFrames (ADI_ETHER_LAN91C111_DATA *dev,ADI_ETHER_BUFFER *bufs);
int QueueNewXmtFrames (ADI_ETHER_LAN91C111_DATA *dev,ADI_ETHER_BUFFER *bufs);
ADI_ETHER_LAN91C111_DATA *dev_g;
int ping=0;
#include <cycle_count_bf.h>
//#define _ADI_DEBUG_LWIP
#define net_device _ADI_ETHER_LAN91C111_DATA
#ifdef _ADI_DEBUG_LWIP
#define ADI_G(x) (printf x)
#else
#define ADI_G(x)
#endif
//#include "..\..\cs8900a.h"
//#include "drivers\lan91c111\lan91c111.h"
#define net_device _ADI_ETHER_LAN91C111_DATA
#include <cplbtab.h>
#define BASE 0x20300000
#define CS89X0_ALLOC_IDLE 0
#define CS89X0_ALLOC_SUCE 1
#define CS89X0_ALLOC_WAIT 2
inline int readreg(struct net_device *dev, int portno);
inline void writereg(struct net_device *dev, int portno, int value) ;
inline int readword(struct net_device *dev, int portno);
inline void writeword(struct net_device *dev, int portno, int value);
inline void writeblock(struct net_device *dev, char *pData, int Length);
inline void readblock(struct net_device *dev, char *pData, int Length);
inline short inw(int addr);
int net_open(struct net_device *dev);
void cs8900a_probe(struct net_device *dev);
extern ADI_ETHER_BUFFER *rcv_list,*xmt_list;
static void ker_msec(void)
{
unsigned long long int cur,nd;
_GET_CYCLE_COUNT(cur);
nd = cur + (__PROCESSOR_SPEED__/1000);
while (cur < nd) {
_GET_CYCLE_COUNT(cur);
}
}
static int smsc_sleep(unsigned int msec)
{
while (msec != 0) {
ker_msec();
msec--;
}
return 0;
}
#pragma optimize_off
/****************************************************************************
* Read register from EEPROM
****************************************************************************/
static int eeprom_read_reg(int reg_no)
{
int timeout;
// select bank 2
_outpw(BSR_REG, 2);
_outpw(PTR_REG,reg_no);
// select bank 1
_outpw(BSR_REG, 1);
_outpw(CTL_REG,_inpw(CTL_REG) | CTL_EEPROM_SELECT | CTL_RELOAD);
timeout = 100;
while((_inpw(CTL_REG) & CTL_RELOAD) && --timeout)
{
int t=10000;
while(t>0)
t--;
}
// error in reading from eeprom
if(timeout == 0)
return -1;
return(_inpw(GP_REG));
}
/****************************************************************************
* Write register to EEPROM
****************************************************************************/
static int eeprom_write_reg(int reg_no, int val)
{
int timeout;
// select bank 2
_outpw(BSR_REG, 2);
_outpw(PTR_REG,reg_no);
// select bank 1
_outpw(BSR_REG, 1);
_outpw(GP_REG, val);
_outpw(CTL_REG,_inpw(CTL_REG) | CTL_EEPROM_SELECT | CTL_STORE);
timeout = 100;
while((_inpw(CTL_REG) & CTL_STORE) && --timeout)
{
int t=10000;
while(t>0)
t--;
}
// error in reading from eeprom
if(timeout == 0)
return -1;
return 1;
}
/******************************************************************************
* Set MAC address in the SMSC
*****************************************************************************/
static void set_mac_in_SMSC(const char* mac_addr)
{
unsigned short page;
short wtmp;
// save old page
page = _inpw(BSR_REG);
// select bank 1
_outpw(BSR_REG, 1);
// Set EEPROM Store
_outpw(CTL_REG,CTL_EEPROM_SELECT | CTL_STORE);
wtmp = (((mac_addr[1])<<8)|(mac_addr[0]));
_outpw(ADDR0_REG, wtmp);
wtmp = (((mac_addr[3])<<8)|(mac_addr[2]));
_outpw(ADDR1_REG, wtmp);
wtmp = (((mac_addr[5])<<8)|(mac_addr[4]));
_outpw(ADDR2_REG, wtmp);
// restore bank
_outpw(BSR_REG, page);
return;
}
/******************************************************************************
* Get MAC address From the SMSC
*****************************************************************************/
static void get_mac_frm_SMSC(char* mac_addr)
{
volatile unsigned short addr;
volatile unsigned short page;
page = _inpw(BSR_REG);
_outpw(BSR_REG, 1);
addr = _inpw(ADDR0_REG); // get MAC addr
mac_addr[0] = addr & 0xFF;
mac_addr[1] = addr >> 8;
addr = _inpw(ADDR1_REG); // get MAC addr
mac_addr[2] = addr & 0xFF;
mac_addr[3] = addr >> 8;
addr = _inpw(ADDR2_REG); // get MAC addr
mac_addr[4] = addr & 0xFF;
mac_addr[5] = addr >> 8;
_outpw(BSR_REG, page);
return;
}
/******************************************************************************
* Get MAC address From the EEPROM
*****************************************************************************/
static void set_mac_in_EEPROM(const char* mac_addr)
{
unsigned short page;
short wtmp;
// save old page
page = _inpw(BSR_REG);
wtmp = (((mac_addr[1])<<8)|(mac_addr[0]));
eeprom_write_reg(0x20,wtmp);
wtmp = (((mac_addr[3])<<8)|(mac_addr[2]));
eeprom_write_reg(0x21, wtmp);
wtmp = (((mac_addr[5])<<8)|(mac_addr[4]));
eeprom_write_reg(0x22, wtmp);
// restore bank
_outpw(BSR_REG, page);
return;
}
/******************************************************************************
* Get MAC address From the EEPROM
*****************************************************************************/
static void get_mac_frm_EEPROM(char* mac_addr)
{
volatile unsigned short addr,i,val,j=0;
volatile unsigned short page;
page = _inpw(BSR_REG);
// eeprom offset 20 has mac addr
for(i=0x20;i<0x23;i++)
{
val = eeprom_read_reg(i);
mac_addr[j++] = val & 0xff;
mac_addr[j++] = val >> 8;
}
_outpw(BSR_REG, page);
return;
}
/******************************************************************************
* Change the current IRQ mask
*****************************************************************************/
static void LAN91C111_enable_int (unsigned char IRQ)
{
volatile unsigned short page;
// save old page
page = _inpw(BSR_REG);
// switch to bank 2
_outpw(BSR_REG, 2);
// update current mask
_outp(IM_REG, _inp(IM_REG) | IRQ);
// restore bank
_outpw(BSR_REG, page);
return;
}
/******************************************************************************
* Change the current IRQ mask
*****************************************************************************/
static void LAN91C111_disable_int (unsigned char IRQ)
{
volatile unsigned short page;
volatile unsigned char mask;
// save old page
page = _inpw(BSR_REG);
// switch to bank 2
_outpw(BSR_REG, 2);
// write new mask
_outp(IM_REG, _inp(IM_REG) & ~IRQ);
// restore bank
_outpw(BSR_REG, page);
return;
}
/******************************************************************************
* Writes a word through the MII interface to the PHY
*****************************************************************************/
static void LAN91C111_write_phy_register(unsigned char phyreg, unsigned short phydata)
{
volatile int i;
volatile unsigned short oldBank, wmask, mii_reg;
volatile unsigned char bits[65], bmask;
volatile int clk_idx = 0;
// Prepare bit stream for PHY
// 32 consecutive ones on MDO to establish sync
for (i = 0; i < 32; ++i)
bits[clk_idx++] = MII_MDOE | MII_MDO;
// Start code <01>
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE | MII_MDO;
// Write command <01>
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE | MII_MDO;
// Output the PHY address, msb first, internal PHY = 0
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE;
// Output the phy register number, msb first
bmask = 0x10;
for (i = 0; i < 5; ++i)
{
if (phyreg & bmask)
bits[clk_idx++] = MII_MDOE | MII_MDO;
else
bits[clk_idx++] = MII_MDOE;
// Shift to next lowest bit
bmask >>= 1;
}
// Tristate and turnaround (2 bit times) <10>
bits[clk_idx++] = MII_MDOE | MII_MDO;;
bits[clk_idx++] = 0;
// Write out 16 bits of data, msb first
wmask = 0x8000;
for (i = 0; i < 16; ++i)
{
if (phydata & wmask)
bits[clk_idx++] = MII_MDOE | MII_MDO;
else
bits[clk_idx++] = MII_MDOE;
// Shift to next lowest bit
wmask >>= 1;
}
// Final clock bit (tristate)
bits[clk_idx++] = 0;
// Save the current bank
oldBank = _inpw(BSR_REG);
// Select bank 3
_outpw(BSR_REG, 3);
// Get the current MII register value
mii_reg = _inpw(MII_REG);
// Turn off all MII Interface bits
mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
// Clock all cycles
for (i = 0; i < sizeof bits; ++i)
{
// Clock Low - output data
_outpw(MII_REG, mii_reg | bits[i] );
// Clock Hi - input data
_outpw(MII_REG, mii_reg | bits[i] | MII_MCLK);
}
// Return to idle state
// Set clock to low, data to low, and output tristated
_outpw(MII_REG, mii_reg);
// Restore original bank select
_outpw(BSR_REG, oldBank );
return;
}
/******************************************************************************
* Reads a word through the MII interface off the PHY
*****************************************************************************/
static unsigned short LAN91C111_read_phy_register(unsigned char phyreg)
{
volatile unsigned char bits[64];
volatile unsigned char bmask;
volatile unsigned short oldBank, mii_reg, phydata, wmask;
volatile int i, clk_idx = 0;
volatile int input_idx;
// Prepare bit stream for PHY
// 32 consecutive ones on MDO to establish sync
for (i = 0; i < 32; ++i)
bits[clk_idx++] = MII_MDOE | MII_MDO;
// Start code <01>
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE | MII_MDO;
// Read command <10>
bits[clk_idx++] = MII_MDOE | MII_MDO;
bits[clk_idx++] = MII_MDOE;
// internal PHY address = <00000>
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE;
bits[clk_idx++] = MII_MDOE;
// Output the phy register number, msb first
bmask = 0x10;
for (i = 0; i < 5; ++i)
{
if (phyreg & bmask)
bits[clk_idx++] = MII_MDOE | MII_MDO;
else
bits[clk_idx++] = MII_MDOE;
// Shift to next lowest bit
bmask >>= 1;
}
// Tristate and turnaround (2 bit times)
bits[clk_idx++] = 0;
// Input starts at this bit time
input_idx = clk_idx;
// Will input 16 bits
for (i = 0; i < 16; ++i)
bits[clk_idx++] = 0;
// Final clock bit
bits[clk_idx++] = 0;
// Save the current bank
oldBank = _inpw(BSR_REG);
// Select bank 3
_outpw(BSR_REG, 3);
// Get the current MII register value
mii_reg = _inpw(MII_REG);
// Turn off all MII Interface bits
mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
// Clock all 64 cycles
for (i = 0; i < clk_idx /*sizeof bits*/; ++i)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -