?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{FILE START}

library

?curdirlinks? - Rev 32

?prevdifflink? - Blame - ?getfile?

/*********************************************************************
 *
 *     MAC Module (Microchip PIC32MX5-7) for Microchip TCP/IP Stack
 *
 *********************************************************************
 * FileName:        ETHPIC32IntMac.c
 * Dependencies:    see the include section below
 * 
 * Processor:       PIC32MX
 *                  
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 *
 * The software supplied herewith by Microchip Technology Incorporated
 * (the “Company”) for its PICmicro® Microcontroller is intended and
 * supplied to you, the Company’s customer, for use solely and
 * exclusively on Microchip PICmicro Microcontroller products. The
 * software is owned by the Company and/or its supplier, and is
 * protected under applicable copyright laws. All rights are reserved.
 * Any use in violation of the foregoing restrictions may subject the
 * user to criminal sanctions under applicable laws, as well as to
 * civil liability for the breach of the terms and conditions of this
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 * $Id: $
 *
********************************************************************/
#include <string.h>

#include "GenericTypeDefs.h"

#include "TCPIP Stack/TCPIP.h"
#include "TCPIP Stack/MAC.h"


// Compile only for PIC32MX with Ethernet MAC interface (must not have external ENCX24J600, ENC28J60, or ZG2100M hardware defined)
#if defined(__PIC32MX__) && defined(_ETH) && !defined(ENC100_INTERFACE_MODE) && !defined(ENC_CS_TRIS) && !defined(ZG_CS_TRIS)

// running on PIC32MX5-7 family with embedded ETHC

#include <peripheral/eth.h>

#include "TCPIP Stack/ETHPIC32ExtPhy.h"


/** D E F I N I T I O N S ****************************************************/


#define ETHER_IP    (0x00u)
#define ETHER_ARP   (0x06u)


#define LINK_REFRESH_MS 100             // refresh link status time, ms

typedef struct
{
        int             txBusy;                                                                         // busy flag
        unsigned int    dataBuff[(MAC_TX_BUFFER_SIZE+sizeof(ETHER_HEADER)+sizeof(int)-1)/sizeof(int)];  // actual data buffer
}sEthTxDcpt;    // TX buffer descriptor

/******************************************************************************
 * Prototypes
 ******************************************************************************/
static void             _TxAckCallback(void* pPktBuff, int buffIx);                     // Eth tx buffer acnowledge function
static int              _LinkReconfigure(void);                                         // link reconfiguration


// TX buffers
static volatile sEthTxDcpt      _TxDescriptors[EMAC_TX_DESCRIPTORS];                    // the statically allocated TX buffers
static volatile sEthTxDcpt*     _pTxCurrDcpt=0;                                         // the current TX buffer
static int                      _TxLastDcptIx=0;                                        // the last TX descriptor used
static unsigned short int       _TxCurrSize=0;                                          // the current TX buffer size


// RX buffers
static unsigned char            _RxBuffers[EMAC_RX_DESCRIPTORS][EMAC_RX_BUFF_SIZE];     // rx buffers for incoming data
static unsigned char*           _pRxCurrBuff=0;                                         // the current RX buffer
static unsigned short int       _RxCurrSize=0;                                          // the current RX buffer size



// HTTP +SSL buffers
static unsigned char            _HttpSSlBuffer[RESERVED_HTTP_MEMORY+RESERVED_SSL_MEMORY];


// general stuff
static unsigned char*           _CurrWrPtr=0;                                           // the current write pointer
static unsigned char*           _CurrRdPtr=0;                                           // the current read pointer


// timing and link status maintenance
static DWORD                    _linkUpdTick;                                           // last tick value when the link update was started
static eEthLinkStat             _linkPrev;                                              // last value of the link status
static int                      _linkPresent;                                           // if connection to the PHY properly detected
static int                      _linkNegotiation;                                       // if an auto-negotiation is in effect

// run time statistics
/*static*/ int                  _stackMgrRxOkPkts=0;
/*static*/ int                  _stackMgrRxBadPkts=0;
/*static*/ int                  _stackMgrInGetHdr=0;
/*static*/ int                  _stackMgrRxDiscarded=0;
/*static*/ int                  _stackMgrTxNotReady=0;


/*
 * interface functions
 *
*/




/****************************************************************************
 * Function:        MACInit
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *                
 * Side Effects:    None
 *
 * Overview:        This function initializes the Eth controller, the MAC and the PHY. It should be called to be able to schedule
 *                  any Eth transmit or receive operation.
 *
 * Note:            None 
 *****************************************************************************/
void MACInit(void)
{
    union
    {
        double      align;              // alignement
        BYTE            addr[6];            // address itself
    }SysMACAddr;        // aligned MAC address

    int         ix;
        eEthRes         ethRes, phyInitRes;
        BYTE            useFactMACAddr[6] = {0x00, 0x04, 0xa3, 0x00, 0x00, 0x00};               // to check if factory programmed MAC address needed
        BYTE            unsetMACAddr[6] =   {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};               // not set MAC address

    int         initFail=0;

        _stackMgrRxBadPkts=_stackMgrRxOkPkts=_stackMgrInGetHdr=_stackMgrRxDiscarded=0;
        _CurrWrPtr=_CurrRdPtr=0;

        // set the TX/RX pointers
        for(ix=0; ix<sizeof(_TxDescriptors)/sizeof(*_TxDescriptors); ix++)
        {
                _TxDescriptors[ix].txBusy=0;
        }
        _pTxCurrDcpt=_TxDescriptors+0; _TxLastDcptIx=0; _TxCurrSize=0;

        _pRxCurrBuff=0; _RxCurrSize=0;  

        _linkNegotiation=_linkPresent=0;
        _linkPrev=ETH_LINK_ST_DOWN;
        
                
        while(1)
        {
                eEthLinkStat    linkStat;
                eEthOpenFlags   oFlags, linkFlags;
                eMacPauseType   pauseType;
                eEthPhyCfgFlags cfgFlags;


                
        #ifdef PHY_RMII
                cfgFlags=ETH_PHY_CFG_RMII;
        #else
                cfgFlags=ETH_PHY_CFG_MII;               
        #endif
                
        #ifdef PHY_CONFIG_ALTERNATE
                cfgFlags|=ETH_PHY_CFG_ALTERNATE;
        #else
                cfgFlags|=ETH_PHY_CFG_DEFAULT;  
        #endif


        #if ETH_CFG_LINK
                        oFlags=ETH_CFG_AUTO?ETH_OPEN_AUTO:0;
                        oFlags|=ETH_CFG_10?ETH_OPEN_10:0;
                        oFlags|=ETH_CFG_100?ETH_OPEN_100:0;
                        oFlags|=ETH_CFG_HDUPLEX?ETH_OPEN_HDUPLEX:0;
                        oFlags|=ETH_CFG_FDUPLEX?ETH_OPEN_FDUPLEX:0;
                        if(ETH_CFG_AUTO_MDIX)
                        {
                                oFlags|=ETH_OPEN_MDIX_AUTO;
                        }
                        else
                        {
                                oFlags|=ETH_CFG_SWAP_MDIX?ETH_OPEN_MDIX_SWAP:ETH_OPEN_MDIX_NORM;
                        }                       
        #else
                oFlags= ETH_OPEN_DEFAULT;
        #endif // ETH_CFG_LINK

                
                pauseType=(oFlags&ETH_OPEN_FDUPLEX)?MAC_PAUSE_CPBL_MASK:MAC_PAUSE_TYPE_NONE;
                
                // start the initialization sequence    
                EthInit();

                phyInitRes=EthPhyInit(oFlags, cfgFlags, &linkFlags);
                
                // let the auto-negotiation (if any) take place
                // continue the initialization
                EthRxFiltersClr(ETH_FILT_ALL_FILTERS);
                EthRxFiltersSet(ETH_FILT_CRC_ERR_REJECT|ETH_FILT_RUNT_REJECT|ETH_FILT_ME_UCAST_ACCEPT|ETH_FILT_MCAST_ACCEPT|ETH_FILT_BCAST_ACCEPT);

                
                // set the MAC address
        memcpy(SysMACAddr.addr, AppConfig.MyMACAddr.v, sizeof(SysMACAddr.addr));
        if(memcmp(SysMACAddr.addr, useFactMACAddr, sizeof(useFactMACAddr))==0 || memcmp(SysMACAddr.addr, unsetMACAddr, sizeof(unsetMACAddr))==0 )
                {       // use the factory programmed address existent in the MAC
            unsigned short* pS=(unsigned short*)SysMACAddr.addr;
            *pS++=EMACxSA2;
            *pS++=EMACxSA1;
            *pS=EMACxSA0;
            memcpy(AppConfig.MyMACAddr.v, SysMACAddr.addr, sizeof(SysMACAddr.addr));
                }
        else
        {   // use the supplied address
                        EthMACSetAddress(SysMACAddr.addr);                
        }
                                
                if(EthDescriptorsAdd(EMAC_TX_DESCRIPTORS, ETH_DCPT_TYPE_TX, 0)!=EMAC_TX_DESCRIPTORS)
                {
                        initFail++;
                }

                if(EthDescriptorsAdd(EMAC_RX_DESCRIPTORS, ETH_DCPT_TYPE_RX, 0)!=EMAC_RX_DESCRIPTORS)
                {
                        initFail++;
                }

                EthRxSetBufferSize(EMAC_RX_BUFF_SIZE);

                // set the RX buffers as permanent receive buffers
                for(ix=0, ethRes=ETH_RES_OK; ix<EMAC_RX_DESCRIPTORS && ethRes==ETH_RES_OK; ix++)
                {
                        unsigned char* pRxBuff=_RxBuffers[ix];
                        ethRes=EthRxBuffersAppend(&pRxBuff, 1, BUFF_FLAG_RX_STICKY);
                }

                if(ethRes!=ETH_RES_OK)
                {
                        initFail++;
                }


                if(phyInitRes==ETH_RES_OK)
                {       // PHY was detected
                        _linkPresent=1;
                        if(oFlags&ETH_OPEN_AUTO)
                        {       // we'll just wait for the negotiation to be done
                                _linkNegotiation=1;     // performing the negotiation
                                linkStat=_LinkReconfigure()?ETH_LINK_ST_UP:ETH_LINK_ST_DOWN;    // if negotiation not done yet we need to try it next time
                        }
                        else
                        {       // no need of negotiation results; just update the MAC
                                EthMACOpen(linkFlags, pauseType);
                                linkStat=EthPhyGetLinkStatus(0);
                        }
                        
                        _linkUpdTick=TickGet();         // the last time we performed the link read
                        _linkPrev=linkStat;
                }
                else
                {
                        initFail++;
                }

                break;
        }

        
//      return !initFail;       // at this point initFail gives some indication of any existent problems
        
}


/****************************************************************************
 * Function:        MACIsLinked
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          TRUE if link is up
 *                  FALSE otherwise
 *
 * Side Effects:    None
 *
 * Overview:        This function checks the link status
 *
 * Note:            None 
 *****************************************************************************/
BOOL MACIsLinked(void)
{
        return (_linkPrev&ETH_LINK_ST_UP)!=0;
}


/****************************************************************************
 * Function:        MACGetTxBaseAddr
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          TX buffer base address
 *                
 * Side Effects:    None
 *
 * Overview:        This function returns the address of the current TX buffer.
 *
 * Note:            The returned value could be 0 if currently there's no available TX buffer. 
 *****************************************************************************/
PTR_BASE MACGetTxBaseAddr(void)
{
        return _pTxCurrDcpt?(PTR_BASE)_pTxCurrDcpt->dataBuff:0;
}

/****************************************************************************
 * Function:        MACGetHttpBaseAddr
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          HTTP buffer base address
 *                
 * Side Effects:    None
 *
 * Overview:        This function returns the address of the HTTP buffer.
 *
 * Note:            The HTTP buffer is a static one, always available. 
 *****************************************************************************/
PTR_BASE MACGetHttpBaseAddr(void)
{
        return (PTR_BASE)_HttpSSlBuffer;
}

/****************************************************************************
 * Function:        MACGetSslBaseAddr
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          SSL buffer base address
 *                
 * Side Effects:    None
 *
 * Overview:        This function returns the address of the SSL buffer.
 *
 * Note:            The SSL buffer is a static one, always available. 
 *****************************************************************************/
PTR_BASE MACGetSslBaseAddr(void)
{
        return (PTR_BASE)(_HttpSSlBuffer+RESERVED_HTTP_MEMORY);
}


/**************************
 * TX functions
 ***********************************************/

/****************************************************************************
 * Function:        MACSetWritePtr
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          old write pointer
 *                
 * Side Effects:    None
 *
 * Overview:        This function sets the new write pointer.
 *
 * Note:            None
 *****************************************************************************/
PTR_BASE MACSetWritePtr(PTR_BASE address)
{
        unsigned char* oldPtr;

        oldPtr=_CurrWrPtr;
        _CurrWrPtr=(unsigned char*)address;
        return (PTR_BASE)oldPtr;
}


/******************************************************************************
 * Function:        BOOL MACIsTxReady(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          TRUE: If data can be inserted in the current TX buffer
 *                  FALSE: there is no free TX buffer
 *
 * Side Effects:    None
 *
 * Overview:        Checks if there is an available current TX buffer
 *
 * Note:            None
 *****************************************************************************/
BOOL MACIsTxReady(void)
{
        int     ix;

        EthTxAckBuffer(0, _TxAckCallback);              // acknowledge everything

        if(_pTxCurrDcpt==0)
        {
                for(ix=_TxLastDcptIx+1; ix<sizeof(_TxDescriptors)/sizeof(*_TxDescriptors); ix++)
                {                       
                        if(_TxDescriptors[ix].txBusy==0)
                        {       // found a non busy descriptor
                                _pTxCurrDcpt=_TxDescriptors+ix;
                                _TxLastDcptIx=ix;
                                break;
                        }
                }
                if(_pTxCurrDcpt==0)
                {
                        for(ix=0; ix<_TxLastDcptIx; ix++)
                        {
                                if(_TxDescriptors[ix].txBusy==0)
                                {       // found a non busy descriptor
                                        _pTxCurrDcpt=_TxDescriptors+ix;
                                        _TxLastDcptIx=ix;
                                        break;
                                }
                        }
                }
        }


        if( _pTxCurrDcpt==0)
        {
                _stackMgrTxNotReady++;
        }
        
        return _pTxCurrDcpt!=0;
}

/******************************************************************************
 * Function:        void MACPut(BYTE val)
 *
 * PreCondition:    None
 *
 * Input:           byte to be written
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:       Writes a byte to the current write location and increments the write pointer. 
 *
 * Note:            None
 *****************************************************************************/
void MACPut(BYTE val)
{
        *_CurrWrPtr++=val;
}

/******************************************************************************
 * Function:        void MACPutArray(BYTE* buff, WORD len)
 *
 * PreCondition:    None
 *
 * Input:           buff - buffer to be written
 *                  len - buffer length
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Writes a buffer to the current write location and updates the write pointer. 
 *
 * Note:            None
 *****************************************************************************/
void MACPutArray(BYTE *buff, WORD len)
{
        memcpy(_CurrWrPtr, buff, len);
        _CurrWrPtr+=len;
}


/******************************************************************************
 * Function:        void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
 *
 * PreCondition:    None
 *
 * Input:           remote - Pointer to memory which contains the destination MAC address (6 bytes)
 *                  type - packet type: MAC_IP or ARP
 *                  dataLen - ethernet frame payload
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:       Sets the write pointer at the beginning of the current TX buffer
 *                 and sets the ETH header and the frame length. Updates the write pointer
 *
 * Note:            Assumes there is an available TX buffer, i.e. MACIsTxReady() returned !0
 *****************************************************************************/
void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
{
        _TxCurrSize=dataLen+sizeof(ETHER_HEADER);
        _CurrWrPtr=(unsigned char*)_pTxCurrDcpt->dataBuff;              // point at the beg of the buffer
        

        memcpy(_CurrWrPtr, remote, sizeof(*remote));
        _CurrWrPtr+=sizeof(*remote);
        memcpy(_CurrWrPtr, &AppConfig.MyMACAddr, sizeof(AppConfig.MyMACAddr));
        _CurrWrPtr+=sizeof(AppConfig.MyMACAddr);

        
        *_CurrWrPtr++=0x08;
        *_CurrWrPtr++=(type == MAC_IP) ? ETHER_IP : ETHER_ARP;
        
}



void MACFlush(void)
{
        if(_pTxCurrDcpt && _TxCurrSize)
        {       // there is a buffer to transmit
                _pTxCurrDcpt->txBusy=1; 
                EthTxSendBuffer((void*)_pTxCurrDcpt->dataBuff, _TxCurrSize);
                // res should be ETH_RES_OK since we made sure we had a descriptor available
                // by the call to MACIsTxReady and the number of the buffers matches the number of descriptors
                _pTxCurrDcpt=0;
                _TxCurrSize=0;
        }
}

/**************************
 * RX functions
 ***********************************************/


/******************************************************************************
 * Function:        void MACDiscardRx(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Marks the last received packet (obtained using 
 *                  MACGetHeader())as being processed and frees the buffer
 *                  memory associated with it.
 *                  It acknowledges the ETHC.
 *
 * Note:            Is is safe to call this function multiple times between
 *                  MACGetHeader() calls.  Extra packets won't be thrown away 
 *                  until MACGetHeader() makes it available.
 *****************************************************************************/
void MACDiscardRx(void)
{
        if(_pRxCurrBuff)
        {       // an already existing packet
                EthRxAckBuffer(_pRxCurrBuff, 0);
                _pRxCurrBuff=0;
                _RxCurrSize=0;

                _stackMgrRxDiscarded++;
        }       
}



/******************************************************************************
 * Function:        BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
 *
 * PreCondition:    None
 *
 * Input:           *remote: Location to store the Source MAC address of the
 *                           received frame.
 *                  *type: Location of a BYTE to store the constant
 *                         MAC_UNKNOWN, ETHER_IP, or ETHER_ARP, representing
 *                         the contents of the Ethernet type field.
 *
 * Output:          TRUE: If a packet was waiting in the RX buffer.  The
 *                        remote, and type values are updated.
 *                  FALSE: If a packet was not pending.  remote and type are
 *                         not changed.
 *
 * Side Effects:    Last packet is discarded if MACDiscardRx() hasn't already
 *                  been called.
 *
 * Overview:        None
 *
 * Note:            Sets the read pointer at the beginning of the new packet
 *****************************************************************************/
BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
{
        void*                   pNewPkt;
        const sRxPktStat*       pRxPktStat;
        eEthRes                 res;

        _stackMgrInGetHdr++;

        // verify the link status
        // if auto negotiation is enabled we may have to reconfigure the MAC

        while(_linkPresent)
        {
                eEthLinkStat    linkCurr;
                DWORD           currTick=TickGet();
                
                if(currTick-_linkUpdTick< (TICKS_PER_SECOND/1000)*LINK_REFRESH_MS)
                {       // not time to do anything yet
                        break;
                }

                linkCurr=EthPhyGetLinkStatus(0);        // read current PHY status
                _linkUpdTick=currTick;                  // start a new counting period

                if(_linkNegotiation)
                {       // the auto-negotiation turned on
                        if((linkCurr&ETH_LINK_ST_UP) && !(_linkPrev&ETH_LINK_ST_UP))
                        {       // we're up after being done. do renegotiate!
                                linkCurr=_LinkReconfigure()?ETH_LINK_ST_UP:ETH_LINK_ST_DOWN;    // if negotiation not done yet we need to try it next time
                        }
                        // else link went/still down; nothing to do yet
                }
                _linkPrev=linkCurr;
        
                break;
        }


        MACDiscardRx();         // discard/acknowledge the old RX buffer, if any
        
        res=EthRxGetBuffer(&pNewPkt, &pRxPktStat);
        
        if(res==ETH_RES_OK)
        {       // available packet; minimum check

                if(pRxPktStat->rxOk && !pRxPktStat->runtPkt && !pRxPktStat->crcError)
                {       // valid packet;
                        WORD_VAL newType;
                        _RxCurrSize=pRxPktStat->rxBytes;
                        _pRxCurrBuff=pNewPkt;
                        _CurrRdPtr=_pRxCurrBuff+sizeof(ETHER_HEADER);   // skip the packet header
                        // set the packet type
                        memcpy(remote, &((ETHER_HEADER*)pNewPkt)->SourceMACAddr, sizeof(*remote));
                        *type=MAC_UNKNOWN;
                        newType=((ETHER_HEADER*)pNewPkt)->Type;
                        if( newType.v[0]==0x08 && (newType.v[1]==ETHER_IP || newType.v[1]==ETHER_ARP) )
                        {
                                *type=newType.v[1];
                        }
                        
                        _stackMgrRxOkPkts++;
                }
        }

        if(_pRxCurrBuff==0 && pNewPkt)
        {       // failed packet, discard
                EthRxAckBuffer(pNewPkt, 0);
                _stackMgrRxBadPkts++;
        }
                
        
        return _pRxCurrBuff!=0;
}



/******************************************************************************
 * Function:        void MACSetReadPtrInRx(WORD offset)
 *
 * PreCondition:    A packet has been obtained by calling MACGetHeader() and
 *                  getting a TRUE result.
 *
 * Input:           offset: WORD specifying how many bytes beyond the Ethernet
 *                          header's type field to relocate the read pointer.
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        The current read pointer is updated.  All calls to
 *                  MACGet() and MACGetArray() will use these new values.
 *
 * Note:            
 ******************************************************************************/
void MACSetReadPtrInRx(WORD offset)
{
        _CurrRdPtr=_pRxCurrBuff+sizeof(ETHER_HEADER)+offset;
}


/****************************************************************************
 * Function:        MACSetReadPtr
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          old read pointer
 *                
 * Side Effects:    None
 *
 * Overview:        This function sets the new read pointer value.
 *
 * Note:            None
 *****************************************************************************/
PTR_BASE MACSetReadPtr(PTR_BASE address)
{
        unsigned char* oldPtr;

        oldPtr=_CurrRdPtr;
        _CurrRdPtr=(unsigned char*)address;
        return (PTR_BASE)oldPtr;
}




/******************************************************************************
 * Function:        BYTE MACGet()
 *
 * PreCondition:    A valid packet should vahe been obtained or the read pointer properly set.
 *
 * Input:           None
 *
 * Output:          Byte read from the current read pointer location
 *
 * Side Effects:    None
 *
 * Overview:        MACGet returns the byte pointed to by the current read pointer location and
 *                  increments the read pointer.
 *
 * Note:            None
 *****************************************************************************/
BYTE MACGet(void)
{
        return *_CurrRdPtr++;
}


/******************************************************************************
 * Function:        WORD MACGetArray(BYTE *address, WORD len)
 *
 * PreCondition:    A valid packet should vahe been obtained or the read pointer properly set.
 *
 * Input:           address: Pointer to storage location
 *                  len:  Number of bytes to read from the data buffer.
 *
 * Output:          number of bytes copied to the data buffer.
 *
 * Side Effects:    None
 *
 * Overview:        Copies data in the supplied buffer.
 *
 * Note:            The read pointer is updated
 *****************************************************************************/
WORD MACGetArray(BYTE *address, WORD len)
{
        if(address)
        {
                memcpy(address, _CurrRdPtr, len);
        }

        _CurrRdPtr+=len;
        return len;
}

/******************************************************************************
 * Function:        WORD MACGetFreeRxSize(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          An estimate of how much RX buffer space is free at the present time.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 *****************************************************************************/
WORD MACGetFreeRxSize(void)
{
        int avlblRxBuffs=sizeof(_RxBuffers)/sizeof(*_RxBuffers)-EthDescriptorsGetRxUnack();     // avlbl=allBuffs-unAck

        return avlblRxBuffs*(sizeof(_RxBuffers[0])/sizeof(*_RxBuffers[0]));     // avlbl* sizeof(buffer)
}


/*****************************************************************************
  Function:
        

  Summary:
        Asynchronously copies data from one address to another within the Ethernet memory.

  Description:


  Precondition:
        SPI bus must be initialized (done in MACInit()).


  Returns:
        None

  Remarks:
        Call MACIsMemCopyDone() to see when the transfer is complete.
        
        Copying to a destination region that overlaps with the source address 
        is supported only if the destination start address is at a lower memory 
        address (closer to 0x0000) than the source pointer.  However, if they do 
        overlap there must be at least 2 bytes of non-overlap to ensure correct 
        results due to hardware DMA requirements.  For example, destAddr = 0; 
        sourceAddr = 1; is illegal while destAddr = 0; sourceAddr = 2; is fine.
  
        If a prior transfer is already in progress prior to calling this function, 
        this function will block until it can start this transfer.

        If a negative value is used for the sourceAddr or destAddr parameters, 
        then that pointer will get updated with the next address after the read or 
        write.
 *****************************************************************************/


/******************************************************************************
 * Function:        void MACMemCopyAsync(PTR_BASE destAddr, PTR_BASE sourceAddr, WORD len)
 *
 * PreCondition:    Read and write pointers properly set if using the current ponter values
 *
 * Input:           destAddr - Destination address in the memory to copy to.  If it equals -1,
 *                     the current write pointer will be used.
 *                  sourceAddr - Source address to read from.  If it equals -1,
 *                     the current read pointer will be used.
 *                  len - number of bytes to copy
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Copies data from one address to another within the Ethernet memory.
 *                  Overlapped memory regions are allowed only if the destination start address
 *                  is at a lower memory address than the source address.
 *
 * Note:            The addresses do not have to be aligned.
 *****************************************************************************/
void MACMemCopyAsync(PTR_BASE destAddr, PTR_BASE sourceAddr, WORD len)
{
        if(len)
        {
                unsigned char   *pDst, *pSrc;

                pDst=(destAddr==-1)?_CurrWrPtr:(unsigned char*)destAddr;
                pSrc=(sourceAddr==-1)?_CurrRdPtr:(unsigned char*)sourceAddr;
                
                memcpy(pDst, pSrc, len);

        }
}

/******************************************************************************
 * Function:        void MACIsMemCopyDone(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          TRUE
 *
 * Side Effects:    None
 *
 * Overview:        Since there's no copy initiated by the DMA, the function returns always true for now.
 *
 * Note:            None
 *****************************************************************************/
BOOL MACIsMemCopyDone(void)
{
        return 1;
}


/******************************************************************************
 * Function:        WORD CalcIPBufferChecksum(WORD len)
 *
 * PreCondition:    Read buffer pointer set to starting of checksum data
 *
 * Input:           len: Total number of bytes to calculate the checksum over.
 *
 * Output:          16-bit checksum as defined by RFC 793
 *
 * Side Effects:    None
 *
 * Overview:        This function performs a checksum calculation of the buffer
 *                  pointed by the current value of the read pointer.
 *
 * Note:            None
 *****************************************************************************/
WORD CalcIPBufferChecksum(WORD len)
{
        return CalcIPChecksum(_CurrRdPtr, len);
}


/******************************************************************************
 * Function:        WORD MACCalcRxChecksum(WORD offset, WORD len)
 *
 * PreCondition:    None
 *
 * Input:           offset  - Number of bytes beyond the beginning of the
 *                          Ethernet data (first byte after the type field)
 *                          where the checksum should begin
 *                  len     - Total number of bytes to include in the checksum
 *
 * Output:          16-bit checksum as defined by RFC 793.
 *
 * Side Effects:    None
 *
 * Overview:        This function performs a checksum calculation in the current receive buffer.
 *
 * Note:            None
 *****************************************************************************/
WORD MACCalcRxChecksum(WORD offset, WORD len)
{
        return CalcIPChecksum(_pRxCurrBuff+sizeof(ETHER_HEADER)+offset, len);
}


/**************************
 * local functions and helpers
 ***********************************************/

/*********************************************************************
* Function:        void _TxAckCallback(void* pPktBuff)
 *
 * PreCondition:    None
 * 
 * Input:           pPktBuff - tx buffer to be acknowledged
 * 
 * Output:          None
 * 
 * Side Effects:    None
 * 
 * Overview:        TX acknowledge call back function.
 *                  Called by the Eth MAC when TX buffers are acknoledged (as a result of a call to EthTxAckBuffer).
 * 
 * Note:            None
 ********************************************************************/
static void     _TxAckCallback(void* pPktBuff, int buffIx)
{
        volatile sEthTxDcpt*    pDcpt;

        pDcpt=(sEthTxDcpt*)((char*)pPktBuff-offsetof(sEthTxDcpt, dataBuff));

        pDcpt->txBusy=0;

}


/*********************************************************************
* Function:        int  _LinkReconfigure(void)
 *
 * PreCondition:    None
 * 
 * Input:           None
 * 
 * Output:          TRUE if negotiation succeeded and MAC was updated
 *                  FALSE otherwise
 * 
 * Side Effects:    None
 * 
 * Overview:        Performs re-configuration after auto-negotiation performed.
 * 
 * Note:            None
 ********************************************************************/
static int _LinkReconfigure(void)
{

        eEthOpenFlags   linkFlags;
        eEthLinkStat    linkStat;
        eMacPauseType   pauseType;
        eEthRes         phyRes;
        int             success=0;


        phyRes=EthPhyNegotiationComplete(0);    // see if negotiation complete
        if(phyRes==ETH_RES_OK)
        {       
                linkStat=EthPhyGetNegotiationResult(&linkFlags, &pauseType);
                if(linkStat&ETH_LINK_ST_UP)
                {       // negotiation succeeded; properly update the MAC
                #ifdef PHY_RMII
                        EthMIIMInit(GetSystemClock(), EthPhyMIIMClock(), linkFlags, 1);
                #else
                        EthMIIMInit(GetSystemClock(), EthPhyMIIMClock(), linkFlags, 0);
                #endif
                        EthMACOpen(linkFlags, pauseType);
                        success=1;
                }
        }

        return success;
}



#endif  // defined(__PIC32MX__) && defined(_ETH)


{FILE END}
{FOOTER START}

Powered by WebSVN v2.8.3