T168_111\core\N32903文件:第20~32个文件

RTC.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright (c) Nuvoton Technology Corp. All rights reserved.                                             */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------------------------------------*/
/* Includes of system headers                                                                              */
/*---------------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wbio.h"
#include "wblib.h"
#include "Common.h"
#include "RTC.h"


/*---------------------------------------------------------------------------------------------------------*/
/* Macro, type and constant definitions                                                                    */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_GLOBALS

//#define RTC_DEBUG
#ifdef RTC_DEBUG
#define RTCDEBUG     DrvSIO_printf
#else
#define RTCDEBUG(...)
#endif

/*---------------------------------------------------------------------------------------------------------*/
/* Global file scope (static) variables                                                                    */
/*---------------------------------------------------------------------------------------------------------*/
static PFN_RTC_CALLBACK  *g_pfnRTCCallBack_Tick    = NULL, *g_pfnRTCCallBack_Alarm   = NULL, *g_pfnRTCCallBack_PSWI   = NULL;
                   
static UINT32 volatile g_u32RTC_Count  = 0;
static CHAR g_chHourMode = 0;
static BOOL volatile g_bIsEnableTickInt  = FALSE;
static BOOL volatile g_bIsEnableAlarmInt = FALSE;

static UINT32 volatile g_u32Reg, g_u32Reg1,g_u32hiYear,g_u32loYear,g_u32hiMonth,g_u32loMonth,g_u32hiDay,g_u32loDay;
static UINT32 volatile g_u32hiHour,g_u32loHour,g_u32hiMin,g_u32loMin,g_u32hiSec,g_u32loSec;

/*---------------------------------------------------------------------------------------------------------*/
/* Functions                                                                                               */
/*---------------------------------------------------------------------------------------------------------*/


/*---------------------------------------------------------------------------------------------------------*/
/* Function:     <RTC_ISR>                                                                                 */
/*                                                                                                         */
/* Parameter:                                                                                              */
/*               VOID                                                                                      */
/* Returns:                                                                                                */
/*               None                                                                                      */
/* Side effects:                                                                                           */
/*                                                                                                         */
/* Description:                                                                                            */
/*               Install ISR to handle interrupt event                                                     */
/*---------------------------------------------------------------------------------------------------------*/

static VOID RTC_ISR (VOID)
{ 
    UINT32 volatile u32RegRIIR;

    u32RegRIIR = inp32(RIIR);
    if (u32RegRIIR & RTC_TICK_INT)                                       /* tick interrupt occurred */
    {
          outp32(RIIR, RTC_TICK_INT);
          g_u32RTC_Count++;                                              /* maintain RTC tick count */

          if (g_pfnRTCCallBack_Tick != NULL)                             /* execute tick callback function */
          {
              g_pfnRTCCallBack_Tick();
          }

    }

    if (u32RegRIIR & RTC_ALARM_INT)                                     /* alarm interrupt occurred */
    {    
          outp32(RIIR, RTC_ALARM_INT);

          RTC_Ioctl(0,RTC_IOC_DISABLE_INT,RTC_ALARM_INT,0);
           
          if (g_pfnRTCCallBack_Alarm != NULL)                            /* execute alarm callback function */
          {
              g_pfnRTCCallBack_Alarm();
          }
   }
    if (u32RegRIIR & RTC_PSWI_INT)                                     /* alarm interrupt occurred */
    {    
          outp32(RIIR, RTC_PSWI_INT);

         // RTC_Ioctl(0,RTC_IOC_DISABLE_INT,RTC_PSWI_INT,0);
           
          if (g_pfnRTCCallBack_PSWI != NULL)                            /* execute alarm callback function */
          {
              g_pfnRTCCallBack_PSWI();
          }
   }   
}

/*---------------------------------------------------------------------------------------------------------*/
/* Function:     RTC_SetFrequencyCompensation                                                                */
/*                                                                                                         */
/* Parameter:                                                                                              */
/*               float number                                                                              */
/* Returns:                                                                                                */
/*               E_SUCCESS                    Success.                                                       */
/*               E_RTC_ERR_FCR_VALUE        Wrong Compenation VALUE                                        */
/* Side effects:                                                                                           */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*                                                                                                         */
/*               Set Frequecy Compenation Data                                                             */
/*---------------------------------------------------------------------------------------------------------*/
UINT32 RTC_SetFrequencyCompensation(FLOAT fnumber)
{
    INT32 i32intergerPart  ;
    INT32 i32fractionPart ;
    INT32 i32RegInt,i32RegFra ;
       UINT32 u32Reg;

    i32intergerPart = (INT32) (fnumber) ;
    i32fractionPart = ((INT32) ( ((fnumber - i32intergerPart) *100)) / 100);
    i32RegInt = i32intergerPart - RTC_FCR_REFERENCE ;
    i32RegFra = ((i32fractionPart) * 60);
    /*-----------------------------------------------------------------------------------------------------*/
    /* Judge Interger part is reasonable                                                                   */
    /*-----------------------------------------------------------------------------------------------------*/

    if ( (i32RegInt < 0) | (i32RegInt > 15) )
    {
        return E_RTC_ERR_FCR_VALUE ;
    }

    u32Reg = RTC_WriteEnable();
    if (u32Reg != 0)
    {
        return E_RTC_ERR_EIO ;
    }
    outp32(RTC_FCR, (UINT32)(g_u32Reg >>8 | i32RegFra));

    return E_RTC_SUCCESS;
}

/*---------------------------------------------------------------------------------------------------------*/
/* Function:     RTC_WriteEnable                                                                           */
/*                                                                                                         */
/* Parameter:                                                                                              */
/*               VOID                                                                                      */
/* Returns:                                                                                                */
/*               E_SUCCESS                    Success.                                                       */
/*               E_RTC_ERR_FAILED           FAILED                                                         */
/* Side effects:                                                                                           */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*                                                                                                         */
/*               Access PW to AER to make access other register enable                                     */
/*---------------------------------------------------------------------------------------------------------*/
UINT32 RTC_WriteEnable (VOID)
{
    INT32 i32i;
    
      outp32(INIR, RTC_INIT_KEY);
    outp32(AER, RTC_WRITE_KEY);


    for (i32i = 0 ; i32i < RTC_WAIT_COUNT ; i32i++)
    {
        /*-------------------------------------------------------------------------------------------------*/
        /* check RTC_AER[16] to find out RTC write enable                                                  */
        /*-------------------------------------------------------------------------------------------------*/
        if ( inp32(AER) & 0x10000 )
        {
            break;
        }
    }

    if (i32i == RTC_WAIT_COUNT)
    {
        RTCDEBUG ("\nRTC: RTC_WriteEnable, set write enable FAILED!\n");
        return E_RTC_ERR_EIO;
    }

    return E_RTC_SUCCESS;
}


/*---------------------------------------------------------------------------------------------------------*/
/* Function:     RTC_Init                                                                                   */
/*                                                                                                         */
/* Parameter:                                                                                              */
/*               VOID                                                                                      */
/* Returns:                                                                                                */
/*               E_SUCCESS                Success.                                                           */
/*               E_RTC_ERR_EIO            Initial RTC FAILED.                                                   */
/* Side effects:                                                                                           */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*                                                                                                         */
/*               Initial RTC and install ISR                                                               */
/*---------------------------------------------------------------------------------------------------------*/


UINT32 RTC_Init (VOID)
{
    INT32 i32i;

    /*-----------------------------------------------------------------------------------------------------*/
    /* Initial time data struct and some parameters.                                                       */
    /*-----------------------------------------------------------------------------------------------------*/
    g_pfnRTCCallBack_Alarm = NULL;
    g_pfnRTCCallBack_Tick = NULL;
      g_pfnRTCCallBack_PSWI = NULL;
    g_u32RTC_Count = 0;
    /*-----------------------------------------------------------------------------------------------------*/
    /* When RTC is power on, write 0xa5eb1357 to RTC_INIR to reset all logic.                              */
    /*-----------------------------------------------------------------------------------------------------*/
    outp32(INIR, RTC_INIT_KEY);

    for (i32i = 0 ; i32i < RTC_WAIT_COUNT ; i32i++)
    {
        if ( inp32(INIR) & 0x01 )
        {            /* Check RTC_INIR[0] to find out RTC reset signal */
            break;

        }
    }
        
    if (i32i == RTC_WAIT_COUNT)
    {
        RTCDEBUG("\nRTC: RTC_Init, initial RTC FAILED!\n");
        return E_RTC_ERR_EIO;
    }

    /*-----------------------------------------------------------------------------------------------------*/
    /* Install RTC ISR                                                                                     */
    /*-----------------------------------------------------------------------------------------------------*/
     outp32( RIIR, RTC_ALL_INT );
     
    sysInstallISR(IRQ_LEVEL_1, IRQ_RTC, (PVOID)RTC_ISR);    
    sysSetLocalInterrupt(ENABLE_IRQ);
    sysEnableInterrupt(IRQ_RTC);        
    
    return E_RTC_SUCCESS;
}


/*---------------------------------------------------------------------------------------------------------*/
/* Function:     RTC_Open                                                                                  */
/*                                                                                                         */
/* Parameter:    RTC_TIME_DATA_T *sPt            Just Set Current_Timer                                      */
/*                                                                                                         */
/* Returns:                                                                                                */
/*               E_SUCCESS                Success.                                                           */
/*               E_RTC_ERR_EIO        Initial RTC FAILED.                                                    */
/* Side effects:                                                                                           */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*               Just Set Current_Timer .                                                                  */
//*--------------------------------------------------------------------------------------------------------*/

UINT32 RTC_Open (RTC_TIME_DATA_T *sPt)
{
    UINT32 u32Reg;
    
    /*-----------------------------------------------------------------------------------------------------*/
    /* DO BASIC JUDGEMENT TO Check RTC time data value is reasonable or not.                               */
    /*-----------------------------------------------------------------------------------------------------*/
    if ( ((sPt->u32Year - RTC_YEAR2000) > 99)|
         ((sPt->u32cMonth == 0) || (sPt->u32cMonth > 12))|
         ((sPt->u32cDay   == 0) || (sPt->u32cDay   > 31)))
    {
        return E_RTC_ERR_CALENDAR_VALUE;
    }

    if (sPt->u8cClockDisplay == RTC_CLOCK_12)
    {
        if ( (sPt->u32cHour == 0) || (sPt->u32cHour > 12) )
        {
            return E_RTC_ERR_TIMESACLE_VALUE ;
        }
    }
    else if (sPt->u8cClockDisplay == RTC_CLOCK_24)
    {
        if (sPt->u32cHour > 23)
        {
            return E_RTC_ERR_TIMESACLE_VALUE ;
        }
    }
    else
    {
        return E_RTC_ERR_TIMESACLE_VALUE ;
    }

    if ((sPt->u32cMinute > 59) |
        (sPt->u32cSecond > 59) |
        (sPt->u32cSecond > 59))
    {
        return E_RTC_ERR_TIME_VALUE ;
    }
    if (sPt->u32cDayOfWeek > 6)
    {
        return E_RTC_ERR_DWR_VALUE ;
    }

    /*-----------------------------------------------------------------------------------------------------*/
    /* Important, call RTC_WriteEnable() before write data into any register.                              */
    /*-----------------------------------------------------------------------------------------------------*/
    g_u32Reg = RTC_WriteEnable();
    if (g_u32Reg != 0)
    {
        return E_RTC_ERR_EIO;
    }

    /*-----------------------------------------------------------------------------------------------------*/
    /* Second, set RTC time data.                                                                          */
    /*-----------------------------------------------------------------------------------------------------*/
    if (sPt->u8cClockDisplay == RTC_CLOCK_12)
    {
        g_chHourMode = RTC_CLOCK_12;
        RTC_WriteEnable();
        outp32(TSSR, RTC_CLOCK_12);

        /*-------------------------------------------------------------------------------------------------*/
        /* important, range of 12-hour PM mode is 21 upto 32                                               */
        /*-------------------------------------------------------------------------------------------------*/
        if (sPt->u8cAmPm == RTC_PM)
            sPt->u32cHour += 20;
    }
    else                                                                               /* RTC_CLOCK_24 */
    {
        g_chHourMode = RTC_CLOCK_24;
        RTC_WriteEnable();
        outp32(TSSR, RTC_CLOCK_24);
        RTCDEBUG ("RTC: 24-hour\n");
    }

    outp32(DWR, (UINT32)sPt->u32cDayOfWeek);
    g_u32hiYear  = (sPt->u32Year - RTC_YEAR2000) / 10;
    g_u32loYear  = (sPt->u32Year - RTC_YEAR2000) % 10;
    g_u32hiMonth =  sPt->u32cMonth              / 10;
    g_u32loMonth =  sPt->u32cMonth              % 10;
    g_u32hiDay   =  sPt->u32cDay                / 10;
    g_u32loDay   =  sPt->u32cDay                % 10;
    u32Reg    = (g_u32hiYear << 20);
    u32Reg    |= (g_u32loYear << 16);
    u32Reg    |= (g_u32hiMonth << 12);
    u32Reg    |= (g_u32loMonth << 8);
    u32Reg    |= (g_u32hiDay << 4);
    u32Reg    |= g_u32loDay;
    g_u32Reg = u32Reg;
    outp32 (CLR, (UINT32)g_u32Reg);

    g_u32hiHour  = sPt->u32cHour / 10;
    g_u32loHour  = sPt->u32cHour % 10;
    g_u32hiMin   = sPt->u32cMinute / 10;
    g_u32loMin   = sPt->u32cMinute % 10;
    g_u32hiSec   = sPt->u32cSecond / 10;
    g_u32loSec   = sPt->u32cSecond % 10;
    u32Reg     = (g_u32hiHour << 20);
    u32Reg    |= (g_u32loHour << 16);
    u32Reg    |= (g_u32hiMin << 12);
    u32Reg    |= (g_u32loMin << 8);
    u32Reg    |= (g_u32hiSec << 4);
    u32Reg    |= g_u32loSec;
    g_u32Reg = u32Reg;
    outp32(TLR, (UINT32)g_u32Reg);
    
    RTC_WriteEnable();
   // u32Reg = inp32(TLR);
    while( inp32(TLR) != (UINT32)g_u32Reg);
    

    return E_RTC_SUCCESS;

}


/*---------------------------------------------------------------------------------------------------------*/
/* Function:     RTC_Read                                                                                     */
/*                                                                                                         */
/* Parameter:                                                                                              */
/*               eTime                            Currnet_Timer/ Alarm_Time                                  */
/*               RTC_TIME_DATA_T *spt           Time Data                                                  */
/* Returns:                                                                                                */
/*               E_SUCCESS               Success.                                                          */
/*               E_RTC_ERR_EIO             Initial RTC FAILED.                                                  */
/* Side effects:                                                                                           */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*               Read current date/time or alarm date/time from RTC                                        */
//*--------------------------------------------------------------------------------------------------------*/

UINT32 RTC_Read (E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt)
{
    UINT32 u32Tmp;

    g_u32Reg = RTC_WriteEnable();
    if (g_u32Reg != 0)
    {
        return E_RTC_ERR_EIO;
    }    
    
    sPt->u8cClockDisplay = inp32(TSSR);                               /* 12/24-hour */
    sPt->u32cDayOfWeek = inp32(DWR);                                   /* Day of week */

    switch (eTime)
    {
        case RTC_CURRENT_TIME:
        {
            g_u32Reg   = inp32(CLR);
            g_u32Reg1  = inp32(TLR);
            break;
        }
        case RTC_ALARM_TIME:
        {
            g_u32Reg   = inp32(CAR);
            g_u32Reg1  = inp32(TAR);
            break;
        }
        default:
        {
            return E_RTC_ERR_ENOTTY;
        }
    }


    g_u32hiYear  = (g_u32Reg & 0xF00000) >> 20;
    g_u32loYear  = (g_u32Reg & 0xF0000) >> 16;
    g_u32hiMonth = (g_u32Reg & 0x1000) >> 12;
    g_u32loMonth = (g_u32Reg & 0xF00) >> 8;
    g_u32hiDay   = (g_u32Reg & 0x30) >> 4;
    g_u32loDay   =  g_u32Reg & 0xF;

    u32Tmp = (g_u32hiYear * 10);
    u32Tmp+= g_u32loYear;
    sPt->u32Year   =   u32Tmp  + RTC_YEAR2000;
    
    u32Tmp = (g_u32hiMonth * 10);
    sPt->u32cMonth = u32Tmp + g_u32loMonth;
    
    u32Tmp = (g_u32hiDay * 10);
    sPt->u32cDay   =  u32Tmp  + g_u32loDay;


    g_u32hiHour = (g_u32Reg1 & 0x300000) >> 20;
    g_u32loHour = (g_u32Reg1 & 0xF0000) >> 16;
    g_u32hiMin  = (g_u32Reg1 & 0x7000) >> 12;
    g_u32loMin  = (g_u32Reg1 & 0xF00) >> 8;
    g_u32hiSec  = (g_u32Reg1 & 0x70) >> 4;
    g_u32loSec  =  g_u32Reg1 & 0xF;


    if (sPt->u8cClockDisplay == RTC_CLOCK_12)
    {
    
        u32Tmp = (g_u32hiHour * 10);
        u32Tmp+= g_u32loHour;
        sPt->u32cHour = u32Tmp;                                /* AM: 1~12. PM: 21~32. */
        switch (eTime)
        {
            case RTC_CURRENT_TIME:
            {
                if (sPt->u32cHour >= 21)
                {
                    sPt->u8cAmPm = RTC_PM;
                    sPt->u32cHour -= 20;
                }
                else
                {
                    sPt->u8cAmPm = RTC_AM;
                }
                break;
            }
            case RTC_ALARM_TIME:
            {            
                if (sPt->u32cHour < 12)
                {
                    if(sPt->u32cHour == 0)
                        sPt->u32cHour = 12;
                    sPt->u8cAmPm = RTC_AM;
                }
                else
                {
                    sPt->u32cHour -= 12;
                    if(sPt->u32cHour == 0)
                        sPt->u32cHour = 12;                    
                    sPt->u8cAmPm = RTC_PM;
                }                 
                break;
            }
            default:
            {
                return E_RTC_ERR_ENOTTY;
            }            
        }
        u32Tmp = (g_u32hiMin  * 10);
        u32Tmp+= g_u32loMin;
        sPt->u32cMinute = u32Tmp;
        
        u32Tmp = (g_u32hiSec  * 10);
        u32Tmp+= g_u32loSec;
        sPt->u32cSecond = u32Tmp;

    }
    else
    {   /* RTC_CLOCK_24 */
        u32Tmp = (g_u32hiHour * 10);
        u32Tmp+= g_u32loHour;
        sPt->u32cHour   = u32Tmp;
        
        u32Tmp = (g_u32hiMin  * 10);
        u32Tmp+= g_u32loMin;
        sPt->u32cMinute = u32Tmp;
        
        u32Tmp = (g_u32hiSec  * 10);
        u32Tmp+= g_u32loSec;
        sPt->u32cSecond = u32Tmp;
    }


    return E_RTC_SUCCESS;

}

/*---------------------------------------------------------------------------------------------------------*/
/* Function:     RTC_Write                                                                                    */
/*                                                                                                         */
/* Parameter:                                                                                              */
/*               eTime                            Currnet_Timer/ Alarm_Time                                  */
/*               RTC_TIME_DATA_T *sPt             Time Data                                                  */
/* Returns:                                                                                                */
/*               E_SUCCESS               Success.                                                          */
/*               E_RTC_ERR_EIO           Initial RTC FAILED.                                               */
/* Side effects:                                                                                           */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*               Read current date/time or alarm date/time from RTC                                        */
//*--------------------------------------------------------------------------------------------------------*/
UINT32 RTC_Write(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt)
{
    UINT32 u32Reg;
    
    /*-----------------------------------------------------------------------------------------------------*/
    /* Check RTC time data value is reasonable or not.                                                     */
    /*-----------------------------------------------------------------------------------------------------*/
    if ( ((sPt->u32Year - RTC_YEAR2000) > 99)|
         ((sPt->u32cMonth == 0) || (sPt->u32cMonth > 12))|
         ((sPt->u32cDay   == 0) || (sPt->u32cDay   > 31)))
    {
        RTCDEBUG ("\nRTC: Year value is incorrect\n");
        return E_RTC_ERR_CALENDAR_VALUE;
    }

    if ( (sPt->u32Year - RTC_YEAR2000) > 99 )
    {
        RTCDEBUG ("\nRTC: Year value is incorrect\n");
        return E_RTC_ERR_CALENDAR_VALUE;
    }

    if ( (sPt->u32cMonth == 0) || (sPt->u32cMonth > 12) )
    {
        RTCDEBUG ("\nRTC: Month value is incorrect\n");
        return E_RTC_ERR_CALENDAR_VALUE;
    }

    if ( (sPt->u32cDay == 0) || (sPt->u32cDay > 31) )
    {
        RTCDEBUG ("\nRTC: Day value is incorrect\n");
        return E_RTC_ERR_CALENDAR_VALUE;
    }

    if (sPt->u8cClockDisplay == RTC_CLOCK_12)
    {
        if ( (sPt->u32cHour == 0) || (sPt->u32cHour > 12) )
        {
            RTCDEBUG ("\nRTC: Hour value is incorrect\n");
            return E_RTC_ERR_TIME_VALUE;
        }
    }
    else if (sPt->u8cClockDisplay == RTC_CLOCK_24)
    {
        if (sPt->u32cHour > 23)
        {
            RTCDEBUG ("\nRTC: Hour value is incorrect\n");
            return E_RTC_ERR_TIME_VALUE;
        }
    }
    else
    {
        RTCDEBUG ("\nRTC: Clock mode is incorrect\n");
        return E_RTC_ERR_TIME_VALUE;
    }

    if (sPt->u32cMinute > 59)
    {
        RTCDEBUG ("\nRTC: Minute value is incorrect\n");
        return E_RTC_ERR_TIME_VALUE;
    }

    if (sPt->u32cSecond > 59)
    {
        RTCDEBUG ("\nRTC: Second value is incorrect\n");
        return E_RTC_ERR_TIME_VALUE;
    }

    if (sPt->u32cDayOfWeek > 6)
    {
        RTCDEBUG ("\nRTC: Day of week value is incorrect\n");
        return E_RTC_ERR_DWR_VALUE;
    }


    /*-----------------------------------------------------------------------------------------------------*/
    /* Important, call RTC_Open() before write data into any register.                                     */
    /*-----------------------------------------------------------------------------------------------------*/
    g_u32Reg = RTC_WriteEnable();
    if (g_u32Reg != 0)
    {
        return E_RTC_ERR_EIO;
    }

    switch (eTime)
    {

        case RTC_CURRENT_TIME:
            /*---------------------------------------------------------------------------------------------*/
            /* Second, set RTC time data.                                                                  */
            /*---------------------------------------------------------------------------------------------*/

            if (sPt->u8cClockDisplay == RTC_CLOCK_12)
            {
                g_chHourMode = RTC_CLOCK_12;
                outp32(TSSR, RTC_CLOCK_12);
                RTCDEBUG ("RTC: 12-hour\n");
                /*-----------------------------------------------------------------------------------------*/
                /* important, range of 12-hour PM mode is 21 upto 32                                       */
                /*-----------------------------------------------------------------------------------------*/
                if (sPt->u8cAmPm == RTC_PM)
                    sPt->u32cHour += 20;
            }
            else                                                                  /* RTC_CLOCK_24 */
            {
                g_chHourMode = RTC_CLOCK_24;
                outp32(TSSR, RTC_CLOCK_24);
                RTCDEBUG ("RTC: 24-hour\n");
            }

            outp32(DWR,(UINT32) sPt->u32cDayOfWeek);

            g_u32hiYear  = (sPt->u32Year - RTC_YEAR2000) / 10;
            g_u32loYear  = (sPt->u32Year - RTC_YEAR2000) % 10;
            g_u32hiMonth = sPt->u32cMonth / 10;
            g_u32loMonth = sPt->u32cMonth % 10;
            g_u32hiDay   = sPt->u32cDay / 10;
            g_u32loDay   = sPt->u32cDay % 10;
            
            u32Reg = (g_u32hiYear << 20);
            u32Reg|= (g_u32loYear << 16);
            u32Reg|= (g_u32hiMonth << 12);
            u32Reg|= (g_u32loMonth << 8);
            u32Reg|= (g_u32hiDay << 4);
            u32Reg|= g_u32loDay;
            g_u32Reg = u32Reg;
            RTCDEBUG ("RTC: REG_RTC_CLR[0x%08x]\n", inp32(CLR));
            RTC_WriteEnable();
            outp32 (CLR, (UINT32)g_u32Reg);

            g_u32hiHour  = sPt->u32cHour / 10;
            g_u32loHour  = sPt->u32cHour % 10;
            g_u32hiMin   = sPt->u32cMinute / 10;
            g_u32loMin   = sPt->u32cMinute % 10;
            g_u32hiSec   = sPt->u32cSecond / 10;
            g_u32loSec   = sPt->u32cSecond % 10;
            
            u32Reg = (g_u32hiHour << 20);
            u32Reg|= (g_u32loHour << 16);
            u32Reg|= (g_u32hiMin << 12);
            u32Reg|= (g_u32loMin << 8);
            u32Reg|= (g_u32hiSec << 4);
            u32Reg|= g_u32loSec;
            g_u32Reg = u32Reg;
            RTCDEBUG ("RTC: REG_RTC_TLR[0x%08x]\n", inp32(TLR));
            RTC_WriteEnable();
            outp32(TLR, (UINT32)g_u32Reg);
            
            RTC_WriteEnable();
            while(inp32(TLR) != (UINT32)g_u32Reg);

            if (g_chHourMode == RTC_CLOCK_12)
            {
                if (sPt->u8cAmPm == RTC_PM)       /* important, range of 12-hour PM mode is 21 upto 32 */
                    sPt->u32cHour -= 20;
            }
            return E_RTC_SUCCESS;


         case RTC_ALARM_TIME:

            g_pfnRTCCallBack_Alarm = NULL;                                         /* Initial call back function.*/
            /*---------------------------------------------------------------------------------------------*/
            /* Second, set alarm time data.                                                                */
            /*---------------------------------------------------------------------------------------------*/
            g_u32hiYear = (sPt->u32Year - RTC_YEAR2000) / 10;
            g_u32loYear = (sPt->u32Year - RTC_YEAR2000) % 10;
            g_u32hiMonth = sPt->u32cMonth / 10;
            g_u32loMonth = sPt->u32cMonth % 10;
            g_u32hiDay = sPt->u32cDay / 10;
            g_u32loDay = sPt->u32cDay % 10;
            
            u32Reg = (g_u32hiYear << 20);
            u32Reg|= (g_u32loYear << 16);
            u32Reg|= (g_u32hiMonth << 12);
            u32Reg|= (g_u32loMonth << 8);
            u32Reg|= (g_u32hiDay << 4);
            u32Reg|= g_u32loDay;
            g_u32Reg = u32Reg;
            outp32(CAR, (UINT32)g_u32Reg);

            if (g_chHourMode == RTC_CLOCK_12)
            {
                if (sPt->u8cAmPm == RTC_PM)       /* important, range of 12-hour PM mode is 21 upto 32 */
                    sPt->u32cHour += 20;
            }
            g_u32hiHour   = sPt->u32cHour / 10;
            g_u32loHour   = sPt->u32cHour % 10;
            g_u32hiMin  = sPt->u32cMinute / 10;
            g_u32loMin  = sPt->u32cMinute % 10;
            g_u32hiSec  = sPt->u32cSecond / 10;
            g_u32loSec  = sPt->u32cSecond % 10;
            
            u32Reg = (g_u32hiHour << 20);
            u32Reg|= (g_u32loHour << 16);
            u32Reg|= (g_u32hiMin << 12);
            u32Reg|= (g_u32loMin << 8);
            u32Reg|= (g_u32hiSec << 4);
            u32Reg|= g_u32loSec;
            
            g_u32Reg = u32Reg;
            outp32(TAR, (UINT32)g_u32Reg);          
            
            if (g_chHourMode == RTC_CLOCK_12)
            {
                if (sPt->u8cAmPm == RTC_PM)       /* important, range of 12-hour PM mode is 21 upto 32 */
                {
                    sPt->u32cHour -= 20;
      
                    g_u32hiHour   = (sPt->u32cHour + 12) / 10;
                    g_u32loHour   = (sPt->u32cHour + 12) % 10;
                    g_u32hiMin  = sPt->u32cMinute / 10;
                    g_u32loMin  = sPt->u32cMinute % 10;
                    g_u32hiSec  = sPt->u32cSecond / 10;
                    g_u32loSec  = sPt->u32cSecond % 10;
                    
                    u32Reg = (g_u32hiHour << 20);
                    u32Reg|= (g_u32loHour << 16);
                    u32Reg|= (g_u32hiMin << 12);
                    u32Reg|= (g_u32loMin << 8);
                    u32Reg|= (g_u32hiSec << 4);
                    u32Reg|= g_u32loSec;
                    
                    g_u32Reg = u32Reg;                
                } 
            }            
            /*---------------------------------------------------------------------------------------------*/
            /* Third, install alarm callback function.                                                     */
            /*---------------------------------------------------------------------------------------------*/
            if (sPt->pfnAlarmCallBack != NULL)
                g_pfnRTCCallBack_Alarm = sPt->pfnAlarmCallBack;
            /*---------------------------------------------------------------------------------------------*/
            /* Finally, enable alarm interrupt.                                                            */
            /*---------------------------------------------------------------------------------------------*/

            RTC_Ioctl(0,RTC_IOC_ENABLE_INT,RTC_ALARM_INT,0);
            
            u32Reg = inp32(TAR);
            RTC_WriteEnable();
            while(inp32(TAR) != (UINT32)g_u32Reg);
            
            return E_RTC_SUCCESS;


       default:
        {
            return E_RTC_ERR_ENOTTY;
        }
    }

}

/*---------------------------------------------------------------------------------------------------------*/
/* Function:     RTC_Ioctl                                                                                  */
/*                                                                                                         */
/* Parameter:                                                                                              */
/*               i32Num             Interface number.   always set 0                                       */
/*               eCmd               Command.                                                               */
/*               u32Arg0            Arguments for the command.                                             */
/*               u32Arg1            Arguments for the command.                                             */
/* Returns:                                                                                                */
/*               E_SUCCESS                 Success.                                                             */
/*               E_RTC_ERR_ENOTTY        Command not support, or parameter incorrect.                         */
/*               E_RTC_ERR_ENODEV        Interface number incorrect.                                          */
/* Side effects:                                                                                           */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*               Support some commands for application.                                                    */
//*--------------------------------------------------------------------------------------------------------*/

UINT32 RTC_Ioctl (INT32 i32Num, E_RTC_CMD eCmd, UINT32 u32Arg0, UINT32 u32Arg1)
{
    INT32 i32Ret;
    UINT32 u32Reg;
    RTC_TICK_T *ptick;

    if (i32Num != 0)
        return E_RTC_ERR_ENODEV;

    switch (eCmd)
    {

        case RTC_IOC_IDENTIFY_LEAP_YEAR:
        {
            u32Reg = inp32(LIR);
            if (u32Reg & 0x01)
            {
                *(PUINT32)u32Arg0 = RTC_LEAP_YEAR;
                RTCDEBUG("\nRTC: It's a leap year\n");
            }
            else
            {
                *(PUINT32)u32Arg0 = 0;
                RTCDEBUG("\nRTC: It's not a leap year\n");
            }
            break;
        }
        case RTC_IOC_SET_TICK_MODE:
        {
            ptick = (RTC_TICK_T *) u32Arg0;
            
            if (g_bIsEnableTickInt== TRUE)
            {            
                RTC_Ioctl(0,RTC_IOC_DISABLE_INT,RTC_TICK_INT,0);
                g_bIsEnableTickInt = TRUE;
              }    
            g_u32RTC_Count = 0;

            u32Reg = RTC_WriteEnable();
            if (u32Reg != 0)
            {
                return E_RTC_ERR_EIO ;
            }
            if (ptick->ucMode > RTC_TICK_1_128_SEC)                            /*Tick mode 0 to 7 */
            {
                return E_RTC_ERR_ENOTTY ;
            }
            
            outp32(TTR, ptick->ucMode);           
           
            
            if (ptick->pfnTickCallBack != NULL)
            {
                g_pfnRTCCallBack_Tick = ptick->pfnTickCallBack;
            }
            else
            {
                g_pfnRTCCallBack_Tick = NULL;
            }
            
            RTC_WriteEnable();
            while(inp32(TTR) != ptick->ucMode);
            /*---------------------------------------------------------------------------------------------*/
            /* Reset tick interrupt status if program enable tick interrupt before.                        */
            /*---------------------------------------------------------------------------------------------*/
            if (g_bIsEnableTickInt== TRUE)
            {

                RTC_Ioctl(0,RTC_IOC_ENABLE_INT,RTC_TICK_INT,0);
                return E_RTC_SUCCESS;
            }
            break;
        }

        case RTC_IOC_GET_TICK:
        {
            (*(PUINT32)u32Arg0) = g_u32RTC_Count;
            break;
        }

        case RTC_IOC_RESTORE_TICK:
        {
            g_u32RTC_Count = 0;
            break;
        }

        case RTC_IOC_ENABLE_INT:
        {
            INT32 i32Ret;

            i32Ret = RTC_WriteEnable();
            if (i32Ret != 0)
            {    
                return E_RTC_ERR_EIO;
            }
            switch ((RTC_INT_SOURCE)u32Arg0)
            {

                case RTC_TICK_INT:
                {
                    g_bIsEnableTickInt   = TRUE;
                    outp32(RIER, inp32(RIER) | RTC_TICK_INT)  ;
                    break;
                }
                case RTC_ALARM_INT:
                {
                    g_bIsEnableAlarmInt  = TRUE;
                    outp32(RIER, inp32(RIER) | RTC_ALARM_INT) ;
                    break;
                }
                case RTC_PSWI_INT:
                {
                    g_bIsEnableAlarmInt  = TRUE;
                    outp32(RIER, inp32(RIER) | RTC_PSWI_INT) ;
                    break;
                }              
                default:
                {
                    return E_RTC_ERR_ENOTTY;

                }
            }
            break;
        }
        case RTC_IOC_DISABLE_INT:
        {
            INT32 i32Ret;

            i32Ret = RTC_WriteEnable();
            if (i32Ret != 0)
            {
                return E_RTC_ERR_EIO;
            }            
            switch ((RTC_INT_SOURCE)u32Arg0)
            {
                case RTC_TICK_INT:
                {
                    g_bIsEnableTickInt   = FALSE;
                    outp32( RIER, inp32(RIER) & (~RTC_TICK_INT) );
                    outp32( RIIR, inp32(RIIR) & (RTC_TICK_INT) );
                    break;
                }
                case RTC_ALARM_INT:
                {
                    g_bIsEnableAlarmInt  = FALSE;
                    outp32( RIER, inp32(RIER) & (~RTC_ALARM_INT) );
                    outp32( RIIR, inp32(RIIR) & (RTC_ALARM_INT) );
                    break;
                }
                case RTC_PSWI_INT:
                {
                    g_bIsEnableAlarmInt  = FALSE;
                    outp32( RIER, inp32(RIER) & (~RTC_PSWI_INT) );
                    outp32( RIIR, inp32(RIIR) & (RTC_PSWI_INT) );
                    break;
                }                

                case RTC_ALL_INT:
                {
                    g_bIsEnableTickInt   = FALSE;
                    g_bIsEnableAlarmInt  = FALSE;
                    outp32( RIER, 0 );
                    outp32( RIIR, RTC_ALL_INT );

                    break;
                }
                default:
                {
                    return E_RTC_ERR_ENOTTY;
                }
            }


            break;
        }

        case RTC_IOC_SET_FREQUENCY:
        {
            i32Ret= RTC_SetFrequencyCompensation(u32Arg0) ;
            if (i32Ret != 0)
            {
                return E_RTC_ERR_ENOTTY;
            }
            break;
        }
        case RTC_IOC_SET_POWER_ON:
        {
            g_u32Reg = RTC_WriteEnable();
            if (g_u32Reg != 0)
            {
                return E_RTC_ERR_EIO;
            }
            outp32(PWRON, inp32(PWRON) | 0x01);

            break;
        }
        case RTC_IOC_SET_POWER_OFF:
        {
            g_u32Reg = RTC_WriteEnable();
            if (g_u32Reg != 0)
            {
                return E_RTC_ERR_EIO;
            }
            outp32(PWRON, (inp32(PWRON) & ~0x05) | 2);
            //outp32(REG_APBCLK, inp32(REG_APBCLK) & ~RTC_CKE);
            outp32(REG_AHBCLK,0);
            while(1);            
            break;
        }
        case RTC_IOC_SET_POWER_OFF_PERIOD:
        {
            g_u32Reg = RTC_WriteEnable();
            if (g_u32Reg != 0)
            {
                return E_RTC_ERR_EIO;
            }
            
            outp32(PWRON, (inp32(PWRON) & ~0xF0000) | ((u32Arg0 & 0xF) << 16));
            
            while(((inp32(PWRON) & 0xF0000)) != ((u32Arg0 & 0xF) << 16) );
            break;
        }
        case RTC_IOC_ENABLE_HW_POWEROFF:
        {
            g_u32Reg = RTC_WriteEnable();
            if (g_u32Reg != 0)
            {
                return E_RTC_ERR_EIO;
            }                       
            outp32(PWRON, (inp32(PWRON) | 0x04));
            while(!(inp32(PWRON) & 0x04));
            break;
        }
        case RTC_IOC_DISABLE_HW_POWEROFF:
        {
            g_u32Reg = RTC_WriteEnable();
            if (g_u32Reg != 0)
            {
                return E_RTC_ERR_EIO;
            }                       
            outp32(PWRON, (inp32(PWRON) & ~0x04));
            while((inp32(PWRON) & 0x04));
            break;
        }        
        case RTC_IOC_SET_PSWI_CALLBACK:
        {     
            g_u32Reg = RTC_WriteEnable();
            if (g_u32Reg != 0)
            {
                return E_RTC_ERR_EIO;
            }               
        
            RTC_Ioctl(0, RTC_IOC_ENABLE_INT, RTC_PSWI_INT, 0);
            
            if (((PFN_RTC_CALLBACK  *) u32Arg0) != NULL)
            {
                g_pfnRTCCallBack_PSWI = (PFN_RTC_CALLBACK  *) u32Arg0;
            }
            else
            {
                g_pfnRTCCallBack_PSWI = NULL;
            }
               break;
        }                            
        case RTC_IOC_GET_POWERKEY_STATUS:
        {
            g_u32Reg = RTC_WriteEnable();
            if (g_u32Reg != 0)
            {
                return E_RTC_ERR_EIO;
            }
            
            g_u32Reg = RTC_WriteEnable();
            if (g_u32Reg != 0)
            {
                return E_RTC_ERR_EIO;
            }
            
            if(inp32(PWRON) & 0x80)
                 *(PUINT32)u32Arg0 = 1;
            else
                 *(PUINT32)u32Arg0 = 0;    

            break;
        }
        default:
        {
            return E_RTC_ERR_ENOTTY;
        }
    }

    return E_RTC_SUCCESS;
}

/*---------------------------------------------------------------------------------------------------------*/
/* Function:     RTC_Close                                                                                  */
/*                                                                                                         */
/* Parameter:                                                                                              */
/*               VOID                                                                                       */
/* Returns:                                                                                                */
/*               E_SUCCESS                Success.                                                         */
/*               E_RTC_ERR_ENODEV           Interface number incorrect.                                      */
/* Side effects:                                                                                           */
/*                                                                                                         */
/* DESCRIPTION                                                                                             */
/*               Disable AIC channel of RTC and both tick and alarm interrupt..                             */
/*---------------------------------------------------------------------------------------------------------*/

UINT32 RTC_Close (VOID)
{

    g_bIsEnableTickInt = FALSE;
    
       sysDisableInterrupt(IRQ_RTC);
   

    RTC_Ioctl(0,RTC_IOC_DISABLE_INT,RTC_ALL_INT,0);


    return E_RTC_SUCCESS;
}

extern UINT32 RTC_Init(VOID);
extern UINT32 RTC_Open(RTC_TIME_DATA_T *sPt);
extern UINT32 RTC_Ioctl(INT32 nNum, E_RTC_CMD uCmd, UINT32 uArg0, UINT32 u32Arg1);
extern UINT32 RTC_Read(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt);
extern UINT32 RTC_Write(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt);
extern UINT32 RTC_Close(VOID);



RTC.h  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright (c) Nuvoton Technology Corp. All rights reserved.                                             */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/
#ifndef __DRVRTC_H__
#define __DRVRTC_H__


/*---------------------------------------------------------------------------------------------------------*/
/* Includes of system headers                                                                              */
/*---------------------------------------------------------------------------------------------------------*/
#include "wbio.h"
#include "w55fa93_reg.h"


#ifdef  __cplusplus
extern "C"
{
#endif

/*---------------------------------------------------------------------------------------------------------*/
/*  Define Version number                                                                                   */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_MAJOR_NUM 1
#define RTC_MINOR_NUM 0
#define RTC_BUILD_NUM 1


/*---------------------------------------------------------------------------------------------------------*/
/* Define Error Code                                                                                       */
/*---------------------------------------------------------------------------------------------------------*/
// E_DRVRTC_ERR_CALENDAR_VALUE        Wrong Calendar Value                                                     
// E_DRVRTC_ERR_TIMESACLE_VALUE        Wrong Time Scale Value                                                  
// E_DRVRTC_ERR_TIME_VALUE            Wrong Time Value                                                          
// E_DRVRTC_ERR_DWR_VALUE            Wrong Day Value                                                          
// E_DRVRTC_ERR_FCR_VALUE            Wrong Compenation value                                                  
// E_DRVRTC_ERR_EIO                 Initial RTC Failed.                                                       
// E_DRVRTC_ERR_ENOTTY                Command not support, or parameter incorrect.                              
// E_DRVRTC_ERR_ENODEV               Interface number incorrect.                                            
// E_DRVRTC_ERR_FAILED                Failed.                                                                  
#define E_RTC_SUCCESS                    0
#define E_RTC_ERR_CALENDAR_VALUE        1
#define E_RTC_ERR_TIMESACLE_VALUE        2
#define E_RTC_ERR_TIME_VALUE            3
#define E_RTC_ERR_DWR_VALUE                4
#define E_RTC_ERR_FCR_VALUE                5
#define E_RTC_ERR_EIO                    6
#define E_RTC_ERR_ENOTTY                7
#define E_RTC_ERR_ENODEV                8

/*---------------------------------------------------------------------------------------------------------*/
/*  RTC Access Key                                                                                              */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_INIT_KEY            0xa5eb1357
#define RTC_WRITE_KEY        0xa965

/*---------------------------------------------------------------------------------------------------------*/
/*  RTC Initial Time Out Value                                                                                  */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_WAIT_COUNT        10000

/*---------------------------------------------------------------------------------------------------------*/
/*  RTC Reference                                                                                            */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_YEAR2000            2000
#define RTC_FCR_REFERENCE        32761

/*---------------------------------------------------------------------------------------------------------*/
/*  Leap Year                                                                                                */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_LEAP_YEAR        1

/*---------------------------------------------------------------------------------------------------------*/
/*  12-Hour / 24-Hour                                                                                          */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_CLOCK_12            0 
#define RTC_CLOCK_24            1

/*---------------------------------------------------------------------------------------------------------*/
/*  AM / PM                                                                                                    */
/*---------------------------------------------------------------------------------------------------------*/
#define RTC_AM                1
#define RTC_PM                2

/*---------------------------------------------------------------------------------------------------------*/
/* INTERRUPT SOURCE                                                                                           */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
    RTC_ALARM_INT    =0x01,
    RTC_TICK_INT     =0x02,
    RTC_PSWI_INT     =0x04,
    RTC_ALL_INT      =0x07
}RTC_INT_SOURCE;

/*---------------------------------------------------------------------------------------------------------*/
/* Define Ioctl commands                                                                                   */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
    RTC_IOC_IDENTIFY_LEAP_YEAR         =  0,
    RTC_IOC_SET_TICK_MODE           =  1,
    RTC_IOC_GET_TICK                =  2,
    RTC_IOC_RESTORE_TICK               =  3,
    RTC_IOC_ENABLE_INT                 =  4,
    RTC_IOC_DISABLE_INT             =  5,
    RTC_IOC_SET_CURRENT_TIME          =  6,
    RTC_IOC_SET_ALAMRM_TIME             =  7,
    RTC_IOC_SET_FREQUENCY              =  8,    
    RTC_IOC_SET_POWER_ON            =  9,
    RTC_IOC_SET_POWER_OFF           =  10,        
    RTC_IOC_SET_POWER_OFF_PERIOD      =  11,
    RTC_IOC_ENABLE_HW_POWEROFF        =  12,
    RTC_IOC_DISABLE_HW_POWEROFF        =  13,
    RTC_IOC_GET_POWERKEY_STATUS      =  14,     
    RTC_IOC_SET_PSWI_CALLBACK        =  15
}E_RTC_CMD;

/*---------------------------------------------------------------------------------------------------------*/
/* Define for RTC Tick mode                                                                                */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
     RTC_TICK_1_SEC       =         0,                           /* 1     sec                            */
     RTC_TICK_1_2_SEC     =         1,                           /* 1/2   sec                            */
     RTC_TICK_1_4_SEC     =         2,                           /* 1/4   sec                            */ 
     RTC_TICK_1_8_SEC     =         3,                           /* 1/8   sec                            */
     RTC_TICK_1_16_SEC    =         4,                           /* 1/16  sec                            */
     RTC_TICK_1_32_SEC    =         5,                           /* 1/32  sec                            */ 
     RTC_TICK_1_64_SEC    =         6,                           /* 1/64  sec                            */
     RTC_TICK_1_128_SEC   =         7                            /* 1/128 sec                            */
}RTC_TICK;

/*---------------------------------------------------------------------------------------------------------*/
/* Define Time data struct & some parameters                                                               */
/*---------------------------------------------------------------------------------------------------------*/
typedef void (PFN_RTC_CALLBACK)(void);

typedef enum
{
    RTC_CURRENT_TIME    =    0,
    RTC_ALARM_TIME      =    1 
}E_RTC_TIME_SELECT;

/*---------------------------------------------------------------------------------------------------------*/
/* Define Day of week parameter                                                                            */
/*---------------------------------------------------------------------------------------------------------*/
typedef enum
{
    RTC_SUNDAY         =   0,
    RTC_MONDAY         =   1,
    RTC_TUESDAY        =   2,
    RTC_WEDNESDAY      =   3,
    RTC_THURSDAY       =   4,
    RTC_FRIDAY         =   5,
    RTC_SATURDAY       =   6
}E_RTC_DWR_PARAMETER;
/*---------------------------------------------------------------------------------------------------------*/
/* Define Time Data Struct                                                                                 */
/*---------------------------------------------------------------------------------------------------------*/
typedef struct
{
    UINT8 u8cClockDisplay;                                         /* 12-Hour, 24-Hour */
    UINT8 u8cAmPm;                                                 /* Only 12-hr used */
    UINT32 u32cSecond;
    UINT32 u32cMinute;
    UINT32 u32cHour;
    UINT32 u32cDayOfWeek;
    UINT32 u32cDay;
    UINT32 u32cMonth;
    UINT32 u32Year;
    PFN_RTC_CALLBACK *pfnAlarmCallBack;    
}RTC_TIME_DATA_T;

/*---------------------------------------------------------------------------------------------------------*/
/* Define Tick Struct                                                                                      */
/*---------------------------------------------------------------------------------------------------------*/
typedef struct
{
    UINT8 ucMode;
    PFN_RTC_CALLBACK *pfnTickCallBack;
}RTC_TICK_T;

/*---------------------------------------------------------------------------------------------------------*/
/* Define Function Prototype                                                                               */
/*---------------------------------------------------------------------------------------------------------*/
UINT32 RTC_Init(VOID);   
UINT32 RTC_Open(RTC_TIME_DATA_T *sPt);
UINT32 RTC_Ioctl(INT32 i32Num, E_RTC_CMD eCmd, UINT32 u32Arg0, UINT32 u32Arg1);
UINT32 RTC_Read(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt);
UINT32 RTC_Write(E_RTC_TIME_SELECT eTime, RTC_TIME_DATA_T *sPt);
UINT32 RTC_SetFrequencyCompensation(FLOAT fnumber);
UINT32 RTC_WriteEnable (VOID);
UINT32 RTC_Close(VOID);

#ifdef  __cplusplus
}
#endif

#endif /* __DRVRTC_H__ */



sd.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential                                       */
/*                                                                                   */
/* Copyright (c) 2008 by Nuvoton Technology Corporation                              */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
#ifdef ECOS
#include "drv_api.h"
#include "diag.h"
#include "Common.h"
#include "wbio.h"
#else
#include "wblib.h"
#endif

#include "w55fa93_reg.h"
#include "w55fa93_sic.h"
#include "fmi.h"
UINT32 _fmi_uFMIReferenceClock;
// define DATE CODE and show it when running to make maintaining easy.
#define SD_DATE_CODE    FMI_DATE_CODE

#define SD_BLOCK_SIZE   512

#define FMI_SD_INITCOUNT    2000
#define FMI_TICKCOUNT       1000

#define FMI_TYPE_UNKNOWN    0
#define FMI_TYPE_SD_HIGH    1
#define FMI_TYPE_SD_LOW     2
#define FMI_TYPE_MMC        3

// global variables
// For response R3 (such as ACMD41, CRC-7 is invalid; but SD controller will still
//      calculate CRC-7 and get an error result, software should ignore this error and clear SDISR [CRC_IF] flag
//      _fmi_uR3_CMD is the flag for it. 1 means software should ignore CRC-7 error
UINT32 _fmi_uR3_CMD=0;
UINT32 _fmi_uR7_CMD=0;


DISK_DATA_T SD_DiskInfo0;
DISK_DATA_T SD_DiskInfo1;
DISK_DATA_T SD_DiskInfo2;

#define schedule();
__align(4096) UCHAR _fmi_ucSDHCBuffer[512];
UINT8 *_fmi_pSDHCBuffer;

//--- 2014/3/27, check the sector number is valid or not for current SD card.
unsigned int g_max_valid_sector;    // The max valid sector number for current SD card.

static int sd0_ok = 0;
static int sd1_ok = 0;
static int sd2_ok = 0;

INT fmiSDCheckSector(UINT32 uSector, UINT32 uBufcnt)
{
    if ((uSector + uBufcnt - 1) > g_max_valid_sector)
    {
        sysprintf("ERROR: Fail to access invalid sector number %d from SD card !!\n", uSector+uBufcnt-1);
        sysprintf("       The max valid sector number for current SD card is %d.\n", g_max_valid_sector);
        return FMI_SD_SELECT_ERROR; // invalid sector
    }
    return 0;   // valid sector
}


void fmiCheckRB()
{
    while(1)
    {
        outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);
        while(inpw(REG_SDCR) & SDCR_8CLK_OE);
        if (inpw(REG_SDISR) & SDISR_SD_DATA0)
            break;
    }
}

INT fmiSDCommand(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg)
{
    outpw(REG_SDARG, uArg);
    outpw(REG_SDCR, (inpw(REG_SDCR)&(~SDCR_CMD_CODE))|(ucCmd << 8)|(SDCR_CO_EN));

    while(inpw(REG_SDCR) & SDCR_CO_EN)
    {
        if (pSD == pSD0)
            fmiSD_CardStatus();
        if (pSD->bIsCardInsert == FALSE)
            return FMI_NO_SD_CARD;
    }

    return Successful;
}


INT fmiSDCmdAndRsp(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg, INT ntickCount)
{
    outpw(REG_SDARG, uArg);
    outpw(REG_SDCR, (inpw(REG_SDCR)&(~SDCR_CMD_CODE))|(ucCmd << 8)|(SDCR_CO_EN | SDCR_RI_EN));

    if (ntickCount > 0)
    {
        while(inpw(REG_SDCR) & SDCR_RI_EN)
        {
            if(ntickCount-- == 0) {
                outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_SWRST); // reset SD engine
                return FMI_SD_INIT_TIMEOUT;
            }
            if (pSD == pSD0)
                fmiSD_CardStatus();
            if (pSD->bIsCardInsert == FALSE)
                return FMI_NO_SD_CARD;
        }
    }
    else
    {
        while(inpw(REG_SDCR) & SDCR_RI_EN)
        {
            if (pSD == pSD0)
                fmiSD_CardStatus();
            if (pSD->bIsCardInsert == FALSE)
                return FMI_NO_SD_CARD;
        }
    }

    if (_fmi_uR7_CMD)
    {
        if (((inpw(REG_SDRSP1) & 0xff) != 0x55) && ((inpw(REG_SDRSP0) & 0xf) != 0x01))
        {
            _fmi_uR7_CMD = 0;
            return FMI_SD_CMD8_ERROR;
        }
    }

    if (!_fmi_uR3_CMD)
    {
        if (inpw(REG_SDISR) & SDISR_CRC_7)      // check CRC7
            return Successful;
        else
        {
#ifdef DEBUG
            sysprintf("response error [%d]!\n", ucCmd);
#endif
            return FMI_SD_CRC7_ERROR;
        }
    }
    else    // ignore CRC error for R3 case
    {
        _fmi_uR3_CMD = 0;
        outpw(REG_SDISR, SDISR_CRC_IF);
        return Successful;
    }
}


// Get 16 bytes CID or CSD
INT fmiSDCmdAndRsp2(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg, UINT *puR2ptr)
{
    unsigned int i;
    unsigned int tmpBuf[5];

    outpw(REG_SDARG, uArg);
    outpw(REG_SDCR, (inpw(REG_SDCR)&(~SDCR_CMD_CODE))|(ucCmd << 8)|(SDCR_CO_EN | SDCR_R2_EN));

    while(inpw(REG_SDCR) & SDCR_R2_EN)
    {
        if (pSD == pSD0)
            fmiSD_CardStatus();
        if (pSD->bIsCardInsert == FALSE)
            return FMI_NO_SD_CARD;
    }

    if (inpw(REG_SDISR) & SDISR_CRC_7)
    {
        for (i=0; i<5; i++)
            tmpBuf[i] = Swap32(inpw(REG_FB_0+i*4));

        for (i=0; i<4; i++)
            *puR2ptr++ = ((tmpBuf[i] & 0x00ffffff)<<8) | ((tmpBuf[i+1] & 0xff000000)>>24);
        return Successful;
    }
    else
        return FMI_SD_CRC7_ERROR;
}


INT fmiSDCmdAndRspDataIn(FMI_SD_INFO_T *pSD, UINT8 ucCmd, UINT32 uArg)
{
    outpw(REG_SDARG, uArg);
    outpw(REG_SDCR, (inpw(REG_SDCR)&(~SDCR_CMD_CODE))|(ucCmd << 8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DI_EN));

    while (inpw(REG_SDCR) & SDCR_RI_EN)
    {
        if (pSD == pSD0)
            fmiSD_CardStatus();
        if (pSD->bIsCardInsert == FALSE)
            return FMI_NO_SD_CARD;
    }

    while (inpw(REG_SDCR) & SDCR_DI_EN)
    {
        if (pSD == pSD0)
            fmiSD_CardStatus();
        if (pSD->bIsCardInsert == FALSE)
            return FMI_NO_SD_CARD;
    }

    if (!(inpw(REG_SDISR) & SDISR_CRC_7))       // check CRC7
    {
#ifdef DEBUG
        sysprintf("fmiSDCmdAndRspDataIn: response error [%d]!\n", ucCmd);
#endif
        return FMI_SD_CRC7_ERROR;
    }

    if (!(inpw(REG_SDISR) & SDISR_CRC_16))      // check CRC16
    {
#ifdef DEBUG
        sysprintf("fmiSDCmdAndRspDataIn: read data CRC16 error!\n");
#endif
        return FMI_SD_CRC16_ERROR;
    }
    return Successful;
}

// Initial
INT fmiSD_Init(FMI_SD_INFO_T *pSD)
{
    int volatile i, status, rate;
    unsigned int resp;
    unsigned int CIDBuffer[4];
    unsigned int volatile u32CmdTimeOut;
    int sdport;

    if (pSD == pSD0)
        sdport = 0;
    else if (pSD == pSD1)
        sdport = 1;
    else if (pSD == pSD2)
        sdport = 2;
    else
        return FMI_SD_INIT_ERROR;
    sysprintf("Initial SD NonOS Driver (%s) for SD port %d\n", SD_DATE_CODE, sdport);

#if 1
    // set the clock to 200KHz
    /* divider */
    rate = _fmi_uFMIReferenceClock / 200;
    if ((_fmi_uFMIReferenceClock % 200) == 0)
        rate = rate - 1;
#else
    // set the clock to 400KHz
    /* divider */
    rate = _fmi_uFMIReferenceClock / 400;
    if ((_fmi_uFMIReferenceClock % 400) == 0)
        rate = rate - 1;
#endif

    for(i=0; i<100; i++);
    outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_S) | (0x03 << 19));     // SD clock from UPLL
    outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N0) | (0x07 << 16));    // SD clock divided by 8
    rate /= 8;
    rate &= 0xFF;
    if (rate) rate--;
    outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N1) | (rate << 24));    // SD clock divider

    for(i=0; i<1000; i++);

    // power ON 74 clock
    outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_74CLK_OE);

    while(inpw(REG_SDCR) & SDCR_74CLK_OE)
    {
        if (pSD == pSD0)
            fmiSD_CardStatus();
        if (pSD->bIsCardInsert == FALSE)
            return FMI_NO_SD_CARD;
    }

    fmiSDCommand(pSD, 0, 0);        // reset all cards
    for (i=0x100; i>0; i--);

    // initial SDHC
    _fmi_uR7_CMD = 1;
    u32CmdTimeOut = 5000;

    i = fmiSDCmdAndRsp(pSD, 8, 0x00000155, u32CmdTimeOut);
    if (i == Successful)
    {
        // SD 2.0
        fmiSDCmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
        _fmi_uR3_CMD = 1;
        fmiSDCmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 2.7v-3.6v
        resp = inpw(REG_SDRSP0);

        while (!(resp & 0x00800000))        // check if card is ready
        {
            fmiSDCmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
            _fmi_uR3_CMD = 1;
            fmiSDCmdAndRsp(pSD, 41, 0x40ff8000, u32CmdTimeOut); // 3.0v-3.4v
            resp = inpw(REG_SDRSP0);
        }
        if (resp & 0x00400000)
            pSD->uCardType = FMI_TYPE_SD_HIGH;
        else
            pSD->uCardType = FMI_TYPE_SD_LOW;
    }
    else
    {
        // SD 1.1 or MMC
        fmiSDCommand(pSD, 0, 0);        // reset all cards
        for (i=0x100; i>0; i--);

        i = fmiSDCmdAndRsp(pSD, 55, 0x00, u32CmdTimeOut);
        if (i == FMI_SD_INIT_TIMEOUT)     // MMC memory
        {
            fmiSDCommand(pSD, 0, 0);        // reset
            for (i=0x100; i>0; i--);

            _fmi_uR3_CMD = 1;
            // 2014/8/6, to support eMMC v4.4, the argument of CMD1 should be 0x40ff8000 to support both MMC plus and eMMC cards.
            if (fmiSDCmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut) != FMI_SD_INIT_TIMEOUT)   // MMC memory
            {
                resp = inpw(REG_SDRSP0);
                while (!(resp & 0x00800000))        // check if card is ready
                {
                    _fmi_uR3_CMD = 1;
                    fmiSDCmdAndRsp(pSD, 1, 0x40ff8000, u32CmdTimeOut);  // high voltage
                    resp = inpw(REG_SDRSP0);
                }
                // MMC card is ready. Check the access mode of MMC card.
                if (resp & 0x00400000)
                    pSD->uCardType = FMI_TYPE_MMC_SECTOR_MODE;
                else
                    pSD->uCardType = FMI_TYPE_MMC;
            }
            else
            {
                pSD->uCardType = FMI_TYPE_UNKNOWN;
                return FMI_ERR_DEVICE;
            }
        }
        else if (i == Successful)    // SD Memory
        {
            _fmi_uR3_CMD = 1;
            fmiSDCmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v
            resp = inpw(REG_SDRSP0);
            while (!(resp & 0x00800000))        // check if card is ready
            {
                fmiSDCmdAndRsp(pSD, 55, 0x00,u32CmdTimeOut);
                _fmi_uR3_CMD = 1;
                fmiSDCmdAndRsp(pSD, 41, 0x00ff8000, u32CmdTimeOut); // 3.0v-3.4v
                resp = inpw(REG_SDRSP0);
            }
            pSD->uCardType = FMI_TYPE_SD_LOW;
        }
        else
        {
            pSD->uCardType = FMI_TYPE_UNKNOWN;
#ifdef DEBUG
            sysprintf("CMD55 CRC error !!\n");
#endif
            return FMI_SD_INIT_ERROR;
        }
    }

    // CMD2, CMD3
    if (pSD->uCardType != FMI_TYPE_UNKNOWN)
    {
        fmiSDCmdAndRsp2(pSD, 2, 0x00, CIDBuffer);
        if ((pSD->uCardType == FMI_TYPE_MMC) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
        {
            // Increase RCA for next MMC card.
            // The RCA value 0 is reserved to set all cards with CMD7.
            // The default value is 1.
            pSD->uRCA = (pSD->uRCA + 0x10000) & 0xFFFF0000;   // RCA is 16-bit value at MSB
            if (pSD->uRCA == 0)
                pSD->uRCA = 0x10000;

            if ((status = fmiSDCmdAndRsp(pSD, 3, pSD->uRCA, 0)) != Successful)  // set RCA for MMC
                return status;
        }
        else
        {
            if ((status = fmiSDCmdAndRsp(pSD, 3, 0x00, 0)) != Successful)       // get RCA for SD
                return status;
            else
                pSD->uRCA = (inpw(REG_SDRSP0) << 8) & 0xffff0000;
        }
    }

#ifdef DEBUG
    switch (pSD->uCardType)
    {
        case FMI_TYPE_SD_HIGH:
            DBG_PRINTF("This is high capacity SD memory card\n");       break;
        case FMI_TYPE_SD_LOW:
            DBG_PRINTF("This is standard capacity SD memory card\n");   break;
        case FMI_TYPE_MMC:
            DBG_PRINTF("This is standard capacity MMC memory card\n");  break;
        case FMI_TYPE_MMC_SECTOR_MODE:
            DBG_PRINTF("This is high capacity MMC memory card\n");      break;
    }
#endif

    // set data transfer clock
    return Successful;
}


INT fmiSwitchToHighSpeed(FMI_SD_INFO_T *pSD)
{
    int volatile status=0;
    UINT16 current_comsumption, busy_status0, busy_status1;
    // UINT16 fun1_info, switch_status;

    outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer);   // set DMA transfer starting address
    outpw(REG_SDBLEN, 63);  // 512 bit

    if ((status = fmiSDCmdAndRspDataIn(pSD, 6, 0x00ffff01)) != Successful)
        return Fail;

    current_comsumption = _fmi_pSDHCBuffer[0]<<8 | _fmi_pSDHCBuffer[1];
    if (!current_comsumption)
        return Fail;

    // fun1_info =  _fmi_pSDHCBuffer[12]<<8 | _fmi_pSDHCBuffer[13];
    // switch_status =  _fmi_pSDHCBuffer[16] & 0xf;
    busy_status0 = _fmi_pSDHCBuffer[28]<<8 | _fmi_pSDHCBuffer[29];

    if (!busy_status0)  // function ready
    {
        outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer);   // set DMA transfer starting address
        outpw(REG_SDBLEN, 63);  // 512 bit

        if ((status = fmiSDCmdAndRspDataIn(pSD, 6, 0x80ffff01)) != Successful)
            return Fail;

        // function change timing: 8 clocks
        outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);
        while(inpw(REG_SDCR) & SDCR_8CLK_OE);

        current_comsumption = _fmi_pSDHCBuffer[0]<<8 | _fmi_pSDHCBuffer[1];
        if (!current_comsumption)
            return Fail;

        busy_status1 = _fmi_pSDHCBuffer[28]<<8 | _fmi_pSDHCBuffer[29];
        if (!busy_status1)
            sysprintf("switch into high speed mode !!!\n");

        return Successful;
    }
    else
        return Fail;
}


INT fmiSelectCard(FMI_SD_INFO_T *pSD)
{
    int volatile status=0, i;
    int rate;
    UINT32 arg;

    if ((status = fmiSDCmdAndRsp(pSD, 7, pSD->uRCA, 0)) != Successful)
        return status;

    fmiCheckRB();

    // if SD card set 4bit
    if (pSD->uCardType == FMI_TYPE_SD_HIGH)
    {
        _fmi_pSDHCBuffer = (UINT8 *)((UINT32)_fmi_ucSDHCBuffer | 0x80000000);
        outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer);   // set DMA transfer starting address
        outpw(REG_SDBLEN, 7);   // 64 bit

        if ((status = fmiSDCmdAndRsp(pSD, 55, pSD->uRCA, 0)) != Successful)
            return status;
        if ((status = fmiSDCmdAndRspDataIn(pSD, 51, 0x00)) != Successful)
            return status;

        if ((_fmi_ucSDHCBuffer[0] & 0xf) == 0x2)
        {
            // support SD spec v2.0
            status = fmiSwitchToHighSpeed(pSD);
            if (status == Successful)
            {
                /* divider */
                rate = _fmi_uFMIReferenceClock / SDHC_FREQ;
                if ((_fmi_uFMIReferenceClock % SDHC_FREQ) > 0)
                    rate ++;

                for(i=0; i<100; i++);

                outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_S) | (0x03 << 19));     // SD clock from UPLL
                outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N0) | (0x01 << 16));    // SD clock divided by 8

                if (rate % 2)
                {
                    rate /= 2;
                    rate &= 0xFF;
                }
                else
                {
                    rate /= 2;
                    rate &= 0xFF;
                    rate--;
                }

                outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N1) | (rate << 24));    // SD clock divider

                for(i=0; i<1000; i++);
            }
        }

        if ((status = fmiSDCmdAndRsp(pSD, 55, pSD->uRCA, 0)) != Successful)
            return status;
        if ((status = fmiSDCmdAndRsp(pSD, 6, 0x02, 0)) != Successful)   // set bus width to 4-bit mode for SD card
            return status;

        outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_DBW);   // set bus width to 4-bit mode for SD host controller
    }
    else if (pSD->uCardType == FMI_TYPE_SD_LOW)
    {
#if 0
        _fmi_pSDHCBuffer = (UINT8 *)((UINT32)_fmi_ucSDHCBuffer | 0x80000000);
        outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer);   // set DMA transfer starting address
        outpw(REG_SDBLEN, 7);   // 64 bit

        if ((status = fmiSDCmdAndRsp(pSD, 55, pSD->uRCA, 0)) != Successful)
            return status;
        if ((status = fmiSDCmdAndRspDataIn(pSD, 51, 0x00)) != Successful)
            return status;
#endif
        if ((status = fmiSDCmdAndRsp(pSD, 55, pSD->uRCA, 0)) != Successful)
            return status;
        if ((status = fmiSDCmdAndRsp(pSD, 6, 0x02, 0)) != Successful)   // set bus width to 4-bit mode for SD card
            return status;

        outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_DBW);   // set bus width to 4-bit mode for SD host controller
    }
    else if ((pSD->uCardType == FMI_TYPE_MMC) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
    {
        //--- sent CMD6 to MMC card to set bus width to 4 bits mode
        // set CMD6 argument Access field to 3, Index to 183, Value to 1 (4-bit mode)
        arg = (3 << 24) | (183 << 16) | (1 << 8);
        if ((status = fmiSDCmdAndRsp(pSD, 6, arg, 0)) != Successful)
            return status;
        fmiCheckRB();

        outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_DBW);   // set bus width to 4-bit mode for SD host controller
    }

    if ((status = fmiSDCmdAndRsp(pSD, 16, SD_BLOCK_SIZE, 0)) != Successful) // set block length
        return status;

    fmiSDCommand(pSD, 7, 0);

    // According to SD spec v2.0 chapter 4.4,
    // "After the last SD Memory Card bus transaction, the host is required,
    //  to provide 8 (eight) clock cycles for the card to complete the
    //  operation before shutting down the clock."
    outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);

#ifdef _SIC_USE_INT_
    outpw(REG_SDIER, inpw(REG_SDIER)|SDIER_BLKD_IEN);
#endif  //_SIC_USE_INT_

    return Successful;
}

/*-----------------------------------------------------------------------------
 * fmiSD_Read_in(), To read data with default black size SD_BLOCK_SIZE
 *---------------------------------------------------------------------------*/
INT fmiSD_Read_in(FMI_SD_INFO_T *pSD, UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr)
{
    BOOL volatile bIsSendCmd=FALSE;
    unsigned int volatile reg;
    int volatile i, loop, status;

    //--- check input parameters
    status = fmiSDCheckSector(uSector, uBufcnt);
    if (status < 0)
        return status;  // invalid sector

    if (uBufcnt == 0)
    {
        sysprintf("ERROR: fmiSD_Read_in(): uBufcnt cannot be 0!!\n");
        return FMI_SD_SELECT_ERROR;
    }

    if ((status = fmiSDCmdAndRsp(pSD, 7, pSD->uRCA, 0)) != Successful)
        return status;
    fmiCheckRB();

    outpw(REG_SDBLEN, SD_BLOCK_SIZE - 1);

    if ((pSD->uCardType == FMI_TYPE_SD_HIGH) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
        outpw(REG_SDARG, uSector);
    else
        outpw(REG_SDARG, uSector * SD_BLOCK_SIZE);

    outpw(REG_DMACSAR, uDAddr);

    loop = uBufcnt / 255;
    for (i=0; i<loop; i++)
    {
#ifdef _SIC_USE_INT_
        _fmi_bIsSDDataReady = FALSE;
#endif  //_SIC_USE_INT_

        reg = inpw(REG_SDCR) & ~SDCR_CMD_CODE;
        reg = reg | 0xff0000;   // set BLK_CNT to 255
        if (bIsSendCmd == FALSE)
        {
            outpw(REG_SDCR, reg|(18<<8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DI_EN));
            bIsSendCmd = TRUE;
        }
        else
            outpw(REG_SDCR, reg | SDCR_DI_EN);

#ifdef _SIC_USE_INT_
        while(!_fmi_bIsSDDataReady)
#else
        while(1)
#endif  //_SIC_USE_INT_
        {
#ifndef _SIC_USE_INT_
            if ((inpw(REG_SDISR) & SDISR_BLKD_IF) && (!(inpw(REG_SDCR) & SDCR_DI_EN)))
            {
                outpw(REG_SDISR, SDISR_BLKD_IF);
                break;
            }
#endif
            if (pSD == pSD0)
                fmiSD_CardStatus();
            if (pSD->bIsCardInsert == FALSE)
                return FMI_NO_SD_CARD;

            /* Call schedule() to release CPU power to other tasks during waiting SIC/DMA completed. */
            schedule();
        }

        if (!(inpw(REG_SDISR) & SDISR_CRC_7))       // check CRC7
        {
#ifdef DEBUG
            sysprintf("fmiSD_Read_in(): response error!\n");
#endif
            return FMI_SD_CRC7_ERROR;
        }

        if (!(inpw(REG_SDISR) & SDISR_CRC_16))      // check CRC16
        {
#ifdef DEBUG
            sysprintf("fmiSD_Read_in() :read data CRC16 error!\n");
#endif
            return FMI_SD_CRC16_ERROR;
        }
    }

    loop = uBufcnt % 255;
    if (loop != 0)
    {
#ifdef _SIC_USE_INT_
        _fmi_bIsSDDataReady = FALSE;
#endif  //_SIC_USE_INT_

        reg = inpw(REG_SDCR) & (~SDCR_CMD_CODE);
        reg = reg & (~SDCR_BLKCNT);
        reg |= (loop << 16);    // setup SDCR_BLKCNT

        if (bIsSendCmd == FALSE)
        {
            outpw(REG_SDCR, reg|(18<<8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DI_EN));
            bIsSendCmd = TRUE;
        }
        else
            outpw(REG_SDCR, reg | SDCR_DI_EN);

#ifdef _SIC_USE_INT_
        while(!_fmi_bIsSDDataReady)
#else
        while(1)
#endif  //_SIC_USE_INT_
        {
#ifndef _SIC_USE_INT_
            if ((inpw(REG_SDISR) & SDISR_BLKD_IF) && (!(inpw(REG_SDCR) & SDCR_DI_EN)))
            {
                outpw(REG_SDISR, SDISR_BLKD_IF);
                break;
            }
#endif
            if (pSD == pSD0)
                fmiSD_CardStatus();
            if (pSD->bIsCardInsert == FALSE)
                return FMI_NO_SD_CARD;

            /* Call schedule() to release CPU power to other tasks during waiting SIC/DMA completed. */
            schedule();
        }

        if (!(inpw(REG_SDISR) & SDISR_CRC_7))       // check CRC7
        {
#ifdef DEBUG
            sysprintf("fmiSD_Read_in(): response error!\n");
#endif
            return FMI_SD_CRC7_ERROR;
        }

        if (!(inpw(REG_SDISR) & SDISR_CRC_16))      // check CRC16
        {
#ifdef DEBUG
            sysprintf("fmiSD_Read_in(): read data CRC16 error!\n");
#endif
            return FMI_SD_CRC16_ERROR;
        }
    }

    if (fmiSDCmdAndRsp(pSD, 12, 0, 0))      // stop command
    {
#ifdef DEBUG
        sysprintf("stop command fail !!\n");
#endif
        return FMI_SD_CRC7_ERROR;
    }
    fmiCheckRB();

    fmiSDCommand(pSD, 7, 0);

    // According to SD spec v2.0 chapter 4.4,
    // "After the last SD Memory Card bus transaction, the host is required,
    //  to provide 8 (eight) clock cycles for the card to complete the
    //  operation before shutting down the clock."
    outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);

    return Successful;
}

/*-----------------------------------------------------------------------------
 * fmiSD_Write_in(), To write data with static black size SD_BLOCK_SIZE
 *---------------------------------------------------------------------------*/
INT fmiSD_Write_in(FMI_SD_INFO_T *pSD, UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr)
{
    BOOL volatile bIsSendCmd=FALSE;
    unsigned int volatile reg;
    int volatile i, loop, status;

    //--- check input parameters
    status = fmiSDCheckSector(uSector, uBufcnt);
    if (status < 0)
        return status;  // invalid sector

    if (uBufcnt == 0)
    {
        sysprintf("ERROR: fmiSD_Write_in(): uBufcnt cannot be 0!!\n");
        return FMI_SD_SELECT_ERROR;
    }

    if ((status = fmiSDCmdAndRsp(pSD, 7, pSD->uRCA, 0)) != Successful)
        return status;
    fmiCheckRB();

    // According to SD Spec v2.0, the write CMD block size MUST be 512, and the start address MUST be 512*n.
    outpw(REG_SDBLEN, SD_BLOCK_SIZE - 1);           // set the block size

    if ((pSD->uCardType == FMI_TYPE_SD_HIGH) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
        outpw(REG_SDARG, uSector);
    else
        outpw(REG_SDARG, uSector * SD_BLOCK_SIZE);  // set start address for SD CMD

    outpw(REG_DMACSAR, uSAddr);
    loop = uBufcnt / 255;   // the maximum block count is 0xFF=255 for register SDCR[BLK_CNT]
    for (i=0; i<loop; i++)
    {
#ifdef _SIC_USE_INT_
        _fmi_bIsSDDataReady = FALSE;
#endif  //_SIC_USE_INT_

        reg = inpw(REG_SDCR) & 0xff00c080;
        reg = reg | 0xff0000;   // set BLK_CNT to 0xFF=255
        if (!bIsSendCmd)
        {
            outpw(REG_SDCR, reg|(25<<8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DO_EN));
            bIsSendCmd = TRUE;
        }
        else
            outpw(REG_SDCR, reg | SDCR_DO_EN);

#ifdef _SIC_USE_INT_
        while(!_fmi_bIsSDDataReady)
#else
        while(1)
#endif  //_SIC_USE_INT_
        {
#ifndef _SIC_USE_INT_
            if ((inpw(REG_SDISR) & SDISR_BLKD_IF) && (!(inpw(REG_SDCR) & SDCR_DO_EN)))
            {
                outpw(REG_SDISR, SDISR_BLKD_IF);
                break;
            }
#endif
            if (pSD == pSD0)
                fmiSD_CardStatus();
            if (pSD->bIsCardInsert == FALSE)
                return FMI_NO_SD_CARD;

            /* Call schedule() to release CPU power to other tasks during waiting SIC/DMA completed. */
            schedule();
        }

        if ((inpw(REG_SDISR) & SDISR_CRC_IF) != 0)      // check CRC
        {
#ifdef DEBUG
            sysprintf("1. fmiSD_Write:write data error [SDISR = 0x%08X]\n", inpw(REG_SDISR));
#endif
            outpw(REG_SDISR, SDISR_CRC_IF);
            return FMI_SD_CRC_ERROR;
        }
    }

    loop = uBufcnt % 255;
    if (loop != 0)
    {
#ifdef _SIC_USE_INT_
        _fmi_bIsSDDataReady = FALSE;
#endif  //_SIC_USE_INT_

        reg = (inpw(REG_SDCR) & 0xff00c080) | (loop << 16);
        if (!bIsSendCmd)
        {
            outpw(REG_SDCR, reg|(25<<8)|(SDCR_CO_EN | SDCR_RI_EN | SDCR_DO_EN));
            bIsSendCmd = TRUE;
        }
        else
            outpw(REG_SDCR, reg | SDCR_DO_EN);

#ifdef _SIC_USE_INT_
        while(!_fmi_bIsSDDataReady)
#else
        while(1)
#endif  //_SIC_USE_INT_
        {
#ifndef _SIC_USE_INT_
            if ((inpw(REG_SDISR) & SDISR_BLKD_IF) && (!(inpw(REG_SDCR) & SDCR_DO_EN)))
            {
                outpw(REG_SDISR, SDISR_BLKD_IF);
                break;
            }
#endif
            if (pSD == pSD0)
                fmiSD_CardStatus();
            if (pSD->bIsCardInsert == FALSE)
                return FMI_NO_SD_CARD;

            /* Call schedule() to release CPU power to other tasks during waiting SIC/DMA completed. */
            schedule();
        }

        if ((inpw(REG_SDISR) & SDISR_CRC_IF) != 0)      // check CRC
        {
#ifdef DEBUG
            sysprintf("2. fmiSD_Write:write data error [SDISR = 0x%08X]\n", inpw(REG_SDISR));
#endif
            outpw(REG_SDISR, SDISR_CRC_IF);
            return FMI_SD_CRC_ERROR;
        }
    }
    outpw(REG_SDISR, SDISR_CRC_IF);

    if (fmiSDCmdAndRsp(pSD, 12, 0, 0))      // stop command
    {
#ifdef DEBUG
        sysprintf("stop command fail !!\n");
#endif
        return FMI_SD_CRC7_ERROR;
    }
    fmiCheckRB();

    fmiSDCommand(pSD, 7, 0);

    // According to SD spec v2.0 chapter 4.4,
    // "After the last SD Memory Card bus transaction, the host is required,
    //  to provide 8 (eight) clock cycles for the card to complete the
    //  operation before shutting down the clock."
    outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);

    return Successful;
}


VOID fmiGet_SD_info(FMI_SD_INFO_T *pSD, DISK_DATA_T *_info)
{
    unsigned int i;
    unsigned int R_LEN, C_Size, MULT, size;
    unsigned int Buffer[4];
    unsigned char *ptr;
    int volatile status;

    fmiSDCmdAndRsp2(pSD, 9, pSD->uRCA, Buffer);

#ifdef DEBUG
    sysprintf("max. data transfer rate [%x][%08x]\n", Buffer[0]&0xff, Buffer[0]);
    sysprintf("CSD = 0x%08X 0x%08X 0x%08X 0x%08X\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
#endif

    if ((pSD->uCardType == FMI_TYPE_MMC) || (pSD->uCardType == FMI_TYPE_MMC_SECTOR_MODE))
    {
        // for MMC/eMMC card
        if ((Buffer[0] & 0xc0000000) == 0xc0000000)
        {
            // CSD_STRUCTURE [127:126] is 3
            // CSD version depend on EXT_CSD register in eMMC v4.4 for card size > 2GB
            fmiSDCmdAndRsp(pSD, 7, pSD->uRCA, 0);

            _fmi_pSDHCBuffer = (UINT8 *)((UINT32)_fmi_ucSDHCBuffer | 0x80000000);
            outpw(REG_DMACSAR, (UINT32)_fmi_pSDHCBuffer);   // set DMA transfer starting address
            outpw(REG_SDBLEN, 511);     // read 512 bytes for EXT_CSD
            if ((status = fmiSDCmdAndRspDataIn(pSD, 8, 0x00)) != Successful)
                return;

            fmiSDCommand(pSD, 7, 0);

            // According to SD spec v2.0 chapter 4.4,
            // "After the last SD Memory Card bus transaction, the host is required,
            //  to provide 8 (eight) clock cycles for the card to complete the
            //  operation before shutting down the clock."
            outpw(REG_SDCR, inpw(REG_SDCR)|SDCR_8CLK_OE);

            _info->totalSectorN = (*(UINT32 *)(_fmi_pSDHCBuffer+212));
            _info->diskSize = _info->totalSectorN / 2;
        }
        else
        {
            // CSD version v1.0/1.1/1.2 in eMMC v4.4 spec for card size <= 2GB
            R_LEN = (Buffer[1] & 0x000f0000) >> 16;
            C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30);
            MULT = (Buffer[2] & 0x00038000) >> 15;
            size = (C_Size+1) * (1<<(MULT+2)) * (1<<R_LEN);

            _info->diskSize = size / 1024;
            _info->totalSectorN = size / 512;
        }
    }
    else
    {
        // for SD/SDHC card
        if ((Buffer[0] & 0xc0000000) && (pSD->uCardType != FMI_TYPE_MMC))
        {
            // CSD version 2.0 in SD v2.0 spec for SDHC card
            C_Size = ((Buffer[1] & 0x0000003f) << 16) | ((Buffer[2] & 0xffff0000) >> 16);
            size = (C_Size+1) * 512;    // Kbytes
    
            _info->diskSize = size;
            _info->totalSectorN = size << 1;
        }
        else
        {
            // CSD version 1.0 in SD v2.0 spec for SD card
            R_LEN = (Buffer[1] & 0x000f0000) >> 16;
            C_Size = ((Buffer[1] & 0x000003ff) << 2) | ((Buffer[2] & 0xc0000000) >> 30);
            MULT = (Buffer[2] & 0x00038000) >> 15;
            size = (C_Size+1) * (1<<(MULT+2)) * (1<<R_LEN);
    
            _info->diskSize = size / 1024;
            _info->totalSectorN = size / 512;
        }
    }
    _info->sectorSize = 512;

    g_max_valid_sector = _info->totalSectorN;

    fmiSDCmdAndRsp2(pSD, 10, pSD->uRCA, Buffer);

    _info->vendor[0] = (Buffer[0] & 0xff000000) >> 24;
    ptr = (unsigned char *)Buffer;
    ptr = (unsigned char *)Buffer + 3;
    for (i=0; i<5; i++)
        _info->product[i] = *ptr++;
    ptr = (unsigned char *)Buffer + 9;
    for (i=0; i<4; i++)
        _info->serial[i] = *ptr++;

#ifdef DEBUG
    sysprintf("SD card CID is %08X-%08X-%08X-%08X\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
#endif
}
#if 0
INT  fmiSD_CardStatus()
{
    if (g_SD0_card_detect)
    {
        if (inpw(REG_SDISR) & SDISR_CD_Card)    // CD pin status
        {
            pSD0->bIsCardInsert = FALSE;
            return FMI_NO_SD_CARD;
        }
        else
        {
            pSD0->bIsCardInsert = TRUE;
            return 0;
        }
    }
    else
    {
        pSD0->bIsCardInsert = TRUE;     // always report card inserted.
        return 0;
    }
}
#define DISK_TYPE_SD_MMC                   0x00000020

INT  fmiInitSDDevice(INT cardSel)   /* int sd_init_onedisk(INT i) */
{
    PDISK_T *pDisk;
    DISK_DATA_T* pSDDisk;
    FMI_SD_INFO_T *pSD_temp = NULL;

    int volatile rate, i;

    if(sd0_ok)
            SD_DiskInfo0.totalSectorN;
    
    //Reset FMI
    outpw(REG_FMICR, FMI_SWRST);        // Start reset FMI controller.
    while(inpw(REG_FMICR)&FMI_SWRST);

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_SWRST);   // SD software reset
    while(inpw(REG_SDCR) & SDCR_SWRST);

    outpw(REG_SDCR, inpw(REG_SDCR) & ~0xFF);        // disable SD clock ouput

    if (cardSel == 0)
    {
        if(sd0_ok == 1)
            return(0);
        pSDDisk = &SD_DiskInfo0;
    }
    else if (cardSel == 1)
    {
        if(sd1_ok == 1)
            return(0);
        pSDDisk = &SD_DiskInfo1;
    }
    else if (cardSel == 2)
    {
        if(sd2_ok == 1)
            return(0);
        pSDDisk = &SD_DiskInfo2;
    }

    // enable SD-0/1/2 pin?
    if (fmiSD_CardSel(cardSel))
        return FMI_NO_SD_CARD;

    //Enable SD-0 card detectipn pin
    if (cardSel==0)
    {
        if (g_SD0_card_detect)
            outpw(REG_GPAFUN, inpw(REG_GPAFUN) | MF_GPA1);  // GPA1 for SD-0 card detection
        outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CDSRC);    // SD card detection source from GPIO but not DAT3
    }

    // Disable FMI/SD host interrupt
    outpw(REG_FMIIER, 0);

//  outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_SDNWR) | (0x01 << 24));     // set SDNWR = 1
    outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_SDNWR) | (0x09 << 24));     // set SDNWR = 9
    outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_BLKCNT) | (0x01 << 16));    // set BLKCNT = 1
    outpw(REG_SDCR, inpw(REG_SDCR) & ~SDCR_DBW);        // SD 1-bit data bus

    outpw(REG_SDTMOUT,0xFFFFFF);


    pSD_temp = (FMI_SD_INFO_T *)malloc(sizeof(FMI_SD_INFO_T)+4);
    if (pSD_temp == NULL)
        return FMI_NO_MEMORY;

    memset((char *)pSD_temp, 0, sizeof(FMI_SD_INFO_T)+4);

    if (cardSel==0)
    {
        pSD0_offset = (UINT32)pSD_temp %4;
        pSD0 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD0_offset);
    }
    else if (cardSel==1)
    {
        pSD1_offset = (UINT32)pSD_temp %4;
        pSD1 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD1_offset);
    }
    else if (cardSel==2)
    {
        pSD2_offset = (UINT32)pSD_temp %4;
        pSD2 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD2_offset);
    }

    outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CDSRC);    // select GPIO detect
    outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CD_IEN);   // enable card detect interrupt

    if (cardSel==0)
    {
        if (fmiSD_CardStatus() == FMI_NO_SD_CARD)
        {
            if (pSD0 != NULL)
            {
                free((FMI_SD_INFO_T *)((UINT32)pSD0 - pSD0_offset));
                pSD0 = 0;
            }
            free((FMI_SD_INFO_T *)((UINT32)pSD0 - pSD0_offset));
            sysprintf("ERROR: fmiInitSDDevice(): SD port %d has no card ! REG_SDISR = 0x%08X\n", cardSel, inpw(REG_SDISR));
            return FMI_NO_SD_CARD;
        }

        if (fmiSD_Init(pSD0) < 0)
            return FMI_SD_INIT_ERROR;

        /* divider */
        if (pSD0->uCardType == FMI_TYPE_MMC)
            rate = _fmi_uFMIReferenceClock / MMC_FREQ;
        else if (pSD0->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
            rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
        else
            rate = _fmi_uFMIReferenceClock / SD_FREQ;

        if (pSD0->uCardType == FMI_TYPE_MMC)
        {
            if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
                rate ++;
        }
        else if (pSD0->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
        {
            if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
                rate ++;
        }
        else
        {
            if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
                rate ++;
        }
    }
    else if (cardSel==1)
    {
        // SD-1 no card detect
        pSD1->bIsCardInsert = TRUE;

        // SD-1 initial
        if (fmiSD_Init(pSD1) < 0)
            return FMI_SD_INIT_ERROR;

        /* divider */
        if (pSD1->uCardType == FMI_TYPE_MMC)
            rate = _fmi_uFMIReferenceClock / MMC_FREQ;
        else if (pSD1->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
            rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
        else
            rate = _fmi_uFMIReferenceClock / SD_FREQ;

        if (pSD1->uCardType == FMI_TYPE_MMC)
        {
            if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
                rate ++;
        }
        else if (pSD1->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
        {
            if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
                rate ++;
        }
        else
        {
            if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
                rate ++;
        }
    }
    else if (cardSel==2)
    {
        // SD-2 no card detect
        pSD2->bIsCardInsert = TRUE;

        // SD-2 initial
        if (fmiSD_Init(pSD2) < 0)
            return FMI_SD_INIT_ERROR;

        /* divider */
        if (pSD2->uCardType == FMI_TYPE_MMC)
            rate = _fmi_uFMIReferenceClock / MMC_FREQ;
        else if (pSD2->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
            rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
        else
            rate = _fmi_uFMIReferenceClock / SD_FREQ;

        if (pSD2->uCardType == FMI_TYPE_MMC)
        {
            if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
                rate ++;
        }
        else if (pSD2->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
        {
            if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
                rate ++;
        }
        else
        {
            if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
                rate ++;
        }
    }

    for(i=0; i<100; i++);

    outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_S) | (0x03 << 19));     // SD clock from UPLL
    outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N0) | (0x01 << 16));    // SD clock divided by 2
    if (rate % 2)
    {
        rate /= 2;
        rate &= 0xFF;
    }
    else
    {
        rate /= 2;
        rate &= 0xFF;
        rate--;
    }
    outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N1) | (rate << 24));    // SD clock divider

    for(i=0; i<1000; i++);

    /* init SD interface */
    if (cardSel==0)
    {
        fmiGet_SD_info(pSD0, pSDDisk);
        if (fmiSelectCard(pSD0))
            return FMI_SD_SELECT_ERROR;
    }
    else if (cardSel==1)
    {
        fmiGet_SD_info(pSD1, pSDDisk);
        if (fmiSelectCard(pSD1))
            return FMI_SD_SELECT_ERROR;
    }
    else if (cardSel==2)
    {
        fmiGet_SD_info(pSD2, pSDDisk);
        if (fmiSelectCard(pSD2))
            return FMI_SD_SELECT_ERROR;
    }

    /*
     * Create physical disk descriptor
     */
    pDisk = (PDISK_T *)malloc(sizeof(PDISK_T));
    if (pDisk == NULL)
        return FMI_NO_MEMORY;
    memset((char *)pDisk, 0, sizeof(PDISK_T));

    /* read Disk information */
    pDisk->szManufacture[0] = '\0';
    strcpy(pDisk->szProduct, (char *)pSDDisk->product);
    strcpy(pDisk->szSerialNo, (char *)pSDDisk->serial);


    pDisk->nDiskType = DISK_TYPE_SD_MMC;

    pDisk->nPartitionN = 0;
    //pDisk->ptPartList = NULL;

    pDisk->nSectorSize = 512;
    pDisk->uTotalSectorN = pSDDisk->totalSectorN;
    pDisk->uDiskSize = pSDDisk->diskSize;

    /* create relationship between UMAS device and file system hard disk device */


#ifdef DEBUG
    printf("SD disk found: size=%d MB\n", (int)pDisk->uDiskSize / 1024);
#endif


    if (cardSel == 0)
        sd0_ok = 1;
    else if (cardSel == 1)
        sd1_ok = 1;
    else if (cardSel == 2)
        sd2_ok = 1;

    return pDisk->uTotalSectorN;
}
#endif

INT  fmiSD_CardSel00(INT cardSel)
{
    if (cardSel==0)
    {
        outpw(REG_GPEFUN, inpw(REG_GPEFUN)&(~0x0000FFF0) | 0x0000aaa0); // SD0_CLK/CMD/DAT0_3 pins selected
        outpw(REG_SDCR, inpw(REG_SDCR) & (~SDCR_SDPORT));               // SD_0 port selected
    }
    else if (cardSel==1)
    {
        outpw(REG_GPBFUN, inpw(REG_GPBFUN)&(~0x00000FFF) | 0x00000AAA); // SD1_CLK_CMD_DAT0_3 pins selected
        outpw(REG_SDCR, inpw(REG_SDCR) & (~0x60000000) | 0x20000000);   // SD_1 port selected
    }
    else if (cardSel==2)
    {
        outpw(REG_GPEFUN, inpw(REG_GPEFUN)&(~0x000F0000) | 0x00050000); // SD2_DAT0_1 pins selected
        outpw(REG_GPDFUN, inpw(REG_GPDFUN)&(~0x0003FC00) | 0x00015400); // SD2_CLK/CMD/DAT2_3 pins selected
        outpw(REG_SDCR, inpw(REG_SDCR) & (~0x60000000) | 0x40000000);   // SD_2 port selected
    }
    else
        return 1;   // wrong SD card select

    //--- 2014/2/26, Reset SD controller and DMAC to keep clean status for next access.
    // Reset DMAC engine and interrupt satus
    outpw(REG_DMACCSR, inpw(REG_DMACCSR) | DMAC_SWRST | DMAC_EN);
    while(inpw(REG_DMACCSR) & DMAC_SWRST);
    outpw(REG_DMACCSR, inpw(REG_DMACCSR) | DMAC_EN);
    outpw(REG_DMACISR, WEOT_IF | TABORT_IF);    // clear all interrupt flag

    // Reset FMI engine and interrupt status
    outpw(REG_FMICR, FMI_SWRST);
    while(inpw(REG_FMICR) & FMI_SWRST);
    outpw(REG_FMIISR, FMI_DAT_IF);              // clear all interrupt flag

    // Reset SD engine and interrupt status
    outpw(REG_FMICR, FMI_SD_EN);
    outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_SWRST);
    while(inpw(REG_SDCR) & SDCR_SWRST);
    outpw(REG_SDISR, 0xFFFFFFFF);               // clear all interrupt flag

    return 0;
}
INT sicSdRead00(INT32 sdSectorNo, INT32 sdSectorCount, INT32 sdTargetAddr)
{
    if (fmiSD_CardSel(0))
        return FMI_NO_SD_CARD;

    return fmiSD_Read(sdSectorNo, sdSectorCount, sdTargetAddr);
}

INT  fmiSD_Read00(UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr)
{
    int status=0;

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Read_in(pSD0, uSector, uBufcnt, uDAddr);

    return status;
}

INT  fmiSD_Write00(UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr)
{
    int status=0;

        if (fmiSD_CardSel(0))
        return FMI_NO_SD_CARD;
    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Write_in(pSD0, uSector, uBufcnt, uSAddr);

    return status;
}
UINT32 SdGetTotalSector()
{
       return  0;
}
/*-----------------------------------------------------------------------------
 * Get SD card status for SD port 0 and assign the status to global value pSD0->bIsCardInsert.
 * Return:  0              is SD card inserted;
 *          FMI_NO_SD_CARD is SD card removed.
 *---------------------------------------------------------------------------*/
INT  fmiSD_CardStatus()
{
    if (g_SD0_card_detect)
    {
        if (inpw(REG_SDISR) & SDISR_CD_Card)    // CD pin status
        {
            pSD0->bIsCardInsert = FALSE;
            return FMI_NO_SD_CARD;
        }
        else
        {
            pSD0->bIsCardInsert = TRUE;
            return 0;
        }
    }
    else
    {
        pSD0->bIsCardInsert = TRUE;     // always report card inserted.
        return 0;
    }
}



sd.h  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

#ifndef _SD_H
#define _SD_H
#include "Common.h"

INT  fmiSD_Read(UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr);
INT  fmiSD_Write(UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr);
INT  fmiInitSDDevice(int cardSel);
VOID fmiInitDevice(VOID);
UINT32 SdGetTotalSector(VOID);
#endif


SDGlue.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential                                       */
/*                                                                                   */
/* Copyright (c) 2008 by Nuvoton Technology Corporation                              */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
/*
 * Driver for FMI devices
 * SD layer glue code
 *
 */
#if 1
#ifdef ECOS
    #include "stdlib.h"
    #include "string.h"
    #include "drv_api.h"
    #include "diag.h"
    #include "wbtypes.h"
    #include "wbio.h"
#else
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "wblib.h"
#endif

#include "w55fa93_reg.h"
#include "w55fa93_sic.h"
#include "fmi.h"
#include "nvtfat.h"

FMI_SD_INFO_T *pSD0 = NULL;
FMI_SD_INFO_T *pSD1 = NULL;
FMI_SD_INFO_T *pSD2 = NULL;

UINT8 pSD0_offset = 0;
UINT8 pSD1_offset = 0;
UINT8 pSD2_offset = 0;

PDISK_T *pDisk_SD0 = NULL;
PDISK_T *pDisk_SD1 = NULL;
PDISK_T *pDisk_SD2 = NULL;

extern DISK_DATA_T SD_DiskInfo0;
extern DISK_DATA_T SD_DiskInfo1;
extern DISK_DATA_T SD_DiskInfo2;

INT32 g_SD0_card_detect = FALSE;    // default is DISABLE SD0 card detect feature.

extern INT  fsPhysicalDiskConnected(PDISK_T *pDisk);


static INT  sd_disk_init(PDISK_T  *lDisk)
{
    return 0;
}


static INT  sd_disk_ioctl(PDISK_T *lDisk, INT control, VOID *param)
{
    return 0;
}

static INT  sd_disk_read(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff)
{
    int status;

    fmiSD_CardSel(0);

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Read_in(pSD0, sector_no, number_of_sector, (unsigned int)buff);

    if (status != Successful)
        return status;

    return FS_OK;
}

static INT  sd_disk_write(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff, BOOL IsWait)
{
    int status;

    fmiSD_CardSel(0);

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Write_in(pSD0, sector_no, number_of_sector, (unsigned int)buff);

    if (status != Successful)
        return status;

    return FS_OK;
}

static INT  sd_disk_init0(PDISK_T  *lDisk)
{
    return 0;
}

static INT  sd_disk_ioctl0(PDISK_T *lDisk, INT control, VOID *param)
{
    return 0;
}

static INT  sd_disk_read0(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff)
{
    return sd_disk_read(pDisk, sector_no, number_of_sector, buff);
}

static INT  sd_disk_write0(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff, BOOL IsWait)
{
    return sd_disk_write(pDisk, sector_no, number_of_sector, buff, IsWait);
}

static INT  sd_disk_init1(PDISK_T  *lDisk)
{
    return 0;
}

static INT  sd_disk_ioctl1(PDISK_T *lDisk, INT control, VOID *param)
{
    return 0;
}

static INT  sd_disk_read1(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff)
{
    int status;

    fmiSD_CardSel(1);

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Read_in(pSD1, sector_no, number_of_sector, (unsigned int)buff);

    if (status != Successful)
        return status;

    return FS_OK;
}

static INT  sd_disk_write1(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff, BOOL IsWait)
{
    int status;

    fmiSD_CardSel(1);

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Write_in(pSD1, sector_no, number_of_sector, (unsigned int)buff);

    if (status != Successful)
        return status;

    return FS_OK;
}

static INT  sd_disk_init2(PDISK_T  *lDisk)
{
    return 0;
}

static INT  sd_disk_ioctl2(PDISK_T *lDisk, INT control, VOID *param)
{
    return 0;
}

static INT  sd_disk_read2(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff)
{
    int status;

    fmiSD_CardSel(2);

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Read_in(pSD2, sector_no, number_of_sector, (unsigned int)buff);

    if (status != Successful)
        return status;

    return FS_OK;
}

static INT  sd_disk_write2(PDISK_T *pDisk, UINT32 sector_no, INT number_of_sector, UINT8 *buff, BOOL IsWait)
{
    int status;

    fmiSD_CardSel(2);

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Write_in(pSD2, sector_no, number_of_sector, (unsigned int)buff);

    if (status != Successful)
        return status;

    return FS_OK;
}

STORAGE_DRIVER_T  _SDDiskDriver =
{
    sd_disk_init,
    sd_disk_read,
    sd_disk_write,
    sd_disk_ioctl
};

STORAGE_DRIVER_T  _SD0DiskDriver =
{
    sd_disk_init0,
    sd_disk_read0,
    sd_disk_write0,
    sd_disk_ioctl0
};

STORAGE_DRIVER_T  _SD1DiskDriver =
{
    sd_disk_init1,
    sd_disk_read1,
    sd_disk_write1,
    sd_disk_ioctl1
};

STORAGE_DRIVER_T  _SD2DiskDriver =
{
    sd_disk_init2,
    sd_disk_read2,
    sd_disk_write2,
    sd_disk_ioctl2
};

static int sd0_ok = 0;
static int sd1_ok = 0;
static int sd2_ok = 0;

INT  fmiSD_CardSel(INT cardSel)
{
    if (cardSel==0)
    {
        outpw(REG_GPEFUN, inpw(REG_GPEFUN)&(~0x0000FFF0) | 0x0000aaa0); // SD0_CLK/CMD/DAT0_3 pins selected
        outpw(REG_SDCR, inpw(REG_SDCR) & (~SDCR_SDPORT));               // SD_0 port selected
    }
    else if (cardSel==1)
    {
        outpw(REG_GPBFUN, inpw(REG_GPBFUN)&(~0x00000FFF) | 0x00000AAA); // SD1_CLK_CMD_DAT0_3 pins selected
        outpw(REG_SDCR, inpw(REG_SDCR) & (~0x60000000) | 0x20000000);   // SD_1 port selected
    }
    else if (cardSel==2)
    {
        outpw(REG_GPEFUN, inpw(REG_GPEFUN)&(~0x000F0000) | 0x00050000); // SD2_DAT0_1 pins selected
        outpw(REG_GPDFUN, inpw(REG_GPDFUN)&(~0x0003FC00) | 0x00015400); // SD2_CLK/CMD/DAT2_3 pins selected
        outpw(REG_SDCR, inpw(REG_SDCR) & (~0x60000000) | 0x40000000);   // SD_2 port selected
    }
    else
        return 1;   // wrong SD card select

    //--- 2014/2/26, Reset SD controller and DMAC to keep clean status for next access.
    // Reset DMAC engine and interrupt satus
    outpw(REG_DMACCSR, inpw(REG_DMACCSR) | DMAC_SWRST | DMAC_EN);
    while(inpw(REG_DMACCSR) & DMAC_SWRST);
    outpw(REG_DMACCSR, inpw(REG_DMACCSR) | DMAC_EN);
    outpw(REG_DMACISR, WEOT_IF | TABORT_IF);    // clear all interrupt flag

    // Reset FMI engine and interrupt status
    outpw(REG_FMICR, FMI_SWRST);
    while(inpw(REG_FMICR) & FMI_SWRST);
    outpw(REG_FMIISR, FMI_DAT_IF);              // clear all interrupt flag

    // Reset SD engine and interrupt status
    outpw(REG_FMICR, FMI_SD_EN);
    outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_SWRST);
    while(inpw(REG_SDCR) & SDCR_SWRST);
    outpw(REG_SDISR, 0xFFFFFFFF);               // clear all interrupt flag

    return 0;
}

INT  fmiInitSDDevice(INT cardSel)   /* int sd_init_onedisk(INT i) */
{
    PDISK_T *pDisk;
    DISK_DATA_T* pSDDisk;
    FMI_SD_INFO_T *pSD_temp = NULL;

    int volatile rate, i;

    //Reset FMI
    outpw(REG_FMICR, FMI_SWRST);        // Start reset FMI controller.
    while(inpw(REG_FMICR)&FMI_SWRST);

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    outpw(REG_SDCR, inpw(REG_SDCR) | SDCR_SWRST);   // SD software reset
    while(inpw(REG_SDCR) & SDCR_SWRST);

    outpw(REG_SDCR, inpw(REG_SDCR) & ~0xFF);        // disable SD clock ouput

    if (cardSel == 0)
    {
        if(sd0_ok == 1)
            return(0);
        pSDDisk = &SD_DiskInfo0;
    }
    else if (cardSel == 1)
    {
        if(sd1_ok == 1)
            return(0);
        pSDDisk = &SD_DiskInfo1;
    }
    else if (cardSel == 2)
    {
        if(sd2_ok == 1)
            return(0);
        pSDDisk = &SD_DiskInfo2;
    }

    // enable SD-0/1/2 pin?
    if (fmiSD_CardSel(cardSel))
        return FMI_NO_SD_CARD;

    //Enable SD-0 card detectipn pin
    if (cardSel==0)
    {
        if (g_SD0_card_detect)
            outpw(REG_GPAFUN, inpw(REG_GPAFUN) | MF_GPA1);  // GPA1 for SD-0 card detection
        outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CDSRC);    // SD card detection source from GPIO but not DAT3
    }

    // Disable FMI/SD host interrupt
    outpw(REG_FMIIER, 0);

//  outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_SDNWR) | (0x01 << 24));     // set SDNWR = 1
    outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_SDNWR) | (0x09 << 24));     // set SDNWR = 9
    outpw(REG_SDCR, (inpw(REG_SDCR) & ~SDCR_BLKCNT) | (0x01 << 16));    // set BLKCNT = 1
    outpw(REG_SDCR, inpw(REG_SDCR) & ~SDCR_DBW);        // SD 1-bit data bus

    outpw(REG_SDTMOUT,0xFFFFFF);


    pSD_temp = malloc(sizeof(FMI_SD_INFO_T)+4);
    if (pSD_temp == NULL)
        return FMI_NO_MEMORY;

    memset((char *)pSD_temp, 0, sizeof(FMI_SD_INFO_T)+4);

    if (cardSel==0)
    {
        pSD0_offset = (UINT32)pSD_temp %4;
        pSD0 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD0_offset);
    }
    else if (cardSel==1)
    {
        pSD1_offset = (UINT32)pSD_temp %4;
        pSD1 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD1_offset);
    }
    else if (cardSel==2)
    {
        pSD2_offset = (UINT32)pSD_temp %4;
        pSD2 = (FMI_SD_INFO_T *)((UINT32)pSD_temp + pSD2_offset);
    }

    outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CDSRC);    // select GPIO detect
    outpw(REG_SDIER, inpw(REG_SDIER) | SDIER_CD_IEN);   // enable card detect interrupt

    if (cardSel==0)
    {
        if (fmiSD_CardStatus() == FMI_NO_SD_CARD)
        {
            if (pSD0 != NULL)
            {
                free((FMI_SD_INFO_T *)((UINT32)pSD0 - pSD0_offset));
                pSD0 = 0;
            }
            free((FMI_SD_INFO_T *)((UINT32)pSD0 - pSD0_offset));
            sysprintf("ERROR: fmiInitSDDevice(): SD port %d has no card ! REG_SDISR = 0x%08X\n", cardSel, inpw(REG_SDISR));
            return FMI_NO_SD_CARD;
        }

        if (fmiSD_Init(pSD0) < 0)
            return FMI_SD_INIT_ERROR;

        /* divider */
        if (pSD0->uCardType == FMI_TYPE_MMC)
            rate = _fmi_uFMIReferenceClock / MMC_FREQ;
        else if (pSD0->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
            rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
        else
            rate = _fmi_uFMIReferenceClock / SD_FREQ;

        if (pSD0->uCardType == FMI_TYPE_MMC)
        {
            if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
                rate ++;
        }
        else if (pSD0->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
        {
            if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
                rate ++;
        }
        else
        {
            if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
                rate ++;
        }
    }
    else if (cardSel==1)
    {
        // SD-1 no card detect
        pSD1->bIsCardInsert = TRUE;

        // SD-1 initial
        if (fmiSD_Init(pSD1) < 0)
            return FMI_SD_INIT_ERROR;

        /* divider */
        if (pSD1->uCardType == FMI_TYPE_MMC)
            rate = _fmi_uFMIReferenceClock / MMC_FREQ;
        else if (pSD1->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
            rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
        else
            rate = _fmi_uFMIReferenceClock / SD_FREQ;

        if (pSD1->uCardType == FMI_TYPE_MMC)
        {
            if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
                rate ++;
        }
        else if (pSD1->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
        {
            if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
                rate ++;
        }
        else
        {
            if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
                rate ++;
        }
    }
    else if (cardSel==2)
    {
        // SD-2 no card detect
        pSD2->bIsCardInsert = TRUE;

        // SD-2 initial
        if (fmiSD_Init(pSD2) < 0)
            return FMI_SD_INIT_ERROR;

        /* divider */
        if (pSD2->uCardType == FMI_TYPE_MMC)
            rate = _fmi_uFMIReferenceClock / MMC_FREQ;
        else if (pSD2->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
            rate = _fmi_uFMIReferenceClock / EMMC_FREQ;
        else
            rate = _fmi_uFMIReferenceClock / SD_FREQ;

        if (pSD2->uCardType == FMI_TYPE_MMC)
        {
            if ((_fmi_uFMIReferenceClock % MMC_FREQ) > 0)
                rate ++;
        }
        else if (pSD2->uCardType == FMI_TYPE_MMC_SECTOR_MODE)
        {
            if ((_fmi_uFMIReferenceClock % EMMC_FREQ) > 0)
                rate ++;
        }
        else
        {
            if ((_fmi_uFMIReferenceClock % SD_FREQ) > 0)
                rate ++;
        }
    }

    for(i=0; i<100; i++);

    outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_S) | (0x03 << 19));     // SD clock from UPLL
    outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N0) | (0x01 << 16));    // SD clock divided by 2
    if (rate % 2)
    {
        rate /= 2;
        rate &= 0xFF;
    }
    else
    {
        rate /= 2;
        rate &= 0xFF;
        rate--;
    }
    outpw(REG_CLKDIV2, (inpw(REG_CLKDIV2) & ~SD_N1) | (rate << 24));    // SD clock divider

    for(i=0; i<1000; i++);

    /* init SD interface */
    if (cardSel==0)
    {
        fmiGet_SD_info(pSD0, pSDDisk);
        if (fmiSelectCard(pSD0))
            return FMI_SD_SELECT_ERROR;
    }
    else if (cardSel==1)
    {
        fmiGet_SD_info(pSD1, pSDDisk);
        if (fmiSelectCard(pSD1))
            return FMI_SD_SELECT_ERROR;
    }
    else if (cardSel==2)
    {
        fmiGet_SD_info(pSD2, pSDDisk);
        if (fmiSelectCard(pSD2))
            return FMI_SD_SELECT_ERROR;
    }

    /*
     * Create physical disk descriptor
     */
    pDisk = malloc(sizeof(PDISK_T));
    if (pDisk == NULL)
        return FMI_NO_MEMORY;
    memset((char *)pDisk, 0, sizeof(PDISK_T));

    /* read Disk information */
    pDisk->szManufacture[0] = '\0';
    strcpy(pDisk->szProduct, (char *)pSDDisk->product);
    strcpy(pDisk->szSerialNo, (char *)pSDDisk->serial);


    pDisk->nDiskType = DISK_TYPE_SD_MMC;

    pDisk->nPartitionN = 0;
    //pDisk->ptPartList = NULL;

    pDisk->nSectorSize = 512;
    pDisk->uTotalSectorN = pSDDisk->totalSectorN;
    pDisk->uDiskSize = pSDDisk->diskSize;

    /* create relationship between UMAS device and file system hard disk device */

    if (cardSel==0)
        pDisk->ptDriver = &_SD0DiskDriver;
    else if (cardSel==1)
        pDisk->ptDriver = &_SD1DiskDriver;
    else if (cardSel==2)
        pDisk->ptDriver = &_SD2DiskDriver;

#ifdef DEBUG
    printf("SD disk found: size=%d MB\n", (int)pDisk->uDiskSize / 1024);
#endif

    if (cardSel==0)
    {
        pDisk_SD0 = pDisk;
    }
    else if (cardSel==1)
    {
        pDisk_SD1 = pDisk;
    }
    else if (cardSel==2)
    {
        pDisk_SD2 = pDisk;
    }


    //fsPhysicalDiskConnected(pDisk);

    if (cardSel == 0)
        sd0_ok = 1;
    else if (cardSel == 1)
        sd1_ok = 1;
    else if (cardSel == 2)
        sd2_ok = 1;

    return pDisk->uTotalSectorN;
}

INT  fmiSD_Read(UINT32 uSector, UINT32 uBufcnt, UINT32 uDAddr)
{
    int status=0;

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Read_in(pSD0, uSector, uBufcnt, uDAddr);

    return status;
}

INT  fmiSD_Write(UINT32 uSector, UINT32 uBufcnt, UINT32 uSAddr)
{
    int status=0;

    // enable SD
    outpw(REG_FMICR, FMI_SD_EN);
    status = fmiSD_Write_in(pSD0, uSector, uBufcnt, uSAddr);

    return status;
}

/*-----------------------------------------------------------------------------------*/
/* Function:                                                                         */
/*   sicSdOpen                                                                       */
/*                                                                                   */
/* Parameters:                                                                       */
/*   sdPortNo               SD port number(port0 or port1).                          */
/*                                                                                   */
/* Returns:                                                                          */
/*   >0                     Total sector.                                            */
/*   FMI_NO_SD_CARD         No SD card insert.                                       */
/*   FMI_SD_INIT_ERROR      Card initial and identify error.                         */
/*   FMI_SD_SELECT_ERROR    Select card from identify mode to stand-by mode error.   */
/*                                                                                   */
/* Side effects:                                                                     */
/*   None.                                                                           */
/*                                                                                   */
/* Description:                                                                      */
/*   This function initial SD from identification to stand-by mode.                  */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
INT sicSdOpen_sel(INT cardSel)
{
    return fmiInitSDDevice(cardSel);
}

INT sicSdOpen(void)
{
    return fmiInitSDDevice(0);
}

INT sicSdOpen0(void)
{
    return fmiInitSDDevice(0);
}

INT sicSdOpen1(void)
{
    return fmiInitSDDevice(1);
}

INT sicSdOpen2(void)
{
    return fmiInitSDDevice(2);
}
#endif


Smpl_Pdma_SPI.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "wblib.h"
#include "w55fa93_edma.h"
#include "w55fa93_gpio.h"
#include "w55fa93_spi.h"

#define TEST_SIZE    4 * 1024
__align(4096) UINT8 WriteBuffer[TEST_SIZE];
__align(4096) UINT8 ReadBuffer[TEST_SIZE];

static INT32 g_PdmaCh = 0;
volatile static BOOL g_bPdmaInt = FALSE;

void SPI_SwitchToTPH() {

        //1.spi_in config to GPIO
        outpw(REG_GPBFUN , inpw(REG_GPBFUN)  & (~BIT23) & (~BIT22)); //B11 latch
        gpio_setportdir(GPIO_PORTB, BIT11, BIT11);

        //2.config freq
        outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | (1 << 11));//clk idle high
        outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & (~(1 << 10)));//MSB first
        outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) &  (~(0x1f << 3)));
        outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | (8 << 3));//8 BIT
        outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & (~(1 << 2)));//tx on rising
#if defined(CPU_144MHZ_MODE)
        spiIoctl(1, SPI_SET_CLOCK, 72, 9000);
#else
        spiIoctl(1, SPI_SET_CLOCK, /*96*/48, 8000); // ch_20220802 : APB clock should be 48.
#endif
        spiTxLen(1, 0, 8);
        //2.close cs0
        //outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);
        //spiTxLen(0, 0, 8);
}

void SPI_SwitchToFlash(VOID)
{

#if defined(CPU_144MHZ_MODE)
    spiIoctl(0, 0, 72, 18000);
#else
    spiIoctl(0, 0, 48/*96*/, 12000); // ch_20220802 : APB clock should be 48.
#endif
    //Startup SPI0 multi-function features, chip select using SS0
    outpw(REG_GPDFUN, inpw(REG_GPDFUN) | 0xFF000000);
    outpw(REG_SPI0_SSR, 0x00);     // CS active low
    outpw(REG_SPI0_CNTRL, 0x04); // Tx: falling edge, Rx: rising edge
}

void PdmaCallback_SPI(unsigned int arg)
{     
    EDMA_Free(g_PdmaCh);      
    g_bPdmaInt = TRUE;
}

int initSPIPDMA_Write(UINT32 src_addr, UINT32 dma_length)
{
    
    g_PdmaCh = PDMA_FindandRequest();
    EDMA_SetAPB(g_PdmaCh,            //int channel, 
                        eDRVEDMA_SPIMS0,            //E_DRVEDMA_APB_DEVICE eDevice, 
                        eDRVEDMA_WRITE_APB,        //E_DRVEDMA_APB_RW eRWAPB, 
                        eDRVEDMA_WIDTH_32BITS);    //E_DRVEDMA_TRANSFER_WIDTH eTransferWidth    

    EDMA_SetupHandlers(g_PdmaCh,         //int channel
                        eDRVEDMA_BLKD,             //int interrupt,    
                        PdmaCallback_SPI,                 //void (*irq_handler) (void *),
                        NULL);                    //void *data

    EDMA_SetWrapINTType(g_PdmaCh , NULL);                                

    EDMA_SetDirection(g_PdmaCh , eDRVEDMA_DIRECTION_INCREMENTED, eDRVEDMA_DIRECTION_FIXED);


    EDMA_SetupSingle(g_PdmaCh,        // int channel, 
                                src_addr,        // unsigned int src_addr,  (ADC data port physical address) 
                                REG_SPI0_TX0, //phaddrrecord,        // unsigned int dest_addr,
                                dma_length);    // unsigned int dma_length /* Lenth equal 2 half buffer */

    return Successful;
}

int initSPIPDMA_Read(UINT32 dest_addr, UINT32 dma_length)
{
    
    g_PdmaCh = PDMA_FindandRequest();
    EDMA_SetAPB(g_PdmaCh,            //int channel, 
                        eDRVEDMA_SPIMS0,            //E_DRVEDMA_APB_DEVICE eDevice, 
                        eDRVEDMA_READ_APB,        //E_DRVEDMA_APB_RW eRWAPB, 
                        eDRVEDMA_WIDTH_32BITS);    //E_DRVEDMA_TRANSFER_WIDTH eTransferWidth    

    EDMA_SetupHandlers(g_PdmaCh,         //int channel
                        eDRVEDMA_BLKD,             //int interrupt,    
                        PdmaCallback_SPI,                 //void (*irq_handler) (void *),
                        NULL);                    //void *data

    EDMA_SetWrapINTType(g_PdmaCh , NULL);                                

    EDMA_SetDirection(g_PdmaCh , eDRVEDMA_DIRECTION_FIXED, eDRVEDMA_DIRECTION_INCREMENTED);


    EDMA_SetupSingle(g_PdmaCh,        // int channel, 
                                REG_SPI0_RX0,        // unsigned int src_addr,  (ADC data port physical address) 
                                dest_addr, //phaddrrecord,        // unsigned int dest_addr,
                                dma_length);    // unsigned int dma_length /* Lenth equal 2 half buffer */

    return Successful;
}


INT spiFlashPDMAWrite(UINT32 addr, UINT32 len, UINT32 *buf)
{
    int count=0, page, i;    
    
    count = len / 256;
    if ((len % 256) != 0)
        count++;

    for (i=0; i<count; i++)
    {
        // check data len
        if (len >= 256)
        {
            page = 256;
            len = len - 256;
        }
        else
            page = len;

        usiWriteEnable();

        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

        // write command
        outpw(REG_SPI0_TX0, 0x02);
        spiTxLen(0, 0, 8);
        spiActive(0);

        // address
        outpw(REG_SPI0_TX0, addr+i*256);
        spiTxLen(0, 0, 24);
        spiActive(0);    

        outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | BYTE_ENDIN);
        spiTxLen(0, 0, 32);        

        initSPIPDMA_Write((UINT32)buf, page);
        (UINT32)buf = (UINT32)buf + page;

        EDMA_Trigger(g_PdmaCh);
        outp32(REG_SPI0_EDMA, (inp32(REG_SPI0_EDMA) & ~0x03) | EDMA_GO);                            

        while(g_bPdmaInt == FALSE);    
        g_bPdmaInt = FALSE;

        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

        outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~BYTE_ENDIN);
        spiTxLen(0, 0, 8);
        outp32(REG_SPI0_EDMA, inp32(REG_SPI0_EDMA) & ~EDMA_GO);

        // check status
        if(usiCheckBusy(4*1.5*1000)!=Successful)
            return Fail;
    }

    return Successful;
}

INT spiFlashPDMARead(UINT32 addr, UINT32 len, UINT32 *buf)
{
    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

    // read command
    outpw(REG_SPI0_TX0, 0x0b);
    spiTxLen(0, 0, 8);
    spiActive(0);

    // address
    outpw(REG_SPI0_TX0, addr);
    spiTxLen(0, 0, 24);
    spiActive(0);

    // dummy byte
    outp32(REG_SPI0_TX0, 0xff);
    spiTxLen(0, 0, 8);
    spiActive(0);

    outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | BYTE_ENDIN);
    spiTxLen(0, 0, 32);

    initSPIPDMA_Read((UINT32)buf, len);
    
    EDMA_Trigger(g_PdmaCh);
    outp32(REG_SPI0_EDMA, (inp32(REG_SPI0_EDMA) & ~0x03) | (EDMA_RW | EDMA_GO));    
    outp32(REG_SPI0_CNTRL, inp32(REG_SPI0_CNTRL) |GO_BUSY);        
    
    while(g_bPdmaInt == FALSE);    
    g_bPdmaInt = FALSE;
    
    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

    outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~BYTE_ENDIN);
    spiTxLen(0, 0, 8);
    outp32(REG_SPI0_EDMA, inp32(REG_SPI0_EDMA) & ~EDMA_GO);

    return Successful;
}

INT TPH_SpiEnd(VOID)
{

    //clear status
    outp32(REG_VDMA_ISR + 1 * 0x100, inp32(REG_VDMA_ISR + 1 * 0x100) | (EDMASG_IF | EDMABLKD_IF | EDMATABORT_IF));
    outp32(REG_VDMA_IER + 1 * 0x100, inp32(REG_VDMA_IER + 1 * 0x100) & ~(SG_IEN | WAR_IE | BLKD_IE | EDMATABORT_IE));
    outp32(REG_VDMA_CSR + 1 * 0x100, inp32(REG_VDMA_CSR + 1 * 0x100) & ~EDMACEN);
    outp32(REG_AHBCLK,inp32(REG_AHBCLK) & ~(0x00000400 << 1));
    //spiIoctl(0, 0, 48, 24000);
    //g_bPdmaInt = TRUE;
    return 0;
}

void TPH_SpiStart(UINT32 addr, UINT32 len, UINT32 type,void (*irq_handler) (void *))
{
       UINT32  index;
       UINT32 loop = 1000;
       static int flag=1;
       UINT32 PDMA_CSR=(eDRVEDMA_WIDTH_8BITS<<TRANSFER_WIDTH_BIT)|
                        (eDRVEDMA_MEMORY_TO_DEVICE << MODE_SELECT_BIT)|
                         (eDRVEDMA_DIRECTION_FIXED<<DESTINATION_DIRECTION_BIT) | TRIG_EN | EDMACEN;

       unsigned char *pSrc;

       pSrc = (UINT8 *)((UINT32)WriteBuffer | NON_CACHE_BIT);

       /
       // ch_20220802
//       for (index = 0; index < len; index ++) {
//            *(pSrc + index) =  *((UINT8 *)addr + index);
//       }
       memcpy(pSrc, (UINT8 *)addr, len); // ch_20220802 : improve the issue of printing BLANK.
       /

        SPI_SwitchToTPH();
   
       if(type)
               outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | LSB);
       else
               outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) &(~LSB));

       outp32(REG_AHBCLK,inp32(REG_AHBCLK) | (0x00000400 << 1));                        // Enable Channel Clock        
      
        if(flag)
        {
            outp32(REG_EDSSR,(~CH1_TXSEL)|(0x01<<16));
            sysInstallISR(IRQ_LEVEL_6, IRQ_EDMA, (PVOID)irq_handler);
            sysSetInterruptType(IRQ_EDMA, HIGH_LEVEL_SENSITIVE);
            outpw(REG_AIC_MECR, inp32(REG_AIC_MECR)|(1 << IRQ_EDMA));
            outp32(REG_PDMA_SAR1, (UINT32)pSrc);
            outp32(REG_PDMA_DAR1,REG_SPI1_TX0);
            outp32(REG_PDMA_BCR1,len);
            flag=0;
        }
        
        outp32(REG_PDMA_IER1, inp32(REG_PDMA_IER1)|(SG_IEN | BLKD_IE | EDMATABORT_IE)); 
        outp32(REG_PDMA_CSR1, PDMA_CSR);
        outp32(REG_SPI1_EDMA, (inp32(REG_SPI1_EDMA) & ~0x03) | EDMA_GO);
        
}

void test() {
    

}



spi.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential                                       */
/*                                                                                   */
/* Copyright (c) 2008 by Nuvoton Technology Corporation                              */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
/****************************************************************************
 * 
 * FILENAME
 *     spi.c
 *
 * VERSION
 *     1.0
 *
 * DESCRIPTION
 *     This file contains SPI library APIs.
 *
 * DATA STRUCTURES
 *     None
 *
 * FUNCTIONS
 *     None
 *
 * HISTORY
  *     10/12/07      Create Ver 1.0
 *
 * REMARK
 *     None
 **************************************************************************/
/* Header files */
#ifdef ECOS
#include "stdlib.h"
#include "string.h"
#include "drv_api.h"
#include "diag.h"
#include "Common.h"
#include "wbio.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"
#endif

#include "w55fa93_reg.h"
#include "w55fa93_spi.h"

//static PFN_DRVSPI_CALLBACK g_pfnSPI0callback = NULL;
//static PFN_DRVSPI_CALLBACK g_pfnSPI1callback = NULL;


/*-----------------------------------------------------------------------------------*/
int spiActive(int port)
{
    if (port == 0)
    {
        outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL)|0x01);
        while(inpw(REG_SPI0_CNTRL) & 0x01);
    }
    else
    {
        outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL)|0x01);
        while(inpw(REG_SPI1_CNTRL) & 0x01);
    }
    return 0;
}

/*-----------------------------------------------------------------------------------*/
VOID spiSetGo(UINT8 u8Port)
{
    UINT32 u32Reg;

    if (u8Port == 0)
    {
        u32Reg = inpw(REG_SPI0_CNTRL);
        outpw(REG_SPI0_CNTRL, u32Reg | GO_BUSY);
    }
    else
    {
        u32Reg = inpw(REG_SPI1_CNTRL);
        outpw(REG_SPI1_CNTRL, u32Reg | GO_BUSY);
    }    
}

/*-----------------------------------------------------------------------------------*/
BOOL spiIsBusy(UINT8 u8Port)
{
    UINT32 u32reg;

    if(u8Port == 0)
        u32reg = inpw(REG_SPI0_CNTRL);
    else
        u32reg = inpw(REG_SPI1_CNTRL);    

    return ((u32reg & GO_BUSY)?TRUE:FALSE);
}

/*-----------------------------------------------------------------------------------*/
int spiTxLen(int port, int count, int bitLen)
{
    unsigned int reg;

    if (port == 0)
        reg = inpw(REG_SPI0_CNTRL);
    else
        reg = inpw(REG_SPI1_CNTRL);

    if ((count < 0) || (count > 3))
        return -1;

    if ((bitLen <= 0) || (bitLen > 32))
        return -1;

    if (bitLen == 32)
        reg = reg & 0xffffff07;
    else
        reg = (reg & 0xffffff07) | (bitLen << 3);
    reg = (reg & 0xfffffcff) | (count << 8);

    if (port == 0)
        outpw(REG_SPI0_CNTRL, reg);
    else
        outpw(REG_SPI1_CNTRL, reg);

    return 0;
}

/*-----------------------------------------------------------------------------------*/
void spiSetClock(int port, int clock_by_MHz, int output_by_kHz)
{
    int volatile divider;

    divider = (clock_by_MHz * 1000) / (2 * output_by_kHz) - 1;
    if (port == 0)
        outpw(REG_SPI0_DIVIDER, divider);
    else
        outpw(REG_SPI1_DIVIDER, divider);
}


/*-----------------------------------------------------------------------------------*/
static BOOL _spi_init_flag0 = FALSE, _spi_init_flag1 = FALSE;
int spiOpen(SPI_INFO_T *pInfo)
{
    int volatile i;

    if (pInfo->nPort == 0)
    {
        if(_spi_init_flag0)
        {
            sysprintf("SPI0 pin is unavailable!!\n");
            return -1;
        }

        if (!_spi_init_flag0)
        {
            outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS0_CKE);   // enable the clocks of SPI
            outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI0RST);
            outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI0RST);
            for (i=0; i<200; i++);

            outpw(REG_GPDFUN, inpw(REG_GPDFUN) | 0xFF000000);    // enable spi0 pin function

            if (pInfo->bIsSlaveMode)
                outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | 0x40000);
            else    // master mode
                outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~0x40000);

            if (pInfo->bIsClockIdleHigh)
                outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | 0x800);
            else    // clock idle low
                outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~0x800);

            if (pInfo->bIsLSBFirst)
                outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | 0x400);
            else    // MSB first
                outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~0x400);

            if (pInfo->bIsAutoSelect)
                outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x8);
            else
                outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~0x8);

            if (pInfo->bIsActiveLow)
                outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~0x4);
            else    // active high
                outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x4);

            if (pInfo->bIsTxNegative)
                outpw(REG_SPI0_CNTRL, (inpw(REG_SPI0_CNTRL) & ~0x6)| 0x4); // Tx falling; Rx rising
            else
                outpw(REG_SPI0_CNTRL, (inpw(REG_SPI0_CNTRL) & ~0x6)| 0x2); // Tx rising; Rx falling

            _spi_init_flag0 = TRUE;
        }
    }
    else
    {
        if(_spi_init_flag1)
        {
            sysprintf("SPI1 pin is unavailable!!\n");
            return -1;
        }

        if (!_spi_init_flag1)
        {
            outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS1_CKE);   // enable the clocks of SPI
            outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI1RST);
            outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI1RST);
            for (i=0; i<200; i++);

            outpw(REG_GPBFUN, inpw(REG_GPBFUN) | 0x03FC0000);    // enable spi1 pin function

            if (pInfo->bIsSlaveMode)
            {
                sysprintf("SPI1 only support Master mode!!\n");
                return -1;
            }
            else    // master mode
                outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~0x40000);

            if (pInfo->bIsClockIdleHigh)
                outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | 0x800);
            else    // clock idle low
                outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~0x800);

            if (pInfo->bIsLSBFirst)
                outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | 0x400);
            else    // MSB first
                outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~0x400);

            if (pInfo->bIsAutoSelect)
                outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) | 0x8);
            else
                outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~0x8);

            if (pInfo->bIsActiveLow)
                outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~0x4);
            else    // active high
                outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) | 0x4);

            if (pInfo->bIsTxNegative)
                outpw(REG_SPI1_CNTRL, (inpw(REG_SPI1_CNTRL) & ~0x6)| 0x4); // Tx falling; Rx rising
            else
                outpw(REG_SPI1_CNTRL, (inpw(REG_SPI1_CNTRL) & ~0x6)| 0x2); // Tx rising; Rx falling

            _spi_init_flag1 = TRUE;
        }
    }
    return 0;
}


/*-----------------------------------------------------------------------------------*/

VOID spiIoctl(INT32 spiPort, INT32 spiFeature, INT32 spiArg0, INT32 spiArg1)
{
    switch(spiFeature)
    {
        case SPI_SET_CLOCK:
                spiSetClock(spiPort, spiArg0, spiArg1);
            break;
    }
}

/*-----------------------------------------------------------------------------------*/

INT spiEnable(INT32 spiPort)
{
    if (spiPort == 0)
        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);
    else
        outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) | 0x01);
    return 0;
}

/*-----------------------------------------------------------------------------------*/

INT spiDisable(INT32 spiPort)
{
    if (spiPort == 0)
        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~0x01);
    else
        outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~0x01);
    return 0;
}

INT spiRead(INT port, INT RxBitLen, INT len, CHAR *pDst)
{
    switch (RxBitLen)
    {
        case SPI_32BIT:
            if (port == 0)
                outpw(REG_SPI0_TX0, 0xffffffff);
            else
                outpw(REG_SPI1_TX0, 0xffffffff);

            while (len-- > 0)
            {
                spiTxLen(port, 0, SPI_32BIT);
                spiActive(port);
                if (port == 0)
                    *((INT32 *)pDst) = inpw(REG_SPI0_RX0) & 0xffffffff;
                else
                    *((INT32 *)pDst) = inpw(REG_SPI1_RX0) & 0xffffffff;
                pDst += 4;
            }

            break;

        case SPI_16BIT:
            if (port == 0)
                outpw(REG_SPI0_TX0, 0xffff);
            else
                outpw(REG_SPI1_TX0, 0xffff);

            while (len-- > 0)
            {
                spiTxLen(port, 0, SPI_16BIT);
                spiActive(port);
                if (port == 0)
                    *((INT16 *)pDst) = inpw(REG_SPI0_RX0) & 0xffff;
                else
                    *((INT16 *)pDst) = inpw(REG_SPI1_RX0) & 0xffff;
                pDst += 2;
            }

            break;

        case SPI_8BIT:
            if (port == 0)
                outpw(REG_SPI0_TX0, 0xff);
            else
                outpw(REG_SPI1_TX0, 0xff);

            while (len-- > 0)
            {
                spiTxLen(port, 0, SPI_8BIT);
                spiActive(port);
                if (port == 0)
                    *((INT8 *)pDst) = inpw(REG_SPI0_RX0) & 0xff;
                else
                    *((INT8 *)pDst) = inpw(REG_SPI1_RX0) & 0xff;
                pDst ++;
            }

            break;
    }
    return 0;
}

INT spiWrite(INT port, INT TxBitLen, INT len, CHAR *pSrc)
{
    switch (TxBitLen)
    {
        case SPI_32BIT:
            while (len-- > 0)
            {
                if (port == 0)
                    outpw(REG_SPI0_TX0, *((INT32 *)pSrc));
                else
                    outpw(REG_SPI1_TX0, *((INT32 *)pSrc));
                spiTxLen(port, 0, SPI_32BIT);
                spiActive(port);
                pSrc += 4;
            }

            break;

        case SPI_16BIT:
            while (len-- > 0)
            {
                if (port == 0)
                    outpw(REG_SPI0_TX0, *((INT16 *)pSrc));
                else
                    outpw(REG_SPI1_TX0, *((INT16 *)pSrc));
                spiTxLen(port, 0, SPI_16BIT);
                spiActive(port);
                pSrc += 2;
            }

            break;

        case SPI_8BIT:
            while (len-- > 0)
            {
                if (port == 0)
                    outpw(REG_SPI0_TX0, *((INT8 *)pSrc));
                else
                    outpw(REG_SPI1_TX0, *((INT8 *)pSrc));
                spiTxLen(port, 0, SPI_8BIT);
                spiActive(port);
                pSrc ++;
            }

            break;
    }
    return 0;
}




spi_dma.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

没文件



spi_dma.h  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

#ifndef _SPI_DMA_H
#define _SPI_DMA_H
#include "w55fa93_edma.h"
#include "w55fa93_spi.h"

void TPH_SpiFree(void);
void TPH_SpiWrite(UINT8 * buffer, UINT32 len, PFN_DRVEDMA_CALLBACK irq);

void TPH_SpiStart(UINT32 addr, UINT32 len, UINT32 type,void (*irq_handler) (void *));
int TPH_SpiEnd(VOID);
void readStatus(void);
INT spiFlashPDMARead(UINT32 addr, UINT32 len, UINT32 *buf);

#endif




spiflash.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/*-----------------------------------------------------------------------------------*/
/* Nuvoton Technology Corporation confidential                                       */
/*                                                                                   */
/* Copyright (c) 2008 by Nuvoton Technology Corporation                              */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
/****************************************************************************
 * 
 * FILENAME
 *     spiflash.c
 *
 * VERSION
 *     1.0
 *
 * DESCRIPTION
 *     This file contains SPI flash library APIs.
 *
 * DATA STRUCTURES
 *     None
 *
 * FUNCTIONS
 *     None
 *
 * HISTORY
 *     10/12/07      Create Ver 1.0
 *     06/12/09      Add SPI flash
 *
 * REMARK
 *     None
 **************************************************************************/
/* Header files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"

#include "w55fa93_reg.h"
#include "w55fa93_spi.h"


int usiCheckBusy(unsigned int timeout)
{
    // check status
    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

    // status command
    outpw(REG_SPI0_TX0, 0x05);
    spiTxLen(0, 0, 8);
    spiActive(0);

    // get status
    while(timeout)
    {
        outpw(REG_SPI0_TX0, 0xff);
        spiTxLen(0, 0, 8);
        spiActive(0);
        if (((inpw(REG_SPI0_RX0) & 0xff) & 0x01) != 0x01)
            break;
            timeout--;
    }

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

    return timeout?Successful:Fail;
}

INT16 usiReadID()
{
    UINT16 volatile id;

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

    // command 8 bit
    outpw(REG_SPI0_TX0, 0x90);
    spiTxLen(0, 0, 8);
    spiActive(0);

    // address 24 bit
    outpw(REG_SPI0_TX0, 0x000000);
    spiTxLen(0, 0, 24);
    spiActive(0);

    // data 16 bit
    outpw(REG_SPI0_TX0, 0xffff);
    spiTxLen(0, 0, 16);
    spiActive(0);
    id = inpw(REG_SPI0_RX0) & 0xffff;

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

    return id;
}


int usiWriteEnable(void)
{
    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

    outpw(REG_SPI0_TX0, 0x06);
    spiTxLen(0, 0, 8);
    spiActive(0);

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

    return Successful;
}

int usiWriteDisable(void)
{
    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

    outpw(REG_SPI0_TX0, 0x04);
    spiTxLen(0, 0, 8);
    spiActive(0);

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

    return Successful;
}

int usiStatusWrite(UINT8 data)
{
    usiWriteEnable();

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

    // status command
    outpw(REG_SPI0_TX0, 0x01);
    spiTxLen(0, 0, 8);
    spiActive(0);

    // write status
    outpw(REG_SPI0_TX0, data);
    spiTxLen(0, 0, 8);
    spiActive(0);

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

    return Successful;
}


/**************************************************/
INT spiFlashInit(void)
{
    static BOOL bIsSpiFlashOK = 0;
    static BOOL bIsSpi1FlashOK = 0;
    int volatile loop;

    if (!bIsSpiFlashOK)
    {
        outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS0_CKE);    // turn on SPI clk
        //Reset SPI controller first
        outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI0RST);
        outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI0RST);
        // delay for time
        // Delay
        for (loop=0; loop<500; loop++);  
        //configure SPI0 interface, Base Address 0xB800C000

        /* apb clock is 48MHz, output clock is 10MHz */
#if defined(CPU_144MHZ_MODE)
        spiIoctl(0, SPI_SET_CLOCK, 72, 24000);
#else
        spiIoctl(0, SPI_SET_CLOCK, 96, 24000);
#endif
        //Startup SPI0 multi-function features, chip select using SS0
        outpw(REG_GPDFUN, inpw(REG_GPDFUN) | 0xFF000000);

        outpw(REG_SPI0_SSR, 0x00);        // CS active low
        outpw(REG_SPI0_CNTRL, 0x04);        // Tx: falling edge, Rx: rising edge

        if ((loop=usiReadID()) == -1)
        {
            sysprintf("read id error !! [0x%x]\n", loop&0xffff);
            return -1;
        }

        sysprintf("SPI flash id [0x%x]\n", loop&0xffff);
        usiStatusWrite(0x00);    // clear block protect
        // delay for time
        // Delay
        for (loop=0; loop<0x20000; loop++);  

        bIsSpiFlashOK = 1;
    }    

    if (!bIsSpi1FlashOK)
    {
        outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS1_CKE);    // turn on SPI clk
        //Reset SPI controller first
        outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI1RST);
        outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI1RST);
        // delay for time
        // Delay
        for (loop=0; loop<500; loop++);  
        //configure SPI0 interface, Base Address 0xB800C000

        /* apb clock is 48MHz, output clock is 10MHz */
#if defined(CPU_144MHZ_MODE)
        spiIoctl(1, SPI_SET_CLOCK, 72, 24000);
#else
        spiIoctl(1, SPI_SET_CLOCK, 96, 24000);
#endif
        //Startup SPI0 multi-function features, chip select using SS0
        outpw(REG_GPDFUN, inpw(REG_GPDFUN)^(0x55<<18));

        outpw(REG_SPI1_SSR, 0x00);        // CS active low
        outpw(REG_SPI1_CNTRL, 0x04);        // Tx: falling edge, Rx: rising edge

        //usiStatusWrite(0x00);    // clear block protect
        // delay for time
        // Delay
        for (loop=0; loop<0x20000; loop++);  

        bIsSpi1FlashOK = 1;
    }    


    return 0;
 }


INT spiFlashEraseBlock(UINT32 addr, UINT32 secCount)
{
    int volatile i;

    if ((addr % (64*1024)) != 0)
        return -1;

    for (i=0; i<secCount; i++)
    {
        usiWriteEnable();

        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

        // erase command
        outpw(REG_SPI0_TX0, 0xd8);
        spiTxLen(0, 0, 8);
        spiActive(0);

        // address
        outpw(REG_SPI0_TX0, addr+i*64*1024);
        spiTxLen(0, 0, 24);
        spiActive(0);

        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

        // check status
        if(usiCheckBusy(1.2*1.5*1000*1000)!=Successful)
                return Fail;
    }

    return Successful;
}
INT spiFlashEraseSector(UINT32 addr, UINT32 secCount)
{
    int volatile i;


    if ((addr % (4*1024)) != 0)
        return -1;

    for (i=0; i<secCount; i++)
    {
        usiWriteEnable();

        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

        // erase command
        outpw(REG_SPI0_TX0, 0x20);
        spiTxLen(0, 0, 8);
        spiActive(0);

        // address
        outpw(REG_SPI0_TX0, addr+i*4*1024);
        spiTxLen(0, 0, 24);
        spiActive(0);

        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

        // check status
        if(usiCheckBusy(0.6*1000*1000)!=Successful)
                return Fail;
    }

    return Successful;
}


INT spiFlashEraseAll(void)
{
    usiWriteEnable();

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

    outpw(REG_SPI0_TX0, 0xc7);
    spiTxLen(0, 0, 8);
    spiActive(0);

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

    // check status
    if(usiCheckBusy(60*1000*1000)!=Successful)
           return Fail;

    return Successful;
}


INT spiFlashWrite(UINT32 addr, UINT32 len, UINT32 *buf)
{
    int volatile count=0, page, i;
    UINT32 u32Tmp;

    SPI_SwitchToFlash();
    
    count = len / 256;
    if ((len % 256) != 0)
        count++;

    for (i=0; i<count; i++)
    {
        // check data len
        if (len >= 256)
        {
            page = 256;
            len = len - 256;
        }
        else
            page = len;

        //sysprintf("len %d page %d\n",len , page);
        usiWriteEnable();

        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

        // write command
        outpw(REG_SPI0_TX0, 0x02);
        spiTxLen(0, 0, 8);
        spiActive(0);

        // address
        outpw(REG_SPI0_TX0, addr+i*256);
        spiTxLen(0, 0, 24);
        spiActive(0);        
        
        // write data
        while (page > 0)
        {    
            u32Tmp = ((*buf & 0xFF) << 24) | ((*buf & 0xFF00) << 8) | ((*buf & 0xFF0000) >> 8)| ((*buf & 0xFF000000) >> 24);
            outpw(REG_SPI0_TX0, u32Tmp);
            spiTxLen(0, 0, 32);
            spiActive(0);
            buf++;
            page -=4;
        }

        outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

        // check status
        if(usiCheckBusy(4*1.5*1000)!=Successful)
                return Fail;
    }

    return Successful;
}


INT spiFlashRead(UINT32 addr, UINT32 len, UINT32 *buf)
{
    int volatile i;
    UINT32 u32Tmp;
    UINT8 *ptr;

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01);    // CS0

    // read command
    outpw(REG_SPI0_TX0, 03);
    spiTxLen(0, 0, 8);
    spiActive(0);

    // address
    outpw(REG_SPI0_TX0, addr);
    spiTxLen(0, 0, 24);
    spiActive(0);

    // data     
    for (i=0; i<len/4; i++)
    {
        outpw(REG_SPI0_TX0, 0xffffffff);
        spiTxLen(0, 0, 32);
        spiActive(0);
        u32Tmp = inp32(REG_SPI0_RX0);
        *buf++ = ((u32Tmp & 0xFF) << 24) | ((u32Tmp & 0xFF00) << 8) | ((u32Tmp & 0xFF0000) >> 8)| ((u32Tmp & 0xFF000000) >> 24);
    }
    
    if(len % 4)
    {
        ptr = (UINT8 *)buf;
        for (i=0; i<(len %4); i++)
        {
            outpb(REG_SPI0_TX0, 0xff);
            spiTxLen(0, 0, 8);
            spiActive(0);
            *ptr++ = inpb(REG_SPI0_RX0);
        }        
    }    

    outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & 0xfe);    // CS0

    return Successful;
}




standalone.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/*
 * standalone.c - minimal bootstrap for C library
 * Copyright (C) 2000 ARM Limited.
 * All rights reserved.
 */

/*
 * RCS $Revision: 1 $
 * Checkin $Date: 07/07/05 2:54p $ 0
 * Revising $Author: Sjlu0 $
 */

/*
 * This code defines a run-time environment for the C library.
 * Without this, the C startup code will attempt to use semi-hosting
 * calls to get environment information.
 */
extern unsigned int Image$$ZI$$Limit;

void _sys_exit(int return_code)
{
label:  goto label; /* endless loop */
}

void _ttywrch(int ch)
{
    char tempch = (char)ch;
    (void)tempch;
}


__value_in_regs struct R0_R3 {unsigned heap_base, stack_base, heap_limit, stack_limit;} 
    __user_initial_stackheap(unsigned int R0, unsigned int SP, unsigned int R2, unsigned int SL)
{
    struct R0_R3 config;

    //config.heap_base = 0x00060000;
    config.heap_base = (unsigned int)&Image$$ZI$$Limit;
    config.stack_base = SP;

/*
To place heap_base directly above the ZI area, use:
    extern unsigned int Image$$ZI$$Limit;
    config.heap_base = (unsigned int)&Image$$ZI$$Limit;
(or &Image$$region_name$$ZI$$Limit for scatterloaded images)

To specify the limits for the heap & stack, use e.g:
    config.heap_limit = SL;
    config.stack_limit = SL;
*/

    return config;
}


/* end of file standalone.c */




usbd.c  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

/****************************************************************************
 *
 **************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wblib.h"
#include "w55fa93_reg.h"
#include "usbd.h"

#define DATA_CODE    "20170606"

__align(4) volatile USBD_INFO_T usbdInfo = {0};
__align(4) volatile USBD_STATUS_T usbdStatus = {0};

USB_CMD_T    _usb_cmd_pkt;
INT32 volatile usb_halt_ep;
BOOL volatile g_bHostAttached = FALSE;
VOID usbd_isr(void);
UINT32 volatile class_out_len = 0;
VOID usbdClearAllFlags(void)
{
    usbdInfo.GET_DEV_Flag=0;
    usbdInfo.GET_CFG_Flag=0;
    usbdInfo.GET_QUL_Flag=0;
    usbdInfo.GET_OSCFG_Flag=0;
    usbdInfo.GET_STR_Flag=0;
    usbdInfo.GET_HID_Flag = 0;
    usbdInfo.GET_HID_RPT_Flag = 0;
    usbdInfo.usbdGetConfig=0;
    usbdInfo.usbdGetInterface=0;
    usbdInfo.usbdGetStatus=0;    
    usbdInfo.enabletestmode = 0;
}

VOID udcOpen(void)
{
    UINT32 u32PllOutKHz,u32ExtFreq;
    int i;    
    
    
    //sysprintf("N3290 UDC Library (%s)\n",DATA_CODE);
    
    u32ExtFreq = sysGetExternalClock();      

    outp32(REG_CLKDIV2, inp32(REG_CLKDIV2) & ~0x0060F0E0);
    
    if(u32ExtFreq == 27000)
    {
        u32PllOutKHz = sysGetPLLOutputKhz(eSYS_UPLL, u32ExtFreq);
        
        i = (u32PllOutKHz / 2) / 12000 - 1;
        
        /* USB Clock source = UPLL / 2 */
        /* USB Clock = USB Clock source / (i+1) */
        outp32(REG_CLKDIV2, inp32(REG_CLKDIV2) | 0x00600020 | (i << 12));    
        
    }
    
#ifndef __USBD_FULL_SPEED_MODE__        
    if(inp32(PHY_CTL) & Vbus_status)
    {
        usbdInfo.u32VbusStatus = 1;
        usbdStatus.usbConnected = 1;
    }
    else    
    {
        usbdInfo.u32VbusStatus = 0;
        usbdStatus.usbConnected = 0;
    }
        
#endif                   

#ifdef __USBD_FULL_SPEED_MODE__    
    outp32(REG_AHBCLK, inp32(REG_AHBCLK) | USBH_CKE);
    outp32(REG_HC_RH_OP_MODE, inp32(REG_HC_RH_OP_MODE) | (BIT16|BIT17) );
#endif
    outp32(REG_AHBCLK, inp32(REG_AHBCLK) | USBD_CKE | HCLK3_CKE);
    outpw(REG_AHBIPRST, inpw(REG_AHBIPRST) | UDCRST);
    outpw(REG_AHBIPRST, inpw(REG_AHBIPRST) & ~UDCRST);
    
    outp32(PHY_CTL, (0x20 | Phy_suspend));
    
    outp32(CEP_END_ADDR, 0x7F);
    
    while(inp32(CEP_END_ADDR) != 0x7F);            
    usbdInfo.u32UVC = 0;
#ifdef __USBD_FULL_SPEED_MODE__    
    outp32(OPER, 0x0);        
    while(inp32(OPER) != 0x0);
    
    for(i=0;i<0x30000;i++)
    {
        if(inp32(PHY_CTL) & Vbus_status)
        {
            usbdInfo.u32VbusStatus = 1;
            usbdStatus.usbConnected = 1;
            break;
        }
        else    
        {
            usbdInfo.u32VbusStatus = 0;
            usbdStatus.usbConnected = 0;
        }
    }
#endif

}


VOID udcInit(void)
{  
    /* initial state */
    usbdInfo._usbd_devstate = 0;        //initial state
    usbdInfo._usbd_address  = 0;        //not set 
    usbdInfo._usbd_confsel  = 0;        //not selected
    usbdInfo._usbd_intfsel  = 0;        //not selected
    
#ifdef __USBD_FULL_SPEED_MODE__    
    usbdInfo._usbd_speedset = 1;        // default at high speed mode
#else
    usbdInfo._usbd_speedset = 2;        // default at high speed mode
#endif     

    usbdInfo.AlternateFlag = 0;
    usbdInfo.AlternateFlag_Audio = 0;         // For UAC audio
    usbdStatus.appConnected = 0;
    usbdStatus.appConnected_Audio = 0;        // For UAC audio
    usbdInfo._usbd_haltep = -1;
    
    sysInstallISR(IRQ_LEVEL_7, IRQ_UDC, (PVOID)usbd_isr);
    sysEnableInterrupt(IRQ_UDC);
    sysSetLocalInterrupt(ENABLE_IRQ);
    
    /* 
     * configure mass storage interface endpoint 
     */
    /* Device is in High Speed */
    if (usbdInfo._usbd_speedset == 2)
    {
        usbdInfo.pfnHighSpeedInit();
    }
    /* Device is in Full Speed */
    else if (usbdInfo._usbd_speedset == 1)
    {
        usbdInfo.pfnFullSpeedInit();
    }

    /*
     * configure USB controller 
     */
    outp32(IRQ_ENB_L, (USB_IE|CEP_IE|EPA_IE|EPB_IE|EPC_IE|EPD_IE));    /* enable usb, cep, epa, epb, epc interrupt */
    outp32(USB_IRQ_ENB, (DMACOM_IE | RUM_IE | RST_IE|VBUS_IE));
    outp32(ADDR, 0);
#ifndef __USBD_FULL_SPEED_MODE__        
    outp32(OPER, SET_HISPD);
#endif
    /* allocate 0xff bytes mem for cep */
    outp32(CEP_START_ADDR, 0);
    outp32(CEP_END_ADDR, 0x7F);
    outp32(CEP_IRQ_ENB, (CEP_SUPPKT | CEP_STS_END));
    if(inp32(PHY_CTL) & Vbus_status)
        outp32(PHY_CTL, (0x20 | Phy_suspend | vbus_detect));    
}

VOID udcDeinit(void)
{
    outp32(PHY_CTL, (inp32(PHY_CTL) & ~vbus_detect));
    usbdInfo.USBModeFlag =0;
}

VOID udcClose(void)
{
    outp32(REG_AHBCLK, inp32(REG_AHBCLK) & ~USBD_CKE);
}

BOOL udcIsAttached(void)
{
    return((inp32(PHY_CTL) & Vbus_status) ? TRUE : FALSE);
}

BOOL udcIsAttachedToHost(void)
{
    return g_bHostAttached;    
}

VOID usbd_update_device(void)
{
    /* update this device for set requests */
    switch(_usb_cmd_pkt.bRequest)
    {
        case USBR_SET_ADDRESS:
            outp32(ADDR, usbdInfo._usbd_address);
            break;

        case USBR_SET_CONFIGURATION:
            if(usbdInfo.i32EPA_Num != -1)
            {        
                outp32(EPA_RSP_SC, EP_TOGGLE);
            }
            if(usbdInfo.i32EPB_Num != -1)
            {        
                outp32(EPB_RSP_SC, EP_TOGGLE);
            }
            if(usbdInfo.i32EPC_Num != -1)
            {        
                outp32(EPC_RSP_SC, EP_TOGGLE);
            }
            if(usbdInfo.i32EPD_Num != -1)
            {        
                outp32(EPD_RSP_SC, EP_TOGGLE);
            }
            break;

        case USBR_SET_INTERFACE:
            break;

        case USBR_SET_FEATURE:
            if(usbdInfo._usbd_haltep == 0)
                outp32(CEP_CTRL_STAT, CEP_SEND_STALL);
            else if(usbdInfo.i32EPA_Num != -1 && usbdInfo._usbd_haltep == usbdInfo.i32EPA_Num )
            {
                outp32(EPA_RSP_SC, EP_HALT);
            }
            else if(usbdInfo.i32EPB_Num != -1 && usbdInfo._usbd_haltep == usbdInfo.i32EPB_Num )
            {
                outp32(EPB_RSP_SC, EP_HALT);
            }
            else if(usbdInfo.i32EPC_Num != -1 && usbdInfo._usbd_haltep == usbdInfo.i32EPC_Num )
            {
                outp32(EPC_RSP_SC,EP_HALT);
            }                        
            else if(usbdInfo.i32EPD_Num != -1 && usbdInfo._usbd_haltep == usbdInfo.i32EPD_Num )
            {
                outp32(EPD_RSP_SC, EP_HALT);
            }        
            else if(usbdInfo.enableremotewakeup == 1)
            {
                usbdInfo.enableremotewakeup = 0;
                usbdInfo.remotewakeup = 1;
            }
            if(usbdInfo.enabletestmode == 1)
            {
                usbdInfo.enabletestmode = 0;
                usbdInfo.testmode = 1;
                if(usbdInfo.testselector == TEST_J)
                    outp32(USB_TEST, TEST_J);
                else if(usbdInfo.testselector==TEST_K)
                    outp32(USB_TEST, TEST_K);
                else if(usbdInfo.testselector==TEST_SE0_NAK)
                    outp32(USB_TEST, TEST_SE0_NAK);
                else if(usbdInfo.testselector==TEST_PACKET)
                    outp32(USB_TEST, TEST_PACKET);
                else if(usbdInfo.testselector==TEST_FORCE_ENABLE)
                    outp32(USB_TEST, TEST_FORCE_ENABLE);
            }
            break;

        case USBR_CLEAR_FEATURE:
            if(usbdInfo.i32EPA_Num != -1 && usbdInfo._usbd_unhaltep == usbdInfo.i32EPA_Num && usbdInfo._usbd_haltep == usbdInfo.i32EPA_Num)
            {
                outp32(EPA_RSP_SC, 0x0);
                usb_halt_ep = usb_halt_ep & ~0x01;
                outp32(EPA_RSP_SC, EP_TOGGLE);
                usbdInfo._usbd_haltep = -1; /* just for changing the haltep value */
            }
            if(usbdInfo.i32EPB_Num != -1 && usbdInfo._usbd_unhaltep == usbdInfo.i32EPB_Num && usbdInfo._usbd_haltep == usbdInfo.i32EPB_Num)
            {
                outp32(EPB_RSP_SC, 0x0);
                usb_halt_ep = usb_halt_ep & ~0x02;
                outp32(EPB_RSP_SC, EP_TOGGLE);
                usbdInfo._usbd_haltep = -1; /* just for changing the haltep value */
            }
            if(usbdInfo.i32EPC_Num != -1 && usbdInfo._usbd_unhaltep == usbdInfo.i32EPC_Num && usbdInfo._usbd_haltep == usbdInfo.i32EPC_Num)
            {
                outp32(EPC_RSP_SC, 0x0);
                usb_halt_ep = usb_halt_ep & ~0x04;
                outp32(EPC_RSP_SC, EP_TOGGLE);
                usbdInfo._usbd_haltep = -1; /* just for changing the haltep value */
            }
            if(usbdInfo.i32EPD_Num != -1 && usbdInfo._usbd_unhaltep == usbdInfo.i32EPD_Num && usbdInfo._usbd_haltep == usbdInfo.i32EPD_Num)
            {
                outp32(EPD_RSP_SC, 0x0);
                usb_halt_ep = usb_halt_ep & ~0x08;
                outp32(EPD_RSP_SC, EP_TOGGLE);
                usbdInfo._usbd_haltep = -1; /* just for changing the haltep value */
            }            
            else if(usbdInfo.disableremotewakeup == 1)
            {
                usbdInfo.disableremotewakeup=0;
                usbdInfo.remotewakeup=0;
            }
            break;
        
        default:
            break;
    }
}

VOID usbd_send_descriptor(void)
{
    UINT32 volatile temp_cnt;
    int volatile i;
    UINT32 volatile *ptr;
    UINT8 volatile *pRemainder;

    if ((usbdInfo.CLASS_CMD_Iflag==1) || (usbdInfo.GET_DEV_Flag == 1) || (usbdInfo.GET_QUL_Flag == 1) || 
        (usbdInfo.GET_CFG_Flag == 1) || (usbdInfo.GET_OSCFG_Flag == 1) || (usbdInfo.GET_STR_Flag == 1) ||
        (usbdInfo.usbdGetConfig == 1) || (usbdInfo.usbdGetInterface == 1) ||(usbdInfo.usbdGetStatus == 1)
        || (usbdInfo.GET_HID_Flag == 1) || (usbdInfo.GET_HID_RPT_Flag == 1)) 
    {
        if (usbdInfo._usbd_remlen_flag == 0)
        {
            if (usbdInfo.GET_DEV_Flag == 1)
                ptr = (UINT32 *)usbdInfo.pu32DevDescriptor;
            else if (usbdInfo.GET_QUL_Flag == 1)
                ptr =(UINT32 *)usbdInfo.pu32QulDescriptor;
            else if (usbdInfo.GET_CFG_Flag == 1)
            {
                if (usbdInfo._usbd_speedset == 2)
                    ptr = (UINT32 *)usbdInfo.pu32HSConfDescriptor;
                else if (usbdInfo._usbd_speedset == 1)
                    ptr = (UINT32 *)usbdInfo.pu32FSConfDescriptor;    
            }
            else if (usbdInfo.GET_OSCFG_Flag == 1)
            {
                if (usbdInfo._usbd_speedset == 2)
                    ptr = (UINT32 *)usbdInfo.pu32HOSConfDescriptor;
                else if (usbdInfo._usbd_speedset == 1)
                    ptr = (UINT32 *)usbdInfo.pu32FOSConfDescriptor;    
                        
            }
            else if (usbdInfo.GET_STR_Flag == 1)
                ptr = (UINT32 *)usbdInfo.pu32StringDescriptor[_usb_cmd_pkt.wValue & 0x7];                            
            else if (usbdInfo.GET_HID_Flag == 1)
                ptr = (UINT32 *)usbdInfo.pu32HIDDescriptor;
            else if (usbdInfo.GET_HID_RPT_Flag == 1)
                ptr = (UINT32 *)usbdInfo.pu32HIDRPTDescriptor;                                
            else if (usbdInfo.usbdGetConfig == 1)
            {
                /* Send Configuration Selector Data (1 bytes) to Host */
                outp8(CEP_DATA_BUF, usbdInfo._usbd_confsel);
                outp32(IN_TRNSFR_CNT, 1);
                return;
            }
            else if (usbdInfo.usbdGetInterface == 1)
            {
                /* Send Alternate Selector Data (1 bytes) to Host */
                outp8(CEP_DATA_BUF, usbdInfo._usbd_altsel);
                outp32(IN_TRNSFR_CNT, 1);
                return;
            }
            else if (usbdInfo.usbdGetStatus == 1)
            {
                /* Send Status (2 bytes) to Host */
                outp8(CEP_DATA_BUF, (UINT8)usbdInfo.usbdGetStatusData);
                outp8(CEP_DATA_BUF, 0);
                outp32(IN_TRNSFR_CNT, 2);
                return;
            }        
            else if (usbdInfo.CLASS_CMD_Iflag == 1)
            {               
                if(usbdInfo.u32UVC == 1 && usbdStatus.appConnected == 1)
                {        
                    int volatile flag = 0;
                    int volatile i = 0;
                    int volatile count0 = 0, count1 = 0;    
                    while(1)
                    {
                        count0 = inp32(EPA_DATA_CNT) & 0xFFFF;                        
                        
                        for(i = 0; i < 5; i++)
                            ;
                        count1 = inp32(EPA_DATA_CNT) & 0xFFFF;
                        
                        if(count0 == count1)
                            flag++;
                        else
                            flag = 0;
                                
                        if(flag > 5)
                            break;    
                        
                    }    
                }        
        
                outp32(CEP_END_ADDR, 0x7F);            
                 /* Class Data In */
                if(usbdInfo.pfnClassDataINCallBack != NULL)
                    usbdInfo.pfnClassDataINCallBack();

                return;
            }
        }        
        else
            ptr = usbdInfo._usbd_ptr;

        if (_usb_cmd_pkt.wLength > 0x40)
        {
            usbdInfo._usbd_remlen_flag = 1;
            usbdInfo._usbd_remlen = _usb_cmd_pkt.wLength - 0x40;
            _usb_cmd_pkt.wLength = 0x40;
        }
        else if (usbdInfo._usbd_remlen != 0)
        {
            if (usbdInfo._usbd_remlen > 0x40)
            {
                usbdInfo._usbd_remlen_flag = 1;
                usbdInfo._usbd_remlen = usbdInfo._usbd_remlen -0x40;
                _usb_cmd_pkt.wLength = 0x40;                
            }
            else
            {
                usbdInfo._usbd_remlen_flag = 0;
                _usb_cmd_pkt.wLength = usbdInfo._usbd_remlen;
                usbdInfo._usbd_remlen = 0;                
            }      
        }
        else
        {
            usbdInfo._usbd_remlen_flag = 0;
            usbdInfo._usbd_remlen = 0;
        }
    
        temp_cnt = _usb_cmd_pkt.wLength / 4;

        for (i=0; i<temp_cnt; i++)
            outp32(CEP_DATA_BUF, *ptr++);
            
        temp_cnt = _usb_cmd_pkt.wLength % 4;
        
        if (temp_cnt)
        {
            pRemainder = (UINT8 *)ptr;
            for (i=0; i<temp_cnt; i++)
            {
                outp8(CEP_DATA_BUF, *pRemainder);
                pRemainder++;
            }            
        }            

        if (usbdInfo._usbd_remlen_flag)
            usbdInfo._usbd_ptr = (UINT32  *)ptr;

        outp32(IN_TRNSFR_CNT, _usb_cmd_pkt.wLength);
    }
}

VOID usbd_control_packet(void)
{
    UINT32    volatile temp;
    BOOL    volatile ReqErr = 0;
    
    /* Get Command */    
    temp = inp32(SETUP1_0);
    _usb_cmd_pkt.bmRequestType = (UINT8)temp & 0xff;
    _usb_cmd_pkt.bRequest = (UINT8)(temp >> 8) & 0xff;
    _usb_cmd_pkt.wValue = (UINT16)inp32(SETUP3_2);
    _usb_cmd_pkt.wIndex = (UINT16)inp32(SETUP5_4);
    _usb_cmd_pkt.wLength = (UINT16)inp32(SETUP7_6);

    usbdClearAllFlags();

    usbdInfo.CLASS_CMD_Iflag = 0;
    usbdInfo.CLASS_CMD_Oflag = 0;  
    
    if ((_usb_cmd_pkt.bmRequestType &0xE0) == 0xa0)     /* 0xA1 or 0xA2 is Class Get Request */
    {
        outp32(CEP_IRQ_STAT, CEP_STACOM_IS);        /* Add by SPCheng */
        if (_usb_cmd_pkt.wLength == 0)
        {
             /* Class Data Out without Data */
            if(usbdInfo.pfnClassDataINCallBack != NULL)
                usbdInfo.pfnClassDataINCallBack();    
            return;                        
        } 
        usbdInfo.CLASS_CMD_Iflag = 1;
         usbdInfo._usbd_DMA_In =1; 
        
        outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);        // BA+0x34 , clear status, In talken
        outp32(CEP_IRQ_ENB, CEP_IN_TK_IE);            //suppkt int ,status and in token
        
                    
        
        return;         
    }         
    else if ((_usb_cmd_pkt.bmRequestType &0xE0) == 0x20)     //0x21 or 0x22 is Class Set Request
    {
        if(usbdInfo.u32UVC == 1 && usbdStatus.appConnected == 1)
        {    
            int volatile flag = 0;
            int volatile i = 0;
            int volatile count0 = 0, count1 = 0;    
            outp32(CEP_END_ADDR, 0x7F);        
            while(1)
            {
                count0 = inp32(EPA_DATA_CNT) & 0xFFFF;                        
                
                for(i = 0; i < 5; i++)
                    ;
                count1 = inp32(EPA_DATA_CNT) & 0xFFFF;
                
                if(count0 == count1)
                    flag++;
                else
                    flag = 0;
                        
                if(flag > 5)
                    break;    
                
            }        
        }
        usbdInfo.CLASS_CMD_Oflag = 1; 
           
        if (_usb_cmd_pkt.wLength == 0)
        {
             /* Class Data Out without Data */
            if(usbdInfo.pfnClassDataOUTCallBack != NULL)
                usbdInfo.pfnClassDataOUTCallBack();    
                
            outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR);        /* clear nak so that sts stage is complete */            
                
        }        
        else        
            outp32(CEP_IRQ_ENB, /*CEP_OUT_TK_IE |*/ CEP_DATA_RxED_IE);        //OUT_TK_IE        
            
        return;     
    }     
    switch (_usb_cmd_pkt.bRequest)
    {
        case USBR_GET_DESCRIPTOR:
        /*    ReqErr = ((_usb_cmd_pkt.bmRequestType == 0x80) && ((_usb_cmd_pkt.wValue & 0xf000) == 0)
            && ((_usb_cmd_pkt.wValue & 0x80) == 0)) ? 0 : 1;

            if(ReqErr==1)
            {
                sysprintf("ERROR\n");
                break;
            }*/
            switch    ((_usb_cmd_pkt.wValue & 0xff00) >> 8) 
            {                  
                case USB_DT_DEVICE:
                    // clear flags
                    usbdClearAllFlags();
                    usbdInfo.GET_DEV_Flag = 1;
                    usbdInfo.USBModeFlag=1;    /*  acpi debug */
                    if (_usb_cmd_pkt.wLength > usbdInfo.u32DevDescriptorLen)
                        _usb_cmd_pkt.wLength = usbdInfo.u32DevDescriptorLen;

                    break;

                case USB_DT_CONFIG:
                    usbdClearAllFlags();
                    usbdInfo.GET_CFG_Flag = 1;
                    {
                        if (usbdInfo._usbd_speedset == 2)
                        {
                            if (_usb_cmd_pkt.wLength > usbdInfo.u32HSConfDescriptorLen)
                                _usb_cmd_pkt.wLength = usbdInfo.u32HSConfDescriptorLen;                        
                        }
                        else
                        {
                            if (_usb_cmd_pkt.wLength > usbdInfo.u32FSConfDescriptorLen)
                                _usb_cmd_pkt.wLength = usbdInfo.u32FSConfDescriptorLen;    
                        }                    
                    }    
                    break;
                case USB_DT_QUALIFIER:    /* high-speed operation */                
                    usbdClearAllFlags();                    
                    usbdInfo.GET_QUL_Flag = 1;
                    if (_usb_cmd_pkt.wLength > usbdInfo.u32QulDescriptorLen)
                        _usb_cmd_pkt.wLength = usbdInfo.u32QulDescriptorLen;
                    break;
                case USB_DT_OSCONFIG:    /* other speed configuration */
                    usbdClearAllFlags();
                    usbdInfo.GET_OSCFG_Flag = 1;
                    
                    if (usbdInfo._usbd_speedset == 2)
                    {
                        if (_usb_cmd_pkt.wLength > usbdInfo.u32HOSConfDescriptorLen)
                            _usb_cmd_pkt.wLength = usbdInfo.u32HOSConfDescriptorLen;                    
                    }    
                    else if (usbdInfo._usbd_speedset == 1)
                    {
                        if (_usb_cmd_pkt.wLength > usbdInfo.u32FOSConfDescriptorLen)
                            _usb_cmd_pkt.wLength = usbdInfo.u32FOSConfDescriptorLen;    
                    }                        
                    
    

                    break;

                case USB_DT_STRING:
                    usbdClearAllFlags();
                    usbdInfo.GET_STR_Flag = 1;
                    if (_usb_cmd_pkt.wLength > usbdInfo.u32StringDescriptorLen[_usb_cmd_pkt.wValue & 0x7])
                        _usb_cmd_pkt.wLength = usbdInfo.u32StringDescriptorLen[_usb_cmd_pkt.wValue & 0x7];
                        
                    break;
                case USB_DT_HID:
                    usbdClearAllFlags();
                    usbdInfo.GET_HID_Flag = 1;
                    if (_usb_cmd_pkt.wLength > usbdInfo.u32HIDDescriptorLen)
                        _usb_cmd_pkt.wLength = usbdInfo.u32HIDDescriptorLen;                    
                    break;                
                case USB_DT_HID_RPT:
                    usbdClearAllFlags();
                    //sysprintf("USB_DT_HID_RPT\n");
                    usbdInfo.GET_HID_RPT_Flag = 1;
                    usbdStatus.appConnected = 1;
                    if (_usb_cmd_pkt.wLength > usbdInfo.u32HIDRPTDescriptorLen)
                        _usb_cmd_pkt.wLength = usbdInfo.u32HIDRPTDescriptorLen;                        
                    break;
                default:
                    ReqErr=1;
                    break;
            }    //end of switch
            if (ReqErr == 0)
            {
                outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
                outp32(CEP_IRQ_ENB, CEP_IN_TK_IE);        //suppkt int ,status and in token
            }
    
            break;

        case USBR_SET_ADDRESS:
            ReqErr = ((_usb_cmd_pkt.bmRequestType == 0) && ((_usb_cmd_pkt.wValue & 0xff00) == 0)
             && (_usb_cmd_pkt.wIndex == 0) && (_usb_cmd_pkt.wLength == 0)) ? 0 : 1;

            if ((_usb_cmd_pkt.wValue & 0xffff) > 0x7f)
                ReqErr=1;    /* Devaddr > 127 */

            if (usbdInfo._usbd_devstate == 3)
                ReqErr=1;    /* Dev is configured */

            if (ReqErr==1) 
                break;        
            if(usbdInfo._usbd_devstate == 2)
            {
                if(_usb_cmd_pkt.wValue == 0)
                    usbdInfo._usbd_devstate = 1;                /* enter default state */
                usbdInfo._usbd_address = _usb_cmd_pkt.wValue;    /* if wval !=0,use new address */    
            }

            if(usbdInfo._usbd_devstate == 1)
            {
                if(_usb_cmd_pkt.wValue != 0)
                {
                    usbdInfo._usbd_address = _usb_cmd_pkt.wValue;
                    usbdInfo._usbd_devstate = 2;
                }
            }
            outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
            outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR);            /* clear nak so that sts stage is complete */
            outp32(CEP_IRQ_ENB, CEP_STACOM_IE);                /* enable status complete interrupt */
            break;

        case USBR_GET_CONFIGURATION:
            ReqErr = ((_usb_cmd_pkt.bmRequestType == 0x80) && (_usb_cmd_pkt.wValue == 0) &&
            (_usb_cmd_pkt.wIndex == 0) && (_usb_cmd_pkt.wLength == 0x1) ) ? 0 : 1;
            
            if (ReqErr==1)
                break;

            usbdClearAllFlags();
            usbdInfo.usbdGetConfig=1;            

            outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
            outp32(CEP_IRQ_ENB, CEP_IN_TK_IE);        /* status and in token */ 

            break;

        case USBR_SET_CONFIGURATION:
            ReqErr = ((_usb_cmd_pkt.bmRequestType == 0) && ((_usb_cmd_pkt.wValue & 0xff00) == 0) &&
            ((_usb_cmd_pkt.wValue & 0x80) == 0) && (_usb_cmd_pkt.wIndex == 0) && 
            (_usb_cmd_pkt.wLength == 0)) ? 0 : 1;

            if (usbdInfo._usbd_devstate == 1)
                ReqErr=1; /* Device is in Default state */

            if ((_usb_cmd_pkt.wValue != 1) && (_usb_cmd_pkt.wValue != 0) )  /* Only configuration one is supported */
                ReqErr=1;    /* Configuration choosed is invalid */
    
            if(ReqErr==1) 
                break;    
                
            if (_usb_cmd_pkt.wValue == 0)
            {
                usbdInfo._usbd_confsel = 0;
                usbdInfo._usbd_devstate = 2;
            }
            else
            {
                usbdInfo._usbd_confsel = _usb_cmd_pkt.wValue;
                usbdInfo._usbd_devstate = 3;
            }
            usbdInfo.USBStartFlag = 1;
            outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
            outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR);    /* clear nak so that sts stage is complete */            
            outp32(CEP_IRQ_ENB, CEP_STACOM_IE);                /* suppkt int ,status and in token */
            break;

        case USBR_GET_INTERFACE:
            ReqErr = ((_usb_cmd_pkt.bmRequestType == 0x81) && (_usb_cmd_pkt.wValue == 0)
                     && (_usb_cmd_pkt.wLength == 0x1)) ? 0 : 1;
            
            if ((usbdInfo._usbd_devstate == 1) || (usbdInfo._usbd_devstate == 2))
                ReqErr=1; /* Device state is not valid */

            if(ReqErr == 1) 
                break;    /*  Request Error */
            
            usbdClearAllFlags();
            usbdInfo.usbdGetInterface = 1;            
    
            outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
            outp32(CEP_IRQ_ENB, CEP_IN_TK_IE);        /* status and in token */        
            break;

        case USBR_SET_INTERFACE:

            usbdInfo._usbd_altsel = _usb_cmd_pkt.wValue;
            usbdInfo._usbd_intfsel = _usb_cmd_pkt.wIndex;
            
            if(usbdInfo.u32UVC)
            {                      
                if ( usbdInfo._usbd_intfsel == 1 )  // for video interface
                {
                    if (_usb_cmd_pkt.wValue != 0)      // Set alternative interface Video
                    {
                        usbdInfo.AlternateFlag=1;
                        usbdStatus.appConnected = 1;
                            outp32(CEP_END_ADDR, 0x0);
                        //sysprintf("Interface 1, alter 1\n");                    
                    }
                    else
                    {
                        outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)|0x00000080);    /* Reset DMA */
                        outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)&0x0000007F);    
                        outp32(EPA_RSP_SC, BUF_FLUSH);    /* flush fifo */
                             
                        usbdInfo._usbd_DMA_In =1;                
                        usbdInfo.AlternateFlag=0;
                        usbdStatus.appConnected = 0;
                            outp32(CEP_END_ADDR, 0x7F);     
                        //sysprintf("Interface 1, alter 0\n");                       
                    }
                }
                else if ( usbdInfo._usbd_intfsel == 3 )  // for audio microphone interface
                {
                    if (_usb_cmd_pkt.wValue == 1)   // for audio settng of Isochronous In
                    {
                        usbdInfo.AlternateFlag_Audio=1;
                        usbdStatus.appConnected_Audio = 1;
                        //sysprintf("Setup Interface 3, alter 1\n");                        
                    }
                    else
                    {         
                        usbdInfo.AlternateFlag_Audio=0;
                        usbdStatus.appConnected_Audio = 0;
                        //sysprintf("Setup Interface 3, alter 0\n");                       
                    }
                }
                else
                {
                    //outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)|0x00000080);    /* Reset DMA */
                       //outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)&0x0000007F);    
                       //usbdInfo._usbd_DMA_In =1;    
                    //sysprintf("Interface no, alter no\n");                             
                }  
            }
            else
            {

                if (_usb_cmd_pkt.wValue !=0)
                {
                    usbdInfo.AlternateFlag=1;
                    usbdStatus.appConnected = 1;
                    outp32(CEP_START_ADDR, 0);
                    outp32(CEP_END_ADDR, 0x0);                             
                }
                else
                {
                    outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)|0x00000080);    /* Reset DMA */
                    outp32(DMA_CTRL_STS, inp32(DMA_CTRL_STS)&0x0000007F);    
                                 
                    usbdInfo._usbd_DMA_In =1;                
                    usbdInfo.AlternateFlag=0;
                    usbdStatus.appConnected = 0;
                }              
            }    
            outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
            outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR);    /* clear nak so that sts stage is complete */
            
            
            outp32(CEP_IRQ_ENB, CEP_STACOM_IE);                /* suppkt int ,status and in token */
            
            break;

        case USBR_SET_FEATURE:
            if (usbdInfo._usbd_devstate == 1)
            {
                if((_usb_cmd_pkt.bmRequestType & 0x3) == 0x0)     /* Receipent is Device */
                {
                    if((_usb_cmd_pkt.wValue & 0x3) == TEST_MODE)
                    {
                        usbdInfo.enabletestmode = 1;
                        usbdInfo.testselector = (_usb_cmd_pkt.wIndex >> 8);
                        outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
                        outp32(CEP_IRQ_ENB, CEP_STACOM_IE);                /* suppkt int ,status and in token */                     
                    }
                }
                else
                    ReqErr=1; /* Device is in Default State */
            }

            if (usbdInfo._usbd_devstate == 2)
            {
                if ((_usb_cmd_pkt.bmRequestType & 0x3 == 2) && ((_usb_cmd_pkt.wIndex & 0xff) != 0))    /* ep but not cep */
                    ReqErr =1; /* Device is in Addressed State, but for noncep */
                else if ((_usb_cmd_pkt.bmRequestType & 0x3) == 0x1)
                    ReqErr=1; /* Device is in Addressed State, but for interfac */
            }

            if (ReqErr == 1) 
                break;    /* Request Error */
                
            /* check if recipient and wvalue are appropriate */     
            switch(_usb_cmd_pkt.bmRequestType & 0x3)
            {
                case 0:        /* device */
                    if ((_usb_cmd_pkt.wValue & 0x3) == DEVICE_REMOTE_WAKEUP)
                        usbdInfo.enableremotewakeup = 1;
                    else if((_usb_cmd_pkt.wValue & 0x3) == TEST_MODE)
                    {
                        usbdInfo.enabletestmode = 1;
                        usbdInfo.testselector = (_usb_cmd_pkt.wIndex >> 8);
                    }
                    else
                        ReqErr=1; /* No such feature for device */

                    break;

                case 1:        /* interface */
                    break;

                case 2:        /* endpoint */
                    if((_usb_cmd_pkt.wValue & 0x3) == ENDPOINT_HALT)
                    {
                        //dx->chgfea=dx->feature | ENDPOINT_HALT;
                        if((_usb_cmd_pkt.wIndex & 0xF) == 0)         /* endPoint zero */
                            usbdInfo._usbd_haltep = 0;
                        else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPA_Num)    /* endPoint A */
                            usbdInfo._usbd_haltep = usbdInfo.i32EPA_Num;
                        else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPB_Num)    /* endPoint B */
                            usbdInfo._usbd_haltep = usbdInfo.i32EPB_Num;
                        else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPC_Num)    /* endPoint C */
                            usbdInfo._usbd_haltep = usbdInfo.i32EPC_Num;
                        else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPD_Num)    /* endPoint D */
                            usbdInfo._usbd_haltep = usbdInfo.i32EPD_Num;                                                                                                                    
                        else
                            ReqErr=1; /* Selected endpoint was not present */
                    }
                    else
                        ReqErr=1; /* Neither device,endpoint nor interface was choosen */

                    break;

                default:
                    break;
            }//device
    
            outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
            outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR);    /* clear nak so that sts stage is complete */
            outp32(CEP_IRQ_ENB, CEP_STACOM_IE);                /* suppkt int ,status and in token */
            break;

        case USBR_CLEAR_FEATURE:
            ReqErr = (((_usb_cmd_pkt.bmRequestType & 0xfc) == 0) && ((_usb_cmd_pkt.wValue & 0xfffc) == 0) 
            && ((_usb_cmd_pkt.wIndex & 0xff00) == 0) && (_usb_cmd_pkt.wLength == 0)) ? 0 : 1;

            if (usbdInfo._usbd_devstate == 1) 
                ReqErr =1; /* Device is in default state */

            if (usbdInfo._usbd_devstate == 2)
            {
                if((_usb_cmd_pkt.bmRequestType == 2) && (_usb_cmd_pkt.wIndex != 0)) //ep but not cep
                    ReqErr =1; /* Device is in Addressed State, but for noncep */
                else if(_usb_cmd_pkt.bmRequestType == 0x1)    //recip is interface
                    ReqErr=1;    /* Device is in Addressed State, but for interface */
            }
            if(ReqErr == 1) 
                break;    /* Request Error */

            switch((_usb_cmd_pkt.bmRequestType & 0x3))
            {
                case 0:        /* device */ 
                    if((_usb_cmd_pkt.wValue & 0x3) == DEVICE_REMOTE_WAKEUP)
                        usbdInfo.disableremotewakeup = 1;
                    else
                        ReqErr=1;    /* No such feature for device */

                    break;

                case 1:        /* interface */
                    break;

                case 2:        /* endpoint */
                    if((_usb_cmd_pkt.wValue & 0x3) == ENDPOINT_HALT)
                    {
                        //dx->chgfea=dx->feature |ENDPOINT_HALT;
                        if((_usb_cmd_pkt.wIndex & 0xF) == 0)         /* endPoint zero */
                            usbdInfo._usbd_unhaltep = 0;
                        else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPA_Num)    /* endPoint A */
                            usbdInfo._usbd_unhaltep = usbdInfo.i32EPA_Num;
                        else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPB_Num)    /* endPoint B */
                            usbdInfo._usbd_unhaltep = usbdInfo.i32EPB_Num;
                        else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPC_Num)    /* endPoint C */
                            usbdInfo._usbd_unhaltep = usbdInfo.i32EPC_Num;
                        else if((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPD_Num)    /* endPoint D */
                            usbdInfo._usbd_unhaltep = usbdInfo.i32EPD_Num;                                                                                            
                        else
                            ReqErr=1;    /* endpoint choosen was not supported */
                    }
                    else
                        ReqErr=1;    /* Neither device,interface nor endpoint was choosen */
                        
                    break;

                default:
                    break;
            }    //device

            outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
            outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR);    /* clear nak so that sts stage is complete */
            outp32(CEP_IRQ_ENB, CEP_STACOM_IE);
            break;

        case USBR_GET_STATUS:
            /* check if this is valid */
            ReqErr = (((_usb_cmd_pkt.bmRequestType & 0xfc) == 0x80) && (_usb_cmd_pkt.wValue == 0) 
            && ((_usb_cmd_pkt.wIndex & 0xff00) == 0) && (_usb_cmd_pkt.wLength == 0x2)) ? 0 : 1;

            if (usbdInfo._usbd_devstate == 1)
                ReqErr =1;    /* Device is in default State */

            if (usbdInfo._usbd_devstate == 2)
            {
                if ((_usb_cmd_pkt.bmRequestType & 0x3 == 0x2) && (_usb_cmd_pkt.wIndex != 0))
                    ReqErr =1;    /* Device is in Addressed State, but for noncep */
                else if (_usb_cmd_pkt.bmRequestType & 0x3 == 0x1)
                    ReqErr =1;    /* Device is in Addressed State, but for interface */
            }

            if (ReqErr == 1)
                break;    /* Request Error */
            
            usbdClearAllFlags();
            usbdInfo.usbdGetStatus=1;
            
            switch (_usb_cmd_pkt.bmRequestType & 0x3)
            {
                case 0:
                    if (usbdInfo.remotewakeup == 1)
                        usbdInfo.usbdGetStatusData = 0x3;
                    else 
                        usbdInfo.usbdGetStatusData = 0x1;
                    break;

                case 1:    /* interface */
                    if (_usb_cmd_pkt.wIndex == 0)
                        usbdInfo.usbdGetStatusData = 0;    /* Status of interface zero */
                    else
                        ReqErr=1;    /* Status of interface non zero */

                    break;

                case 2:    /* endpoint */
                    if (_usb_cmd_pkt.wIndex == 0x0)
                        usbdInfo.usbdGetStatusData = 0;    /* Status of Endpoint zero */
                    else if (((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPA_Num )||
                            ((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPB_Num )||    
                            ((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPC_Num )||
                            ((_usb_cmd_pkt.wIndex & 0xF) == usbdInfo.i32EPD_Num )                
                    )
                    {
                        /* Status of Endpoint one */    
                        if (usbdInfo._usbd_haltep == (_usb_cmd_pkt.wIndex & 0xF))
                            usbdInfo.usbdGetStatusData = 0x1;
                        else
                            usbdInfo.usbdGetStatusData = 0;
                    }                    
                    else
                        ReqErr=1;    /* Status of non-existing Endpoint */
                        
                    break;

                default:
                    break;
            }
            outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
            outp32(CEP_IRQ_ENB, CEP_IN_TK_IE);        //suppkt int ,status and in token
            break;

        default:
            break;
    }
    if (ReqErr == 1)
    {
        outp32(CEP_IRQ_ENB, (inp32(CEP_IRQ_ENB) | (CEP_SETUP_TK_IE |CEP_SETUP_PK_IE)));                        
        outp32(CEP_CTRL_STAT, CEP_SETUP_PK_IS);

    }    
}


VOID usbd_isr(void)
{
    UINT32 volatile IrqStL, IrqEnL, IrqSt, IrqEn;

    IrqStL = inp32(IRQ_STAT_L);    /* Wnat kind od EP's interrupt */
    IrqEnL = inp32(IRQ_ENB_L);    /* Which EP'S interrupt is enable */

    if (!(IrqStL & IrqEnL))
        return;

    /* USB interrupt */
    if (IrqStL & IRQ_USB_STAT)
    {
        IrqSt = inp32(USB_IRQ_STAT);
        IrqEn = inp32(USB_IRQ_ENB);

        if(IrqSt & USB_VBUS & IrqEn)
        {
            if(inp32(PHY_CTL) & Vbus_status)
            {
                usbdInfo._usbd_devstate = 1;    /* default state */
                usbdInfo._usbd_address = 0;        /* zero */
    
                if(usbdInfo.pfnPlug!=NULL)
                    usbdInfo.pfnPlug();    
                usbdInfo.u32VbusStatus = 1;
                usbdStatus.usbConnected = 1;
                outp32(PHY_CTL, (0x20 | Phy_suspend | vbus_detect));                        
            }
            else
            {
                if(usbdInfo.pfnUnplug!=NULL)
                    usbdInfo.pfnUnplug();        
                usbdInfo.u32VbusStatus = 0;    
                usbdStatus.usbConnected = 0;
                usbdInfo.USBModeFlag =0;
                usbdInfo.AlternateFlag = 0;
                usbdStatus.appConnected = 0;
                usbdInfo.AlternateFlag_Audio = 0;
                usbdStatus.appConnected_Audio = 0;
                usbdClearAllFlags();
                g_bHostAttached = FALSE;
                outp32(PHY_CTL, (0x20 | Phy_suspend));
            }
            outp32(USB_IRQ_STAT, VBUS_IS);
            
        }
        if (IrqSt & SOF_IS & IrqEn)
        {
            if(usbdInfo.pfnSOF!=NULL)
                usbdInfo.pfnSOF();
            g_bHostAttached = TRUE;                
            outp32(USB_IRQ_STAT, SOF_IS);
        }

        if (IrqSt & RST_IS & IrqEn)
        {
            usbdInfo._usbd_devstate = 0;
            usbdInfo._usbd_speedset = 0;
            usbdInfo._usbd_address = 0;

            /* clear flags */
            usbdClearAllFlags();
            usbdInfo.USBModeFlag=0;
            usbdInfo._usbd_DMA_Flag=0;
            usbdInfo._usbd_DMA_In=1;
            g_bHostAttached = TRUE;    
            /* reset dma */
            if(usbdInfo.pfnReset!=NULL)
                usbdInfo.pfnReset();            
            
            outp32(DMA_CTRL_STS, RST_DMA);
            {
                UINT32 iii;
                for (iii=0; iii<0x100; iii++);
            }
            outp32(DMA_CTRL_STS, 0);

            usbdInfo._usbd_devstate = 1;    /* default state */
            usbdInfo._usbd_address = 0;        /* zero */
#ifdef __USBD_STANDARD_MODE__        
            if (inp32(OPER) & CUR_SPD)// 1:High Speed ; 0:Full speed
            {
                usbdInfo._usbd_speedset = 2;        
                usbdInfo.pfnHighSpeedInit();
            }
            else    
            {
                usbdInfo._usbd_speedset = 1;        
                usbdInfo.pfnFullSpeedInit();
            }
#else

    #ifdef __USBD_HIGH_SPEED_MODE__    
                {
                    usbdInfo._usbd_speedset = 2;        /* for high speed */
                    usbdInfo.pfnHighSpeedInit();
                }
    #endif

    #ifdef __USBD_FULL_SPEED_MODE__                
                {
                    usbdInfo._usbd_speedset = 1;        /* or full speed */
                    usbdInfo.pfnFullSpeedInit();
                }
    #endif            
            
#endif        
            
            outp32(CEP_IRQ_ENB, CEP_SETUP_PK_IE);                /* enable stetup interrupt */

            if(usbdInfo.i32EPA_Num != -1)
            {
                outp32(EPA_RSP_SC, 0);
                outp32(EPA_RSP_SC, BUF_FLUSH);    /* flush fifo */
                outp32(EPA_RSP_SC, TOGGLE);
            }            
            if(usbdInfo.i32EPB_Num != -1)
            {
                outp32(EPB_RSP_SC, 0);
                outp32(EPB_RSP_SC, BUF_FLUSH);    /* flush fifo */
                outp32(EPB_RSP_SC, TOGGLE);
            }            
            if(usbdInfo.i32EPC_Num != -1)
            {
                outp32(EPC_RSP_SC, 0);
                outp32(EPC_RSP_SC, BUF_FLUSH);    /* flush fifo */
                outp32(EPC_RSP_SC, TOGGLE);
            }            
            if(usbdInfo.i32EPD_Num != -1)
            {
                outp32(EPD_RSP_SC, 0);
                outp32(EPD_RSP_SC, BUF_FLUSH);    /* flush fifo */
                outp32(EPD_RSP_SC, TOGGLE);
            }    

            outp32(ADDR, 0);
            outp32(USB_IRQ_STAT, RST_IS);
            outp32(USB_IRQ_ENB, (RST_IE|SUS_IE|RUM_IE|VBUS_IE));            
            outp32(CEP_IRQ_STAT, ~(CEP_SETUP_TK_IS | CEP_SETUP_PK_IS));
        }

        if (IrqSt & RUM_IS & IrqEn)
        {
            usbdInfo._usbd_resume = 1;
            outp32(USB_IRQ_STAT, RUM_IS);        /* Resume */
            g_bHostAttached = TRUE;    
            outp32(USB_IRQ_ENB, (USB_RST_STS|USB_SUS_REQ|VBUS_IE));
        }

        if (IrqSt & SUS_IS & IrqEn)
        {
            int volatile i;
            int volatile test;
            usbdInfo._usbd_resume = 0;
            g_bHostAttached = TRUE;    
#ifdef __USBD_FULL_SPEED_MODE__                
            outp32(USB_IRQ_ENB, (USB_RST_STS|USB_RESUME|VBUS_IE));
#endif            

            test = inp32(PHY_CTL) & Vbus_status;        
            for(i=0;i<0x90000;i++)
            {        
                    
                if(test != (inp32(PHY_CTL) & Vbus_status))
                {
                    if(inp32(PHY_CTL) & Vbus_status)
                    {
                        usbdInfo.u32VbusStatus = 1;
                        usbdStatus.usbConnected = 1;
                        outp32(PHY_CTL, (0x20 | Phy_suspend | vbus_detect));    
                    }
                    else    
                    {
                        outp32(USB_IRQ_ENB, (USB_RST_STS|USB_RESUME|VBUS_IE));
                        usbdInfo.u32VbusStatus = 0;    
                        usbdStatus.usbConnected = 0;
                        usbdInfo.USBModeFlag =0;
                        usbdInfo.AlternateFlag = 0;
                        usbdStatus.appConnected = 0;
                        usbdInfo.AlternateFlag_Audio = 0;
                        usbdStatus.appConnected_Audio = 0;
                        outp32(PHY_CTL, (0x20 | Phy_suspend));
                    //    sysprintf("Unplug(S)!!\n");
                    }
                    outp32(USB_IRQ_STAT, VBUS_IS);
                    break;
                }

            }    
            outp32(USB_IRQ_STAT, SUS_IS);        /* Suspend */
            outp32(USB_IRQ_ENB, (USB_RST_STS|USB_RESUME|VBUS_IE));
        }

        if (IrqSt & HISPD_IS & IrqEn)
        {
            usbdInfo._usbd_devstate = 1;            /* default state */
            usbdInfo._usbd_speedset = 2;            /* for high speed */
            usbdInfo._usbd_address = 0;                /* zero */
            g_bHostAttached = TRUE;    
            outp32(CEP_IRQ_ENB, CEP_SETUP_PK_IE);    /* enable stetup interrupt */
            outp32(USB_IRQ_STAT, HISPD_IS);
        }
        
        if (IrqSt & DMACOM_IS & IrqEn)    /* DMA Completion */
        {
            usbdInfo._usbd_DMA_Flag = 1;
            g_bHostAttached = TRUE;    
            outp32(USB_IRQ_STAT, DMACOM_IS);    
            
            if(usbdInfo.pfnDMACompletion!=NULL)
                usbdInfo.pfnDMACompletion();    
    
            
        }

        if (IrqSt & TCLKOK_IS & IrqEn)
            outp32(USB_IRQ_STAT, TCLKOK_IS);    
            
        outp32(IRQ_STAT_L, IRQ_USB_STAT);    
    }
    /* Control Endpoint Interrupt */
    if (IrqStL & IRQ_CEP) 
    {
        IrqSt = inp32(CEP_IRQ_STAT);
        IrqEn = inp32(CEP_IRQ_ENB);
        g_bHostAttached = TRUE;    
//sysprintf("Control IRQ status = %x, ControlIRQ Enable=%x\n", IrqSt, IrqEn);
        if (IrqSt & CEP_SUPTOK & IrqEn)    /* SETUP TOKEN */
        {
            outp32(CEP_IRQ_STAT, CEP_SETUP_TK_IS);
            return;
        }

        if (IrqSt & CEP_SUPPKT & IrqEn)    /* SETUP PACKET */
        {    
            outp32(CEP_IRQ_STAT, CEP_SETUP_PK_IS);
            usbd_control_packet();        /* Setup Packet */
            
            return;
        }

        if (IrqSt & CEP_OUT_TOK & IrqEn)    /* OUT TOKEN */
        {
            outp32(CEP_IRQ_STAT, CEP_OUT_TK_IS);    
            
            /* DIFF */
//            outp32(CEP_IRQ_ENB, (CEP_DATA_RxED_IE|CEP_STACOM_IE));        /* suppkt int//enb sts completion int */
            return;
        }

        if (IrqSt & CEP_IN_TOK & IrqEn)
        {
            /* IN TOKEN */                
            outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
            if (!(IrqSt & CEP_STACOM_IS))
            {
                outp32(CEP_IRQ_STAT, CEP_DATA_TxED_IS);
                outp32(CEP_IRQ_ENB, CEP_DATA_TxED_IE|CEP_SETUP_PK_IE);
                usbd_send_descriptor();        /* Send DAESCRIPTOR */
            }
            else
            {
                outp32(CEP_IRQ_STAT, CEP_DATA_TxED_IS);
                outp32(CEP_IRQ_ENB, (CEP_STACOM_IE | CEP_DATA_TxED_IE));
            }
            return;
        }

        if (IrqSt & CEP_PING_TOK & IrqEn)
        {
            outp32(CEP_IRQ_STAT, CEP_PING_IS);
            return;
        }

        if (IrqSt & CEP_DATA_TXD & IrqEn)
        {
            /* DIFF */
            outp32(CEP_IRQ_STAT, (CEP_STACOM_IS|CEP_DATA_TxED_IS));
            
            if (usbdInfo._usbd_remlen_flag)
            {
                outp32(CEP_IRQ_STAT, CEP_IN_TK_IS);
                outp32(CEP_IRQ_ENB, (CEP_DATA_TxED_IE|CEP_IN_TK_IE));        /* suppkt int ,status and in token */
            }
            else
            {
                outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
                outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR);        /* clear nak so that sts stage is complete */
                outp32(CEP_IRQ_ENB, CEP_STACOM_IE);            /* suppkt int ,status and in token */

            }
            if(usbdStatus.appConnected == 1)
            {
                if(usbdInfo.u32UVC)
                    outp32(CEP_END_ADDR, 0x0);      
            }        
            return;
        }

        if (IrqSt & CEP_DATA_RXD & IrqEn)
        {        
            /* Data Packet receive(OUT) */
            if (usbdInfo.CLASS_CMD_Oflag && usbdInfo.pfnClassDataOUTCallBack != NULL)                   
            {
                class_out_len = _usb_cmd_pkt.wLength;
                class_out_len -= inp32(OUT_TRNSFR_CNT);
                usbdInfo.pfnClassDataOUTCallBack();
                usbdInfo.CLASS_CMD_Oflag = 0;
            }
                outp32(CEP_IRQ_STAT, (CEP_DATA_RxED_IS));
                outp32(CEP_CTRL_STAT, CEP_NAK_CLEAR);        /* clear nak so that sts stage is complete */
                            
            if(class_out_len > 0)
            {
                outp32(CEP_IRQ_ENB,  CEP_DATA_RxED_IE);        // suppkt int//enb sts completion int                
            }
            else
            {
                outp32(CEP_IRQ_ENB,  (CEP_STACOM_IE|CEP_PING_IE|CEP_SETUP_PK_IE));        // suppkt int//enb sts completion int                
            
            }
            if(usbdInfo.u32UVC == 1 && usbdStatus.appConnected == 1)
            {
                
                outp32(CEP_START_ADDR, 0);
                outp32(CEP_END_ADDR, 0x0);    
            }
            return;
        }

        if (IrqSt & CEP_NAK_IS & IrqEn)
        {
            outp32(CEP_IRQ_STAT, CEP_NAK_IS);
            return;
        }

        if (IrqSt & CEP_STALL_IS & IrqEn)
        {
            outp32(CEP_IRQ_STAT, CEP_STALL_IS);
            return;
        }

        if (IrqSt & CEP_ERR_IS & IrqEn)
        {
            outp32(CEP_IRQ_STAT, CEP_ERR_IS);
            return;
        }

        if (IrqSt & CEP_STACOM_IS & IrqEn)
        {
            /* Update Device */
            usbd_update_device();            
            outp32(CEP_IRQ_STAT, CEP_STACOM_IS);
            
            /* DIFF */
            if (usbdInfo.CLASS_CMD_Iflag/* || usbdInfo.CLASS_CMD_Oflag*/ || usbdInfo._usbd_resume || usbdInfo.GET_DEV_Flag)
                usbdInfo.USBModeFlag = 1;

            outp32(CEP_IRQ_ENB, CEP_SETUP_PK_IE);
            return;
        }

        if (IrqSt & CEP_FULL_IS & IrqEn)
        {
            outp32(CEP_IRQ_STAT, CEP_FULL_IS);
            return;
        }

        if (IrqSt & CEP_EMPTY_IS & IrqEn)
        {
            outp32(CEP_IRQ_STAT, CEP_EMPTY_IS);
            return;
        }
        outp32(IRQ_STAT_L, IRQ_CEP);
    }
    /* Endpoint Interrupt */
    if (IrqStL & IRQ_NCEP) 
    {
        g_bHostAttached = TRUE;    
        if (IrqStL & EPA_INT)    /* Endpoint A */
        {
            IrqSt = inp32(EPA_IRQ_STAT);            
            IrqEn = inp32(EPA_IRQ_ENB);
            
            outp32(EPA_IRQ_STAT, IrqSt);

            if (usbdInfo.pfnEPACallBack != NULL)                   
                usbdInfo.pfnEPACallBack(IrqEn, IrqSt);  
                            
        }
        
        if (IrqStL & EPB_INT)    /* Endpoint B */
        {
            IrqSt = inp32(EPB_IRQ_STAT);
            IrqEn = inp32(EPB_IRQ_ENB);
            
            outp32(EPB_IRQ_STAT, IrqSt);

            if (usbdInfo.pfnEPBCallBack != NULL)                   
                usbdInfo.pfnEPBCallBack(IrqEn, IrqSt);  

        }

        if (IrqStL & EPC_INT)    /* Endpoint C */
        {
            IrqSt = inp32(EPC_IRQ_STAT);
            IrqEn = inp32(EPC_IRQ_ENB);
            
            outp32(EPC_IRQ_STAT, IrqSt);
            
            if (usbdInfo.pfnEPCCallBack != NULL)                   
                usbdInfo.pfnEPCCallBack(IrqEn, IrqSt);  
                            
        }
    
        if (IrqStL & EPD_INT)    /* Endpoint D */
        {
            IrqSt = inp32(EPD_IRQ_STAT);
            IrqEn = inp32(EPD_IRQ_ENB);        
            outp32(EPD_IRQ_STAT, IrqSt);
            
            if (usbdInfo.pfnEPDCallBack != NULL)                   
                usbdInfo.pfnEPDCallBack(IrqEn, IrqSt);  
        }    
        outp32(IRQ_STAT_L, IRQ_NCEP);
    }
}


usbd.h  。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

#ifndef _W55FA93_USBD_H_
#define _W55FA93_USBD_H_

/*
 * Standard requests
 */
#define USBR_GET_STATUS            0x00
#define USBR_CLEAR_FEATURE        0x01
#define USBR_SET_FEATURE        0x03
#define USBR_SET_ADDRESS        0x05
#define USBR_GET_DESCRIPTOR        0x06
#define USBR_SET_DESCRIPTOR        0x07
#define USBR_GET_CONFIGURATION    0x08
#define USBR_SET_CONFIGURATION    0x09
#define USBR_GET_INTERFACE        0x0A
#define USBR_SET_INTERFACE        0x0B
#define USBR_SYNCH_FRAME        0x0C

/*
 * Descriptor types
 */
#define USB_DT_DEVICE            0x01
#define USB_DT_CONFIG            0x02
#define USB_DT_STRING            0x03
#define USB_DT_INTERFACE        0x04
#define USB_DT_ENDPOINT            0x05
#define USB_DT_QUALIFIER        0x06
#define USB_DT_OSCONFIG            0x07
#define USB_DT_IFPOWER            0x08

#define USB_DT_HID                 0x21
#define USB_DT_HID_RPT             0x22

#define EP_INPUT    0x80
#define EP_OUTPUT    0x00

// USB Endpoint Type
#define    EP_ISO                0x01
#define    EP_BULK                0x02
#define    EP_INT                0x03
//USB FEATURE SELECTOR            value
#define DEVICE_REMOTE_WAKEUP    1
#define ENDPOINT_HALT            0
#define TEST_MODE                2

//USB TEST MODES
#define TEST_J                    0x01
#define TEST_K                    0x02
#define TEST_SE0_NAK            0x03
#define TEST_PACKET                0x04
#define TEST_FORCE_ENABLE        0x05

//Driver definition of tokens
#define OUT_TOK        0x00
#define IN_TOK        0x01
#define SUP_TOK     0x02
#define PING_TOK    0x03
#define NO_TOK        0x04

//Bit Definitions of IRQ_ENB/STAT register
#define    IRQ_USB_STAT        0x01
#define IRQ_CEP                0x02
#define IRQ_NCEP            0xfc   

//Definition of Bits in USB_IRQ_STS register

#define USB_SOF            0x01    
#define USB_RST_STS        0x02
#define    USB_RESUME        0x04
#define    USB_SUS_REQ        0x08
#define    USB_HS_SETTLE    0x10
#define    USB_DMA_REQ        0x20
#define USABLE_CLK        0x40
#define USB_VBUS        0x100
//Definition of Bits in USB_OPER register
#define USB_GEN_RES     0x1
#define USB_HS            0x2
#define USB_CUR_SPD_HS  0x4

//Definition of Bits in CEP_IRQ_STS register

#define CEP_SUPTOK         0x0001
#define CEP_SUPPKT        0x0002
#define CEP_OUT_TOK        0x0004
#define CEP_IN_TOK        0x0008
#define CEP_PING_TOK    0x0010
#define CEP_DATA_TXD    0x0020
#define CEP_DATA_RXD    0x0040
#define CEP_NAK_SENT    0x0080
#define CEP_STALL_SENT    0x0100
#define CEP_USB_ERR        0x0200
#define CEP_STS_END        0x0400
#define CEP_BUFF_FULL    0x0800
#define CEP_BUFF_EMPTY    0x1000

//Definition of Bits in CEP_CTRL_STS register
#define CEP_NAK_CLEAR        0x00  //writing zero clears the nak bit
#define CEP_SEND_STALL        0x02

//Definition of Bits in EP_IRQ_STS register

#define EP_BUFF_FULL    0x001
#define EP_BUFF_EMPTY    0x002
#define EP_SHORT_PKT    0x004
#define EP_DATA_TXD        0x008
#define EP_DATA_RXD        0x010
#define EP_OUT_TOK        0x020
#define EP_IN_TOK        0x040
#define EP_PING_TOK        0x080
#define EP_NAK_SENT        0x100
#define EP_STALL_SENT    0x200
#define EP_USB_ERR        0x800

//Bit Definitons of EP_RSP_SC Register
#define EP_BUFF_FLUSH   0x01
#define EP_MODE         0x06
#define EP_MODE_AUTO    0x01
#define EP_MODE_MAN     0x02
#define EP_MODE_FLY        0x03
#define EP_TOGGLE        0x8
#define EP_HALT            0x10
#define EP_ZERO_IN      0x20
#define EP_PKT_END      0x40

/* Define Endpoint feature */
#define Ep_In        0x01
#define Ep_Out       0x00
#define Ep_Bulk      0x01
#define Ep_Int       0x02
#define Ep_Iso       0x03
#define EP_A         0x00
#define EP_B         0x01
#define EP_C         0x02
#define EP_D         0x03

typedef struct usb_cmd
{
    UINT8    bmRequestType;
    UINT8    bRequest;
    UINT16    wValue;
    UINT16    wIndex;
    UINT16    wLength;
}    USB_CMD_T;


typedef void (*PFN_USBD_CALLBACK)(void);
typedef BOOL (PFN_USBD_EXIT_CALLBACK)(void);
typedef void (*PFN_USBD_EP_CALLBACK)(UINT32 u32IntEn,UINT32 u32IntStatus);

__packed  typedef struct{
/* Descriptor pointer */
    PUINT32 pu32DevDescriptor;
    PUINT32 pu32QulDescriptor;
    PUINT32 pu32HSConfDescriptor;
    PUINT32 pu32FSConfDescriptor;    
    PUINT32 pu32HOSConfDescriptor;
    PUINT32 pu32FOSConfDescriptor;    
    PUINT32 pu32HIDDescriptor;
    PUINT32 pu32HIDRPTDescriptor;        
    PUINT32 pu32StringDescriptor[5];
    
    /* Descriptor length */
    UINT32    u32DevDescriptorLen;    
    UINT32    u32QulDescriptorLen;    
    UINT32    u32HSConfDescriptorLen;    
    UINT32    u32FSConfDescriptorLen;    
    UINT32    u32HOSConfDescriptorLen;    
    UINT32    u32FOSConfDescriptorLen;    
    UINT32    u32HIDDescriptorLen;    
    UINT32    u32HIDRPTDescriptorLen;        
    UINT32     u32StringDescriptorLen[5];

    /* USBD Init */
    PFN_USBD_CALLBACK pfnHighSpeedInit;
    PFN_USBD_CALLBACK pfnFullSpeedInit;

    /* Endpoint Number */
    INT32    i32EPA_Num;
    INT32    i32EPB_Num;
    INT32    i32EPC_Num;
    INT32    i32EPD_Num;    
                
    /* Endpoint Call Back */    
    PFN_USBD_EP_CALLBACK pfnEPACallBack;
    PFN_USBD_EP_CALLBACK pfnEPBCallBack;    
    PFN_USBD_EP_CALLBACK pfnEPCCallBack;
    PFN_USBD_EP_CALLBACK pfnEPDCallBack;
                
    /* Class Call Back */    
    PFN_USBD_CALLBACK pfnClassDataINCallBack;
    PFN_USBD_CALLBACK pfnClassDataOUTCallBack;
    PFN_USBD_CALLBACK pfnDMACompletion;
    PFN_USBD_CALLBACK pfnReset;
    PFN_USBD_CALLBACK pfnSOF;    
    PFN_USBD_CALLBACK pfnPlug;    
    PFN_USBD_CALLBACK pfnUnplug;    
    
    /* Transfer Control */
    UINT32    _usbd_remlen;
    BOOL    _usbd_remlen_flag;
    UINT32    *_usbd_ptr;
    
    /* Command Status Control */
    UINT8    GET_DEV_Flag;
    UINT8    GET_CFG_Flag;
    UINT8    GET_QUL_Flag;
    UINT8    GET_OSCFG_Flag;
    UINT8    GET_STR_Flag;
    UINT8    GET_VEN_Flag;
    UINT8    GET_VENO_Flag;
    UINT8    GET_HID_Flag;
    UINT8    GET_HID_RPT_Flag;
    UINT8    CLASS_CMD_Flag;
    UINT8    CLASS_CMD_Iflag;
    UINT8    CLASS_CMD_Oflag;
    
    UINT32    usbdMaxPacketSize;
    
    /* DMA Status flag */
    UINT8    _usbd_DMA_Flag;
    UINT8    _usbd_DMA_In;
     
    /* Status flag */    
    UINT8    _usbd_resume;
    UINT8    USBModeFlag;   
    UINT32    _usbd_devstate;
    UINT32    _usbd_address;
    UINT32    _usbd_speedset;
    UINT16    _usbd_confsel;
    UINT16    _usbd_intfsel;
    UINT16    _usbd_altsel;
    UINT32    _usbd_feature;
    INT32    _usbd_haltep;
    INT32    _usbd_unhaltep;
    INT32    remotewakeup;
    INT32    testmode;
    INT32    enableremotewakeup;
    INT32    enabletestmode;
    INT32    disableremotewakeup;
    INT32    disabletestmode;
    INT32    testselector;
    UINT32    usbdGetStatusData;
    UINT8    usbdGetConfig;
    UINT8    usbdGetInterface;
    UINT8    usbdGetStatus;

    /* for isochronous */
    UINT32  AlternateFlag;        
    UINT32  u32VbusStatus;
    /* for Isochronous */
    UINT32  AlternateFlag_Audio;
    UINT32    u32UVC;
    UINT32  USBStartFlag;

}USBD_INFO_T;

__packed  typedef struct{
    UINT32  appConnected;        
    UINT32  usbConnected;    
    UINT32  appConnected_Audio;
}USBD_STATUS_T;


typedef struct
{
    UINT8 EP_Num;
    UINT8 EP_Dir;
    UINT8 EP_Type;
}    USB_EP_Inf_T;


VOID udcOpen(void);
VOID udcClose(void);
VOID udcInit(void);
VOID udcDeinit(void);
BOOL udcIsAttached(void);
BOOL udcIsAttachedToHost(void);

#endif

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值