Some fixes and cleanups in the USB code.
- USB hub: disable device "options" parameter if device is set to "none". - USB hub: handle device disconnect in runtime_config(). - Removed handling of USB device type in host controllers and external hub.
This commit is contained in:
parent
368c83127e
commit
16d79cbf0b
@ -159,7 +159,7 @@ void bx_uhci_core_c::reset_uhci(unsigned type)
|
||||
hub.usb_port[j].able_changed = 0;
|
||||
hub.usb_port[j].status = 0;
|
||||
if (hub.usb_port[j].device != NULL) {
|
||||
set_connect_status(j, hub.usb_port[j].device->get_type(), 1);
|
||||
set_connect_status(j, 1);
|
||||
}
|
||||
}
|
||||
while (packets != NULL) {
|
||||
@ -541,7 +541,7 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
if (hub.usb_port[port].device != NULL) {
|
||||
hub.usb_port[port].low_speed =
|
||||
(hub.usb_port[port].device->get_speed() == USB_SPEED_LOW);
|
||||
set_connect_status(port, hub.usb_port[port].device->get_type(), 1);
|
||||
set_connect_status(port, 1);
|
||||
hub.usb_port[port].device->usb_send_msg(USB_MSG_RESET);
|
||||
}
|
||||
}
|
||||
@ -935,72 +935,71 @@ const char *usb_speed[4] = {
|
||||
"super"
|
||||
};
|
||||
|
||||
void bx_uhci_core_c::set_connect_status(Bit8u port, int type, bool connected)
|
||||
bool bx_uhci_core_c::set_connect_status(Bit8u port, bool connected)
|
||||
{
|
||||
usb_device_c *device = hub.usb_port[port].device;
|
||||
if (device != NULL) {
|
||||
if (device->get_type() == type) {
|
||||
if (connected) {
|
||||
BX_DEBUG(("port #%d: speed = %s", port+1, usb_speed[device->get_speed()]));
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
hub.usb_port[port].low_speed = 1;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
hub.usb_port[port].low_speed = 0;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_SUPER:
|
||||
BX_ERROR(("HC ignores device with unsupported speed"));
|
||||
return;
|
||||
default:
|
||||
BX_PANIC(("USB device returned invalid speed value"));
|
||||
set_connect_status(port, type, 0);
|
||||
return;
|
||||
}
|
||||
if (hub.usb_port[port].low_speed) {
|
||||
hub.usb_port[port].line_dminus = 1; // dminus=1 & dplus=0 = low speed (at idle time)
|
||||
hub.usb_port[port].line_dplus = 0; // dminus=0 & dplus=1 = high speed (at idle time)
|
||||
} else {
|
||||
hub.usb_port[port].line_dminus = 0;
|
||||
hub.usb_port[port].line_dplus = 1;
|
||||
}
|
||||
hub.usb_port[port].status = 1;
|
||||
hub.usb_port[port].connect_changed = 1;
|
||||
|
||||
// if in suspend state, signal resume
|
||||
if (hub.usb_command.suspend) {
|
||||
hub.usb_port[port].resume = 1;
|
||||
hub.usb_status.resume = 1;
|
||||
if (hub.usb_enable.resume) {
|
||||
hub.usb_status.interrupt = 1;
|
||||
}
|
||||
update_irq();
|
||||
}
|
||||
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
set_connect_status(port, type, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
}
|
||||
device->set_event_handler(this, uhci_event_handler, port);
|
||||
} else {
|
||||
hub.usb_port[port].status = 0;
|
||||
hub.usb_port[port].connect_changed = 1;
|
||||
if (hub.usb_port[port].enabled) {
|
||||
hub.usb_port[port].able_changed = 1;
|
||||
hub.usb_port[port].enabled = 0;
|
||||
}
|
||||
hub.usb_port[port].low_speed = 0;
|
||||
hub.usb_port[port].line_dminus = 0;
|
||||
hub.usb_port[port].line_dplus = 0;
|
||||
if (connected) {
|
||||
BX_DEBUG(("port #%d: speed = %s", port+1, usb_speed[device->get_speed()]));
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
hub.usb_port[port].low_speed = 1;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
hub.usb_port[port].low_speed = 0;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_SUPER:
|
||||
BX_ERROR(("HC ignores device with unsupported speed"));
|
||||
return 0;
|
||||
default:
|
||||
BX_PANIC(("USB device returned invalid speed value"));
|
||||
set_connect_status(port, 0);
|
||||
return 0;
|
||||
}
|
||||
if (hub.usb_port[port].low_speed) {
|
||||
hub.usb_port[port].line_dminus = 1; // dminus=1 & dplus=0 = low speed (at idle time)
|
||||
hub.usb_port[port].line_dplus = 0; // dminus=0 & dplus=1 = high speed (at idle time)
|
||||
} else {
|
||||
hub.usb_port[port].line_dminus = 0;
|
||||
hub.usb_port[port].line_dplus = 1;
|
||||
}
|
||||
hub.usb_port[port].status = 1;
|
||||
hub.usb_port[port].connect_changed = 1;
|
||||
|
||||
// if in suspend state, signal resume
|
||||
if (hub.usb_command.suspend) {
|
||||
hub.usb_port[port].resume = 1;
|
||||
hub.usb_status.resume = 1;
|
||||
if (hub.usb_enable.resume) {
|
||||
hub.usb_status.interrupt = 1;
|
||||
}
|
||||
update_irq();
|
||||
}
|
||||
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
set_connect_status(port, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return 0;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
}
|
||||
device->set_event_handler(this, uhci_event_handler, port);
|
||||
} else {
|
||||
hub.usb_port[port].status = 0;
|
||||
hub.usb_port[port].connect_changed = 1;
|
||||
if (hub.usb_port[port].enabled) {
|
||||
hub.usb_port[port].able_changed = 1;
|
||||
hub.usb_port[port].enabled = 0;
|
||||
}
|
||||
hub.usb_port[port].low_speed = 0;
|
||||
hub.usb_port[port].line_dminus = 0;
|
||||
hub.usb_port[port].line_dplus = 0;
|
||||
}
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
void bx_uhci_core_c::set_port_device(int port, usb_device_c *dev)
|
||||
@ -1008,9 +1007,9 @@ void bx_uhci_core_c::set_port_device(int port, usb_device_c *dev)
|
||||
usb_device_c *olddev = hub.usb_port[port].device;
|
||||
if ((dev != NULL) && (olddev == NULL)) {
|
||||
hub.usb_port[port].device = dev;
|
||||
set_connect_status(port, dev->get_type(), 1);
|
||||
set_connect_status(port, 1);
|
||||
} else if ((dev == NULL) && (olddev != NULL)) {
|
||||
set_connect_status(port, olddev->get_type(), 0);
|
||||
set_connect_status(port, 0);
|
||||
hub.usb_port[port].device = dev;
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ protected:
|
||||
void update_irq(void);
|
||||
|
||||
int broadcast_packet(USBPacket *p);
|
||||
void set_connect_status(Bit8u port, int type, bool connected);
|
||||
bool set_connect_status(Bit8u port, bool connected);
|
||||
|
||||
static void uhci_timer_handler(void *);
|
||||
void uhci_timer(void);
|
||||
|
@ -108,7 +108,7 @@ void bx_usbdev_ctl_c::list_devices(void)
|
||||
}
|
||||
}
|
||||
|
||||
int bx_usbdev_ctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void **dev)
|
||||
bool bx_usbdev_ctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void **dev)
|
||||
{
|
||||
usbmod_type modtype = USB_MOD_TYPE_NONE;
|
||||
usbdev_type devtype = USB_DEV_TYPE_NONE;
|
||||
@ -174,7 +174,7 @@ int bx_usbdev_ctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void **
|
||||
if (*device != NULL) {
|
||||
parse_port_options(*device, portconf);
|
||||
}
|
||||
return devtype;
|
||||
return (*device != NULL);
|
||||
}
|
||||
|
||||
void bx_usbdev_ctl_c::parse_port_options(usb_device_c *device, bx_list_c *portconf)
|
||||
|
@ -176,7 +176,7 @@ public:
|
||||
void exit(void);
|
||||
const char **get_device_names(void);
|
||||
void list_devices(void);
|
||||
virtual int init_device(bx_list_c *portconf, logfunctions *hub, void **dev);
|
||||
virtual bool init_device(bx_list_c *portconf, logfunctions *hub, void **dev);
|
||||
private:
|
||||
void parse_port_options(usb_device_c *dev, bx_list_c *portconf);
|
||||
};
|
||||
|
@ -468,7 +468,7 @@ void bx_usb_ehci_c::reset_hc()
|
||||
sprintf(pname, "port%d", i+1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_EHCI)));
|
||||
} else {
|
||||
set_connect_status(i, BX_EHCI_THIS hub.usb_port[i].device->get_type(), 1);
|
||||
set_connect_status(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -506,7 +506,6 @@ void bx_usb_ehci_c::reset_port(int p)
|
||||
|
||||
void bx_usb_ehci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
{
|
||||
int type;
|
||||
char pname[BX_PATHNAME_LEN];
|
||||
const char *devname = NULL;
|
||||
|
||||
@ -518,12 +517,12 @@ void bx_usb_ehci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
BX_ERROR(("init_device(): port%d already in use", port+1));
|
||||
return;
|
||||
}
|
||||
sprintf(pname, "usb_ehci.hub.port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root());
|
||||
type = DEV_usb_init_device(portconf, BX_EHCI_THIS_PTR, &BX_EHCI_THIS hub.usb_port[port].device);
|
||||
if (BX_EHCI_THIS hub.usb_port[port].device != NULL) {
|
||||
set_connect_status(port, type, 1);
|
||||
BX_EHCI_THIS hub.usb_port[port].device->register_state(sr_list);
|
||||
if (DEV_usb_init_device(portconf, BX_EHCI_THIS_PTR, &BX_EHCI_THIS hub.usb_port[port].device)) {
|
||||
if (set_connect_status(port, 1)) {
|
||||
sprintf(pname, "usb_ehci.hub.port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root());
|
||||
BX_EHCI_THIS hub.usb_port[port].device->register_state(sr_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,75 +534,73 @@ void bx_usb_ehci_c::remove_device(Bit8u port)
|
||||
}
|
||||
}
|
||||
|
||||
void bx_usb_ehci_c::set_connect_status(Bit8u port, int type, bool connected)
|
||||
bool bx_usb_ehci_c::set_connect_status(Bit8u port, bool connected)
|
||||
{
|
||||
const bool ccs_org = BX_EHCI_THIS hub.usb_port[port].portsc.ccs;
|
||||
const bool ped_org = BX_EHCI_THIS hub.usb_port[port].portsc.ped;
|
||||
|
||||
usb_device_c *device = BX_EHCI_THIS hub.usb_port[port].device;
|
||||
if (device != NULL) {
|
||||
if (device->get_type() == type) {
|
||||
if (connected) {
|
||||
if (BX_EHCI_THIS hub.usb_port[port].portsc.po) {
|
||||
BX_EHCI_THIS uhci[port >> 1]->set_port_device(port & 1, device);
|
||||
return;
|
||||
if (connected) {
|
||||
if (BX_EHCI_THIS hub.usb_port[port].portsc.po) {
|
||||
BX_EHCI_THIS uhci[port >> 1]->set_port_device(port & 1, device);
|
||||
return 1;
|
||||
}
|
||||
if (device->get_speed() == USB_SPEED_SUPER) {
|
||||
BX_PANIC(("Super-speed device not supported on USB2 port."));
|
||||
set_connect_status(port, 0);
|
||||
return 0;
|
||||
}
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
BX_INFO(("Low speed device connected to port #%d", port+1));
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ls = 0x1;
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ped = 0;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
BX_INFO(("Full speed device connected to port #%d", port+1));
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ls = 0x2;
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ped = 0;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
BX_INFO(("High speed device connected to port #%d", port+1));
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ls = 0x0;
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ped = 1;
|
||||
break;
|
||||
default:
|
||||
BX_ERROR(("device->get_speed() returned invalid speed value"));
|
||||
}
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ccs = 1;
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
set_connect_status(port, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return 0;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
if (device->get_speed() == USB_SPEED_SUPER) {
|
||||
BX_PANIC(("Super-speed device not supported on USB2 port."));
|
||||
set_connect_status(port, type, 0);
|
||||
return;
|
||||
}
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
BX_INFO(("Low speed device connected to port #%d", port+1));
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ls = 0x1;
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ped = 0;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
BX_INFO(("Full speed device connected to port #%d", port+1));
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ls = 0x2;
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ped = 0;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
BX_INFO(("High speed device connected to port #%d", port+1));
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ls = 0x0;
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ped = 1;
|
||||
break;
|
||||
default:
|
||||
BX_ERROR(("device->get_speed() returned invalid speed value"));
|
||||
}
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ccs = 1;
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
set_connect_status(port, type, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
}
|
||||
device->set_event_handler(BX_EHCI_THIS_PTR, ehci_event_handler, port);
|
||||
} else { // not connected
|
||||
if (BX_EHCI_THIS hub.usb_port[port].portsc.po) {
|
||||
}
|
||||
device->set_event_handler(BX_EHCI_THIS_PTR, ehci_event_handler, port);
|
||||
} else { // not connected
|
||||
if (BX_EHCI_THIS hub.usb_port[port].portsc.po) {
|
||||
BX_EHCI_THIS uhci[port >> 1]->set_port_device(port & 1, NULL);
|
||||
if ((!BX_EHCI_THIS hub.usb_port[port].owner_change) &&
|
||||
(BX_EHCI_THIS hub.op_regs.ConfigFlag & 1)) {
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.po = 0;
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.csc = 1;
|
||||
}
|
||||
} else {
|
||||
} else {
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ccs = 0;
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.ped = 0;
|
||||
BX_EHCI_THIS queues_rip_device(device, 0);
|
||||
BX_EHCI_THIS queues_rip_device(device, 1);
|
||||
device->set_async_mode(0);
|
||||
}
|
||||
if (!BX_EHCI_THIS hub.usb_port[port].owner_change) {
|
||||
remove_device(port);
|
||||
}
|
||||
if (BX_EHCI_THIS hub.usb_port[port].portsc.po)
|
||||
return;
|
||||
}
|
||||
if (!BX_EHCI_THIS hub.usb_port[port].owner_change) {
|
||||
remove_device(port);
|
||||
}
|
||||
if (BX_EHCI_THIS hub.usb_port[port].portsc.po)
|
||||
return 0;
|
||||
}
|
||||
if (ccs_org != BX_EHCI_THIS hub.usb_port[port].portsc.ccs)
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.csc = 1;
|
||||
@ -613,6 +610,7 @@ void bx_usb_ehci_c::set_connect_status(Bit8u port, int type, bool connected)
|
||||
BX_EHCI_THIS hub.op_regs.UsbSts.inti |= USBSTS_PCD;
|
||||
BX_EHCI_THIS update_irq();
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
void bx_usb_ehci_c::change_port_owner(int port)
|
||||
@ -627,11 +625,11 @@ void bx_usb_ehci_c::change_port_owner(int port)
|
||||
BX_INFO(("port #%d: owner change to %s", port+1,
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.po ? "EHCI":"UHCI"));
|
||||
if (device != NULL) {
|
||||
set_connect_status(port, device->get_type(), 0);
|
||||
set_connect_status(port, 0);
|
||||
}
|
||||
BX_EHCI_THIS hub.usb_port[port].portsc.po ^= 1;
|
||||
if (device != NULL) {
|
||||
set_connect_status(port, device->get_type(), 1);
|
||||
set_connect_status(port, 1);
|
||||
}
|
||||
}
|
||||
BX_EHCI_THIS hub.usb_port[port].owner_change = 0;
|
||||
@ -2220,7 +2218,6 @@ void bx_usb_ehci_c::runtime_config(void)
|
||||
{
|
||||
int i;
|
||||
char pname[6];
|
||||
int type = -1;
|
||||
|
||||
for (i = 0; i < USB_EHCI_PORTS; i++) {
|
||||
// device change support
|
||||
@ -2231,10 +2228,7 @@ void bx_usb_ehci_c::runtime_config(void)
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_EHCI)));
|
||||
} else {
|
||||
BX_INFO(("USB port #%d: device disconnect", i+1));
|
||||
if (BX_EHCI_THIS hub.usb_port[i].device != NULL) {
|
||||
type = BX_EHCI_THIS hub.usb_port[i].device->get_type();
|
||||
}
|
||||
set_connect_status(i, type, 0);
|
||||
set_connect_status(i, 0);
|
||||
}
|
||||
BX_EHCI_THIS device_change &= ~(1 << i);
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ private:
|
||||
|
||||
static void init_device(Bit8u port, bx_list_c *portconf);
|
||||
static void remove_device(Bit8u port);
|
||||
static void set_connect_status(Bit8u port, int type, bool connected);
|
||||
static bool set_connect_status(Bit8u port, bool connected);
|
||||
static void change_port_owner(int port);
|
||||
|
||||
// EHCI core methods ported from QEMU 1.2.2
|
||||
|
@ -254,8 +254,9 @@ bool usb_hub_device_c::init()
|
||||
int i;
|
||||
char pname[10];
|
||||
char label[32];
|
||||
bx_list_c *port;
|
||||
bx_list_c *port, *deplist;
|
||||
bx_param_enum_c *device;
|
||||
bx_param_string_c *options;
|
||||
|
||||
// set up config descriptor, status and runtime config for hub.n_ports
|
||||
bx_hub_config_descriptor[22] = (hub.n_ports + 1 + 7) / 8;
|
||||
@ -270,7 +271,11 @@ bool usb_hub_device_c::init()
|
||||
port->set_options(port->SERIES_ASK | port->USE_BOX_TITLE);
|
||||
device = new bx_param_enum_c(port, "device", "Device", "", usb_device_names, 0, 0);
|
||||
device->set_handler(hub_param_handler);
|
||||
new bx_param_string_c(port, "options", "Options", "", "", BX_PATHNAME_LEN);
|
||||
options = new bx_param_string_c(port, "options", "Options", "", "", BX_PATHNAME_LEN);
|
||||
deplist = new bx_list_c(NULL);
|
||||
deplist->add(options);
|
||||
device->set_dependent_list(deplist, 1);
|
||||
device->set_dependent_bitmap(0, 0);
|
||||
}
|
||||
if (SIM->is_wx_selected()) {
|
||||
bx_list_c *usb = (bx_list_c*)SIM->get_param("ports.usb");
|
||||
@ -565,7 +570,6 @@ int usb_hub_device_c::handle_packet(USBPacket *p)
|
||||
|
||||
void usb_hub_device_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
{
|
||||
int type;
|
||||
char pname[BX_PATHNAME_LEN];
|
||||
const char *devname = NULL;
|
||||
|
||||
@ -577,12 +581,12 @@ void usb_hub_device_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
BX_ERROR(("init_device(): port%d already in use", port+1));
|
||||
return;
|
||||
}
|
||||
sprintf(pname, "port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, hub.state);
|
||||
type = DEV_usb_init_device(portconf, this, &hub.usb_port[port].device);
|
||||
if (hub.usb_port[port].device != NULL) {
|
||||
usb_set_connect_status(port, type, 1);
|
||||
hub.usb_port[port].device->register_state(sr_list);
|
||||
if (DEV_usb_init_device(portconf, this, &hub.usb_port[port].device)) {
|
||||
if (usb_set_connect_status(port, 1)) {
|
||||
sprintf(pname, "port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, hub.state);
|
||||
hub.usb_port[port].device->register_state(sr_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -613,61 +617,60 @@ void usb_hub_device_c::event_handler(int event, USBPacket *packet, int port)
|
||||
}
|
||||
}
|
||||
|
||||
void usb_hub_device_c::usb_set_connect_status(Bit8u port, int type, bool connected)
|
||||
bool usb_hub_device_c::usb_set_connect_status(Bit8u port, bool connected)
|
||||
{
|
||||
usb_device_c *device = hub.usb_port[port].device;
|
||||
if (device != NULL) {
|
||||
if (device->get_type() == type) {
|
||||
if (connected) {
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
hub.usb_port[port].PortStatus |= PORT_STAT_LOW_SPEED;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
hub.usb_port[port].PortStatus &= ~PORT_STAT_LOW_SPEED;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_SUPER:
|
||||
BX_PANIC(("Hub supports 'low' or 'full' speed devices only."));
|
||||
usb_set_connect_status(port, type, 0);
|
||||
return;
|
||||
default:
|
||||
BX_PANIC(("USB device returned invalid speed value"));
|
||||
usb_set_connect_status(port, type, 0);
|
||||
return;
|
||||
}
|
||||
hub.usb_port[port].PortStatus |= PORT_STAT_CONNECTION;
|
||||
hub.usb_port[port].PortChange |= PORT_STAT_C_CONNECTION;
|
||||
if (hub.usb_port[port].PortStatus & PORT_STAT_SUSPEND) {
|
||||
hub.usb_port[port].PortChange |= PORT_STAT_C_SUSPEND;
|
||||
}
|
||||
if (d.event.dev != NULL) {
|
||||
d.event.cb(USB_EVENT_WAKEUP, NULL, d.event.dev, d.event.port);
|
||||
}
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
usb_set_connect_status(port, type, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
}
|
||||
device->set_event_handler(this, hub_event_handler, port);
|
||||
} else {
|
||||
if (d.event.dev != NULL) {
|
||||
d.event.cb(USB_EVENT_WAKEUP, NULL, d.event.dev, d.event.port);
|
||||
}
|
||||
hub.usb_port[port].PortStatus &= ~PORT_STAT_CONNECTION;
|
||||
hub.usb_port[port].PortChange |= PORT_STAT_C_CONNECTION;
|
||||
if (hub.usb_port[port].PortStatus & PORT_STAT_ENABLE) {
|
||||
hub.usb_port[port].PortStatus &= ~PORT_STAT_ENABLE;
|
||||
hub.usb_port[port].PortChange |= PORT_STAT_C_ENABLE;
|
||||
}
|
||||
remove_device(port);
|
||||
if (connected) {
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
hub.usb_port[port].PortStatus |= PORT_STAT_LOW_SPEED;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
hub.usb_port[port].PortStatus &= ~PORT_STAT_LOW_SPEED;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_SUPER:
|
||||
BX_PANIC(("Hub supports 'low' or 'full' speed devices only."));
|
||||
usb_set_connect_status(port, 0);
|
||||
return 0;
|
||||
default:
|
||||
BX_PANIC(("USB device returned invalid speed value"));
|
||||
usb_set_connect_status(port, 0);
|
||||
return 0;
|
||||
}
|
||||
hub.usb_port[port].PortStatus |= PORT_STAT_CONNECTION;
|
||||
hub.usb_port[port].PortChange |= PORT_STAT_C_CONNECTION;
|
||||
if (hub.usb_port[port].PortStatus & PORT_STAT_SUSPEND) {
|
||||
hub.usb_port[port].PortChange |= PORT_STAT_C_SUSPEND;
|
||||
}
|
||||
if (d.event.dev != NULL) {
|
||||
d.event.cb(USB_EVENT_WAKEUP, NULL, d.event.dev, d.event.port);
|
||||
}
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
usb_set_connect_status(port, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return 0;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
}
|
||||
device->set_event_handler(this, hub_event_handler, port);
|
||||
} else {
|
||||
if (d.event.dev != NULL) {
|
||||
d.event.cb(USB_EVENT_WAKEUP, NULL, d.event.dev, d.event.port);
|
||||
}
|
||||
hub.usb_port[port].PortStatus &= ~PORT_STAT_CONNECTION;
|
||||
hub.usb_port[port].PortChange |= PORT_STAT_C_CONNECTION;
|
||||
if (hub.usb_port[port].PortStatus & PORT_STAT_ENABLE) {
|
||||
hub.usb_port[port].PortStatus &= ~PORT_STAT_ENABLE;
|
||||
hub.usb_port[port].PortChange |= PORT_STAT_C_ENABLE;
|
||||
}
|
||||
remove_device(port);
|
||||
}
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
void usb_hub_device_c::runtime_config()
|
||||
@ -679,9 +682,14 @@ void usb_hub_device_c::runtime_config()
|
||||
// device change support
|
||||
if ((hub.device_change & (1 << i)) != 0) {
|
||||
hubnum = atoi(hub.config->get_name()+6);
|
||||
BX_INFO(("USB hub #%d, port #%d: device connect", hubnum, i+1));
|
||||
sprintf(pname, "port%d", i + 1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, hub.config));
|
||||
if ((hub.usb_port[i].PortStatus & PORT_STAT_CONNECTION) == 0) {
|
||||
BX_INFO(("USB hub #%d, port #%d: device connect", hubnum, i+1));
|
||||
sprintf(pname, "port%d", i + 1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, hub.config));
|
||||
} else {
|
||||
BX_INFO(("USB hub #%d, port #%d: device disconnect", hubnum, i+1));
|
||||
usb_set_connect_status(i, 0);
|
||||
}
|
||||
hub.device_change &= ~(1 << i);
|
||||
}
|
||||
// forward to connected device
|
||||
@ -697,8 +705,7 @@ void usb_hub_device_c::runtime_config()
|
||||
// USB hub runtime parameter handler
|
||||
Bit64s usb_hub_device_c::hub_param_handler(bx_param_c *param, int set, Bit64s val)
|
||||
{
|
||||
int type = -1;
|
||||
int hubnum, portnum;
|
||||
int portnum;
|
||||
usb_hub_device_c *hub;
|
||||
bx_list_c *port;
|
||||
|
||||
@ -706,16 +713,11 @@ Bit64s usb_hub_device_c::hub_param_handler(bx_param_c *param, int set, Bit64s va
|
||||
port = (bx_list_c*)param->get_parent();
|
||||
hub = (usb_hub_device_c*)(port->get_parent()->get_device_param());
|
||||
if (hub != NULL) {
|
||||
hubnum = atoi(port->get_parent()->get_name()+6);
|
||||
portnum = atoi(port->get_name()+4) - 1;
|
||||
bool empty = (val == 0);
|
||||
if ((portnum >= 0) && (portnum < hub->hub.n_ports)) {
|
||||
if (empty && (hub->hub.usb_port[portnum].PortStatus & PORT_STAT_CONNECTION)) {
|
||||
BX_INFO(("USB hub #%d, port #%d: device disconnect", hubnum, portnum+1));
|
||||
if (hub->hub.usb_port[portnum].device != NULL) {
|
||||
type = hub->hub.usb_port[portnum].device->get_type();
|
||||
}
|
||||
hub->usb_set_connect_status(portnum, type, 0);
|
||||
hub->hub.device_change |= (1 << portnum);
|
||||
} else if (!empty && !(hub->hub.usb_port[portnum].PortStatus & PORT_STAT_CONNECTION)) {
|
||||
hub->hub.device_change |= (1 << portnum);
|
||||
} else {
|
||||
|
@ -73,7 +73,7 @@ private:
|
||||
int broadcast_packet(USBPacket *p);
|
||||
void init_device(Bit8u port, bx_list_c *portconf);
|
||||
void remove_device(Bit8u port);
|
||||
void usb_set_connect_status(Bit8u port, int type, bool connected);
|
||||
bool usb_set_connect_status(Bit8u port, bool connected);
|
||||
|
||||
static Bit64s hub_param_handler(bx_param_c *param, int set, Bit64s val);
|
||||
};
|
||||
|
@ -360,7 +360,7 @@ void bx_usb_ohci_c::reset_hc()
|
||||
sprintf(pname, "port%d", i+1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_OHCI)));
|
||||
} else {
|
||||
usb_set_connect_status(i, BX_OHCI_THIS hub.usb_port[i].device->get_type(), 1);
|
||||
usb_set_connect_status(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -482,7 +482,6 @@ void bx_usb_ohci_c::after_restore_state(void)
|
||||
|
||||
void bx_usb_ohci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
{
|
||||
int type;
|
||||
char pname[BX_PATHNAME_LEN];
|
||||
const char *devname = NULL;
|
||||
|
||||
@ -494,12 +493,12 @@ void bx_usb_ohci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
BX_ERROR(("init_device(): port%d already in use", port+1));
|
||||
return;
|
||||
}
|
||||
sprintf(pname, "usb_ohci.hub.port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root());
|
||||
type = DEV_usb_init_device(portconf, BX_OHCI_THIS_PTR, &BX_OHCI_THIS hub.usb_port[port].device);
|
||||
if (BX_OHCI_THIS hub.usb_port[port].device != NULL) {
|
||||
usb_set_connect_status(port, type, 1);
|
||||
BX_OHCI_THIS hub.usb_port[port].device->register_state(sr_list);
|
||||
if (DEV_usb_init_device(portconf, BX_OHCI_THIS_PTR, &BX_OHCI_THIS hub.usb_port[port].device)) {
|
||||
if (usb_set_connect_status(port, 1)) {
|
||||
sprintf(pname, "usb_ohci.hub.port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root());
|
||||
BX_OHCI_THIS hub.usb_port[port].device->register_state(sr_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -971,7 +970,7 @@ bool bx_usb_ohci_c::write_handler(bx_phy_address addr, unsigned len, void *data,
|
||||
if (BX_OHCI_THIS hub.usb_port[p].device != NULL) {
|
||||
BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.lsda =
|
||||
(BX_OHCI_THIS hub.usb_port[p].device->get_speed() == USB_SPEED_LOW);
|
||||
usb_set_connect_status(p, BX_OHCI_THIS hub.usb_port[p].device->get_type(), 1);
|
||||
usb_set_connect_status(p, 1);
|
||||
BX_OHCI_THIS hub.usb_port[p].device->usb_send_msg(USB_MSG_RESET);
|
||||
}
|
||||
set_interrupt(OHCI_INTR_RHSC);
|
||||
@ -1403,7 +1402,6 @@ void bx_usb_ohci_c::runtime_config(void)
|
||||
{
|
||||
int i;
|
||||
char pname[6];
|
||||
int type = -1;
|
||||
|
||||
for (i = 0; i < USB_OHCI_PORTS; i++) {
|
||||
// device change support
|
||||
@ -1414,10 +1412,7 @@ void bx_usb_ohci_c::runtime_config(void)
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_OHCI)));
|
||||
} else {
|
||||
BX_INFO(("USB port #%d: device disconnect", i+1));
|
||||
if (BX_OHCI_THIS hub.usb_port[i].device != NULL) {
|
||||
type = BX_OHCI_THIS hub.usb_port[i].device->get_type();
|
||||
}
|
||||
usb_set_connect_status(i, type, 0);
|
||||
usb_set_connect_status(i, 0);
|
||||
}
|
||||
BX_OHCI_THIS hub.device_change &= ~(1 << i);
|
||||
}
|
||||
@ -1458,49 +1453,47 @@ void bx_usb_ohci_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_l
|
||||
}
|
||||
}
|
||||
|
||||
void bx_usb_ohci_c::usb_set_connect_status(Bit8u port, int type, bool connected)
|
||||
bool bx_usb_ohci_c::usb_set_connect_status(Bit8u port, bool connected)
|
||||
{
|
||||
const bool ccs_org = BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs;
|
||||
const bool pes_org = BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.pes;
|
||||
|
||||
usb_device_c *device = BX_OHCI_THIS hub.usb_port[port].device;
|
||||
if (device != NULL) {
|
||||
if (device->get_type() == type) {
|
||||
if (connected) {
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.lsda = 1;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.lsda = 0;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_SUPER:
|
||||
BX_PANIC(("HC supports 'low' or 'full' speed devices only."));
|
||||
usb_set_connect_status(port, type, 0);
|
||||
return;
|
||||
default:
|
||||
BX_PANIC(("USB device returned invalid speed value"));
|
||||
usb_set_connect_status(port, type, 0);
|
||||
return;
|
||||
}
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs = 1;
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
usb_set_connect_status(port, type, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
}
|
||||
device->set_event_handler(BX_OHCI_THIS_PTR, ohci_event_handler, port);
|
||||
} else { // not connected
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs = 0;
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.pes = 0;
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.lsda = 0;
|
||||
remove_device(port);
|
||||
if (connected) {
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.lsda = 1;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.lsda = 0;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
case USB_SPEED_SUPER:
|
||||
BX_PANIC(("HC supports 'low' or 'full' speed devices only."));
|
||||
usb_set_connect_status(port, 0);
|
||||
return 0;
|
||||
default:
|
||||
BX_PANIC(("USB device returned invalid speed value"));
|
||||
usb_set_connect_status(port, 0);
|
||||
return 0;
|
||||
}
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs = 1;
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
usb_set_connect_status(port, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return 0;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
}
|
||||
device->set_event_handler(BX_OHCI_THIS_PTR, ohci_event_handler, port);
|
||||
} else { // not connected
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs = 0;
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.pes = 0;
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.lsda = 0;
|
||||
remove_device(port);
|
||||
}
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.csc |= (ccs_org != BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs);
|
||||
BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.pesc |= (pes_org != BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.pes);
|
||||
@ -1508,6 +1501,7 @@ void bx_usb_ohci_c::usb_set_connect_status(Bit8u port, int type, bool connected)
|
||||
// we changed the value of the port, so show it
|
||||
set_interrupt(OHCI_INTR_RHSC);
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
// USB runtime parameter handler
|
||||
|
@ -277,7 +277,7 @@ private:
|
||||
static void init_device(Bit8u port, bx_list_c *portconf);
|
||||
static void remove_device(Bit8u port);
|
||||
static int broadcast_packet(USBPacket *p);
|
||||
static void usb_set_connect_status(Bit8u port, int type, bool connected);
|
||||
static bool usb_set_connect_status(Bit8u port, bool connected);
|
||||
|
||||
static void usb_frame_handler(void *);
|
||||
void usb_frame_timer(void);
|
||||
|
@ -196,7 +196,6 @@ void bx_usb_uhci_c::after_restore_state()
|
||||
|
||||
void bx_usb_uhci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
{
|
||||
int type;
|
||||
char pname[BX_PATHNAME_LEN];
|
||||
const char *devname = NULL;
|
||||
|
||||
@ -208,12 +207,12 @@ void bx_usb_uhci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
BX_ERROR(("init_device(): port%d already in use", port+1));
|
||||
return;
|
||||
}
|
||||
sprintf(pname, "usb_uhci.hub.port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root());
|
||||
type = DEV_usb_init_device(portconf, BX_UHCI_THIS_PTR, &BX_UHCI_THIS hub.usb_port[port].device);
|
||||
if (BX_UHCI_THIS hub.usb_port[port].device != NULL) {
|
||||
set_connect_status(port, type, 1);
|
||||
BX_UHCI_THIS hub.usb_port[port].device->register_state(sr_list);
|
||||
if (DEV_usb_init_device(portconf, BX_UHCI_THIS_PTR, &BX_UHCI_THIS hub.usb_port[port].device)) {
|
||||
if (set_connect_status(port, 1)) {
|
||||
sprintf(pname, "usb_uhci.hub.port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root());
|
||||
BX_UHCI_THIS hub.usb_port[port].device->register_state(sr_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,7 +234,6 @@ void bx_usb_uhci_c::runtime_config(void)
|
||||
{
|
||||
int i;
|
||||
char pname[6];
|
||||
int type = -1;
|
||||
|
||||
for (i = 0; i < USB_UHCI_PORTS; i++) {
|
||||
// device change support
|
||||
@ -246,10 +244,7 @@ void bx_usb_uhci_c::runtime_config(void)
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_UHCI)));
|
||||
} else {
|
||||
BX_INFO(("USB port #%d: device disconnect", i+1));
|
||||
if (BX_UHCI_THIS hub.usb_port[i].device != NULL) {
|
||||
type = BX_UHCI_THIS hub.usb_port[i].device->get_type();
|
||||
}
|
||||
set_connect_status(i, type, 0);
|
||||
set_connect_status(i, 0);
|
||||
remove_device(i);
|
||||
}
|
||||
BX_UHCI_THIS device_change &= ~(1 << i);
|
||||
|
@ -3,7 +3,7 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (C) 2009-2016 Benjamin D Lunt (fys [at] fysnet [dot] net)
|
||||
// 2009-2016 The Bochs Project
|
||||
// 2009-2021 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
|
||||
|
@ -542,7 +542,7 @@ void bx_usb_xhci_c::reset_hc()
|
||||
sprintf(pname, "port%d", i+1);
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_XHCI)));
|
||||
} else {
|
||||
usb_set_connect_status(i, BX_XHCI_THIS hub.usb_port[i].device->get_type(), 1);
|
||||
usb_set_connect_status(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -975,7 +975,6 @@ void bx_usb_xhci_c::after_restore_state(void)
|
||||
|
||||
void bx_usb_xhci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
{
|
||||
int type;
|
||||
char pname[BX_PATHNAME_LEN];
|
||||
const char *devname = NULL;
|
||||
|
||||
@ -987,12 +986,12 @@ void bx_usb_xhci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
BX_ERROR(("init_device(): port%d already in use", port+1));
|
||||
return;
|
||||
}
|
||||
sprintf(pname, "usb_xhci.hub.port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root());
|
||||
type = DEV_usb_init_device(portconf, BX_XHCI_THIS_PTR, &BX_XHCI_THIS hub.usb_port[port].device);
|
||||
if (BX_XHCI_THIS hub.usb_port[port].device != NULL) {
|
||||
usb_set_connect_status(port, type, 1);
|
||||
BX_XHCI_THIS hub.usb_port[port].device->register_state(sr_list);
|
||||
if (DEV_usb_init_device(portconf, BX_XHCI_THIS_PTR, &BX_XHCI_THIS hub.usb_port[port].device)) {
|
||||
if (usb_set_connect_status(port, 1)) {
|
||||
sprintf(pname, "usb_xhci.hub.port%d.device", port+1);
|
||||
bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root());
|
||||
BX_XHCI_THIS hub.usb_port[port].device->register_state(sr_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3076,7 +3075,6 @@ void bx_usb_xhci_c::runtime_config(void)
|
||||
{
|
||||
int i;
|
||||
char pname[6];
|
||||
int type = -1;
|
||||
|
||||
for (i = 0; i < BX_N_USB_XHCI_PORTS; i++) {
|
||||
// device change support
|
||||
@ -3087,10 +3085,7 @@ void bx_usb_xhci_c::runtime_config(void)
|
||||
init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_XHCI)));
|
||||
} else {
|
||||
BX_INFO(("USB port #%d: device disconnect", i+1));
|
||||
if (BX_XHCI_THIS hub.usb_port[i].device != NULL) {
|
||||
type = BX_XHCI_THIS hub.usb_port[i].device->get_type();
|
||||
}
|
||||
usb_set_connect_status(i, type, 0);
|
||||
usb_set_connect_status(i, 0);
|
||||
}
|
||||
BX_XHCI_THIS device_change &= ~(1 << i);
|
||||
}
|
||||
@ -3139,63 +3134,61 @@ void bx_usb_xhci_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_l
|
||||
}
|
||||
}
|
||||
|
||||
void bx_usb_xhci_c::usb_set_connect_status(Bit8u port, int type, bool connected)
|
||||
bool bx_usb_xhci_c::usb_set_connect_status(Bit8u port, bool connected)
|
||||
{
|
||||
const bool ccs_org = BX_XHCI_THIS hub.usb_port[port].portsc.ccs;
|
||||
const bool ped_org = BX_XHCI_THIS hub.usb_port[port].portsc.ped;
|
||||
|
||||
usb_device_c *device = BX_XHCI_THIS hub.usb_port[port].device;
|
||||
if (device != NULL) {
|
||||
if (device->get_type() == type) {
|
||||
if (connected) {
|
||||
if ((device->get_speed() == USB_SPEED_SUPER) &&
|
||||
!BX_XHCI_THIS hub.usb_port[port].is_usb3) {
|
||||
BX_PANIC(("Super-speed device not supported on USB2 port."));
|
||||
usb_set_connect_status(port, type, 0);
|
||||
return;
|
||||
if (connected) {
|
||||
if ((device->get_speed() == USB_SPEED_SUPER) &&
|
||||
!BX_XHCI_THIS hub.usb_port[port].is_usb3) {
|
||||
BX_PANIC(("Super-speed device not supported on USB2 port."));
|
||||
usb_set_connect_status(port, 0);
|
||||
return 0;
|
||||
}
|
||||
if (BX_XHCI_THIS hub.usb_port[port].is_usb3) {
|
||||
if (!device->set_speed(USB_SPEED_SUPER)) {
|
||||
BX_PANIC(("Only super-speed devices supported on USB3 port."));
|
||||
usb_set_connect_status(port, 0);
|
||||
return 0;
|
||||
}
|
||||
if (BX_XHCI_THIS hub.usb_port[port].is_usb3) {
|
||||
if (!device->set_speed(USB_SPEED_SUPER)) {
|
||||
BX_PANIC(("Only super-speed devices supported on USB3 port."));
|
||||
usb_set_connect_status(port, type, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.speed = 2;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.speed = 1;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.speed = 3;
|
||||
break;
|
||||
case USB_SPEED_SUPER:
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.speed = 4;
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("USB device returned invalid speed value"));
|
||||
usb_set_connect_status(port, 0);
|
||||
return 0;
|
||||
}
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.ccs = 1;
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
usb_set_connect_status(port, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return 0;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
switch (device->get_speed()) {
|
||||
case USB_SPEED_LOW:
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.speed = 2;
|
||||
break;
|
||||
case USB_SPEED_FULL:
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.speed = 1;
|
||||
break;
|
||||
case USB_SPEED_HIGH:
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.speed = 3;
|
||||
break;
|
||||
case USB_SPEED_SUPER:
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.speed = 4;
|
||||
break;
|
||||
default:
|
||||
BX_PANIC(("USB device returned invalid speed value"));
|
||||
usb_set_connect_status(port, type, 0);
|
||||
return;
|
||||
}
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.ccs = 1;
|
||||
if (!device->get_connected()) {
|
||||
if (!device->init()) {
|
||||
usb_set_connect_status(port, type, 0);
|
||||
BX_ERROR(("port #%d: connect failed", port+1));
|
||||
return;
|
||||
} else {
|
||||
BX_INFO(("port #%d: connect: %s", port+1, device->get_info()));
|
||||
}
|
||||
}
|
||||
device->set_event_handler(BX_XHCI_THIS_PTR, xhci_event_handler, port);
|
||||
} else { // not connected
|
||||
}
|
||||
device->set_event_handler(BX_XHCI_THIS_PTR, xhci_event_handler, port);
|
||||
} else { // not connected
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.ccs = 0;
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.ped = 0;
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.speed = 0;
|
||||
remove_device(port);
|
||||
}
|
||||
}
|
||||
if (ccs_org != BX_XHCI_THIS hub.usb_port[port].portsc.ccs)
|
||||
BX_XHCI_THIS hub.usb_port[port].portsc.csc = 1;
|
||||
@ -3208,6 +3201,7 @@ void bx_usb_xhci_c::usb_set_connect_status(Bit8u port, int type, bool connected)
|
||||
write_event_TRB(0, ((port + 1) << 24), TRB_SET_COMP_CODE(1), TRB_SET_TYPE(PORT_STATUS_CHANGE), 1);
|
||||
}
|
||||
}
|
||||
return connected;
|
||||
}
|
||||
|
||||
// USB runtime parameter handler
|
||||
|
@ -565,7 +565,7 @@ private:
|
||||
|
||||
static void init_device(Bit8u port, bx_list_c *portconf);
|
||||
static void remove_device(Bit8u port);
|
||||
static void usb_set_connect_status(Bit8u port, int type, bool connected);
|
||||
static bool usb_set_connect_status(Bit8u port, bool connected);
|
||||
|
||||
static int broadcast_packet(USBPacket *p, const int port);
|
||||
static void xhci_timer_handler(void *);
|
||||
|
Loading…
Reference in New Issue
Block a user