From b46fc681d2f4624c3c7ed15c327cf7d21650e29b Mon Sep 17 00:00:00 2001 From: Benjamin David Lunt <11790532+fysnet@users.noreply.github.com> Date: Wed, 13 Sep 2023 21:30:26 -0700 Subject: [PATCH] Improve default device detection (#77) This improves the detection of the default speed of a device when given in bochsrc. It will first get the max speed of the port given. For example, uhci and ohci will return FULL, ehci will return HIGH. xHCI will return SUPER if the port is a super-speed port, else it will return HIGH. Then it will compare this with the max speed allowed for that device, returning the highest common speed. Of course, if the speed option is given, the above is overwritten by the specified speed. Both checks are still performed on the result. 1) does device allow the result speed? 2) does the controller allow the result speed? --- bochs/iodev/usb/uhci_core.cc | 4 ++++ bochs/iodev/usb/usb_common.cc | 7 ++++++- bochs/iodev/usb/usb_common.h | 5 +++-- bochs/iodev/usb/usb_ehci.cc | 4 ++++ bochs/iodev/usb/usb_ohci.cc | 4 ++++ bochs/iodev/usb/usb_xhci.cc | 9 +++++++++ 6 files changed, 30 insertions(+), 3 deletions(-) diff --git a/bochs/iodev/usb/uhci_core.cc b/bochs/iodev/usb/uhci_core.cc index 4e8d4264ac..7358e35ba6 100644 --- a/bochs/iodev/usb/uhci_core.cc +++ b/bochs/iodev/usb/uhci_core.cc @@ -871,6 +871,10 @@ int bx_uhci_core_c::event_handler(int event, void *ptr, int port) break; // host controller events start here + 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; diff --git a/bochs/iodev/usb/usb_common.cc b/bochs/iodev/usb/usb_common.cc index 58a7ee8714..7207adb7ba 100644 --- a/bochs/iodev/usb/usb_common.cc +++ b/bochs/iodev/usb/usb_common.cc @@ -157,7 +157,12 @@ static const char *usb_speed[4] = { void bx_usbdev_ctl_c::parse_port_options(usb_device_c *device, bx_list_c *portconf) { - int speed = device->get_default_speed(USB_SPEED_FULL); // try to default to FULL speed if parameter not given. + // if the speed option parameter is not given: + // first try to default to speed of controller + // then adjust to default max speed of device + // if the speed option parameter is given, this will be overwritten anyway + int speed = device->hc_event(USB_EVENT_DEFAULT_SPEED, device); + speed = device->get_default_speed(speed); char *opts[16]; memset(opts, 0, sizeof(opts)); diff --git a/bochs/iodev/usb/usb_common.h b/bochs/iodev/usb/usb_common.h index 8454edcdec..89c733de64 100644 --- a/bochs/iodev/usb/usb_common.h +++ b/bochs/iodev/usb/usb_common.h @@ -142,7 +142,8 @@ typedef struct USBPacket USBPacket; #define USB_EVENT_WAKEUP 0 #define USB_EVENT_ASYNC 1 // controller events -#define USB_EVENT_CHECK_SPEED 10 +#define USB_EVENT_DEFAULT_SPEED 10 +#define USB_EVENT_CHECK_SPEED 11 // set this to 1 to monitor the TD's toggle bit // setting to 0 will speed up the emualtion slightly @@ -240,7 +241,7 @@ class BOCHSAPI usb_device_c : public logfunctions { int get_default_speed(int speed) { if ((speed >= d.minspeed) && (speed <= d.maxspeed)) return speed; - return d.minspeed; // will be no more than full-speed + return BX_MIN(speed, d.maxspeed); } // return information for the specified ep of the current device diff --git a/bochs/iodev/usb/usb_ehci.cc b/bochs/iodev/usb/usb_ehci.cc index acfe3de9a2..c4265d0770 100644 --- a/bochs/iodev/usb/usb_ehci.cc +++ b/bochs/iodev/usb/usb_ehci.cc @@ -1324,6 +1324,10 @@ int bx_usb_ehci_c::event_handler(int event, void *ptr, int port) break; // host controller events start here + case USB_EVENT_DEFAULT_SPEED: + // return default speed for specified port number + return USB_SPEED_HIGH; + case USB_EVENT_CHECK_SPEED: if (ptr != NULL) { usb_device_c *usb_device = (usb_device_c *) ptr; diff --git a/bochs/iodev/usb/usb_ohci.cc b/bochs/iodev/usb/usb_ohci.cc index 3efe93bb98..5fd2b8e709 100644 --- a/bochs/iodev/usb/usb_ohci.cc +++ b/bochs/iodev/usb/usb_ohci.cc @@ -1233,6 +1233,10 @@ int bx_usb_ohci_c::event_handler(int event, void *ptr, int port) break; // host controller events start here + 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; diff --git a/bochs/iodev/usb/usb_xhci.cc b/bochs/iodev/usb/usb_xhci.cc index ee2080bb52..c5fa770f60 100644 --- a/bochs/iodev/usb/usb_xhci.cc +++ b/bochs/iodev/usb/usb_xhci.cc @@ -2149,6 +2149,15 @@ int bx_usb_xhci_c::event_handler(int event, void *ptr, int port) break; // host controller events start here + case USB_EVENT_DEFAULT_SPEED: + // return default speed for specified port number + if (BX_XHCI_THIS hub.usb_port[port].is_usb3 == 1) { + // return super-speed + return USB_SPEED_SUPER; + } + // else return high-speed + return USB_SPEED_HIGH; + case USB_EVENT_CHECK_SPEED: // all super-speed device must be on the first half port register sets, // while all non-super-speed device must be on the second half.