/*
*********************************************************************************************************
*                                             uC/FS V4
*                                     The Embedded File System
*
*                         (c) Copyright 2008-2010; Micrium, Inc.; Weston, FL
*
*               All rights reserved. Protected by international copyright laws.
*
*               uC/FS is provided in source form to registered licensees ONLY.  It is
*               illegal to distribute this source code to any third party unless you receive
*               written permission by an authorized Micrium representative.  Knowledge of
*               the source code may NOT be used to develop a similar product.
*
*               Please help us continue to provide the Embedded community with the finest
*               software available.  Your honesty is greatly appreciated.
*
*               You can contact us at www.micrium.com.
&
* Author      : Lance Simms (12/16/10)
*               Adapted for the Compact Flash controller on board the Logic PXA270 Zoom SDK kit
*
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*
*                                      FILE SYSTEM DEVICE DRIVER
*
*                                              TEMPLATE
*
* Filename      : fs_dev_CF_Card.c
* Version       : V4.04
* Programmer(s) : BAN
*********************************************************************************************************
* Note(s)       : (a) Replace CF_Card with the driver identifier (in the correct case).
*                 (b) Replace $$$$ with code/definitions/etc.
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                            INCLUDE FILES
*********************************************************************************************************
*/

#define    FS_DEV_CF_Card_MODULE
#include  <fs_dev_CF_Card.h>


/*
*********************************************************************************************************
*                                            LOCAL DEFINES
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                            TYPE DEFINES
*
* Note(s) : (1) FS_DEV_xxx_TYPE_??? #define values specifically chosen as ASCII representations of the
*               device types.  Memory displays of device data will display the device TYPEs with their
*               chosen ASCII names.
*********************************************************************************************************
*/

#define  FS_DEV_CF_Card_TYPE_NONE           FS_TYPE_CREATE(ASCII_CHAR_LATIN_UPPER_N,  \
                                                        ASCII_CHAR_LATIN_UPPER_O,  \
                                                        ASCII_CHAR_LATIN_UPPER_N,  \
                                                        ASCII_CHAR_LATIN_UPPER_E)

#define  FS_DEV_CF_Card_TYPE_CF_Card           FS_TYPE_CREATE(ASCII_CHAR_LATIN_UPPER_C,  \
                                                        ASCII_CHAR_LATIN_UPPER_F,  \
                                                        ASCII_CHAR_LATIN_UPPER_C,  \
                                                        ASCII_CHAR_LATIN_LOWER_D)


/*
*********************************************************************************************************
*                                          LOCAL DATA TYPES
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                     CF_Card DEVICE DATA DATA TYPE
*********************************************************************************************************
*/

typedef  struct  fs_dev_CF_Card_data  FS_DEV_CF_Card_DATA;
struct  fs_dev_CF_Card_data {
    FS_TYPE            Type;
    FS_QTY             UnitNbr;
    FS_SEC_SIZE        SecSize;
    FS_SEC_QTY         SecCnt;
    void              *DiskPtr;
    
#if (FS_CFG_CTR_STAT_EN == DEF_ENABLED)
    FS_CTR             StatRdCtr;
    FS_CTR             StatWrCtr;
#endif

#if (FS_CFG_CTR_ERR_EN == DEF_ENABLED)
   /* $$$$ ERROR COUNTERS */
#endif

    FS_DEV_CF_Card_DATA  *NextPtr;
};


/*
*********************************************************************************************************
*                                           LOCAL CONSTANTS
*********************************************************************************************************
*/

#define  FS_DEV_CF_Card_NAME_LEN               4u

static  const  CPU_CHAR  FSDev_CF_Card_Name[] = "CF_Card";


/*
*********************************************************************************************************
*                                            LOCAL TABLES
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                       LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/

static  FS_DEV_CF_Card_DATA  *FSDev_CF_Card_ListFreePtr;


/*
*********************************************************************************************************
*                                            LOCAL MACRO'S
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                      LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/

                                                                                /* -------- DEV INTERFACE FNCTS ------- */
static  const  CPU_CHAR   *FSDev_CF_Card_NameGet (void);                           /* Get name of driver.                  */

static  void               FSDev_CF_Card_Init    (FS_ERR       *p_err);            /* Init driver.                         */

static  void               FSDev_CF_Card_Open    (FS_DEV       *p_dev,             /* Open device.                         */
                                               void         *p_dev_cfg,
                                               FS_ERR       *p_err);

static  void               FSDev_CF_Card_Close   (FS_DEV       *p_dev);            /* Close device.                        */

static  void               FSDev_CF_Card_Rd      (FS_DEV       *p_dev,             /* Read from device.                    */
                                               void         *p_dest,
                                               FS_SEC_NBR    start,
                                               FS_SEC_QTY    cnt,
                                               FS_ERR       *p_err);

#if (FS_CFG_RD_ONLY_EN == DEF_DISABLED)
static  void               FSDev_CF_Card_Wr      (FS_DEV       *p_dev,             /* Write to device.                     */
                                               void         *p_src,
                                               FS_SEC_NBR    start,
                                               FS_SEC_QTY    cnt,
                                               FS_ERR       *p_err);
#endif

static  void               FSDev_CF_Card_Query   (FS_DEV       *p_dev,             /* Get device info.                     */
                                               FS_DEV_INFO  *p_info,
                                               FS_ERR       *p_err);

static  void               FSDev_CF_Card_IO_Ctrl (FS_DEV       *p_dev,             /* Perform device I/O control.          */
                                               CPU_INT08U    opt,
                                               void         *p_data,
                                               FS_ERR       *p_err);

                                                                                /* ------------ LOCAL FNCTS ----------- */
static  void               FSDev_CF_Card_DataFree(FS_DEV_CF_Card_DATA  *p_CF_Card_data); /* Free CF_Card data.                      */

static  FS_DEV_CF_Card_DATA  *FSDev_CF_Card_DataGet (void);                           /* Allocate & init CF_Card data.           */

/*
*********************************************************************************************************
*                                         INTERFACE STRUCTURE
*********************************************************************************************************
*/

const  FS_DEV_API  FSDev_CF_Card = {
    FSDev_CF_Card_NameGet,
    FSDev_CF_Card_Init,
    FSDev_CF_Card_Open,
    FSDev_CF_Card_Close,
    FSDev_CF_Card_Rd,
#if (FS_CFG_RD_ONLY_EN == DEF_DISABLED)
    FSDev_CF_Card_Wr,
#endif
    FSDev_CF_Card_Query,
    FSDev_CF_Card_IO_Ctrl
};


/*
*********************************************************************************************************
*                                     LOCAL CONFIGURATION ERRORS
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*********************************************************************************************************
*                                     DRIVER INTERFACE FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                        FSDev_CF_Card_NameGet()
*
* Description : Return name of device driver.
*
* Argument(s) : none.
*
* Return(s)   : Pointer to string which holds device driver name.
*
* Caller(s)   : various.
*
* Note(s)     : (1) The name MUST NOT include the ':' character.
*
*               (2) The name MUST be constant; each time this function is called, the same name MUST be
*                   returned.
*********************************************************************************************************
*/

static  const  CPU_CHAR  *FSDev_CF_Card_NameGet (void)
{
    return (FSDev_CF_Card_Name);
}


/*
*********************************************************************************************************
*                                          FSDev_CF_Card_Init()
*
* Description : Initialize the driver.
*
* Argument(s) : p_err       Pointer to variable that will receive the return error code from this function :
*
*                               FS_ERR_NONE    Device driver initialized successfully.
*
* Return(s)   : none.
*
* Caller(s)   : FS_DevDrvAdd().
*
* Note(s)     : (1) This function should initialize any structures, tables or variables that are common
*                   to all devices or are used to manage devices accessed with the driver.  This function
*                   SHOULD NOT initialize any devices; that will be done individually for each with
*                   device driver's 'Open()' function.
*********************************************************************************************************
*/

static  void  FSDev_CF_Card_Init (FS_ERR  *p_err)
{
    FSDev_CF_Card_UnitCtr     =  0u;
    FSDev_CF_Card_ListFreePtr = (FS_DEV_CF_Card_DATA *)0;

   *p_err = FS_ERR_NONE;
}


/*
*********************************************************************************************************
*                                          FSDev_CF_Card_Open()
*
* Description : Open (initialize) a device instance.
*
* Argument(s) : p_dev       Pointer to device to open.
*
*               p_dev_cfg   Pointer to device configuration.
*
*               p_err       Pointer to variable that will receive the return error code from this function :
*
*                               FS_ERR_NONE                    Device opened successfully.
*                               FS_ERR_DEV_ALREADY_OPEN        Device is already opened.
*                               FS_ERR_DEV_INVALID_CFG         Device configuration specified invalid.
*                               FS_ERR_DEV_INVALID_LOW_FMT     Device needs to be low-level formatted.
*                               FS_ERR_DEV_INVALID_LOW_PARAMS  Device low-level device parameters invalid.
*                               FS_ERR_DEV_INVALID_UNIT_NBR    Device unit number is invalid.
*                               FS_ERR_DEV_IO                  Device I/O error.
*                               FS_ERR_DEV_NOT_PRESENT         Device is not present.
*                               FS_ERR_DEV_TIMEOUT             Device timeout.
*                               FS_ERR_MEM_ALLOC               Memory could not be allocated.
*
* Return(s)   : none.
*
* Caller(s)   : FSDev_Open().
*
* Note(s)     : (1) Tracking whether a device is open is not necessary, because this should NEVER be
*                   called when a device is already open.
*
*               (2) Some drivers may need to track whether a device has been previously opened
*                   (indicating that the hardware has previously been initialized).
*
*               (3) This function will be called EVERY time the device is opened.
*
*               (4) See 'FSDev_Open() Notes #3'.
*
*               (5) The driver should identify the device instance to be opened by checking
*                   'p_dev->UnitNbr'.  For example, if "template:2:" is to be opened, then
*                   'p_dev->UnitNbr' will hold the integer 2.
*********************************************************************************************************
*/

static  void  FSDev_CF_Card_Open (FS_DEV  *p_dev,
                                  void    *p_dev_cfg,
                                  FS_ERR  *p_err)
{
    *p_err = FS_ERR_NONE;
}


/*
*********************************************************************************************************
*                                         FSDev_CF_Card_Close()
*
* Description : Close (uninitialize) a device instance.
*
* Argument(s) : p_dev       Pointer to device to close.
*
* Return(s)   : none.
*
* Caller(s)   : FSDev_Close().
*
* Note(s)     : (1) Tracking whether a device is open is not necessary, because this should ONLY be
*                   called when a device is open.
*
*               (2) This function will be called EVERY time the device is closed.
*********************************************************************************************************
*/

static  void  FSDev_CF_Card_Close (FS_DEV  *p_dev)
{

}


/*
*********************************************************************************************************
*                                           FSDev_CF_Card_Rd()
*
* Author      : Lance Simms (12/16/10)
*
* Description : Read from a device & store data in buffer.
*
* Argument(s) : p_dev       Pointer to device to read from.
*
*               p_dest      Pointer to destination buffer.
*
*               start       Start sector of read.
*
*               cnt         Number of sectors to read.
*
*               p_err       Pointer to variable that will receive the return error code from this function :
*
*                               FS_ERR_NONE                    Sector(s) read.
*                               FS_ERR_DEV_INVALID_UNIT_NBR    Device unit number is invalid.
*                               FS_ERR_DEV_NOT_OPEN            Device is not open.
*                               FS_ERR_DEV_NOT_PRESENT         Device is not present.
*                               FS_ERR_DEV_IO                  Device I/O error.
*                               FS_ERR_DEV_TIMEOUT             Device timeout.
*
* Return(s)   : none.
*
* Caller(s)   : FSDev_RdLocked().
*
* Note(s)     : (1) Tracking whether a device is open is not necessary, because this should ONLY be
*                   called when a device is open.
*             : (2) From the Identify Drive information, the card says that 1 sector is the maximum amount 
*                   of sectors it supports when doing READ MULTIPLE SECTOR COMMANDS.  Therefore, I will not 
*                   use this as an option.
*
*********************************************************************************************************
*/

static  void  FSDev_CF_Card_Rd (FS_DEV      *p_dev,
                             void        *p_dest,
                             FS_SEC_NBR   start,
                             FS_SEC_QTY   cnt,
                             FS_ERR      *p_err)
{
  
  //Error and loop indexes
  INT32U i=0, j=0, k=0;
  
  //Compact Flash variables
  INT32U  SectorNum          = (INT32U)start;       /* The number of the sector that will be read/written on the drive                  */
  INT32U  TotalSectors       = (INT32U)cnt;         /* The number of total sectors to read/write on the drive                           */                  
  INT32U  ThisNumSectors     = 0;                   /* Read in 256 sectors unless it's the last in the chunk (1-255)                    */
  INT32U  LastNumSectors     = TotalSectors%256L;   /* The last number of sectors will be 1-255                                         */
  INT32U  NumSectorGroups    = TotalSectors/256L+1; /* The number of total read sector commands that will be issued                     */               
  INT8U   DriveHeadRegVal    = 0;                   /* The 8 bit value that will go to the drive head register                          */

  //Unions to read from the Compact Flash Card
  INT16Union int16union;                            /* 16 bit union to read in unsigned shorts                                          */
  INT32Union int32union;                            /* 32 bit union to read in unsigned ints                                            */

  //Micrium Buffer variables
  CPU_INT16U *p_dest_16 = (CPU_INT16U *) p_dest;    /* Pointer to the buffer that will hold these numbers                               */
      
  //Read in the number of sectors
  for (i=0; i<NumSectorGroups;i++){

    //TASK REGISTERS 2-3) SET SECTOR NUMBER AND SECTOR COUNT REGISTERS
    if (i == (NumSectorGroups-1)){ 
      ThisNumSectors         = LastNumSectors;
      int16union.chararr[0]  = (INT8U)ThisNumSectors;  
    } else {
      ThisNumSectors         = (INT8U)256;
      int16union.chararr[0]  = (INT8U)ThisNumSectors;
    }
    int32union.int32u        = (INT32U)SectorNum;
    int16union.chararr[1]    = (INT8U)int32union.chararr[0];
    cf_wait();
    CF_SECTOR_CNT_REG_ADDR   = (INT16U)int16union.int16u;
    cf_wait();
      
    //TASK REGISTERS 4-5) SET CYLINDER LOW AND HIGH REGISTER 
    int16union.chararr[0]    = (INT8U)int32union.chararr[1]; //Cyl low
    int16union.chararr[1]    = (INT8U)int32union.chararr[2]; //Cyl High      
    CF_CYL_LOW_REG_ADDR      = (INT16U)int16union.int16u;
    cf_wait();
      
    //TASK REGISTERS 6-7) Allow LBA addressing and specify the upper bytes (REG 6) and issue command (REG 7)
    DriveHeadRegVal = int32union.chararr[3];               //LBA24-LBA27 - Drive/Head Register
    DriveHeadRegVal |= 0xF0;                               //Set upper bits
    DriveHeadRegVal &= 0xEF;                               //Get the lower 4 bits from the upper byte of sector number to HS0-HS3 and set upper 4 bits for LBA and drive 0
    int16union.chararr[0] = (INT8U)DriveHeadRegVal;
    int16union.chararr[1] = (INT8U)CF_READ_SECTOR_CMD; 
    CF_SELECT_CARD_HEAD_REG_ADDR = (INT16U)int16union.int16u;
    cf_wait();
      
#ifdef PRINT_CF_STATUS_AND_ERRORS
    //print them out 
    printf("CF_SECTOR_CNT_BYTE_REG_ADDR %X\n\r", CF_SECTOR_CNT_BYTE_REG_ADDR);  
    printf("CF_SECTOR_NUM_REG_ADDR            %X\n\r", CF_SECTOR_NUM_REG_ADDR);
    printf("CF_CYL_LOW_BYTE_REG_ADDR          %X\n\r", CF_CYL_LOW_BYTE_REG_ADDR);
    printf("CF_CYL_HIGH_REG_ADDR              %X\n\r", CF_CYL_HIGH_REG_ADDR);
    printf("CF_SELECT_CARD_HEAD_BYTE_REG_ADDR %X\n\r", CF_SELECT_CARD_HEAD_BYTE_REG_ADDR);             
    printf("CMD OR STATUS ADDR                %X\n\r", CF_CMD_OR_STATUS_REG_ADDR);  
#endif
  
    //Do the actual reading of ThisNumSectors sectors to the output buffer************************
    for (j=0; j< ThisNumSectors; j++){
      
#ifdef PRINT_CF_STATUS_AND_ERRORS
      //print out the sector number if requested
      printf("\n\rReading Sector %d ...\n\r", SectorNum);
#endif
      
      //Wait until DRQ goes high to indicate data buffer is ready
      while((CF_CMD_OR_STATUS_REG_ADDR & CF_DRQ_BIT) == 0){}
      
      //Loope through the 512 bytes as 256 accesses to 16 bit words
      for (k=0; k<(CF_SECTOR_SIZE/2); k++){
        *p_dest_16 = CF_EVEN_RD_DATA_REG_ADDR;
        p_dest_16++;
      }
      SectorNum++;
    }               
  }
    
  *p_err = FS_ERR_NONE;
}


/*
*********************************************************************************************************
*                                           FSDev_CF_Card_Wr()
*
* Author      : Lance Simms (12/16/10)
*
* Description : Write data to a device from a buffer.
*
* Argument(s) : p_dev       Pointer to device to write to.
*
*               p_src       Pointer to source buffer.
*
*               start       Start sector of write.
*
*               cnt         Number of sectors to write.
*
*               p_err       Pointer to variable that will receive the return error code from this function :
*
*                               FS_ERR_NONE                    Sector(s) written.
*                               FS_ERR_DEV_INVALID_UNIT_NBR    Device unit number is invalid.
*                               FS_ERR_DEV_NOT_OPEN            Device is not open.
*                               FS_ERR_DEV_NOT_PRESENT         Device is not present.
*                               FS_ERR_DEV_IO                  Device I/O error.
*                               FS_ERR_DEV_TIMEOUT             Device timeout.
*
* Return(s)   : none.
*
* Caller(s)   : FSDev_WrLocked().
*
* Note(s)     : (1) Tracking whether a device is open is not necessary, because this should ONLY be
*                   called when a device is open.
*********************************************************************************************************
*/

#if (FS_CFG_RD_ONLY_EN == DEF_DISABLED)
static  void  FSDev_CF_Card_Wr (FS_DEV      *p_dev,
                             void        *p_src,
                             FS_SEC_NBR   start,
                             FS_SEC_QTY   cnt,
                             FS_ERR      *p_err)
{
  //Error and loop indexes
  INT32U i=0, j=0, k=0;
  
  //Compact Flash variables
  INT32U  SectorNum          = (INT32U)start;       /* The number of the sector that will be read/written on the drive                  */
  INT32U  TotalSectors       = (INT32U)cnt;         /* The number of total sectors to read/write on the drive                           */                  
  INT32U  ThisNumSectors     = 0;                   /* Read in 256 sectors unless it's the last in the chunk (1-255)                    */
  INT32U  LastNumSectors     = TotalSectors%256L;   /* The last number of sectors will be 1-255                                         */
  INT32U  NumSectorGroups    = TotalSectors/256L+1; /* The number of total read sector commands that will be issued                     */               
  INT8U   DriveHeadRegVal    = 0;                   /* The 8 bit value that will go to the drive head register                          */

  //Unions to read from the Compact Flash Card
  INT16Union int16union;                            /* 16 bit union to read in unsigned shorts                                          */
  INT32Union int32union;                            /* 32 bit union to read in unsigned ints                                            */

  //Micrium Buffer variables
  CPU_INT16U *p_dest_16 = (CPU_INT16U *) p_src;     /* Pointer to the buffer that will hold these numbers                               */
      
  //Read in the number of sectors
  for (i=0; i<NumSectorGroups;i++){

    //TASK REGISTERS 2-3) SET SECTOR NUMBER AND SECTOR COUNT REGISTERS
    if (i == (NumSectorGroups-1)){ 
      ThisNumSectors         = LastNumSectors;
      int16union.chararr[0]  = (INT8U)ThisNumSectors;  
    } else {
      ThisNumSectors         = (INT8U)256;
      int16union.chararr[0]  = (INT8U)ThisNumSectors;
    }
    int32union.int32u        = (INT32U)SectorNum;
    int16union.chararr[1]    = (INT8U)int32union.chararr[0];
    cf_wait();
    CF_SECTOR_CNT_REG_ADDR   = (INT16U)int16union.int16u;
    cf_wait();
      
    //TASK REGISTERS 4-5) SET CYLINDER LOW AND HIGH REGISTER 
    int16union.chararr[0]    = (INT8U)int32union.chararr[1]; //Cyl low
    int16union.chararr[1]    = (INT8U)int32union.chararr[2]; //Cyl High      
    CF_CYL_LOW_REG_ADDR      = (INT16U)int16union.int16u;
    cf_wait();
      
    //TASK REGISTERS 6-7) Allow LBA addressing and specify the upper bytes (REG 6) and issue command (REG 7)
    DriveHeadRegVal = int32union.chararr[3];               //LBA24-LBA27 - Drive/Head Register
    DriveHeadRegVal |= 0xF0;                               //Set upper bits
    DriveHeadRegVal &= 0xEF;                               //Get the lower 4 bits from the upper byte of sector number to HS0-HS3 and set upper 4 bits for LBA and drive 0
    int16union.chararr[0] = (INT8U)DriveHeadRegVal;
    int16union.chararr[1] = (INT8U)CF_WRITE_SECTOR_CMD; 
    CF_SELECT_CARD_HEAD_REG_ADDR = (INT16U)int16union.int16u;
    cf_wait();
      
#ifdef PRINT_CF_STATUS_AND_ERRORS
    //print them out 
    printf("CF_SECTOR_CNT_BYTE_REG_ADDR %X\n\r", CF_SECTOR_CNT_BYTE_REG_ADDR);  
    printf("CF_SECTOR_NUM_REG_ADDR            %X\n\r", CF_SECTOR_NUM_REG_ADDR);
    printf("CF_CYL_LOW_BYTE_REG_ADDR          %X\n\r", CF_CYL_LOW_BYTE_REG_ADDR);
    printf("CF_CYL_HIGH_REG_ADDR              %X\n\r", CF_CYL_HIGH_REG_ADDR);
    printf("CF_SELECT_CARD_HEAD_BYTE_REG_ADDR %X\n\r", CF_SELECT_CARD_HEAD_BYTE_REG_ADDR);             
    printf("CMD OR STATUS ADDR                %X\n\r", CF_CMD_OR_STATUS_REG_ADDR);  
#endif

    //Wait for busy to be set
    //Do the actual writing of ThisNumSectors sectors to the output buffer************************
    for (j=0; j< ThisNumSectors; j++){
      
      //Wait until DRQ is set
      while ((CF_CMD_OR_STATUS_REG_ADDR & CF_DRQ_BIT) == 0){printf("Waiting for DRQ to be set\n\r");}
      //Wait until busy is cleared
      while ((CF_CMD_OR_STATUS_REG_ADDR & CF_BSY_BIT) != 0){printf("Waiting for BSY to be cleared\n\r");}

#ifdef PRINT_CF_STATUS_AND_ERRORS
      //print out the sector number if requested
      printf("\n\rWriting Sector %d ...\n\r", SectorNum);
#endif
      
      //Loop through the 512 bytes as 256 accesses to 16 bit words
      for (k=0; k<(CF_SECTOR_SIZE/2); k++){
        CF_EVEN_RD_DATA_REG_ADDR = *p_dest_16;
        p_dest_16++;
      }
      SectorNum++;
    }               
  }
  
  //Wait until DRQ is cleared
  while ((CF_CMD_OR_STATUS_REG_ADDR & CF_DRQ_BIT) != 0){printf("Waiting for DRQ to be cleared\n\r");}
               
  //Wait until busy is cleared
  while ((CF_CMD_OR_STATUS_REG_ADDR & CF_BSY_BIT) != 0){printf("Waiting for BSY to be cleared\n\r");}
           
  *p_err = FS_ERR_NONE;
  
}
#endif


/*
*********************************************************************************************************
*                                         FSDev_CF_Card_Query()
*
* Author      : Lance Simms (12/16/10)
*
* Description : Get information about a device.
*
* Argument(s) : p_dev       Pointer to device to query.
*
*               p_info      Pointer to structure that will receive device information.
*
*               p_err       Pointer to variable that will receive the return error code from this function :
*
*                               FS_ERR_NONE                    Device information obtained.
*                               FS_ERR_DEV_INVALID_UNIT_NBR    Device unit number is invalid.
*                               FS_ERR_DEV_NOT_OPEN            Device is not open.
*                               FS_ERR_DEV_NOT_PRESENT         Device is not present.
*
* Return(s)   : none.
*
* Caller(s)   : FSDev_Open(),
*               FSDev_Refresh(),
*               FSDev_QueryLocked().
*
* Note(s)     : (1) Tracking whether a device is open is not necessary, because this should ONLY be
*                   called when a device is open.
*********************************************************************************************************
*/

static  void  FSDev_CF_Card_Query (FS_DEV       *p_dev,
                                FS_DEV_INFO  *p_info,
                                FS_ERR       *p_err)
{

    
    //Determined and added these values from the Card Information Structure (Lance Simms 12/16/10)
    p_info->SecSize = 512;               /* $$$$ DETERMINE SECTOR SIZE OF DEVICE               */;
    p_info->Size    = 63744;             /* $$$$ DETERMINE NUMBER OF SECTOR IN DEVICE          */;
    p_info->Fixed   = 1;                 /* $$$$ INDICATE WHETHER DEVICE IS FIXED OR REMOVABLE */;

   *p_err = FS_ERR_NONE;
}


/*
*********************************************************************************************************
*                                        FSDev_CF_Card_IO_Ctrl()
*
* Description : Perform device I/O control operation.
*
* Argument(s) : p_dev       Pointer to device to control.
*
*               opt         Control command.
*
*               p_data      Buffer which holds data to be used for operation.
*                              OR
*                           Buffer in which data will be stored as a result of operation.
*
*               p_err       Pointer to variable that will receive return the error code from this function :
*
*                               FS_ERR_NONE                    Control operation performed successfully.
*                               FS_ERR_DEV_INVALID_IO_CTRL     I/O control operation unknown to driver.
*                               FS_ERR_DEV_INVALID_UNIT_NBR    Device unit number is invalid.
*                               FS_ERR_DEV_IO                  Device I/O error.
*                               FS_ERR_DEV_NOT_OPEN            Device is not open.
*                               FS_ERR_DEV_NOT_PRESENT         Device is not present.
*                               FS_ERR_DEV_TIMEOUT             Device timeout.
*
* Return(s)   : none.
*
* Caller(s)   : various.
*
* Note(s)     : (1) Tracking whether a device is open is not necessary, because this should ONLY be
*                   called when a device is open.
*
*               (2) Defined I/O control operations are :
*
*                   (a) FS_DEV_IO_CTRL_REFRESH           Refresh device.
*                   (b) FS_DEV_IO_CTRL_LOW_FMT           Low-level format device.
*                   (c) FS_DEV_IO_CTRL_LOW_MOUNT         Low-level mount device.
*                   (d) FS_DEV_IO_CTRL_LOW_UNMOUNT       Low-level unmount device.
*                   (e) FS_DEV_IO_CTRL_LOW_COMPACT       Low-level compact device.
*                   (f) FS_DEV_IO_CTRL_LOW_DEFRAG        Low-level defragment device.
*                   (g) FS_DEV_IO_CTRL_SEC_RELEASE       Release data in sector.
*                   (h) FS_DEV_IO_CTRL_PHY_RD            Read  physical device.
*                   (i) FS_DEV_IO_CTRL_PHY_WR            Write physical device.
*                   (j) FS_DEV_IO_CTRL_PHY_RD_PAGE       Read  physical device page.
*                   (k) FS_DEV_IO_CTRL_PHY_WR_PAGE       Write physical device page.
*                   (l) FS_DEV_IO_CTRL_PHY_ERASE_BLK     Erase physical device block.
*                   (m) FS_DEV_IO_CTRL_PHY_ERASE_CHIP    Erase physical device.
*
*                   Not all of these operations are valid for all devices.
*********************************************************************************************************
*/

static  void  FSDev_CF_Card_IO_Ctrl (FS_DEV      *p_dev,
                                  CPU_INT08U   opt,
                                  void        *p_data,
                                  FS_ERR      *p_err)
{
   (void)&p_dev;
   (void)&opt;
   (void)&p_data;


                                                                /* ------------------ PERFORM I/O CTL ----------------- */
   *p_err = FS_ERR_DEV_INVALID_IO_CTRL;
}


/*
*********************************************************************************************************
*********************************************************************************************************
*                                           LOCAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                       FSDev_CF_Card_DataFree()
*
* Description : Free a CF_Card data object.
*
* Argument(s) : p_CF_Card_data   Pointer to a CF_Card data object.
*               -----------   Argument validated by caller.
*
* Return(s)   : none.
*
* Caller(s)   : FSDev_CF_Card_Close().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  void  FSDev_CF_Card_DataFree (FS_DEV_CF_Card_DATA  *p_CF_Card_data)
{
    CPU_SR_ALLOC();


    CPU_CRITICAL_ENTER();
    p_CF_Card_data->Type      = FS_DEV_CF_Card_TYPE_NONE;
    p_CF_Card_data->NextPtr   = FSDev_CF_Card_ListFreePtr;            /* Add to free pool.                                    */
    FSDev_CF_Card_ListFreePtr = p_CF_Card_data;
    CPU_CRITICAL_EXIT();
}


/*
*********************************************************************************************************
*                                        FSDev_CF_Card_DataGet()
*
* Author      : Lance Simms (12/16/10)
*
* Description : Allocate & initialize a CF_Card data object.
*
* Argument(s) : none.
*
* Return(s)   : Pointer to a CF_Card data object, if NO errors.
*               Pointer to NULL,               otherwise.
*
* Caller(s)   : FSDev_CF_Card_Open().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  FS_DEV_CF_Card_DATA  *FSDev_CF_Card_DataGet (void)
{
    LIB_ERR            alloc_err;
    CPU_SIZE_T         octets_reqd;
    FS_DEV_CF_Card_DATA  *p_CF_Card_data;
    CPU_SR_ALLOC();


                                                                /* --------------------- ALLOC DATA ------------------- */
    CPU_CRITICAL_ENTER();
    if (FSDev_CF_Card_ListFreePtr == (FS_DEV_CF_Card_DATA *)0) {
        p_CF_Card_data = (FS_DEV_CF_Card_DATA *)Mem_HeapAlloc( sizeof(FS_DEV_CF_Card_DATA),
                                                         sizeof(CPU_INT32U),
                                                        &octets_reqd,
                                                        &alloc_err);
        if (p_CF_Card_data == (FS_DEV_CF_Card_DATA *)0) {
            CPU_CRITICAL_EXIT();
            FS_TRACE_DBG(("FSDev_CF_Card_DataGet(): Could not alloc mem for CF_Card data: %d octets required.\r\n", octets_reqd));
            return ((FS_DEV_CF_Card_DATA *)0);
        }
        (void)&alloc_err;

        FSDev_CF_Card_UnitCtr++;


    } else {
        p_CF_Card_data            = FSDev_CF_Card_ListFreePtr;
        FSDev_CF_Card_ListFreePtr = FSDev_CF_Card_ListFreePtr->NextPtr;
    }
    CPU_CRITICAL_EXIT();


                                                                /* ---------------------- CLR DATA -------------------- */
    p_CF_Card_data->Type      =  FS_DEV_CF_Card_TYPE_CF_Card;   /* Type of card is a name of CFCA                       */
    p_CF_Card_data->UnitNbr   =  0;                             /* Unit number = card 0                                 */
    p_CF_Card_data->SecSize   =  512u;                          /* number of bytes per sector                           */
    p_CF_Card_data->SecCnt    =  63744;                         /* number off sectors on disk                           */
    p_CF_Card_data->DiskPtr   = (void *)0;

#if (FS_CFG_CTR_STAT_EN   == DEF_ENABLED)
    p_CF_Card_data->StatRdCtr =  0u;
    p_CF_Card_data->StatWrCtr =  0u;
#endif

    p_CF_Card_data->NextPtr   = (FS_DEV_CF_Card_DATA *)0;

#if (FS_CFG_CTR_ERR_EN     == DEF_ENABLED)                      /* Clr err ctrs.                                        */
   /* $$$$ CLEAR ERROR COUNTERS */
#endif

    return (p_CF_Card_data);
}
  		  	 	    		 			 			  	  			 	 	  		  			 		 		   		 	 	  		 
