Merge branch 'hotswap'

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23759 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Maurus Cuelenaere 2009-11-26 16:57:30 +00:00
parent b2dc7f004e
commit d052ced874
7 changed files with 282 additions and 125 deletions

View file

@ -74,7 +74,11 @@ int release_dirs(int volume)
int closed = 0; int closed = 0;
for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++) for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++)
{ {
#ifdef HAVE_MULTIVOLUME
if (pdir->fatdir.file.volume == volume) if (pdir->fatdir.file.volume == volume)
#else
(void)volume;
#endif
{ {
pdir->busy = false; /* mark as available, no further action */ pdir->busy = false; /* mark as available, no further action */
closed++; closed++;

View file

@ -782,7 +782,11 @@ int release_files(int volume)
int closed = 0; int closed = 0;
for ( fd=0; fd<MAX_OPEN_FILES; fd++, pfile++) for ( fd=0; fd<MAX_OPEN_FILES; fd++, pfile++)
{ {
#ifdef HAVE_MULTIVOLUME
if (pfile->fatfile.volume == volume) if (pfile->fatfile.volume == volume)
#else
(void)volume;
#endif
{ {
pfile->busy = false; /* mark as available, no further action */ pfile->busy = false; /* mark as available, no further action */
closed++; closed++;

View file

@ -458,11 +458,15 @@ int fat_mount(IF_MV2(int volume,) IF_MD2(int drive,) long startsector)
int fat_unmount(int volume, bool flush) int fat_unmount(int volume, bool flush)
{ {
int rc; int rc;
#ifdef HAVE_MULTIVOLUME
struct bpb* fat_bpb = &fat_bpbs[volume]; struct bpb* fat_bpb = &fat_bpbs[volume];
#else
(void)volume;
#endif
if(flush) if(flush)
{ {
rc = flush_fat(fat_bpb); /* the clean way, while still alive */ rc = flush_fat(IF_MV(fat_bpb)); /* the clean way, while still alive */
} }
else else
{ /* volume is not accessible any more, e.g. MMC removed */ { /* volume is not accessible any more, e.g. MMC removed */
@ -471,7 +475,11 @@ int fat_unmount(int volume, bool flush)
for(i = 0;i < FAT_CACHE_SIZE;i++) for(i = 0;i < FAT_CACHE_SIZE;i++)
{ {
struct fat_cache_entry *fce = &fat_cache[i]; struct fat_cache_entry *fce = &fat_cache[i];
if(fce->inuse && fce->fat_vol == fat_bpb) if(fce->inuse
#ifdef HAVE_MULTIVOLUME
&& fce->fat_vol == fat_bpb
#endif
)
{ {
fce->inuse = false; /* discard all from that volume */ fce->inuse = false; /* discard all from that volume */
fce->dirty = false; fce->dirty = false;
@ -480,7 +488,9 @@ int fat_unmount(int volume, bool flush)
mutex_unlock(&cache_mutex); mutex_unlock(&cache_mutex);
rc = 0; rc = 0;
} }
#ifdef HAVE_MULTIVOLUME
fat_bpb->mounted = false; fat_bpb->mounted = false;
#endif
return rc; return rc;
} }
#endif /* #ifdef HAVE_HOTSWAP */ #endif /* #ifdef HAVE_HOTSWAP */

View file

@ -167,11 +167,19 @@
#define CFG_EXTAL 12000000 /* EXT clock: 12 Mhz */ #define CFG_EXTAL 12000000 /* EXT clock: 12 Mhz */
/*
No access to the NAND yet..
#define CONFIG_STORAGE (STORAGE_NAND | STORAGE_SD) #define CONFIG_STORAGE (STORAGE_NAND | STORAGE_SD)
#define NUM_DRIVES 2 #define NUM_DRIVES 2
*/
#define CONFIG_STORAGE (STORAGE_SD)
#define NUM_DRIVES 1
#define HAVE_HOTSWAP_STORAGE_AS_MAIN
#define INCLUDE_TIMEOUT_API
/* Define this if media can be exchanged on the fly */ /* Define this if media can be exchanged on the fly */
//#define HAVE_HOTSWAP #define HAVE_HOTSWAP
/* Define this if you have a Ingenic JZ4732 */ /* Define this if you have a Ingenic JZ4732 */
#define CONFIG_CPU JZ4732 #define CONFIG_CPU JZ4732

View file

@ -22,25 +22,40 @@
#include "config.h" #include "config.h"
#include "jz4740.h" #include "jz4740.h"
#include "ata.h" #include "ata.h"
#include "ata_idle_notify.h"
#include "ata-sd-target.h" #include "ata-sd-target.h"
#include "disk.h"
#include "fat.h"
#include "led.h"
#include "hotswap.h"
#include "logf.h" #include "logf.h"
#include "sd.h" #include "sd.h"
#include "system.h" #include "system.h"
#include "kernel.h" #include "kernel.h"
#include "panic.h"
#include "debug.h"
#include "storage.h" #include "storage.h"
#include "string.h" #include "string.h"
#include "led.h" #include "usb.h"
static struct wakeup sd_wakeup; static long last_disk_activity = -1;
static long last_disk_activity = -1; static int sd_drive_nr = 0;
static tCardInfo card; static tCardInfo card;
static long sd_stack[(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)];
static const char sd_thread_name[] = "ata/sd";
static struct event_queue sd_queue;
static struct mutex sd_mtx;
static struct wakeup sd_wakeup;
static void sd_thread(void) __attribute__((noreturn));
static int use_4bit;
static int num_6;
static int sd2_0;
//#define SD_DMA_ENABLE //#define SD_DMA_ENABLE
#define SD_DMA_INTERRUPT 0 #define SD_DMA_INTERRUPT 0
#define DEBUG(x...) logf(x) //#define DEBUG(x...) logf(x)
#define DEBUG(x, ...)
#define SD_INSERT_STATUS() __gpio_get_pin(MMC_CD_PIN) #define SD_INSERT_STATUS() __gpio_get_pin(MMC_CD_PIN)
#define SD_RESET() __msc_reset() #define SD_RESET() __msc_reset()
@ -117,7 +132,6 @@ enum sd_rsp_t
RESPONSE_R7 = 9, RESPONSE_R7 = 9,
}; };
/* /*
MMC status in R1 MMC status in R1
Type Type
@ -199,10 +213,6 @@ struct sd_request
#define SD_EVENT_TX_DATA_DONE 0x02 /* Tx data done */ #define SD_EVENT_TX_DATA_DONE 0x02 /* Tx data done */
#define SD_EVENT_PROG_DONE 0x04 /* Programming is done */ #define SD_EVENT_PROG_DONE 0x04 /* Programming is done */
static int use_4bit = 1; /* Use 4-bit data bus */
static int num_6 = 0;
static int sd2_0 = 0;
/************************************************************************** /**************************************************************************
* Utility functions * Utility functions
**************************************************************************/ **************************************************************************/
@ -214,7 +224,7 @@ static int sd2_0 = 0;
#define PARSE_U16(_buf,_index) \ #define PARSE_U16(_buf,_index) \
(((unsigned short)_buf[_index]) << 8) | ((unsigned short)_buf[_index+1]); (((unsigned short)_buf[_index]) << 8) | ((unsigned short)_buf[_index+1]);
int sd_unpack_r1(struct sd_request *request, struct sd_response_r1 *r1) static int sd_unpack_r1(struct sd_request *request, struct sd_response_r1 *r1)
{ {
unsigned char *buf = request->response; unsigned char *buf = request->response;
@ -253,17 +263,7 @@ int sd_unpack_r1(struct sd_request *request, struct sd_response_r1 *r1)
return 0; return 0;
} }
int sd_unpack_scr(struct sd_request *request, struct sd_response_r1 *r1, unsigned int *scr) static int sd_unpack_r6(struct sd_request *request, struct sd_response_r1 *r1, unsigned long *rca)
{
unsigned char *buf = request->response;
if (request->result)
return request->result;
*scr = PARSE_U32(buf, 5); /* Save SCR returned by the SD Card */
return sd_unpack_r1(request, r1);
}
static inline int sd_unpack_r6(struct sd_request *request, struct sd_response_r1 *r1, unsigned long *rca)
{ {
unsigned char *buf = request->response; unsigned char *buf = request->response;
@ -278,7 +278,7 @@ static inline int sd_unpack_r6(struct sd_request *request, struct sd_response_r1
return sd_unpack_r1(request, r1); return sd_unpack_r1(request, r1);
} }
int sd_unpack_r3(struct sd_request *request, struct sd_response_r3 *r3) static int sd_unpack_r3(struct sd_request *request, struct sd_response_r3 *r3)
{ {
unsigned char *buf = request->response; unsigned char *buf = request->response;
@ -287,7 +287,9 @@ int sd_unpack_r3(struct sd_request *request, struct sd_response_r3 *r3)
r3->ocr = PARSE_U32(buf,1); r3->ocr = PARSE_U32(buf,1);
DEBUG("sd_unpack_r3: ocr=%08x", r3->ocr); DEBUG("sd_unpack_r3: ocr=%08x", r3->ocr);
if (buf[0] != 0x3f) return SD_ERROR_HEADER_MISMATCH; if (buf[0] != 0x3f)
return SD_ERROR_HEADER_MISMATCH;
return 0; return 0;
} }
@ -917,7 +919,6 @@ static void jz_sd_tx_handler(unsigned int arg)
} }
if (__dmac_channel_transmit_end_detected(arg)) if (__dmac_channel_transmit_end_detected(arg))
{ {
__dmac_channel_clear_transmit_end(arg); __dmac_channel_clear_transmit_end(arg);
OSSemPost(sd_dma_tx_sem); OSSemPost(sd_dma_tx_sem);
} }
@ -945,6 +946,14 @@ void MSC(void)
logf("MSC interrupt"); logf("MSC interrupt");
} }
static void sd_gpio_setup_irq(bool inserted)
{
if(inserted)
__gpio_as_irq_rise_edge(MMC_CD_PIN);
else
__gpio_as_irq_fall_edge(MMC_CD_PIN);
}
/******************************************************************************************************************* /*******************************************************************************************************************
** Name: void sd_hardware_init() ** Name: void sd_hardware_init()
** Function: initialize the hardware condiction that access sd card ** Function: initialize the hardware condiction that access sd card
@ -954,7 +963,8 @@ void MSC(void)
static void jz_sd_hardware_init(void) static void jz_sd_hardware_init(void)
{ {
__cpm_start_msc(); /* enable mmc clock */ __cpm_start_msc(); /* enable mmc clock */
mmc_init_gpio(); /* init GPIO */ sd_init_gpio(); /* init GPIO */
sd_gpio_setup_irq(jz_sd_chkcard());
#ifdef SD_POWER_ON #ifdef SD_POWER_ON
SD_POWER_ON(); /* turn on power of card */ SD_POWER_ON(); /* turn on power of card */
#endif #endif
@ -1000,7 +1010,6 @@ static void sd_simple_cmd(struct sd_request *request, int cmd, unsigned int arg,
#define SD_INIT_DOING 0 #define SD_INIT_DOING 0
#define SD_INIT_PASSED 1 #define SD_INIT_PASSED 1
#define SD_INIT_FAILED 2 #define SD_INIT_FAILED 2
static int sd_init_card_state(struct sd_request *request) static int sd_init_card_state(struct sd_request *request)
{ {
struct sd_response_r1 r1; struct sd_response_r1 r1;
@ -1026,41 +1035,42 @@ static int sd_init_card_state(struct sd_request *request)
retval); retval);
limit_41++; limit_41++;
sd_simple_cmd(request, SD_APP_OP_COND, ocr, RESPONSE_R3); sd_simple_cmd(request, SD_APP_OP_COND, ocr, RESPONSE_R3);
} else if (limit_41 < 100) { }
else if (limit_41 < 100)
{
limit_41++; limit_41++;
sd_simple_cmd(request, SD_APP_OP_COND, ocr, RESPONSE_R3); sd_simple_cmd(request, SD_APP_OP_COND, ocr, RESPONSE_R3);
} else{ }
else
/* reset the card to idle*/ /* reset the card to idle*/
sd_simple_cmd(request, SD_GO_IDLE_STATE, 0, RESPONSE_NONE); sd_simple_cmd(request, SD_GO_IDLE_STATE, 0, RESPONSE_NONE);
}
break; break;
case SD_APP_OP_COND: case SD_APP_OP_COND:
retval = sd_unpack_r3(request, &r3); retval = sd_unpack_r3(request, &r3);
if (retval) if (retval)
{
break; break;
}
DEBUG("sd_init_card_state: read ocr value = 0x%08x", r3.ocr); DEBUG("sd_init_card_state: read ocr value = 0x%08x", r3.ocr);
card.ocr = r3.ocr; card.ocr = r3.ocr;
if(!(r3.ocr & SD_CARD_BUSY || ocr == 0)){ if(!(r3.ocr & SD_CARD_BUSY || ocr == 0))
udelay(10000); {
sleep(HZ / 100);
sd_simple_cmd(request, SD_APP_CMD, 0, RESPONSE_R1); sd_simple_cmd(request, SD_APP_CMD, 0, RESPONSE_R1);
} }
else else
{ {
/* Set the data bus width to 4 bits */ /* Set the data bus width to 4 bits */
use_4bit = 1; use_4bit = 1;
sd_simple_cmd(request, SD_ALL_SEND_CID, 0, RESPONSE_R2_CID); sd_simple_cmd(request, SD_ALL_SEND_CID, 0, RESPONSE_R2_CID);
} }
break; break;
case SD_ALL_SEND_CID: case SD_ALL_SEND_CID:
for(i=0; i<4; i++) for(i=0; i<4; i++)
card.cid[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) | card.cid[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) |
(request->response[3+i*4]<< 8) | request->response[4+i*4]); (request->response[3+i*4]<< 8) | request->response[4+i*4]);
logf("CID: %08lx%08lx%08lx%08lx", card.cid[0], card.cid[1], card.cid[2], card.cid[3]); logf("CID: %08lx%08lx%08lx%08lx", card.cid[0], card.cid[1], card.cid[2], card.cid[3]);
sd_simple_cmd(request, SD_SEND_RELATIVE_ADDR, 0, RESPONSE_R6); sd_simple_cmd(request, SD_SEND_RELATIVE_ADDR, 0, RESPONSE_R6);
@ -1068,7 +1078,7 @@ static int sd_init_card_state(struct sd_request *request)
case SD_SEND_RELATIVE_ADDR: case SD_SEND_RELATIVE_ADDR:
retval = sd_unpack_r6(request, &r1, &card.rca); retval = sd_unpack_r6(request, &r1, &card.rca);
card.rca = card.rca << 16; card.rca = card.rca << 16;
DEBUG("sd_init_card_state: Get RCA from SD: 0x%04x Status: %x", card.rca, r1.status); DEBUG("sd_init_card_state: Get RCA from SD: 0x%04lx Status: %x", card.rca, r1.status);
if (retval) if (retval)
{ {
DEBUG("sd_init_card_state: unable to SET_RELATIVE_ADDR error=%d", DEBUG("sd_init_card_state: unable to SET_RELATIVE_ADDR error=%d",
@ -1082,7 +1092,7 @@ static int sd_init_card_state(struct sd_request *request)
case SD_SEND_CSD: case SD_SEND_CSD:
for(i=0; i<4; i++) for(i=0; i<4; i++)
card.csd[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) | card.csd[i] = ((request->response[1+i*4]<<24) | (request->response[2+i*4]<<16) |
(request->response[3+i*4]<< 8) | request->response[4+i*4]); (request->response[3+i*4]<< 8) | request->response[4+i*4]);
sd_parse_csd(&card); sd_parse_csd(&card);
sd2_0 = (card_extract_bits(card.csd, 127, 2) == 1); sd2_0 = (card_extract_bits(card.csd, 127, 2) == 1);
@ -1091,6 +1101,7 @@ static int sd_init_card_state(struct sd_request *request)
DEBUG("SD card is ready"); DEBUG("SD card is ready");
jz_sd_set_clock(SD_CLOCK_FAST); jz_sd_set_clock(SD_CLOCK_FAST);
return SD_INIT_PASSED; return SD_INIT_PASSED;
default: default:
DEBUG("sd_init_card_state: error! Illegal last cmd %d", request->cmd); DEBUG("sd_init_card_state: error! Illegal last cmd %d", request->cmd);
return SD_INIT_FAILED; return SD_INIT_FAILED;
@ -1141,7 +1152,7 @@ static int sd_switch_hs(struct sd_request *request)
return 0; return 0;
} }
int sd_select_card(void) static int sd_select_card(void)
{ {
struct sd_request request; struct sd_request request;
struct sd_response_r1 r1; struct sd_response_r1 r1;
@ -1173,31 +1184,57 @@ int sd_select_card(void)
if (retval) if (retval)
return retval; return retval;
card.initialized = 1;
return 0; return 0;
} }
static int sd_init_device(void)
{
int retval;
struct sd_request init_req;
mutex_lock(&sd_mtx);
/* Initialise card data as blank */
memset(&card, 0, sizeof(tCardInfo));
sd2_0 = 0;
num_6 = 0;
use_4bit = 0;
/* reset mmc/sd controller */
jz_sd_hardware_init();
sd_simple_cmd(&init_req, SD_CIM_RESET, 0, RESPONSE_NONE);
sd_simple_cmd(&init_req, SD_GO_IDLE_STATE, 0, RESPONSE_NONE);
sleep(HZ/2); /* Give the card/controller some rest */
while((retval = sd_init_card_state(&init_req)) == SD_INIT_DOING);
retval = (retval == SD_INIT_PASSED ? sd_select_card() : -1);
mutex_unlock(&sd_mtx);
return retval;
}
int sd_init(void) int sd_init(void)
{ {
int retval;
static bool inited = false; static bool inited = false;
struct sd_request init_req;
if(!inited) if(!inited)
{ {
jz_sd_hardware_init();
wakeup_init(&sd_wakeup); wakeup_init(&sd_wakeup);
num_6 = 0; mutex_init(&sd_mtx);
queue_init(&sd_queue, true);
create_thread(sd_thread, sd_stack, sizeof(sd_stack), 0,
sd_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
IF_COP(, CPU));
inited = true; inited = true;
} }
sd_simple_cmd(&init_req, SD_CIM_RESET, 0, RESPONSE_NONE); return sd_init_device();
sd_simple_cmd(&init_req, SD_GO_IDLE_STATE, 0, RESPONSE_NONE);
while ((retval = sd_init_card_state(&init_req)) == SD_INIT_DOING);
if (retval == SD_INIT_PASSED)
return sd_select_card();
else
return -1;
} }
static inline bool card_detect_target(void) static inline bool card_detect_target(void)
@ -1205,20 +1242,6 @@ static inline bool card_detect_target(void)
return (jz_sd_chkcard() == 1); return (jz_sd_chkcard() == 1);
} }
#ifdef HAVE_HOTSWAP
void card_enable_monitoring_target(bool on)
{
if(on)
{
}
else
{
}
}
#endif
tCardInfo* card_get_info_target(int card_no) tCardInfo* card_get_info_target(int card_no)
{ {
(void)card_no; (void)card_no;
@ -1230,30 +1253,34 @@ int sd_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf
#ifdef HAVE_MULTIVOLUME #ifdef HAVE_MULTIVOLUME
(void)drive; (void)drive;
#endif #endif
mutex_lock(&sd_mtx);
led(true); led(true);
struct sd_request request; struct sd_request request;
struct sd_response_r1 r1; struct sd_response_r1 r1;
int retval; int retval = -1;
if (!card_detect_target() || count == 0 || start > card.numblocks) if (!card_detect_target() || count == 0 || start > card.numblocks)
return -1; goto err;
if(card.initialized == 0 && !sd_init_device())
goto err;
sd_simple_cmd(&request, SD_SEND_STATUS, card.rca, RESPONSE_R1); sd_simple_cmd(&request, SD_SEND_STATUS, card.rca, RESPONSE_R1);
retval = sd_unpack_r1(&request, &r1); retval = sd_unpack_r1(&request, &r1);
if (retval && (retval != SD_ERROR_STATE_MISMATCH)) if (retval && (retval != SD_ERROR_STATE_MISMATCH))
return retval; goto err;
sd_simple_cmd(&request, SD_SET_BLOCKLEN, SD_BLOCK_SIZE, RESPONSE_R1); sd_simple_cmd(&request, SD_SET_BLOCKLEN, SD_BLOCK_SIZE, RESPONSE_R1);
if ((retval = sd_unpack_r1(&request, &r1))) if ((retval = sd_unpack_r1(&request, &r1)))
return retval; goto err;
if (sd2_0) if (sd2_0)
{ {
sd_send_cmd(&request, SD_READ_MULTIPLE_BLOCK, start, sd_send_cmd(&request, SD_READ_MULTIPLE_BLOCK, start,
count, SD_BLOCK_SIZE, RESPONSE_R1, buf); count, SD_BLOCK_SIZE, RESPONSE_R1, buf);
if ((retval = sd_unpack_r1(&request, &r1))) if ((retval = sd_unpack_r1(&request, &r1)))
return retval; goto err;
} }
else else
{ {
@ -1261,16 +1288,18 @@ int sd_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* buf
start * SD_BLOCK_SIZE, count, start * SD_BLOCK_SIZE, count,
SD_BLOCK_SIZE, RESPONSE_R1, buf); SD_BLOCK_SIZE, RESPONSE_R1, buf);
if ((retval = sd_unpack_r1(&request, &r1))) if ((retval = sd_unpack_r1(&request, &r1)))
return retval; goto err;
} }
last_disk_activity = current_tick; last_disk_activity = current_tick;
sd_simple_cmd(&request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B); sd_simple_cmd(&request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B);
if ((retval = sd_unpack_r1(&request, &r1))) if ((retval = sd_unpack_r1(&request, &r1)))
return retval; goto err;
err:
led(false); led(false);
mutex_unlock(&sd_mtx);
return retval; return retval;
} }
@ -1280,23 +1309,27 @@ int sd_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const vo
#ifdef HAVE_MULTIVOLUME #ifdef HAVE_MULTIVOLUME
(void)drive; (void)drive;
#endif #endif
mutex_lock(&sd_mtx);
led(true); led(true);
struct sd_request request; struct sd_request request;
struct sd_response_r1 r1; struct sd_response_r1 r1;
int retval; int retval = -1;
if (!card_detect_target() || count == 0 || start > card.numblocks) if (!card_detect_target() || count == 0 || start > card.numblocks)
return -1; goto err;
if(card.initialized == 0 && !sd_init_device())
goto err;
sd_simple_cmd(&request, SD_SEND_STATUS, card.rca, RESPONSE_R1); sd_simple_cmd(&request, SD_SEND_STATUS, card.rca, RESPONSE_R1);
retval = sd_unpack_r1(&request, &r1); retval = sd_unpack_r1(&request, &r1);
if (retval && (retval != SD_ERROR_STATE_MISMATCH)) if (retval && (retval != SD_ERROR_STATE_MISMATCH))
return retval; goto err;
sd_simple_cmd(&request, SD_SET_BLOCKLEN, SD_BLOCK_SIZE, RESPONSE_R1); sd_simple_cmd(&request, SD_SET_BLOCKLEN, SD_BLOCK_SIZE, RESPONSE_R1);
if ((retval = sd_unpack_r1(&request, &r1))) if ((retval = sd_unpack_r1(&request, &r1)))
return retval; goto err;
if (sd2_0) if (sd2_0)
{ {
@ -1304,7 +1337,7 @@ int sd_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const vo
count, SD_BLOCK_SIZE, RESPONSE_R1, count, SD_BLOCK_SIZE, RESPONSE_R1,
(void*)buf); (void*)buf);
if ((retval = sd_unpack_r1(&request, &r1))) if ((retval = sd_unpack_r1(&request, &r1)))
return retval; goto err;
} }
else else
{ {
@ -1312,13 +1345,18 @@ int sd_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const vo
start * SD_BLOCK_SIZE, count, start * SD_BLOCK_SIZE, count,
SD_BLOCK_SIZE, RESPONSE_R1, (void*)buf); SD_BLOCK_SIZE, RESPONSE_R1, (void*)buf);
if ((retval = sd_unpack_r1(&request, &r1))) if ((retval = sd_unpack_r1(&request, &r1)))
return retval; goto err;
} }
last_disk_activity = current_tick;
sd_simple_cmd(&request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B); sd_simple_cmd(&request, SD_STOP_TRANSMISSION, 0, RESPONSE_R1B);
if ((retval = sd_unpack_r1(&request, &r1))) if ((retval = sd_unpack_r1(&request, &r1)))
return retval; goto err;
err:
led(false); led(false);
mutex_unlock(&sd_mtx);
return retval; return retval;
} }
@ -1342,10 +1380,9 @@ void sd_sleepnow(void)
{ {
} }
/* TODO */
bool sd_disk_is_active(void) bool sd_disk_is_active(void)
{ {
return false; return sd_mtx.locked;
} }
int sd_soft_reset(void) int sd_soft_reset(void)
@ -1359,8 +1396,39 @@ bool sd_removable(IF_MV_NONVOID(int drive))
#ifdef HAVE_MULTIVOLUME #ifdef HAVE_MULTIVOLUME
(void)drive; (void)drive;
#endif #endif
//return true; return true;
return false; }
void card_enable_monitoring_target(bool on)
{
if(on)
sd_gpio_setup_irq(card_detect_target());
else
__gpio_mask_irq(MMC_CD_PIN);
}
static int sd_oneshot_callback(struct timeout *tmo)
{
(void)tmo;
int state = card_detect_target();
/* This is called only if the state was stable for 300ms - check state
* and post appropriate event. */
if (state)
queue_broadcast(SYS_HOTSWAP_INSERTED, 0);
else
queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0);
sd_gpio_setup_irq(state);
return 0;
}
/* called on insertion/removal interrupt */
void MMC_CD_IRQ(void)
{
static struct timeout sd_oneshot;
timeout_register(&sd_oneshot, sd_oneshot_callback, (3*HZ/10), 0);
} }
#endif #endif
@ -1375,9 +1443,72 @@ bool sd_present(IF_MV_NONVOID(int drive))
#ifdef CONFIG_STORAGE_MULTI #ifdef CONFIG_STORAGE_MULTI
int sd_num_drives(int first_drive) int sd_num_drives(int first_drive)
{ {
/* We don't care which logical drive number(s) we have been assigned */ sd_drive_nr = first_drive;
(void)first_drive;
return 1; return 1;
} }
#endif #endif
static void sd_thread(void)
{
struct queue_event ev;
bool idle_notified = false;
while (1)
{
queue_wait_w_tmo(&sd_queue, &ev, HZ);
switch (ev.id)
{
#ifdef HAVE_HOTSWAP
case SYS_HOTSWAP_INSERTED:
case SYS_HOTSWAP_EXTRACTED:
fat_lock(); /* lock-out FAT activity first -
prevent deadlocking via disk_mount that
would cause a reverse-order attempt with
another thread */
mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
into driver that bypass the fat cache */
/* We now have exclusive control of fat cache and ata */
disk_unmount(sd_drive_nr); /* release "by force", ensure file
descriptors aren't leaked and any busy
ones are invalid if mounting */
/* Force card init for new card, re-init for re-inserted one or
* clear if the last attempt to init failed with an error. */
card.initialized = 0;
if(ev.id == SYS_HOTSWAP_INSERTED)
disk_mount(sd_drive_nr);
queue_broadcast(SYS_FS_CHANGED, 0);
/* Access is now safe */
mutex_unlock(&sd_mtx);
fat_unlock();
break;
#endif
case SYS_TIMEOUT:
if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ)))
idle_notified = false;
else
{
if (!idle_notified)
{
call_storage_idle_notifys(false);
idle_notified = true;
}
}
break;
case SYS_USB_CONNECTED:
usb_acknowledge(SYS_USB_CONNECTED_ACK);
/* Wait until the USB cable is extracted again */
usb_wait_for_disconnect(&sd_queue);
break;
case SYS_USB_DISCONNECTED:
usb_acknowledge(SYS_USB_DISCONNECTED_ACK);
break;
}
}
}

View file

@ -22,20 +22,19 @@
#ifndef ATA_SD_TARGET_H #ifndef ATA_SD_TARGET_H
#define ATA_SD_TARGET_H #define ATA_SD_TARGET_H
#include "inttypes.h"
#include "hotswap.h"
#include "jz4740.h" #include "jz4740.h"
#include "system.h"
int _sd_read_sectors(unsigned long start, int count, void* buf);
int _sd_write_sectors(unsigned long start, int count, const void* buf);
int _sd_init(void);
#define MMC_CD_PIN (32*1 + 29) /* Pin to check card insertion */ #define MMC_CD_PIN (32*1 + 29) /* Pin to check card insertion */
#define MMC_CD_IRQ GPIO61
static inline void mmc_init_gpio(void) static inline void sd_init_gpio(void)
{ {
__gpio_as_msc(); __gpio_as_msc();
__gpio_enable_pull(MMC_CD_PIN);
__gpio_as_input(MMC_CD_PIN); __gpio_as_input(MMC_CD_PIN);
__gpio_mask_irq(MMC_CD_PIN);
system_enable_irq(GPIO_IRQ(MMC_CD_PIN));
} }
#endif #endif

View file

@ -33,14 +33,14 @@
/* This one returns the old status */ /* This one returns the old status */
static inline int set_interrupt_status(int status, int mask) static inline int set_interrupt_status(int status, int mask)
{ {
unsigned int res, oldstatus; unsigned int res, oldstatus;
res = oldstatus = read_c0_status(); res = oldstatus = read_c0_status();
res &= ~mask; res &= ~mask;
res |= (status & mask); res |= (status & mask);
write_c0_status(res); write_c0_status(res);
return oldstatus; return oldstatus;
} }
static inline void enable_interrupt(void) static inline void enable_interrupt(void)
@ -72,8 +72,8 @@ static inline void restore_interrupt(int status)
#define disable_irq_save() disable_interrupt_save(ST0_IE) #define disable_irq_save() disable_interrupt_save(ST0_IE)
#define restore_irq(c0_status) restore_interrupt(c0_status) #define restore_irq(c0_status) restore_interrupt(c0_status)
#define swap16(x) (((x) & 0xff) << 8 | ((x) >> 8) & 0xff) #define swap16(x) (((x) & 0xff) << 8 | ((x) >> 8) & 0xff)
#define swap32(x) (((x) & 0xff) << 24 | ((x) & 0xff00) << 8 | \ #define swap32(x) (((x) & 0xff) << 24 | ((x) & 0xff00) << 8 | \
((x) & 0xff0000) >> 8 | ((x) >> 24) & 0xff) ((x) & 0xff0000) >> 8 | ((x) >> 24) & 0xff)
#define UNCACHED_ADDRESS(addr) ((unsigned int)(addr) | 0xA0000000) #define UNCACHED_ADDRESS(addr) ((unsigned int)(addr) | 0xA0000000)
@ -94,6 +94,7 @@ void dma_disable(void);
#define XDMA_CALLBACK(n) DMA ## n #define XDMA_CALLBACK(n) DMA ## n
#define DMA_CALLBACK(n) XDMA_CALLBACK(n) #define DMA_CALLBACK(n) XDMA_CALLBACK(n)
#define DMA_IRQ(n) (IRQ_DMA_0 + n) #define DMA_IRQ(n) (IRQ_DMA_0 + (n))
#define GPIO_IRQ(n) (IRQ_GPIO_0 + (n))
#endif /* __SYSTEM_TARGET_H_ */ #endif /* __SYSTEM_TARGET_H_ */