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 */