#include <Copyright.h>
/********************************************************************************
* qdInt.c
*
* DESCRIPTION:
*        This sample shows how to call QuarterDeck Interrupt handler when QD INT
*        raised, and how to take care each Interrupt Cause.
*
* DEPENDENCIES:   NONE.
*
* FILE REVISION NUMBER:
*
*******************************************************************************/

#include "msSample.h"


/*
 *    To enable quarterDeck interrupt, you need to call eventSetActive() and
 *    gprtPhyIntEnable(), as following sample routine.
 *    sampleQDIntEnable will enable all interrupt causes.
 *    For Port, GT_ATU_FULL, GT_ATU_DONE, GT_PHY_INTERRUPT, and GT_EE_INTERRUPT
 *    are enabled.
 *
 *    In this sample, GT_SPEED_CHANGED, GT_DUPLEX_CHANGED, and 
 *  GT_LINK_STATUS_CHANGED are enabled for ports 0 ~ 2.
*/
GT_STATUS sampleQDIntEnable(GT_QD_DEV *dev)
{
    GT_STATUS status;
    GT_LPORT port;
    GT_U16 data;

    /* 
     *    Enable QuarterDeck interrupt for ATUFull, ATUDone, PHYInt, and EEInt.
     *    If writing 0 into eventSetActive(), all port interrupt will be disabled.
    */
    data = GT_STATS_DONE|GT_VTU_PROB|GT_VTU_DONE|
           GT_ATU_FULL|GT_ATU_DONE|GT_EE_INTERRUPT;
/*           GT_ATU_FULL|GT_ATU_DONE|GT_PHY_INTERRUPT|GT_EE_INTERRUPT; */
    if((status = eventSetActive(dev,data)) != GT_OK)
    {
        MSG_PRINT(("eventSetActive returned fail.\n"));
        return status;
    }

    /* 
     *    Enable Phy interrupt for every possible interrupt cause.
     *    If writing 0 into gprtPhyIntEnable(), all port interrupt will be disabled.
    */
    data =     GT_SPEED_CHANGED|GT_DUPLEX_CHANGED|GT_LINK_STATUS_CHANGED;

    for(port=0; port<3; port++)
    {
        if((status = gprtPhyIntEnable(dev,port,data)) != GT_OK)
        {
            MSG_PRINT(("gprtPhyIntEnable returned fail.\n"));
            return status;
        }
    }

    return GT_OK;
}

/*
 *    Disable QuarterDeck Interrupt.
*/
GT_STATUS sampleQDIntDisable(GT_QD_DEV *dev)
{
    GT_STATUS status;
    GT_LPORT port;

    /* 
     *    Writing 0 into eventSetActive(), all port interrupt will be disabled.
    */
    if((status = eventSetActive(dev,0)) != GT_OK)
    {
        MSG_PRINT(("eventSetActive returned fail.\n"));
        return status;
    }

    /* 
     *    Writing 0 into gprtPhyIntEnable(), all port interrupt will be disabled.
    */
    for(port=0; port<3; port++)
    {
        if((status = gprtPhyIntEnable(dev,port,0)) != GT_OK)
        {
            MSG_PRINT(("gprtPhyIntEnable returned fail.\n"));
            return status;
        }
    }
    return GT_OK;
}


/*
 *    Assume that the following function, sampleQDIntVector(), is registered 
 *    when BSP calls intConnect for QD Interrupt.
 *    This sample will show how to deal with QuarterDeck Interrupt.
*/
GT_STATUS sampleQDIntVector(GT_QD_DEV *dev)
{
    GT_U16 intCause, phyIntCause;
    GT_U16 portVec;
    GT_LPORT port;
    GT_VTU_INT_STATUS vtuInt;
    GT_ATU_INT_STATUS atuInt;

    /*
     *    Disable QuarterDeck Interrupt in System Level.
     *    ToDo...
    */

    /*
     *    Check if QD generated the interrupt.
    */
    if(eventGetIntStatus(dev,&intCause) != GT_OK)
    {
        /* QD didn't generate the interrupt. */
        return GT_FAIL;
    }

    /*
     *    QD generated interrupt with the reason in intCause.
    */

    if(intCause & GT_STATS_DONE)
    {
        /* 
         *    Statistics Done Interrupt
         *    ToDo...
        */

    }
    if(intCause & GT_VTU_DONE)
    {
        /* 
         *    VTU Done Interrupt
         *    ToDo...
        */

    }

    if(intCause & GT_VTU_PROB)
    {
        /* 
         *    Vlan Table Problem/Violation.
         *    Need to read the cause.
        */
        do {
            if(gvtuGetIntStatus(dev,&vtuInt) != GT_OK)
            {
                /* failed to retrieve VTU Interrupt cause */
                break;
            }

            if(vtuInt.vtuIntCause & GT_VTU_FULL_VIOLATION)
            {
                /* 
                 *    Vlan Table is Full
                 *    ToDo...
                */
            }

            if(vtuInt.vtuIntCause & GT_MEMBER_VIOLATION)
            {
                /* 
                 *    Member Violation
                 *    ToDo...
                */
            }

            if(vtuInt.vtuIntCause & GT_MISS_VIOLATION)
            {
                /* 
                 *    Miss Violation
                 *    ToDo...
                */
            }
        } while(vtuInt.vtuIntCause != 0);
    }

    if(intCause & GT_ATU_PROB)
    {
        /* 
         *    ATU cannot load or learn a new mapping due to all the available
         *    locations for an address being locked.
         *    ToDo...
        */
        do {
            if(gatuGetIntStatus(dev,&atuInt) != GT_OK)
            {
                /* failed to retrieve VTU Interrupt cause */
                break;
            }

            if(atuInt.atuIntCause & GT_FULL_VIOLATION)
            {
                /* 
                 *    Table is Full
                 *    ToDo...
                */
            }

            if(atuInt.atuIntCause & GT_MEMBER_VIOLATION)
            {
                /* 
                 *    Member Violation
                 *    ToDo...
                */
            }

            if(atuInt.atuIntCause & GT_MISS_VIOLATION)
            {
                /* 
                 *    Miss Violation
                 *    ToDo...
                */
            }
        } while(atuInt.atuIntCause != 0);

    }

    if(intCause & GT_ATU_DONE)
    {
        /* 
         *    There is a transitions from a one to a zero on ATUBusy bit
         *    (Refer to ATU Operation Register.)
         *    ToDo...
        */

    }

    if(intCause & GT_PHY_INTERRUPT)
    {
        /* 
         *    At least one of the Phy generated interrupt.
         *    We need to read Phy Interrupt Summary and go through each phy
         *    based on the summary.
        */

        if(gprtGetPhyIntPortSummary(dev,&portVec) != GT_OK)
        {
            return GT_FAIL;
        }

        port = 0;
        while(portVec)
        {
            if(portVec & 0x01)
            {
                /*
                 *    Call gprtGetPhyIntStatus to get intCause
                */
                if(gprtGetPhyIntStatus(dev,port,&phyIntCause) != GT_OK)
                {
                    /* 
                     *    Something wrong with the system. Need to do the 
                     *    necessary work. 
                     *    ToDo...
                    */
                }

                if(phyIntCause & GT_SPEED_CHANGED)
                {
                    /* 
                     *    Speed has been changed.
                     *    ToDo...
                    */
                }

                if(phyIntCause & GT_DUPLEX_CHANGED)
                {
                    /* 
                     *    Duplex mode has been changed.
                     *    ToDo...
                    */
                }

                if(phyIntCause & GT_PAGE_RECEIVED)
                {
                    /* 
                     *    Page received.
                     *    ToDo...
                    */

                }

                if(phyIntCause & GT_AUTO_NEG_COMPLETED)
                {
                    /* 
                     *    AutoNegotiation completed.
                     *    ToDo...
                    */

                }

                if(phyIntCause & GT_LINK_STATUS_CHANGED)
                {
                    /* 
                     *    Link Status changed.
                     *    ToDo...
                    */

                }

                if(phyIntCause & GT_SYMBOL_ERROR)
                {
                    /* 
                     *    Symbol error
                     *    ToDo...
                    */

                }

                if(phyIntCause & GT_FALSE_CARRIER)
                {
                    /* 
                     *    False Carrier.
                     *    ToDo...
                    */

                }

                if(phyIntCause & GT_FIFO_FLOW)
                {
                    /* 
                     *    Fifo Overflow/underflow error
                     *    ToDo...
                    */

                }

                if(phyIntCause & GT_CROSSOVER_CHANGED)
                {
                    /* 
                     *    MDI/MDIX crossover changed.
                     *    ToDo...
                    */

                }

                if(phyIntCause & GT_POLARITY_CHANGED)
                {
                    /* 
                     *    Polarity changed.
                     *    ToDo...
                    */

                }

                if(phyIntCause & GT_JABBER)
                {
                    /* 
                     *    Jabber
                     *    ToDo...
                    */

                }
            }

            portVec >>= 1;
            port++;
        }
    }

    if(intCause & GT_EE_INTERRUPT)
    {
        /* 
         *    EEPROM is done loading registers.
         *    ToDo...
        */

    }


    /*
     *    Now, all the QuarterDeck related interrupt have been cleared,
     *    so it's OK to enable QuarterDeck Interrupt in System Level.
     *    ToDo...
    */
    
    return GT_OK;

}
