#include <Copyright.h>
/********************************************************************************
* ev96122mii.c
*
* DESCRIPTION:
*       SMI access routines for EV-96122 board
*
* DEPENDENCIES:   Platform.
*
* FILE REVISION NUMBER:
*
*******************************************************************************/

#include <msSample.h>

/*
 * For each platform, all we need is 
 * 1) Assigning functions into 
 *         fgtReadMii : to read MII registers, and
 *         fgtWriteMii : to write MII registers.
 *
 * 2) Register Interrupt (Not Defined Yet.)
*/

/* 
 *  EV-96122 Specific Definition
*/

#define SMI_OP_CODE_BIT_READ                    1
#define SMI_OP_CODE_BIT_WRITE                   0
#define SMI_BUSY                                1<<28
#define READ_VALID                              1<<27

#ifdef FIREFOX
#define ETHER_SMI_REG                   0x10 
#define internalRegBaseAddr 0x80008000
#define NONE_CACHEABLE        0x00000000
#define CACHEABLE            0x00000000
#define SMI_RX_TIMEOUT        1000
#else
#define ETHER_SMI_REG                   0x080810 
#define internalRegBaseAddr 0x14000000
#define NONE_CACHEABLE        0xa0000000
#define CACHEABLE            0x80000000
#define SMI_RX_TIMEOUT        10000000
#endif

typedef unsigned int              SMI_REG;

#ifdef LE /* Little Endian */              
#define SHORT_SWAP(X) (X)
#define WORD_SWAP(X) (X)
#define LONG_SWAP(X) ((l64)(X))

#else    /* Big Endian */
#define SHORT_SWAP(X) ((X <<8 ) | (X >> 8))

#define WORD_SWAP(X) (((X)&0xff)<<24)+      \
                    (((X)&0xff00)<<8)+      \
                    (((X)&0xff0000)>>8)+    \
                    (((X)&0xff000000)>>24)

#define LONG_SWAP(X) ( (l64) (((X)&0xffULL)<<56)+               \
                            (((X)&0xff00ULL)<<40)+              \
                            (((X)&0xff0000ULL)<<24)+            \
                            (((X)&0xff000000ULL)<<8)+           \
                            (((X)&0xff00000000ULL)>>8)+         \
                            (((X)&0xff0000000000ULL)>>24)+      \
                            (((X)&0xff000000000000ULL)>>40)+    \
                            (((X)&0xff00000000000000ULL)>>56))   

#endif

#define GT_REG_READ(offset, pData)                                          \
*pData = ( (volatile unsigned int)*((unsigned int *)                        \
           (NONE_CACHEABLE | internalRegBaseAddr | (offset))) );            \
*pData = WORD_SWAP(*pData)

#define GT_REG_WRITE(offset, data)                                          \
(volatile unsigned int)*((unsigned int *)(NONE_CACHEABLE |                  \
          internalRegBaseAddr | (offset))) = WORD_SWAP(data)

typedef enum _bool{false,true} bool;

/*****************************************************************************
*
* bool etherReadMIIReg (unsigned int portNumber , unsigned int MIIReg,
* unsigned int* value)
*
* Description
* This function will access the MII registers and will read the value of
* the MII register , and will retrieve the value in the pointer.
* Inputs
* portNumber - one of the 2 possiable Ethernet ports (0-1).
* MIIReg - the MII register offset.
* Outputs
* value - pointer to unsigned int which will receive the value.
* Returns Value
* true if success.
* false if fail to make the assignment.
* Error types (and exceptions if exist)
*/

GT_BOOL gtBspReadMii (GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
                        unsigned int* value)
{
SMI_REG smiReg;
unsigned int phyAddr;
unsigned int timeOut = 10; /* in 100MS units */
int i;

/* first check that it is not busy */
    GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
    if(smiReg & SMI_BUSY) 
    {
        for(i = 0 ; i < SMI_RX_TIMEOUT ; i++);
        do {
            GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
            if(timeOut-- < 1 ) {
                return false;
            }
        } while (smiReg & SMI_BUSY);
    }
/* not busy */

    phyAddr = portNumber;

    smiReg =  (phyAddr << 16) | (SMI_OP_CODE_BIT_READ << 26) | (MIIReg << 21) |
         SMI_OP_CODE_BIT_READ<<26;

    GT_REG_WRITE (ETHER_SMI_REG,*((unsigned int*)&smiReg));
    timeOut = 10; /* initialize the time out var again */
    GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
    if(!(smiReg & READ_VALID)) 
        {
            i=0;
            while(i < SMI_RX_TIMEOUT)
            {
                i++;
            }
        {
        }
        do {
            GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
            if(timeOut-- < 1 ) {
                return false;
            }
        } while (!(smiReg & READ_VALID));
     }
    *value = (unsigned int)(smiReg & 0xffff);
    
    return true;


}

/*****************************************************************************
* 
* bool etherWriteMIIReg (unsigned int portNumber , unsigned int MIIReg,
* unsigned int value)
* 
* Description
* This function will access the MII registers and will write the value
* to the MII register.
* Inputs
* portNumber - one of the 2 possiable Ethernet ports (0-1).
* MIIReg - the MII register offset.
* value -the value that will be written.
* Outputs
* Returns Value
* true if success.
* false if fail to make the assignment.
* Error types (and exceptions if exist)
*/

GT_BOOL gtBspWriteMii (GT_QD_DEV* dev, unsigned int portNumber , unsigned int MIIReg,
                       unsigned int value)
{
SMI_REG smiReg;
unsigned int phyAddr;
unsigned int timeOut = 10; /* in 100MS units */
int i;

/* first check that it is not busy */
    GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
    if(smiReg & SMI_BUSY) 
    {
        for(i = 0 ; i < SMI_RX_TIMEOUT ; i++);
        do {
            GT_REG_READ (ETHER_SMI_REG,(unsigned int*)&smiReg);
            if(timeOut-- < 1 ) {
                return false;
            }
        } while (smiReg & SMI_BUSY);
    }
/* not busy */

    phyAddr = portNumber;

    smiReg = 0; /* make sure no garbage value in reserved bits */
    smiReg = smiReg | (phyAddr << 16) | (SMI_OP_CODE_BIT_WRITE << 26) |
             (MIIReg << 21) | (value & 0xffff);

    GT_REG_WRITE (ETHER_SMI_REG,*((unsigned int*)&smiReg));

    return(true);
}


void gtBspMiiInit(GT_QD_DEV* dev)
{
    return;    
}
