Skip to content

Commit

Permalink
Rewrite of the host controller side of the USB debugger support.
Browse files Browse the repository at this point in the history
  • Loading branch information
vruppert committed Jun 16, 2024
1 parent 4f39404 commit 67e4e12
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 137 deletions.
29 changes: 29 additions & 0 deletions bochs/gui/siminterface.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#include "iodev.h"
#include "bx_debug/debug.h"
#include "virt_timer.h"
#if BX_USE_WIN32USBDEBUG
#include "gui/win32usb.h"
#endif

bx_simulator_interface_c *SIM = NULL;
logfunctions *siminterface_log = NULL;
Expand Down Expand Up @@ -70,6 +73,7 @@ class bx_real_sim_c : public bx_simulator_interface_c {
config_interface_callback_t ci_callback;
void *ci_callback_data;
#if BX_USE_WIN32USBDEBUG
int usb_debug_type;
usb_interface_callback_t usbi_callback;
#endif
rt_conf_entry_t *rt_conf_entries;
Expand Down Expand Up @@ -180,6 +184,8 @@ class bx_real_sim_c : public bx_simulator_interface_c {
void *userdata);
virtual int configuration_interface(const char* name, ci_command_t command);
#if BX_USE_WIN32USBDEBUG
virtual void register_usb_debug_type(int type);
virtual void usb_debug_trigger(int type, int trigger, int wParam, int lParam);
virtual void register_usb_interface(usb_interface_callback_t callback, void *data);
virtual int usb_config_interface(int type, int wParam, int lParam);
#endif
Expand Down Expand Up @@ -390,6 +396,7 @@ bx_real_sim_c::bx_real_sim_c()
ci_callback = NULL;
ci_callback_data = NULL;
#if BX_USE_WIN32USBDEBUG
usb_debug_type = 0;
usbi_callback = NULL;
#endif
is_sim_thread_func = NULL;
Expand Down Expand Up @@ -943,6 +950,28 @@ int bx_real_sim_c::configuration_interface(const char *ignore, ci_command_t comm
}

#if BX_USE_WIN32USBDEBUG
void bx_real_sim_c::register_usb_debug_type(int type)
{
if (type != USB_DEBUG_NONE) {
if ((type != USB_DEBUG_UHCI) && (type != USB_DEBUG_XHCI)) {
BX_PANIC(("USB debugger does not yet support type %d", type));
} else {
usb_debug_type = type;
}
}
}

void bx_real_sim_c::usb_debug_trigger(int type, int trigger, int wParam, int lParam)
{
if (type != USB_DEBUG_NONE) {
if (type == usb_debug_type) {
win32_usb_trigger(type, trigger, wParam, lParam);
} else {
BX_PANIC(("USB debugger triggered with wrong type %d", type));
}
}
}

void bx_real_sim_c::register_usb_interface(usb_interface_callback_t callback, void *data)
{
usbi_callback = callback;
Expand Down
2 changes: 2 additions & 0 deletions bochs/gui/siminterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,8 @@ class BOCHSAPI bx_simulator_interface_c {
void *userdata) {}
virtual int configuration_interface(const char* name, ci_command_t command) {return -1; }
#if BX_USE_WIN32USBDEBUG
virtual void register_usb_debug_type(int type) {}
virtual void usb_debug_trigger(int type, int trigger, int wParam, int lParam) {}
virtual void register_usb_interface(usb_interface_callback_t callback, void *data) {}
virtual int usb_config_interface(int type, int wParam, int lParam) { return -1; }
#endif
Expand Down
2 changes: 1 addition & 1 deletion bochs/gui/win32usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ BOCHSAPI_MSVCONLY int win32_usb_start(HWND hwnd, int break_type, int wParam, int
#define USB_DEBUG_RESET 5
#define USB_DEBUG_ENABLE 6

BOCHSAPI_MSVCONLY void win32_usb_trigger(int type, int trigger, int wParam, int lParam);
void win32_usb_trigger(int type, int trigger, int wParam, int lParam);

// lParam flags
#define USB_LPARAM_FLAG_BEFORE 0x00000001
Expand Down
14 changes: 7 additions & 7 deletions bochs/iodev/usb/ohci_core.cc
Original file line number Diff line number Diff line change
Expand Up @@ -804,21 +804,21 @@ bool bx_ohci_core_c::mem_write(bx_phy_address addr, unsigned len, void *data)
case 0x60: // HcRhPortStatus[3]
#if (USB_OHCI_PORTS < 4)
#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0);
SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0);
#endif
break;
#endif
case 0x5C: // HcRhPortStatus[2]
#if (USB_OHCI_PORTS < 3)
#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0);
SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0);
#endif
break;
#endif
case 0x58: // HcRhPortStatus[1]
#if (USB_OHCI_PORTS < 2)
#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0);
SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_NONEXIST, 0, 0);
#endif
break;
#endif
Expand All @@ -833,7 +833,7 @@ bool bx_ohci_core_c::mem_write(bx_phy_address addr, unsigned len, void *data)
hub.usb_port[p].HcRhPortStatus.csc = 1;
else {
#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_ENABLE, 0, 0);
SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_ENABLE, 0, 0);
#endif
hub.usb_port[p].HcRhPortStatus.pes = 1;
}
Expand All @@ -852,7 +852,7 @@ bool bx_ohci_core_c::mem_write(bx_phy_address addr, unsigned len, void *data)
hub.usb_port[p].HcRhPortStatus.csc = 1;
else {
#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_RESET, 0, 0);
SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_RESET, 0, 0);
#endif
reset_port(p);
hub.usb_port[p].HcRhPortStatus.pps = 1;
Expand Down Expand Up @@ -922,7 +922,7 @@ void bx_ohci_core_c::ohci_timer(void)

if (hub.op_regs.HcControl.hcfs == OHCI_USB_OPERATIONAL) {
#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_FRAME, 0, 0);
SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_FRAME, 0, 0);
#endif
// set remaining to the interval amount.
hub.op_regs.HcFmRemainingToggle = hub.op_regs.HcFmInterval.fit;
Expand Down Expand Up @@ -1164,7 +1164,7 @@ int bx_ohci_core_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed, int toggl
}

#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_OHCI, USB_DEBUG_COMMAND, 0, 0);
SIM->usb_debug_trigger(USB_DEBUG_OHCI, USB_DEBUG_COMMAND, 0, 0);
#endif

// The td->cc field should be 111x if it hasn't been processed yet.
Expand Down
60 changes: 30 additions & 30 deletions bochs/iodev/usb/uhci_core.cc
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len)
case 0x00: // command register (16-bit) (R/W)
if (value & 0xFF00)
BX_DEBUG(("write to command register with bits 15:8 not zero: 0x%04x", value));

hub.usb_command.max_packet_size = (value & 0x80) ? 1: 0;
hub.usb_command.configured = (value & 0x40) ? 1: 0;
hub.usb_command.debug = (value & 0x20) ? 1: 0;
Expand Down Expand Up @@ -520,7 +520,7 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len)
BX_ERROR(("write to non existent offset 0x14 (port #3)"));
#if BX_USE_WIN32USBDEBUG
// Non existant Register Port (the next one after the last)
win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_NONEXIST, 0, 0);
SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_NONEXIST, 0, 0);
#endif
break;

Expand All @@ -533,7 +533,7 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len)
break;
#if BX_USE_WIN32USBDEBUG
if ((value & (1 << 9)) && !hub.usb_port[port].reset)
win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_RESET, port, 0);
SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_RESET, port, 0);
#endif
if (value & ((1<<5) | (1<<4) | (1<<0)))
BX_DEBUG(("write to one or more read-only bits in port #%d register: 0x%04x", port+1, value));
Expand Down Expand Up @@ -561,7 +561,7 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len)
hub.usb_port[port].resume = (value & (1<<6)) ? 1 : 0;
if (!hub.usb_port[port].enabled && (value & (1<<2))) {
#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_ENABLE, port, 0);
SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_ENABLE, port, 0);
#endif
hub.usb_port[port].enable_changed = 0;
} else
Expand Down Expand Up @@ -611,7 +611,7 @@ void bx_uhci_core_c::uhci_timer_handler(void *this_ptr)
// we can loop indefinitely, never ending the 1ms frame.
// Therefore, we save a list of queue heads we execute, possibly updating to the
// next queue head when a loop is found.
//
//
// Let's try to add this queue's address to our stack of processed queues.
// if the queue has already been processed, it will be in this list (return TRUE)
// if the queue has not been processed yet, return FALSE
Expand All @@ -637,15 +637,15 @@ bool bx_uhci_core_c::uhci_add_queue(struct USB_UHCI_QUEUE_STACK *stack, const Bi
// add the queue's address
stack->queue_stack[stack->queue_cnt] = addr;
stack->queue_cnt++;

return 0;
}

// Called once every 1ms
void bx_uhci_core_c::uhci_timer(void)
{
#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_FRAME, 0, 0);
SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_FRAME, 0, 0);
#endif

// If the "global reset" bit was set by software
Expand All @@ -666,7 +666,7 @@ void bx_uhci_core_c::uhci_timer(void)
}
return;
}

// if the run bit is set, let's see if we can process a few TDs
if (hub.usb_command.schedule) {
// our stack of queues we have processed
Expand All @@ -680,28 +680,28 @@ void bx_uhci_core_c::uhci_timer(void)
struct TD td;
Bit32u address = hub.usb_frame_base.frame_base +
((hub.usb_frame_num.frame_num & 0x3FF) * sizeof(Bit32u));

// reset our queue stack to zero
queue_stack.queue_cnt = 0;

// read in the frame pointer
DEV_MEM_READ_PHYSICAL(address, sizeof(Bit32u), (Bit8u *) &item);

//BX_DEBUG(("Start of Frame %d", hub.usb_frame_num.frame_num & 0x3FF));

// start the loop. we allow USB_UHCI_LOOP_COUNT queues to be processed
while (count--) {
// The UHCI (USB 1.1) only allows so many bytes to be transfered per frame.
// Due to control/bulk reclamation, we need to catch this and stop transferring
// Due to control/bulk reclamation, we need to catch this and stop transferring
// or this code will just keep processing TDs.
if (bytes_processed >= hub.max_bandwidth) {
BX_DEBUG(("Process Bandwidth Limits for this frame (%d with a limit of %d).", bytes_processed, hub.max_bandwidth));
break;
}

if (!USB_UHCI_IS_LINK_VALID(item)) // the the T bit is set, we are done
break;

// is it a queue?
if (USB_UHCI_IS_LINK_QUEUE(item)) {
// add it to our current list of queues
Expand All @@ -717,13 +717,13 @@ void bx_uhci_core_c::uhci_timer(void)
uhci_add_queue(&queue_stack, item & ~0xF);
}
}

// read in the queue
DEV_MEM_READ_PHYSICAL(item & ~0xF, sizeof(struct QUEUE), (Bit8u *) &queue);

// this massively populates the log file, so I keep it commented out
//BX_DEBUG(("Queue at 0x%08X: horz = 0x%08X, vert = 0x%08X", item & ~0xF, queue.horz, queue.vert));

// if the vert pointer is valid, there are td's in it to process
// else only the head pointer may be valid
if (!USB_UHCI_IS_LINK_VALID(queue.vert)) {
Expand All @@ -742,7 +742,7 @@ void bx_uhci_core_c::uhci_timer(void)
}
continue;
}

// else, we found a Transfer Descriptor
address = item & ~0xF;
DEV_MEM_READ_PHYSICAL(address, sizeof(struct TD), (Bit8u *) &td);
Expand All @@ -767,17 +767,17 @@ void bx_uhci_core_c::uhci_timer(void)
}
}
if (td.dword1 & (1<<22)) stalled = was_stall = 1;

// write back the status to the TD
DEV_MEM_WRITE_PHYSICAL(address + sizeof(Bit32u), sizeof(Bit32u), (Bit8u *) &td.dword1);
#if BX_USE_WIN32USBDEBUG
// trigger again so that the user can see the processed packet
win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_COMMAND, address, USB_LPARAM_FLAG_AFTER);
SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_COMMAND, address, USB_LPARAM_FLAG_AFTER);
#endif
// we processed another td within this queue line
td_count++;
bytes_processed += r_actlen;

// move to the next item
if (!was_stall) {
item = td.dword0;
Expand All @@ -803,11 +803,11 @@ void bx_uhci_core_c::uhci_timer(void)
}
}
}

// move to next item (no queues) or queue head (queues found)
item = (queue_addr != 0) ? queue.horz : td.dword0;
} // while loop

// set the status register bit:0 to 1 if SPD is enabled
// and if interrupts not masked via interrupt register, raise irq interrupt.
if (shortpacket) hub.usb_status.status2 |= STATUS2_SPD;
Expand Down Expand Up @@ -836,7 +836,7 @@ void bx_uhci_core_c::uhci_timer(void)
if (interrupt || shortpacket) {
hub.usb_status.interrupt = 1;
}

// if we needed to fire an interrupt now, lets do it *after* we increment the frame_num register
update_irq();
} // end run schedule
Expand Down Expand Up @@ -892,7 +892,7 @@ int bx_uhci_core_c::event_handler(int event, void *ptr, int port)
case USB_EVENT_DEFAULT_SPEED:
// return default speed for specified port number
return USB_SPEED_FULL;

case USB_EVENT_CHECK_SPEED:
if (ptr != NULL) {
usb_device_c *usb_device = (usb_device_c *) ptr;
Expand All @@ -904,7 +904,7 @@ int bx_uhci_core_c::event_handler(int event, void *ptr, int port)
BX_ERROR(("unknown/unsupported event (id=%d) on port #%d", event, port+1));
ret = -1; // unknown event, event not handled
}

return ret;
}

Expand All @@ -922,9 +922,9 @@ bool bx_uhci_core_c::DoTransfer(Bit32u address, struct TD *td)
}

BX_DEBUG(("TD found at address 0x%08X: 0x%08X 0x%08X 0x%08X 0x%08X", address, td->dword0, td->dword1, td->dword2, td->dword3));

#if BX_USE_WIN32USBDEBUG
win32_usb_trigger(USB_DEBUG_UHCI, USB_DEBUG_COMMAND, address, USB_LPARAM_FLAG_BEFORE);
SIM->usb_debug_trigger(USB_DEBUG_UHCI, USB_DEBUG_COMMAND, address, USB_LPARAM_FLAG_BEFORE);
#endif

// check TD to make sure it is valid
Expand All @@ -945,7 +945,7 @@ bool bx_uhci_core_c::DoTransfer(Bit32u address, struct TD *td)
if (td->dword1 & (1 << 25)) {
BX_ERROR(("UHCI Core: ISO bit is set..."));
}

// the reserved bit in the Link Pointer should be zero
if (td->dword0 & (1<<3)) {
BX_INFO(("UHCI Core: Reserved bit in the Link Pointer is not zero."));
Expand Down
Loading

0 comments on commit 67e4e12

Please sign in to comment.