Hi Alexander,
The first thing I did was to disable caching and buffering in L4.. And it was a fiasco. The good news is that reading IO memory via the DS attached pointer and via the mmio Register class seems to bring identical results.
it would be interesting to know if your current working version works with caches enabled. Just to see if the issue is related with caches.
Turned out, the wrong data came from musb_read_fifo function. This function calls __raw_readl, __raw_readb, __raw_readw functions. I think I have implemented them correctly given that unaligned access works fine in genode. I would appreciate if someone takes a look at them.
https://github.com/astarasikov/genode/blob/omap4-otg-dirty/dde_linux/src/dri...
Your implementation looks ok. It is just a copy of the corresponding 'b' and 'l' functions with the type changed, isn't it?
Turns out, there's a single FIFO register and when you read from it or write to it, the controller immediately feeds it with the new data. So, maybe multiple unaligned access caused it to fail.
What I did was to comment out musb_{write,read}_fifo code and manually read the data. First I decided to read by 4-byte words, but that failed. To my surprise, reading by single bytes did the trick and the driver is now receiving the correct data and the host recognizes the device, albeit at the third attempt.
The 'musb_write_fifo' function is known to work on Linux. I am afraid that replacing this known-good code with a custom implementation will hide the symptom at best. I have a slight suspicion. Let's take another look at 'musb_write_fifo' again
http://lxr.linux.no/#linux+v3.6.1/drivers/usb/musb/musb_core.c#L232
The function uses different write-access functions for different alignments and length constrains. One particularly interesting case is the 32-aligned case for a len >= 4. Here, the 'writesl' function is used, which is just a wrapper around 'outsl'. Let's take a closer look to 'outsl':
http://lxr.linux.no/#linux+v3.6.1/include/asm-generic/io.h#L209
The function uses a loop to repeatedly call 'outl'. On x86, 'outl' performs an I/O port access. DDE Linux maps this function to the coresponding 'dde_kit_outl' implementation, which uses core's IO_PORT service to perform the access. On ARM, however, there are no I/O ports. Hence, the the out* function of the IO_PORT service in core are no-ops. You could validate the hypothesis by adding a bit of log output to the dummy functions at:
base/src/core/arm/io_port_session_component.c
If any of these functions is called on ARM, this is an error. If this is the case, the solution would be to implement the 'outl' function in your version of 'lx_emul.h' with an I/O memory access.
I must admit that I'm quite surprised that the 'outl' function is called on ARM at all. Of course, I recommend to check the other 'out*' functions as well.
And, btw, I've found a small bug in dde_linux. In the file dde_linux/src/drivers/usb/arm/platform/lx_emul.h the definition SZ_4K = 0x00001000a, seems clearly wrong to me. That 'a' at the end is probably a bad typo. When I figure out the musb issues, I'll submit a pull request for this if no one else does that before.
You are right. That is a typo. Thank you very much!
Cheers Norman