Skip to content

Commit

Permalink
Remerge Fix OHCI Toggle function (#82)
Browse files Browse the repository at this point in the history
This fixes the toggle bit check in the OHCI.
Tested Guests: WinXP, Win7
Tested devices: HID, HUB, DISK, CD-ROM
  • Loading branch information
Stanislav Shwartsman committed Oct 7, 2023
1 parent 6307786 commit d4eea1d
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 12 deletions.
30 changes: 19 additions & 11 deletions bochs/iodev/usb/usb_ohci.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,7 @@ void bx_usb_ohci_c::process_lists(void)
bool bx_usb_ohci_c::process_ed(struct OHCI_ED *ed, const Bit32u ed_address)
{
struct OHCI_TD cur_td;
int toggle;
bool ret = 0;

if (!ED_GET_H(ed) && !ED_GET_K(ed) && (ED_GET_HEADP(ed) != ED_GET_TAILP(ed))) {
Expand All @@ -1171,12 +1172,20 @@ bool bx_usb_ohci_c::process_ed(struct OHCI_ED *ed, const Bit32u ed_address)
BX_DEBUG(("Found a valid ED that points to an control/bulk/int TD"));
ret = 1;
while (ED_GET_HEADP(ed) != ED_GET_TAILP(ed)) {
toggle = ED_GET_C(ed);
DEV_MEM_READ_PHYSICAL(ED_GET_HEADP(ed), 4, (Bit8u*) &cur_td.dword0);
DEV_MEM_READ_PHYSICAL(ED_GET_HEADP(ed) + 4, 4, (Bit8u*) &cur_td.dword1);
DEV_MEM_READ_PHYSICAL(ED_GET_HEADP(ed) + 8, 4, (Bit8u*) &cur_td.dword2);
DEV_MEM_READ_PHYSICAL(ED_GET_HEADP(ed) + 12, 4, (Bit8u*) &cur_td.dword3);
BX_DEBUG(("Head: 0x%08X Tail: 0x%08X Next: 0x%08X", ED_GET_HEADP(ed), ED_GET_TAILP(ed), TD_GET_NEXTTD(&cur_td)));
if (process_td(&cur_td, ed)) {
if (TD_GET_T(&cur_td) & 2)
toggle = TD_GET_T(&cur_td) & 1;
int td_ret = process_td(&cur_td, ed, toggle);
if (td_ret == 0) {
// USB_RET_ASYNC or already processed TD, so done with ED (for now)
break;
} else if (td_ret > 0) {
// Processed TD with no error
const Bit32u temp = ED_GET_HEADP(ed);
if (TD_GET_CC(&cur_td) < NotAccessed) {
ED_SET_HEADP(ed, TD_GET_NEXTTD(&cur_td));
Expand All @@ -1185,11 +1194,15 @@ bool bx_usb_ohci_c::process_ed(struct OHCI_ED *ed, const Bit32u ed_address)
if (TD_GET_DI(&cur_td) < BX_OHCI_THIS hub.ohci_done_count)
BX_OHCI_THIS hub.ohci_done_count = TD_GET_DI(&cur_td);
}
ED_SET_C(ed, toggle ^ 1);
DEV_MEM_WRITE_PHYSICAL(temp, 4, (Bit8u*) &cur_td.dword0);
DEV_MEM_WRITE_PHYSICAL(temp + 4, 4, (Bit8u*) &cur_td.dword1);
DEV_MEM_WRITE_PHYSICAL(temp + 8, 4, (Bit8u*) &cur_td.dword2);
} else
} else {
// Processed TD with error, advance the toggle anyway
ED_SET_C(ed, toggle ^ 1);
break;
}
}
}
DEV_MEM_WRITE_PHYSICAL(ed_address + 8, 4, (Bit8u*) &ed->dword2);
Expand Down Expand Up @@ -1252,10 +1265,10 @@ int bx_usb_ohci_c::event_handler(int event, void *ptr, int port)
return ret;
}

bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
int bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed, int toggle)
{
unsigned pid = 0, len = 0, len1, len2;
bool ret2 = 1;
int ret2 = 1;
int ilen, ret = 0;
Bit32u addr;
Bit16u maxlen = 0;
Expand Down Expand Up @@ -1320,7 +1333,7 @@ bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
p->packet.devep = ED_GET_EN(ed);
p->packet.speed = ED_GET_S(ed) ? USB_SPEED_LOW : USB_SPEED_FULL;
#if HANDLE_TOGGLE_CONTROL
p->packet.toggle = (TD_GET_T(td) & 2) ? ((TD_GET_T(td) & 1) > 0) : (ED_GET_C(ed) > 0);
p->packet.toggle = toggle;
#endif
p->packet.complete_cb = ohci_event_handler;
p->packet.complete_dev = this;
Expand Down Expand Up @@ -1383,11 +1396,6 @@ bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
TD_SET_CBP(td, TD_GET_CBP(td) + ret);
}
}
if (TD_GET_T(td) & 2) {
TD_SET_T(td, TD_GET_T(td) ^ 1);
ED_SET_C(ed, (TD_GET_T(td) & 1));
} else
ED_SET_C(ed, (ED_GET_C(ed) ^ 1));
if ((pid != USB_TOKEN_OUT) || (ret == (int) len)) {
TD_SET_CC(td, NoError);
TD_SET_EC(td, 0);
Expand All @@ -1401,7 +1409,6 @@ bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
TD_SET_CC(td, DeviceNotResponding);
break;
case USB_RET_NAK: // (-2)
ret2 = 0;
break;
case USB_RET_STALL: // (-3)
TD_SET_CC(td, Stall);
Expand All @@ -1413,6 +1420,7 @@ bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed)
BX_ERROR(("Unknown error returned: %d", ret));
break;
}
ret2 = ret;
}
if (ret != USB_RET_NAK) {
TD_SET_EC(td, 3);
Expand Down
2 changes: 1 addition & 1 deletion bochs/iodev/usb/usb_ohci.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ class bx_usb_ohci_c : public bx_pci_device_c {

void process_lists();
bool process_ed(struct OHCI_ED *, const Bit32u);
bool process_td(struct OHCI_TD *, struct OHCI_ED *);
int process_td(struct OHCI_TD *, struct OHCI_ED *, int);

#if BX_USE_USB_OHCI_SMF
static bool read_handler(bx_phy_address addr, unsigned len, void *data, void *param);
Expand Down

0 comments on commit d4eea1d

Please sign in to comment.