diff options
-rw-r--r-- | apps/debug_menu.c | 132 | ||||
-rw-r--r-- | firmware/drivers/ata_mmc.c | 194 | ||||
-rw-r--r-- | firmware/export/ata_mmc.h | 42 |
3 files changed, 279 insertions, 89 deletions
diff --git a/apps/debug_menu.c b/apps/debug_menu.c index cb6ad07c4a..663ea7bdf4 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c | |||
@@ -54,6 +54,9 @@ | |||
54 | #ifdef CONFIG_TUNER | 54 | #ifdef CONFIG_TUNER |
55 | #include "radio.h" | 55 | #include "radio.h" |
56 | #endif | 56 | #endif |
57 | #ifdef HAVE_MMC | ||
58 | #include "ata_mmc.h" | ||
59 | #endif | ||
57 | 60 | ||
58 | /*---------------------------------------------------*/ | 61 | /*---------------------------------------------------*/ |
59 | /* SPECIAL DEBUG STUFF */ | 62 | /* SPECIAL DEBUG STUFF */ |
@@ -1260,9 +1263,134 @@ static bool view_runtime(void) | |||
1260 | } | 1263 | } |
1261 | 1264 | ||
1262 | #ifdef HAVE_MMC | 1265 | #ifdef HAVE_MMC |
1263 | static bool dbg_mmc_info(void) | 1266 | /* value is 10 * real value */ |
1267 | static unsigned char prep_value_unit(unsigned int *value, | ||
1268 | const unsigned char *units) | ||
1269 | { | ||
1270 | int unit_no = 0; | ||
1271 | |||
1272 | while (*value >= 10000) | ||
1273 | { | ||
1274 | *value /= 1000; | ||
1275 | unit_no++; | ||
1276 | } | ||
1277 | return units[unit_no]; | ||
1278 | } | ||
1279 | |||
1280 | bool dbg_mmc_info(void) | ||
1264 | { | 1281 | { |
1265 | splash(HZ, true, "To be implemented."); | 1282 | bool done = false; |
1283 | int currval = 0; | ||
1284 | unsigned int value; | ||
1285 | tCardInfo *card; | ||
1286 | unsigned char pbuf[32]; | ||
1287 | unsigned char card_name[7]; | ||
1288 | unsigned char unit; | ||
1289 | |||
1290 | static const unsigned char i_vmin[] = { 0, 1, 5, 10, 25, 35, 60, 100 }; | ||
1291 | static const unsigned char i_vmax[] = { 1, 5, 10, 25, 35, 45, 80, 200 }; | ||
1292 | |||
1293 | card_name[6] = '\0'; | ||
1294 | |||
1295 | lcd_setmargins(0, 0); | ||
1296 | lcd_setfont(FONT_SYSFIXED); | ||
1297 | |||
1298 | while (!done) | ||
1299 | { | ||
1300 | card = mmc_card_info(currval / 2); | ||
1301 | |||
1302 | lcd_clear_display(); | ||
1303 | snprintf(pbuf, sizeof(pbuf), "[MMC%d p%d]", currval / 2, | ||
1304 | (currval % 2) + 1); | ||
1305 | lcd_puts(0, 0, pbuf); | ||
1306 | |||
1307 | if (card->initialized) | ||
1308 | { | ||
1309 | if (!(currval % 2)) /* General info */ | ||
1310 | { | ||
1311 | strncpy(card_name, ((unsigned char*)card->cid) + 3, 6); | ||
1312 | snprintf(pbuf, sizeof(pbuf), "%s Rev %d.%d", card_name, | ||
1313 | mmc_extract_bits(card->cid, 72, 4), | ||
1314 | mmc_extract_bits(card->cid, 76, 4)); | ||
1315 | lcd_puts(0, 1, pbuf); | ||
1316 | snprintf(pbuf, sizeof(pbuf), "Prod: %d/%d", | ||
1317 | mmc_extract_bits(card->cid, 112, 4), | ||
1318 | mmc_extract_bits(card->cid, 116, 4) + 1997); | ||
1319 | lcd_puts(0, 2, pbuf); | ||
1320 | snprintf(pbuf, sizeof(pbuf), "Ser#: 0x%08x", | ||
1321 | mmc_extract_bits(card->cid, 80, 32)); | ||
1322 | lcd_puts(0, 3, pbuf); | ||
1323 | snprintf(pbuf, sizeof(pbuf), "M=%02x, O=%04x", | ||
1324 | mmc_extract_bits(card->cid, 0, 8), | ||
1325 | mmc_extract_bits(card->cid, 8, 16)); | ||
1326 | lcd_puts(0, 4, pbuf); | ||
1327 | value = mmc_extract_bits(card->csd, 54, 12) | ||
1328 | * (SECTOR_SIZE << (mmc_extract_bits(card->csd, 78, 3)+2)); | ||
1329 | snprintf(pbuf, sizeof(pbuf), "Size: %d MB", | ||
1330 | value / (1024*1024)); | ||
1331 | lcd_puts(0, 5, pbuf); | ||
1332 | } | ||
1333 | else /* Technical details */ | ||
1334 | { | ||
1335 | value = card->speed / 100; | ||
1336 | unit = prep_value_unit(&value, "kMG"); | ||
1337 | if (value < 100) | ||
1338 | snprintf(pbuf, sizeof(pbuf), "Speed: %d.%01d %cBit/s", | ||
1339 | value / 10, value % 10, unit); | ||
1340 | else | ||
1341 | snprintf(pbuf, sizeof(pbuf), "Tsac: %d %cBit/s", | ||
1342 | value / 10, unit); | ||
1343 | lcd_puts(0, 1, pbuf); | ||
1344 | |||
1345 | value = card->tsac; | ||
1346 | unit = prep_value_unit(&value, "nµm"); | ||
1347 | if (value < 100) | ||
1348 | snprintf(pbuf, sizeof(pbuf), "Tsac: %d.%01d %cs", | ||
1349 | value / 10, value % 10, unit); | ||
1350 | else | ||
1351 | snprintf(pbuf, sizeof(pbuf), "Tsac: %d %cs", | ||
1352 | value / 10, unit); | ||
1353 | lcd_puts(0, 1, pbuf); | ||
1354 | |||
1355 | snprintf(pbuf, sizeof(pbuf), "Nsac: %d clk", card->nsac); | ||
1356 | lcd_puts(0, 2, pbuf); | ||
1357 | snprintf(pbuf, sizeof(pbuf), "R2W: *%d", card->r2w_factor); | ||
1358 | lcd_puts(0, 3, pbuf); | ||
1359 | snprintf(pbuf, sizeof(pbuf), "IRmax: %d..%d mA", | ||
1360 | i_vmin[mmc_extract_bits(card->csd, 66, 3)], | ||
1361 | i_vmax[mmc_extract_bits(card->csd, 69, 3)]); | ||
1362 | lcd_puts(0, 4, pbuf); | ||
1363 | snprintf(pbuf, sizeof(pbuf), "IWmax: %d..%d mA", | ||
1364 | i_vmin[mmc_extract_bits(card->csd, 72, 3)], | ||
1365 | i_vmax[mmc_extract_bits(card->csd, 75, 3)]); | ||
1366 | lcd_puts(0, 5, pbuf); | ||
1367 | } | ||
1368 | } | ||
1369 | else | ||
1370 | lcd_puts(0, 1, "Not found!"); | ||
1371 | |||
1372 | lcd_update(); | ||
1373 | |||
1374 | switch (button_get(true)) | ||
1375 | { | ||
1376 | case SETTINGS_OK: | ||
1377 | case SETTINGS_CANCEL: | ||
1378 | done = true; | ||
1379 | break; | ||
1380 | |||
1381 | case SETTINGS_DEC: | ||
1382 | currval--; | ||
1383 | if (currval < 0) | ||
1384 | currval = 3; | ||
1385 | break; | ||
1386 | |||
1387 | case SETTINGS_INC: | ||
1388 | currval++; | ||
1389 | if (currval > 3) | ||
1390 | currval = 0; | ||
1391 | break; | ||
1392 | } | ||
1393 | } | ||
1266 | 1394 | ||
1267 | return false; | 1395 | return false; |
1268 | } | 1396 | } |
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c index 7a187f092b..ea7c5f1737 100644 --- a/firmware/drivers/ata_mmc.c +++ b/firmware/drivers/ata_mmc.c | |||
@@ -18,6 +18,7 @@ | |||
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include <stdbool.h> | 19 | #include <stdbool.h> |
20 | #include "ata.h" | 20 | #include "ata.h" |
21 | #include "ata_mmc.h" | ||
21 | #include "kernel.h" | 22 | #include "kernel.h" |
22 | #include "thread.h" | 23 | #include "thread.h" |
23 | #include "led.h" | 24 | #include "led.h" |
@@ -106,22 +107,6 @@ static const unsigned char dummy[] = { | |||
106 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF | 107 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF |
107 | }; | 108 | }; |
108 | 109 | ||
109 | typedef struct | ||
110 | { | ||
111 | bool initialized; | ||
112 | unsigned char bitrate_register; | ||
113 | unsigned char rev; | ||
114 | unsigned char rev_fract; | ||
115 | unsigned int speed; /* bps */ | ||
116 | unsigned int read_timeout; /* n * 8 clock cycles */ | ||
117 | unsigned int write_timeout; /* n * 8 clock cycles */ | ||
118 | unsigned int size; /* in bytes */ | ||
119 | unsigned int manuf_month; | ||
120 | unsigned int manuf_year; | ||
121 | unsigned long serial_number; | ||
122 | unsigned char name[7]; | ||
123 | } tCardInfo; | ||
124 | |||
125 | static tCardInfo card_info[2]; | 110 | static tCardInfo card_info[2]; |
126 | 111 | ||
127 | /* private function declarations */ | 112 | /* private function declarations */ |
@@ -149,6 +134,8 @@ static int select_card(int card_no) | |||
149 | or_b(0x10, &PADRH); /* set clock gate PA12 CHECKME: mask? */ | 134 | or_b(0x10, &PADRH); /* set clock gate PA12 CHECKME: mask? */ |
150 | else /* external */ | 135 | else /* external */ |
151 | and_b(~0x10, &PADRH); /* clear clock gate PA12 CHECKME: mask?*/ | 136 | and_b(~0x10, &PADRH); /* clear clock gate PA12 CHECKME: mask?*/ |
137 | |||
138 | last_disk_activity = current_tick; | ||
152 | 139 | ||
153 | if (!card_info[card_no].initialized) | 140 | if (!card_info[card_no].initialized) |
154 | { | 141 | { |
@@ -177,6 +164,8 @@ static void deselect_card(void) | |||
177 | { | 164 | { |
178 | while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ | 165 | while (!(SSR1 & SCI_TEND)); /* wait for end of transfer */ |
179 | or_b(0x06, &PADRH); /* deassert CS (both cards) */ | 166 | or_b(0x06, &PADRH); /* deassert CS (both cards) */ |
167 | |||
168 | last_disk_activity = current_tick; | ||
180 | } | 169 | } |
181 | 170 | ||
182 | static void setup_sci1(int bitrate_register) | 171 | static void setup_sci1(int bitrate_register) |
@@ -235,8 +224,7 @@ static void read_transfer(unsigned char *buf, int len) | |||
235 | *buf = fliptable[(signed char)(RDR1)]; /* read & bitswap */ | 224 | *buf = fliptable[(signed char)(RDR1)]; /* read & bitswap */ |
236 | } | 225 | } |
237 | 226 | ||
238 | /* timeout is in bytes */ | 227 | static unsigned char poll_byte(int timeout) /* timeout is in bytes */ |
239 | static unsigned char poll_byte(int timeout) | ||
240 | { | 228 | { |
241 | int i; | 229 | int i; |
242 | unsigned char data = 0; /* stop the compiler complaining */ | 230 | unsigned char data = 0; /* stop the compiler complaining */ |
@@ -254,7 +242,7 @@ static unsigned char poll_byte(int timeout) | |||
254 | return fliptable[(signed char)data]; | 242 | return fliptable[(signed char)data]; |
255 | } | 243 | } |
256 | 244 | ||
257 | static unsigned char poll_busy(int timeout) | 245 | static unsigned char poll_busy(int timeout) /* timeout is in bytes */ |
258 | { | 246 | { |
259 | int i; | 247 | int i; |
260 | unsigned char data, dummy; | 248 | unsigned char data, dummy; |
@@ -362,101 +350,134 @@ static int send_data(char start_token, const unsigned char *buf, int len, | |||
362 | return ret; | 350 | return ret; |
363 | } | 351 | } |
364 | 352 | ||
353 | /* helper function to extract n (<=32) bits from an arbitrary position. | ||
354 | counting from MSB to LSB */ | ||
355 | unsigned long mmc_extract_bits( | ||
356 | const unsigned long *p, /* the start of the bitfield array */ | ||
357 | unsigned int start, /* bit no. to start reading */ | ||
358 | unsigned int size) /* how many bits to read */ | ||
359 | { | ||
360 | unsigned int bit_index; | ||
361 | unsigned int bits_to_use; | ||
362 | unsigned long mask; | ||
363 | unsigned long result; | ||
364 | |||
365 | if (size == 1) | ||
366 | { /* short cut */ | ||
367 | return ((p[start/32] >> (31 - (start % 32))) & 1); | ||
368 | } | ||
369 | |||
370 | result = 0; | ||
371 | while (size) | ||
372 | { | ||
373 | bit_index = start % 32; | ||
374 | bits_to_use = MIN(32 - bit_index, size); | ||
375 | mask = 0xFFFFFFFF >> (32 - bits_to_use); | ||
376 | |||
377 | result <<= bits_to_use; /* start last round */ | ||
378 | result |= (p[start/32] >> (32 - bits_to_use - bit_index)) & mask; | ||
379 | |||
380 | start += bits_to_use; | ||
381 | size -= bits_to_use; | ||
382 | } | ||
383 | |||
384 | return result; | ||
385 | } | ||
386 | |||
365 | static int initialize_card(int card_no) | 387 | static int initialize_card(int card_no) |
366 | { | 388 | { |
367 | int i, temp; | 389 | int i, temp; |
368 | unsigned char response; | 390 | unsigned char response[5]; |
369 | unsigned char cxd[16]; | ||
370 | tCardInfo *card = &card_info[card_no]; | 391 | tCardInfo *card = &card_info[card_no]; |
371 | 392 | ||
372 | static const char mantissa[] = { /* *10 */ | 393 | static const char mantissa[] = { /* *10 */ |
373 | 0, 10, 12, 13, 15, 20, 25, 30, | 394 | 0, 10, 12, 13, 15, 20, 25, 30, |
374 | 35, 40, 45, 50, 55, 60, 70, 80 | 395 | 35, 40, 45, 50, 55, 60, 70, 80 |
375 | }; | 396 | }; |
376 | static const int speed_exponent[] = { /* /10 */ | 397 | static const int exponent[] = { /* use varies */ |
377 | 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 | 398 | 1, 10, 100, 1000, 10000, 100000, 1000000, |
378 | }; | 399 | 10000000, 100000000, 1000000000 |
379 | |||
380 | static const int time_exponent[] = { /* reciprocal */ | ||
381 | 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100 | ||
382 | }; | 400 | }; |
383 | 401 | ||
384 | /* switch to SPI mode */ | 402 | /* switch to SPI mode */ |
385 | send_cmd(CMD_GO_IDLE_STATE, 0, &response); | 403 | send_cmd(CMD_GO_IDLE_STATE, 0, response); |
386 | if (response != 0x01) | 404 | if (response[0] != 0x01) |
387 | return -1; /* error response */ | 405 | return -1; /* error response */ |
388 | 406 | ||
389 | /* initialize card */ | 407 | /* initialize card */ |
390 | i = 0; | 408 | i = 0; |
391 | while (send_cmd(CMD_SEND_OP_COND, 0, &response) && (++i < 200)); | 409 | while (send_cmd(CMD_SEND_OP_COND, 0, response) && (++i < 200)); |
392 | if (response != 0x00) | 410 | if (response[0] != 0x00) |
393 | return -2; /* not ready */ | 411 | return -2; /* not ready */ |
394 | 412 | ||
395 | /* get CSD register */ | 413 | /* get OCR register */ |
396 | if (send_cmd(CMD_SEND_CSD, 0, &response)) | 414 | if (send_cmd(CMD_READ_OCR, 0, response)) |
397 | return -3; | 415 | return -3; |
398 | if (receive_data(cxd, 16, 50)) | 416 | card->ocr = (response[1] << 24) + (response[2] << 16) |
399 | return -4; | 417 | + (response[3] << 8) + response[4]; |
400 | 418 | ||
401 | /* check block size */ | 419 | /* check voltage */ |
402 | if (1 << (cxd[5] & 0x0F) != SECTOR_SIZE) | 420 | if (!(card->ocr & 0x00100000)) /* 3.2 .. 3.3 V */ |
421 | return -4; | ||
422 | |||
423 | /* get CSD register */ | ||
424 | if (send_cmd(CMD_SEND_CSD, 0, response)) | ||
403 | return -5; | 425 | return -5; |
426 | if (receive_data((unsigned char*)card->csd, 16, 20)) | ||
427 | return -6; | ||
404 | 428 | ||
405 | /* max transmission speed the card is capable of */ | 429 | /* check block size */ |
406 | card->speed = mantissa[(cxd[3] & 0x78) >> 3] | 430 | if ((1 << mmc_extract_bits(card->csd, 44, 4)) != SECTOR_SIZE) |
407 | * speed_exponent[(cxd[3] & 0x07)]; | 431 | return -7; |
408 | 432 | ||
409 | /* calculate the clock divider */ | 433 | /* max transmission speed, clock divider */ |
434 | temp = mmc_extract_bits(card->csd, 29, 3); | ||
435 | temp = (temp > 3) ? 3 : temp; | ||
436 | card->speed = mantissa[mmc_extract_bits(card->csd, 25, 4)] | ||
437 | * exponent[temp + 4]; | ||
410 | card->bitrate_register = (FREQ/4-1) / card->speed; | 438 | card->bitrate_register = (FREQ/4-1) / card->speed; |
411 | 439 | ||
412 | /* calculate read timeout in clock cycles from TSAC, NSAC and the actual | 440 | /* NSAC, TSAC, read timeout */ |
413 | * clock frequency */ | 441 | card->nsac = 100 * mmc_extract_bits(card->csd, 16, 8); |
414 | temp = (FREQ/4) / (card->bitrate_register + 1); /* actual frequency */ | 442 | card->tsac = mantissa[mmc_extract_bits(card->csd, 9, 4)]; |
415 | card->read_timeout = | 443 | temp = mmc_extract_bits(card->csd, 13, 3); |
416 | (temp * mantissa[(cxd[1] & 0x78) >> 3] + (1000 * cxd[2])) | 444 | card->read_timeout = ((FREQ/4) / (card->bitrate_register + 1) |
417 | / (time_exponent[cxd[1] & 0x07] * 8); | 445 | * card->tsac / exponent[9 - temp] |
418 | 446 | + (10 * card->nsac)); | |
419 | /* calculate write timeout */ | 447 | card->read_timeout /= 8; /* clocks -> bytes */ |
420 | temp = (cxd[12] & 0x1C) >> 2; | 448 | card->tsac *= exponent[temp]; |
421 | if (temp > 5) | 449 | |
422 | temp = 5; | 450 | /* r2w_factor, write timeout */ |
423 | card->write_timeout = card->read_timeout * (1 << temp); | 451 | temp = mmc_extract_bits(card->csd, 99, 3); |
424 | 452 | temp = (temp > 5) ? 5 : temp; | |
425 | /* calculate size */ | 453 | card->r2w_factor = 1 << temp; |
426 | card->size = ((unsigned int)(cxd[6] & 0x03) << 10) | 454 | card->write_timeout = card->read_timeout * card->r2w_factor; |
427 | + ((unsigned int)cxd[7] << 2) | ||
428 | + ((unsigned int)(cxd[8] & 0xC0) >> 6); | ||
429 | temp = ((cxd[9] & 0x03) << 1) + ((cxd[10] & 0x80) >> 7) + 2; | ||
430 | card->size *= (SECTOR_SIZE << temp); | ||
431 | 455 | ||
432 | /* switch to full speed */ | 456 | /* switch to full speed */ |
433 | setup_sci1(card->bitrate_register); | 457 | setup_sci1(card->bitrate_register); |
434 | 458 | ||
435 | /* get CID register */ | 459 | /* get CID register */ |
436 | if (send_cmd(CMD_SEND_CID, 0, &response)) | 460 | if (send_cmd(CMD_SEND_CID, 0, response)) |
437 | return -6; | 461 | return -8; |
438 | if (receive_data(cxd, 16, 50)) | 462 | if (receive_data((unsigned char*)card->cid, 16, 20)) |
439 | return -7; | 463 | return -9; |
440 | |||
441 | /* get data from CID */ | ||
442 | strncpy(card->name, &cxd[3], 6); | ||
443 | card->name[6] = '\0'; | ||
444 | |||
445 | card->rev = (cxd[9] & 0xF0) >> 4; | ||
446 | card->rev_fract = cxd[9] & 0x0F; | ||
447 | |||
448 | card->manuf_month = (cxd[14] & 0xF0) >> 4; | ||
449 | card->manuf_year = (cxd[14] & 0x0F) + 1997; | ||
450 | |||
451 | card->serial_number = ((unsigned long)cxd[10] << 24) | ||
452 | + ((unsigned long)cxd[11] << 16) | ||
453 | + ((unsigned long)cxd[12] << 8) | ||
454 | + (unsigned long)cxd[13]; | ||
455 | 464 | ||
456 | card->initialized = true; | 465 | card->initialized = true; |
457 | return 0; | 466 | return 0; |
458 | } | 467 | } |
459 | 468 | ||
469 | tCardInfo *mmc_card_info(int card_no) | ||
470 | { | ||
471 | tCardInfo *card = &card_info[card_no]; | ||
472 | |||
473 | if (!card->initialized) | ||
474 | { | ||
475 | select_card(card_no); | ||
476 | deselect_card(); | ||
477 | } | ||
478 | return card; | ||
479 | } | ||
480 | |||
460 | int ata_read_sectors(unsigned long start, | 481 | int ata_read_sectors(unsigned long start, |
461 | int incount, | 482 | int incount, |
462 | void* inbuf) | 483 | void* inbuf) |
@@ -467,9 +488,6 @@ int ata_read_sectors(unsigned long start, | |||
467 | unsigned char response; | 488 | unsigned char response; |
468 | tCardInfo *card = &card_info[current_card]; | 489 | tCardInfo *card = &card_info[current_card]; |
469 | 490 | ||
470 | if (incount <= 0) | ||
471 | return ret; | ||
472 | |||
473 | addr = start * SECTOR_SIZE; | 491 | addr = start * SECTOR_SIZE; |
474 | 492 | ||
475 | mutex_lock(&mmc_mutex); | 493 | mutex_lock(&mmc_mutex); |
@@ -482,6 +500,7 @@ int ata_read_sectors(unsigned long start, | |||
482 | ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response); | 500 | ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response); |
483 | if (ret == 0) | 501 | if (ret == 0) |
484 | ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout); | 502 | ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout); |
503 | last_disk_activity = current_tick; | ||
485 | } | 504 | } |
486 | else | 505 | else |
487 | { | 506 | { |
@@ -490,6 +509,7 @@ int ata_read_sectors(unsigned long start, | |||
490 | { | 509 | { |
491 | ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout); | 510 | ret = receive_data(inbuf, SECTOR_SIZE, card->read_timeout); |
492 | inbuf += SECTOR_SIZE; | 511 | inbuf += SECTOR_SIZE; |
512 | last_disk_activity = current_tick; | ||
493 | } | 513 | } |
494 | if (ret == 0) | 514 | if (ret == 0) |
495 | ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response); | 515 | ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response); |
@@ -519,9 +539,6 @@ int ata_write_sectors(unsigned long start, | |||
519 | if (start == 0) | 539 | if (start == 0) |
520 | panicf("Writing on sector 0\n"); | 540 | panicf("Writing on sector 0\n"); |
521 | 541 | ||
522 | if (count <= 0) | ||
523 | return ret; | ||
524 | |||
525 | addr = start * SECTOR_SIZE; | 542 | addr = start * SECTOR_SIZE; |
526 | 543 | ||
527 | mutex_lock(&mmc_mutex); | 544 | mutex_lock(&mmc_mutex); |
@@ -535,6 +552,7 @@ int ata_write_sectors(unsigned long start, | |||
535 | if (ret == 0) | 552 | if (ret == 0) |
536 | ret = send_data(DT_START_BLOCK, buf, SECTOR_SIZE, | 553 | ret = send_data(DT_START_BLOCK, buf, SECTOR_SIZE, |
537 | card->write_timeout); | 554 | card->write_timeout); |
555 | last_disk_activity = current_tick; | ||
538 | } | 556 | } |
539 | else | 557 | else |
540 | { | 558 | { |
@@ -544,12 +562,14 @@ int ata_write_sectors(unsigned long start, | |||
544 | ret = send_data(DT_START_WRITE_MULTIPLE, buf, SECTOR_SIZE, | 562 | ret = send_data(DT_START_WRITE_MULTIPLE, buf, SECTOR_SIZE, |
545 | card->write_timeout); | 563 | card->write_timeout); |
546 | buf += SECTOR_SIZE; | 564 | buf += SECTOR_SIZE; |
565 | last_disk_activity = current_tick; | ||
547 | } | 566 | } |
548 | if (ret == 0) | 567 | if (ret == 0) |
549 | { | 568 | { |
550 | response = DT_STOP_TRAN; | 569 | response = DT_STOP_TRAN; |
551 | write_transfer(&response, 1); | 570 | write_transfer(&response, 1); |
552 | poll_busy(card->write_timeout); | 571 | poll_busy(card->write_timeout); |
572 | last_disk_activity = current_tick; | ||
553 | } | 573 | } |
554 | } | 574 | } |
555 | } | 575 | } |
diff --git a/firmware/export/ata_mmc.h b/firmware/export/ata_mmc.h new file mode 100644 index 0000000000..afc0dc24af --- /dev/null +++ b/firmware/export/ata_mmc.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2004 by Jens Arnold | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #ifndef __ATA_MMC_H__ | ||
20 | #define __ATA_MMC_H__ | ||
21 | |||
22 | typedef struct | ||
23 | { | ||
24 | bool initialized; | ||
25 | unsigned char bitrate_register; | ||
26 | unsigned int read_timeout; /* n * 8 clock cycles */ | ||
27 | unsigned int write_timeout; /* n * 8 clock cycles */ | ||
28 | |||
29 | unsigned long ocr; /* OCR register */ | ||
30 | unsigned long csd[4]; /* CSD register, 16 bytes */ | ||
31 | unsigned long cid[4]; /* CID register, 16 bytes */ | ||
32 | unsigned int speed; /* bit/s */ | ||
33 | unsigned int nsac; /* clock cycles */ | ||
34 | unsigned int tsac; /* n * 0.1 ns */ | ||
35 | unsigned int r2w_factor; | ||
36 | } tCardInfo; | ||
37 | |||
38 | unsigned long mmc_extract_bits(const unsigned long *p, unsigned int start, | ||
39 | unsigned int size); | ||
40 | tCardInfo *mmc_card_info(int card_no); | ||
41 | |||
42 | #endif | ||