1
0
Fork 0
forked from len0rd/rockbox

Implemented multiple block reading and writing. Significant speedup.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@5153 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jens Arnold 2004-10-03 23:32:09 +00:00
parent 4f8d3482c6
commit dc6caf9ce8

View file

@ -42,16 +42,14 @@
#define CMD_GO_IDLE_STATE 0x40 /* R1 */ #define CMD_GO_IDLE_STATE 0x40 /* R1 */
#define CMD_SEND_OP_COND 0x41 /* R1 */ #define CMD_SEND_OP_COND 0x41 /* R1 */
#define CMD_SEND_CSD 0x49 /* R1 */ #define CMD_SEND_CSD 0x49 /* R1 */
#define CMD_SEND_CID 0x4A /* R1 */ #define CMD_SEND_CID 0x4a /* R1 */
#define CMD_STOP_TRANSMISSION 0x4C /* R1 */ #define CMD_STOP_TRANSMISSION 0x4c /* R1 */
#define CMD_SEND_STATUS 0x4D /* R2 */ #define CMD_SEND_STATUS 0x4d /* R2 */
#define CMD_SET_BLOCKLEN 0x50 /* R1 */
#define CMD_READ_SINGLE_BLOCK 0x51 /* R1 */ #define CMD_READ_SINGLE_BLOCK 0x51 /* R1 */
#define CMD_READ_MULTIPLE_BLOCK 0x52 /* R1 */ #define CMD_READ_MULTIPLE_BLOCK 0x52 /* R1 */
#define CMD_SET_BLOCK_COUNT 0x57 /* R1 */
#define CMD_WRITE_BLOCK 0x58 /* R1b */ #define CMD_WRITE_BLOCK 0x58 /* R1b */
#define CMD_WRITE_MULTIPLE_BLOCK 0x59 /* R1b */ #define CMD_WRITE_MULTIPLE_BLOCK 0x59 /* R1b */
#define CMD_READ_OCR 0x7A /* R3 */ #define CMD_READ_OCR 0x7a /* R3 */
/* Response formats: /* Response formats:
R1 = single byte, msb=0, various error flags R1 = single byte, msb=0, various error flags
@ -77,6 +75,12 @@
#define R2_ERASE_SKIP 0x02 #define R2_ERASE_SKIP 0x02
#define R2_CARD_LOCKED 0x01 #define R2_CARD_LOCKED 0x01
/* Data start tokens */
#define DT_START_BLOCK 0xfe
#define DT_START_WRITE_MULTIPLE 0xfc
#define DT_STOP_TRAN 0xfd
// DEBUG // DEBUG
#include "../../apps/screens.h" #include "../../apps/screens.h"
@ -89,7 +93,7 @@ long last_disk_activity = -1;
/* private variables */ /* private variables */
static struct mutex ata_mtx; static struct mutex mmc_mutex;
static char mmc_stack[DEFAULT_STACK_SIZE]; static char mmc_stack[DEFAULT_STACK_SIZE];
static const char mmc_thread_name[] = "mmc"; static const char mmc_thread_name[] = "mmc";
@ -129,8 +133,11 @@ static void write_transfer(const unsigned char *buf, int len)
static void read_transfer(unsigned char *buf, int len) static void read_transfer(unsigned char *buf, int len)
__attribute__ ((section(".icode"))); __attribute__ ((section(".icode")));
static unsigned char poll_byte(int timeout); static unsigned char poll_byte(int timeout);
static unsigned char poll_busy(int timeout);
static int send_cmd(int cmd, unsigned long parameter, unsigned char *response); static int send_cmd(int cmd, unsigned long parameter, unsigned char *response);
static int receive_data(unsigned char *buf, int len, int timeout); static int receive_data(unsigned char *buf, int len, int timeout);
static int send_data(char start_token, const unsigned char *buf, int len,
int timeout);
static int initialize_card(int card_no); static int initialize_card(int card_no);
/* implementation */ /* implementation */
@ -264,7 +271,7 @@ static unsigned char poll_busy(int timeout)
static int send_cmd(int cmd, unsigned long parameter, unsigned char *response) static int send_cmd(int cmd, unsigned long parameter, unsigned char *response)
{ {
unsigned char command[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95 }; unsigned char command[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 0xFF};
command[0] = cmd; command[0] = cmd;
@ -276,7 +283,7 @@ static int send_cmd(int cmd, unsigned long parameter, unsigned char *response)
command[4] = parameter & 0xFF; command[4] = parameter & 0xFF;
} }
write_transfer(command, 6); write_transfer(command, 7);
response[0] = poll_byte(20); response[0] = poll_byte(20);
@ -291,7 +298,7 @@ static int send_cmd(int cmd, unsigned long parameter, unsigned char *response)
case CMD_SEND_CSD: /* R1 response, leave open */ case CMD_SEND_CSD: /* R1 response, leave open */
case CMD_SEND_CID: case CMD_SEND_CID:
case CMD_READ_SINGLE_BLOCK: case CMD_READ_SINGLE_BLOCK:
// case READ_MULTIPLE_BLOCK: case CMD_READ_MULTIPLE_BLOCK:
break; break;
case CMD_SEND_STATUS: /* R2 response, close with dummy */ case CMD_SEND_STATUS: /* R2 response, close with dummy */
@ -316,7 +323,7 @@ static int receive_data(unsigned char *buf, int len, int timeout)
{ {
unsigned char crc[2]; /* unused */ unsigned char crc[2]; /* unused */
if (poll_byte(timeout) != 0xFE) if (poll_byte(timeout) != DT_START_BLOCK)
{ {
write_transfer(dummy, 1); write_transfer(dummy, 1);
return -1; /* not start of data */ return -1; /* not start of data */
@ -329,12 +336,12 @@ static int receive_data(unsigned char *buf, int len, int timeout)
return 0; return 0;
} }
static int send_data(const unsigned char *buf, int len, int timeout) static int send_data(char start_token, const unsigned char *buf, int len,
int timeout)
{ {
static const unsigned char start_data = 0xFE;
int ret = 0; int ret = 0;
write_transfer(&start_data, 1); write_transfer(&start_token, 1);
write_transfer(buf, len); write_transfer(buf, len);
write_transfer(dummy, 2); /* crc - dontcare */ write_transfer(dummy, 2); /* crc - dontcare */
@ -441,6 +448,7 @@ static int initialize_card(int card_no)
return 0; return 0;
} }
#if 0 /* old implementation */
int ata_read_sectors(unsigned long start, int ata_read_sectors(unsigned long start,
int incount, int incount,
void* inbuf) void* inbuf)
@ -453,7 +461,7 @@ int ata_read_sectors(unsigned long start,
addr = start * SECTOR_SIZE; addr = start * SECTOR_SIZE;
mutex_lock(&ata_mtx); mutex_lock(&mmc_mutex);
ret = select_card(current_card); ret = select_card(current_card);
for (i = 0; (i < incount) && (ret == 0); i++) for (i = 0; (i < incount) && (ret == 0); i++)
@ -467,11 +475,56 @@ int ata_read_sectors(unsigned long start,
} }
deselect_card(); deselect_card();
mutex_unlock(&ata_mtx); mutex_unlock(&mmc_mutex);
return ret; return ret;
} }
#endif
int ata_read_sectors(unsigned long start,
int incount,
void* inbuf)
{
int ret = 0;
int i;
unsigned long addr;
unsigned char response;
tCardInfo *card = &card_info[current_card];
if (incount <= 0)
return ret;
addr = start * SECTOR_SIZE;
mutex_lock(&mmc_mutex);
ret = select_card(current_card);
if (ret == 0)
{
if (incount == 1)
{
ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response);
if (ret == 0)
ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout);
}
else
{
ret = send_cmd(CMD_READ_MULTIPLE_BLOCK, addr, &response);
for (i = 0; (i < incount) && (ret == 0); i++)
{
ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout);
inbuf += SECTOR_SIZE;
}
if (ret == 0)
ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response);
}
}
deselect_card();
mutex_unlock(&mmc_mutex);
return ret;
}
int ata_write_sectors(unsigned long start, int ata_write_sectors(unsigned long start,
int count, int count,
@ -486,24 +539,44 @@ int ata_write_sectors(unsigned long start,
if (start == 0) if (start == 0)
panicf("Writing on sector 0\n"); panicf("Writing on sector 0\n");
addr = start * SECTOR_SIZE; if (count <= 0)
return ret;
mutex_lock(&ata_mtx); addr = start * SECTOR_SIZE;
mutex_lock(&mmc_mutex);
ret = select_card(current_card); ret = select_card(current_card);
for (i = 0; (i < count) && (ret == 0); i++) if (ret == 0)
{ {
if ((ret = send_cmd(CMD_WRITE_BLOCK, addr, &response))) if (count == 1)
break; {
ret = send_data(buf, SECTOR_SIZE, card->write_timeout); ret = send_cmd(CMD_WRITE_BLOCK, addr, &response);
if (ret == 0)
addr += SECTOR_SIZE; ret = send_data(DT_START_BLOCK, buf, SECTOR_SIZE,
buf += SECTOR_SIZE; card->write_timeout);
}
else
{
ret = send_cmd(CMD_WRITE_MULTIPLE_BLOCK, addr, &response);
for (i = 0; (i < count) && (ret == 0); i++)
{
ret = send_data(DT_START_WRITE_MULTIPLE, buf, SECTOR_SIZE,
card->write_timeout);
buf += SECTOR_SIZE;
}
if (ret == 0)
{
response = DT_STOP_TRAN;
write_transfer(&response, 1);
poll_busy(card->write_timeout);
}
}
} }
deselect_card(); deselect_card();
mutex_unlock(&ata_mtx); mutex_unlock(&mmc_mutex);
return ret; return ret;
} }
@ -523,8 +596,9 @@ void ata_spindown(int seconds)
} }
bool ata_disk_is_active(void) bool ata_disk_is_active(void)
{ {
return false; /* FIXME: dirty, but makes idle poweroff work */ /* this is correct unless early return from write gets implemented */
return mmc_mutex.locked;
} }
int ata_standby(int time) int ata_standby(int time)
@ -596,7 +670,7 @@ int ata_init(void)
{ {
int rc = 0; int rc = 0;
mutex_init(&ata_mtx); mutex_init(&mmc_mutex);
led(false); led(false);