Page 1 of 2

xhci bochs - qemu - real hardware

Posted: Wed Jan 29, 2020 2:35 pm
by SanderR
Hello everyone.

I have been working on my XHCI driver for half a year now.
This is the code I wrote for it so far: https://github.com/AdeRegt/SanderOSUSB/ ... dev/xhci.c

I used BOCHS as my main testing device since it had great debugging tools.
I'm running BOCHS with an emulated USB stick.
I got my BOCHS code this far that I am attempting to read the descriptor of the connected USB device.
Somehow, this returns an array of 0 on Bochs:
00118992392e[USBMSD] USB MSD handle_control: unknown descriptor type 0x00
I was hoping this would be because I'm just emulating a USB and I wanted to test it on qemu.

My code on qemu and real hardware was totally incompatible with addresses.
I had to use an offset on real hardware of 0x7C and on qemu I found a way to get the right offset (lines 57-64 in my code).

I run my code again and qemu hangs at line 295.

My questions are:
A: What did I do wrong that qemu keeps hanging at line 295?
B: Is there a more easy way to get the right offsets?

The following messages are emitted by qemu after the reset:

[email protected]:usb_xhci_reset === RESET ===
[email protected]:usb_xhci_slot_disable slotid 1
[email protected]:usb_xhci_ep_disable slotid 1, epid 1
[email protected]:usb_xhci_ep_disable slotid 1, epid 3
[email protected]:usb_xhci_slot_disable slotid 2
[email protected]:usb_xhci_ep_disable slotid 2, epid 1
[email protected]:usb_xhci_slot_disable slotid 3
[email protected]:usb_xhci_slot_disable slotid 4
[email protected]:usb_xhci_slot_disable slotid 5
[email protected]:usb_xhci_slot_disable slotid 6
[email protected]:usb_xhci_slot_disable slotid 7
[email protected]:usb_xhci_slot_disable slotid 8
[email protected]:usb_xhci_slot_disable slotid 9
[email protected]:usb_xhci_slot_disable slotid 10
[email protected]:usb_xhci_slot_disable slotid 11
[email protected]:usb_xhci_slot_disable slotid 12
[email protected]:usb_xhci_slot_disable slotid 13
[email protected]:usb_xhci_slot_disable slotid 14
[email protected]:usb_xhci_slot_disable slotid 15
[email protected]:usb_xhci_slot_disable slotid 16
[email protected]:usb_xhci_slot_disable slotid 17
[email protected]:usb_xhci_slot_disable slotid 18
[email protected]:usb_xhci_slot_disable slotid 19
[email protected]:usb_xhci_slot_disable slotid 20
[email protected]:usb_xhci_slot_disable slotid 21
[email protected]:usb_xhci_slot_disable slotid 22
[email protected]:usb_xhci_slot_disable slotid 23
[email protected]:usb_xhci_slot_disable slotid 24
[email protected]:usb_xhci_slot_disable slotid 25
[email protected]:usb_xhci_slot_disable slotid 26
[email protected]:usb_xhci_slot_disable slotid 27
[email protected]:usb_xhci_slot_disable slotid 28
[email protected]:usb_xhci_slot_disable slotid 29
[email protected]:usb_xhci_slot_disable slotid 30
[email protected]:usb_xhci_slot_disable slotid 31
[email protected]:usb_xhci_slot_disable slotid 32
[email protected]:usb_xhci_slot_disable slotid 33
[email protected]:usb_xhci_slot_disable slotid 34
[email protected]:usb_xhci_slot_disable slotid 35
[email protected]:usb_xhci_slot_disable slotid 36
[email protected]:usb_xhci_slot_disable slotid 37
[email protected]:usb_xhci_slot_disable slotid 38
[email protected]:usb_xhci_slot_disable slotid 39
[email protected]:usb_xhci_slot_disable slotid 40
[email protected]:usb_xhci_slot_disable slotid 41
[email protected]:usb_xhci_slot_disable slotid 42
[email protected]:usb_xhci_slot_disable slotid 43
[email protected]:usb_xhci_slot_disable slotid 44
[email protected]:usb_xhci_slot_disable slotid 45
[email protected]:usb_xhci_slot_disable slotid 46
[email protected]:usb_xhci_slot_disable slotid 47
[email protected]:usb_xhci_slot_disable slotid 48
[email protected]:usb_xhci_slot_disable slotid 49
[email protected]:usb_xhci_slot_disable slotid 50
[email protected]:usb_xhci_slot_disable slotid 51
[email protected]:usb_xhci_slot_disable slotid 52
[email protected]:usb_xhci_slot_disable slotid 53
[email protected]:usb_xhci_slot_disable slotid 54
[email protected]:usb_xhci_slot_disable slotid 55
[email protected]:usb_xhci_slot_disable slotid 56
[email protected]:usb_xhci_slot_disable slotid 57
[email protected]:usb_xhci_slot_disable slotid 58
[email protected]:usb_xhci_slot_disable slotid 59
[email protected]:usb_xhci_slot_disable slotid 60
[email protected]:usb_xhci_slot_disable slotid 61
[email protected]:usb_xhci_slot_disable slotid 62
[email protected]:usb_xhci_slot_disable slotid 63
[email protected]:usb_xhci_slot_disable slotid 64
[email protected]:usb_xhci_port_link port 1, pls 5
[email protected]:usb_xhci_port_notify port 1, bits 0x20000
[email protected]:usb_xhci_port_link port 2, pls 5
[email protected]:usb_xhci_port_notify port 2, bits 0x20000
[email protected]:usb_xhci_port_link port 3, pls 5
[email protected]:usb_xhci_port_notify port 3, bits 0x20000
[email protected]:usb_xhci_port_link port 4, pls 5
[email protected]:usb_xhci_port_notify port 4, bits 0x20000
[email protected]:usb_xhci_port_link port 5, pls 7
[email protected]:usb_xhci_port_notify port 5, bits 0x20000
[email protected]:usb_xhci_port_link port 6, pls 7
[email protected]:usb_xhci_port_notify port 6, bits 0x20000
[email protected]:usb_xhci_port_link port 7, pls 5
[email protected]:usb_xhci_port_notify port 7, bits 0x20000
[email protected]:usb_xhci_port_link port 8, pls 5
[email protected]:usb_xhci_port_notify port 8, bits 0x20000
[email protected]:usb_xhci_irq_intx level 0
[email protected]:usb_xhci_oper_read off 0x0004, ret 0x00000001
[email protected]:usb_xhci_oper_read off 0x0000, ret 0x00000000
[email protected]:usb_xhci_runtime_read off 0x0028, ret 0x00000000
[email protected]:usb_xhci_runtime_write off 0x0028, val 0x00000001
[email protected]:usb_xhci_runtime_write off 0x0038, val 0x00116c00
[email protected]:usb_xhci_runtime_write off 0x003c, val 0x00000000
[email protected]:usb_xhci_runtime_write off 0x0030, val 0x00116a00
[email protected]:usb_xhci_runtime_write off 0x0034, val 0x00000000
[email protected]:usb_xhci_oper_read off 0x0018, ret 0x00000000
[email protected]:usb_xhci_oper_write off 0x0018, val 0x00116e00
[email protected]:usb_xhci_oper_write off 0x001c, val 0x00000000
[email protected]:usb_xhci_oper_read off 0x0030, ret 0x00000000
[email protected]:usb_xhci_oper_write off 0x0030, val 0x00116b00
[email protected]:usb_xhci_oper_write off 0x0034, val 0x00000000
[email protected]:usb_xhci_oper_read off 0x0000, ret 0x00000000
[email protected]:usb_xhci_oper_write off 0x0000, val 0x00000004
[email protected]:usb_xhci_irq_intx level 0
[email protected]:usb_xhci_oper_read off 0x0000, ret 0x00000004
[email protected]:usb_xhci_oper_write off 0x0000, val 0x00000005
[email protected]:usb_xhci_run
[email protected]:usb_xhci_irq_intx level 0
[email protected]:usb_xhci_oper_read off 0x0004, ret 0x00000000
[email protected]:usb_xhci_oper_read off 0x0000, ret 0x00000005
[email protected]:usb_xhci_port_read port 1, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 1, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 1, warm 0
[email protected]:usb_xhci_port_read port 1, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_read port 2, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 2, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 2, warm 0
[email protected]:usb_xhci_port_read port 2, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_read port 3, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 3, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 3, warm 0
[email protected]:usb_xhci_port_read port 3, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_read port 4, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 4, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 4, warm 0
[email protected]:usb_xhci_port_read port 4, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_read port 5, off 0x0000, ret 0x00020ee1
[email protected]:usb_xhci_doorbell_write off 0x0000, val 0x00000000
[email protected]:usb_xhci_fetch_trb addr 0x0000000000116e00, CR_ENABLE_SLOT, p 0x0000000000000000, s 0x00000000, c 0x00002400
[email protected]:usb_xhci_runtime_read off 0x0020, ret 0x00000000

The following are the working bochs messages:

00184710831d[XHCI ] register read from offset 0x0000: 0x0000000000000020 (len=1)
00184784396d[XHCI ] register read from offset 0x0002: 0x0000000000000100 (len=4)
00184820376d[XHCI ] register read from offset 0x0010: 0x000000000140530F (len=4)
00184820376d[XHCI ] register read from offset 0x0007: 0x0000000000000000 (len=1)
00184930819d[XHCI ] register read from offset 0x0018: 0x0000000000000600 (len=4)
00185003908d[XHCI ] register read from offset 0x0014: 0x0000000000000800 (len=4)
00185076520d[XHCI ] register read from offset 0x0058: 0x0000000000000000 (len=4)
00185112883d[XHCI ] register read from offset 0x0050: 0x0000000000000000 (len=4)
00185149235d[XHCI ] register read from offset 0x0038: 0x0000000000000000 (len=4)
00185185587d[XHCI ] register read from offset 0x0020: 0x0000000000000000 (len=4)
00185221478d[XHCI ] register read from offset 0x0020: 0x0000000000000000 (len=4)
00185221478d[XHCI ] register write to offset 0x0020: 0x0000000000000002 (len=4)
00188584523d[XHCI ] register read from offset 0x0024: 0x0000000000000001 (len=4)
00188584523d[XHCI ] register read from offset 0x0020: 0x0000000000000000 (len=4)
00188622016d[XHCI ] register read from offset 0x0628: 0x0000000000000000 (len=4)
00188622016d[XHCI ] register write to offset 0x0628: 0x0000000000000001 (len=4)
00188622016d[XHCI ] register write to offset 0x0638: 0x0000000000116C00 (len=4)
00188622016d[XHCI ] register write to offset 0x063C: 0x0000000000000000 (len=4)
00188622016d[XHCI ] register write to offset 0x0630: 0x0000000000116A00 (len=4)
00188622016d[XHCI ] register write to offset 0x0634: 0x0000000000000000 (len=4)
00188622016d[XHCI ] Interrupter 00: Event Ring Table (at 0x0000000000116a00) has 1 entries:
00188622016d[XHCI ] 00: address = 0x0000000000116c00 Count = 16
00188622016d[XHCI ] register read from offset 0x0038: 0x0000000000000000 (len=4)
00188622016d[XHCI ] register write to offset 0x0038: 0x0000000000116E00 (len=4)
00188622016d[XHCI ] register write to offset 0x003C: 0x0000000000000000 (len=4)
00188622016d[XHCI ] register read from offset 0x0050: 0x0000000000000000 (len=4)
00188622016d[XHCI ] register write to offset 0x0050: 0x0000000000116B00 (len=4)
00188622016d[XHCI ] register write to offset 0x0054: 0x0000000000000000 (len=4)
00188622016d[XHCI ] register read from offset 0x0020: 0x0000000000000000 (len=4)
00188622016d[XHCI ] register write to offset 0x0020: 0x0000000000000004 (len=4)
00192184587d[XHCI ] register read from offset 0x0020: 0x0000000000000004 (len=4)
00192184587d[XHCI ] register write to offset 0x0020: 0x0000000000000005 (len=4)
00195784640d[XHCI ] register read from offset 0x0024: 0x0000000000000000 (len=4)
00195784640d[XHCI ] register read from offset 0x0020: 0x0000000000000005 (len=4)
00195858290d[XHCI ] register read from offset 0x0420: 0x0000000000000000 (len=4)
00195858308d[XHCI ] register write to offset 0x0420: 0x0000000000000210 (len=4)
00195858308i[XHCI ] Reset port #1, type=0
00199384698d[XHCI ] register read from offset 0x0420: 0x0000000000201203 (len=4)
00199531697d[XHCI ] register write to offset 0x0800: 0x0000000000000000 (len=4)
00199531697d[XHCI ] Command Doorbell Rang
00199531697d[XHCI ] Dump command trb: 9(dec) (0x0000000000000000 0x00000000 0x00002400) (0)
00199531697d[XHCI ] 0x0000000000116e00: Command Ring: Found Enable Slot TRB (slot = 1) (returning 1)
00199531697d[XHCI ] register read from offset 0x0620: 0x0000000000000001 (len=1)
00199614344d[XHCI ] register write to offset 0x0800: 0x0000000000000000 (len=4)
00199614344d[XHCI ] Command Doorbell Rang
00199614344d[XHCI ] Dump command trb: 11(dec) (0x00000000000304d0 0x00000000 0x01002C00) (0)
00199614344d[XHCI ] slot_context->int_target = 0, slot_context->max_exit_latency = 0
00199614344d[XHCI ] ep_num = 1, speed = -1, ep_context->max_packet_size = 1
00199614344d[XHCI ] 0x0000000000116e10: Command Ring: SetAddress TRB (bsr = 0) (addr = 2) (slot = 1) (returning 1)
00199614376d[XHCI ] register read from offset 0x0620: 0x0000000000000001 (len=1)
00199688937d[XHCI ] register write to offset 0x0800: 0x0000000000000000 (len=4)
00199688937d[XHCI ] Command Doorbell Rang
00199688937d[XHCI ] Dump command trb: 12(dec) (0x00000000000304d0 0x00000000 0x01003000) (0)
00199688937d[XHCI ] 0x0000000000116e20: Command Ring: Found Config_EP TRB (slot = 1) (returning 1)
00199688937d[XHCI ] register read from offset 0x0620: 0x0000000000000001 (len=1)
00199800258d[XHCI ] register write to offset 0x0804: 0x0000000000000001 (len=4)
00199800258d[XHCI ] Rang Doorbell: slot = 1 ep = 1 (IN)
00199800258d[XHCI ] Found TRB: address = 0x0000000000117000 0x0000000000040680 0x00400008 0x00030841 1
00199800258d[XHCI ] Found TRB: address = 0x0000000000117000 0x0000000000040680 0x00400008 0x00030841 1 (SPD occurred = 0)
00199800258d[XHCI ] 0x0000000000117000: Transfer Ring (slot = 1) (ep = 1) (len = 8): Found SETUP TRB
00199800258e[USBMSD] USB MSD handle_control: unknown descriptor type 0x00
00199800258d[XHCI ] OUT: Transferred 8 bytes (ret = -3)
00199800258d[XHCI ] Found TRB: address = 0x0000000000117010 0x0000000000030524 0x00000008 0x00010C01 1 (SPD occurred = 0)
00199800258d[XHCI ] 0x0000000000117010: Transfer Ring (slot = 1) (ep = 1) (len = 8): Found DATA STAGE TRB
00199800258d[XHCI ] Process Transfer Ring: Processed 2 TRB's
00199800258d[XHCI ] register read from offset 0x0620: 0x0000000000000001 (len=1)
00599911076d[XHCI ] register read from offset 0x0430: 0x0000000000000000 (len=4)
00599911076d[XHCI ] register write to offset 0x0430: 0x0000000000000210 (len=4)
00599911076i[XHCI ] Reset port #2, type=0
00603111124d[XHCI ] register read from offset 0x0430: 0x00000000000002A0 (len=4)
00603111124d[XHCI ] register read from offset 0x0440: 0x0000000000000000 (len=4)
00603111124d[XHCI ] register write to offset 0x0440: 0x0000000000000210 (len=4)
00603111124i[XHCI ] Reset port #3, type=0
00606711184d[XHCI ] register read from offset 0x0440: 0x00000000000002A0 (len=4)
00606711184d[XHCI ] register read from offset 0x0450: 0x0000000000000000 (len=4)
00606711184d[XHCI ] register write to offset 0x0450: 0x0000000000000210 (len=4)
00606711184i[XHCI ] Reset port #4, type=0
00610311244d[XHCI ] register read from offset 0x0450: 0x00000000000002A0 (len=4)
00610311244e[XHCI ] register read from unknown offset 0x00000460: 0x0000000000000000 (len=4)
00610311244d[XHCI ] register read from offset 0x0460: 0x0000000000000000 (len=4)
00610311244d[XHCI ] register write to offset 0x0460: 0x0000000000000210 (len=4)
00610311244e[XHCI ] register write to unknown offset 0x00000460: 0x0000000000000210 (len=4)
00613911295e[XHCI ] register read from unknown offset 0x00000460: 0x0000000000000000 (len=4)
00613911295d[XHCI ] register read from offset 0x0460: 0x0000000000000000 (len=4)
00613911302d[XHCI ] register read from offset 0x0038: 0x0000000000000008 (len=4)
01741168000p[XGUI ] >>PANIC<< POWER button turned off.

Re: xhci bochs - qemu - real hardware

Posted: Wed Jan 29, 2020 4:22 pm
by SanderR
An update: it seems that on BOCHS you should not set the C bit at a TRB when you want it to get processed but in qemu you should.
Now it is enabling a port and when I ask for an address it gives error code 5 back...

Re: xhci bochs - qemu - real hardware

Posted: Wed Jan 29, 2020 5:40 pm
by BenLunt
Hi,

A quick look at your debug report and I noticed:

00199614344d[XHCI ] slot_context->int_target = 0, slot_context->max_exit_latency = 0
00199614344d[XHCI ] ep_num = 1, speed = -1, ep_context->max_packet_size = 1

Speed shouldn't be -1 and Max Packet Size shouldn't be 1.

What do you mean by the 'C Bit'? Are you referring to the Cycle bit in the Command Ring? It can be either 1 or 0, all depending on what you tell the controller it will be.

I don't have time at the moment to look over your code, hopefully will be able to soon, but I would double check that your structure packing is correct.

Also, the following looks wrong to me (beside the two errors mentioned above):

00199531697d[XHCI ] 0x0000000000116e00: Command Ring: Found Enable Slot TRB (slot = 1) (returning 1)
00199614344d[XHCI ] Command Doorbell Rang
00199614344d[XHCI ] Dump command trb: 11(dec) (0x00000000000304d0 0x00000000 0x01002C00) (0)
00199614344d[XHCI ] slot_context->int_target = 0, slot_context->max_exit_latency = 0
00199614344d[XHCI ] ep_num = 1, speed = -1, ep_context->max_packet_size = 1
00199614344d[XHCI ] 0x0000000000116e10: Command Ring: SetAddress TRB (bsr = 0) (addr = 2) (slot = 1) (returning 1)
00199688937d[XHCI ] Command Doorbell Rang

You should send the Set Address command with the BSR (Block) bit set on the first time. You haven't setup the slot yet to allow the device to be addressed. You should send the Set Address command, blocking the request from being sent to the device, configure the slot and the endpoint(s), then send the Set Address command again (BSR = 0) to actually set the address of the device. Note that the address of the device is set by the controller, not your code. The controller will block all standard SET ADDRESS requests. Therefore, do not send the SET ADDRESS request, but send the Set Address Command twice, once with BSR = 1, configure the slot and endpoint(s), and then send it again with BSR = 0.

Without looking at your code, I can't confirm that you are doing this. From the debug output shown, it looks like you may not be sending the Set Address command correctly.

Ben
- http://www.fysnet.net/the_universal_serial_bus.htm

Re: xhci bochs - qemu - real hardware

Posted: Thu Jan 30, 2020 3:55 pm
by SanderR
Hello,

Thank you for your reply.

The speed is not changing its value of -1 whichever value I put in there.
I changed the max packet size to 32.

Yes, I mean the cycle bit.
I noticed with bochs it is used to stop executing and with qemu it is for executing the trb.

Things are a bit unclear to me.

My current configuration is:
Enable slot
SetAddress
Config EP
Getting Descriptor from USB

SetAddress and Config EP are pointing to the same location in my code.

Which steps do I need to take to implement the BSR?
This?
Enable slot
SetAddress (BSR=1)
Config EP
SetAddress (BSR=0)
Getting Descriptor from USB

I tried to change SetAddress (BSR=0) to SetAddress(BSR=1) but this make the Config EP fail. SetAddress and ConfigEP points to the same location. is this an issue?


00110020066i[XHCI ] Reset port #1, type=0
00113546456d[XHCI ] register read from offset 0x0420: 0x0000000000201203 (len=4)
00113693469d[XHCI ] register write to offset 0x0800: 0x0000000000000000 (len=4)
00113693469d[XHCI ] Command Doorbell Rang
00113693469d[XHCI ] Dump command trb: 9(dec) (0x0000000000000000 0x00000000 0x00002400) (0)
00113693469d[XHCI ] 0x0000000000116e00: Command Ring: Found Enable Slot TRB (slot = 1) (returning 1)
00113693469d[XHCI ] register read from offset 0x0620: 0x0000000000000001 (len=1)
00113776138d[XHCI ] register write to offset 0x0800: 0x0000000000000000 (len=4)
00113776138d[XHCI ] Command Doorbell Rang
00113776138d[XHCI ] Dump command trb: 11(dec) (0x00000000000304d0 0x00000000 0x01002E00) (0)
00113776138d[XHCI ] slot_context->int_target = 0, slot_context->max_exit_latency = 0
00113776138d[XHCI ] ep_num = 1, speed = -1, ep_context->max_packet_size = 32
00113776138d[XHCI ] 0x0000000000116e10: Command Ring: SetAddress TRB (bsr = 1) (addr = 0) (slot = 1) (returning 1)
00113776138d[XHCI ] register read from offset 0x0620: 0x0000000000000001 (len=1)
00113850702d[XHCI ] register write to offset 0x0800: 0x0000000000000000 (len=4)
00113850702d[XHCI ] Command Doorbell Rang
00113850702d[XHCI ] Dump command trb: 12(dec) (0x00000000000304d0 0x00000000 0x01003000) (0)
00113850702d[XHCI ] 0x0000000000116e20: Command Ring: Found Config_EP TRB (slot = 1) (returning 19)
00113850702d[XHCI ] register read from offset 0x0620: 0x0000000000000001 (len=1)

git is updated.

Re: xhci bochs - qemu - real hardware

Posted: Thu Jan 30, 2020 6:10 pm
by BenLunt
This is an overview of what you do:
  • Enable Slot. This will return a slot number for you. (Enable Slot Command sent)
  • Initialize the Slot and Control EP. (Host side)
    This is your data that you store on the HOST side.
    Initialize all of the data for the slot and the Control EP
    Set the MaxPacket Size to 8 for Low-speed, 64 for Full- and High-speed, and 512 for Super speed devices.
    (You should have figured out the speed of the device during reset)
  • Set Address Command. BSR = 1. (Set Address Command sent)
    This command expects an INPUT CONTEXT structure in aligned memory.
    It expects the A and D bits to be initialized
    It expects a SLOT CONTEXT to be written
    It expects a CONTROL EP CONTEXT to be written
    You then send the command, with the BSR bit set to 1.
    If this is successful, you can then read back the context memory to store in your HOST side data.
    If this is not successful, you *must* disable the slot (DISABLE SLOT command)
  • Now you can send the GET_DESCRIPTOR request *only requesting the first 8 bytes*.
    As long as that is successful, ignore the data returned *except* for the MaxPacketSize field.
    If not successful, you have done something wrong.
  • Reset the device again.
  • Set Address Command. BSR = 0. (Set Address Command sent)
    This time, use the returned MaxPacketSize field found in the first 8 bytes retrieved above.
  • Now you can send the GET_DESCRIPTOR request, requesting all 18 bytes.
This is the sequence that most devices expect. Yes, other sequences will probably work, but unfortunately, most manufacturers, when testing their devices, tested on a modern-well known OS, and if it worked on that OS, it passed all tests. The above sequence is what this modern-well known OS does.

Ben
- http://www.fysnet.net/the_universal_serial_bus.htm

Re: xhci bochs - qemu - real hardware

Posted: Sat Feb 01, 2020 6:49 am
by SanderR
Thank you for your reply.

So I got the following now:
System detects there is a port attached.
System send ENABLE_SLOT command
System setup the structures like this:

Code: Select all

			//
			//
			// Device Slot Initialisation
			//
			//
			
			printf("[XHCI] Port %x : Device Slot Initialisation BSR1 \n",i);
			
			TRB local_ring_control[20] __attribute__ ((aligned (0x100)));
	
			printf("[XHCI] Port %x : Setting up DCBAAP for port \n",i);
			unsigned long bse = (unsigned long)malloc(0x420);
			btc[(assignedSloth*2)+0] 	= bse;
			btc[(assignedSloth*2)+1] 	= 0;
			
			printf("[XHCI] Port %x : Setting up input controll\n",i);
			unsigned long *t = (unsigned long*)malloc(0x54);
			
			printf("[XHCI] Port %x : Setting up Input Controll Context\n",i);
			// Input Control Context
			t[0x00] = 0;
			t[0x01] = 0;
			t[0x02] = 0;
			t[0x03] = 0;
			
			t[0x01] |= 0b00000000000000000000000000000011 ; // enabling A0 and A1
			
			printf("[XHCI] Port %x : Setting up Slot Context\n",i);
			// Slot(h) Context
			t[0x10] = 0;
			t[0x11] = 0;
			t[0x12] = 0;
			t[0x13] = 0;
			
			t[0x11] |= (1<<16); // Root hub port number
			t[0x10] |= 0; // route string
			t[0x10] |= (1<<27); // context entries 
			
			printf("[XHCI] Port %x : Setting up Endpoint Context\n",i);
			// Endpoint Context
			t[0x20] = 0;
			t[0x21] = 0;
			t[0x22] = 0;
			t[0x23] = 0;
			
			t[0x21] |= (4<<3); // set ep_type to controll
			t[0x21] |= (devicespeed<<16); // set max packet size
			t[0x21] |= (0<<8); // max burst size
			t[0x22] |= (unsigned long)&local_ring_control; // TR dequeue pointer
			t[0x22] |= 1; // dequeue cycle state
			t[0x20] |= (0<<16); // set interval 
			t[0x20] |= (0<<10); // set max primairy streams
			t[0x20] |= (0<<8); // set mult
			t[0x21] |= (3<<1); // set CErr
On BOCHS this succeeds.
On QEMU it fails.
QEMU gives the error code 0x5 back when I send the SET_ADDRESS command.

Code: Select all


int xhci_set_address(unsigned long assignedSloth,unsigned long* t,unsigned char bsr){
	// Address Device Command BSR1
	TRB* trb = ((TRB*)((unsigned long)(&command_ring_control)+command_ring_offset));
	trb->bar1 = (unsigned long)t&0xFFFFFFF0;
	trb->bar2 = 0;
	trb->bar3 = 0;
	trb->bar4 = 0;
	if(deviceid!=XHCI_DEVICE_BOCHS){
		trb->bar4 |= 1; // set cycle bit
	}
	if(bsr){
		trb->bar4 |= (1<<9); // set bsr bit
	}
	trb->bar4 |= (11<<10); // trb type
	trb->bar4 |= (assignedSloth<<24); // assigned sloth
	
	command_ring_offset += 0x10;
	
	// stop codon
	TRB *trb6 = ((TRB*)((unsigned long)(&command_ring_control)+command_ring_offset));
	trb6->bar1 = 0;
	trb6->bar2 = 0;
	trb6->bar3 = 0;
	if(deviceid!=XHCI_DEVICE_BOCHS){
		trb6->bar4 = 0;
	}else{
		trb6->bar4 = 1;
	}
	
	// doorbell
	((unsigned long*)doorbel)[0] = 0;
	
	// wait
	while(1){
		unsigned long r = ((unsigned long*)iman_addr)[0];
		if(r&1){
			break;
		}
	}
	
	// RESULTS
	TRB* trbres2 = ((TRB*)((unsigned long)(&event_ring_queue)+event_ring_offset));
	unsigned long completioncode2 = (trbres2->bar3 & 0b111111100000000000000000000000) >> 24;
	
	event_ring_offset += 0x10;
	return completioncode2;
}

In BOCHS I continue with the attempt to get the first 8 bits of the descriptor.
The system returns nothing in there. So I guess BOCHS makes the same problem as qemu but bochs do not return a error.

For completeness, here is the code for getting the descriptor:

Code: Select all


			printf("[XHCI] Port %x : GET DEVICE DESCRIPTOR\n",i);
			//
			// GET DEVICE DESCRIPTOR
			// trb-type=2
			// trt=3
			// transferlength=8
			// IOC=0
			// IDT=1
			// reqtype= 0x80
			// req=6
			// wValue=0100
			// wIndex=0
			// wLength=0
			//
			
			unsigned char *devicedescriptor = (unsigned char*)malloc(8);
			printf("[XHCI] devicedescriptor located at %x \n",(unsigned long)devicedescriptor);
			TRB *dc1 = ((TRB*)((unsigned long)&local_ring_control));
			dc1->bar1 = 0b00000000000001000000011010000000;
			dc1->bar2 = 0b00000000000000000000000000000000;
			dc1->bar3 = 0b00000000010000000000000000001000;
			dc1->bar4 = 0b00000000000000110000100001000001;
			
			// single date stage
			// TRB Type = Data Stage TRB.
			// X Direction (DIR) = ‘1’.
			// X TRB Transfer Length = 8.
			// X Chain bit (CH) = 0.
			// X Interrupt On Completion (IOC) = 0.
			// X Immediate Data (IDT) = 0.
			// X Data Buffer Pointer = The address of the Device Descriptor receive buffer.
			// X Cycle bit = Current Producer Cycle State.
			TRB *dc2 = ((TRB*)((unsigned long)(&local_ring_control)+0x10));
			dc2->bar1 = (unsigned long)devicedescriptor;
			dc2->bar2 = 0b00000000000000000000000000000000;
			dc2->bar3 = 0b00000000000000000000000000001000;
			dc2->bar4 = 0b00000000000000010000110000000001;
			
			TRB *dc3 = ((TRB*)((unsigned long)(&local_ring_control)+0x20));
			dc3->bar1 = 0;
			dc3->bar2 = 0;
			dc3->bar3 = 0;
			dc3->bar4 = 0;
			
			
			((unsigned long*)doorbel)[assignedSloth] = 1;
			
			while(1){
				unsigned long r = ((unsigned long*)iman_addr)[0];
				if(r&1){
					break;
				}
			}
			
			printf("[XHCI] Port %x : devdesc %x %x %x %x %x %x %x %x \n",i,devicedescriptor[0],devicedescriptor[1],devicedescriptor[2],devicedescriptor[3],devicedescriptor[4],devicedescriptor[5],devicedescriptor[6],devicedescriptor[7]);
			printf("[XHCI] Port %x : deviceclass=%x \n",i,devicedescriptor[4]);
			if(devicedescriptor[4]==0){
				printf("[XHCI] Port %x : Deviceclass cannot be 0! \n",i);
			}else{
				printf("[XHCI] Port %x : Device initialised succesfully\n",i);
			}
			sleep(10000);
I looked at the sourcecode of BOCHS and this output of devicespeed -1 is always given with the first SETADDRESS command.

Re: xhci bochs - qemu - real hardware

Posted: Sat Feb 01, 2020 4:49 pm
by BenLunt
Hi,

Your code is somewhat hard to follow. I would suggest that you have a separate structure for your context(s), one that uses standard integers, dwords, etc. For example:

Code: Select all

struct xHCI_SLOT_CONTEXT {
  unsigned entries;
  bit8u    hub;
  bit8u    mtt;
  unsigned speed;
  ...
You then can easily assign values to members of the context throughout your code. Then you can call a routine that will convert from this structure to the format of the xHCI CONTEXT. You can have another routine to convert it back so that you can read it with some standard sense of source code. It will make it much easier on you.

With the below code, you allocate 84 bytes, correct? If so, why do you write past the end of the allocated buffer with the rest of the code.
SanderR wrote:

Code: Select all

			printf("[XHCI] Port %x : Setting up input controll\n",i);
			unsigned long *t = (unsigned long*)malloc(0x54);
For example, the code below will write to offsets starting at offset 128 of the buffer, well past the end of the memory you allocated.
SanderR wrote:

Code: Select all

			// Endpoint Context
			t[0x20] = 0;
			t[0x21] = 0;
			t[0x22] = 0;
			t[0x23] = 0;
Next: If you are allocating memory for your CONTEXT(s), including the A and D bits, *it must be aligned* on the boundary the controller specifies. An alignment of 4096 is quite common.

Next: Your code is assuming the CONTEXT size is 64 bytes. This may not be the case. The controller will indicate whether it is 32 bytes or 64 bytes in size. This makes the conversion routines I mentioned before much more useful, since they will calculate the correct address to read and write from, depending on the size of a CONTEXT.
SanderR wrote:

Code: Select all

			TRB *dc1 = ((TRB*)((unsigned long)&local_ring_control));
			dc1->bar1 = 0b00000000000001000000011010000000;
			dc1->bar2 = 0b00000000000000000000000000000000;
			dc1->bar3 = 0b00000000010000000000000000001000;
			dc1->bar4 = 0b00000000000000110000100001000001;
Again, it would be much easier to read and understand your code if you make use of the wonderful capabilities of the C language? For example:

Code: Select all

struct xHCI_TRB {
  bit64u param;
  bit32u status;
  bit32u command;
};

#define TRB_SET_SLOT(x)      (((x) & 0xFF) << 24)
#define TRB_SET_TYPE(x)      (((x) & 0x3F) << 10)

  TRB->command = TRB_SET_SLOT(slot_id) | TRB_SET_TYPE(ADDRESS_DEVICE) | (block_it << 9);

  etc.

Ben
- http://www.fysnet.net/osdesign_book_series.htm

Re: xhci bochs - qemu - real hardware

Posted: Fri Feb 07, 2020 3:21 pm
by BenLunt
SanderR,

Just wondering how you are doing on this project. Any progress?

Ben
- http://www.fysnet.net/osdesign_book_series.htm

Re: xhci bochs - qemu - real hardware

Posted: Fri Feb 07, 2020 3:48 pm
by SanderR
Hello Ben,

Thank you for the message,
I was implementing your recommendations and it toke quite a while since I had deadlines at work and had allmost no time to work on it after my normal job.

The system now converts a structure to the right proportions in memory. however it returns me a errorcode 5 when issuing the SETADDRESS command (on bochs it succeed but on qemu it gives a error 5). The code is updated in github now.

Re: xhci bochs - qemu - real hardware

Posted: Fri Feb 07, 2020 5:56 pm
by BenLunt
SanderR wrote:Hello Ben,

Thank you for the message,
I was implementing your recommendations and it toke quite a while since I had deadlines at work and had allmost no time to work on it after my normal job.

The system now converts a structure to the right proportions in memory. however it returns me a errorcode 5 when issuing the SETADDRESS command (on bochs it succeed but on qemu it gives a error 5). The code is updated in github now.
Error 5 is an 'Invalid parameter in the TRB'.
Could be any of the following:
1) Valid Ring with a valid TRB, though this TRB has an invalid parameter. One of the fields within the TRB is not valid, known, or defined as it should be.
2) Valid Ring with no TRB at current pointer.
3) Invalid Ring pointing to garbage.

Since it works in Bochs and not in QEMU, I would start with 1) above. QEMU might do a more thorough check on the TRB. I know Bochs isn't this thorough on the check.

Re: xhci bochs - qemu - real hardware

Posted: Sat Feb 08, 2020 5:59 am
by SanderR
1) I do not understand if you speaking of the TRB that issues the SETADDRESS command or if you speak of the TRB which is inside the ring.
2) To try this I have put a trb (NO-OP) before I issue the SETADDRESS command:

Code: Select all

TRB *trbx = ((TRB*)((unsigned long)(&local_ring_control)));
trbx->bar1 = 0;
trbx->bar2 = 0;
trbx->bar3 = 0;
trbx->bar4 = (8<<10);

Bochs recognised it as a valid TRB.
3) RIng pointing to garbage: I checked this by printing the raw bytes of the trb request on qemu and I was unable to see a error inside the link to the ring. (addr: 0x116E00 pointer with bit 1 set like said in the specification: 0x116E01 )

Code: Select all

printf("[XHCI] Port %x : Setting up Endpoint Context \n",i);
			// Endpoint Context
			XHCI_ENDPOINT_CONTEXT* endpoint_context = (XHCI_ENDPOINT_CONTEXT*)malloc(sizeof(XHCI_ENDPOINT_CONTEXT));
			endpoint_context->endpointtype = 4;
			endpoint_context->maxpstreams = 0;
			endpoint_context->mult = 0;
			endpoint_context->cerr = 3;
			endpoint_context->maxburstsize = 0;
			endpoint_context->maxpacketsize = devicespeed;
			endpoint_context->interval = 0;
			endpoint_context->dequeuepointer = (unsigned long)&local_ring_control;
			endpoint_context->dcs = 1;
			xhci_endpoint_context_to_addr(endpoint_context,t);
			printf("[XHCI] Port %x : local transfer ring points to %x  and trb points to %x \n",i,(unsigned long)&local_ring_control,t[0x20+2]);
Maybe you can see something at the logs?

Code: Select all

[email protected]:usb_xhci_run 
[email protected]:usb_xhci_irq_intx level 0
[email protected]:usb_xhci_oper_read off 0x0004, ret 0x00000000
[email protected]:usb_xhci_oper_read off 0x0000, ret 0x00000005
[email protected]:usb_xhci_port_read port 1, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 1, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 1, warm 0
[email protected]:usb_xhci_port_read port 1, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_read port 2, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 2, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 2, warm 0
[email protected]:usb_xhci_port_read port 2, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_read port 3, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 3, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 3, warm 0
[email protected]:usb_xhci_port_read port 3, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_read port 4, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 4, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 4, warm 0
[email protected]:usb_xhci_port_read port 4, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_read port 5, off 0x0000, ret 0x00020ee1
[email protected]:usb_xhci_doorbell_write off 0x0000, val 0x00000000
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114600, CR_ENABLE_SLOT, p 0x0000000000000000, s 0x00000000, c 0x00002401
[email protected]:usb_xhci_slot_enable slotid 1
[email protected]:usb_xhci_queue_event v 0, idx 0, ER_COMMAND_COMPLETE, CC_SUCCESS, p 0x0000000000114600, s 0x01000000, c 0x01008401
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114610, TRB_RESERVED, p 0x0000000000000000, s 0x00000000, c 0x00000000
[email protected]:usb_xhci_runtime_read off 0x0020, ret 0x00000001
[email protected]:usb_xhci_doorbell_write off 0x0000, val 0x00000000
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114610, CR_ADDRESS_DEVICE, p 0x0000000000116000, s 0x00000000, c 0x01002e01
[email protected]:usb_xhci_queue_event v 0, idx 1, ER_COMMAND_COMPLETE, CC_TRB_ERROR, p 0x0000000000114610, s 0x05000000, c 0x01008401
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114620, TRB_RESERVED, p 0x0000000000000000, s 0x00000000, c 0x00000000
[email protected]:usb_xhci_runtime_read off 0x0020, ret 0x00000001
[email protected]:usb_xhci_doorbell_write off 0x0000, val 0x00000000
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114620, CR_DISABLE_SLOT, p 0x0000000000000000, s 0x00000000, c 0x01002801
[email protected]:usb_xhci_slot_disable slotid 1
[email protected]:usb_xhci_queue_event v 0, idx 2, ER_COMMAND_COMPLETE, CC_SUCCESS, p 0x0000000000114620, s 0x01000000, c 0x01008401
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114630, TRB_RESERVED, p 0x0000000000000000, s 0x00000000, c 0x00000000
[email protected]:usb_xhci_runtime_read off 0x0020, ret 0x00000001
[email protected]:usb_xhci_port_read port 6, off 0x0000, ret 0x00020ee1
[email protected]:usb_xhci_doorbell_write off 0x0000, val 0x00000000
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114630, CR_ENABLE_SLOT, p 0x0000000000000000, s 0x00000000, c 0x00002401
[email protected]:usb_xhci_slot_enable slotid 1
[email protected]:usb_xhci_queue_event v 0, idx 3, ER_COMMAND_COMPLETE, CC_SUCCESS, p 0x0000000000114630, s 0x01000000, c 0x01008401
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114640, TRB_RESERVED, p 0x0000000000000000, s 0x00000000, c 0x00000000
[email protected]:usb_xhci_runtime_read off 0x0020, ret 0x00000001
[email protected]:usb_xhci_doorbell_write off 0x0000, val 0x00000000
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114640, CR_ADDRESS_DEVICE, p 0x0000000000116000, s 0x00000000, c 0x01002e01
[email protected]:usb_xhci_queue_event v 0, idx 4, ER_COMMAND_COMPLETE, CC_TRB_ERROR, p 0x0000000000114640, s 0x05000000, c 0x01008401
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114650, TRB_RESERVED, p 0x0000000000000000, s 0x00000000, c 0x00000000
[email protected]:usb_xhci_runtime_read off 0x0020, ret 0x00000001
[email protected]:usb_xhci_doorbell_write off 0x0000, val 0x00000000
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114650, CR_DISABLE_SLOT, p 0x0000000000000000, s 0x00000000, c 0x01002801
[email protected]:usb_xhci_slot_disable slotid 1
[email protected]:usb_xhci_queue_event v 0, idx 5, ER_COMMAND_COMPLETE, CC_SUCCESS, p 0x0000000000114650, s 0x01000000, c 0x01008401
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114660, TRB_RESERVED, p 0x0000000000000000, s 0x00000000, c 0x00000000
[email protected]:usb_xhci_runtime_read off 0x0020, ret 0x00000001
[email protected]:usb_xhci_port_read port 7, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 7, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 7, warm 0
[email protected]:usb_xhci_port_read port 7, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_read port 8, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_port_write port 8, off 0x0000, val 0x00000210
[email protected]:usb_xhci_port_reset port 8, warm 0
[email protected]:usb_xhci_port_read port 8, off 0x0000, ret 0x000202a0
[email protected]:usb_xhci_oper_read off 0x0018, ret 0x00114600

Code: Select all


00101747351d[XHCI  ] register read from offset 0x0000:  0x0000000000000020 (len=1)
00101783753d[XHCI  ] register read from offset 0x0000:  0x0000000000000020 (len=1)
00101893539d[XHCI  ] register read from offset 0x0002:  0x0000000000000100 (len=4)
00101929519d[XHCI  ] register read from offset 0x0010:  0x000000000140530F (len=4)
00101929519d[XHCI  ] register read from offset 0x0007:  0x0000000000000000 (len=1)
00102039965d[XHCI  ] register read from offset 0x0018:  0x0000000000000600 (len=4)
00102113054d[XHCI  ] register read from offset 0x0014:  0x0000000000000800 (len=4)
00102185666d[XHCI  ] register read from offset 0x0058:  0x0000000000000000 (len=4)
00102222029d[XHCI  ] register read from offset 0x0050:  0x0000000000000000 (len=4)
00102258330d[XHCI  ] register read from offset 0x0038:  0x0000000000000000 (len=4)
00102294682d[XHCI  ] register read from offset 0x0020:  0x0000000000000000 (len=4)
00102330624d[XHCI  ] register read from offset 0x0020:  0x0000000000000000 (len=4)
00102330624d[XHCI  ] register write to  offset 0x0020:  0x0000000000000002 (len=4)
00105621252d[XHCI  ] register read from offset 0x0024:  0x0000000000000001 (len=4)
00105621252d[XHCI  ] register read from offset 0x0020:  0x0000000000000000 (len=4)
00105732910d[XHCI  ] register read from offset 0x0628:  0x0000000000000000 (len=4)
00105732910d[XHCI  ] register write to  offset 0x0628:  0x0000000000000001 (len=4)
00105770329d[XHCI  ] register write to  offset 0x0638:  0x0000000000114400 (len=4)
00105770329d[XHCI  ] register write to  offset 0x063C:  0x0000000000000000 (len=4)
00105808230d[XHCI  ] register write to  offset 0x0630:  0x0000000000115E00 (len=4)
00105808230d[XHCI  ] register write to  offset 0x0634:  0x0000000000000000 (len=4)
00105808230d[XHCI  ] Interrupter 00: Event Ring Table (at 0x0000000000115e00) has 1 entries:
00105808230d[XHCI  ]  00:  address = 0x0000000000114400  Count = 16
00105845362d[XHCI  ] register read from offset 0x0038:  0x0000000000000000 (len=4)
00105845362d[XHCI  ] register write to  offset 0x0038:  0x0000000000114600 (len=4)
00105845362d[XHCI  ] register write to  offset 0x003C:  0x0000000000000000 (len=4)
00105881392d[XHCI  ] register read from offset 0x0050:  0x0000000000000000 (len=4)
00105881392d[XHCI  ] register write to  offset 0x0050:  0x0000000000115F00 (len=4)
00105881392d[XHCI  ] register write to  offset 0x0054:  0x0000000000000000 (len=4)
00105917278d[XHCI  ] register read from offset 0x0020:  0x0000000000000000 (len=4)
00105917278d[XHCI  ] register write to  offset 0x0020:  0x0000000000000004 (len=4)
00109256654d[XHCI  ] register read from offset 0x0020:  0x0000000000000004 (len=4)
00109256654d[XHCI  ] register write to  offset 0x0020:  0x0000000000000005 (len=4)
00112821368d[XHCI  ] register read from offset 0x0024:  0x0000000000000000 (len=4)
00112821368d[XHCI  ] register read from offset 0x0020:  0x0000000000000005 (len=4)
00112931715d[XHCI  ] register read from offset 0x0420:  0x0000000000000000 (len=4)
00112931749d[XHCI  ] register write to  offset 0x0420:  0x0000000000000210 (len=4)
00112931749i[XHCI  ] Reset port #1, type=0
00116421422d[XHCI  ] register read from offset 0x0420:  0x0000000000201203 (len=4)
00116568779d[XHCI  ] register write to  offset 0x0800:  0x0000000000000000 (len=4)
00116568779d[XHCI  ] Command Doorbell Rang
00116568779d[XHCI  ] Dump command trb: 9(dec)  (0x0000000000000000 0x00000000 0x00002400) (0)
00116568779d[XHCI  ] 0x0000000000114600: Command Ring: Found Enable Slot TRB (slot = 1) (returning 1)
00116568779d[XHCI  ] register read from offset 0x0620:  0x0000000000000001 (len=1)
00116874665d[XHCI  ] register write to  offset 0x0800:  0x0000000000000000 (len=4)
00116874665d[XHCI  ] Command Doorbell Rang
00116874665d[XHCI  ] Dump command trb: 11(dec)  (0x0000000000116000 0x00000000 0x01002E00) (0)
00116874665d[XHCI  ]    slot_context->int_target = 0, slot_context->max_exit_latency = 0
00116874665d[XHCI  ]    ep_num = 1, speed = -1, ep_context->max_packet_size = 512
00116874665d[XHCI  ] 0x0000000000114610: Command Ring: SetAddress TRB (bsr = 1) (addr = 0) (slot = 1) (returning 1)
00116874665d[XHCI  ] register read from offset 0x0620:  0x0000000000000001 (len=1)
00116911376d[XHCI  ] register write to  offset 0x0804:  0x0000000000000001 (len=4)
00116911376d[XHCI  ] Rang Doorbell:  slot = 1  ep = 1 (IN)
00116911376d[XHCI  ] Found TRB: address = 0x0000000000116e00 0x0000000000000000 0x00000000 0x00002001  1
00116911376d[XHCI  ] Found TRB: address = 0x0000000000116e00 0x0000000000000000 0x00000000 0x00002001  1 (SPD occurred = 0)
00116911376d[XHCI  ] 0x0000000000116e00: Transfer Ring (slot = 1) (ep = 1): Found No Op TRB
00116911376d[XHCI  ] Process Transfer Ring: Processed 1 TRB's
00116911376d[XHCI  ] register read from offset 0x0620:  0x0000000000000001 (len=1)
00116948146d[XHCI  ] register write to  offset 0x0804:  0x0000000000000001 (len=4)
00116948146d[XHCI  ] Rang Doorbell:  slot = 1  ep = 1 (IN)
00116948146d[XHCI  ] Found TRB: address = 0x0000000000116e10 0x0000000000040680 0x00400008 0x00030841  1
00116948146d[XHCI  ] Found TRB: address = 0x0000000000116e10 0x0000000000040680 0x00400008 0x00030841  1 (SPD occurred = 0)
00116948146d[XHCI  ] 0x0000000000116e10: Transfer Ring (slot = 1) (ep = 1) (len = 8): Found SETUP TRB
00116948146e[USBMSD] USB MSD handle_control: unknown descriptor type 0x00
00116948146d[XHCI  ] OUT: Transferred 8 bytes (ret = -3)
00116948146d[XHCI  ] Process Transfer Ring: Processed 1 TRB's
00116948146d[XHCI  ] register read from offset 0x0620:  0x0000000000000001 (len=1)
00117094866d[XHCI  ] register write to  offset 0x0800:  0x0000000000000000 (len=4)
00117094866d[XHCI  ] Command Doorbell Rang
00117094866d[XHCI  ] Dump command trb: 10(dec)  (0x0000000000000000 0x00000000 0x01002800) (0)
00117094866d[XHCI  ] 0x0000000000114620: Command Ring: Found Disable Slot TRB (slot = 1) (returning 1)
00117094898d[XHCI  ] register read from offset 0x0620:  0x0000000000000001 (len=1)
00117094918d[XHCI  ] register read from offset 0x0430:  0x0000000000000000 (len=4)
00117094918d[XHCI  ] register write to  offset 0x0430:  0x0000000000000210 (len=4)
00117094918i[XHCI  ] Reset port #2, type=0
00120021474d[XHCI  ] register read from offset 0x0430:  0x00000000000002A0 (len=4)
00120058021d[XHCI  ] register read from offset 0x0440:  0x0000000000000000 (len=4)
00120058021d[XHCI  ] register write to  offset 0x0440:  0x0000000000000210 (len=4)
00120058021i[XHCI  ] Reset port #3, type=0
00123621534d[XHCI  ] register read from offset 0x0440:  0x00000000000002A0 (len=4)
00123658079d[XHCI  ] register read from offset 0x0450:  0x0000000000000000 (len=4)
00123658079d[XHCI  ] register write to  offset 0x0450:  0x0000000000000210 (len=4)
00123658079i[XHCI  ] Reset port #4, type=0
00127221594d[XHCI  ] register read from offset 0x0450:  0x00000000000002A0 (len=4)
00127258139e[XHCI  ] register read from unknown offset 0x00000460:  0x0000000000000000 (len=4)
00127258139d[XHCI  ] register read from offset 0x0460:  0x0000000000000000 (len=4)
00127258139d[XHCI  ] register write to  offset 0x0460:  0x0000000000000210 (len=4)
00127258139e[XHCI  ] register write to unknown offset 0x00000460:  0x0000000000000210 (len=4)
00130821645e[XHCI  ] register read from unknown offset 0x00000460:  0x0000000000000000 (len=4)
00130821645d[XHCI  ] register read from offset 0x0460:  0x0000000000000000 (len=4)
00130821652d[XHCI  ] register read from offset 0x0038:  0x0000000000000008 (len=4)
02548576000p[XGUI  ] >>PANIC<< POWER button turned off.

Re: xhci bochs - qemu - real hardware

Posted: Sat Feb 08, 2020 8:56 am
by linuxyne
It is possible to enable the DEBUG_XHCI flag if one is willing to compile qemu. That will enable the DPRINTFs that should show more info.

Code: Select all

./configure --prefix=/path/to/an/empty/folder --target-list=x86_64-softmmu --extra-cflags=-DDEBUG_XHCI
make -j5 && make install
I ran your cdrom.iso using the following commandline:

Code: Select all

./qemu-system-x86_64 -cdrom cdrom.iso -device qemu-xhci,id=xhci -drive if=none,id=usbstick,file=cdrom.iso -device usb-storage,bus=xhci.0,drive=usbstick &> output.txt
I closed qemu once 'Local ring not defined as it should be' message was printed on the screen. The output.txt file can be found here.

Below likely shows where qemu had troubles. You can match these lines with qemu's function xhci_address_slot:

Code: Select all

xhci: input context at 116000
xhci: output context at 300b0
xhci: input slot context: 00000000 00000000 00000000 00000000
xhci: input ep0 context: 08000000 00010000 00000000 00000000 00000000
xhci: port not found

Re: xhci bochs - qemu - real hardware

Posted: Sun Feb 09, 2020 4:28 pm
by SanderR
I finished building qemu as instructed.
I found the problem and now the system is accepting SET_ADDRESS on qemu and BOCHS.

somehow it has now troubles finding the ring in bochs and qemu since they do not accept my commands so far.

Re: xhci bochs - qemu - real hardware

Posted: Sun Feb 09, 2020 7:54 pm
by linuxyne
The trace-events and DPRINTFs point to a likely cause - a NOOP instead of SETUP:

Code: Select all

[email protected]:usb_xhci_fetch_trb addr 0x0000000000115e00, TR_NOOP, p 0x0000000000000000, s 0x00000000, c 0x00002001
[email protected]:usb_xhci_xfer_start 0x7f2e7c0aa4b0: slotid 1, epid 1, streamid 0
xhci: ep0 first TD not SETUP: 8
You can also add your own DPRINTFs into qemu's source at appropriate locations to trace particular code-paths or variables.

Edit: Included fetch trace event.

Re: xhci bochs - qemu - real hardware

Posted: Wed Feb 12, 2020 1:39 pm
by SanderR
So I tried to put this setup TRB inside the queue.
Qemu does not seem to recognize it.
Qemu is increasing the pointer with 1 byte and that is it.

Code: Select all


			unsigned long lrcoffset = 0;
			if(0){
				printf("[XHCI] Port %x : NOOP ring control\n",i);
				TRB *trbx = ((TRB*)((unsigned long)(&local_ring_control)+lrcoffset));
				trbx->bar1 = 0;
				trbx->bar2 = 0;
				trbx->bar3 = 0;
				trbx->bar4 = (8<<10) | 0b01;
				lrcoffset += 0x10;
			}
			
			printf("[XHCI] Port %x : GET DEVICE DESCRIPTOR\n",i);
			//
			// GET DEVICE DESCRIPTOR
			// trb-type=2
			// trt=3
			// transferlength=8
			// IOC=0
			// IDT=1
			// reqtype= 0x80
			// req=6
			// wValue=0100
			// wIndex=0
			// wLength=0
			//
			
			unsigned char *devicedescriptor = (unsigned char*)malloc(8);
			TRB *dc1 = ((TRB*)((unsigned long*)(&local_ring_control)+lrcoffset));
			dc1->bar1 = 0;
			dc1->bar2 = 0;
			dc1->bar3 = 0;
			dc1->bar4 = 0;
			
			dc1->bar1 |= 0x80; // reqtype=0x80
			dc1->bar1 |= (6<<8); // req=6
			dc1->bar1 |= (0x100 << 16); // wValue = 0100
			dc1->bar2 |= 0; // windex=0
			dc1->bar2 |= (0 << 16); // wlength=0
			dc1->bar3 |= 8; // trbtransferlength
			dc1->bar3 |= (0 << 22); // interrupetertrager
			dc1->bar4 |= 1; // cyclebit
			dc1->bar4 |= (00<<5); // ioc=0
			dc1->bar4 |= (1<<6); // idt=1
			dc1->bar4 |= (2<<10); // trbtype
			dc1->bar4 |= (3<<16); // trt = 3;
			lrcoffset += 0x10;
			
			// single date stage
			// TRB Type = Data Stage TRB.
			// X Direction (DIR) = ‘1’.
			// X TRB Transfer Length = 8.
			// X Chain bit (CH) = 0.
			// X Interrupt On Completion (IOC) = 0.
			// X Immediate Data (IDT) = 0.
			// X Data Buffer Pointer = The address of the Device Descriptor receive buffer.
			// X Cycle bit = Current Producer Cycle State.
			TRB *dc2 = ((TRB*)((unsigned long)(&local_ring_control)+lrcoffset));
			dc2->bar1 = (unsigned long)devicedescriptor;
			dc2->bar2 = 0b00000000000000000000000000000000;
			dc2->bar3 = 0b00000000000000000000000000001000;
			dc2->bar4 = 0b00000000000000010000110000000000;
			lrcoffset+=0x10;
			
			((unsigned long*)doorbel)[assignedSloth] = 1;
			
			while(1){
				unsigned long r = ((unsigned long*)iman_addr)[0];
				if(r&1){
					break;
				}
			}
			
			printf("[XHCI] Port %x : devdesc %x %x %x %x %x %x %x %x \n",i,devicedescriptor[0],devicedescriptor[1],devicedescriptor[2],devicedescriptor[3],devicedescriptor[4],devicedescriptor[5],devicedescriptor[6],devicedescriptor[7]);
			printf("[XHCI] Port %x : deviceclass=%x \n",i,devicedescriptor[4]);
			if(devicedescriptor[4]==0){
				printf("[XHCI] Port %x : Deviceclass cannot be 0! \n",i);
				goto disabledevice;
			}else{
				printf("[XHCI] Port %x : Device initialised succesfully\n",i);
			}
			sleep(10000);
			
			continue;
qemu logs:

(completion of SET_ADDRESS)

Code: Select all

[email protected]:usb_xhci_queue_event v 0, idx 1, ER_COMMAND_COMPLETE, CC_SUCCESS, p 0x0000000000114610, s 0x01000000, c 0x01008401
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114620, TRB_RESERVED, p 0x0000000000000000, s 0x00000000, c 0x00000000
[email protected]:usb_xhci_runtime_read off 0x0020, ret 0x00000001
[email protected]:usb_xhci_doorbell_write off 0x0004, val 0x00000001
[email protected]:usb_xhci_ep_kick slotid 1, epid 1, streamid 0
xhci: set epctx: 300d0 state=1 dequeue=0000000000115e01
[email protected]:usb_xhci_runtime_read off 0x0020, ret 0x00000001
[email protected]:usb_xhci_doorbell_write off 0x0000, val 0x00000000
xhci_process_commands()
[email protected]:usb_xhci_fetch_trb addr 0x0000000000114620, CR_DISABLE_SLOT, p 0x0000000000000000, s 0x00000000, c 0x01002801
(ISSUING OF DISABLE_SLOT)