commit
8eee519f4e
@ -267,9 +267,14 @@ void bx_init_usb_options(const char *usb_name, const char *pname, int maxports)
|
||||
"Options",
|
||||
descr,
|
||||
"", BX_PATHNAME_LEN);
|
||||
bx_param_bool_c *overcurrent = new bx_param_bool_c(port,
|
||||
"over_current",
|
||||
"signal over-current",
|
||||
"signal over-current", 0);
|
||||
port->set_group(group);
|
||||
deplist->add(port);
|
||||
deplist->add(device);
|
||||
deplist->add(overcurrent);
|
||||
deplist2 = new bx_list_c(NULL);
|
||||
deplist2->add(options);
|
||||
device->set_dependent_list(deplist2, 1);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -166,7 +166,7 @@ void bx_uhci_core_c::reset_uhci(unsigned type)
|
||||
hub.usb_port[j].resume = 0;
|
||||
hub.usb_port[j].suspend = 0;
|
||||
hub.usb_port[j].over_current_change = 0;
|
||||
hub.usb_port[j].over_current = 1;
|
||||
hub.usb_port[j].over_current = 0;
|
||||
hub.usb_port[j].enabled = 0;
|
||||
hub.usb_port[j].enable_changed = 0;
|
||||
hub.usb_port[j].status = 0;
|
||||
@ -564,7 +564,7 @@ void bx_uhci_core_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
||||
if (hub.usb_port[port].reset) {
|
||||
hub.usb_port[port].suspend = 0;
|
||||
hub.usb_port[port].over_current_change = 0;
|
||||
hub.usb_port[port].over_current = 1;
|
||||
hub.usb_port[port].over_current = 0;
|
||||
hub.usb_port[port].resume = 0;
|
||||
hub.usb_port[port].enabled = 0;
|
||||
// are we are currently connected/disconnected
|
||||
@ -645,7 +645,7 @@ void bx_uhci_core_c::uhci_timer(void)
|
||||
hub.usb_port[i].reset = 0;
|
||||
hub.usb_port[i].resume = 0;
|
||||
hub.usb_port[i].status = 0;
|
||||
hub.usb_port[i].over_current = 1;
|
||||
hub.usb_port[i].over_current = 0;
|
||||
hub.usb_port[i].over_current_change = 0;
|
||||
hub.usb_port[i].suspend = 0;
|
||||
}
|
||||
@ -734,10 +734,14 @@ void bx_uhci_core_c::uhci_timer(void)
|
||||
const int r_actlen = (((td.dword1 & 0x7FF) + 1) & 0x7FF);
|
||||
const int r_maxlen = (((td.dword2 >> 21) + 1) & 0x7FF);
|
||||
BX_DEBUG((" r_actlen = %d r_maxlen = %d", r_actlen, r_maxlen));
|
||||
if (((td.dword2 & 0xFF) == USB_TOKEN_IN) && spd && (queue_addr != 0) && (r_actlen < r_maxlen) && ((td.dword1 & 0x00FF0000) == 0)) {
|
||||
BX_DEBUG(("Short Packet Detected"));
|
||||
shortpacket = was_short = 1;
|
||||
td.dword1 |= (1<<29);
|
||||
if (((td.dword2 & 0xFF) == USB_TOKEN_IN) && (queue_addr != 0) && (r_actlen < r_maxlen) && ((td.dword1 & 0x00FF0000) == 0)) {
|
||||
if (spd) {
|
||||
BX_DEBUG(("Short Packet Detected"));
|
||||
shortpacket = was_short = 1;
|
||||
td.dword1 |= (1<<29);
|
||||
} else {
|
||||
BX_DEBUG(("A Short Packet was detected, but the SPD bit in DWORD1 was clear"));
|
||||
}
|
||||
}
|
||||
if (td.dword1 & (1<<22)) stalled = was_stall = 1;
|
||||
|
||||
|
@ -168,7 +168,7 @@ typedef struct {
|
||||
bool status;
|
||||
} usb_port[USB_UHCI_PORTS];
|
||||
|
||||
int max_bandwidth; // standard USB 1.1 is 1280 bytes (VTxxxxx models allowed a few more)
|
||||
int max_bandwidth; // standard USB 1.1 is 1280 bytes (VTxxxxx models allowed a few less (1023))
|
||||
int loop_reached; // did we reach our bandwidth loop limit
|
||||
Bit8u devfunc;
|
||||
} bx_uhci_core_t;
|
||||
|
@ -194,7 +194,7 @@ bx_usb_ehci_c::bx_usb_ehci_c()
|
||||
|
||||
bx_usb_ehci_c::~bx_usb_ehci_c()
|
||||
{
|
||||
char pname[16];
|
||||
char pname[32];
|
||||
int i;
|
||||
|
||||
SIM->unregister_runtime_config_handler(rt_conf_id);
|
||||
@ -209,6 +209,8 @@ bx_usb_ehci_c::~bx_usb_ehci_c()
|
||||
SIM->get_param_enum(pname, SIM->get_param(BXPN_USB_EHCI))->set_handler(NULL);
|
||||
sprintf(pname, "port%d.options", i+1);
|
||||
SIM->get_param_string(pname, SIM->get_param(BXPN_USB_EHCI))->set_enable_handler(NULL);
|
||||
sprintf(pname, "port%d.over_current", i+1);
|
||||
SIM->get_param_bool(pname, SIM->get_param(BXPN_USB_EHCI))->set_handler(NULL);
|
||||
remove_device(i);
|
||||
}
|
||||
|
||||
@ -225,7 +227,14 @@ void bx_usb_ehci_c::init(void)
|
||||
bx_list_c *ehci, *port;
|
||||
bx_param_enum_c *device;
|
||||
bx_param_string_c *options;
|
||||
bx_param_bool_c *over_current;
|
||||
Bit8u devfunc;
|
||||
|
||||
/* If you wish to set DEBUG=report in the code, instead of
|
||||
* in the configuration, simply uncomment this line. I use
|
||||
* it when I am working on this emulation.
|
||||
*/
|
||||
//LOG_THIS setonoff(LOGLEV_DEBUG, ACT_REPORT);
|
||||
|
||||
// Read in values from config interface
|
||||
ehci = (bx_list_c*) SIM->get_param(BXPN_USB_EHCI);
|
||||
@ -283,6 +292,8 @@ void bx_usb_ehci_c::init(void)
|
||||
device->set_handler(usb_param_handler);
|
||||
options = (bx_param_string_c*)port->get_by_name("options");
|
||||
options->set_enable_handler(usb_param_enable_handler);
|
||||
over_current = (bx_param_bool_c*)port->get_by_name("over_current");
|
||||
over_current->set_handler(usb_param_oc_handler);
|
||||
BX_EHCI_THIS hub.usb_port[i].device = NULL;
|
||||
BX_EHCI_THIS hub.usb_port[i].owner_change = 0;
|
||||
BX_EHCI_THIS hub.usb_port[i].portsc.ccs = 0;
|
||||
@ -530,6 +541,7 @@ void bx_usb_ehci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
} else {
|
||||
((bx_param_enum_c*)portconf->get_by_name("device"))->set_by_name("none");
|
||||
((bx_param_string_c*)portconf->get_by_name("options"))->set("none");
|
||||
((bx_param_bool_c*)portconf->get_by_name("over_current"))->set(0);
|
||||
set_connect_status(port, 0);
|
||||
}
|
||||
}
|
||||
@ -1370,6 +1382,15 @@ int bx_usb_ehci_c::execute(EHCIPacket *p)
|
||||
int ret;
|
||||
int endp;
|
||||
|
||||
// if we remove the device, or signal an over-current, there is a possibility
|
||||
// that 'dev' is NULL. simply return that we transfered zero bytes.
|
||||
// ( we can't return USB_RET_PROCERR, since this code will then reset the HC.
|
||||
// On an over-current, we don't want the HC to reset... )
|
||||
if (p->queue->dev == NULL) {
|
||||
BX_DEBUG(("Attempting to execute a packet with no device attached."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
BX_ASSERT(p->async == EHCI_ASYNC_NONE ||
|
||||
p->async == EHCI_ASYNC_INITIALIZED);
|
||||
|
||||
@ -2329,6 +2350,32 @@ Bit64s bx_usb_ehci_c::usb_param_handler(bx_param_c *param, bool set, Bit64s val)
|
||||
return val;
|
||||
}
|
||||
|
||||
// USB runtime parameter handler: over-current
|
||||
Bit64s bx_usb_ehci_c::usb_param_oc_handler(bx_param_c *param, bool set, Bit64s val)
|
||||
{
|
||||
int portnum;
|
||||
|
||||
if (set && val) {
|
||||
portnum = atoi((param->get_parent())->get_name()+4) - 1;
|
||||
if ((portnum >= 0) && (portnum < USB_EHCI_PORTS)) {
|
||||
if (BX_EHCI_THIS hub.usb_port[portnum].portsc.ccs) {
|
||||
// EHCI, section 4.2.5, page 58
|
||||
BX_EHCI_THIS hub.usb_port[portnum].portsc.occ = 1;
|
||||
BX_EHCI_THIS hub.usb_port[portnum].portsc.oca = 1;
|
||||
BX_EHCI_THIS hub.usb_port[portnum].portsc.pec = 1;
|
||||
BX_EHCI_THIS hub.usb_port[portnum].portsc.ped = 0;
|
||||
BX_EHCI_THIS hub.usb_port[portnum].portsc.pp = 0; // optional (the HC may leave power on, limiting the current)
|
||||
BX_DEBUG(("Over-current signaled on port #%d.", portnum + 1));
|
||||
BX_EHCI_THIS raise_irq(USBSTS_PCD);
|
||||
}
|
||||
} else {
|
||||
BX_ERROR(("Over-current: Bad portnum given: %d", portnum + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // clear the indicator for next time
|
||||
}
|
||||
|
||||
// USB runtime parameter enable handler
|
||||
bool bx_usb_ehci_c::usb_param_enable_handler(bx_param_c *param, bool en)
|
||||
{
|
||||
|
@ -419,6 +419,7 @@ private:
|
||||
void runtime_config(void);
|
||||
|
||||
static Bit64s usb_param_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
static Bit64s usb_param_oc_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
static bool usb_param_enable_handler(bx_param_c *param, bool en);
|
||||
};
|
||||
|
||||
|
@ -254,6 +254,7 @@ bool usb_hub_device_c::init()
|
||||
bx_list_c *port, *deplist;
|
||||
bx_param_enum_c *device;
|
||||
bx_param_string_c *options;
|
||||
bx_param_bool_c *overcurrent;
|
||||
|
||||
// set up config descriptor, status and runtime config for hub.n_ports
|
||||
bx_hub_config_descriptor[22] = (hub.n_ports + 1 + 7) / 8;
|
||||
@ -272,8 +273,14 @@ bool usb_hub_device_c::init()
|
||||
options = new bx_param_string_c(port, "options", "Options", "", "",
|
||||
BX_PATHNAME_LEN);
|
||||
options->set_enable_handler(hub_param_enable_handler);
|
||||
overcurrent = new bx_param_bool_c(port,
|
||||
"over_current",
|
||||
"signal over-current",
|
||||
"signal over-current", 0);
|
||||
overcurrent->set_handler(hub_param_oc_handler);
|
||||
deplist = new bx_list_c(NULL);
|
||||
deplist->add(options);
|
||||
deplist->add(overcurrent);
|
||||
device->set_dependent_list(deplist, 1);
|
||||
device->set_dependent_bitmap(0, 0);
|
||||
}
|
||||
@ -601,12 +608,8 @@ void usb_hub_device_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
|
||||
void usb_hub_device_c::remove_device(Bit8u port)
|
||||
{
|
||||
// TODO: there is something wrong with 'delete'ing hub.usb_port[port].device
|
||||
// Bochs crashes and doesn't delete the .lock file when we close Bochs
|
||||
if (hub.usb_port[port].device != NULL) {
|
||||
|
||||
delete hub.usb_port[port].device; // this is the culprit. Somewhere in the destruction of usb_device_c, something happens.
|
||||
// simply freeing (free(hub.usb_port[port].device)) it, doesn't crash, so it is one of the destructors...
|
||||
delete hub.usb_port[port].device;
|
||||
hub.usb_port[port].device = NULL;
|
||||
}
|
||||
}
|
||||
@ -764,6 +767,28 @@ bool usb_hub_device_c::hub_param_enable_handler(bx_param_c *param, bool en)
|
||||
return en;
|
||||
}
|
||||
|
||||
// USB runtime parameter handler: over-current
|
||||
Bit64s usb_hub_device_c::hub_param_oc_handler(bx_param_c *param, bool set, Bit64s val)
|
||||
{
|
||||
int portnum;
|
||||
usb_hub_device_c *hub;
|
||||
bx_list_c *port;
|
||||
|
||||
if (set && val) {
|
||||
port = (bx_list_c *) param->get_parent();
|
||||
hub = (usb_hub_device_c *) (port->get_parent()->get_device_param());
|
||||
if (hub != NULL) {
|
||||
portnum = atoi(port->get_name()+4) - 1;
|
||||
hub->hub.usb_port[portnum].PortStatus &= ~PORT_STAT_POWER;
|
||||
hub->hub.usb_port[portnum].PortStatus |= PORT_STAT_OVERCURRENT;
|
||||
hub->hub.usb_port[portnum].PortChange |= PORT_STAT_C_OVERCURRENT;
|
||||
BX_DEBUG(("Over-current signaled on port #%d.", portnum + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // clear the indicator for next time
|
||||
}
|
||||
|
||||
void usb_hub_restore_handler(void *dev, bx_list_c *conf)
|
||||
{
|
||||
if (dev != NULL) {
|
||||
|
@ -77,6 +77,7 @@ private:
|
||||
|
||||
static Bit64s hub_param_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
static bool hub_param_enable_handler(bx_param_c *param, bool en);
|
||||
static Bit64s hub_param_oc_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -137,7 +137,7 @@ bx_usb_ohci_c::bx_usb_ohci_c()
|
||||
|
||||
bx_usb_ohci_c::~bx_usb_ohci_c()
|
||||
{
|
||||
char pname[16];
|
||||
char pname[32];
|
||||
|
||||
SIM->unregister_runtime_config_handler(hub.rt_conf_id);
|
||||
|
||||
@ -146,6 +146,8 @@ bx_usb_ohci_c::~bx_usb_ohci_c()
|
||||
SIM->get_param_enum(pname, SIM->get_param(BXPN_USB_OHCI))->set_handler(NULL);
|
||||
sprintf(pname, "port%d.options", i+1);
|
||||
SIM->get_param_string(pname, SIM->get_param(BXPN_USB_OHCI))->set_enable_handler(NULL);
|
||||
sprintf(pname, "port%d.over_current", i+1);
|
||||
SIM->get_param_bool(pname, SIM->get_param(BXPN_USB_OHCI))->set_handler(NULL);
|
||||
remove_device(i);
|
||||
}
|
||||
|
||||
@ -162,6 +164,7 @@ void bx_usb_ohci_c::init(void)
|
||||
bx_list_c *ohci, *port;
|
||||
bx_param_enum_c *device;
|
||||
bx_param_string_c *options;
|
||||
bx_param_bool_c *over_current;
|
||||
|
||||
/* If you wish to set DEBUG=report in the code, instead of
|
||||
* in the configuration, simply uncomment this line. I use
|
||||
@ -208,6 +211,8 @@ void bx_usb_ohci_c::init(void)
|
||||
device->set_handler(usb_param_handler);
|
||||
options = (bx_param_string_c*)port->get_by_name("options");
|
||||
options->set_enable_handler(usb_param_enable_handler);
|
||||
over_current = (bx_param_bool_c*)port->get_by_name("over_current");
|
||||
over_current->set_handler(usb_param_oc_handler);
|
||||
BX_OHCI_THIS hub.usb_port[i].device = NULL;
|
||||
BX_OHCI_THIS hub.usb_port[i].HcRhPortStatus.ccs = 0;
|
||||
BX_OHCI_THIS hub.usb_port[i].HcRhPortStatus.csc = 0;
|
||||
@ -373,7 +378,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, 1);
|
||||
set_connect_status(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,7 +503,7 @@ void bx_usb_ohci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
char pname[BX_PATHNAME_LEN];
|
||||
|
||||
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)) {
|
||||
if (set_connect_status(port, 1)) {
|
||||
portconf->get_by_name("options")->set_enabled(0);
|
||||
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());
|
||||
@ -506,7 +511,8 @@ void bx_usb_ohci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
} else {
|
||||
((bx_param_enum_c*)portconf->get_by_name("device"))->set_by_name("none");
|
||||
((bx_param_string_c*)portconf->get_by_name("options"))->set("none");
|
||||
usb_set_connect_status(port, 0);
|
||||
((bx_param_bool_c*)portconf->get_by_name("over_current"))->set(0);
|
||||
set_connect_status(port, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -684,24 +690,21 @@ bool bx_usb_ohci_c::read_handler(bx_phy_address addr, unsigned len, void *data,
|
||||
#endif
|
||||
case 0x54: // HcRhPortStatus[0]
|
||||
p = (offset - 0x54) >> 2;
|
||||
if (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps == 1) {
|
||||
val = (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved0 << 21)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prsc ? (1 << 20) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ocic ? (1 << 19) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pssc ? (1 << 18) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pesc ? (1 << 17) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.csc ? (1 << 16) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved1 << 10)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.lsda ? (1 << 9) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps ? (1 << 8) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved2 << 5)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prs ? (1 << 4) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.poci ? (1 << 3) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pss ? (1 << 2) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pes ? (1 << 1) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ccs ? (1 << 0) : 0);
|
||||
} else
|
||||
val = 0;
|
||||
val = (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved0 << 21)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prsc ? (1 << 20) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ocic ? (1 << 19) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pssc ? (1 << 18) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pesc ? (1 << 17) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.csc ? (1 << 16) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved1 << 10)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.lsda ? (1 << 9) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps ? (1 << 8) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved2 << 5)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prs ? (1 << 4) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.poci ? (1 << 3) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pss ? (1 << 2) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pes ? (1 << 1) : 0)
|
||||
| (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ccs ? (1 << 0) : 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -979,7 +982,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, 1);
|
||||
set_connect_status(p, 1);
|
||||
BX_OHCI_THIS hub.usb_port[p].device->usb_send_msg(USB_MSG_RESET);
|
||||
}
|
||||
set_interrupt(OHCI_INTR_RHSC);
|
||||
@ -1433,7 +1436,7 @@ void bx_usb_ohci_c::runtime_config(void)
|
||||
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, 0);
|
||||
set_connect_status(i, 0);
|
||||
}
|
||||
BX_OHCI_THIS hub.device_change &= ~(1 << i);
|
||||
}
|
||||
@ -1473,7 +1476,7 @@ void bx_usb_ohci_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_l
|
||||
}
|
||||
}
|
||||
|
||||
bool bx_usb_ohci_c::usb_set_connect_status(Bit8u port, bool connected)
|
||||
bool bx_usb_ohci_c::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;
|
||||
@ -1544,6 +1547,42 @@ Bit64s bx_usb_ohci_c::usb_param_handler(bx_param_c *param, bool set, Bit64s val)
|
||||
return val;
|
||||
}
|
||||
|
||||
// USB runtime parameter handler: over-current
|
||||
Bit64s bx_usb_ohci_c::usb_param_oc_handler(bx_param_c *param, bool set, Bit64s val)
|
||||
{
|
||||
int portnum;
|
||||
|
||||
if (set && val) {
|
||||
if (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.nocp == 0) {
|
||||
portnum = atoi((param->get_parent())->get_name()+4) - 1;
|
||||
if ((portnum >= 0) && (portnum < USB_OHCI_PORTS)) {
|
||||
if (BX_OHCI_THIS hub.usb_port[portnum].HcRhPortStatus.ccs) {
|
||||
// is over current reported on a per-port basis?
|
||||
if (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.ocpm == 1) {
|
||||
BX_OHCI_THIS hub.usb_port[portnum].HcRhPortStatus.ocic = 1;
|
||||
BX_OHCI_THIS hub.usb_port[portnum].HcRhPortStatus.poci = 1;
|
||||
BX_OHCI_THIS hub.usb_port[portnum].HcRhPortStatus.pes = 0;
|
||||
BX_OHCI_THIS hub.usb_port[portnum].HcRhPortStatus.pesc = 1;
|
||||
BX_OHCI_THIS hub.usb_port[portnum].HcRhPortStatus.pps = 0;
|
||||
BX_DEBUG(("Over-current signaled on port #%d.", portnum + 1));
|
||||
// else over current is reported globally
|
||||
} else {
|
||||
BX_OHCI_THIS hub.op_regs.HcRhStatus.oci = 1;
|
||||
BX_DEBUG(("Global over-current signaled."));
|
||||
}
|
||||
set_interrupt(OHCI_INTR_RHSC);
|
||||
}
|
||||
} else {
|
||||
BX_ERROR(("Over-current: Bad portnum given: %d", portnum + 1));
|
||||
}
|
||||
} else {
|
||||
BX_DEBUG(("Over-current signaled with NOCP set."));
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // clear the indicator for next time
|
||||
}
|
||||
|
||||
// USB runtime parameter enable handler
|
||||
bool bx_usb_ohci_c::usb_param_enable_handler(bx_param_c *param, bool en)
|
||||
{
|
||||
|
@ -275,7 +275,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 bool usb_set_connect_status(Bit8u port, bool connected);
|
||||
static bool set_connect_status(Bit8u port, bool connected);
|
||||
|
||||
static void usb_frame_handler(void *);
|
||||
void usb_frame_timer(void);
|
||||
@ -298,6 +298,7 @@ private:
|
||||
void runtime_config(void);
|
||||
|
||||
static Bit64s usb_param_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
static Bit64s usb_param_oc_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
static bool usb_param_enable_handler(bx_param_c *param, bool en);
|
||||
};
|
||||
|
||||
|
@ -401,7 +401,8 @@ int usb_msd_device_c::uasp_do_data(UASPRequest *req, USBPacket *p)
|
||||
req->usb_len = 0;
|
||||
}
|
||||
|
||||
usb_dump_packet(p->data, len, 0, p->devaddr, ((UASP_GET_DIR(req->mode) == USB_TOKEN_IN) ? USB_DIR_IN : USB_DIR_OUT) | p->devep, USB_TRANS_TYPE_BULK, false, true);
|
||||
// This fills the log.txt file extremely fast, so I comment it out.
|
||||
//usb_dump_packet(p->data, len, 0, p->devaddr, ((UASP_GET_DIR(req->mode) == USB_TOKEN_IN) ? USB_DIR_IN : USB_DIR_OUT) | p->devep, USB_TRANS_TYPE_BULK, false, true);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
@ -102,26 +102,30 @@ PLUGIN_ENTRY_FOR_MODULE(usb_uhci)
|
||||
bx_usb_uhci_c::bx_usb_uhci_c()
|
||||
{
|
||||
put("usb_uhci", "UHCI");
|
||||
device_change = 0;
|
||||
rt_conf_id = -1;
|
||||
}
|
||||
|
||||
bx_usb_uhci_c::~bx_usb_uhci_c()
|
||||
{
|
||||
char pname[16];
|
||||
char pname[32];
|
||||
|
||||
SIM->unregister_runtime_config_handler(rt_conf_id);
|
||||
|
||||
|
||||
for (int i=0; i<USB_UHCI_PORTS; i++) {
|
||||
sprintf(pname, "port%d.device", i+1);
|
||||
SIM->get_param_enum(pname, SIM->get_param(BXPN_USB_UHCI))->set_handler(NULL);
|
||||
sprintf(pname, "port%d.options", i+1);
|
||||
SIM->get_param_string(pname, SIM->get_param(BXPN_USB_UHCI))->set_enable_handler(NULL);
|
||||
sprintf(pname, "port%d.over_current", i+1);
|
||||
SIM->get_param_bool(pname, SIM->get_param(BXPN_USB_UHCI))->set_handler(NULL);
|
||||
remove_device(i);
|
||||
}
|
||||
|
||||
|
||||
SIM->get_bochs_root()->remove("usb_uhci");
|
||||
bx_list_c *usb_rt = (bx_list_c *) SIM->get_param(BXPN_MENU_RUNTIME_USB);
|
||||
usb_rt->remove("uhci");
|
||||
|
||||
BX_DEBUG(("Exit"));
|
||||
}
|
||||
|
||||
@ -132,6 +136,7 @@ void bx_usb_uhci_c::init(void)
|
||||
bx_list_c *uhci, *port;
|
||||
bx_param_enum_c *device;
|
||||
bx_param_string_c *options;
|
||||
bx_param_bool_c *over_current;
|
||||
Bit8u devfunc;
|
||||
Bit16u devid;
|
||||
|
||||
@ -174,6 +179,8 @@ void bx_usb_uhci_c::init(void)
|
||||
device->set_handler(usb_param_handler);
|
||||
options = (bx_param_string_c *) port->get_by_name("options");
|
||||
options->set_enable_handler(usb_param_enable_handler);
|
||||
over_current = (bx_param_bool_c *) port->get_by_name("over_current");
|
||||
over_current->set_handler(usb_param_oc_handler);
|
||||
}
|
||||
|
||||
// register handler for correct device connect handling after runtime config
|
||||
@ -220,6 +227,7 @@ void bx_usb_uhci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
} else {
|
||||
((bx_param_enum_c *) portconf->get_by_name("device"))->set_by_name("none");
|
||||
((bx_param_string_c *) portconf->get_by_name("options"))->set("none");
|
||||
((bx_param_bool_c *) portconf->get_by_name("over_current"))->set(0);
|
||||
set_connect_status(port, 0);
|
||||
}
|
||||
}
|
||||
@ -287,6 +295,31 @@ Bit64s bx_usb_uhci_c::usb_param_handler(bx_param_c *param, bool set, Bit64s val)
|
||||
return val;
|
||||
}
|
||||
|
||||
// USB runtime parameter handler: over-current
|
||||
Bit64s bx_usb_uhci_c::usb_param_oc_handler(bx_param_c *param, bool set, Bit64s val)
|
||||
{
|
||||
int portnum;
|
||||
|
||||
if (set && val) {
|
||||
portnum = atoi((param->get_parent())->get_name()+4) - 1;
|
||||
if ((portnum >= 0) && (portnum < USB_UHCI_PORTS)) {
|
||||
if (BX_UHCI_THIS hub.usb_port[portnum].status) {
|
||||
// The UHCI specification does not specify what happens when an over-current
|
||||
// condition exists. Therefore, we will set the condition and then envoke
|
||||
// an interrupt. Hopefully the guest will check the port change.
|
||||
BX_UHCI_THIS hub.usb_port[portnum].over_current_change = 1;
|
||||
BX_UHCI_THIS hub.usb_port[portnum].over_current = 1;
|
||||
BX_DEBUG(("Over-current signaled on port #%d.", portnum + 1));
|
||||
BX_UHCI_THIS update_irq();
|
||||
}
|
||||
} else {
|
||||
BX_ERROR(("Over-current: Bad portnum given: %d", portnum + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // clear the indicator for next time
|
||||
}
|
||||
|
||||
// USB runtime parameter enable handler
|
||||
bool bx_usb_uhci_c::usb_param_enable_handler(bx_param_c *param, bool en)
|
||||
{
|
||||
|
@ -50,6 +50,7 @@ private:
|
||||
void runtime_config(void);
|
||||
|
||||
static Bit64s usb_param_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
static Bit64s usb_param_oc_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
static bool usb_param_enable_handler(bx_param_c *param, bool en);
|
||||
};
|
||||
|
||||
|
@ -148,8 +148,6 @@ static Bit8u ext_caps[EXT_CAPS_SIZE] = {
|
||||
// builtin configuration handling functions
|
||||
Bit32s usb_xhci_options_parser(const char *context, int num_params, char *params[])
|
||||
{
|
||||
int max_ports;
|
||||
|
||||
if (!strcmp(params[0], "usb_xhci")) {
|
||||
bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_USB_XHCI);
|
||||
for (int i = 1; i < num_params; i++) {
|
||||
@ -163,7 +161,7 @@ Bit32s usb_xhci_options_parser(const char *context, int num_params, char *params
|
||||
else
|
||||
BX_PANIC(("%s: unknown parameter '%s' for usb_xhci: model=", context, ¶ms[i][6]));
|
||||
} else if (!strncmp(params[i], "n_ports=", 8)) {
|
||||
max_ports = (int) strtol(¶ms[i][8], NULL, 10);
|
||||
int max_ports = (int) strtol(¶ms[i][8], NULL, 10);
|
||||
if ((max_ports >= 2) && (max_ports <= USB_XHCI_PORTS_MAX) && !(max_ports & 1))
|
||||
SIM->get_param_num(BXPN_XHCI_N_PORTS)->set(max_ports);
|
||||
else
|
||||
@ -225,7 +223,7 @@ bx_usb_xhci_c::bx_usb_xhci_c()
|
||||
|
||||
bx_usb_xhci_c::~bx_usb_xhci_c()
|
||||
{
|
||||
char pname[16];
|
||||
char pname[32];
|
||||
|
||||
SIM->unregister_runtime_config_handler(rt_conf_id);
|
||||
|
||||
@ -234,6 +232,8 @@ bx_usb_xhci_c::~bx_usb_xhci_c()
|
||||
SIM->get_param_enum(pname, SIM->get_param(BXPN_USB_XHCI))->set_handler(NULL);
|
||||
sprintf(pname, "port%d.options", i+1);
|
||||
SIM->get_param_string(pname, SIM->get_param(BXPN_USB_XHCI))->set_enable_handler(NULL);
|
||||
sprintf(pname, "port%d.over_current", i+1);
|
||||
SIM->get_param_bool(pname, SIM->get_param(BXPN_USB_XHCI))->set_handler(NULL);
|
||||
remove_device(i);
|
||||
}
|
||||
|
||||
@ -251,6 +251,7 @@ void bx_usb_xhci_c::init(void)
|
||||
bx_list_c *xhci, *port;
|
||||
bx_param_enum_c *device;
|
||||
bx_param_string_c *options;
|
||||
bx_param_bool_c *over_current;
|
||||
struct XHCI_PROTOCOL *protocol;
|
||||
|
||||
/* If you wish to set DEBUG=report in the code, instead of
|
||||
@ -303,7 +304,7 @@ void bx_usb_xhci_c::init(void)
|
||||
Bit32s n_ports = SIM->get_param_num(BXPN_XHCI_N_PORTS)->get();
|
||||
if (n_ports > -1) BX_XHCI_THIS hub.n_ports = n_ports;
|
||||
if ((BX_XHCI_THIS hub.n_ports < 2) || (BX_XHCI_THIS hub.n_ports > USB_XHCI_PORTS_MAX) || (BX_XHCI_THIS hub.n_ports & 1)) {
|
||||
BX_PANIC(("n_ports (%d) must be at least 2, not more than 10, and must be an even number.", BX_XHCI_THIS hub.n_ports));
|
||||
BX_PANIC(("n_ports (%d) must be at least 2, not more than %d, and must be an even number.", BX_XHCI_THIS hub.n_ports, USB_XHCI_PORTS_MAX));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -342,6 +343,8 @@ void bx_usb_xhci_c::init(void)
|
||||
device->set_handler(usb_param_handler);
|
||||
options = (bx_param_string_c*)port->get_by_name("options");
|
||||
options->set_enable_handler(usb_param_enable_handler);
|
||||
over_current = (bx_param_bool_c*)port->get_by_name("over_current");
|
||||
over_current->set_handler(usb_param_oc_handler);
|
||||
BX_XHCI_THIS hub.usb_port[i].device = NULL;
|
||||
BX_XHCI_THIS hub.usb_port[i].portsc.ccs = 0;
|
||||
BX_XHCI_THIS hub.usb_port[i].portsc.csc = 0;
|
||||
@ -648,7 +651,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, 1);
|
||||
set_connect_status(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1091,7 +1094,7 @@ void bx_usb_xhci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
char pname[BX_PATHNAME_LEN];
|
||||
|
||||
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)) {
|
||||
if (set_connect_status(port, 1)) {
|
||||
portconf->get_by_name("options")->set_enabled(0);
|
||||
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());
|
||||
@ -1099,7 +1102,8 @@ void bx_usb_xhci_c::init_device(Bit8u port, bx_list_c *portconf)
|
||||
} else {
|
||||
((bx_param_enum_c*)portconf->get_by_name("device"))->set_by_name("none");
|
||||
((bx_param_string_c*)portconf->get_by_name("options"))->set("none");
|
||||
usb_set_connect_status(port, 0);
|
||||
((bx_param_bool_c*)portconf->get_by_name("over_current"))->set(0);
|
||||
set_connect_status(port, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1611,7 +1615,6 @@ bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data,
|
||||
BX_XHCI_THIS hub.op_regs.HcStatus.pcd = (value & (1 << 4)) ? 0 : BX_XHCI_THIS hub.op_regs.HcStatus.pcd;
|
||||
BX_XHCI_THIS hub.op_regs.HcStatus.eint = (value & (1 << 3)) ? 0 : BX_XHCI_THIS hub.op_regs.HcStatus.eint;
|
||||
BX_XHCI_THIS hub.op_regs.HcStatus.hse = (value & (1 << 2)) ? 0 : BX_XHCI_THIS hub.op_regs.HcStatus.hse;
|
||||
//FIXME: should this line go where system software clears the IP bit, or here when it clears the status:eint bit?
|
||||
if (value & (1 << 3)) // acknowledging the interrupt
|
||||
DEV_pci_set_irq(BX_XHCI_THIS devfunc, BX_XHCI_THIS pci_conf[0x3d], 0);
|
||||
break;
|
||||
@ -3487,6 +3490,12 @@ void bx_usb_xhci_c::xhci_timer(void)
|
||||
*/
|
||||
for (port=0; port<BX_XHCI_THIS hub.n_ports; port++) {
|
||||
new_psceg = get_psceg(port);
|
||||
// if any bit has transitioned from 0 to 1 (in any port),
|
||||
// set the pcd bit in the host status register.
|
||||
if ((new_psceg & BX_XHCI_THIS hub.usb_port[port].psceg) > 0)
|
||||
BX_XHCI_THIS hub.op_regs.HcStatus.pcd = 1;
|
||||
// clear any bits that have been cleared by the guest,
|
||||
// if we are now zero *and* there are any new bits set, send a Change Event.
|
||||
BX_XHCI_THIS hub.usb_port[port].psceg &= new_psceg;
|
||||
if ((BX_XHCI_THIS hub.usb_port[port].psceg == 0) && (new_psceg != 0)) {
|
||||
BX_DEBUG(("Port #%d Status Change Event: (%2Xh)", port + 1, new_psceg));
|
||||
@ -3536,7 +3545,7 @@ void bx_usb_xhci_c::runtime_config(void)
|
||||
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, 0);
|
||||
set_connect_status(i, 0);
|
||||
}
|
||||
BX_XHCI_THIS device_change &= ~(1 << i);
|
||||
}
|
||||
@ -3585,7 +3594,7 @@ void bx_usb_xhci_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_l
|
||||
}
|
||||
}
|
||||
|
||||
bool bx_usb_xhci_c::usb_set_connect_status(Bit8u port, bool connected)
|
||||
bool bx_usb_xhci_c::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;
|
||||
@ -3683,6 +3692,28 @@ Bit64s bx_usb_xhci_c::usb_param_handler(bx_param_c *param, bool set, Bit64s val)
|
||||
return val;
|
||||
}
|
||||
|
||||
// USB runtime parameter handler: over-current
|
||||
Bit64s bx_usb_xhci_c::usb_param_oc_handler(bx_param_c *param, bool set, Bit64s val)
|
||||
{
|
||||
int portnum;
|
||||
|
||||
if (set) {
|
||||
portnum = atoi((param->get_parent())->get_name()+4) - 1;
|
||||
if ((portnum >= 0) && (portnum < (int) BX_XHCI_THIS hub.n_ports)) {
|
||||
if (val) {
|
||||
if (BX_XHCI_THIS hub.usb_port[portnum].portsc.ccs) {
|
||||
BX_XHCI_THIS hub.usb_port[portnum].portsc.occ = 1;
|
||||
BX_XHCI_THIS hub.usb_port[portnum].portsc.oca = 1;
|
||||
BX_DEBUG(("Over-current signaled on port #%d.", portnum + 1));
|
||||
write_event_TRB(0, ((portnum + 1) << 24), TRB_SET_COMP_CODE(1), TRB_SET_TYPE(PORT_STATUS_CHANGE), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // clear the indicator for next time
|
||||
}
|
||||
|
||||
// USB runtime parameter enable handler
|
||||
bool bx_usb_xhci_c::usb_param_enable_handler(bx_param_c *param, bool en)
|
||||
{
|
||||
|
@ -620,7 +620,7 @@ private:
|
||||
|
||||
static void init_device(Bit8u port, bx_list_c *portconf);
|
||||
static void remove_device(Bit8u port);
|
||||
static bool usb_set_connect_status(Bit8u port, bool connected);
|
||||
static bool set_connect_status(Bit8u port, bool connected);
|
||||
|
||||
static int broadcast_speed(const int slot);
|
||||
static int broadcast_packet(USBPacket *p, const int port);
|
||||
@ -668,6 +668,7 @@ private:
|
||||
void runtime_config(void);
|
||||
|
||||
static Bit64s usb_param_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
static Bit64s usb_param_oc_handler(bx_param_c *param, bool set, Bit64s val);
|
||||
static bool usb_param_enable_handler(bx_param_c *param, bool en);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user