MathewWi / sneek

Automatically exported from code.google.com/p/sneek
0 stars 0 forks source link

Slow USB drives nearly always not initialized properly - fix included #54

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Install any version of SNEEK that accesses USB for data
2. Connect a harddrive that needs a couple of seconds to boot up.
3. Start Wii

What is the expected output? What do you see instead?
Expected: Proper initialization every time.
Seen: Harddrive initialization fails ALMOST every time.

What revision are you using? With what configuration
(SNEEK/UNEEK/SNEEK+DI)?
Tested with SNEEK+DI r106 - expected to be the same for UNEEK/older revisions, 
but not tested.

Identified problem: Slow harddrives fail to initialize because the TinyEHCI 
library used only tries initialization once. This can be fixed with a delay 
before loading the DI module - easy enough. The problem then is that there is a 
race condition here - the DI module and the Wii's own USB code end up in a race 
for control over the drive. Here there are (at least) 3 possible ways this can 
go:
1: They both do initialization at the same time. One of them fails. If the DI 
module is the one that fails, boot stops there. If the Wii's own code fails, 
everything goes "perfect".
2: The DI module fully initializes the device before the Wii's own code even 
tries. It gets proper access... and the Wii's own code fails to claim the 
device. All goes well.
3: The Wii's own code fully initializes the device before the DI module even 
tries. The DI module then resets it and initializes it as well - causing the 
Wii's own code to fail a couple of seconds later, and crash.

Fix:
We want to force scenario #2, since that is what is supposed to happen and what 
usually happens with fast harddrives. To do this, I put in 2 delays: a delay 
before loading the DI module to ensure the harddrive is ready for 
initialization (this is a slow harddrive, after all!). Then another delay right 
after the DI module loads, preventing the Wii's own code (normally loaded 
nearly right after it) from being "first".
Patch for es/ES.c included that implements both delays. They could both 
probably be a lot shorter, especially the second one. Best is if the second 
delay waits for the DI module to finish initialization instead of a certain 
amount of time - which is guesswork and not very robust.

Disclaimer: I know nearly nothing about low level USB. My observations are 
based on a multitude of experiments, not knowledge. I can only say that this is 
what seems to be going on judging from the output, and the fix at least works 
for me. I just hope it helps add support for slower USB drives! :-)

Original issue reported on code.google.com by thuli...@gmail.com on 16 Jul 2010 at 11:19

Attachments:

GoogleCodeExporter commented 9 years ago
Thanks will look into that.
Anyone with a failing drive who could test and report what happens with those 
changes?

Original comment by cred...@rypp.net on 19 Jul 2010 at 5:35

GoogleCodeExporter commented 9 years ago
I'd love to try this patch. I've got a 500gb Seagate FreeAgent Go that I cannot 
get to work for the life of me, I'm just not sure at what line in the ES.c file 
to place the patch. 

Original comment by SpacePor...@gmail.com on 19 Jul 2010 at 11:40

GoogleCodeExporter commented 9 years ago
It's a diff patch file. In Linux those can be applied with the command "patch 
-p0 < patchfilenamehere" run inside the es directory.
Windows versions of the diff/patch programs can be found here: 
http://gnuwin32.sourceforge.net/packages/diffutils.htm

Alternatively, open the patch and es/ES.c in a text editor and make the changes 
yourself:
The lines with a + in front need to be added, the lines with @@ in front give 
you the line numbers. There are some lines of context around them to make the 
locations easier to find.

Original comment by thuli...@gmail.com on 19 Jul 2010 at 11:47

GoogleCodeExporter commented 9 years ago
Ok, I patched the ES.c file and recompiled the boot2_di and di bin files. My 
small usb flash drive still works (though it takes longer to start up of 
course), but my seagate still will not work, neither from boot2 nor boot IOS. 
Should I try making the delay even longer?

Original comment by SpacePor...@gmail.com on 19 Jul 2010 at 1:09

GoogleCodeExporter commented 9 years ago
The first delay is the most important, I've noticed. The second delay you can 
probably reduce to 1000000 in stead of 5000000 (it worked just fine in my 
tests), the first delay might need to be longer. My hard drive needs about 4 
seconds to boot up, so I set it to 4000000 - try counting how long it takes for 
your drive to start and give it a few seconds extra just to be sure.

I'm currently trying to change the code so that it will simply retry the hard 
drive until it works and then continue - which is of course better than a set 
delay, and allows fast devices to be fast.

By the way - this fix of course only will work for you if slowness of your 
drive is your problem. There can be countless other reasons it's not working...

Original comment by thuli...@gmail.com on 19 Jul 2010 at 1:17

GoogleCodeExporter commented 9 years ago
Well, I tried using a nine second delay even and that still wouldn't work. I 
know there are a number of things that can also prevent a drive from working, 
but I thought I've taken care of anything else. I have the exact file structure 
as the smaller working flash drive. I have a 32K cluster size. I just do not 
know what is wrong.
Thanks for helping me out though!

Original comment by SpacePor...@gmail.com on 19 Jul 2010 at 1:41

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
I made the solution more robust:
- The ES module will now wait for the DI module to be ready before it continues 
loading the rest of the modules... without a set timeout, causing the fastest 
bootup possible for the drive used.
- The DI module waits for the hard drive to be detected and settled before it 
resets the device.
- This also means you can turn on the Wii, THEN plug in the harddrive, and it 
will *still* work. You may have to unplug any other USB devices if you do this 
though... depending on what they are.
- If getting the device description fails, it will keep retrying at that stage 
of the device initialization until it succeeds or the Wii is turned off (could 
possibly be improved...)

Changed files are included. Works with r106. Because these are quite a few 
changes I did not make a patch file... but I can if that's preferred.

I also changed es/SMenu.c to be more user-friendly, support button-repeats 
(holding button = repeated pressing, for fast navigation), and have all games 
listed in alphabetical order in stead of directory order.
If you want to try the harddrive fix without the changed menu, simply do not 
use the es/SMenu.c file from the zip... both changes can be used independantly 
from each other (SMenu and/or everything else).

I think it should be possible to make this all work without the new 
DVD_CONNECTED call in the DI module... but this works and I didn't feel like 
changing it :)

Comments/further improvements/etc are of course welcome!

Original comment by thuli...@gmail.com on 23 Jul 2010 at 11:21

Attachments:

GoogleCodeExporter commented 9 years ago
r110 seems to fix this issue.
At least, it works for me without changes, unlike earlier versions :)

Original comment by thuli...@gmail.com on 26 Jul 2010 at 1:26

GoogleCodeExporter commented 9 years ago
I workaround this (even with r114) by turning on the wii WITHOUT the SD card.
Wait for the health screen -> put in the SD card and press reset
Now sneeks loads without problems (UNEEK and UNEEK+DI) (WD Essentials 1TB FAT32 
32kb)
Otherwise it will flash 3 times (cannot find kernel.bin) and no screen output.
This has to do with slow usb devices like thulinma stated.
Waiting for the health screen, you can hear the drive spinning up.

Original comment by digd...@zonnet.nl on 1 Aug 2010 at 12:23

GoogleCodeExporter commented 9 years ago
I've been running into the same problem running UNEEK (without DI).  What I see 
as the output from my USB Gecko is that my USB drive is slow coming up and 
reports as not connected for about 5 seconds.  The EHCI module then moves on 
the the second USB port and it looks like it tries to boot from my network 
adaptor which obviously fails.

The workaround I came up with was to add the following code to fs-usb/ehci.c in 
ehci_reset_port.

    dev->id = 0;
// NEW CODE START
    int retries = 10;
    while (!(PORT_CONNECT&status) && retries > 0)
    {
        msleep(1000);  // sleep 1 second
        status = ehci_readl(status_reg);
        ehci_dbg ( "port %d status at retry %d %X \n", port,retries,status);
        retries--;
    }
// NEW CODE END
    if ((PORT_OWNER&status) || !(PORT_CONNECT&status))

With this code, I see the following output:

FS: Discovering EHCI devices...
 port 0 status at retry 10 3000 
 port 0 status at retry 9 3000 
 port 0 status at retry 8 3000 
 port 0 status at retry 7 3000 
 port 0 status at retry 6 3000 
 port 0 status at retry 5 1803 
 port 0 has usb2 device connected! reset it...
 port 0 reseted status:1005...

Original comment by MrB...@widgetville.net on 5 Aug 2010 at 11:36

GoogleCodeExporter commented 9 years ago
Adding this fixes the slow usb problems for me (r118).
Made the retries 30 like in cfg usb loader

Original comment by digd...@zonnet.nl on 7 Aug 2010 at 10:28

GoogleCodeExporter commented 9 years ago
Adding this (re: comment 11) also fixes my drive, the previous commits didn't 
help

Original comment by mrplow...@gmail.com on 15 Aug 2010 at 5:15