/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright (C) 2014 Renesas Electronics Corporation. All rights reserved.
*******************************************************************************/
/*******************************************************************************
* File Name    : usb0_mscd_fsi.c
* $Rev: 682 $
* $Date:: 2014-01-23 09:15:07 +0900#$
* Device(s)    :
* Tool-Chain   :
* OS           : None
* H/W Platform :
* Description  : USB Sample Program
* Operation    :
* Limitations  :
*******************************************************************************/


/*******************************************************************************
Includes   <System Includes> , "Project Includes"
*******************************************************************************/
#include <stdio.h>
#include "usb_hmscd_rza1.h"
#include "usb_hmscd_fsi.h"
#include "ff.h"
#include "fat_fsi.h"


/*******************************************************************************
Typedef definitions
*******************************************************************************/

/*******************************************************************************
Macro definitions
*******************************************************************************/


/*******************************************************************************
Imported global variables and functions (from other files)
*******************************************************************************/


/*******************************************************************************
Exported global variables and functions (to be accessed by other files)
*******************************************************************************/
/*
   ==== describe sector size ====
	assign maximum sector size to support in library
*/
#define DFS_SECTOR_SIZE		2048

#define BUFF_SIZE			(DFS_SECTOR_SIZE * 8)	/* for 8 sectors */
/* USB0 = 4drive(1 or 2-5) */	/* 0-3 */
/* USB1 = 4drive(1 or 2-5) */	/* 4-7 */
/* SD   = 2drive           */	/* 8-9 */
/* MMC  = 1drive           */	/* 10  */
#define DRVNO				11
/*
  ==== dealing access time ====
  specify to renew/not renew access time of file opened as read only


  [setting range]
     0 : not renew access time（default）
     1 : renew access time

*/
#define ACCESSTIME_ENABLE	0						/* 1: to renew , 0: not to renew */

/*
  ==== Type the full path settings ====
  storing type for fullpath when specified 8.3 file name


  [setting range]
     0 : long name conversion
     1 : 8.3 file name

*/
#define FULLPATH_TYPE		0						/* long name conversion */

#define	DIR_SIZE	32				/* directory entry byte size  */

/* FAT type */
#define	FAT12		1				/* 12-bit FAT */
#define	FAT16		2				/* 16-bit FAT */
#define	FAT32		3				/* 32-bit FAT */
#define	EXFAT		4				/* EXFAT */

#define PATH_LENGTH 260

unsigned long dfs_rw_buff[BUFF_SIZE/sizeof(unsigned long)] __attribute__ ((section ("BSS_FAT_NC")));

/* These are management variables for each drive. 314 bytes are needed for one drive. */
unsigned char dfs_dev_flag[DRVNO];			/* device state flag */
unsigned char dfs_fat_type[DRVNO];			/* FAT type (1=FAT12, 2=FAT16, 3=FAT32, 4=exFAT) */
unsigned long dfs_cluster_size[DRVNO];		/* number of sectors for one cluster */
unsigned char dfs_fat_count[DRVNO];			/* number of FAT (generally, 2) */
unsigned char dfs_mediatype[DRVNO];			/* media type */

unsigned short dfs_sector_size[DRVNO];		/* byte count for one sector */

unsigned long dfs_fat_sector[DRVNO];		/* number of sector for one FAT */
unsigned long dfs_fsinfo_sector[DRVNO];		/* file system information sector number */

unsigned long dfs_total_sector[DRVNO];		/* total number of sectors */
unsigned long dfs_fat_top[DRVNO];			/* beginning FAT sector number */
unsigned long dfs_rootdir_top[DRVNO];	    /* beginning sector number of root direcotry information  */
unsigned long dfs_data_top[DRVNO];			/* beginning sector number of data area */
unsigned long dfs_currentdir_top[DRVNO];	/* beginning sector number of current directory */
unsigned long dfs_fat_start[DRVNO];			/* cluster number for starting FAT search */
unsigned long dfs_free_cluster[DRVNO];		/* number of unused cluster */
char dfs_DeviceIsModified[DRVNO];			/* drive change check flag for FAT 32 */
char dfs_fullpath[DRVNO][PATH_LENGTH*2];

unsigned short dfs_track_sector[DRVNO];		/* number of sector for one track */
unsigned long dfs_cylinder_sector[DRVNO];	/* number of sectors for one cylinder */
unsigned long dfs_offset_sector[DRVNO];		/* beginning sector number of boot table */

/***************************************************************************/
const int dfs_drv_num = DRVNO; /* maximum number of drives */
const unsigned long dfs_buff_size = BUFF_SIZE; /* buffer size for copying */
unsigned char dfs_accesstime_enable=ACCESSTIME_ENABLE; /* renewed/unrenewed access time at file closing  */
unsigned char dfs_fullpath_type = FULLPATH_TYPE; /* storing type for fullpath when specified 8.3 file name  (0: long name conversion , 1:8.3 file name ) */


/*******************************************************************************
Private global variables and functions
*******************************************************************************/
static uint32_t    g_usb0_hmscd_fsi_work[ USB_HMSCD_FSI_WORK_SIZE / sizeof( uint32_t ) ] __attribute__ ((section ("BSS_FAT_NC")));
static uint8_t     g_usb0_hmscd_fsi_inquiry_data[ 36 ] __attribute__ ((section ("BSS_FAT_NC")));

static USB_HMSCD_FSI_DEVICE_INFO_t    g_usb0_hmscd_fsi_fat_info[ USB_HMSCD_FSI_MAX_DEVICE_NUM ];
static USB_HMSCD_FSI_PBR_INFO_t       g_usb0_hmscd_fsi_pbr_info[ USB_HMSCD_FSI_MAX_DRIVE ];
static int32_t                        g_usb0_hmscd_fsi_mount_drv;
static int32_t                        g_usb0_hmscd_fsi_test_unit_enable[USB_HMSCD_FSI_MAX_DEVICE_NUM][USB_HMSCD_FSI_USB_MAX_UNIT];
static int32_t                        g_usb0_hmscd_fsi_test_unit_count[USB_HMSCD_FSI_MAX_DEVICE_NUM][USB_HMSCD_FSI_USB_MAX_UNIT];

static int32_t    usb0_fsi_check_partition_record( uint8_t *Data );
static int32_t    usb0_fsi_file_system_initialize( int32_t side, uint32_t offset_sector, uint8_t *Data );
static int32_t    usb0_fsi_check_boot_record( uint8_t *Data, uint32_t *ParLBA, uint8_t *PerInfo );
static int32_t    usb0_fsi_test_unit_retry( uint16_t devadr, uint16_t unit);
static int32_t    usb0_fsi_check_boot( uint16_t device_address, uint16_t unit_number, int32_t *drive, int32_t *drvnum );


/*******************************************************************************
* Function Name: usb0_fsi_dev_open
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
int32_t usb0_fsi_dev_open( int32_t side )
{
    int32_t           ret2;
    int32_t           ret;
    int32_t           usb_side;
    USB_HMSCD_RW_t    mscd_rw;
    uint32_t          bytes;
    uint8_t           cswstatus;
    uint32_t          offset_sector;

    usb_side = (side - FAT_DRV_USB0_0);
    if( usb_side > USB_HMSCD_FSI_MAX_DRIVE )
    {
        return -1;
    }

    if( usb_side < USB_HMSCD_FSI_USB_DRIVE )
    {
        return -1;
    }

    if( g_usb0_hmscd_fsi_pbr_info[ usb_side ].ready == 0 )
    {
        return -1;
    }


    if( g_usb0_hmscd_fsi_pbr_info[ usb_side ].sector_size > sizeof(g_usb0_hmscd_fsi_work) )
    {
        printf("SECTOR SIZE is over %d\n", g_usb0_hmscd_fsi_pbr_info[ usb_side ].sector_size);
        return -1;
    }

    offset_sector = (g_usb0_hmscd_fsi_pbr_info[ usb_side ].pbr_lsn + g_usb0_hmscd_fsi_pbr_info[ usb_side ].mbr_lsn);

    mscd_rw.device_address = g_usb0_hmscd_fsi_pbr_info[ usb_side ].device_address;
    mscd_rw.unit_number    = g_usb0_hmscd_fsi_pbr_info[ usb_side ].unit_number;
    mscd_rw.buffer         = (uint8_t *)&g_usb0_hmscd_fsi_work[0];
    mscd_rw.sector_number  = offset_sector;
    mscd_rw.sector_count   = 1;
    mscd_rw.transfer_bytes = g_usb0_hmscd_fsi_pbr_info[ usb_side ].sector_size;

    ret = usb0_api_hmscd_read10( &mscd_rw, &bytes, &cswstatus );
    if( ( ret != USB_HMSCD_SUCCESS ) || ( cswstatus != USB_HMSCD_CSW_PASS ) )
    {
        g_usb0_hmscd_fsi_test_unit_enable[mscd_rw.device_address - 1][mscd_rw.unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
        g_usb0_hmscd_fsi_test_unit_count[mscd_rw.device_address - 1][mscd_rw.unit_number]  = 0;
        return -1;
    }

    ret2 = usb0_fsi_check_partition_record( (uint8_t *)&g_usb0_hmscd_fsi_work[0] );
    if( ret2 != USB_HMSCD_SUCCESS )
    {
        return -1;
    }

    ret2 = usb0_fsi_file_system_initialize( side, offset_sector, (uint8_t *)&g_usb0_hmscd_fsi_work[0] );
    if( ret2 != USB_HMSCD_SUCCESS )
    {
        return -1;
    }

    return 0;
}

/*******************************************************************************
* Function Name: usb0_fsi_dev_close
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
int32_t usb0_fsi_dev_close( int32_t side )
{
    int32_t    usb_side;

    usb_side = (side - FAT_DRV_USB0_0);
    if( usb_side > USB_HMSCD_FSI_MAX_DRIVE )
    {
        return -1;
    }

    if( usb_side < USB_HMSCD_FSI_USB_DRIVE )
    {
        return -1;
    }

    return 0;
}

/*******************************************************************************
* Function Name: usb0_fsi_test_unit_retry
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
static int32_t usb0_fsi_test_unit_retry( uint16_t devadr, uint16_t unit )
{
    int32_t    retry;
    int32_t    ret;

    for( retry = 0; retry < 3; retry++ )
    {
        /* TestUnitReadyを実行                         */
        ret = usb0_api_hmscd_unit_search( devadr, unit, 1 );
        if( ret == USB_HMSCD_SUCCESS )
        {
            return 0;        /* リトライする           */
        }
        else if( ret == USB_HMSCD_NO_MEDIA )
        {
            return -1;        /* リトライしない        */
        }
        else if( ret == USB_HMSCD_DETACH )
        {
            return -1;        /* リトライしない        */
        }
        else
        {
            /* TestUnitReadyのリトライ                 */
        }
    }

    /* リトライ回数オーバー                            */
    return -1;                /* リトライしない        */
}

/*******************************************************************************
* Function Name: usb0_fsi_dev_read_sector
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
int32_t usb0_fsi_dev_read_sector( int32_t side, uint8_t *buffer,
                                  uint32_t sector_number, int32_t sector_count )
{
    int32_t           ret;
    int32_t           error2;
    int32_t           error;
    USB_HMSCD_RW_t    mscd_rw;
    uint32_t          bytes;
    uint8_t           cswstatus;
    int32_t           usb_side;

    usb_side = (side - FAT_DRV_USB0_0);

    mscd_rw.device_address = g_usb0_hmscd_fsi_pbr_info[ usb_side ].device_address;
    mscd_rw.unit_number    = g_usb0_hmscd_fsi_pbr_info[ usb_side ].unit_number;
    mscd_rw.sector_number  = (sector_number + dfs_offset_sector[side]);
    mscd_rw.transfer_bytes = ( (uint32_t)sector_count * dfs_sector_size[ side ] );
    mscd_rw.sector_count   = (uint32_t)sector_count;
    mscd_rw.buffer         = buffer;

    /* read function */
    error = usb0_api_hmscd_read10( &mscd_rw, &bytes, &cswstatus );
    if( error != USB_HMSCD_SUCCESS )
    {
        if( error == USB_HMSCD_TIMEOUT )
        {
            ret = -1;        /* リトライしない        */
        }
        else if( error == USB_HMSCD_NAK_TIMEOUT )
        {
            ret = -1;        /* リトライしない        */
        }
        else if( error == USB_HMSCD_DETACH )
        {
            ret = -1;        /* リトライしない        */
        }
        else if( error == USB_HMSCD_ERROR )
        {
            ret = -1;        /* リトライしない        */
        }
        else if( error == USB_HMSCD_COM_ERR )
        {
            ret = -1;        /* リトライしない        */
        }
        else if( error == USB_HMSCD_DEV_ADDR_ERR )
        {
            ret = -1;        /* リトライしない        */
        }
        else
        {
            /* USB_HMSCD_TAGERR, USB_HMSCD_STALL, USB_HMSCD_SUCCESS_CSW_PHASE_ERROR */
            error2 = usb0_fsi_test_unit_retry( mscd_rw.device_address, mscd_rw.unit_number);
            if( error2 == 0 ){
                ret = -2;    /* リトライする          */
            }
            else{
                ret = -1;    /* リトライはしない      */
                             /* TestUnitReady実行中にUSB_HMSCD_ERRORやMSCD_COMが発生したら */
                             /* USB切断→再接続要求発行済み                                */
            }
        }
    }
    else if( cswstatus != USB_HMSCD_CSW_PASS )
    {
        /* CSWエラー */
        error2 = usb0_fsi_test_unit_retry( mscd_rw.device_address, mscd_rw.unit_number);
        if( error2 == 0 )
        {
            ret = -2;        /* リトライする          */
        }
        else
        {
            ret = -1;        /* リトライはしない      */
                             /* TestUnitReady実行中にUSB_HMSCD_ERRORやMSCD_COMが発生したら */
                             /* USB切断→再接続要求発行済み                                */
        }
    }
    else
    {
        /* USB_HMSCD_SUCCESS && USB_HMSCD_CSW_PASS */
        ret = 0;            /* READ10成功          */
    }

    if( ret == -1 )
    {
        /* もうリトライしないのでTestUnitReadyによるドライブ切断検出を再開 */
        g_usb0_hmscd_fsi_test_unit_enable[mscd_rw.device_address - 1][mscd_rw.unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
        g_usb0_hmscd_fsi_test_unit_count[mscd_rw.device_address - 1][mscd_rw.unit_number]  = 0;
    }

    return ret;
}

/*******************************************************************************
* Function Name: usb0_fsi_dev_write_sector
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
int32_t usb0_fsi_dev_write_sector( int32_t side, uint8_t *buffer,
                                   uint32_t sector_number, int32_t sector_count )
{
    int32_t           error;
    USB_HMSCD_RW_t    mscd_rw;
    uint32_t          bytes;
    uint8_t           cswstatus;
    int32_t           usb_side;

    usb_side = (side - FAT_DRV_USB0_0);

    mscd_rw.device_address = g_usb0_hmscd_fsi_pbr_info[ usb_side ].device_address;
    mscd_rw.unit_number    = g_usb0_hmscd_fsi_pbr_info[ usb_side ].unit_number;
    mscd_rw.sector_number  = (sector_number + dfs_offset_sector[ side ]);
    mscd_rw.transfer_bytes = ( (uint32_t)sector_count * dfs_sector_size[ side ] );
    mscd_rw.sector_count   = (uint32_t)sector_count;
    mscd_rw.buffer         = buffer;

    /* write function */
    error = usb0_api_hmscd_write10( &mscd_rw, &bytes, &cswstatus );
    if( (error != USB_HMSCD_SUCCESS) || (cswstatus != USB_HMSCD_CSW_PASS) )
    {
        return -1;
    }

    return 0;
}

/*******************************************************************************
* Function Name: usb0_fsi_init
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
void usb0_fsi_init(void)
{
    int32_t    drive;
    int32_t    devadr;
    int32_t    unit;

    g_usb0_hmscd_fsi_mount_drv = 0;

    for( devadr = 0 ; devadr < USB_HMSCD_FSI_MAX_DEVICE_NUM ; ++devadr )
    {
        for( unit = 0 ; unit < USB_HMSCD_FSI_USB_MAX_UNIT ; ++unit )
        {
            g_usb0_hmscd_fsi_fat_info[ devadr ].device[ unit ].ready = USB_HMSCD_FSI_DEVICE_NOTREADY;
            g_usb0_hmscd_fsi_fat_info[ devadr ].device[ unit ].type  = USB_HMSCD_PDT_UNKNOWN;
            g_usb0_hmscd_fsi_fat_info[ devadr ].mount_drive[ unit ]  = 0;

            g_usb0_hmscd_fsi_test_unit_enable[ devadr ][ unit ] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
            g_usb0_hmscd_fsi_test_unit_count[ devadr ][ unit ]  = 0;

        }
        g_usb0_hmscd_fsi_fat_info[ devadr ].max_lun = 0;
    }

    for( drive = 0 ; drive < USB_HMSCD_FSI_MAX_DRIVE ; ++drive )
    {
        g_usb0_hmscd_fsi_pbr_info[ drive ].ready          = 0;
        g_usb0_hmscd_fsi_pbr_info[ drive ].device_address = 0;
        g_usb0_hmscd_fsi_pbr_info[ drive ].unit_number    = 0;
        g_usb0_hmscd_fsi_pbr_info[ drive ].pbr_lsn        = 0;
        g_usb0_hmscd_fsi_pbr_info[ drive ].mbr_lsn        = 0;
        g_usb0_hmscd_fsi_pbr_info[ drive ].sector_size    = 0;
    }
}

/*******************************************************************************
* Function Name: usb0_fsi_clear
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
void usb0_fsi_clear( uint16_t device_address )
{
    int32_t    devadr;
    int32_t    unit;
    int32_t    drive;

    devadr = (int32_t)(device_address - 1);
    for( unit = 0; unit < USB_HMSCD_FSI_USB_MAX_UNIT; unit++ )
    {
        g_usb0_hmscd_fsi_fat_info[ devadr ].device[ unit ].ready = USB_HMSCD_FSI_DEVICE_NOTREADY;
        g_usb0_hmscd_fsi_fat_info[ devadr ].device[ unit ].type  = USB_HMSCD_PDT_UNKNOWN;
        g_usb0_hmscd_fsi_fat_info[ devadr ].mount_drive[ unit ]  = 0;

        g_usb0_hmscd_fsi_test_unit_enable[ devadr ][ unit ] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
        g_usb0_hmscd_fsi_test_unit_count[ devadr ][ unit ]  = 0;
    }
    g_usb0_hmscd_fsi_fat_info[ devadr ].max_lun = 0;

    for( drive = 0 ; drive < USB_HMSCD_FSI_MAX_DRIVE ; ++drive )
    {
        if( g_usb0_hmscd_fsi_pbr_info[ drive ].device_address == device_address )
        {
            g_usb0_hmscd_fsi_pbr_info[ drive ].ready = 0;

            if( g_usb0_hmscd_fsi_mount_drv > 0 )
            {
                --g_usb0_hmscd_fsi_mount_drv;
                printf(
                    "USB detach drive=%d device_address=%d total_drive=%d\n",
                     drive, device_address, g_usb0_hmscd_fsi_mount_drv );
            }
        }
    }
}

/*******************************************************************************
* Function Name: usb0_fsi_drv_clear
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
void usb0_fsi_drv_clear(uint16_t device_address, uint16_t unit_number)
{
    int32_t    devadr_ofst;
    int32_t    drive;

    devadr_ofst = (int32_t)(device_address - 1);
    g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].mount_drive[ unit_number ] = 0;
    g_usb0_hmscd_fsi_test_unit_enable[ devadr_ofst ][ unit_number ]     = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
    g_usb0_hmscd_fsi_test_unit_count[ devadr_ofst ][ unit_number ]      = 0;

    for(drive = 0 ; drive < USB_HMSCD_FSI_MAX_DRIVE ; ++drive)
    {
        if( (g_usb0_hmscd_fsi_pbr_info[ drive ].device_address == device_address) &&
            (g_usb0_hmscd_fsi_pbr_info[ drive ].unit_number    == unit_number)       )
        {
            g_usb0_hmscd_fsi_pbr_info[ drive ].ready = 0;

            if(g_usb0_hmscd_fsi_mount_drv > 0)
            {
                --g_usb0_hmscd_fsi_mount_drv;
            }
        }
    }
}

/*******************************************************************************
* Function Name: usb0_fsi_drive_search
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
void usb0_fsi_drive_search( uint16_t device_address )
{
    int32_t     temp_drv;
    int32_t     loop;
    int32_t     mount_trig;
    int32_t     devadr_ofst;
    int32_t     add_drv;
    int32_t     add_drvnum[ USB_HMSCD_FSI_MAX_DRIVE ];
    int32_t     ret;
    uint16_t    unit_number;
    uint16_t    max_lun_num;
    uint8_t     maxunit;
    uint32_t    bytes;
    uint8_t     cswstatus = USB_HMSCD_CSW_FAIL;

    devadr_ofst = (int32_t)(device_address - 1);

    if( g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].max_lun  == 0 )
    {
        printf( "search drive \n" );

        for( unit_number = 0; unit_number < USB_HMSCD_FSI_USB_MAX_UNIT; unit_number++ )
        {
            g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready = USB_HMSCD_FSI_DEVICE_NOTREADY;
            g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].type  = USB_HMSCD_PDT_UNKNOWN;
            g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].mount_drive[ unit_number ]  = 0;
        }

        ret = usb0_api_hmscd_get_max_unit( device_address, &maxunit );
        if( ret != USB_HMSCD_SUCCESS )
        {
            if( ret != USB_HMSCD_STALL ){
                return;
            }
            printf( "Get Max Unit Error\n" );
        }

        /* Number of drive is change                        */
        g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].max_lun = (int32_t)(maxunit + 1);
    }

    max_lun_num = (uint16_t)g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].max_lun;

    mount_trig = 0;
    for( unit_number = 0; unit_number < max_lun_num; unit_number++ )
    {
        if( g_usb0_hmscd_fsi_test_unit_enable[devadr_ofst][unit_number] == USB_HMSCD_FSI_TEST_UNIT_ENABLE )
        {
            ret = usb0_api_hmscd_unit_search( device_address, unit_number, 10 );
            if( ret == USB_HMSCD_SUCCESS )
            {
                if( g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready == USB_HMSCD_FSI_DEVICE_NOTREADY )
                {
                    /* State is changed to ready     */
                    mount_trig = 1;
                    g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready = USB_HMSCD_FSI_DEVICE_CHANGE_TO_READY;
                    g_usb0_hmscd_fsi_test_unit_enable[devadr_ofst][unit_number] = USB_HMSCD_FSI_TEST_UNIT_DISABLE;
                    g_usb0_hmscd_fsi_test_unit_count[devadr_ofst][unit_number]  = 0;

                    for( loop = 0; loop < USB_HMSCD_FSI_INQUIRY_COUNT; loop++ )
                    {
                        /* Issue INQUIRY command    */
                        ret = usb0_api_hmscd_inquiry( device_address, unit_number,
                                                            &bytes, &cswstatus,
                                                            (uint8_t *)&g_usb0_hmscd_fsi_inquiry_data[ 0 ] );
                        if( (ret == USB_HMSCD_SUCCESS) && (cswstatus == USB_HMSCD_CSW_PASS) )
                        {
                            /* State is pass        */
                        }
                        else if(cswstatus != USB_HMSCD_CSW_PASS)
                        {
                            /* State is busy        */
                            printf("INQUIRY CSW ERROR %d st time\n", loop);
                        }
                        else
                        {
                            /* State is busy        */
                            printf("INQUIRY ERROR %d st time\n", loop);
                        }
                    }

                    if( (ret == USB_HMSCD_SUCCESS) && (cswstatus == USB_HMSCD_CSW_PASS) )
                    {
                        g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].type = (int32_t)g_usb0_hmscd_fsi_inquiry_data[ 0 ];

                    }
                    else if(cswstatus != USB_HMSCD_CSW_PASS)
                    {
                        /* State is busy        */
                        printf("INQUIRY CSW ERROR Finaly\n");
                        g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready = USB_HMSCD_FSI_DEVICE_NOTREADY;
                        g_usb0_hmscd_fsi_test_unit_enable[devadr_ofst][unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
                        g_usb0_hmscd_fsi_test_unit_count[devadr_ofst][unit_number]  = 0;
                    }
                    else
                    {
                        /* State is busy            */
                        printf("INQUIRY ERROR Finaly\n");
                        g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready = USB_HMSCD_FSI_DEVICE_NOTREADY;
                        g_usb0_hmscd_fsi_test_unit_enable[devadr_ofst][unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
                        g_usb0_hmscd_fsi_test_unit_count[devadr_ofst][unit_number]  = 0;
                    }
                }
            }
            else if( ret == USB_HMSCD_NO_MEDIA )
            {
                if( g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready == USB_HMSCD_FSI_DEVICE_READY )
                {
                    /* State is changed to busy     */
                    usb0_fsi_drv_clear( device_address, unit_number );
                    printf("ERROR USB device_address=%d unit_number=%d is ready but Medium is not present \n",    device_address, unit_number);
                }

                /* State is busy                    */
                g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready = USB_HMSCD_FSI_DEVICE_NOTREADY;
                g_usb0_hmscd_fsi_test_unit_enable[devadr_ofst][unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
                g_usb0_hmscd_fsi_test_unit_count[devadr_ofst][unit_number]  = 0;
            }
            else
            {
                g_usb0_hmscd_fsi_test_unit_enable[devadr_ofst][unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
                g_usb0_hmscd_fsi_test_unit_count[devadr_ofst][unit_number]  = 0;
            }
        }
        else
        {
            g_usb0_hmscd_fsi_test_unit_count[devadr_ofst][unit_number] += 1;
            if( g_usb0_hmscd_fsi_test_unit_count[devadr_ofst][unit_number] == 10 )
            {
                g_usb0_hmscd_fsi_test_unit_enable[devadr_ofst][unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
                g_usb0_hmscd_fsi_test_unit_count[devadr_ofst][unit_number]  = 0;
            }
        }
    }


    temp_drv = g_usb0_hmscd_fsi_mount_drv;

    if( mount_trig == 1 )
    {
        for( unit_number = 0; unit_number < max_lun_num; unit_number++ )
        {
            if( (g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready == USB_HMSCD_FSI_DEVICE_CHANGE_TO_READY) &&
                (g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].type  == USB_HMSCD_PDT_DIRECT) )
            {

                ret = usb0_fsi_check_boot( device_address, unit_number, &add_drv, &add_drvnum[ 0 ] );
                if( ret == 1 )
                {
                    g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready = USB_HMSCD_FSI_DEVICE_READY;

                    /* The count of mounted drive change */
                    g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].mount_drive[ unit_number ] += add_drv;
                    g_usb0_hmscd_fsi_mount_drv += add_drv;
                }
                else
                {
                    g_usb0_hmscd_fsi_fat_info[ devadr_ofst ].device[ unit_number ].ready = USB_HMSCD_FSI_DEVICE_NOTREADY;
                }
            }
        }
    }

    if( g_usb0_hmscd_fsi_mount_drv != temp_drv )
    {
        printf( "USB device_address=%d total_drive=%d\n", device_address, g_usb0_hmscd_fsi_mount_drv );
    }
}

/*******************************************************************************
* Function Name: usb0_fsi_file_system_initialize
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
static int32_t usb0_fsi_file_system_initialize( int32_t side, uint32_t offset_sector, uint8_t *Data )
{
    uint32_t    clus_num;
    uint32_t    rootdir_entry;
    uint8_t     *rw_buff = (uint8_t *)Data;

    /* Check  Partition BootSector signature */
    if ( (0x55 != rw_buff[0x1fe]) || (0xaa != rw_buff[0x1ff]) )
    {
        return -2;    /* Boot code Error */
    }

    dfs_offset_sector[side] = offset_sector;

    dfs_sector_size[side]  = rw_buff[0x0b] + (rw_buff[0x0c] << 8);
    dfs_cluster_size[side] = rw_buff[0x0d];
    dfs_total_sector[side] = rw_buff[0x13] + (rw_buff[0x14] << 8);
    if (dfs_total_sector[side] == 0)
    {
        dfs_total_sector[side] = rw_buff[0x20] + (rw_buff[0x21] << 8) + (rw_buff[0x22] << 16) + (rw_buff[0x23] << 24);
    }

    rootdir_entry        = rw_buff[0x11] + (rw_buff[0x12] << 8);
    dfs_fat_count[side]  = rw_buff[0x10];
    dfs_fat_sector[side] = rw_buff[0x16] + (rw_buff[0x17] << 8);
    if(dfs_fat_sector[side] == 0)
    {
        dfs_fat_sector[side] = rw_buff[0x24] + (rw_buff[0x25] << 8) + (rw_buff[0x26] << 16) + (rw_buff[0x27] << 24);
    }

    dfs_track_sector[side]    = rw_buff[0x18] + (rw_buff[0x19] << 8);
    dfs_cylinder_sector[side] = (rw_buff[0x1a] + (rw_buff[0x1b] << 8)) * dfs_track_sector[side];
    dfs_fat_top[side] = rw_buff[0x0e] + (rw_buff[0x0f] << 8);

    dfs_rootdir_top[side] = dfs_fat_top[side] + dfs_fat_count[side] * dfs_fat_sector[side];
    dfs_data_top[side]    = dfs_rootdir_top[side] + rootdir_entry * DIR_SIZE / dfs_sector_size[side];

    clus_num = (dfs_total_sector[side] - dfs_data_top[side]) / dfs_cluster_size[side];
    if (clus_num < 4085)
    {
        dfs_fat_type[side] = FAT12;
    }
    else if (clus_num < 65525 )
    {
        dfs_fat_type[side] = FAT16;
    }
    else
    {
        dfs_fat_type[side] = FAT32;
    }

    if ( dfs_fat_type[side] == FAT32 )
    {
        dfs_fsinfo_sector[side] = rw_buff[0x30] + (rw_buff[0x31] << 8);
    }

    dfs_mediatype[side] = rw_buff[0x15];

    return 0;
}

/*******************************************************************************
* Function Name: usb0_fsi_check_boot_record
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
static int32_t usb0_fsi_check_boot_record( uint8_t *Data, uint32_t *ParLBA, uint8_t *PerInfo )
{
    USB_HMSCD_FSI_MBR_t         *MBRData;
    USB_HMSCD_FSI_PBR_t         *PBRData;
    USB_HMSCD_FSI_PT_TABLE_t    *Partition;
    int32_t                     embrflag;
    int32_t                     loop;
    uint16_t                    dummy_short;

    PBRData = (USB_HMSCD_FSI_PBR_t *)Data;
    MBRData = (USB_HMSCD_FSI_MBR_t *)Data;

    /* BOOT Recorder ? */
    dummy_short  = (uint16_t)( PBRData->signature[0]      );
    dummy_short |= (uint16_t)( PBRData->signature[1] << 8 );
    if( dummy_short != USB_HMSCD_FSI_BOOT_SIG )
    {
        PerInfo[0] = USB_HMSCD_FSI_PT_NONE;
        return -1;
    }

    embrflag = USB_HMSCD_FSI_PT_NONE;

    /* MBR check ( Partition n ) */
    for( loop = 0; loop < USB_HMSCD_FSI_MAX_PARTITION; loop++ )
    {
        Partition     = (USB_HMSCD_FSI_PT_TABLE_t *)&MBRData->partition_table[loop * 16];
        PerInfo[loop] = USB_HMSCD_FSI_PT_NONE;
        ParLBA[loop]  = (uint32_t)( Partition->start_sector_num[0]       );
        ParLBA[loop] |= (uint32_t)( Partition->start_sector_num[1] <<  8 );
        ParLBA[loop] |= (uint32_t)( Partition->start_sector_num[2] << 16 );
        ParLBA[loop] |= (uint32_t)( Partition->start_sector_num[3] << 24 );
        switch( Partition->partition_type )
        {
        case    USB_HMSCD_FSI_PT_NONE:
            break;
        case    USB_HMSCD_FSI_PT_EPRTA:
        case    USB_HMSCD_FSI_PT_EPRTB:
            embrflag = USB_HMSCD_FSI_EMBR_ADDR;
            PerInfo[loop] = USB_HMSCD_FSI_PT_EPRT;
            break;
        case    USB_HMSCD_FSI_PT_FAT12A:
            if( embrflag == USB_HMSCD_FSI_PT_NONE )
            {
                embrflag = USB_HMSCD_FSI_MBR_ADDR;
            }
            PerInfo[loop] = USB_HMSCD_FSI_PT_FAT12;
            break;
        case    USB_HMSCD_FSI_PT_FAT16A:
        case    USB_HMSCD_FSI_PT_FAT16B:
        case    USB_HMSCD_FSI_PT_FAT16X:
            if( embrflag == USB_HMSCD_FSI_PT_NONE )
            {
                embrflag = USB_HMSCD_FSI_MBR_ADDR;
            }
            PerInfo[loop] = USB_HMSCD_FSI_PT_FAT16;
            break;
        case    USB_HMSCD_FSI_PT_FAT32A:
        case    USB_HMSCD_FSI_PT_FAT32X:
            if( embrflag==USB_HMSCD_FSI_PT_NONE )
            {
                embrflag = USB_HMSCD_FSI_MBR_ADDR;
            }
            PerInfo[loop] = USB_HMSCD_FSI_PT_FAT32;
            break;
        default:
            break;
        }
    }

    switch( embrflag )
    {
    case    USB_HMSCD_FSI_MBR_ADDR:
    case    USB_HMSCD_FSI_EMBR_ADDR:
        return embrflag;
    default:
        break;
    }

    embrflag = usb0_fsi_check_partition_record( Data );
    if( embrflag == 0 )
    {
        return USB_HMSCD_FSI_PBR_ADDS;
    }
    return -1;
}

/*******************************************************************************
* Function Name: usb0_fsi_check_partition_record
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
static int32_t usb0_fsi_check_partition_record( uint8_t *Data )
{
    USB_HMSCD_FSI_FAT_32_t    *Fat32;
    USB_HMSCD_FSI_PBR_t       *PBRData;
    int32_t                   PerInfoFlag;
    uint8_t                   tmp_cluster_size;
    uint8_t                   tmp_fat_count;
    uint16_t                  dummy_short;
    uint16_t                  tmp_fat_sector;
    uint16_t                  tmp_sector_size;
    uint16_t                  reserved_sector;
    uint16_t                  TotalSector;
    uint16_t                  RootdirEntry;
    uint32_t                  TotalSector32;
    uint32_t                  FATSector32;
    uint32_t                  tmp_rootdir_top;
    uint32_t                  tmp_data_top;
    uint32_t                  tmp_fat_sector_long;
    uint32_t                  clus_num;

    PerInfoFlag = 0;
    PBRData     = (USB_HMSCD_FSI_PBR_t *)Data;

    if( (PBRData->jmp_code != USB_HMSCD_FSI_JMP_CODE1) || (PBRData->nop_code != USB_HMSCD_FSI_NOP_CODE) )
    {
        if( PBRData->jmp_code != USB_HMSCD_FSI_JMP_CODE2 )
        {
            return -1;
        }
    }

    /* BOOT Recorder ? */
    dummy_short  = (uint16_t)( PBRData->signature[0]      );
    dummy_short |= (uint16_t)( PBRData->signature[1] << 8 );
    if( dummy_short != USB_HMSCD_FSI_BOOT_SIG )
    {
        return -1;
    }

    /* PBR check */
    Fat32   = (USB_HMSCD_FSI_FAT_32_t    *)&PBRData->fat_sig_data;

    tmp_fat_sector   = (uint16_t)( PBRData->fat_sector[0]      );
    tmp_fat_sector  |= (uint16_t)( PBRData->fat_sector[1] << 8 );

    TotalSector32    = (uint32_t)( PBRData->total_sector1[0]       );
    TotalSector32   |= (uint32_t)( PBRData->total_sector1[1] <<  8 );
    TotalSector32   |= (uint32_t)( PBRData->total_sector1[2] << 16 );
    TotalSector32   |= (uint32_t)( PBRData->total_sector1[3] << 24 );

    tmp_sector_size  = (uint16_t)( PBRData->sector_size[0]      );
    tmp_sector_size |= (uint16_t)( PBRData->sector_size[1] << 8 );

    reserved_sector  = (uint16_t)( PBRData->reserved_sector[0]      );
    reserved_sector |= (uint16_t)( PBRData->reserved_sector[1] << 8 );

    RootdirEntry     = (uint16_t)( PBRData->root_dir_top[0]      );
    RootdirEntry    |= (uint16_t)( PBRData->root_dir_top[1] << 8 );

    TotalSector      = (uint16_t)( PBRData->total_sector0[0]      );
    TotalSector     |= (uint16_t)( PBRData->total_sector0[1] << 8 );

    FATSector32      = (uint32_t)( Fat32->fat_sector[0]       );
    FATSector32     |= (uint32_t)( Fat32->fat_sector[1] <<  8 );
    FATSector32     |= (uint32_t)( Fat32->fat_sector[2] << 16 );
    FATSector32     |= (uint32_t)( Fat32->fat_sector[3] << 24 );

    tmp_cluster_size = PBRData->cluster_size;         /* sector@cluster */
    tmp_fat_count    = PBRData->fat_count;            /* Number of FAT */

    if(tmp_sector_size == 0)
    {
        return -1;
    }

    if(tmp_cluster_size == 0)
    {
        return -1;
    }

    tmp_fat_sector_long = tmp_fat_sector;
    if(tmp_fat_sector_long == 0)
    {
        if( TotalSector32 != 0 )
        {                                             /* FAT32 */
            tmp_fat_sector_long = FATSector32;        /* Number of FAT sector */
        }
    }

    tmp_rootdir_top = (reserved_sector + (tmp_fat_sector_long * tmp_fat_count));
    tmp_data_top    = (tmp_rootdir_top  + (((RootdirEntry * 32) + tmp_sector_size - 1) / tmp_sector_size));
    if(TotalSector != 0)
    {                                                 /* FAT12,16 */
        clus_num = ((TotalSector - tmp_data_top) / tmp_cluster_size);
    }
    else
    {                                                 /* FAT32 */
        clus_num = ((TotalSector32 - tmp_data_top) / tmp_cluster_size);
    }

    if(clus_num < 4085)
    {
        PerInfoFlag = FAT12;
    }
    else if(clus_num < 65525 )
    {
        PerInfoFlag = FAT16;
    }
    else
    {
        PerInfoFlag = FAT32;
    }

    if( PerInfoFlag == 0 )
    {
        return -1;
    }

    return 0;
}

/*******************************************************************************
* Function Name: usb0_fsi_check_boot
* Description  :
* Arguments    :
* Return Value :
*******************************************************************************/
static int32_t usb0_fsi_check_boot( uint16_t device_address, uint16_t unit_number,
                                    int32_t *drive, int32_t *drvnum )
{
    int32_t            ret2;
    int32_t            pbrcnt;
    int32_t            epbr;
    int32_t            part;
    uint8_t            *ptr;
    uint8_t            partition[4];
    uint32_t           sector_size;
    uint32_t           partlba[4];
    int32_t            ret;
    USB_HMSCD_RW_t     mscd_rw;
    uint32_t           boot_lsn;
    uint32_t           pbr_lsn;
    uint32_t           pbr_lsn_tmp;
    uint32_t           e_pbr_lsn;
    uint32_t           bytes;
    uint8_t            cswstatus;

    ret = usb0_api_hmscd_read_capacity( device_address, unit_number,
                                        &bytes, &cswstatus, (uint8_t *)&g_usb0_hmscd_fsi_work[0] );
    if( ret == USB_HMSCD_SUCCESS )
    {
        if( cswstatus != USB_HMSCD_CSW_PASS )
        {
            printf( "READ CAPACITY CSW ERROR unit_number=%d \n", unit_number );
            g_usb0_hmscd_fsi_test_unit_enable[device_address - 1][unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
            g_usb0_hmscd_fsi_test_unit_count[device_address - 1][unit_number]  = 0;
            return 0;
        }

        ptr = (uint8_t *)&g_usb0_hmscd_fsi_work[0];
        sector_size  = ( *(ptr + 4) << 24 );
        sector_size += ( *(ptr + 5) << 16 );
        sector_size += ( *(ptr + 6) << 8  );
        sector_size += ( *(ptr + 7)       );
    }
    else
    {
        if( ret != USB_HMSCD_STALL )
        {
            printf( "READ CAPACITY ERROR unit_number=%d \n", unit_number );
            g_usb0_hmscd_fsi_test_unit_enable[device_address - 1][unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
            g_usb0_hmscd_fsi_test_unit_count[device_address - 1][unit_number]  = 0;

            return 0;
        }

        printf( "READ CAPACITY ERROR unit_number=%d sector \n", unit_number );
        printf( "The driver will be executed by setting sector size to 512byte \n" );
        sector_size = 512;
    }

    /* sector size check */
    if( ( sector_size % 512 ) != 0 )
    {
        printf( "ERROR SECTOR SIZE is %d \n", sector_size );
        return 0;
    }

    printf( "SECTOR SIZE is %d \n", sector_size );

    /* work size check */
    if( sector_size > sizeof(g_usb0_hmscd_fsi_work) )
    {
        printf("ERROR g_usb0_hmscd_fsi_work( %d ) is less than sector size( %d )\n",
                                 sizeof(g_usb0_hmscd_fsi_work), sector_size );
        return 0;
    }


    pbrcnt   = 0;
    *drive   = 0;
    boot_lsn = 0;
    pbr_lsn  = boot_lsn;
    pbr_lsn_tmp = 0xffffffff;
    do
    {
        /* Search blank area of g_usb0_hmscd_fsi_pbr_info */
        for( ;pbrcnt < USB_HMSCD_FSI_MAX_DRIVE ; ++pbrcnt )
        {
            if( g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].ready == 0 )
            {
                break;
            }
        }

        if( pbrcnt == USB_HMSCD_FSI_MAX_DRIVE )
        {
            return 0;
        }

        /* MBR/EMBR read */
        mscd_rw.device_address  = device_address;
        mscd_rw.unit_number     = unit_number;
        mscd_rw.buffer          = (uint8_t *)&g_usb0_hmscd_fsi_work[0];
        mscd_rw.sector_number   = pbr_lsn;
        mscd_rw.sector_count    = 1;
        mscd_rw.transfer_bytes  = (mscd_rw.sector_count * sector_size);

        ret = usb0_api_hmscd_read10( &mscd_rw, &bytes, &cswstatus );
        if( (ret != USB_HMSCD_SUCCESS) || (cswstatus != USB_HMSCD_CSW_PASS) )
        {
            g_usb0_hmscd_fsi_test_unit_enable[device_address - 1][unit_number] = USB_HMSCD_FSI_TEST_UNIT_ENABLE;
            g_usb0_hmscd_fsi_test_unit_count[device_address - 1][unit_number]  = 0;
            return 0;    /* not change */
        }

        /* check partition */
        ret2 = usb0_fsi_check_boot_record( (uint8_t *)&g_usb0_hmscd_fsi_work[0],  &partlba[0],  &partition[0] );
        if( ret2 == USB_HMSCD_FSI_PBR_ADDS )
        {
            g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].ready = 1;
            g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].device_address = device_address;
            g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].unit_number = unit_number;
            g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].pbr_lsn = pbr_lsn;
            g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].mbr_lsn = 0;
            g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].sector_size = sector_size;

            printf(" Side=%d MBR Sector=%d PBR Sector=%d\n", pbrcnt, g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].mbr_lsn, g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].pbr_lsn);

            drvnum[ *drive ] = pbrcnt;
            *drive += 1;

            return 1;    /* change */
        }
        else if( (ret2 == USB_HMSCD_FSI_MBR_ADDR) || (ret2 == USB_HMSCD_FSI_EMBR_ADDR) )
        {
            epbr = 0;
            e_pbr_lsn = 0xffffffff;
            for( part = 0; part < USB_HMSCD_FSI_MAX_PARTITION; part++ )
            {
                switch( partition[ part ] )
                {
                case    USB_HMSCD_FSI_PT_FAT12:
                case    USB_HMSCD_FSI_PT_FAT16:
                case    USB_HMSCD_FSI_PT_FAT32:
                    g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].ready = 1;
                    g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].device_address = device_address;
                    g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].unit_number = unit_number;
                    g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].pbr_lsn = partlba[ part ];
                    g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].mbr_lsn = pbr_lsn;
                    g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].sector_size = sector_size;

                    printf(" Side=%d MBR Sector=%d PBR Sector=%d\n", pbrcnt, g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].mbr_lsn, g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].pbr_lsn);

                    drvnum[ *drive ] = pbrcnt;
                    ++pbrcnt;
                    *drive += 1;
                    /* Search blank area of g_usb0_hmscd_fsi_pbr_info */
                    for( ;pbrcnt < USB_HMSCD_FSI_MAX_DRIVE ; ++pbrcnt )
                    {
                        if( g_usb0_hmscd_fsi_pbr_info[ pbrcnt ].ready == 0 )
                        {
                            break;
                        }
                    }
                    if( pbrcnt == USB_HMSCD_FSI_MAX_DRIVE )
                    {
                        return 1;
                    }
                    break;

                case    USB_HMSCD_FSI_PT_EPRT:
                        /* 拡張パーティションのオフセット位置は                */
                        /* 最初の拡張パーティションの位置を基準にしている。    */
                        if(pbr_lsn_tmp == 0xffffffff)
                        {
                            e_pbr_lsn = (pbr_lsn + partlba[ part ]);
                            /* 最初の拡張パーティションの位置を覚えておく    */
                            pbr_lsn_tmp = e_pbr_lsn;
                        }
                        else
                        {
                            /* 次の拡張パーティション位置は                        */
                            /* 最初の拡張パーティションの位置 ＋ オフセット位置    */
                            e_pbr_lsn = (pbr_lsn_tmp + partlba[ part ]);
                        }
                        epbr = 1;
                    break;

                default:
                    break;
                }
            }

            if( epbr == 0 )
            {
                return 1;    /* change */
            }
            else
            {
                /* 拡張パーティションありなので次回検索位置を変更    */
                pbr_lsn = e_pbr_lsn;
            }
        }
        else
        {
            return 1;    /* change */
        }

    } while( pbrcnt < USB_HMSCD_FSI_MAX_DRIVE );

    return 1;    /* change */
}

/* End of File */
