#include <Copyright.h>

/********************************************************************************
* gtWeight.c
*
* DESCRIPTION:
*       API definitions for Round Robin Weight table access
*
* DEPENDENCIES:
*
* FILE REVISION NUMBER:
*       $Revision: $
*******************************************************************************/

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


/*******************************************************************************
* gsysSetQoSWeight
*
* DESCRIPTION:
*       Programmable Round Robin Weights.
*		Each port has 4 output Queues. Queue 3 has the highest priority and 
*		Queue 0 has the lowest priority. When a scheduling mode of port is 
*		configured as Weighted Round Robin queuing mode, the access sequece of the 
*		Queue is 3,2,3,1,3,2,3,0,3,2,3,1,3,2,3 by default.
*		This sequence can be configured with this API.
*
* INPUTS:
*       weight - access sequence of the queue
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK      - on success
*       GT_FAIL    - on error
*		GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*       None
*
*******************************************************************************/
GT_STATUS gsysSetQoSWeight
(
    IN  GT_QD_DEV 		*dev,
    IN  GT_QoS_WEIGHT	*weight
)
{
    GT_STATUS	retVal;         /* Functions return value.      */
	GT_U16		data;
	GT_U32		len, i;

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

	/* Check if Switch supports this feature. */
	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
		return GT_NOT_SUPPORTED;
    }

	if (weight->len > 128)
	{
        DBG_INFO(("GT_BAD_PARAM\n"));
		return GT_BAD_PARAM;
	}

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

	len = weight->len/4;

	/* program QoS Weight Table, 4 sequences at a time */

	for(i=0; i<len; i++)
	{
	    /* Wait until the QoS Weight Table is ready. */
    	data = 1;
	    while(data == 1)
    	{
	        retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data);
    	    if(retVal != GT_OK)
        	{
				gtSemGive(dev,dev->tblRegsSem);
    	        return retVal;
        	}
	    }

		data =  (GT_U16)((1 << 15) | (i << 8) | 
				(weight->queue[i*4] & 0x3) |
				((weight->queue[i*4+1] & 0x3) << 2) |
				((weight->queue[i*4+2] & 0x3) << 4) |
				((weight->queue[i*4+3] & 0x3) << 6));

		retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
	    if(retVal != GT_OK)
    	{
	   	    DBG_INFO(("Failed.\n"));
            gtSemGive(dev,dev->tblRegsSem);
    	    return retVal;
	    }
	}

	/* program remaining sequences if any */
	i = weight->len % 4;
	if (i)
	{
	    /* Wait until the QoS Weight Table is ready. */
    	data = 1;
	    while(data == 1)
    	{
	        retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data);
    	    if(retVal != GT_OK)
        	{
	            gtSemGive(dev,dev->tblRegsSem);
    	        return retVal;
        	}
	    }
		
		data =  (GT_U16)((1 << 15) | (len << 8));
		
		switch (i)
		{
			case 3:
				data |= ((weight->queue[len*4+2] & 0x3) << 4);
			case 2:
				data |= ((weight->queue[len*4+1] & 0x3) << 2);
			case 1:
				data |= ((weight->queue[len*4+0] & 0x3) << 0);
				break;
			default:
		   	    DBG_INFO(("Should not come to this point.\n"));
	            gtSemGive(dev,dev->tblRegsSem);
				return GT_FALSE;
		}

		retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
	    if(retVal != GT_OK)
    	{
	   	    DBG_INFO(("Failed.\n"));
            gtSemGive(dev,dev->tblRegsSem);
    	    return retVal;
	    }
	}

	/* Write the lengh of the sequence */

    /* Wait until the QoS Weight Table is ready. */
   	data = 1;
    while(data == 1)
   	{
        retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data);
   	    if(retVal != GT_OK)
       	{
            gtSemGive(dev,dev->tblRegsSem);
   	        return retVal;
       	}
    }

	data =  (GT_U16)((1 << 15) | (0x20 << 8) | weight->len);
		
	retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);

	gtSemGive(dev,dev->tblRegsSem);

    if(retVal != GT_OK)
   	{
   	    DBG_INFO(("Failed.\n"));
   	    return retVal;
    }

	return GT_OK;
}


/*******************************************************************************
* gsysGetQoSWeight
*
* DESCRIPTION:
*       Programmable Round Robin Weights.
*		Each port has 4 output Queues. Queue 3 has the highest priority and 
*		Queue 0 has the lowest priority. When a scheduling mode of port is 
*		configured as Weighted Round Robin queuing mode, the access sequece of the 
*		Queue is 3,2,3,1,3,2,3,0,3,2,3,1,3,2,3 by default.
*		This routine retrieves the access sequence of the Queue.
*
* INPUTS:
*       None.
*
* OUTPUTS:
*       weight - access sequence of the queue
*
* RETURNS:
*       GT_OK      - on success
*       GT_FAIL    - on error
*		GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*       None
*
*******************************************************************************/
GT_STATUS gsysGetQoSWeight
(
    IN  GT_QD_DEV 		*dev,
    OUT GT_QoS_WEIGHT	*weight
)
{
    GT_STATUS	retVal;         /* Functions return value.      */
	GT_U16		data, i;
	GT_U32		len;

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

	/* Check if Switch supports this feature. */
	if (!IS_IN_DEV_GROUP(dev,DEV_QoS_WEIGHT))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
		return GT_NOT_SUPPORTED;
    }

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

	/* Read the lengh of the sequence */

    /* Wait until the QoS Weight Table is ready. */
   	data = 1;
    while(data == 1)
   	{
        retVal = hwGetGlobal2RegField(dev,QD_REG_QOS_WEIGHT,15,1,&data);
   	    if(retVal != GT_OK)
       	{
			gtSemGive(dev,dev->tblRegsSem);
   	        return retVal;
       	}
    }

	data = (0x20 << 8);
		
	retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
    if(retVal != GT_OK)
   	{
   	    DBG_INFO(("Failed.\n"));
		gtSemGive(dev,dev->tblRegsSem);
   	    return retVal;
    }

	retVal = hwReadGlobal2Reg(dev, QD_REG_QOS_WEIGHT, &data);
    if(retVal != GT_OK)
   	{
   	    DBG_INFO(("Failed.\n"));
		gtSemGive(dev,dev->tblRegsSem);
   	    return retVal;
    }

	weight->len = data & 0xFF;

	len = weight->len/4;

	/* read QoS Weight Table, 4 sequences at a time */

	for(i=0; i<len; i++)
	{
		data = i << 8;

		retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
	    if(retVal != GT_OK)
    	{
	   	    DBG_INFO(("Failed.\n"));
			gtSemGive(dev,dev->tblRegsSem);
    	    return retVal;
	    }

		retVal = hwReadGlobal2Reg(dev, QD_REG_QOS_WEIGHT, &data);
    	if(retVal != GT_OK)
	   	{
   		    DBG_INFO(("Failed.\n"));
			gtSemGive(dev,dev->tblRegsSem);
   	    	return retVal;
	    }

		weight->queue[i*4] = data & 0x3;
		weight->queue[i*4+1] = (data >> 2) & 0x3;
		weight->queue[i*4+2] = (data >> 4) & 0x3;
		weight->queue[i*4+3] = (data >> 6) & 0x3;

	}

	/* read remaining sequences if any */
	i = (GT_U16) (weight->len % 4);
	if (i)
	{
		data = (GT_U16)(len << 8);
		
		retVal = hwWriteGlobal2Reg(dev, QD_REG_QOS_WEIGHT, data);
	    if(retVal != GT_OK)
    	{
	   	    DBG_INFO(("Failed.\n"));
			gtSemGive(dev,dev->tblRegsSem);
    	    return retVal;
	    }

		retVal = hwReadGlobal2Reg(dev, QD_REG_QOS_WEIGHT, &data);
    	if(retVal != GT_OK)
	   	{
   		    DBG_INFO(("Failed.\n"));
			gtSemGive(dev,dev->tblRegsSem);
   	    	return retVal;
	    }

		switch (i)
		{
			case 3:
				weight->queue[len*4+2] = (data >> 4) & 0x3;
			case 2:
				weight->queue[len*4+1] = (data >> 2) & 0x3;
			case 1:
				weight->queue[len*4] = data & 0x3;
				break;
			default:
		   	    DBG_INFO(("Should not come to this point.\n"));
				gtSemGive(dev,dev->tblRegsSem);
				return GT_FALSE;
		}
	}

	gtSemGive(dev,dev->tblRegsSem);

	return GT_OK;
}

