www.pudn.com > wsp75_Drivers_cf.rar > KEV7A400_cf_driver.c


/*********************************************************************** 
 * $Workfile:   KEV7A400_cf_driver.c  $ 
 * $Revision:   1.1  $ 
 * $Author:   WellsK  $ 
 * $Date:   Sep 02 2002 16:24:34  $ 
 * 
 * Project: Compact Flash interface driver 
 * 
 * Description: 
 *  This driver reads and writes raw 'sectors' in the CF card via 
 *  the Cylinder/Head/Sector (CHS) mechanism. Support functions for 
 *  initializing and locating the card are available. All bookkeeping 
 *  functions related to supporting the CF interface must be performed 
 *  at a higher driver level. Multitasking in the CF interface is not 
 *  supported. If a read operation is performed, the data should be 
 *  read from the card before another operation is performed. 
 * 
 * Revision History: 
 * $Log:   //smaicnt2/pvcs/VM/CHIPS/archives/LH7A400/Compact Flash/Drivers/KEV7A400_cf_driver.c-arc  $ 
 *  
 *    Rev 1.1   Sep 02 2002 16:24:34   WellsK 
 * Read and write functions return number of bytes that have 
 * been read or written instead of PASS/FAIL (1/0). 
 *  
 *    Rev 1.0   Aug 22 2002 15:59:42   MaysR 
 * Initial revision. 
 *  
 * 
 * SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION 
 * OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE, 
 * AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,  
 * SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE. 
 * 
 * SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY  
 * FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A  
 * SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE 
 * FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS. 
 * 
 * COPYRIGHT (C) 2002 SHARP MICROELECTRONICS OF THE AMERICAS, INC. 
 *     CAMAS, WA 
 **********************************************************************/ 
#include "SMA_types.h" 
#include "KEV7A400_cf_driver.h" 
 
static void cfif_get_chs (void); 
 
// CHS mapping values 
static UNS_16 max_cyl, max_heads, max_sectors_track; 
 
/*********************************************************************** 
 * Function: cfif_get_chs 
 * 
 * Purpose:  Sets up the device specific CHS values. 
 * 
 * Processing:  Issues the CF identification command and reads the CF  
 *              status. The CHS sizing from the CF card is used by the 
 *              driver. 
 * 
 * Parameters:  None 
 * 
 * Outputs:  None 
 * 
 * Returns:  Nothing 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
static void cfif_get_chs (void) 
{ 
    UNS_16 data [256]; 
 
    // Issue a read attributes command to the CF device 
    CF_STAT->status_command = CFC_IDENT; 
 
    // Wait for command to complete 
    while (cfif_is_card_busy () == 1); 
 
    // Move data into the buffer 
    cfif_read_data (data, 512); 
 
    // Save the 3 needed values 
    max_cyl = (UNS_16) data [54]; 
    max_heads = (UNS_16) data [55]; 
    max_sectors_track = (UNS_16) data [56]; 
} 
 
/*********************************************************************** 
 * Function: cfif_init 
 * 
 * Purpose:  Initialize the CF interface and return the card detection  
 *           status. 
 * 
 * Processing:  The pointers used in this driver are initialized. 
 * 
 * Parameters:  None 
 * 
 * Outputs:  None 
 * 
 * Returns:  '1' if a CF card has been detected, '0' otherwise. 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
INT_32 cfif_init (void) 
{ 
    INT_32 inserted; 
 
    inserted = cfif_is_card_inserted (); 
    if (inserted == 1) 
    { 
        // Get CHS mappings (used for absolute sector conversion) 
        cfif_get_chs (); 
    } 
    return inserted; 
} 
 
/*********************************************************************** 
 * Function: cfif_shutdown 
 * 
 * Purpose:  Shutdown the CF interface driver. 
 * 
 * Processing:  This function does nothing and is a placeholder. 
 * 
 * Parameters:  None 
 * 
 * Outputs:  None 
 * 
 * Returns:  Nothing 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
void cfif_shutdown (void) 
{ 
    // Do nothing 
    ; 
} 
 
/*********************************************************************** 
 * Function: cfif_is_card_inserted 
 * 
 * Purpose:  Determine if a card is inserted 
 * 
 * Processing:  TBD 
 * 
 * Parameters:  None 
 * 
 * Outputs:  None 
 * 
 * Returns:  '1' if a card is inserted, '0' otherwise. 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
INT_32 cfif_is_card_inserted (void) 
{ 
    if ((CF_STAT->status_command & CF_DETECT_MASK) == CF_DETECT_VALUE) 
        return 1; 
    return 0; 
} 
 
/*********************************************************************** 
 * Function: cfif_is_card_ready 
 * 
 * Purpose:  Determines if the card is ready for a new command. 
 * 
 * Processing:  If the CF_RDY bit in the CF status register is set,  
 *              return '1', else return a '0'. 
 * 
 * Parameters:  None 
 * 
 * Outputs:  None 
 * 
 * Returns:  '1' if the card is ready for a new command, otherwise '0'. 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
INT_32 cfif_is_card_ready (void) 
{ 
    return ((CF_STAT->status_command & CF_RDY) != 0); 
} 
 
/*********************************************************************** 
 * Function: cfif_is_card_busy 
 * 
 * Purpose:  Determine if a card is busy (processing a command). 
 * 
 * Processing:  If the CF_BUSY bit in the CF status register is set,  
 *              return '1', else return a '0'. 
 *  
 * Parameters:  None 
 * 
 * Outputs:  None 
 * 
 * Returns:  '1' if the card is busy, '0' otherwise. 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
INT_32 cfif_is_card_busy (void) 
{ 
    if (CF_STAT->status_command & CF_BUSY) 
        return 1; 
    return 0; 
} 
 
/*********************************************************************** 
 * Function: cfif_set_sector 
 * 
 * Purpose:  Set the cylinder, head, and sector for the next operation  
 *           (using the absolute sector number). 
 * 
 * Processing:  The sector passed from the caller update the CHS  
 *              device pointers that will be used for the next  
 *              operation. 
 * 
 * Parameters:  sectorno : Sector number 
 * 
 * Outputs:  None 
 * 
 * Returns:  Nothing 
 * 
 * Notes:  The convention is Cylinder/Head/Sector (CHS). The function  
 *         will convert the CHS values to a value that works with the  
 *         CF card. 
 * 
 **********************************************************************/ 
void cfif_set_sector (UNS_32 sectorno) 
{ 
    UNS_16 sector, head, cylinder; 
    UNS_32 csector; 
 
    // Compute real sector number 
    csector = sectorno / (UNS_32) max_sectors_track; 
    csector = (UNS_32) max_sectors_track * csector; 
    sector = (UNS_16) (sectorno - csector + 1); 
 
    // Compute cylinder 
    cylinder = (UNS_16) (sectorno / 
        ((UNS_32) max_sectors_track * (UNS_32) max_heads)); 
 
    // Compute head 
    head = (UNS_16) (sectorno / (UNS_32) max_sectors_track - 
        ((UNS_32) cylinder * (UNS_32) max_heads)); 
 
    // Setup the IDE controller with the CHS mappings 
    CF_STAT->cyl_low = (UNS_16)(cylinder & 0xFF); 
    CF_STAT->cyl_hi = (UNS_16)((cylinder & 0xFF00) >> 8); 
    CF_STAT->sel_card = head; 
    CF_STAT->sector_no = sector; 
} 
 
/*********************************************************************** 
 * Function: cfif_send_command 
 * 
 * Purpose:  Send command to CF card 
 * 
 * Processing:   
 * 
 * Parameters:  Command to send to CF card 
 * 
 * Outputs:  None 
 * 
 * Returns:  Nothing 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
void cfif_send_command (UNS_32 command) 
{ 
    CF_STAT->status_command = (UNS_16)command; 
} 
 
/*********************************************************************** 
 * Function: cfif_start_sector_read 
 * 
 * Purpose:  Starts the read of a sector. 
 * 
 * Processing:  Set the sector size to '1' and issue the sector read command. 
 * 
 * Parameters:  None 
 * 
 * Outputs:  None 
 * 
 * Returns:  Nothing 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
void cfif_start_sector_read (void) 
{ 
    CF_STAT->sector_count = 1; 
    CF_STAT->status_command = CFC_R_SECT; 
} 
 
/*********************************************************************** 
 * Function: cfif_start_sector_write 
 * 
 * Purpose:  Starts the write of a sector. 
 * 
 * Processing:  Set the sector size to '1' and issue the sector write command. 
 * 
 * Parameters:  None 
 * 
 * Outputs:  None 
 * 
 * Returns:  Nothing 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
void cfif_start_sector_write (void) 
{ 
    CF_STAT->sector_count = 1; 
    CF_STAT->status_command = CFC_W_SECT; 
} 
 
/*********************************************************************** 
 * Function: cfif_read_data 
 * 
 * Purpose:  Read a block of data from the CF card. 
 * 
 * Processing:  Copy a block of data of from the CF card buffer to the  
 *              destination address. 
 * 
 * Parameters:  
 *          data  : Pointer to where to put read data from the CF card 
 *          bytes : Number of bytes to read 
 * 
 * Outputs:  The data pointed to by data will be updated. 
 * 
 * Returns:  The number of bytes read from the card. 
 * 
 * Notes:  Data is read AFTER a read command. 
 * 
 **********************************************************************/ 
INT_32 cfif_read_data (void *data, INT_32 bytes) 
{ 
    INT_32 i; 
    UNS_16 *cf_data = (UNS_16 *) data; 
 
    for (i = 0; i < (bytes / 2); i++) 
    { 
        *cf_data = CF_STAT->data; 
        cf_data++; 
    if (CF_STAT->status_command & CF_DWF) 
        return 0; 
    } 
    return bytes; 
} 
 
/*********************************************************************** 
 * Function: cfif_write_data 
 * 
 * Purpose:  Write data to the CF card. 
 * 
 * Processing:  Copy a block of data of from the source address to the  
 *              CF card buffer. 
 * 
 * Parameters: 
 *          data  : Pointer to where to get data to write to the CF card 
 *          bytes : Number of bytes to write 
 * 
 * Outputs:  None 
 * 
 * Returns:  The number of bytes written to the card. 
 * 
 * Notes:  Data is written after a write command. 
 * 
 **********************************************************************/ 
INT_32 cfif_write_data (void *data, INT_32 bytes) 
{ 
    INT_32 i; 
    UNS_16 *cf_data = (UNS_16 *) data; 
 
    for (i = 0; i < (bytes / 2); i++) 
    { 
        // Fill write buffer 
        CF_STAT->data = *cf_data; 
        cf_data++; 
    } 
    if (CF_STAT->status_command & CF_DWF) 
        return 0; 
    return bytes; 
} 
 
/*********************************************************************** 
 * Function: cfif_erase_sector 
 * 
 * Purpose:  Erase CF card sectors. 
 * 
 * Processing:  Erase requested number of card sectors starting with 
 *              specified sector number 
 * 
 * Parameters: 
 *          start: Starting sector number 
 *          bytes : Number of sectors to erase 
 * 
 * Outputs:  None 
 * 
 * Returns:  Success or fail 
 * 
 * Notes:  None 
 * 
 **********************************************************************/ 
INT_32 cfif_erase_sector (INT_32 sectorno) 
{ 
    cfif_set_sector(sectorno); 
    CF_STAT->sector_count = (1); 
    cfif_send_command(CFC_E_SECT); 
    if (CF_STAT->status_command & CF_DWF) 
        return 1; 
    return 0; 
}