Bochs/bochs/gui/gtk_usb_debug.cc
Volker Ruppert 6f42e05b6e Added register view dialog for the GTK USB debugger (UHCI only).
Edited register values cannot be saved to controller yet.
Some optimizations in the USB debug dialog code.
2024-08-04 10:02:30 +02:00

552 lines
23 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023 Benjamin David Lunt
// Copyright (C) 2003-2024 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "bochs.h"
#include "siminterface.h"
#include "param_names.h"
#if BX_USB_DEBUGGER
#include "usb_debug.h"
// hack for xHCI
#include "iodev.h"
#include "iodev/usb/usb_common.h"
#include "iodev/usb/usb_xhci.h"
#include <gtk/gtk.h>
#include <glib.h>
typedef struct {
const char *name;
GtkWidget *entry;
Bit8u fmt_size;
const struct S_ATTRIBUTES *attr;
} usb_reg_t;
const char *chkTxt[6] = {"Reset", "Enable", "Event", "Doorbell", "Start of Frame", "Non-Exist"};
const char *chkBXPN[6] = {BXPN_USB_DEBUG_RESET, BXPN_USB_DEBUG_ENABLE, BXPN_USB_DEBUG_EVENT,
BXPN_USB_DEBUG_DOORBELL, BXPN_USB_DEBUG_START_FRAME, BXPN_USB_DEBUG_NON_EXIST};
GtkWidget *main_dialog;
GtkWidget *DFframe, *DFvbox, *checkbox[6];
GtkWidget *apply_hbox, *apply_button;
// multithreading using pure posix threads -- not glib threads
static void * EventLp(void *data)
{
gtk_main();
return NULL;
}
static void MakeGTKthreads()
{
pthread_t hThread;
pthread_create(&hThread, NULL, EventLp, NULL);
}
GtkWidget* usbdlg_create_label(GtkWidget *box, const char *text, bool expand = true)
{
GtkWidget *label = gtk_label_new(text);
gtk_box_pack_start(GTK_BOX(box), label, expand, expand, 2);
return label;
}
GtkWidget* usbdlg_create_entry_with_label(GtkWidget **box, const char *text,
bool expand = true)
{
gtk_box_pack_start(GTK_BOX(box[0]), gtk_label_new(text), expand, expand, 2);
GtkWidget *entry = gtk_entry_new();
gtk_box_pack_start(GTK_BOX(box[1]), entry, expand, expand, 2);
return entry;
}
GtkWidget* usbdlg_create_ro_entry(GtkWidget *box, bool expand = true)
{
GtkWidget *entry = gtk_entry_new();
gtk_widget_set_sensitive(entry, 0);
gtk_box_pack_start(GTK_BOX(box), entry, expand, expand, 2);
return entry;
}
GtkWidget* usbdlg_create_ro_entry_with_label(GtkWidget **box, const char *text,
bool expand = true)
{
gtk_box_pack_start(GTK_BOX(box[0]), gtk_label_new(text), expand, expand, 2);
GtkWidget *entry = gtk_entry_new();
gtk_widget_set_sensitive(entry, 0);
gtk_box_pack_start(GTK_BOX(box[1]), entry, expand, expand, 2);
return entry;
}
void usbdlg_create_debug_flags(GtkWidget *vbox)
{
DFframe = gtk_frame_new("Debug Flags");
gtk_box_pack_start(GTK_BOX(vbox), DFframe, FALSE, FALSE, 2);
DFvbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add(GTK_CONTAINER(DFframe), DFvbox);
for (int i = 0; i < 6; i++) {
checkbox[i] = gtk_check_button_new_with_label(chkTxt[i]);
if (SIM->get_param_num(chkBXPN[i])->get() > 0) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox[i]), TRUE);
}
gtk_box_pack_start(GTK_BOX(DFvbox), checkbox[i], FALSE, FALSE, 2);
}
}
void usbdlg_set_debug_flags()
{
for (int i = 0; i < 6; i++) {
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbox[i]))) {
SIM->get_param_num(chkBXPN[i])->set(1);
} else {
SIM->get_param_num(chkBXPN[i])->set(0);
}
}
}
static void usb_regview_dialog(GtkWidget *widget, gpointer data)
{
int i, ret;
char buffer[32], format[10];
Bit32u oldval, value;
usb_reg_t *usb_reg_def = (usb_reg_t*)data;
GtkWidget *dialog =
gtk_dialog_new_with_buttons(usb_reg_def->name, GTK_WINDOW(main_dialog), GTK_DIALOG_MODAL,
g_dgettext("gtk30", "_OK"), GTK_RESPONSE_OK,
g_dgettext("gtk30", "_Cancel"), GTK_RESPONSE_CANCEL,
NULL);
gtk_window_set_default_size(GTK_WINDOW(dialog), 250, 250);
GtkWidget *listbox = gtk_list_box_new();
gtk_list_box_set_selection_mode(GTK_LIST_BOX(listbox), GTK_SELECTION_MULTIPLE);
gtk_list_box_set_activate_on_single_click(GTK_LIST_BOX(listbox), 1);
i = 0;
while (usb_reg_def->attr[i].index > -1) {
gtk_list_box_insert(GTK_LIST_BOX(listbox), gtk_label_new(usb_reg_def->attr[i].str), -1);
i++;
}
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), listbox, TRUE, TRUE, 2);
// Show dialog
gtk_widget_show_all(dialog);
oldval = strtoul(gtk_entry_get_text(GTK_ENTRY(usb_reg_def->entry)), NULL, 16);
i = 0;
while (usb_reg_def->attr[i].index > -1) {
if ((oldval & usb_reg_def->attr[i].mask) != 0) {
gtk_list_box_select_row(GTK_LIST_BOX(listbox),
gtk_list_box_get_row_at_index(GTK_LIST_BOX(listbox), i));
} else {
gtk_list_box_unselect_row(GTK_LIST_BOX(listbox),
gtk_list_box_get_row_at_index(GTK_LIST_BOX(listbox), i));
}
i++;
}
ret = gtk_dialog_run(GTK_DIALOG(dialog));
if (ret == GTK_RESPONSE_OK) {
value = 0;
i = 0;
while (usb_reg_def->attr[i].index > -1) {
if (gtk_list_box_row_is_selected(gtk_list_box_get_row_at_index(GTK_LIST_BOX(listbox), i))) {
value |= usb_reg_def->attr[i].mask;
}
i++;
}
if (value != oldval) {
sprintf(format, "0x%%0%iX", usb_reg_def->fmt_size);
sprintf(buffer, format, value);
gtk_entry_set_text(GTK_ENTRY(usb_reg_def->entry), buffer);
}
}
gtk_widget_destroy(dialog);
}
static void on_entry_changed(GtkWidget *widget, gpointer data)
{
gtk_widget_set_sensitive(apply_button, 1);
}
static void apply_changes(GtkWidget *widget, gpointer data)
{
GtkWidget* error = gtk_message_dialog_new(
GTK_WINDOW(main_dialog), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
"Saving changes to controller not implemented yet");
gtk_window_set_title(GTK_WINDOW(error), "WARNING");
gtk_dialog_run(GTK_DIALOG(error));
gtk_widget_destroy(error);
}
int uhci_debug_dialog(int type, int param1)
{
bx_list_c *UHCI_state = NULL;
int i, ret;
Bit32u pci_bar_address, frame_addr, frame_num;
char buffer[COMMON_STR_SIZE];
GtkWidget *mainHbox, *BAhbox, *ORhbox, *PRhbox;
GtkWidget *entry[11], *button[7];
GtkWidget *vbox[3], *ORvbox[3], *PRvbox[3];
GtkWidget *ORframe, *PRframe;
usb_reg_t usb_reg_def[5];
UHCI_state = (bx_list_c*)SIM->get_param("usb_uhci", SIM->get_bochs_root());
if (UHCI_state == NULL)
return -1;
main_dialog = gtk_dialog_new();
switch (type) {
case USB_DEBUG_FRAME:
gtk_window_set_title(GTK_WINDOW(main_dialog), "UHCI Debug Dialog: Break Type: Start of Frame");
break;
case USB_DEBUG_COMMAND:
gtk_window_set_title(GTK_WINDOW(main_dialog), "UHCI Debug Dialog: Break Type: Doorbell");
break;
case USB_DEBUG_NONEXIST:
gtk_window_set_title(GTK_WINDOW(main_dialog), "UHCI Debug Dialog: Break Type: Non-Existant Port Write");
break;
case USB_DEBUG_RESET:
sprintf(buffer, "UHCI Debug Dialog: Break Type: Port %d Reset", param1);
gtk_window_set_title(GTK_WINDOW(main_dialog), buffer);
break;
case USB_DEBUG_ENABLE:
sprintf(buffer, "UHCI Debug Dialog: Break Type: Port %d Enable", param1);
gtk_window_set_title(GTK_WINDOW(main_dialog), buffer);
break;
default:
gtk_window_set_title(GTK_WINDOW(main_dialog), "UHCI Debug Dialog");
}
gtk_window_set_default_size(GTK_WINDOW(main_dialog), 600, 500);
button[0] = gtk_dialog_add_button(GTK_DIALOG(main_dialog), "Continue", GTK_RESPONSE_OK);
button[1] = gtk_dialog_add_button(GTK_DIALOG(main_dialog), "Quit", GTK_RESPONSE_CANCEL);
gtk_dialog_set_default_response(GTK_DIALOG(main_dialog), GTK_RESPONSE_OK);
gtk_window_set_focus(GTK_WINDOW(main_dialog), button[0]);
mainHbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(main_dialog))), mainHbox, TRUE, TRUE, 2);
for (i = 0; i < 3; i++) {
vbox[i] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(mainHbox), vbox[i], TRUE, TRUE, 2);
}
BAhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(vbox[0]), BAhbox, FALSE, FALSE, 2);
usbdlg_create_label(BAhbox, "UHCI at Base IO address", false);
entry[0] = usbdlg_create_ro_entry(BAhbox, false);
ORframe = gtk_frame_new("Operational Registers");
gtk_box_pack_start(GTK_BOX(vbox[0]), ORframe, FALSE, FALSE, 2);
ORhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add(GTK_CONTAINER(ORframe), ORhbox);
for (i = 0; i < 3; i++) {
ORvbox[i] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(ORhbox), ORvbox[i], FALSE, FALSE, 2);
}
entry[1] = usbdlg_create_entry_with_label(ORvbox, "Command");
button[2] = gtk_button_new_with_label("<>");
usb_reg_def[0] = {"Command Register", entry[1], 4, attribs_u_command};
g_signal_connect(button[2], "clicked", G_CALLBACK(usb_regview_dialog), &usb_reg_def[0]);
gtk_box_pack_start(GTK_BOX(ORvbox[2]), button[2], FALSE, FALSE, 2);
entry[2] = usbdlg_create_entry_with_label(ORvbox, "Status");
button[3] = gtk_button_new_with_label("<>");
usb_reg_def[1] = {"Status Register", entry[2], 4, attribs_u_status};
g_signal_connect(button[3], "clicked", G_CALLBACK(usb_regview_dialog), &usb_reg_def[1]);
gtk_box_pack_start(GTK_BOX(ORvbox[2]), button[3], FALSE, FALSE, 2);
entry[3] = usbdlg_create_entry_with_label(ORvbox, "Interrupt Enable");
button[4] = gtk_button_new_with_label("<>");
usb_reg_def[2] = {"Interrupt Enable Register", entry[3], 4, attribs_u_interrupt};
g_signal_connect(button[4], "clicked", G_CALLBACK(usb_regview_dialog), &usb_reg_def[2]);
gtk_box_pack_start(GTK_BOX(ORvbox[2]), button[4], FALSE, FALSE, 2);
entry[4] = usbdlg_create_ro_entry_with_label(ORvbox, "Frame Number");
entry[5] = usbdlg_create_ro_entry_with_label(ORvbox, "Frame Address");
entry[6] = usbdlg_create_ro_entry_with_label(ORvbox, "Start of Frame");
PRframe = gtk_frame_new("Port Registers");
gtk_box_pack_start(GTK_BOX(vbox[0]), PRframe, FALSE, FALSE, 2);
PRhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add(GTK_CONTAINER(PRframe), PRhbox);
for (i = 0; i < 3; i++) {
PRvbox[i] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(PRhbox), PRvbox[i], FALSE, FALSE, 2);
}
usb_reg_def[3] = {"Port 0 Register", NULL, 4, attribs_u_ports};
usb_reg_def[4] = {"Port 1 Register", NULL, 4, attribs_u_ports};
for (i = 0; i < 2; i++) {
sprintf(buffer, "Port %d", i);
entry[i * 2 + 7] = usbdlg_create_entry_with_label(PRvbox, buffer);
entry[i * 2 + 8] = usbdlg_create_ro_entry_with_label(PRvbox, "Emulation Type");
button[i + 5] = gtk_button_new_with_label("<>");
usb_reg_def[i + 3].entry = entry[i * 2 + 7];
g_signal_connect(button[i + 5], "clicked", G_CALLBACK(usb_regview_dialog), &usb_reg_def[i + 3]);
gtk_box_pack_start(GTK_BOX(PRvbox[2]), button[i + 5], FALSE, FALSE, 2);
gtk_box_pack_start(GTK_BOX(PRvbox[2]), gtk_label_new(" "), FALSE, FALSE, 8); // spacer
}
apply_hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(vbox[0]), apply_hbox, FALSE, FALSE, 2);
apply_button = gtk_button_new_with_label(g_dgettext("gtk30", "_Apply"));
gtk_widget_set_sensitive(apply_button, 0);
g_signal_connect(apply_button, "clicked", G_CALLBACK(apply_changes), NULL);
gtk_box_pack_start(GTK_BOX(apply_hbox), apply_button, FALSE, FALSE, 2);
usbdlg_create_debug_flags(vbox[2]);
// Set values
pci_bar_address = get_pci_bar_addr((bx_shadow_data_c*)SIM->get_param("hub.pci_conf", UHCI_state), 4);
sprintf(buffer, "0x%04X", pci_bar_address);
gtk_entry_set_text(GTK_ENTRY(entry[0]), buffer);
sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 0, 2));
gtk_entry_set_text(GTK_ENTRY(entry[1]), buffer);
g_signal_connect(GTK_EDITABLE(entry[1]), "changed", G_CALLBACK(on_entry_changed), NULL);
sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 2, 2));
gtk_entry_set_text(GTK_ENTRY(entry[2]), buffer);
g_signal_connect(GTK_EDITABLE(entry[2]), "changed", G_CALLBACK(on_entry_changed), NULL);
sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 4, 2));
gtk_entry_set_text(GTK_ENTRY(entry[3]), buffer);
g_signal_connect(GTK_EDITABLE(entry[3]), "changed", G_CALLBACK(on_entry_changed), NULL);
frame_num = usb_io_read(pci_bar_address + 6, 2);
sprintf(buffer, "0x%04X", frame_num);
gtk_entry_set_text(GTK_ENTRY(entry[4]), buffer);
frame_addr = usb_io_read(pci_bar_address + 8, 4);
sprintf(buffer, "0x%08X", frame_addr);
gtk_entry_set_text(GTK_ENTRY(entry[5]), buffer);
sprintf(buffer, "0x%02X", usb_io_read(pci_bar_address + 12, 1));
gtk_entry_set_text(GTK_ENTRY(entry[6]), buffer);
sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 16, 2));
gtk_entry_set_text(GTK_ENTRY(entry[7]), buffer);
g_signal_connect(GTK_EDITABLE(entry[7]), "changed", G_CALLBACK(on_entry_changed), NULL);
SIM->get_param_enum("port1.device", host_param)->dump_param(buffer, COMMON_STR_SIZE, 1);
gtk_entry_set_text(GTK_ENTRY(entry[8]), buffer);
sprintf(buffer, "0x%04X", usb_io_read(pci_bar_address + 18, 2));
gtk_entry_set_text(GTK_ENTRY(entry[9]), buffer);
g_signal_connect(GTK_EDITABLE(entry[9]), "changed", G_CALLBACK(on_entry_changed), NULL);
SIM->get_param_enum("port2.device", host_param)->dump_param(buffer, COMMON_STR_SIZE, 1);
gtk_entry_set_text(GTK_ENTRY(entry[10]), buffer);
// Show dialog
gtk_widget_show_all(main_dialog);
ret = gtk_dialog_run(GTK_DIALOG(main_dialog));
if (ret == GTK_RESPONSE_OK) {
usbdlg_set_debug_flags();
}
gtk_widget_destroy(main_dialog);
return ret;
}
int xhci_debug_dialog(int type, int param1)
{
bx_list_c *xHCI_state = NULL;
int i, n_ports, ret;
Bit32u pci_bar_address, dword, offset;
char buffer[COMMON_STR_SIZE], tmpbuf[32];
GtkWidget *mainVbox, *BAhbox, *hbox[2], *vbox[4], *entry[28];
GtkWidget *CRframe, *CRhbox, *CRvbox[2];
GtkWidget *ORframe, *ORhbox, *ORvbox[2];
GtkWidget *RTframe, *RThbox, *RTvbox[2];
GtkWidget *PRframe, *PRhbox, *PRvbox[2];
xHCI_state = (bx_list_c*)SIM->get_param("usb_xhci", SIM->get_bochs_root());
if (xHCI_state == NULL)
return -1;
main_dialog = gtk_dialog_new();
switch (type) {
case USB_DEBUG_COMMAND:
gtk_window_set_title(GTK_WINDOW(main_dialog), "xHCI Debug Dialog: Break Type: Command Ring");
break;
case USB_DEBUG_EVENT:
gtk_window_set_title(GTK_WINDOW(main_dialog), "xHCI Debug Dialog: Break Type: Event Ring");
break;
case USB_DEBUG_FRAME:
gtk_window_set_title(GTK_WINDOW(main_dialog), "xHCI Debug Dialog: Break Type: Frame");
break;
default:
gtk_window_set_title(GTK_WINDOW(main_dialog), "xHCI Debug Dialog");
}
gtk_window_set_default_size(GTK_WINDOW(main_dialog), 600, 500);
gtk_dialog_add_button(GTK_DIALOG(main_dialog), "Continue", GTK_RESPONSE_OK);
gtk_dialog_add_button(GTK_DIALOG(main_dialog), "Quit", GTK_RESPONSE_CANCEL);
gtk_dialog_set_default_response(GTK_DIALOG(main_dialog), GTK_RESPONSE_OK);
mainVbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(main_dialog))), mainVbox, TRUE, TRUE, 2);
BAhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(mainVbox), BAhbox, FALSE, FALSE, 2);
usbdlg_create_label(BAhbox, "xHCI at Base MMIO address", false);
entry[0] = usbdlg_create_ro_entry(BAhbox, false);
hbox[0] = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(mainVbox), hbox[0], TRUE, TRUE, 2);
hbox[1] = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_pack_start(GTK_BOX(mainVbox), hbox[1], TRUE, TRUE, 2);
for (i = 0; i < 4; i++) {
vbox[i] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(hbox[0]), vbox[i], TRUE, TRUE, 2);
}
CRframe = gtk_frame_new("Capability Registers");
gtk_box_pack_start(GTK_BOX(vbox[0]), CRframe, FALSE, FALSE, 2);
CRhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add(GTK_CONTAINER(CRframe), CRhbox);
CRvbox[0] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(CRhbox), CRvbox[0], FALSE, FALSE, 2);
CRvbox[1] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(CRhbox), CRvbox[1], FALSE, FALSE, 2);
entry[1] = usbdlg_create_ro_entry_with_label(CRvbox, "Cap Length");
entry[2] = usbdlg_create_ro_entry_with_label(CRvbox, "HCSParams1");
entry[3] = usbdlg_create_ro_entry_with_label(CRvbox, "HCSParams2");
entry[4] = usbdlg_create_ro_entry_with_label(CRvbox, "HCSParams3");
entry[5] = usbdlg_create_ro_entry_with_label(CRvbox, "HCCParams1");
entry[6] = usbdlg_create_ro_entry_with_label(CRvbox, "DB Offset");
entry[7] = usbdlg_create_ro_entry_with_label(CRvbox, "RTS Offset");
entry[8] = usbdlg_create_ro_entry_with_label(CRvbox, "HCCParams2");
ORframe = gtk_frame_new("Operational Registers");
gtk_box_pack_start(GTK_BOX(vbox[1]), ORframe, FALSE, FALSE, 2);
ORhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add(GTK_CONTAINER(ORframe), ORhbox);
ORvbox[0] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(ORhbox), ORvbox[0], FALSE, FALSE, 2);
ORvbox[1] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(ORhbox), ORvbox[1], FALSE, FALSE, 2);
entry[9] = usbdlg_create_ro_entry_with_label(ORvbox, "Command");
entry[10] = usbdlg_create_ro_entry_with_label(ORvbox, "Status");
entry[11] = usbdlg_create_ro_entry_with_label(ORvbox, "Page Size");
entry[12] = usbdlg_create_ro_entry_with_label(ORvbox, "Device Notification");
entry[13] = usbdlg_create_ro_entry_with_label(ORvbox, "Command Ring");
entry[14] = usbdlg_create_ro_entry_with_label(ORvbox, "Device Context Base");
entry[15] = usbdlg_create_ro_entry_with_label(ORvbox, "Configure");
RTframe = gtk_frame_new("Runtime Registers");
gtk_box_pack_start(GTK_BOX(vbox[2]), RTframe, FALSE, FALSE, 2);
RThbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add(GTK_CONTAINER(RTframe), RThbox);
RTvbox[0] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(RThbox), RTvbox[0], FALSE, FALSE, 2);
RTvbox[1] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(RThbox), RTvbox[1], FALSE, FALSE, 2);
entry[16] = usbdlg_create_ro_entry_with_label(RTvbox, "Microframe Index");
PRframe = gtk_frame_new("Port Registers");
gtk_box_pack_start(GTK_BOX(hbox[1]), PRframe, FALSE, FALSE, 2);
PRhbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_container_add(GTK_CONTAINER(PRframe), PRhbox);
PRvbox[0] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(PRhbox), PRvbox[0], FALSE, FALSE, 2);
PRvbox[1] = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start(GTK_BOX(PRhbox), PRvbox[1], FALSE, FALSE, 2);
n_ports = SIM->get_param_num(BXPN_XHCI_N_PORTS)->get();
for (i = 0; i < n_ports; i++) {
sprintf(buffer, "Port %d", i);
entry[i * 2 + 17] = usbdlg_create_entry_with_label(PRvbox, buffer);
entry[i * 2 + 18] = usbdlg_create_ro_entry_with_label(PRvbox, "Emulation Type");
}
usbdlg_create_debug_flags(vbox[3]);
// Set values
pci_bar_address = get_pci_bar_addr((bx_shadow_data_c*)SIM->get_param("hub.pci_conf", xHCI_state), 0);
sprintf(buffer, "0x%08X", pci_bar_address);
gtk_entry_set_text(GTK_ENTRY(entry[0]), buffer);
for (i = 0; i < 8; i++) {
dword = xhci_read_dword(pci_bar_address + (i * 4));
sprintf(buffer, "0x%08X", dword);
gtk_entry_set_text(GTK_ENTRY(entry[i + 1]), buffer);
}
offset = xhci_read_dword(pci_bar_address + 0) & 0xFF;
dword = xhci_read_dword(pci_bar_address + offset + 0x00);
sprintf(buffer, "0x%08X", dword);
gtk_entry_set_text(GTK_ENTRY(entry[9]), buffer);
dword = xhci_read_dword(pci_bar_address + offset + 0x04);
sprintf(buffer, "0x%08X", dword);
gtk_entry_set_text(GTK_ENTRY(entry[10]), buffer);
dword = xhci_read_dword(pci_bar_address + offset + 0x08);
sprintf(buffer, "0x%08X", dword);
gtk_entry_set_text(GTK_ENTRY(entry[11]), buffer);
dword = xhci_read_dword(pci_bar_address + offset + 0x14);
sprintf(buffer, "0x%08X", dword);
gtk_entry_set_text(GTK_ENTRY(entry[12]), buffer);
// we can't read this using DEV_MEM_READ_PHYSICAL since the handler will return zero
sprintf(buffer, "0x" FMT_ADDRX64, SIM->get_param_num("hub.op_regs.HcCrcr.actual", xHCI_state)->get64());
gtk_entry_set_text(GTK_ENTRY(entry[13]), buffer);
Bit64u qword = xhci_read_dword(pci_bar_address + offset + 0x30) |
((Bit64u) xhci_read_dword(pci_bar_address + offset + 0x34) << 32);
sprintf(buffer, "0x" FMT_ADDRX64, qword);
gtk_entry_set_text(GTK_ENTRY(entry[14]), buffer);
dword = xhci_read_dword(pci_bar_address + offset + 0x38);
sprintf(buffer, "0x%08X", dword);
gtk_entry_set_text(GTK_ENTRY(entry[15]), buffer);
offset = xhci_read_dword(pci_bar_address + 0x18);
dword = xhci_read_dword(pci_bar_address + offset + 0);
sprintf(buffer, "0x%08X", dword);
gtk_entry_set_text(GTK_ENTRY(entry[16]), buffer);
// show up to 10 port register sets
for (i = 0; i < n_ports; i++) {
dword = xhci_read_dword(pci_bar_address + XHCI_PORT_SET_OFFSET + (i * 16));
sprintf(buffer, "0x%08X", dword);
gtk_entry_set_text(GTK_ENTRY(entry[i * 2 + 17]), buffer);
sprintf(tmpbuf, "port%d.device", i + 1);
SIM->get_param_enum(tmpbuf, host_param)->dump_param(buffer, COMMON_STR_SIZE, 1);
gtk_entry_set_text(GTK_ENTRY(entry[i * 2 + 18]), buffer);
}
// Show dialog
gtk_widget_show_all(main_dialog);
ret = gtk_dialog_run(GTK_DIALOG(main_dialog));
if (ret == GTK_RESPONSE_OK) {
usbdlg_set_debug_flags();
}
gtk_widget_destroy(main_dialog);
return ret;
}
int usb_debug_dialog(int type, int param1, int param2)
{
static bool first_call = true;
int argc = 1, ret;
char *argv[2], **argvp, buffer[COMMON_STR_SIZE];
if (first_call) {
if (!SIM->is_wx_selected() && !SIM->has_debug_gui()) {
// you MUST call gtk_init, even with faked arguments, because it inits GDK and Glib
*buffer = 0; // gtk flames out if you pass in a NULL -- sheesh
argv[0] = buffer; // so I really do have to fake up an "argv" list
argv[1] = NULL;
argvp = argv;
if (gtk_init_check(&argc, &argvp) == false) {
fprintf(stderr, "gtk init failed, can not access display?\n");
return -1;
}
MakeGTKthreads();
}
first_call = false;
}
host_param = SIM->get_param(hc_param_str[usb_debug_type]);
if (usb_debug_type == USB_DEBUG_UHCI) {
ret = uhci_debug_dialog(type, param1);
return (ret == GTK_RESPONSE_OK) ? 0 : -1;
} else if (usb_debug_type == USB_DEBUG_XHCI) {
ret = xhci_debug_dialog(type, param1);
return (ret == GTK_RESPONSE_OK) ? 0 : -1;
} else {
GtkWidget* error = gtk_message_dialog_new(
NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK_CANCEL,
"GTK version of USB debugger dialog not implemented yet");
gtk_window_set_title(GTK_WINDOW(error), "WARNING");
ret = gtk_dialog_run(GTK_DIALOG(error));
gtk_widget_destroy(error);
return (ret == GTK_RESPONSE_OK) ? 0 : -1;
}
}
#endif