mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 05:05:20 -05:00
Merge branch 'hotswap'
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23759 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
b2dc7f004e
commit
d052ced874
7 changed files with 282 additions and 125 deletions
|
|
@ -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++;
|
||||||
|
|
|
||||||
|
|
@ -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++;
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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_ */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue