Page 1 of 1

Bochs OHCI stalls and stops after I mess around with STATUS

Posted: Wed Feb 01, 2023 5:42 pm
by sounds
I was reading here: viewtopic.php?p=317896#p317896
BenLunt wrote:This is not exactly the case. If the stall is on the Control Pipe, you don't necessarily ignore it. The stall remains until the next SETUP packet is found. Since the Control Pipe uses SETUP packets almost exclusively, then an ignore of the stall is almost correct. However, if the stall happens during an IN or OUT packet, you still need to remove the remaining scheduled packets before you sent the next SETUP packet.
I decided to add more cases to my OHCI tests and Bochs' OHCI controller did something unexpected. Ben wrote the OHCI code in Bochs, so I'm hoping this turns out to be something easy -

First, this is the log when things are working. (I added comments starting with ";")

Code: Select all

rh_rst            ; detected device connection status change
rh_~rst: 50ms     ; port reset bit cleared. wait 50ms
hdr 80,6,0,1:0 8  ; GET_DEVICE_DESCRIPTOR len=8
HcControl = bf
HcCommandStatus = 0
td0 phys=5208220  ; submit ED and TDs
td[0].nxt=5208560 inf=f2000000 buf=52082e0 end=52082e7 td=373f49008220
td[1].nxt=5208570 inf=f2100000 buf=52082e8 end=52082ef td=373f49008550
td[2].nxt=5208300 inf=f3080000 buf=52082f0 end=52082ef
TD[0] inf=3000000 buf=0 end=52082e7 ; dump contents of TDs after WDH
TD[1] inf=3100000 buf=0 end=52082ef
TD[2] inf=2080000 buf=0 end=52082ef
rh_rst            ; assert another port reset
rh_~rst: 50ms     ; port reset bit cleared. wait 50ms
hdr 80,6,0,1:0 12 ; GET_DEVICE_DESCRIPTOR len=18==0x12
HcControl = bf
HcCommandStatus = 0
td0 phys=5208300  ; submit ED and TDs
td[0].nxt=52085a0 inf=f2000000 buf=5208560 end=5208567 td=373f49008300
td[1].nxt=52085b0 inf=f2100000 buf=5208568 end=520856f td=373f49008590
td[2].nxt=52085c0 inf=f2100000 buf=5208570 end=5208577 td=373f49008590
td[3].nxt=52085d0 inf=f2100000 buf=5208578 end=5208579 td=373f49008590
td[4].nxt=52082e0 inf=f3080000 buf=520857a end=5208579
TD[0] inf=3000000 buf=0 end=5208567 ; dump contents of TDs after WDH
TD[1] inf=3100000 buf=0 end=520856f
TD[2] inf=3100000 buf=0 end=5208577
TD[3] inf=3100000 buf=0 end=5208579
TD[4] inf=2080000 buf=0 end=5208579
DEVICE_DESCRIPTOR: 12 1 10 1 0 0 0 8 b4 4 1 1 1 0 1 2 3 1
hdr 0,5,1,0:0 0   ; SET_ADDRESS len=0
td0 phys=52082e0
td[0].nxt=5208320 inf=f2000000 buf=5208300 end=5208307 td=373f490082e0
td[1].nxt=5208220 inf=f3080000 buf=5208308 end=5208307
TD[0] inf=3000000 buf=0 end=5208307
TD[1] inf=2080000 buf=0 end=5208307
Ok, now I'm going to intentionally cause a stall. I do it by setting td[2].end to == td[2].buf, which is 1 more than what it should be. It's the STATUS packet, so the pipe will stall because a STATUS packet's length should be 0 but it's 1 here:

Code: Select all

rh_rst
rh_~rst: 50ms
hdr 80,6,0,1:0 8
HcControl = bf
HcCommandStatus = 0
td0 phys=fa08220
td[0].nxt=fa08560 inf=f2000000 buf=fa082e0 end=fa082e7 td=ffff959ba8e08220
td[1].nxt=fa08570 inf=f2100000 buf=fa082e8 end=fa082ef td=ffff959ba8e08550
td[2].nxt=fa08300 inf=f3080000 buf=fa082f0 end=fa082f0
TD[0] inf=3000000 buf=0 end=fa082e7
TD[1] inf=3100000 buf=0 end=fa082ef
TD[2] inf=4e080000 buf=fa082f0 end=fa082f0 *stall bit set*
rh_rst
rh_~rst: 50ms
hdr 80,6,0,1:0 12
HcControl = bf
HcCommandStatus = 0
td0 phys=fa08300
td[0].nxt=fa085a0 inf=f2000000 buf=fa08560 end=fa08567 td=ffff959ba8e08300
td[1].nxt=fa085b0 inf=f2100000 buf=fa08568 end=fa0856f td=ffff959ba8e08590
td[2].nxt=fa085c0 inf=f2100000 buf=fa08570 end=fa08577 td=ffff959ba8e08590
td[3].nxt=fa085d0 inf=f2100000 buf=fa08578 end=fa08579 td=ffff959ba8e08590
td[4].nxt=fa082e0 inf=f3080000 buf=fa0857a end=fa0857a
*timeout*
And here's the Bochs log: Notice ret = -3 (that's the stall)

Code: Select all

00023061352 d [OHCI  ] read  PCI register 0x04 value 0x0006 (len=2)
00023061368 d [OHCI  ] write PCI register 0x04 value 0x0006 (len=2)
00023271051 i [OHCI  ] Ben: BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.psm == 1
00023395301 d [OHCI  ] read  PCI register 0x3C value 0x09 (len=1)
00023395326 d [OHCI  ] read  PCI register 0x04 value 0x0006 (len=2)
00023571000 d [OHCI  ] Found a valid ED that points to an control/bulk/int TD
00023571000 d [OHCI  ] Head: 0x0FA08220  Tail: 0x0FA08300  Next: 0x0FA08560
00023571000 d [OHCI  ]     pid = SETUP  addr = 0   endpnt = 0    len = 8  mps = 8 (td->cbp = 0x0FA082E0, td->be = 0x0FA0
82E7)
00023571000 d [OHCI  ]     td->t = 2  ed->c = 0  td->di = 0  td->r = 0
00023571000 d [OHCI  ]  td->cbp = 0x00000000   ret = 8  len = 8  td->cc = 0   td->ec = 0  ed->h = 0
00023571000 d [OHCI  ]     td->t = 3  ed->c = 1
00023571000 d [OHCI  ] Head: 0x0FA08560  Tail: 0x0FA08300  Next: 0x0FA08570
00023571000 d [OHCI  ]     pid = IN  addr = 0   endpnt = 0    len = 8  mps = 8 (td->cbp = 0x0FA082E8, td->be = 0x0FA082E
F)
00023571000 d [OHCI  ]     td->t = 2  ed->c = 1  td->di = 0  td->r = 0
00023571000 d [OHCI  ]  td->cbp = 0x00000000   ret = 8  len = 8  td->cc = 0   td->ec = 0  ed->h = 0
00023571000 d [OHCI  ]     td->t = 3  ed->c = 1
00023571000 d [OHCI  ] Head: 0x0FA08570  Tail: 0x0FA08300  Next: 0x0FA08300
00023571000 d [OHCI  ]     pid = OUT  addr = 0   endpnt = 0    len = 1  mps = 8 (td->cbp = 0x0FA082F0, td->be = 0x0FA082F0)
00023571000 d [OHCI  ]     td->t = 3  ed->c = 1  td->di = 0  td->r = 0
00023571000 d [OHCI  ]  td->cbp = 0x0FA082F0   ret = 0  len = 1  td->cc = 15   td->ec = 0  ed->h = 0
00023571000 d [OHCI  ]     td->t = 2  ed->c = 0
00023571000 d [OHCI  ] Head: 0x0FA08570  Tail: 0x0FA08300  Next: 0x0FA08300
00023571000 d [OHCI  ]     pid = OUT  addr = 0   endpnt = 0    len = 1  mps = 8 (td->cbp = 0x0FA082F0, td->be = 0x0FA082F0)
00023571000 d [OHCI  ]     td->t = 2  ed->c = 0  td->di = 0  td->r = 0
00023571000 d [OHCI  ]  td->cbp = 0x0FA082F0   ret = -3  len = 1  td->cc = 4   td->ec = 3  ed->h = 1
00023571000 d [OHCI  ]     td->t = 2  ed->c = 0
00023574000 d [OHCI  ] done_count = 0, status.wdh = 0
00023574000 d [OHCI  ] Updating the hcca.DoneHead field to 0x0FA08570 and setting the wdh flag
00023577000 d [OHCI  ] done_count = 7, status.wdh = 1
00023580000 d [OHCI  ] done_count = 7, status.wdh = 1
00023583000 d [OHCI  ] done_count = 7, status.wdh = 1
00023577000 d [OHCI  ] done_count = 7, status.wdh = 0
The Bochs ohci controler seems to not reset when a SETUP TD is written to the ED. Since the stall is on a Control Pipe, and I am also resetting the port before enqueueing the next SETUP packet, I wonder why?

Re: Bochs OCHI stalls and stops after I mess around with STA

Posted: Wed Feb 01, 2023 7:18 pm
by BenLunt
First, I am pleased that there are a few people working on their USB code. It is interesting to see the work, and of course the comments. Thanks.

Now, for the answer.

I didn't write any Stall handling code in the OHCI. I wasn't expecting anyone to intentionally cause a stall. :-)

Anyway, I am currently working on the USB emulation in Bochs, so if you have a (smallish) bootable hard drive image that you can share, that intentionally creates the stall you show, I will see what I can do to add function to the OHCI code to handle the stall.

Thank you,
Ben

Re: Bochs OHCI stalls and stops after I mess around with STA

Posted: Thu Feb 02, 2023 1:54 pm
by sounds
That'd probably be fine. I've sent a PM with some questions.