📄 mxf.c
字号:
//--------------------------------------------------------------------------
// IP Stack
//--------------------------------------------------------------------------
// mxf.c
//
// Macronix 98728 Packet Driver - Full Duplex EDMA Version
// *** CSL Compatible 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_edma.h>
#include <csl_cache.h>
#include "llpacket.h"
#include "mx.h"
//
// Static slots to hold our EDMA handle, event value, and
// TX and RX option register settings.
//
static EDMA_Handle hEDMA_tx;
static EDMA_Handle hEDMA_rx;
static EDMA_Handle hEDMA_rxControl;
static EDMA_Handle hEDMA_rld;
#if EDMA_FS_TP1
static EDMA_Handle hEDMA_tp1;
#endif
static int EdmaTxEvent;
static int EdmaRxEvent;
static UINT32 EdmaOptRx;
static UINT32 EdmaRldAddr; // 16 LSB's of reload addr
//
// 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();
static void gmIsrEDMATx(int arg);
static void gmIsrEDMARx(int arg);
//
// 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;
//
// Static data needed in EDMA ISR
//
static UINT32 DMAData1,DMAData2,DMAData3;
static PBM_Handle hDMARxPkt = 0;
static PBM_Handle hDMATxPkt = 0;
// 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;
static 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;
int tmp;
UINT32 EdmaOptTx;
#if EDMA_FS_TP1
UINT32 EdmaOptTp;
#endif
// 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 )
{
//
// In order to remain compatible with CSL, we will allocate
// our DMA channels and completion events.
//
//
// First, we must be able to get EDMA channels 4 and 5. Since
// our hardware uses EXTINT4 and EXTINT5, these channels should
// not be required by any other device.
//
hEDMA_tx = EDMA_open( EDMA_TXCHANNEL, EDMA_OPEN_RESET );
if( hEDMA_tx == EDMA_HINV )
return(0);
#if EDMA_FS_INT
hEDMA_rx = EDMA_open( EDMA_RXCHANNEL, EDMA_OPEN_RESET );
if( hEDMA_rx == EDMA_HINV )
return(0);
// Framesync Drives RXCHANNEL
hEDMA_rxControl = hEDMA_rx;
#endif
//
// When using TP1, we need our RX channel, plus the TP channel
// to control the clock count
//
#if EDMA_FS_TP1
hEDMA_rx = EDMA_open( EDMA_RXCHANNEL, EDMA_OPEN_RESET );
if( hEDMA_rx == EDMA_HINV )
return(0);
hEDMA_tp1 = EDMA_open( EDMA_TPCHANNEL, EDMA_OPEN_RESET );
if( hEDMA_tp1 == EDMA_HINV )
return(0);
// Framesync Drives TPCHANNEL
hEDMA_rxControl = hEDMA_tp1;
#endif
//
// Next, we need a single EDMA reload area. Allocate it now.
// We'll get one off the bottom so we won't conflict with any
// code that just assumes it can use the top entries.
//
tmp = EDMA_TABLE_CNT-1;
do
{
hEDMA_rld = EDMA_allocTable( tmp );
tmp--;
} while( hEDMA_rld == EDMA_HINV && tmp >= 0 );
if( hEDMA_rld == EDMA_HINV )
return(0);
EdmaRldAddr = EDMA_getTableAddress( hEDMA_rld ) & 0xffff;
//
// Finally, allocate some completion events. We'll try for
// events corresponding to our channela
//
if( (EdmaTxEvent = EDMA_intAlloc(EDMA_TXCHANNEL)) < 0 )
EdmaTxEvent = EDMA_intAlloc(-1);
#if EDMA_FS_INT
if( (EdmaRxEvent = EDMA_intAlloc(EDMA_RXCHANNEL)) < 0 )
EdmaRxEvent = EDMA_intAlloc(-1);
#endif
//
// When using TP1, we must have TCC8, and we'll ask for TP channel
//
#if EDMA_FS_TP1
if( (EdmaRxEvent = EDMA_intAlloc(EDMA_TPCHANNEL)) < 0 )
EdmaRxEvent = EDMA_intAlloc(-1);
if( (tmp = EDMA_intAlloc(EDMA_RXCHANNEL)) < 0 )
return(0);
#endif
if( EdmaTxEvent<0 || EdmaRxEvent<0 )
return(0);
//
// Now initialize the Macronix device
//
pGMI = pi;
gmInitialize();
// Configure the interrupts
// Set interrupt polarity for GP interrupt
imanSetExtPolarity(HW_IVAL,MX_EXTINT_POLARITY);
#if EDMA_FS_INT
// Set EDMA RX interrupt polarity to falling edge
imanSetExtPolarity(HW_FSIVAL,MX_EXTINT_POLARITY);
#endif
#if (!C64_SUPPORT)
EdmaOptTx = EDMA_OPT_RMK( EDMA_OPT_PRI_LOW,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_INC,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_NONE,
EDMA_OPT_TCINT_YES,
EdmaTxEvent,
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,
EdmaRxEvent,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_YES );
#if EDMA_FS_TP1
EdmaOptTp = 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_NONE,
EDMA_OPT_TCINT_YES,
EDMA_RXCHANNEL,
EDMA_OPT_LINK_NO,
EDMA_OPT_FS_YES );
#endif
#endif
#if (C64_SUPPORT)
EdmaOptTx = EDMA_OPT_RMK( EDMA_OPT_PRI_LOW,
EDMA_OPT_ESIZE_32BIT,
EDMA_OPT_2DS_NO,
EDMA_OPT_SUM_INC,
EDMA_OPT_2DD_NO,
EDMA_OPT_DUM_NONE,
EDMA_OPT_TCINT_YES,
(EdmaTxEvent&0xf),
(EdmaTxEvent>>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,
(EdmaRxEvent&0xf),
(EdmaRxEvent>>4),
EDMA_OPT_ATCINT_NO,
0,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_YES,
EDMA_OPT_FS_YES );
#if EDMA_FS_TP1
EdmaOptTp = 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_NONE,
EDMA_OPT_TCINT_YES,
(EDMA_RXCHANNEL&0xf),
(EDMA_RXCHANNEL>>4),
EDMA_OPT_ATCINT_NO,
0,
EDMA_OPT_PDTS_DISABLE,
EDMA_OPT_PDTD_DISABLE,
EDMA_OPT_LINK_NO,
EDMA_OPT_FS_YES );
#endif
#endif
//
// When using TP1, setup the clock configuration and
// the clock EMDA.
//
#if EDMA_FS_TP1
// Setup the clock with a period of 2
*(unsigned int*)_TIMER_CTL1_ADDR = 0x0; // Disable clock
*(unsigned int*)_TIMER_CNT1_ADDR = 0x0; // Set count to zero
*(unsigned int*)_TIMER_PRD1_ADDR = 0x2; // Set period to 2
// Clock Events EMDA and resets count to 1 on interrupt
// Src = Address of CNT reg which will always be "1"
// Dst = Clock count register
EDMA_RSETH(hEDMA_tp1,OPT,EdmaOptTp);
EDMA_RSETH(hEDMA_tp1,SRC,EDMA_ADDRH(hEDMA_tp1,CNT));
EDMA_RSETH(hEDMA_tp1,CNT,1);
EDMA_RSETH(hEDMA_tp1,DST,_TIMER_CNT1_ADDR);
EDMA_RSETH(hEDMA_tp1,IDX,0);
EDMA_RSETH(hEDMA_tp1,RLD,0);
EDMA_clearChannel(hEDMA_rx);
EDMA_enableChaining(hEDMA_rx);
#endif
// Hook GP INT - Disable GP int and EDMA int inside ISR
hwiattr.intrMask = HW_IFLAG|HW_IEDMAFLAG;
hwiattr.ccMask = 1;
hwiattr.arg = 0;
HWI_dispatchPlug( HW_IVAL, (Fxn)gmIsr, -1, &hwiattr );
CACHE_invalidate( CACHE_L1PALL, 0, 0 );
// Disable EDMA channels from event triggering
EDMA_disableChannel(hEDMA_tx);
EDMA_disableChannel(hEDMA_rxControl);
// Setup some Tx EDMA fields
EDMA_RSETH(hEDMA_tx,OPT,EdmaOptTx);
EDMA_RSETH(hEDMA_tx,DST,GMAC_WRTXFIFOD);
EDMA_RSETH(hEDMA_tx,IDX,0);
EDMA_RSETH(hEDMA_tx,RLD,0);
// Clear our interrupts
EDMA_intClear( EdmaTxEvent );
EDMA_intClear( EdmaRxEvent );
// Hook our event interrupts
EDMA_intHook( EdmaTxEvent, gmIsrEDMATx );
EDMA_intHook( EdmaRxEvent, gmIsrEDMARx );
// Enable our interrupts
EDMA_intEnable( EdmaTxEvent );
EDMA_intEnable( EdmaRxEvent );
// Setup Dead-Man Link in DMA Space
EDMA_RSETH(hEDMA_rld,OPT,0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -