Revision 10a412da hw/sd.c
b/hw/sd.c | ||
---|---|---|
104 | 104 |
int enable; |
105 | 105 |
}; |
106 | 106 |
|
107 |
static void sd_set_status(SDState *sd)
|
|
107 |
static void sd_set_mode(SDState *sd)
|
|
108 | 108 |
{ |
109 | 109 |
switch (sd->state) { |
110 | 110 |
case sd_inactive_state: |
... | ... | |
126 | 126 |
sd->mode = sd_data_transfer_mode; |
127 | 127 |
break; |
128 | 128 |
} |
129 |
|
|
130 |
sd->card_status &= ~CURRENT_STATE; |
|
131 |
sd->card_status |= sd->state << 9; |
|
132 | 129 |
} |
133 | 130 |
|
134 | 131 |
static const sd_cmd_type_t sd_cmd_type[64] = { |
... | ... | |
341 | 338 |
return sd_crc7(buffer, 5) != req->crc; /* TODO */ |
342 | 339 |
} |
343 | 340 |
|
344 |
static void sd_response_r1_make(SDState *sd, |
|
345 |
uint8_t *response, uint32_t last_status) |
|
341 |
static void sd_response_r1_make(SDState *sd, uint8_t *response) |
|
346 | 342 |
{ |
347 |
uint32_t mask = CARD_STATUS_B ^ ILLEGAL_COMMAND; |
|
348 |
uint32_t status; |
|
349 |
|
|
350 |
status = (sd->card_status & ~mask) | (last_status & mask); |
|
343 |
uint32_t status = sd->card_status; |
|
344 |
/* Clear the "clear on read" status bits (except APP_CMD) */ |
|
351 | 345 |
sd->card_status &= ~CARD_STATUS_C | APP_CMD; |
352 | 346 |
|
353 | 347 |
response[0] = (status >> 24) & 0xff; |
... | ... | |
1286 | 1280 |
|
1287 | 1281 |
int sd_do_command(SDState *sd, SDRequest *req, |
1288 | 1282 |
uint8_t *response) { |
1289 |
uint32_t last_status = sd->card_status;
|
|
1283 |
int last_state;
|
|
1290 | 1284 |
sd_rsp_type_t rtype; |
1291 | 1285 |
int rsplen; |
1292 | 1286 |
|
... | ... | |
1300 | 1294 |
goto send_response; |
1301 | 1295 |
} |
1302 | 1296 |
|
1303 |
sd->card_status &= ~CARD_STATUS_B; |
|
1304 |
sd_set_status(sd); |
|
1305 |
|
|
1306 |
if (last_status & CARD_IS_LOCKED) { |
|
1297 |
if (sd->card_status & CARD_IS_LOCKED) { |
|
1307 | 1298 |
if (!cmd_valid_while_locked(sd, req)) { |
1308 | 1299 |
sd->card_status |= ILLEGAL_COMMAND; |
1309 | 1300 |
fprintf(stderr, "SD: Card is locked\n"); |
... | ... | |
1312 | 1303 |
} |
1313 | 1304 |
} |
1314 | 1305 |
|
1315 |
if (last_status & APP_CMD) { |
|
1306 |
last_state = sd->state; |
|
1307 |
sd_set_mode(sd); |
|
1308 |
|
|
1309 |
if (sd->card_status & APP_CMD) { |
|
1316 | 1310 |
rtype = sd_app_command(sd, *req); |
1317 | 1311 |
sd->card_status &= ~APP_CMD; |
1318 | 1312 |
} else |
... | ... | |
1320 | 1314 |
|
1321 | 1315 |
if (rtype == sd_illegal) { |
1322 | 1316 |
sd->card_status |= ILLEGAL_COMMAND; |
1317 |
} else { |
|
1318 |
/* Valid command, we can update the 'state before command' bits. |
|
1319 |
* (Do this now so they appear in r1 responses.) |
|
1320 |
*/ |
|
1321 |
sd->current_cmd = req->cmd; |
|
1322 |
sd->card_status &= ~CURRENT_STATE; |
|
1323 |
sd->card_status |= (last_state << 9); |
|
1323 | 1324 |
} |
1324 | 1325 |
|
1325 |
sd->current_cmd = req->cmd; |
|
1326 |
|
|
1327 | 1326 |
send_response: |
1328 | 1327 |
switch (rtype) { |
1329 | 1328 |
case sd_r1: |
1330 | 1329 |
case sd_r1b: |
1331 |
sd_response_r1_make(sd, response, last_status);
|
|
1330 |
sd_response_r1_make(sd, response); |
|
1332 | 1331 |
rsplen = 4; |
1333 | 1332 |
break; |
1334 | 1333 |
|
... | ... | |
1364 | 1363 |
break; |
1365 | 1364 |
} |
1366 | 1365 |
|
1366 |
if (rtype != sd_illegal) { |
|
1367 |
/* Clear the "clear on valid command" status bits now we've |
|
1368 |
* sent any response |
|
1369 |
*/ |
|
1370 |
sd->card_status &= ~CARD_STATUS_B; |
|
1371 |
} |
|
1372 |
|
|
1367 | 1373 |
#ifdef DEBUG_SD |
1368 | 1374 |
if (rsplen) { |
1369 | 1375 |
int i; |
Also available in: Unified diff