-
Notifications
You must be signed in to change notification settings - Fork 133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
USB driver not working well with unaligned content #594
Comments
There is a hardware issue in the USB OHCI controller, which causes problems when a certain transfer size is used for outbound flows. The normal version will do some workaround, while the "aligned" version does not (assumption: you provide an aligned memory buffer, which will thus not meet the condition for the hardware bug). Actually, I did try using the normal function and I recall it somewhat worked. But as Sony remarked, the internal workaround might result in issues with some devices. I recall that writes resulted in corruption on my SanDisk. Therefore, writes were left to use the aligned variant. |
Thanks for the reply. So this is why I was thinking that the only solution here is to align the buffer before starting the copy, but the thing is, how to align it without losing too much performance and the best function to do it... |
Some additional useful info:
This last commit is more or less the current status we are using for current drivers in terms of READ/WRITES aligned. @sp193 Do you think it is possible to use Cheers. |
I will add some more debugging info...
From here I conclude that is possible to have also the same issue having an aligned buffer (even 64 bytes aligned) and producing concrete write length. I will check it... |
The payload size restriction of 63 or 64 bytes, refers to the USB frame size (not your request length). Sony wrote that sceUsbdOpenPipe() will internally do some workaround to limit the frame size to 62 bytes. However, this workaround seems to cause corruption with certain USB disks. Therefore, I do not think you can do anything about this, as the only workarounds are already documented by Sony. Only the outbound flow is affected (inbound is not affected).
In my opinion, you could make some assumptions and declare some limitations. Not all DMA channels could work with unaligned pointers, so this is probably not the only device that will require some copying. If you want to have a middle-ground, I think you can attempt to design something like what you have found in the RPC code. If I recall right, it works something like this. Please check.
Where N is the amount needed to align the buffer. Something like this strategy is also present in memcpy, if I remember right. |
👋
I have been facing some issues with USB drivers when using
fwrite
from unaligned 4-byte buffers...Given the next example:
It works as expected, however, if we replace
unsigned char *dummy_content_offset = dummy_content
withunsigned char *dummy_content_offset = dummy_content + 6
to force having an offset, it fails due to alignment issues on the USB driver.Compiling
PS2SDK
withDEBUG=1
we can have some extra information.Without
offset
:With
offset
:If you see, we start to suffer errors likes this one:
Where
bulk data transfer 262
262=0x106
which isfrom
iop/usb/usbd/include/usbd.h
Official documentation for FatFs - Generic FAT Filesystem Module mentioned in the
dread
anddwrite
information about possible alignment issues:http://elm-chan.org/fsw/ff/doc/dread.html
http://elm-chan.org/fsw/ff/doc/dwrite.html
This is something that I actually see reflected on the execution...
Let's follow the callback functions:
Buffer is aligned till it reaches the
iop/fs/bdmfs_fatfs/src/ff.c ==> f_write
function where it plays with buffer index, producing already an unaligned buffer. Is important to mention that code fromf_write
belong tofsw
library.So, why it is failing?
It fails because on the
sceUsbdTransferPipe
we have the next condition:If you see it check if data is aligned with
((u32)data & 3))
, but it only check it if theep->alignFlag
is different that0
.This flag is set when registering the endpoints
We generate 2 different endpoint, one for reading from USB (INPUT), and another one for writing (
OUTPUT
).If we see how this is done is through the function
usb_bulk_probeEndpoint
iniop/usb/usbmass_bd/src/usb_mass.c
If you take a look it uses
sceUsbdOpenPipeAligned
forUSB_DIR_OUT
. ThesceUsbdOpenPipeAligned
is the one that set thealignFlag = 1
, which triggers the condition that fails later on theiop/usb/usbd/src/interface.c ==> sceUsbdTransferPipe
.I don't know how to fix it as I don't have enough experience with drivers at that low level... however, I hope all this information is useful for you...
Pinging @sp193 @rickgaiser @davidgfnet @uyjulian as I know you have experience with these kinds of things.
Cheers.
The text was updated successfully, but these errors were encountered: