A number of people have succeeded in running Rockbox on their 30G G5.5
iPods with some trickery: a regular bootloader and rockbox build,
modified ipod_fw, a fresh 512bps filesystem, and an extra partition
table entry for Rockbox's benefit, with the start and count multiplied
by four.  However, when I try the same technique on my 80G iPod, I
find that the bootloader hangs while trying to read the MBR.

amiconn suggested that I try to debug ATA init somehow, but there
doesn't seem to be much to it.  The value of the IDE control register
is 0x20150020 - does that sound right?

ata_device_init() (see firmware/target/arm/ata-pp5020.c) does

    outl(inl(0xc3000028) | (1 << 5), 0xc3000028);
    outl(inl(0xc3000028) & ~0x10000000, 0xc3000028);

but that just writes back the register twice, unchanged, because
neither of the bitwise operations alter any of the register's bits.


This next bit is probably a waste of time if the ATA init is indeed
the problem, but I got a nice tour through the Rockbox code on the
way, so I don't mind.


By adding a bunch of debugging messages, I traced the hang through the
following call chain:

[bootloader] main()
        -> disk_init()
                -> ata_read_sectors() (it's reading the MBR)
                        -> copy_read_sectors
                        status & STATUS_ERR is true
                        -> perform_soft_reset() - which hangs

perform_soft_reset() hangs here:

  static int perform_soft_reset(void)
  {
      int ret;
      int retry_count;

      SET_REG(ATA_SELECT, SELECT_LBA | ata_device );
      SET_REG(ATA_CONTROL, CONTROL_nIEN|CONTROL_SRST );
      sleep(1); /* >= 5us */                      <-- *** HANGS HERE ***

      SET_REG(ATA_CONTROL, CONTROL_nIEN);
      sleep(1); /* >2ms */
      lcd_log("sleep #2 done");

      /* This little sucker can take up to 30 seconds */
      retry_count = 8;
      do
      {
          lcd_log("boing");
          ret = wait_for_rdy();
      } while(!ret && retry_count--);

      /* Massage the return code so it is 0 on success and -1 on failure */
      ret = ret?0:-1;

      return ret;
  }


So that's a bit odd.

I removed all of my LCD-writing calls from ata_read_sectors() on down,
leaving just two: one before and one after that first sleep(1) call,
and that seems to definitely be where it hangs - I see the before
message, and not the after message.

Suggestions for more stuff to try are welcome.

-- 
Paul Collins
Wellington, New Zealand

Dag vijandelijk luchtschip de huismeester is dood

Reply via email to