#include <Copyright.h>

/*******************************************************************************
* gtBrgStu.c
*
* DESCRIPTION:
*       API definitions for SID (VTU 802.1s Port State Information Database)
*        Translation Unit.
*
* DEPENDENCIES:
*
* FILE REVISION NUMBER:
*       $Revision: $
*******************************************************************************/

#include <msApi.h>
#include <gtSem.h>
#include <gtHwCntl.h>
#include <gtDrvSwRegs.h>

/****************************************************************************/
/* Forward function declaration.                                            */
/****************************************************************************/

static GT_STATUS stuOperationPerform
(
    IN        GT_QD_DEV           *dev,
    IN      GT_STU_OPERATION    stuOp,
    INOUT   GT_U8               *valid,
    INOUT     GT_STU_ENTRY        *stuEntry
);

/*******************************************************************************
* gstuGetEntryCount
*
* DESCRIPTION:
*       Gets the current number of valid entries in the STU table
*
* INPUTS:
*       None.
*
* OUTPUTS:
*       numEntries - number of STU entries.
*
* RETURNS:
*       GT_OK      - on success
*       GT_FAIL    - on error
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*       None
*
*******************************************************************************/
GT_STATUS gstuGetEntryCount
(
    IN  GT_QD_DEV *dev,
    OUT GT_U32    *numEntries
)
{
    GT_U8               valid;
    GT_U32                numOfEntries;
    GT_STATUS           retVal;
    GT_STU_ENTRY        entry;

    DBG_INFO(("gstuGetEntryCount Called.\n"));

    /* check if device supports this feature */
    if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    entry.sid = 0;
    numOfEntries = 0;

    while(1)
    {
        retVal = stuOperationPerform(dev,GET_NEXT_STU_ENTRY,&valid,&entry);
        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
            return retVal;
        }

        if( entry.sid==0x3F )
        {
            if (valid==1) numOfEntries++;
            break;
        }

        numOfEntries++;
    }

    *numEntries = numOfEntries;

    DBG_INFO(("OK.\n"));
    return GT_OK;

}


/*******************************************************************************
* gstuGetEntryFirst
*
* DESCRIPTION:
*       Gets first lexicographic entry from the STU.
*
* INPUTS:
*       None.
*
* OUTPUTS:
*       stuEntry - find the first valid STU entry.
*
* RETURNS:
*       GT_OK      - on success
*       GT_FAIL    - on error
*       GT_NO_SUCH - table is empty.
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gstuGetEntryFirst
(
    IN  GT_QD_DEV       *dev,
    OUT GT_STU_ENTRY    *stuEntry
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_U8               port;
    GT_LPORT               lport;
    GT_STU_ENTRY        entry;

    DBG_INFO(("gstuGetEntryFirst Called.\n"));

    /* check if device supports this feature */
    if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    entry.sid = 0;
    valid = 0;

    retVal = stuOperationPerform(dev,GET_NEXT_STU_ENTRY,&valid, &entry);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
        return retVal;
    }

    /* retrieve the value from the operation */

    if((entry.sid == 0x3F) && (valid == 0))
        return GT_NO_SUCH;

    stuEntry->sid = entry.sid;

    for(lport=0; lport<dev->numOfPorts; lport++)
    {
        port = GT_LPORT_2_PORT(lport);
        stuEntry->portState[lport]=entry.portState[port];
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* gstuGetEntryNext
*
* DESCRIPTION:
*       Gets next lexicographic STU entry from the specified SID.
*
* INPUTS:
*       stuEntry - the SID to start the search.
*
* OUTPUTS:
*       stuEntry - next STU entry.
*
* RETURNS:
*       GT_OK      - on success.
*       GT_FAIL    - on error or entry does not exist.
*       GT_NO_SUCH - no more entries.
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*
*******************************************************************************/
GT_STATUS gstuGetEntryNext
(
    IN  GT_QD_DEV       *dev,
    INOUT GT_STU_ENTRY  *stuEntry
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_U8               port;
    GT_LPORT               lport;
    GT_STU_ENTRY        entry;

    DBG_INFO(("gstuGetEntryNext Called.\n"));

    /* check if device supports this feature */

    if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    if(stuEntry->sid >= 0x3F)
    {
        return GT_NO_SUCH;
    }
    else
    {
        entry.sid = stuEntry->sid;
    }
    valid = 0;

    retVal = stuOperationPerform(dev,GET_NEXT_STU_ENTRY,&valid, &entry);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
        return retVal;
    }

    /* retrieve the value from the operation */

    if((entry.sid == 0x3F) && (valid == 0))
        return GT_NO_SUCH;

    stuEntry->sid = entry.sid;

    for(lport=0; lport<dev->numOfPorts; lport++)
    {
        port = GT_LPORT_2_PORT(lport);
        stuEntry->portState[lport]=entry.portState[port];
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* gstuFindSidEntry
*
* DESCRIPTION:
*       Find STU entry for a specific SID, it will return the entry, if found,
*       along with its associated data
*
* INPUTS:
*       stuEntry - contains the SID to searche for
*
* OUTPUTS:
*       found    - GT_TRUE, if the appropriate entry exists.
*       stuEntry - the entry parameters.
*
* RETURNS:
*       GT_OK      - on success.
*       GT_FAIL    - on error or entry does not exist.
*       GT_NO_SUCH - no such entry.
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*        Valid SID is 1 ~ 63.
*
*******************************************************************************/
GT_STATUS gstuFindSidEntry
(
    IN  GT_QD_DEV       *dev,
    INOUT GT_STU_ENTRY  *stuEntry,
    OUT GT_BOOL         *found
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_U8               port;
    GT_LPORT            lport;
    GT_STU_ENTRY        entry;

    DBG_INFO(("gstuFindSidEntry Called.\n"));

    /* check if device supports this feature */
    if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    if((stuEntry->sid == 0) || (stuEntry->sid > 0x3F))
    {
        DBG_INFO(("GT_BAD_PARAM\n"));
        return GT_BAD_PARAM;
    }

    *found = GT_FALSE;

    /* Decrement 1 from sid */
    entry.sid   = stuEntry->sid-1;
    valid = 0; /* valid is not used as input in this operation */

    retVal = stuOperationPerform(dev,GET_NEXT_STU_ENTRY,&valid, &entry);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
        return retVal;
    }

    /* retrive the value from the operation */
    if ((entry.sid != stuEntry->sid) | (valid == 0))
        return GT_NO_SUCH;

    for(lport=0; lport<dev->numOfPorts; lport++)
    {
        port = GT_LPORT_2_PORT(lport);
        stuEntry->portState[lport]=entry.portState[port];
    }

    *found = GT_TRUE;

    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* gstuAddEntry
*
* DESCRIPTION:
*       Creates or update the entry in STU table based on user input.
*
* INPUTS:
*       stuEntry    - stu entry to insert to the STU.
*
* OUTPUTS:
*       None
*
* RETURNS:
*       GT_OK             - on success
*       GT_FAIL           - on error
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*        Valid SID is 1 ~ 63.
*
*******************************************************************************/
GT_STATUS gstuAddEntry
(
    IN  GT_QD_DEV       *dev,
    IN  GT_STU_ENTRY    *stuEntry
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_U8           port;
    GT_LPORT           lport;
    GT_STU_ENTRY     tmpStuEntry;
    GT_BOOL             found;
    int                count = 50000;
    GT_STU_ENTRY        entry;

    DBG_INFO(("gstuAddEntry Called.\n"));

    /* check if device supports this feature */
    if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    if((stuEntry->sid == 0) || (stuEntry->sid > 0x3F))
    {
        DBG_INFO(("GT_BAD_PARAM\n"));
        return GT_BAD_PARAM;
    }

    entry.sid = stuEntry->sid;

    valid = 1; /* for load operation */

    for(port=0; port<dev->maxPorts; port++)
    {
        lport = GT_PORT_2_LPORT(port);
        if (lport == GT_INVALID_PORT)
            entry.portState[port] = 0;
        else
            entry.portState[port] = stuEntry->portState[lport];
    }

    retVal = stuOperationPerform(dev,LOAD_PURGE_STU_ENTRY,&valid, &entry);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
        return retVal;
    }

    /* verify that the given entry has been added */
    tmpStuEntry.sid = stuEntry->sid;

    if((retVal = gstuFindSidEntry(dev,&tmpStuEntry,&found)) != GT_OK)
    {
        while(count--);
        if((retVal = gstuFindSidEntry(dev,&tmpStuEntry,&found)) != GT_OK)
        {
            DBG_INFO(("Added entry cannot be found\n"));
            return retVal;
        }
    }
    if(found == GT_FALSE)
    {
        DBG_INFO(("Added entry cannot be found\n"));
        return GT_FAIL;
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}

/*******************************************************************************
* gstuDelEntry
*
* DESCRIPTION:
*       Deletes STU entry specified by user.
*
* INPUTS:
*       stuEntry - the STU entry to be deleted
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK           - on success
*       GT_FAIL         - on error
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*        Valid SID is 1 ~ 63.
*
*******************************************************************************/
GT_STATUS gstuDelEntry
(
    IN  GT_QD_DEV       *dev,
    IN  GT_STU_ENTRY     *stuEntry
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_STU_ENTRY        entry;

    DBG_INFO(("gstuDelEntry Called.\n"));

    /* check if device supports this feature */
    if (!IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    if((stuEntry->sid == 0) || (stuEntry->sid > 0x3F))
    {
        DBG_INFO(("GT_BAD_PARAM\n"));
        return GT_BAD_PARAM;
    }

    entry.sid = stuEntry->sid;
    valid = 0; /* for delete operation */

    retVal = stuOperationPerform(dev,LOAD_PURGE_STU_ENTRY,&valid, &entry);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed (stuOperationPerform returned GT_FAIL).\n"));
        return retVal;
    }
    DBG_INFO(("OK.\n"));
    return GT_OK;
}

/****************************************************************************/
/* Internal use functions.                                                  */
/****************************************************************************/

static GT_STATUS stuSetSTUData
(
    IN    GT_QD_DEV           *dev,
    IN    GT_STU_ENTRY        *entry
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data1,data2,data3;           /* Data to be set into the      */
    GT_U16            nStuData = 0;

    data1 = data2 = data3 = 0;

    switch (dev->maxPorts)
    {
        case 11:
            data3 |= (entry->portState[10] & 3) << 10;
            /* pass through */
        case 10:
            data3 |= (entry->portState[9] & 3) << 6;
            /* pass through */
        case 9:
            data3 |= (entry->portState[8] & 3) << 2;
            nStuData++;

            /* pass through */
        case 8:
            data2 |= (entry->portState[7] & 3) << 14;
            /* pass through */
        case 7:
            data2 |= (entry->portState[6] & 3) << 10;
            /* pass through */
        case 6:
            data2 |= (entry->portState[5] & 3) << 6;
            /* pass through */
        case 5:
            data2 |= (entry->portState[4] & 3) << 2;
            nStuData++;

            /* pass through */
        case 4:
            data1 |= (entry->portState[3] & 3) << 14;
            /* pass through */
        case 3:
            data1 |= (entry->portState[2] & 3) << 10;
            /* pass through */
        case 2:
            data1 |= (entry->portState[1] & 3) << 6;
            /* pass through */
        case 1:
            data1 |= (entry->portState[0] & 3) << 2;
            nStuData++;
            break;

        default:
            return GT_FAIL;
    }

    switch(nStuData)
    {
        case 3:
            retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA3_REG,data3);
            if(retVal != GT_OK)
            {
                return retVal;
            }
            /* pass through */
        case 2:
            retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA2_REG,data2);
            if(retVal != GT_OK)
            {
                return retVal;
            }
            /* pass through */
        case 1:
            retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA1_REG,data1);
            if(retVal != GT_OK)
            {
                return retVal;
            }
            break;
        default:
            return GT_FAIL;
    }

    return retVal;
}

static GT_STATUS stuGetSTUData
(
    IN    GT_QD_DEV           *dev,
    OUT    GT_STU_ENTRY        *entry
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data1,data2,data3;           /* Data to be set into the      */
    GT_U16            nStuData = 0;

    data1 = data2 = data3 = 0;

    gtMemSet((void*)entry->portState,0,sizeof(entry->portState));

    switch (dev->maxPorts)
    {
        case 11:
        case 10:
        case 9:
            nStuData = 3;
            break;

        case 8:
        case 7:
        case 6:
        case 5:
            nStuData = 2;
            break;

        case 4:
        case 3:
        case 2:
        case 1:
            nStuData = 1;
            break;

        default:
            return GT_FAIL;
    }

    switch(nStuData)
    {
        case 3:
            retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA3_REG,&data3);
            if(retVal != GT_OK)
            {
                return retVal;
            }
            /* pass through */
        case 2:
            retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA2_REG,&data2);
            if(retVal != GT_OK)
            {
                return retVal;
            }
            /* pass through */
        case 1:
            retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA1_REG,&data1);
            if(retVal != GT_OK)
            {
                return retVal;
            }
            break;
        default:
            return GT_FAIL;
    }

    switch (dev->maxPorts)
    {
        case 11:
            entry->portState[10]  = (data3 >> 10) & 3 ;
            /* pass through */
        case 10:
            entry->portState[9]  = (data3 >> 6) & 3 ;
            /* pass through */
        case 9:
            entry->portState[8]  = (data3 >> 2) & 3 ;
            /* pass through */
        case 8:
            entry->portState[7]  = (data2 >> 14) & 3 ;
            /* pass through */
        case 7:
            entry->portState[6]  = (data2 >> 10) & 3 ;
            /* pass through */
        case 6:
            entry->portState[5]  = (data2 >> 6) & 3 ;
            /* pass through */
        case 5:
            entry->portState[4]  = (data2 >> 2) & 3 ;
            /* pass through */
        case 4:
            entry->portState[3]  = (data1 >> 14) & 3 ;
            /* pass through */
        case 3:
            entry->portState[2]  = (data1 >> 10) & 3 ;
            /* pass through */
        case 2:
            entry->portState[1]  = (data1 >> 6) & 3 ;
            /* pass through */
        case 1:
            entry->portState[0]  = (data1 >> 2) & 3 ;
            break;

        default:
            return GT_FAIL;
    }

    return GT_OK;
}


/*******************************************************************************
* stuOperationPerform
*
* DESCRIPTION:
*       This function is used by all STU control functions, and is responsible
*       to write the required operation into the STU registers.
*
* INPUTS:
*       stuOp       - The STU operation bits to be written into the STU
*                     operation register.
*       sid         - sid
*       valid       - valid bit
*       stuData     - STU Data with port state information
*
* OUTPUTS:
*       sid         - sid
*       valid       - valid bit
*       stuData     - STU Data with port state information
*
* RETURNS:
*       GT_OK on success,
*       GT_FAIL otherwise.
*
* COMMENTS:
*
*******************************************************************************/

static GT_STATUS stuOperationPerform
(
    IN        GT_QD_DEV           *dev,
    IN      GT_STU_OPERATION    stuOp,
    INOUT   GT_U8               *valid,
    INOUT    GT_STU_ENTRY        *entry
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* Data to be set into the      */
                                /* register.                    */

    gtSemTake(dev,dev->vtuRegsSem,OS_WAIT_FOREVER);

    /* Wait until the VTU in ready. */
    data = 1;
    while(data == 1)
    {
        retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,15,1,&data);
        if(retVal != GT_OK)
        {
            gtSemGive(dev,dev->vtuRegsSem);
            return retVal;
        }
    }

    /* Set the VTU data register if Load operation is required. */
    if (stuOp == LOAD_PURGE_STU_ENTRY)
    {
        if (*valid == 1)
        {
            /* set the Port State for all the ports */
            retVal = stuSetSTUData(dev,entry);
            if(retVal != GT_OK)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
            }

            /* Set the valid bit (QD_REG_VTU_VID_REG) */
               data= *valid << 12 ;
            retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_VTU_VID_REG),data);
               if(retVal != GT_OK)
            {
                   gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
                  }
        }
        else
        {
            /* Clear the valid bit (QD_REG_VTU_VID_REG) */
               data= 0 ;
            retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_VTU_VID_REG),data);
               if(retVal != GT_OK)
            {
                   gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
                  }
        }
    }

    /* Set the SID register (QD_REG_STU_SID_REG) */
       data= (entry->sid) & 0x3F;
    retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_STU_SID_REG),data);
       if(retVal != GT_OK)
    {
           gtSemGive(dev,dev->vtuRegsSem);
        return retVal;
       }

    /* Start the STU Operation by defining the stuOp and VTUBusy */
    data = (1 << 15) | (stuOp << 12);

    retVal = hwWriteGlobalReg(dev,QD_REG_VTU_OPERATION,data);
    if(retVal != GT_OK)
    {
        gtSemGive(dev,dev->vtuRegsSem);
        return retVal;
    }

    /* If the operation is a get next operation wait for the response   */
    if(stuOp == GET_NEXT_STU_ENTRY)
    {
        /* Wait until the STU in ready. */
        data = 1;
        while(data == 1)
        {
            retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,15,1,&data);
            if(retVal != GT_OK)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
            }
        }

        /****************** get the valid bit *******************/
        retVal = hwGetGlobalRegField(dev,QD_REG_VTU_VID_REG,12,1,&data);
        if(retVal != GT_OK)
        {
            gtSemGive(dev,dev->vtuRegsSem);
            return retVal;
        }

        *valid = (GT_U8)data;

        /****************** get the sid *******************/

        retVal = hwReadGlobalReg(dev,QD_REG_STU_SID_REG,&data);
        if(retVal != GT_OK)
        {
            gtSemGive(dev,dev->vtuRegsSem);
            return retVal;
        }

        /* the sid is bits 0-5 */
        entry->sid   = data & 0x3F;

        if (*valid)
        {
            /* get the Port State for all the ports */
            retVal = stuGetSTUData(dev,entry);
            if(retVal != GT_OK)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
            }

        } /* entry is valid */

    } /* end of get next entry */

    gtSemGive(dev,dev->vtuRegsSem);
    return GT_OK;
}
