www.pudn.com > efs.rar > fs_hotplug_sd.c


/*********************************************************************** 
 * fs_hotplug_sd.c 
 * 
 * Short description. 
 * Copyright (C) 2006 QUALCOMM, Inc. 
 * 
 * Verbose Description 
 * 
 ***********************************************************************/ 
 
/*=========================================================================== 
 
                        EDIT HISTORY FOR MODULE 
 
  This section contains comments describing changes made to the module. 
  Notice that changes are listed in reverse chronological order. 
 
  $Header: //depot/asic/MSMSHARED/services/efs/MSM_EFS.01.02/fs_hotplug_sd.c#18 $ $DateTime: 2006/11/13 14:44:34 $ $Author: davidb $ 
 
when         who   what, where, why 
----------   ---   --------------------------------------------------------- 
2006-11-09   sch   Implemented common functions b/w CPRM and normal SD 
2006-07-12   s h   Replace FS_GLOBAL_LOCK with SDCC critical section 
2006-06-25   s h   Replaced sd-specific "SD_STATE" with was_present 
2006-06-28   s h   Hold FS_GLOBAL lock only for SD's is_present() 
2006-06-06   s h   Do not allow read/write on closed sd card. 
2006-06-02   s h   Added reset handler 
2006-05-23   s h   Remove redundant INIT call from is_present 
2006-05-23   sch   Initialized the SD controller before opening 
2006-05-17   s h   Always leave a missing card in CLOSED state 
2006-05-17   s h   Careful selection between SDCC/MMC 
2006-05-12   s h   Split 7500 SDCC from normal SDCC. 
2006-05-12   s h   Added 7500-specific naming for SDCC. 
2006-05-10   s h   Replaced DRV_GEOMETRY_DESC with block size & count 
2006-05-08   s h   Removed umount from device-specific calls. 
2006-05-04   s h   Reworked open/close logic to account for sdcc closing 
2006-05-04   s h   Protect against redundant open/close 
2006-04-24   s h   Renamed control flag to FS_HOTPLUG_SD 
2006-04-22   s h   Moved all private definitions into fs_hotplug_i.h 
2006-04-14   s h   Corrected logic bug in SD detect. 
2006-04-13   s h   Include assert.h 
2006-03-31   sch   Modified hotplug_sd_is_present() to include device open 
2006-03-31   s h   Unified MMC & SD through macros 
2006-03-23   s h   Created by moving sd-specific functions out of hotplug 
 
===========================================================================*/ 
 
#include "fs_hotplug.h" 
#include "fs_hotplug_i.h" 
#include "fs_hotplug_sd.h" 
#include "fs_hotplug_sd_lock.h" 
 
#ifdef FS_HOTPLUG_SD 
 
#include "assert.h" 
 
/* These macros lock and unlock the SD card in use.  Note that they 
 * make some assumptions about a local hdev variable being present. */ 
#define LOCK     hotplug_sd_lock(hdev) 
#define UNLOCK   hotplug_sd_unlock(hdev) 
 
/* 
 * SDCC, SDCC_DM, or MMC? 
 * The APIs are all the same, but different. 
 */ 
/* This must come first, since 7500 Apps defines both SDCC flags */ 
#if defined FEATURE_SDCC_EXTERNAL_DM 
#error code not present 
#elif defined FEATURE_DRV_SDCC 
#  include "sdcc_api.h"      /* This also defines drv_geometry_desc */ 
#  define MMC_READ_SERIAL     sdcc_read_serial 
#  define MMC_INIT(x)         sdcc_init(/* no driveno */) 
#  define MMC_OPEN            sdcc_open 
#  define MMC_CLOSE           sdcc_close 
#  define MMC_READ            sdcc_read 
#  define MMC_WRITE           sdcc_write 
 
   extern int mmc_send_status (uint16); 
#  define MMC_SEND_STATUS(x)  mmc_send_status(x) 
 
/* MMC */ 
#else 
#  include "mmcapi.h"        /* This also defines drv_geometry_desc */ 
#  define MMC_READ_SERIAL     mmc_read_serial 
#  define MMC_INIT(x)         mmc_init() 
#  define MMC_OPEN            mmc_drive_open 
#  define MMC_CLOSE           mmc_drive_close 
#  define MMC_READ            mmc_read 
#  define MMC_WRITE           mmc_write 
#  define MMC_SEND_STATUS(x)  mmc_send_status(/*void*/) 
#endif 
 
int 
hotplug_sd_get_size (struct hotplug_device *hdev, uint32 *blocks, 
                     uint16 *bytes_per_block) 
{ 
  int result; 
  struct drv_geometry_desc fat_geom; 
  DRV_GEOMETRY_DESC *desc = (DRV_GEOMETRY_DESC *) &fat_geom; 
 
  LOCK; 
  result = MMC_READ_SERIAL (hdev->driveno, desc); 
  UNLOCK; 
 
  *blocks = desc->totalLBA; 
  *bytes_per_block = desc->dfltBytesPerSect; 
 
  return (result == 0) ? -1 : 0; 
} 
 
/* We need to lock access to the SDCC driver while we fetch status, 
 * since it issues an SDCC command and would corrupt any read/write in 
 * progress */ 
static int 
hotplug_sd_status (struct hotplug_device *hdev) 
{ 
  int result; 
  (void) hdev;                  /* Not all macros use hdev->driveno. */ 
 
  LOCK; 
  result = MMC_SEND_STATUS (hdev->driveno); 
  UNLOCK; 
  return result; 
} 
 
/* 
 * Returns TRUE if an SD card is present in this device. 
 * 
 * If we had a HARDWARE physical card-presence switch, that would be a 
 * great help here.  Then, the logic would first check the physical 
 * switch (GPIO?) to see if it should bother looking for a card.  If 
 * the physical switch was 'empty' we could return immediately without 
 * doing a costly and slow poll. 
 * 
 * If the switch showed something positively in the slot, then we 
 * would do the device poll to confirm a good card was found. 
 * 
 * Maybe future Surfs will have this switch.  (Customers are 
 * encouraged to improve this function to detect a card more quickly 
 * on their particular design.) 
 * 
 * 
 * As far as we know, mmc_send_status() returns 1 when a card is 
 * present, zero when not present. 
 * 
 * A newly (re)inserted card must be initialized.  The only time the 
 * card status is actually fetched is when sdcc_open() is called, so 
 * we must close and open the card each time.  The code attempts to 
 * leave an empty slot in the 'closed' state (returns FALSE). 
 * 
 * A slot with a detected card in it is left in the 'open' state when 
 * we return TRUE. 
 */ 
 
int 
hotplug_sd_is_present (struct hotplug_device *hdev) 
{ 
  if (hdev->was_present) 
  { 
    /* Check if the card that was there earlier is now gone/changed */ 
    if (hotplug_sd_status (hdev) == 0) { 
      hdev->was_present = FALSE; 
      (void) hdev->dev->close (hdev); /* CLOSE it */ 
    } 
  } 
  else 
  { 
    /* If both of these succeed, then the card is now present: */ 
    if ((hdev->dev->open (hdev) == 0) 
        && (hotplug_sd_status (hdev) != 0)) 
      hdev->was_present = TRUE; 
    else 
      (void) hdev->dev->close (hdev); /* Leave it CLOSED */ 
  } 
 
  return hdev->was_present; 
} 
 
/* Open the MMC/SD device.  Do nothing if it's already open. */ 
int 
hotplug_sd_open_device (struct hotplug_device *hdev) 
{ 
  if (! hdev->sd_is_open) { 
    LOCK; 
    /* Every sd open() call needs an INIT first, so do it here: */ 
    MMC_INIT (hdev->driveno); 
 
    /* If MMC_OPEN fails, then it leaves the card "closed" */ 
    hdev->sd_is_open = !!MMC_OPEN (hdev->driveno); 
    UNLOCK; 
  } 
  return hdev->sd_is_open ? 0 : -1; 
} 
 
/* Close the MMC/SD device.  Do nothing if it's already closed. */ 
int 
hotplug_sd_close_device (struct hotplug_device *hdev) 
{ 
  if (hdev->sd_is_open) { 
    LOCK; 
    hdev->sd_is_open = !MMC_CLOSE (hdev->driveno); 
    UNLOCK; 
    /* This state needs to be modified here, because this function might 
       get called from hotplug_lock_dev() */ 
    hdev->was_present = FALSE; 
  } 
  return hdev->sd_is_open ? -1 : 0; 
} 
 
/* Do not permit read operations if the device is closed */ 
int 
hotplug_sd_read (struct hotplug_device *hdev, 
                 uint32 lba, unsigned char *buf, uint16 n_to_read) 
{ 
  int result; 
  if (hdev->sd_is_open) { 
    LOCK; 
    result = (MMC_READ (hdev->driveno, lba, buf, n_to_read) != 0) ? 0 : -1; 
    UNLOCK; 
  } 
  else 
    result = -1; 
 
  return result; 
} 
 
 
/* Do not permit write operations if the device is closed */ 
int 
hotplug_sd_write (struct hotplug_device *hdev, 
                  uint32 lba, unsigned char *buf, uint16 n_to_write) 
{ 
  int result; 
  if (hdev->sd_is_open) { 
    LOCK; 
    result = (MMC_WRITE (hdev->driveno, lba, buf, n_to_write) != 0) ? 0 : -1; 
    UNLOCK; 
  } 
  else 
    result = -1; 
 
  return result; 
} 
 
int 
hotplug_sd_format (struct hotplug_device *hdev) 
{ 
  /* Make sure a card is present */ 
  if (!hdev->dev->is_present (hdev)) 
    return -1; 
 
  ASSERT (hdev->sd_is_open); 
 
  return 0;                     /* OK, ready to format */ 
} 
 
int 
hotplug_sd_reset (struct hotplug_device *hdev) 
{ 
  hotplug_sd_lock_init (hdev); 
  return 0; 
} 
 
 
struct hotplug_dev_funcs hotplug_sd_dev = { 
  hotplug_fat_mount, 
  hotplug_sd_open_device, 
  hotplug_sd_close_device, 
  hotplug_sd_read, 
  hotplug_sd_write, 
  hotplug_sd_write, 
  hotplug_no_erase, 
  hotplug_sd_get_size, 
  hotplug_sd_is_present, 
  hotplug_sd_format, 
  hotplug_sd_reset,             /* Reset */ 
}; 
#else 
extern int __dont_complain_about_empty_file; 
#endif /* FS_HOTPLUG_SD */