1
0
Fork 0
forked from len0rd/rockbox

Change the way send_cmd() returns data to make it cleaner and save binsize. Also change the command composition for the same reasons.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18551 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jens Arnold 2008-09-19 07:27:08 +00:00
parent eab5498484
commit 5b17f37e84

View file

@ -145,7 +145,7 @@ static void read_transfer(unsigned char *buf, int len)
__attribute__ ((section(".icode"))); __attribute__ ((section(".icode")));
static unsigned char poll_byte(long timeout); static unsigned char poll_byte(long timeout);
static unsigned char poll_busy(long timeout); static unsigned char poll_busy(long timeout);
static int send_cmd(int cmd, unsigned long parameter, unsigned char *response); static unsigned char send_cmd(int cmd, unsigned long parameter, void *data);
static int receive_cxd(unsigned char *buf); static int receive_cxd(unsigned char *buf);
static int initialize_card(int card_no); static int initialize_card(int card_no);
static int receive_block(unsigned char *inbuf, long timeout); static int receive_block(unsigned char *inbuf, long timeout);
@ -318,30 +318,25 @@ static unsigned char poll_busy(long timeout)
return (dummy == 0xFF) ? data : 0; return (dummy == 0xFF) ? data : 0;
} }
/* Send MMC command and get response */ /* Send MMC command and get response. Returns R1 byte directly.
static int send_cmd(int cmd, unsigned long parameter, unsigned char *response) * Returns further R2 or R3 bytes in *data (can be NULL for other commands) */
static unsigned char send_cmd(int cmd, unsigned long parameter, void *data)
{ {
unsigned char command[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 0xFF}; static struct {
unsigned char cmd;
unsigned long parameter;
const unsigned char crc7; /* fixed, valid for CMD0 only */
const unsigned char trailer;
} __attribute__((packed)) command = {0x40, 0, 0x95, 0xFF};
command[0] = cmd; unsigned char ret;
if (parameter != 0) command.cmd = cmd;
{ command.parameter = htobe32(parameter);
command[1] = (parameter >> 24) & 0xFF;
command[2] = (parameter >> 16) & 0xFF;
command[3] = (parameter >> 8) & 0xFF;
command[4] = parameter & 0xFF;
}
write_transfer(command, 7); write_transfer((unsigned char *)&command, sizeof(command));
response[0] = poll_byte(20); ret = poll_byte(20);
if (response[0] != 0x00)
{
write_transfer(dummy, 1);
return -1;
}
switch (cmd) switch (cmd)
{ {
@ -349,24 +344,21 @@ static int send_cmd(int cmd, unsigned long parameter, unsigned char *response)
case CMD_SEND_CID: case CMD_SEND_CID:
case CMD_READ_SINGLE_BLOCK: case CMD_READ_SINGLE_BLOCK:
case CMD_READ_MULTIPLE_BLOCK: case CMD_READ_MULTIPLE_BLOCK:
break; return ret;
case CMD_SEND_STATUS: /* R2 response, close with dummy */ case CMD_SEND_STATUS: /* R2 response, close with dummy */
read_transfer(response + 1, 1); read_transfer(data, 1);
write_transfer(dummy, 1);
break; break;
case CMD_READ_OCR: /* R3 response, close with dummy */ case CMD_READ_OCR: /* R3 response, close with dummy */
read_transfer(response + 1, 4); read_transfer(data, 4);
write_transfer(dummy, 1);
break; break;
default: /* R1 response, close with dummy */ default: /* R1 response, close with dummy */
write_transfer(dummy, 1);
break; /* also catches block writes */ break; /* also catches block writes */
} }
write_transfer(dummy, 1);
return 0; return ret;
} }
/* Receive CID/ CSD data (16 bytes) */ /* Receive CID/ CSD data (16 bytes) */
@ -388,7 +380,6 @@ static int initialize_card(int card_no)
{ {
int rc, i; int rc, i;
int blk_exp, ts_exp, taac_exp; int blk_exp, ts_exp, taac_exp;
unsigned char response[5];
tCardInfo *card = &card_info[card_no]; tCardInfo *card = &card_info[card_no];
static const char mantissa[] = { /* *10 */ static const char mantissa[] = { /* *10 */
@ -402,43 +393,40 @@ static int initialize_card(int card_no)
if (card_no == 1) if (card_no == 1)
mmc_status = MMC_TOUCHED; mmc_status = MMC_TOUCHED;
/* switch to SPI mode */ /* switch to SPI mode */
send_cmd(CMD_GO_IDLE_STATE, 0, response); if (send_cmd(CMD_GO_IDLE_STATE, 0, NULL) != 0x01)
if (response[0] != 0x01) return -1; /* error or no response */
return -1; /* error response */
/* initialize card */ /* initialize card */
for (i = 0; i < HZ; i++) /* timeout 1 sec */ for (i = HZ;;) /* try for 1 second*/
{ {
sleep(1); sleep(1);
if (send_cmd(CMD_SEND_OP_COND, 0, response) == 0) if (send_cmd(CMD_SEND_OP_COND, 0, NULL) == 0)
break; break;
if (--i <= 0)
return -2; /* timeout */
} }
if (response[0] != 0x00)
return -2; /* not ready */
/* get OCR register */ /* get OCR register */
rc = send_cmd(CMD_READ_OCR, 0, response); if (send_cmd(CMD_READ_OCR, 0, &card->ocr))
if (rc) return -3;
return rc * 10 - 3; card->ocr = betoh32(card->ocr); /* no-op on big endian */
card->ocr = (response[1] << 24) | (response[2] << 16)
| (response[3] << 8) | response[4];
/* check voltage */ /* check voltage */
if (!(card->ocr & 0x00100000)) /* 3.2 .. 3.3 V */ if (!(card->ocr & 0x00100000)) /* 3.2 .. 3.3 V */
return -4; return -4;
/* get CSD register */ /* get CSD register */
rc = send_cmd(CMD_SEND_CSD, 0, response); if (send_cmd(CMD_SEND_CSD, 0, NULL))
if (rc) return -5;
return rc * 10 - 5;
rc = receive_cxd((unsigned char*)card->csd); rc = receive_cxd((unsigned char*)card->csd);
if (rc) if (rc)
return rc * 10 - 6; return rc * 10 - 5;
blk_exp = card_extract_bits(card->csd, 44, 4); blk_exp = card_extract_bits(card->csd, 44, 4);
if (blk_exp < 9) /* block size < 512 bytes not supported */ if (blk_exp < 9) /* block size < 512 bytes not supported */
return -7; return -6;
card->numblocks = (card_extract_bits(card->csd, 54, 12) + 1) card->numblocks = (card_extract_bits(card->csd, 54, 12) + 1)
<< (card_extract_bits(card->csd, 78, 3) + 2 + blk_exp - 9); << (card_extract_bits(card->csd, 78, 3) + 2 + blk_exp - 9);
@ -472,17 +460,15 @@ static int initialize_card(int card_no)
setup_sci1(card->bitrate_register); setup_sci1(card->bitrate_register);
/* always use 512 byte blocks */ /* always use 512 byte blocks */
rc = send_cmd(CMD_SET_BLOCKLEN, BLOCK_SIZE, response); if (send_cmd(CMD_SET_BLOCKLEN, BLOCK_SIZE, NULL))
if (rc) return -7;
return rc * 10 - 8;
/* get CID register */ /* get CID register */
rc = send_cmd(CMD_SEND_CID, 0, response); if (send_cmd(CMD_SEND_CID, 0, NULL))
if (rc) return -8;
return rc * 10 - 9;
rc = receive_cxd((unsigned char*)card->cid); rc = receive_cxd((unsigned char*)card->cid);
if (rc) if (rc)
return rc * 10 - 9; return rc * 10 - 8;
card->initialized = true; card->initialized = true;
return 0; return 0;
@ -623,7 +609,6 @@ int ata_read_sectors(IF_MV2(int drive,)
int rc = 0; int rc = 0;
int lastblock = 0; int lastblock = 0;
unsigned long end_block; unsigned long end_block;
unsigned char response;
tCardInfo *card; tCardInfo *card;
#ifndef HAVE_MULTIVOLUME #ifndef HAVE_MULTIVOLUME
int drive = current_card; int drive = current_card;
@ -652,11 +637,10 @@ int ata_read_sectors(IF_MV2(int drive,)
if (incount > 1) if (incount > 1)
{ {
rc = send_cmd(CMD_READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, &response);
/* MMC4.2: make multiplication conditional */ /* MMC4.2: make multiplication conditional */
if (rc) if (send_cmd(CMD_READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, NULL))
{ {
rc = rc * 10 - 3; rc = -3;
goto error; goto error;
} }
while (incount-- > lastblock) while (incount-- > lastblock)
@ -666,7 +650,7 @@ int ata_read_sectors(IF_MV2(int drive,)
{ {
/* If an error occurs during multiple block reading, the /* If an error occurs during multiple block reading, the
* host still needs to send CMD_STOP_TRANSMISSION */ * host still needs to send CMD_STOP_TRANSMISSION */
send_cmd(CMD_STOP_TRANSMISSION, 0, &response); send_cmd(CMD_STOP_TRANSMISSION, 0, NULL);
rc = rc * 10 - 4; rc = rc * 10 - 4;
goto error; goto error;
} }
@ -674,20 +658,18 @@ int ata_read_sectors(IF_MV2(int drive,)
start++; start++;
/* ^^ necessary for the abovementioned last block special case */ /* ^^ necessary for the abovementioned last block special case */
} }
rc = send_cmd(CMD_STOP_TRANSMISSION, 0, &response); if (send_cmd(CMD_STOP_TRANSMISSION, 0, NULL))
if (rc)
{ {
rc = rc * 10 - 5; rc = -5;
goto error; goto error;
} }
} }
if (incount > 0) if (incount > 0)
{ {
rc = send_cmd(CMD_READ_SINGLE_BLOCK, start * BLOCK_SIZE, &response);
/* MMC4.2: make multiplication conditional */ /* MMC4.2: make multiplication conditional */
if (rc) if (send_cmd(CMD_READ_SINGLE_BLOCK, start * BLOCK_SIZE, NULL))
{ {
rc = rc * 10 - 6; rc = -6;
goto error; goto error;
} }
rc = receive_block(inbuf, card->read_timeout); rc = receive_block(inbuf, card->read_timeout);
@ -713,7 +695,6 @@ int ata_write_sectors(IF_MV2(int drive,)
int rc = 0; int rc = 0;
int write_cmd; int write_cmd;
unsigned char start_token; unsigned char start_token;
unsigned char response;
tCardInfo *card; tCardInfo *card;
#ifndef HAVE_MULTIVOLUME #ifndef HAVE_MULTIVOLUME
int drive = current_card; int drive = current_card;
@ -743,11 +724,10 @@ int ata_write_sectors(IF_MV2(int drive,)
write_cmd = CMD_WRITE_BLOCK; write_cmd = CMD_WRITE_BLOCK;
start_token = DT_START_BLOCK; start_token = DT_START_BLOCK;
} }
rc = send_cmd(write_cmd, start * BLOCK_SIZE, &response);
/* MMC4.2: make multiplication conditional */ /* MMC4.2: make multiplication conditional */
if (rc) if (send_cmd(write_cmd, start * BLOCK_SIZE, NULL))
{ {
rc = rc * 10 - 2; rc = -2;
goto error; goto error;
} }
@ -771,8 +751,8 @@ int ata_write_sectors(IF_MV2(int drive,)
if (write_cmd == CMD_WRITE_MULTIPLE_BLOCK) if (write_cmd == CMD_WRITE_MULTIPLE_BLOCK)
{ {
response = DT_STOP_TRAN; static const unsigned char stop_tran = DT_STOP_TRAN;
write_transfer(&response, 1); write_transfer(&stop_tran, 1);
poll_busy(card->write_timeout); poll_busy(card->write_timeout);
} }
@ -863,13 +843,10 @@ bool mmc_touched(void)
{ {
if (mmc_status == MMC_UNKNOWN) /* try to detect */ if (mmc_status == MMC_UNKNOWN) /* try to detect */
{ {
unsigned char response;
mutex_lock(&mmc_mutex); mutex_lock(&mmc_mutex);
setup_sci1(7); /* safe value */ setup_sci1(7); /* safe value */
and_b(~0x02, &PADRH); /* assert CS */ and_b(~0x02, &PADRH); /* assert CS */
send_cmd(CMD_SEND_OP_COND, 0, &response); if (send_cmd(CMD_SEND_OP_COND, 0, NULL) == 0xFF)
if (response == 0xFF)
mmc_status = MMC_UNTOUCHED; mmc_status = MMC_UNTOUCHED;
else else
mmc_status = MMC_TOUCHED; mmc_status = MMC_TOUCHED;