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

📄 smsce.c

📁 dm642网络传输程序
💻 C
📖 第 1 页 / 共 2 页
字号:
//--------------------------------------------------------------------------
// 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

⌨️ 快捷键说明

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