#include <Copyright.h>

/*******************************************************************************
* gtBrgVtu.c
*
* DESCRIPTION:
*       API definitions for Vlan Translation Unit for 802.1Q.
*
* DEPENDENCIES:
*
* FILE REVISION NUMBER:
*       $Revision: 9 $
*******************************************************************************/

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

/****************************************************************************/
/* Forward function declaration.                                            */
/****************************************************************************/
#define MEMBER_TAG_CONV_FOR_APP(_dev,_tag)    memberTagConversionForApp(_dev,_tag)
#define MEMBER_TAG_CONV_FOR_DEV(_dev,_tag)    memberTagConversionForDev(_dev,_tag)

static GT_U8 memberTagConversionForApp
(
    IN    GT_QD_DEV           *dev,
    IN    GT_U8               tag
)
{
    GT_U8 convTag;

    /* check if memberTag needs to be converted */
    if (!((IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_FE_AVB_FAMILY))))
        return tag;

    switch(tag)
    {
        case 0:
                convTag = MEMBER_EGRESS_UNMODIFIED;
                break;
        case 1:
                convTag = MEMBER_EGRESS_UNTAGGED;
                break;
        case 2:
                convTag = MEMBER_EGRESS_TAGGED;
                break;
        case 3:
                convTag = NOT_A_MEMBER;
                break;
        default:
                DBG_INFO(("Unknown Tag (%#x) from Device !!!.\n",tag));
                convTag = 0xFF;
                break;
            
    }

    return convTag;
}

static GT_U8 memberTagConversionForDev
(
    IN    GT_QD_DEV           *dev,
    IN    GT_U8               tag
)
{
    GT_U8 convTag;

    /* check if memberTag needs to be converted */
    if (!((IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_FE_AVB_FAMILY))))
        return tag;

    switch(tag)
    {
        case MEMBER_EGRESS_UNMODIFIED:
                convTag = 0;
                break;
        case NOT_A_MEMBER:
                convTag = 3;
                break;
        case MEMBER_EGRESS_UNTAGGED:
                convTag = 1;
                break;
        case MEMBER_EGRESS_TAGGED:
                convTag = 2;
                break;
        default:
                DBG_INFO(("Unknown Tag (%#x) from App. !!!.\n",tag));
                convTag = 0xFF;
                break;
            
    }

    return convTag;
}

static GT_STATUS vtuOperationPerform
(
    IN        GT_QD_DEV           *dev,
    IN      GT_VTU_OPERATION    vtuOp,
    INOUT   GT_U8               *valid,
    INOUT     GT_VTU_ENTRY        *vtuEntry
);

/*******************************************************************************
* gvtuGetEntryCount
*
* DESCRIPTION:
*       Gets the current number of valid entries in the VTU table
*
* INPUTS:
*       None.
*
* OUTPUTS:
*       numEntries - number of VTU entries.
*
* RETURNS:
*       GT_OK      - on success
*       GT_FAIL    - on error
*       GT_NO_SUCH - vlan does not exist.
*
* COMMENTS:
*       None
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuGetEntryCount
(
    IN  GT_QD_DEV *dev,
    OUT GT_U32    *numEntries
)
{
    GT_U8               valid;
    GT_U32        numOfEntries;
    GT_STATUS           retVal;
    GT_VTU_ENTRY        entry;

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

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
      return retVal;

    entry.vid = 0xFFF;
    entry.DBNum = 0;

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

        if( entry.vid==0xFFF )
        {
            if (valid==1) numOfEntries++;
            break;
        }

        numOfEntries++;
    }

    *numEntries = numOfEntries;

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

}


/*******************************************************************************
* gvtuGetEntryFirst
*
* DESCRIPTION:
*       Gets first lexicographic entry from the VTU.
*
* INPUTS:
*       None.
*
* OUTPUTS:
*       vtuEntry - match VTU entry.
*
* RETURNS:
*       GT_OK      - on success
*       GT_FAIL    - on error
*       GT_NO_SUCH - table is empty.
*
* COMMENTS:
*       Search starts from vid of all one's
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuGetEntryFirst
(
    IN  GT_QD_DEV       *dev,
    OUT GT_VTU_ENTRY    *vtuEntry
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_U8               port; 
    GT_LPORT               lport; 
    GT_VTU_ENTRY        entry;

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

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
      return retVal;

    entry.vid = 0xFFF;
    entry.DBNum = 0;

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

    /* retrive the value from the operation */ 

    if((entry.vid == 0xFFF) && (valid == 0))
        return GT_NO_SUCH;

    vtuEntry->DBNum = entry.DBNum;
    vtuEntry->vid   = entry.vid;

    vtuEntry->vidPriOverride = entry.vidPriOverride;
    vtuEntry->vidPriority = entry.vidPriority;

    vtuEntry->vidPolicy = entry.vidPolicy;
    vtuEntry->sid = entry.sid;

    vtuEntry->vidExInfo.useVIDFPri = entry.vidExInfo.useVIDFPri;
    vtuEntry->vidExInfo.vidFPri = entry.vidExInfo.vidFPri;
    vtuEntry->vidExInfo.useVIDQPri = entry.vidExInfo.useVIDQPri;
    vtuEntry->vidExInfo.vidQPri = entry.vidExInfo.vidQPri;
    vtuEntry->vidExInfo.vidNRateLimit = entry.vidExInfo.vidNRateLimit;

    for(lport=0; lport<dev->numOfPorts; lport++)
    {
        port = GT_LPORT_2_PORT(lport);
        vtuEntry->vtuData.memberTagP[lport]=MEMBER_TAG_CONV_FOR_APP(dev,entry.vtuData.memberTagP[port]);
        vtuEntry->vtuData.portStateP[lport]=entry.vtuData.portStateP[port];
    }

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


/*******************************************************************************
* gvtuGetEntryNext
*
* DESCRIPTION:
*       Gets next lexicographic VTU entry from the specified VID.
*
* INPUTS:
*       vtuEntry - the VID to start the search.
*
* OUTPUTS:
*       vtuEntry - match VTU  entry.
*
* RETURNS:
*       GT_OK      - on success.
*       GT_FAIL    - on error or entry does not exist.
*       GT_NO_SUCH - no more entries.
*
* COMMENTS:
*       Search starts from the VID specified by the user.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuGetEntryNext
(
    IN  GT_QD_DEV       *dev,
    INOUT GT_VTU_ENTRY  *vtuEntry
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_U8               port; 
    GT_LPORT               lport; 
    GT_VTU_ENTRY        entry;

    DBG_INFO(("gvtuGetEntryNext Called.\n"));
    
    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
      return retVal;

    entry.DBNum = vtuEntry->DBNum;
    entry.vid   = vtuEntry->vid;
    valid = 0;

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

    /* retrieve the value from the operation */ 

    if((entry.vid == 0xFFF) && (valid == 0))
        return GT_NO_SUCH;

    vtuEntry->DBNum = entry.DBNum;
    vtuEntry->vid   = entry.vid;

    vtuEntry->vidPriOverride = entry.vidPriOverride;
    vtuEntry->vidPriority = entry.vidPriority;

    vtuEntry->vidPolicy = entry.vidPolicy;
    vtuEntry->sid = entry.sid;

    vtuEntry->vidExInfo.useVIDFPri = entry.vidExInfo.useVIDFPri;
    vtuEntry->vidExInfo.vidFPri = entry.vidExInfo.vidFPri;
    vtuEntry->vidExInfo.useVIDQPri = entry.vidExInfo.useVIDQPri;
    vtuEntry->vidExInfo.vidQPri = entry.vidExInfo.vidQPri;
    vtuEntry->vidExInfo.vidNRateLimit = entry.vidExInfo.vidNRateLimit;

    for(lport=0; lport<dev->numOfPorts; lport++)
    {
        port = GT_LPORT_2_PORT(lport);
        vtuEntry->vtuData.memberTagP[lport]=MEMBER_TAG_CONV_FOR_APP(dev,entry.vtuData.memberTagP[port]);
        vtuEntry->vtuData.portStateP[lport]=entry.vtuData.portStateP[port];
    }

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



/*******************************************************************************
* gvtuFindVidEntry
*
* DESCRIPTION:
*       Find VTU entry for a specific VID, it will return the entry, if found, 
*       along with its associated data 
*
* INPUTS:
*       vtuEntry - contains the VID to searche for 
*
* OUTPUTS:
*       found    - GT_TRUE, if the appropriate entry exists.
*       vtuEntry - the entry parameters.
*
* RETURNS:
*       GT_OK      - on success.
*       GT_FAIL    - on error or entry does not exist.
*       GT_NO_SUCH - no more entries.
*
* COMMENTS:
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuFindVidEntry
(
    IN  GT_QD_DEV       *dev,
    INOUT GT_VTU_ENTRY  *vtuEntry,
    OUT GT_BOOL         *found
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_U8               port;
    GT_LPORT            lport;
    GT_VTU_ENTRY        entry;

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

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
      return retVal;

    *found = GT_FALSE;

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

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

    /* retrive the value from the operation */ 

    if( (entry.vid !=vtuEntry->vid) | (valid !=1) )
    {
          DBG_INFO(("Failed.\n"));
          return GT_NO_SUCH;
    }

    vtuEntry->DBNum = entry.DBNum;

    vtuEntry->vidPriOverride = entry.vidPriOverride;
    vtuEntry->vidPriority = entry.vidPriority;

    vtuEntry->vidPolicy = entry.vidPolicy;
    vtuEntry->sid = entry.sid;

    vtuEntry->vidExInfo.useVIDFPri = entry.vidExInfo.useVIDFPri;
    vtuEntry->vidExInfo.vidFPri = entry.vidExInfo.vidFPri;
    vtuEntry->vidExInfo.useVIDQPri = entry.vidExInfo.useVIDQPri;
    vtuEntry->vidExInfo.vidQPri = entry.vidExInfo.vidQPri;
    vtuEntry->vidExInfo.vidNRateLimit = entry.vidExInfo.vidNRateLimit;

    for(lport=0; lport<dev->numOfPorts; lport++)
    {
        port = GT_LPORT_2_PORT(lport);
        vtuEntry->vtuData.memberTagP[lport]=MEMBER_TAG_CONV_FOR_APP(dev,entry.vtuData.memberTagP[port]);
        vtuEntry->vtuData.portStateP[lport]=entry.vtuData.portStateP[port];
    }

    *found = GT_TRUE;

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



/*******************************************************************************
* gvtuFlush
*
* DESCRIPTION:
*       This routine removes all entries from VTU Table.
*
* INPUTS:
*       None
*
* OUTPUTS:
*       None
*
* RETURNS:
*       GT_OK           - on success
*       GT_FAIL         - on error
*
* COMMENTS:
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuFlush
(
    IN  GT_QD_DEV       *dev
)
{
    GT_STATUS       retVal;

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

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK)
    {
        return retVal;
    }

    retVal = vtuOperationPerform(dev,FLUSH_ALL,NULL,NULL);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

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

/*******************************************************************************
* gvtuAddEntry
*
* DESCRIPTION:
*       Creates the new entry in VTU table based on user input.
*
* INPUTS:
*       vtuEntry    - vtu entry to insert to the VTU.
*
* OUTPUTS:
*       None
*
* RETURNS:
*       GT_OK             - on success
*       GT_FAIL           - on error
*       GT_FULL              - vtu table is full
*
* COMMENTS:
*       None.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuAddEntry
(
    IN  GT_QD_DEV   *dev,
    IN GT_VTU_ENTRY *vtuEntry
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_U8           port; 
    GT_LPORT           lport; 
    GT_VTU_ENTRY     tmpVtuEntry;
    GT_BOOL             found;
    int                count = 5000;
    GT_VTU_ENTRY        entry;

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

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
      return retVal;

    entry.DBNum = vtuEntry->DBNum;
    entry.vid   = vtuEntry->vid;

    if(IS_IN_DEV_GROUP(dev,DEV_VTU_EXT_INFO))
    {
        entry.vidPriOverride = 0;
        entry.vidPriority = 0;

        entry.vidPolicy = GT_FALSE;
        entry.sid = 0;

        if(IS_IN_DEV_GROUP(dev,DEV_FQPRI_IN_TABLE))
        {
            entry.vidExInfo.useVIDFPri = vtuEntry->vidExInfo.useVIDFPri;
            entry.vidExInfo.vidFPri = vtuEntry->vidExInfo.vidFPri;
            entry.vidExInfo.useVIDQPri = vtuEntry->vidExInfo.useVIDQPri;
            entry.vidExInfo.vidQPri = vtuEntry->vidExInfo.vidQPri;
            entry.vidExInfo.vidNRateLimit = vtuEntry->vidExInfo.vidNRateLimit;
        }
        else
        {
            entry.vidExInfo.useVIDFPri = 0;
            entry.vidExInfo.vidFPri = 0;
            entry.vidExInfo.useVIDQPri = 0;
            entry.vidExInfo.vidQPri = 0;
            entry.vidExInfo.vidNRateLimit = vtuEntry->vidExInfo.vidNRateLimit;
        }
    }
    else
    {
        entry.vidPriOverride = vtuEntry->vidPriOverride;
        entry.vidPriority = vtuEntry->vidPriority;

        if(IS_IN_DEV_GROUP(dev,DEV_POLICY))
        {
            entry.vidPolicy = vtuEntry->vidPolicy;
        }
        else
        {
            entry.vidPolicy = GT_FALSE;
        }

        if(IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
        {
            entry.sid = vtuEntry->sid;
        }
        else
        {
            entry.sid = 0;
        }

        entry.vidExInfo.useVIDFPri = 0;
        entry.vidExInfo.vidFPri = 0;
        entry.vidExInfo.useVIDQPri = 0;
        entry.vidExInfo.vidQPri = 0;
        entry.vidExInfo.vidNRateLimit = 0;
    }

    valid = 1; /* for load operation */

    for(port=0; port<dev->maxPorts; port++)
    {
        lport = GT_PORT_2_LPORT(port);
        if(lport == GT_INVALID_PORT)
        {
            entry.vtuData.memberTagP[port] = MEMBER_TAG_CONV_FOR_DEV(dev,NOT_A_MEMBER);
            entry.vtuData.portStateP[port] = 0;
        }
        else
        {
            entry.vtuData.memberTagP[port] = MEMBER_TAG_CONV_FOR_DEV(dev,vtuEntry->vtuData.memberTagP[lport]);
            if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
                entry.vtuData.portStateP[port] = vtuEntry->vtuData.portStateP[lport];
            else
                entry.vtuData.portStateP[port] = 0;
        }
    }

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

    /* verify that the given entry has been added */
    tmpVtuEntry.vid = vtuEntry->vid;
    tmpVtuEntry.DBNum = vtuEntry->DBNum;

    if((retVal = gvtuFindVidEntry(dev,&tmpVtuEntry,&found)) != GT_OK)
    {
        while(count--);
        if((retVal = gvtuFindVidEntry(dev,&tmpVtuEntry,&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;
}

/*******************************************************************************
* gvtuDelEntry
*
* DESCRIPTION:
*       Deletes VTU entry specified by user.
*
* INPUTS:
*       vtuEntry - the VTU entry to be deleted 
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK           - on success
*       GT_FAIL         - on error
*       GT_NO_SUCH      - if specified address entry does not exist
*
* COMMENTS:
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuDelEntry
(
    IN  GT_QD_DEV   *dev,
    IN GT_VTU_ENTRY *vtuEntry
)
{
    GT_U8               valid;
    GT_STATUS           retVal;
    GT_VTU_ENTRY        entry;

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

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,1, DEV_802_1Q)) != GT_OK) 
      return retVal;
    
    entry.DBNum = vtuEntry->DBNum;
    entry.vid   = vtuEntry->vid;
    valid = 0; /* for delete operation */

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

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

/*******************************************************************************
* gvtuGetViolation
*
* DESCRIPTION:
*       Get VTU Violation data
*
* INPUTS:
*       None.
*
* OUTPUTS:
*       vtuIntStatus - interrupt cause, source portID, and vid.
*
* RETURNS:
*       GT_OK           - on success
*       GT_FAIL         - on error
*       GT_NOT_SUPPORT  - if current device does not support this feature.
*
* COMMENTS:
*        This is an internal function. No user should call this function.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuGetViolation
(
    IN  GT_QD_DEV         *dev,
    OUT GT_VTU_INT_STATUS *vtuIntStatus
)
{
    GT_U8               spid;
    GT_U16               vid;
    GT_U16               intCause;
    GT_STATUS           retVal;
    GT_VTU_ENTRY        entry;

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

    /* check which Violation occurred */
    retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,4,3,&intCause);
    if(retVal != GT_OK)
    {
        DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
        return retVal;
    }

    if (intCause == 0)
    {
        /* No Violation occurred. */
        vtuIntStatus->vtuIntCause = 0;
        return GT_OK;
    }

    entry.DBNum = 0;

    retVal = vtuOperationPerform(dev,SERVICE_VIOLATIONS,NULL, &entry);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
        return retVal;
    }

    spid = entry.DBNum & 0xF;
    vid = entry.vid;

    if(spid == 0xF)
    {
        vtuIntStatus->vtuIntCause = GT_VTU_FULL_VIOLATION;
        vtuIntStatus->spid = spid;
        vtuIntStatus->vid = 0;
    }
    else
    {
        vtuIntStatus->vtuIntCause = intCause & (GT_MEMBER_VIOLATION | GT_MISS_VIOLATION);
        vtuIntStatus->spid = spid;
        vtuIntStatus->vid = vid;
    }
    
    DBG_INFO(("OK.\n"));
    return GT_OK;
}

/*******************************************************************************
* gvtuGetViolation2
*
* DESCRIPTION:
*       Get VTU Violation data (for Gigabit Device)
*
* INPUTS:
*       None.
*
* OUTPUTS:
*       vtuIntStatus - interrupt cause, source portID, and vid.
*
* RETURNS:
*       GT_OK           - on success
*       GT_FAIL         - on error
*       GT_NOT_SUPPORT  - if current device does not support this feature.
*
* COMMENTS:
*        This is an internal function. No user should call this function.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuGetViolation2
(
    IN  GT_QD_DEV         *dev,
    OUT GT_VTU_INT_STATUS *vtuIntStatus
)
{
    GT_U16               intCause;
    GT_STATUS           retVal;
    GT_VTU_ENTRY        entry;

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

    /* check if Violation occurred */
    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,5,1,&intCause);
    if(retVal != GT_OK)
    {
        DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
        return retVal;
    }

    if (intCause == 0)
    {
        /* No Violation occurred. */
        vtuIntStatus->vtuIntCause = 0;
        return GT_OK;
    }

    entry.DBNum = 0;

    retVal = vtuOperationPerform(dev,SERVICE_VIOLATIONS,NULL, &entry);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
        return retVal;
    }

    /* check which Violation occurred */
    retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,5,2,&intCause);
    if(retVal != GT_OK)
    {
        DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
        return retVal;
    }

    switch (intCause)
    {
        case 0:
            /* No Violation occurred. */
            vtuIntStatus->vtuIntCause = 0;
            return GT_OK;
        case 1:
            /* Miss Violation */
            vtuIntStatus->vtuIntCause = GT_MISS_VIOLATION;
            break;
        case 2:
            /* Member Violation */
            vtuIntStatus->vtuIntCause = GT_MEMBER_VIOLATION;
            break;
        default :
            return GT_FAIL;
    }

    vtuIntStatus->spid = entry.DBNum & 0xF;
    vtuIntStatus->vid = entry.vid;
    
    DBG_INFO(("OK.\n"));
    return GT_OK;
}

/*******************************************************************************
* gvtuGetViolation3
*
* DESCRIPTION:
*       Get VTU Violation data
*
* INPUTS:
*       None.
*
* OUTPUTS:
*       vtuIntStatus - interrupt cause, source portID, and vid.
*
* RETURNS:
*       GT_OK           - on success
*       GT_FAIL         - on error
*       GT_NOT_SUPPORT  - if current device does not support this feature.
*
* COMMENTS:
*        This is an internal function. No user should call this function.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS gvtuGetViolation3
(
    IN  GT_QD_DEV         *dev,
    OUT GT_VTU_INT_STATUS *vtuIntStatus
)
{
    GT_U16               intCause;
    GT_STATUS           retVal;
    GT_VTU_ENTRY        entry;

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

    /* check if Violation occurred */
    retVal = hwGetGlobalRegField(dev,QD_REG_GLOBAL_STATUS,5,1,&intCause);
    if(retVal != GT_OK)
    {
        DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
        return retVal;
    }

    if (intCause == 0)
    {
        /* No Violation occurred. */
        vtuIntStatus->vtuIntCause = 0;
        return GT_OK;
    }

    entry.DBNum = 0;

    retVal = vtuOperationPerform(dev,SERVICE_VIOLATIONS,NULL, &entry);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed (vtuOperationPerform returned GT_FAIL).\n"));
        return retVal;
    }

    /* check which Violation occurred */
    retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,4,3,&intCause);
    if(retVal != GT_OK)
    {
        DBG_INFO(("ERROR to read VTU OPERATION Register.\n"));
        return retVal;
    }

    vtuIntStatus->vtuIntCause = 0;

    if(intCause & 0x1)
    {
        vtuIntStatus->vtuIntCause |= GT_VTU_FULL_VIOLATION;
    }

    if(intCause & 0x2)
    {
        vtuIntStatus->vtuIntCause |= GT_MISS_VIOLATION;
    }

    if(intCause & 0x4)
    {
        vtuIntStatus->vtuIntCause |= GT_MEMBER_VIOLATION;
    }
            
    vtuIntStatus->spid = entry.DBNum & 0xF;
    vtuIntStatus->vid = entry.vid;

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


/*******************************************************************************
* vtuOperationPerform
*
* DESCRIPTION:
*       This function is used by all VTU control functions, and is responsible
*       to write the required operation into the VTU registers.
*
* INPUTS:
*       vtuOp       - The VTU operation bits to be written into the VTU
*                     operation register.
*       DBNum       - DBNum where the given vid belongs to
*       vid         - vlan id
*       valid       - valid bit
*       vtuData     - VTU Data with memberTag information
*
* OUTPUTS:
*       DBNum       - DBNum where the given vid belongs to
*       vid         - vlan id
*       valid       - valid bit
*       vtuData     - VTU Data with memberTag information
*
* RETURNS:
*       GT_OK on success,
*       GT_FAIL otherwise.
*
* COMMENTS:
*
*******************************************************************************/

static GT_STATUS vtuOperationPerform
(
    IN        GT_QD_DEV           *dev,
    IN      GT_VTU_OPERATION    vtuOp,
    INOUT   GT_U8               *valid,
    INOUT    GT_VTU_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. */
#ifdef GT_RMGMT_ACCESS
    {
      HW_DEV_REG_ACCESS regAccess;

      regAccess.entries = 1;
  
      regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0;
      regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS);
      regAccess.rw_reg_list[0].reg = QD_REG_VTU_OPERATION;
      regAccess.rw_reg_list[0].data = 15;
      retVal = hwAccessMultiRegs(dev, &regAccess);
      if(retVal != GT_OK)
      {
        gtSemGive(dev,dev->vtuRegsSem);
        return retVal;
      }
    }
#else
    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;
        }
    }
#endif

    /* Set the VTU data register    */
    /* There is no need to setup data reg. on flush, get next, or service violation */
    if((vtuOp != FLUSH_ALL) && (vtuOp != GET_NEXT_ENTRY) && (vtuOp != SERVICE_VIOLATIONS))
    {

        /****************** VTU DATA 1 REG *******************/

        /* get data and wirte to QD_REG_VTU_DATA1_REG (ports 0 to 3) */

        data =  (entry->vtuData.memberTagP[0] & 3)     |
                ((entry->vtuData.memberTagP[1] & 3)<<4) | 
                ((entry->vtuData.memberTagP[2] & 3)<<8);

        if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
            data |= ((entry->vtuData.portStateP[0] & 3)<<2)    |
                    ((entry->vtuData.portStateP[1] & 3)<<6) | 
                    ((entry->vtuData.portStateP[2] & 3)<<10);
            
        if(dev->maxPorts > 3)
        {
            data |= ((entry->vtuData.memberTagP[3] & 3)<<12) ;
            if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
                data |= ((entry->vtuData.portStateP[3] & 3)<<14) ;
        }

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

        /****************** VTU DATA 2 REG *******************/

        /* get data and wirte to QD_REG_VTU_DATA2_REG (ports 4 to 7) */

        if(dev->maxPorts > 4)
        {
            /* also need to set data register  ports 4 to 6 */

            data =  (entry->vtuData.memberTagP[4] & 3)   |
                    ((entry->vtuData.memberTagP[5] & 3) << 4);

            if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
                data |= ((entry->vtuData.portStateP[4] & 3) << 2) |
                        ((entry->vtuData.portStateP[5] & 3) << 6); 

            if(dev->maxPorts > 6)
            {
                data |= ((entry->vtuData.memberTagP[6] & 3)<<8) ;
                if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
                    data |= ((entry->vtuData.portStateP[6] & 3)<<10) ;
            }

            if(dev->maxPorts > 7)
            {
                data |= ((entry->vtuData.memberTagP[7] & 3)<<12) ;
                if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
                    data |= ((entry->vtuData.portStateP[7] & 3)<<14) ;
            }

            if (IS_IN_DEV_GROUP(dev,DEV_VTU_EXT_INFO))
            {
                if(entry->vidExInfo.useVIDFPri == GT_TRUE)
                    data |= ((1 << 15) | ((entry->vidExInfo.vidFPri & 0x7) << 12));
                if(entry->vidExInfo.useVIDQPri == GT_TRUE)
                    data |= ((1 << 11) | ((entry->vidExInfo.vidQPri & 0x3) << 9));
                if(entry->vidExInfo.vidNRateLimit == GT_TRUE)
                    data |= (1 << 8);
            }

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


        /****************** VTU DATA 3 REG *******************/

        /* get data and wirte to QD_REG_VTU_DATA3_REG (ports 8 to 10) */

        if(dev->maxPorts > 7)
        {
            /* also need to set data register  ports 8 to 9 */

            data =  (entry->vtuData.memberTagP[8] & 3)   |
                    ((entry->vtuData.memberTagP[9] & 3) << 4);

            if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
                data |= ((entry->vtuData.portStateP[8] & 3) << 2)    |
                        ((entry->vtuData.portStateP[9] & 3) << 6);

            if(dev->maxPorts > 10)
            {
                data |= (entry->vtuData.memberTagP[10] & 3) << 8;

                if (IS_IN_DEV_GROUP(dev,DEV_802_1S))
                    data |= (entry->vtuData.portStateP[10] & 3) << 10;
            }
            
            if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
            {
                if(entry->vidPriOverride == GT_TRUE)
                    data |= ((1 << 15) | ((entry->vidPriority & 0x7) << 12));
            }

            retVal = hwWriteGlobalReg(dev,QD_REG_VTU_DATA3_REG,data);
            if(retVal != GT_OK)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
            }
        }
        else if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
        {
            if(entry->vidPriOverride == GT_TRUE)
                data = ((1 << 15) | ((entry->vidPriority & 0x7) << 12));
            else
                data = 0;

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

    /* Set the VID register (QD_REG_VTU_VID_REG) */
    /* There is no need to setup VID reg. on flush and service violation */
    if((vtuOp != FLUSH_ALL) && (vtuOp != SERVICE_VIOLATIONS) )
    {
        data= ( (entry->vid) & 0xFFF ) | ( (*valid) << 12 );
        retVal = hwWriteGlobalReg(dev,(GT_U8)(QD_REG_VTU_VID_REG),data);
        if(retVal != GT_OK)
        {
            gtSemGive(dev,dev->vtuRegsSem);
            return retVal;
        }        
    }

    /* Set SID, FID, VIDPolicy, if it's Load operation */
    if((vtuOp == LOAD_PURGE_ENTRY) && (*valid == 1))
    {
        if(IS_IN_DEV_GROUP(dev,DEV_802_1S_STU))
        {
            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;
            }        
        }

        data = 0;

        if(IS_IN_DEV_GROUP(dev,DEV_FID_REG))
        {
            if(IS_IN_DEV_GROUP(dev,DEV_POLICY))
            {
                data= entry->vidPolicy << 12;
            }

            data |= (entry->DBNum & 0xFFF);

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


    }

    /* Start the VTU Operation by defining the DBNum, vtuOp and VTUBusy    */
    /* 
     * Flush operation will skip the above two setup (for data and vid), and 
     * come to here directly
     */

    if(vtuOp == FLUSH_ALL)
        data = (1 << 15) | (vtuOp << 12);
    else
    {
        if(IS_IN_DEV_GROUP(dev,DEV_FID_REG))
        {
            data = (1 << 15) | (vtuOp << 12);
        }
        else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
        {
            /* Since DBNum is defined as GT_U8, it cannot be >= 256. */
            #if 0
            if(entry->DBNum >= 256)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return GT_BAD_PARAM;
            }    
            #endif
            data = (1 << 15) | (vtuOp << 12) | ((entry->DBNum & 0xF0) << 4) | (entry->DBNum & 0x0F);
        }
        else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
        {
            if(entry->DBNum >= 64)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return GT_BAD_PARAM;
            }    
            data = (1 << 15) | (vtuOp << 12) | ((entry->DBNum & 0x30) << 4) | (entry->DBNum & 0x0F);
        }
        else
        {
            if(entry->DBNum >= 16)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return GT_BAD_PARAM;
            }    
            data = (1 << 15) | (vtuOp << 12) | entry->DBNum;
        }
    }

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

    /* only two operations need to go through the mess below to get some data 
     * after the operations -  service violation and get next entry
     */

    /* If the operation is to service violation operation wait for the response   */
    if(vtuOp == SERVICE_VIOLATIONS)
    {
#ifdef GT_RMGMT_ACCESS
        {
          HW_DEV_REG_ACCESS regAccess;

          regAccess.entries = 1;
  
          regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0;
          regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS);
          regAccess.rw_reg_list[0].reg = QD_REG_VTU_OPERATION;
          regAccess.rw_reg_list[0].data = 15;
          retVal = hwAccessMultiRegs(dev, &regAccess);
          if(retVal != GT_OK)
          {
            gtSemGive(dev,dev->vtuRegsSem);
            return retVal;
          }
        }
#else
        /* 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;
            }
        }
#endif

        /* get the Source Port ID that was involved in the violation */
        retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,0,4,&data);
        if(retVal != GT_OK)
        {
            gtSemGive(dev,dev->vtuRegsSem);
            return retVal;
        }

        entry->DBNum = (GT_U8)(data & 0xF);

        /* get the VID that was involved in the violation */

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

        /* Get the vid - bits 0-11 */
        entry->vid   = data & 0xFFF;


    } /* end of service violations */

    /* If the operation is a get next operation wait for the response   */
    if(vtuOp == GET_NEXT_ENTRY)
    {
        entry->vidExInfo.useVIDFPri = GT_FALSE;
        entry->vidExInfo.vidFPri = 0;

        entry->vidExInfo.useVIDQPri = GT_FALSE;
        entry->vidExInfo.vidQPri = 0;

        entry->vidExInfo.vidNRateLimit = GT_FALSE;

        entry->sid = 0;
           entry->vidPolicy = GT_FALSE;

        /* Wait until the VTU in ready. */
#ifdef GT_RMGMT_ACCESS
        {
          HW_DEV_REG_ACCESS regAccess;

          regAccess.entries = 1;
  
          regAccess.rw_reg_list[0].cmd = HW_REG_WAIT_TILL_0;
          regAccess.rw_reg_list[0].addr = CALC_SMI_DEV_ADDR(dev, 0, GLOBAL_REG_ACCESS);
          regAccess.rw_reg_list[0].reg = QD_REG_VTU_OPERATION;
          regAccess.rw_reg_list[0].data = 15;
          retVal = hwAccessMultiRegs(dev, &regAccess);
          if(retVal != GT_OK)
          {
            gtSemGive(dev,dev->vtuRegsSem);
            return retVal;
          }
        }
#else
        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;
            }
        }
#endif

        /****************** get the vid *******************/

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

        /* the vid is bits 0-11 */
        entry->vid   = data & 0xFFF;

        /* the vid valid is bits 12 */
        *valid   = (data >> 12) & 1;
        
        if (*valid == 0)
        {
            gtSemGive(dev,dev->vtuRegsSem);
            return GT_OK;
        }

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

        /****************** get the DBNum *******************/
        if(IS_IN_DEV_GROUP(dev,DEV_FID_REG))
        {
            retVal = hwReadGlobalReg(dev,(GT_U8)(QD_REG_VTU_FID_REG),&data);
            if(retVal != GT_OK)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
            }        

            if(IS_IN_DEV_GROUP(dev,DEV_POLICY))
            {
                entry->vidPolicy = (data >> 12) & 0x1;
            }

            entry->DBNum = data & 0xFFF;

        }
        else
        {
            retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,0,4,&data);
            if(retVal != GT_OK)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
            }

            entry->DBNum = data & 0xF;
        
            if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_256))
            {
                retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,8,4,&data);
                if(retVal != GT_OK)
                {
                    gtSemGive(dev,dev->vtuRegsSem);
                    return retVal;
                }

                entry->DBNum |= ((data & 0xF) << 4);
            }
            else if (IS_IN_DEV_GROUP(dev,DEV_DBNUM_64))
            {
                retVal = hwGetGlobalRegField(dev,QD_REG_VTU_OPERATION,8,2,&data);
                if(retVal != GT_OK)
                {
                    gtSemGive(dev,dev->vtuRegsSem);
                    return retVal;
                }

                entry->DBNum |= ((data & 0x3) << 4);
            }
        }


        /****************** get the MemberTagP *******************/
        retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA1_REG,&data);
        if(retVal != GT_OK)
        {
            gtSemGive(dev,dev->vtuRegsSem);
            return retVal;
        }

        /* get data from data register for ports 0 to 2 */
        entry->vtuData.memberTagP[0]  =  data & 3 ;
        entry->vtuData.memberTagP[1]  = (data >> 4) & 3 ;
        entry->vtuData.memberTagP[2]  = (data >> 8) & 3 ;
        entry->vtuData.portStateP[0]  = (data >> 2) & 3 ;
        entry->vtuData.portStateP[1]  = (data >> 6) & 3 ;
        entry->vtuData.portStateP[2]  = (data >> 10) & 3 ;

        /****************** for the switch more than 3 ports *****************/

        if(dev->maxPorts > 3)
        {
            /* fullsail has 3 ports, clippership has 7 prots */
            entry->vtuData.memberTagP[3]  = (data >>12) & 3 ;
            entry->vtuData.portStateP[3]  = (data >>14) & 3 ;

            /* get data from data register for ports 4 to 6 */
            retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA2_REG,&data);
            if(retVal != GT_OK)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
            }
            entry->vtuData.memberTagP[4]  = data & 3 ;
            entry->vtuData.memberTagP[5]  = (data >> 4) & 3 ;
            entry->vtuData.portStateP[4]  = (data >> 2) & 3 ;
            entry->vtuData.portStateP[5]  = (data >> 6) & 3 ;

            if(dev->maxPorts > 6)
            {
                entry->vtuData.memberTagP[6]  = (data >> 8) & 3 ;
                entry->vtuData.portStateP[6]  = (data >> 10) & 3 ;
            }
            
            if (IS_IN_DEV_GROUP(dev,DEV_VTU_EXT_INFO))
            {
                entry->vidPriOverride = 0;
                entry->vidPriority = 0;

                entry->vidExInfo.useVIDFPri = (data & 0x8000)?GT_TRUE:GT_FALSE;
                entry->vidExInfo.vidFPri = (data >> 12) & 0x7;

                entry->vidExInfo.useVIDQPri = (data & 0x0800)?GT_TRUE:GT_FALSE;
                entry->vidExInfo.vidQPri = (data >> 9) & 0x3;

                entry->vidExInfo.vidNRateLimit = (data & 0x0100)?GT_TRUE:GT_FALSE;
            }
        }
        /****************** upto 7 port switch *******************/

        /****************** for the switch more than 7 ports *****************/

        if(dev->maxPorts > 7)
        {
            /* fullsail has 3 ports, clippership has 7 prots */
            entry->vtuData.memberTagP[7]  = (data >>12) & 3 ;
            entry->vtuData.portStateP[7]  = (data >>14) & 3 ;

            /* get data from data register for ports 4 to 6 */
            retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA3_REG,&data);
            if(retVal != GT_OK)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
            }
            entry->vtuData.memberTagP[8]  = data & 3 ;
            entry->vtuData.memberTagP[9]  = (data >> 4) & 3 ;
            entry->vtuData.portStateP[8]  = (data >> 2) & 3 ;
            entry->vtuData.portStateP[9]  = (data >> 6) & 3 ;

            if(dev->maxPorts > 10)
            {
                entry->vtuData.memberTagP[10]  = (data >> 8) & 3 ;
                entry->vtuData.portStateP[10]  = (data >> 10) & 3 ;
            }

            if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
            {
                if (data & 0x8000)
                {
                    entry->vidPriOverride = GT_TRUE;
                    entry->vidPriority = (data >> 12) & 0x7;
                }
                else
                {
                    entry->vidPriOverride = GT_FALSE;
                    entry->vidPriority = 0;
                }
            }

        }
        else if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
        {
            /* get data from data register for ports 4 to 6 */
            retVal = hwReadGlobalReg(dev,QD_REG_VTU_DATA3_REG,&data);
            if(retVal != GT_OK)
            {
                gtSemGive(dev,dev->vtuRegsSem);
                return retVal;
            }

            if (data & 0x8000)
            {
                entry->vidPriOverride = GT_TRUE;
                entry->vidPriority = (data >> 12) & 0x7;
            }
            else
            {
                entry->vidPriOverride = GT_FALSE;
                entry->vidPriority = 0;
            }
        }

        /****************** upto 11 ports switch *******************/

    } /* end of get next entry */

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