freemyipod r613 - Code Review

Jump to: navigation, search
Repository:freemyipod
Revision:r612‎ | r613 | r614 >
Date:05:18, 14 February 2011
Author:theseven
Status:new
Tags:
Comment:
emCORE: iPod Classic ATA driver rework:
- Expose BBT access functions
- Rework retry handling, already split access after first failure (which used to be slow before the recent kernel changes)
- If soft resetting the drive fails, power cycle it the hard way
Modified paths:
  • /emcore/trunk/target/ipodclassic/storage_ata-target.h (modified) (history)
  • /emcore/trunk/target/ipodclassic/storage_ata.c (modified) (history)
  • /emcore/trunk/target/ipodclassic/usbtarget.c (modified) (history)

Diff [purge]

Index: emcore/trunk/target/ipodclassic/usbtarget.c
@@ -69,6 +69,20 @@
7070 size = 16;
7171 break;
7272 }
 73+ case 0xffff0003: // ATA_BBT_RELOAD
 74+ {
 75+ ata_bbt_reload();
 76+ buffer[0] = 1;
 77+ size = 16;
 78+ break;
 79+ }
 80+ case 0xffff0004: // ATA_BBT_DISABLE
 81+ {
 82+ ata_bbt_disable();
 83+ buffer[0] = 1;
 84+ size = 16;
 85+ break;
 86+ }
7387 default:
7488 buffer[0] = 2;
7589 size = 16;
Index: emcore/trunk/target/ipodclassic/storage_ata-target.h
@@ -24,9 +24,18 @@
2525 #ifndef __STORAGE_ATA_TARGET_H__
2626 #define __STORAGE_ATA_TARGET_H__
2727
28 -#include "global.h"
 28+#include "../global.h"
2929
3030
 31+struct ata_target_driverinfo
 32+{
 33+ int (*soft_reset)();
 34+ int (*bbt_translate)(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount);
 35+ void (*bbt_reload)();
 36+ void (*bbt_disable)();
 37+};
 38+
 39+
3140 extern uint16_t ata_identify_data[0x100];
3241 extern uint64_t ata_total_sectors;
3342 extern struct mutex ata_mutex;
@@ -35,6 +44,9 @@
3645 extern uint16_t (*ata_bbt)[0x20];
3746 extern uint64_t ata_virtual_sectors;
3847
 48+int ata_bbt_translate(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount);
 49+void ata_bbt_reload();
 50+void ata_bbt_disable();
3951 int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool write);
4052 #endif
4153
Index: emcore/trunk/target/ipodclassic/storage_ata.c
@@ -26,6 +26,12 @@
2727 #include "timer.h"
2828 #include "../ipodnano3g/s5l8702.h"
2929
 30+
 31+#ifndef ATA_RETRIES
 32+#define ATA_RETRIES 3
 33+#endif
 34+
 35+
3036 /** static, private data **/
3137 uint16_t ata_identify_data[0x100];
3238 bool ata_lba48;
@@ -56,7 +62,17 @@
5763 }
5864 #endif
5965
 66+static struct ata_target_driverinfo drvinfo =
 67+{
 68+ .soft_reset = ata_soft_reset,
 69+#ifdef ATA_HAVE_BBT
 70+ .bbt_translate = ata_bbt_translate,
 71+ .bbt_reload = ata_bbt_reload,
 72+ .bbt_disable = ata_bbt_disable
 73+#endif
 74+};
6075
 76+
6177 static uint16_t ata_read_cbr(uint32_t volatile* reg)
6278 {
6379 while (!(ATA_PIO_READY & 2)) yield();
@@ -333,6 +349,59 @@
334350 return 0;
335351 }
336352
 353+#ifdef ATA_HAVE_BBT
 354+int ata_bbt_translate(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount)
 355+{
 356+ if (sector + count > ata_virtual_sectors) RET_ERR(0);
 357+ if (!ata_bbt)
 358+ {
 359+ *phys = sector;
 360+ *physcount = count;
 361+ return 0;
 362+ }
 363+ if (!count)
 364+ {
 365+ *phys = 0;
 366+ *physcount = 0;
 367+ return 0;
 368+ }
 369+ uint32_t offset;
 370+ uint32_t l0idx = sector >> 15;
 371+ uint32_t l0offs = sector & 0x7fff;
 372+ *physcount = MIN(count, 0x8000 - l0offs);
 373+ uint32_t l0data = ata_bbt[0][l0idx << 1];
 374+ uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12;
 375+ if (l0data < 0x8000) offset = l0data + base;
 376+ else
 377+ {
 378+ uint32_t l1idx = (sector >> 10) & 0x1f;
 379+ uint32_t l1offs = sector & 0x3ff;
 380+ *physcount = MIN(count, 0x400 - l1offs);
 381+ uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx];
 382+ if (l1data < 0x8000) offset = l1data + base;
 383+ else
 384+ {
 385+ uint32_t l2idx = (sector >> 5) & 0x1f;
 386+ uint32_t l2offs = sector & 0x1f;
 387+ *physcount = MIN(count, 0x20 - l2offs);
 388+ uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx];
 389+ if (l2data < 0x8000) offset = l2data + base;
 390+ else
 391+ {
 392+ uint32_t l3idx = sector & 0x1f;
 393+ uint32_t l3data = ata_bbt[l2data & 0x7fff][l3idx];
 394+ for (*physcount = 1; *physcount < count && l3idx + *physcount < 0x20; *physcount++)
 395+ if (ata_bbt[l2data & 0x7fff][l3idx + *physcount] != l3data)
 396+ break;
 397+ offset = l3data + base;
 398+ }
 399+ }
 400+ }
 401+ *phys = sector + offset;
 402+ return 0;
 403+}
 404+#endif
 405+
337406 int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write)
338407 {
339408 #ifdef ATA_HAVE_BBT
@@ -340,39 +409,10 @@
341410 if (ata_bbt)
342411 while (count)
343412 {
344 - uint32_t offset;
345 - uint32_t l0idx = sector >> 15;
346 - uint32_t l0offs = sector & 0x7fff;
347 - uint32_t cnt = MIN(count, 0x8000 - l0offs);
348 - uint32_t l0data = ata_bbt[0][l0idx << 1];
349 - uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12;
350 - if (l0data < 0x8000) offset = l0data + base;
351 - else
352 - {
353 - uint32_t l1idx = (sector >> 10) & 0x1f;
354 - uint32_t l1offs = sector & 0x3ff;
355 - cnt = MIN(count, 0x400 - l1offs);
356 - uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx];
357 - if (l1data < 0x8000) offset = l1data + base;
358 - else
359 - {
360 - uint32_t l2idx = (sector >> 5) & 0x1f;
361 - uint32_t l2offs = sector & 0x1f;
362 - cnt = MIN(count, 0x20 - l2offs);
363 - uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx];
364 - if (l2data < 0x8000) offset = l2data + base;
365 - else
366 - {
367 - uint32_t l3idx = sector & 0x1f;
368 - uint32_t l3data = ata_bbt[l2data & 0x7fff][l3idx];
369 - for (cnt = 1; cnt < count && l3idx + cnt < 0x20; cnt++)
370 - if (ata_bbt[l2data & 0x7fff][l3idx + cnt] != l3data)
371 - break;
372 - offset = l3data + base;
373 - }
374 - }
375 - }
376 - uint64_t phys = sector + offset;
 413+ uint64_t phys;
 414+ uint32_t cnt;
 415+ PASS_RC(ata_bbt_translate(sector, count, &phys, &cnt), 0, 0);
 416+ uint32_t offset = phys - sector;
377417 if (offset != ata_last_offset && phys - ata_last_phys < 64) ata_soft_reset();
378418 ata_last_offset = offset;
379419 ata_last_phys = phys + cnt;
@@ -398,20 +438,16 @@
399439 {
400440 uint32_t cnt = MIN(ata_lba48 ? 8192 : 32, count);
401441 int rc = -1;
402 - int tries = 3;
403 - while (tries-- && rc)
 442+ rc = ata_rw_chunk(sector, cnt, buffer, write);
 443+ if (rc) ata_soft_reset();
 444+ if (rc && ATA_RETRIES)
404445 {
405 - rc = ata_rw_chunk(sector, cnt, buffer, write);
406 - if (rc) ata_soft_reset();
407 - }
408 - if (rc)
409 - {
410446 void* buf = buffer;
411447 uint64_t sect;
412448 for (sect = sector; sect < sector + cnt; sect++)
413449 {
414450 rc = -1;
415 - tries = 3;
 451+ tries = ATA_RETRIES;
416452 while (tries-- && rc)
417453 {
418454 rc = ata_rw_chunk(sect, 1, buf, write);
@@ -451,7 +487,13 @@
452488 ata_write_cbr(&ATA_PIO_DAD, BIT(1) | BIT(2));
453489 sleep(10);
454490 ata_write_cbr(&ATA_PIO_DAD, 0);
455 - PASS_RC_MTX(ata_wait_for_rdy(60000000), 0, 0, &ata_mutex);
 491+ int rc = ata_wait_for_rdy(20000000);
 492+ if (IS_ERR(rc))
 493+ {
 494+ ata_power_down();
 495+ sleep(3000000);
 496+ ata_power_up();
 497+ }
456498 ata_set_active();
457499 mutex_unlock(&ata_mutex);
458500 }
@@ -512,6 +554,7 @@
513555 (*info).vendor = "Apple";
514556 (*info).product = "iPod Classic";
515557 (*info).revision = "1.0";
 558+ (*info).driverinfo = &drvinfo;
516559 }
517560
518561 long ata_last_disk_activity(void)
@@ -519,19 +562,20 @@
520563 return ata_last_activity_value;
521564 }
522565
523 -int ata_init(void)
 566+#ifdef ATA_HAVE_BBT
 567+void ata_bbt_disable()
524568 {
525 - mutex_init(&ata_mutex);
526 - wakeup_init(&ata_wakeup);
527 - PCON(7) = 0x44444444;
528 - PCON(8) = 0x44444444;
529 - PCON(9) = 0x44444444;
530 - PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
531 - ata_powered = false;
532 - ata_total_sectors = 0;
533 -#ifdef ATA_HAVE_BBT
534569 mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
 570+ if (ata_bbt) free(ata_bbt);
535571 ata_bbt = NULL;
 572+ ata_virtual_sectors = ata_total_sectors;
 573+ mutex_unlock(&ata_mutex);
 574+}
 575+
 576+void ata_bbt_reload()
 577+{
 578+ mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
 579+ ata_bbt_disable();
536580 ata_power_up();
537581 uint32_t* buf = (uint32_t*)memalign(0x10, 0x1000);
538582 if (buf)
@@ -559,7 +603,22 @@
560604 }
561605 else ata_virtual_sectors = ata_total_sectors;
562606 mutex_unlock(&ata_mutex);
 607+}
563608 #endif
 609+
 610+int ata_init(void)
 611+{
 612+ mutex_init(&ata_mutex);
 613+ wakeup_init(&ata_wakeup);
 614+ PCON(7) = 0x44444444;
 615+ PCON(8) = 0x44444444;
 616+ PCON(9) = 0x44444444;
 617+ PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
 618+ ata_powered = false;
 619+ ata_total_sectors = 0;
 620+#ifdef ATA_HAVE_BBT
 621+ ata_bbt_reload();
 622+#endif
564623 thread_create(&ata_thread_handle, "ATA idle monitor", ata_thread, ata_stack,
565624 sizeof(ata_stack), OS_THREAD, 1, true);
566625 return 0;