?? smsce.c
字號(hào):
//--------------------------------------------------------------------------
// IP Stack
//--------------------------------------------------------------------------
// smsce.c
//
// SMSC Sample Packet Driver - EMDA Version
//
// Author: Michael A. Denio
// Andre Schnarrenberger
// Copyright 2002, 2003 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <std.h>
#include <sys.h>
#include <sem.h>
#include <hwi.h>
#include <c62.h>
#include <assert.h>
#include <stkmain.h>
#include <csl.h>
#include <csl_edma.h>
#include <csl_cache.h>
#include "llpacket.h"
#include "smsc.h"
extern cregister volatile uint ICR;
//
// Static slots to hold our EDMA handle, event value, and
// TX and RX option register settings.
//
static EDMA_Handle hEDMA;
static int EdmaEvent;
static UINT32 EdmaOptTx;
static UINT32 EdmaOptRx;
//
// Declare our local functions
//
static void smscReset();
static void smscStart();
static void smscStop();
static void smscIsr(UINT32);
static void smscSendPacket( UINT8 smscPacketNumber );
static uint smscReceivePacket();
static void smscWritePHY( uint reg_addr, uint data );
static uint smscReadPHY( uint reg_addr );
static void mdioWriteBit(uint bit);
static uint mdioReadBit();
// Local instance information pointer for our single device instance
static PDINFO *pPDI = 0;
// Simple Tx and Rx statistics
uint RxGood=0, RxOver=0, TxGood=0, TxBad=0, IntSave=0;
uint FlashActiveLED = 0;
// SMSC Init State
static uint InitState = 0;
// SMSC Interrupt State
#define ISR_STATE_IDLE 0
#define ISR_STATE_ACTIVE 1
static uint IsrState = ISR_STATE_IDLE;
//
// Current TX and RX state
//
#define STATE_IDLE 0
#define STATE_ALLOC_PEND 1
#define STATE_DMA 2
#define STATE_SEND 3
static volatile uint TxState = STATE_IDLE;
static volatile uint RxState = STATE_IDLE;
// Remember these for TX
static PBM_Handle tx_hPkt;
static UINT8 *tx_pBuffer;
static uint tx_Size;
static uint tx_Offset;
// Trasnmit Control Setting
static UINT16 TransmitControl;
//--------------------------------------------------------------------
// imanSetExtPolarity()
//
// This function is used to set the interrupt detection
// polarity for the interrupts gernerated by GMAC
//--------------------------------------------------------------------
static void imanSetExtPolarity( int extintno, int polarity )
{
if( polarity==EXTINT_POLARITY_LOWHIGH )
*(volatile unsigned int*)0x19c0008 &= ~(1<<(extintno-4));
else if( polarity==EXTINT_POLARITY_HIGHLOW )
*(volatile unsigned int*)0x19c0008 |= (1<<(extintno-4));
}
//--------------------------------------------------------------------
// Delay()
//
// Simple delay function
// Here 't' is roughly in units of 420nS
//--------------------------------------------------------------------
static void Delay(unsigned int t)
{
volatile unsigned int i;
t = (t * HW_CLOCKRATE) / 32;
for( i=0; i<t; i++ );
}
//--------------------------------------------------------------------
// HwPktInit()
//
// Initialize Device environment and return instance count
//--------------------------------------------------------------------
uint HwPktInit()
{
//
// Note: This code supports only a single instance of the device
// Otherwise, we would do device detection here.
//
return(1);
}
//--------------------------------------------------------------------
// HwPktShutdown()
//
// Shutdown Device Environment
//--------------------------------------------------------------------
void HwPktShutdown()
{
}
//--------------------------------------------------------------------
// HwPktOpen()
//
// Open Device Instance
//--------------------------------------------------------------------
uint HwPktOpen( PDINFO *pi )
{
HWI_Attrs hwiattr;
uint i;
// We only have one device, so store off the PDINFO pointer as
// global to this module. Otherwise; we'd pick an unclaimed device
// and associate it with the PDINFO.
// Make sure our int is disabled
gmDisableIER( HW_IFLAG );
// Setup ISR state
IsrState = ISR_STATE_IDLE;
// Use the new PDINFO
pPDI = pi;
// Setup loopback mode (for testing)
if( !pi->hEther )
TransmitControl = TXENA|FDUPLX|EPHLOOP;
else
TransmitControl = TXENA|FDUPLX;
if( InitState )
{
// Clear any pending CPU int
ICR = HW_IFLAG;
// Reset
smscReset();
}
else
{
InitState = 1;
//
// In order to remain compatible with CSL, we will allocate
// our DMA channels and completion events.
//
//
// First, we must be able to get EDMA channel
//
hEDMA = EDMA_open( SMSC_EDMA_CHANNEL_NUMBER, EDMA_OPEN_RESET );
if( hEDMA == EDMA_HINV )
return(0);
// We don't use hardware initiated EDMA
EDMA_disableChannel( hEDMA );
//
// Next, allocate the completion events. We'll try for the same
// event as the EDMA channel we selected.
//
if( (EdmaEvent = EDMA_intAlloc(SMSC_EDMA_CHANNEL_NUMBER)) < 0 )
EdmaEvent = EDMA_intAlloc(-1);
if( EdmaEvent<0 )
return(0);
#if (!C64_SUPPORT)
EdmaOptTx = EDMA_OPT_RMK( EDMA_OPT_PRI_HIGH,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_INC,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_NONE,
EDMA_OPT_TCINT_YES,
EdmaEvent,
EDMA_OPT_LINK_NO,
EDMA_OPT_FS_YES );
EdmaOptRx = EDMA_OPT_RMK( EDMA_OPT_PRI_HIGH,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_NONE,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_INC,
EDMA_OPT_TCINT_YES,
EdmaEvent,
EDMA_OPT_LINK_NO,
EDMA_OPT_FS_YES );
#endif
#if (C64_SUPPORT)
EdmaOptTx = EDMA_OPT_RMK( EDMA_OPT_PRI_HIGH,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_INC,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_NONE,
EDMA_OPT_TCINT_YES,
(EdmaEvent&0xf),
(EdmaEvent>>4),
EDMA_OPT_ATCINT_NO,
0,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_NO,
EDMA_OPT_FS_YES );
EdmaOptRx = EDMA_OPT_RMK( EDMA_OPT_PRI_HIGH,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_NONE,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_INC,
EDMA_OPT_TCINT_YES,
(EdmaEvent&0xf),
(EdmaEvent>>4),
EDMA_OPT_ATCINT_NO,
0,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_NO,
EDMA_OPT_FS_YES );
#endif
// Setup some EDMA fields that don't change
EDMA_RSETH(hEDMA,IDX,0);
EDMA_RSETH(hEDMA,RLD,0);
// Init the CE space
*HW_CE_REG = HW_CE_VALUE;
// Hook device interrupt
hwiattr.intrMask = HW_IFLAG;
hwiattr.ccMask = 1;
hwiattr.arg = 1;
HWI_dispatchPlug( HW_IVAL, (Fxn)smscIsr, -1, &hwiattr );
CACHE_invalidate( CACHE_L1PALL, 0, 0 );
// Enable interrupt and configure interrupt
imanSetExtPolarity( HW_IVAL, SMSC_EXTINT_POLARITY );
// Clear any pending CPU int
ICR = HW_IFLAG;
// Reset
smscReset();
#if !SMSC_EEPROM_INSTALLED
// Write our MAC address (no EEPROM on this board!)
SMSC_WRITE16(SBA,SMSC_BANK_SELECT,1);
for(i=0; i<6; i++ )
SMSC_WRITE8(SBA,SMSC_IAR0+i,pPDI->bMacAddr[i]);
#endif
}
// Read our MAC address
SMSC_WRITE16(SBA,SMSC_BANK_SELECT,1);
for(i=0; i<6; i++ )
pPDI->bMacAddr[i] = SMSC_READ8(SBA,SMSC_IAR0+i);
// Start
smscStart();
// Enable our interrupt
C62_enableIER( HW_IFLAG );
return(1);
}
//--------------------------------------------------------------------
// HwPktClose()
//
// Close Device Instance
//--------------------------------------------------------------------
void HwPktClose( PDINFO *pi )
{
(void)pi;
// Make sure our int is disabled
gmDisableIER( HW_IFLAG );
// Normally we'd shut off the part, but here we'll only
// stop it. This is because it can't handle a soft reset.
smscStop();
}
//--------------------------------------------------------------------
// smscHashIndex()
//
// Calculate the Hash table index for one 6 byte address
//--------------------------------------------------------------------
#define POLY32 0x04c11db7
static unsigned int smscHashIndex( UINT8 *Address )
{
unsigned int Crc = 0xffffffff;
unsigned int Msb;
unsigned char Byte;
int ByteLen, Bit;
for( ByteLen=0; ByteLen<6; ByteLen++ )
{
Byte = *Address++;
for (Bit=0; Bit<8 ; Bit++)
{
Msb = Crc >> 31;
Crc <<= 1;
if( (Msb ^ (Byte>>Bit)) & 1 )
Crc ^= POLY32;
}
}
return( Crc>>26 );
}
//--------------------------------------------------------------------
// HwPktSetRx()
//
// Update Rx Mode (Rx filter and multicast hash table)
//--------------------------------------------------------------------
void HwPktSetRx( PDINFO *pi )
{
UINT8 multicast[8];
UINT16 control;
uint i,idx;
uint mask;
// Make sure our int is disabled
mask = gmDisableIER( HW_IFLAG );
//
// Setup Multicast Table
//
// Clear all multicast bits to zero
for(i=0; i<8; i++)
multicast[i]=0;
// For all multicast addresses, set one corresponding bit
for( i=0; i<pi->MCastCnt; i++ )
{
// Get hash bit (0 to 63)
idx = smscHashIndex( &(pi->bMCast[6*i]) );
// Set hash bit in hash talble
// regOffset = idx/8, and regBit = idx%8
// Bank3, offset "regOffset" |= 1<<regBit
multicast[idx/8] |= 1 << (idx%8);
}
SMSC_WRITE16(SBA,SMSC_BANK_SELECT,3);
for( i=0; i<8; i++ )
SMSC_WRITE8(SBA,SMSC_MULTICAST_TABLE+i,multicast[i]);
//
// Setup the Rx Filter
//
SMSC_WRITE16(SBA,SMSC_BANK_SELECT,0);
control = SMSC_READ16(SBA,SMSC_RECEIVE_CONTROL) & ~(ALMUL|PRMS);
switch( pi->Filter )
{
case ETH_PKTFLT_NOTHING:
case ETH_PKTFLT_DIRECT:
case ETH_PKTFLT_BROADCAST:
case ETH_PKTFLT_MULTICAST:
break;
case ETH_PKTFLT_ALLMULTICAST:
control |= ALMUL;
break;
case ETH_PKTFLT_ALL:
control |= PRMS;
break;
}
control = SMSC_WRITE16( SBA, SMSC_RECEIVE_CONTROL, control );
// Reenable our isr (if it was enabled)
gmEnableIER( mask );
}
//--------------------------------------------------------------------
// HwPktTxNext()
//
// Transmit Next Packet on Tx Queue
//--------------------------------------------------------------------
void HwPktTxNext( PDINFO *pi )
{
uint mask;
UINT8 tempbyte;
// Make sure our int is disabled
mask = gmDisableIER( HW_IFLAG );
// Make sure another call didn't sneak in
if( TxState != STATE_IDLE )
{
gmEnableIER( mask );
return;
}
// Make sure we have a packet to send
if( !(tx_hPkt = PBMQ_deq(&pi->PBMQ_tx)) )
{
pi->TxFree = 1;
gmEnableIER( mask );
return;
}
// Fill in the pending record
tx_pBuffer = PBM_getDataBuffer(tx_hPkt);
tx_Size = PBM_getValidLen(tx_hPkt);
tx_Offset = PBM_getDataOffset(tx_hPkt);
// Mark as "not free" and set TX state
pi->TxFree = 0;
// Clean the cache for external addesses
if( (UINT32)tx_pBuffer & 0x80000000 )
OEMCacheClean( (void *)(tx_pBuffer+tx_Offset), tx_Size );
// Go into allocation phase
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -