📄 mxi.c
字号:
//--------------------------------------------------------------------------
// IP Stack
//--------------------------------------------------------------------------
// mxi.c
//
// Macronix 98728 Packet Driver - ISR Version
//
// Author: Michael A. Denio
// Copyright 2000, 2003 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <std.h>
#include <sys.h>
#include <sem.h>
#include <hwi.h>
#include <c62.h>
#include <stkmain.h>
#include <csl.h>
#include <csl_cache.h>
#include "llpacket.h"
#include "mx.h"
//
// We use the following direct access to registers
//
extern cregister volatile uint ICR;
//
// Declare our local functions
//
static void gmInitialize();
static void gmReset();
static void gmStart();
static void gmStop();
static void gmSendPacket( PBM_Handle hPkt );
static int gmRxPacket();
static void gmIsr();
//
// Current TX and RX state
//
#define STATE_IDLE 0
#define STATE_DMA 1
#define STATE_SEND 2
static volatile uint TxState;
static volatile uint RxState;
// Local instance information pointer for our single device instance
static PDINFO *pGMI = 0;
// Simple Tx and Rx statistics
uint RxGood = 0, RxBad = 0, TxPanic = 0;
uint FatalError = 0, FatalCount = 0;
uint FlashActiveLED = 0;
//
// Some quick equates
//
#define INTMASK (GM_RIM|GM_TIM) // GMAC interrupts we care about
//
// Panic Buffer
//
#pragma DATA_ALIGN(pktPanicBuf, 128);
#pragma DATA_SECTION(pktPanicBuf, "PACKETMEM");
UINT8 pktPanicBuf[1536];
//--------------------------------------------------------------------
// 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
//--------------------------------------------------------------------
static void Delay(unsigned int t)
{
volatile unsigned int i;
while( t-- )
for( i=0; i<(1600*HW_CLOCKRATE); 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;
// 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.
// IF pGMI is aleady set, this is a restart.
if( !pGMI )
{
//
// Now initialize the Macronix device
//
pGMI = pi;
gmInitialize();
// Configure the interrupt
// Set interrupt polarity for GP interrupt
imanSetExtPolarity(HW_IVAL,MX_EXTINT_POLARITY);
// Hook GP INT - Disable GP int inside ISR
hwiattr.intrMask = HW_IFLAG;
hwiattr.ccMask = 1;
hwiattr.arg = 0;
HWI_dispatchPlug( HW_IVAL, (Fxn)gmIsr, -1, &hwiattr );
CACHE_invalidate( CACHE_L1PALL, 0, 0 );
// Enable out general purpose interrupt
C62_enableIER( HW_IFLAG );
}
// Use the new PDINFO
pGMI = pi;
// Reset
gmReset();
// Read our MAC address
*(UINT32 *)pi->bMacAddr = READ32( GMAC_ADDR1 );
*(UINT16 *)(pi->bMacAddr+4) = (UINT16)(READ32( GMAC_ADDR2 ));
// Start
gmStart();
return(1);
}
//--------------------------------------------------------------------
// HwPktClose()
//
// Close Device Instance
//--------------------------------------------------------------------
void HwPktClose( PDINFO *pi )
{
(void)pi;
// Normally we'd shut off the part, but here we'll only
// stop it. This is because it can't handle a soft reset.
gmStop();
}
//--------------------------------------------------------------------
// gmHashIndex()
//
// Calculate the Hash table index for one 6 byte address
//--------------------------------------------------------------------
#define POLY32 0x04c11db7
static unsigned int gmHashIndex( 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 )
{
UINT32 Addr[3];
UINT32 control;
uint i,idx;
//
// Setup Multicast Table
//
// Read what we want to preserve
Addr[0] = READ32( GMAC_ADDR2 );
Addr[2] = READ32( GMAC_ADDR4 );
// Clear all bits out of the hash table
Addr[0] &= 0xFFFF;
Addr[1] = 0;
Addr[2] &= 0xFFFF0000;
for( i=0; i<pi->MCastCnt; i++ )
{
idx = gmHashIndex( &(pi->bMCast[6*i]) );
// Set the bit
if( idx < 16 )
Addr[0] |= 1 << ( idx + 16 );
else if( idx < 48 )
Addr[1] |= 1 << ( idx - 16 );
else
Addr[2] |= 1 << ( idx - 48 );
}
// Write the table back out
WRITE32( GMAC_ADDR2, Addr[0] );
WRITE32( GMAC_ADDR3, Addr[1] );
WRITE32( GMAC_ADDR4, Addr[2] );
//
// Setup the Rx Filter
//
control = READ32( GMAC_CONTROL ) & 0xFFFF00FF;
switch( pi->Filter )
{
case ETH_PKTFLT_NOTHING:
case ETH_PKTFLT_DIRECT:
break;
case ETH_PKTFLT_BROADCAST:
case ETH_PKTFLT_MULTICAST:
control |= GM_AB;
break;
case ETH_PKTFLT_ALLMULTICAST:
control |= GM_AB | GM_PM;
break;
case ETH_PKTFLT_ALL:
control |= GM_PR;
break;
}
WRITE32( GMAC_CONTROL, control );
}
//--------------------------------------------------------------------
// HwPktTxNext()
//
// Transmit Next Packet on Tx Queue
//--------------------------------------------------------------------
void HwPktTxNext( PDINFO *pi )
{
PBM_Handle hPkt;
// If not idle, ignore this call
if( TxState != STATE_IDLE )
return;
// Make sure we have a packet to send
if( !(hPkt = PBMQ_deq(&pi->PBMQ_tx)) )
{
pi->TxFree = 1;
return;
}
// Mark as "not free"
pi->TxFree = 0;
// Send the packet
gmSendPacket( hPkt );
}
//--------------------------------------------------------------------
// _HwPktPoll()
//
// Poll routine - CALLED OUTSIDE OF KERNEL MODE
//
// This function is called at least every 100ms, faster in a
// polling environment. The fTimerTick flag is set only when
// called on a 100ms event.
//--------------------------------------------------------------------
void _HwPktPoll( PDINFO *pi, uint fTimerTick )
{
uint mask,flags,data1,data2;
if( fTimerTick )
{
LED_TOGGLE( USER_LED2 );
if( FlashActiveLED )
{
FlashActiveLED = 0;
LED_TOGGLE( USER_LED3 );
}
}
// Get into kernel mode to be safe
llEnter();
// We can't have our polling interfere with the ISR
// Disable GP interrupt
mask = gmDisableIER( HW_IFLAG );
if( FatalError )
{
FatalCount++;
gmStop();
gmStart();
}
// Ack any pending interrupt
flags = READ32( GMAC_ISR ) & 0xFF00;
if( flags )
{
ICR = HW_IFLAG;
WRITE32( GMAC_ISR, ( 0x00000000 | flags | INTMASK ) );
}
// Check for new Rx packet
while( !FatalError && RxState == STATE_IDLE )
{
data1 = READ32(GMAC_RXRING1) >> 16;
data2 = READ32(GMAC_RXRING2) & 0xFFFF;
if( data1 == data2 )
break;
RxState = STATE_DMA;
gmRxPacket();
}
// Check for Tx Complete
if( TxState==STATE_SEND && !(READ32(GMAC_CONTROL) & (GM_ST0|GM_ST1)) )
{
TxState = STATE_IDLE;
if( PBMQ_count(&pi->PBMQ_tx) )
HwPktTxNext( pi );
else
pi->TxFree = 1;
}
gmEnableIER( mask );
// Leave kernel mode
llExit();
}
//--------------------------------------------------------------------
// gmInitialize()
//
// Reset GMAC and clear its external memory
//--------------------------------------------------------------------
static void gmInitialize()
{
int i,j;
unsigned int page;
// EMIF control
*HW_CE_REG = HW_CE_VALUE;
Delay(4);
// Hard Reset
WRITE32( GMAC_RESET_ON, 0 );
Delay(4);
WRITE32( GMAC_RESET_OFF, 0 );
Delay(4);
// Soft Reset
WRITE32( GMAC_CONTROL, GM_RESET );
Delay(3);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -