Fix USB root hub hotplugging.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1931 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
6cb7ee859a
commit
6106487019
@ -248,19 +248,39 @@ struct ohci_td {
|
|||||||
#define OHCI_CC_BUFFEROVERRUN 0xc
|
#define OHCI_CC_BUFFEROVERRUN 0xc
|
||||||
#define OHCI_CC_BUFFERUNDERRUN 0xd
|
#define OHCI_CC_BUFFERUNDERRUN 0xd
|
||||||
|
|
||||||
|
/* Update IRQ levels */
|
||||||
|
static inline void ohci_intr_update(OHCIState *ohci)
|
||||||
|
{
|
||||||
|
int level = 0;
|
||||||
|
|
||||||
|
if ((ohci->intr & OHCI_INTR_MIE) &&
|
||||||
|
(ohci->intr_status & ohci->intr))
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
pci_set_irq(&ohci->pci_dev, 0, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set an interrupt */
|
||||||
|
static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
|
||||||
|
{
|
||||||
|
ohci->intr_status |= intr;
|
||||||
|
ohci_intr_update(ohci);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach or detach a device on a root hub port. */
|
||||||
static void ohci_attach(USBPort *port1, USBDevice *dev)
|
static void ohci_attach(USBPort *port1, USBDevice *dev)
|
||||||
{
|
{
|
||||||
OHCIState *s = port1->opaque;
|
OHCIState *s = port1->opaque;
|
||||||
OHCIPort *port = &s->rhport[port1->index];
|
OHCIPort *port = &s->rhport[port1->index];
|
||||||
|
uint32_t old_state = port->ctrl;
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
if (port->port.dev) {
|
if (port->port.dev) {
|
||||||
usb_attach(port1, NULL);
|
usb_attach(port1, NULL);
|
||||||
}
|
}
|
||||||
/* set connect status */
|
/* set connect status */
|
||||||
if (!(port->ctrl & OHCI_PORT_CCS)) {
|
port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
|
||||||
port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
|
|
||||||
}
|
|
||||||
/* update speed */
|
/* update speed */
|
||||||
if (dev->speed == USB_SPEED_LOW)
|
if (dev->speed == USB_SPEED_LOW)
|
||||||
port->ctrl |= OHCI_PORT_LSDA;
|
port->ctrl |= OHCI_PORT_LSDA;
|
||||||
@ -273,8 +293,9 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
|
|||||||
dprintf("usb-ohci: Attached port %d\n", port1->index);
|
dprintf("usb-ohci: Attached port %d\n", port1->index);
|
||||||
} else {
|
} else {
|
||||||
/* set connect status */
|
/* set connect status */
|
||||||
if (!(port->ctrl & OHCI_PORT_CCS)) {
|
if (port->ctrl & OHCI_PORT_CCS) {
|
||||||
port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
|
port->ctrl &= ~OHCI_PORT_CCS;
|
||||||
|
port->ctrl |= OHCI_PORT_CSC;
|
||||||
}
|
}
|
||||||
/* disable port */
|
/* disable port */
|
||||||
if (port->ctrl & OHCI_PORT_PES) {
|
if (port->ctrl & OHCI_PORT_PES) {
|
||||||
@ -290,6 +311,9 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
|
|||||||
port->port.dev = NULL;
|
port->port.dev = NULL;
|
||||||
dprintf("usb-ohci: Detached port %d\n", port1->index);
|
dprintf("usb-ohci: Detached port %d\n", port1->index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (old_state != port->ctrl)
|
||||||
|
ohci_set_interrupt(s, OHCI_INTR_RHSC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the controller */
|
/* Reset the controller */
|
||||||
@ -335,25 +359,6 @@ static void ohci_reset(OHCIState *ohci)
|
|||||||
dprintf("usb-ohci: Reset %s\n", ohci->pci_dev.name);
|
dprintf("usb-ohci: Reset %s\n", ohci->pci_dev.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update IRQ levels */
|
|
||||||
static inline void ohci_intr_update(OHCIState *ohci)
|
|
||||||
{
|
|
||||||
int level = 0;
|
|
||||||
|
|
||||||
if ((ohci->intr & OHCI_INTR_MIE) &&
|
|
||||||
(ohci->intr_status & ohci->intr))
|
|
||||||
level = 1;
|
|
||||||
|
|
||||||
pci_set_irq(&ohci->pci_dev, 0, level);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set an interrupt */
|
|
||||||
static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
|
|
||||||
{
|
|
||||||
ohci->intr_status |= intr;
|
|
||||||
ohci_intr_update(ohci);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get an array of dwords from main memory */
|
/* Get an array of dwords from main memory */
|
||||||
static inline int get_dwords(uint32_t addr, uint32_t *buf, int num)
|
static inline int get_dwords(uint32_t addr, uint32_t *buf, int num)
|
||||||
{
|
{
|
||||||
|
@ -327,9 +327,8 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
|
|||||||
usb_attach(port1, NULL);
|
usb_attach(port1, NULL);
|
||||||
}
|
}
|
||||||
/* set connect status */
|
/* set connect status */
|
||||||
if (!(port->ctrl & UHCI_PORT_CCS)) {
|
port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
|
||||||
port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
|
|
||||||
}
|
|
||||||
/* update speed */
|
/* update speed */
|
||||||
if (dev->speed == USB_SPEED_LOW)
|
if (dev->speed == USB_SPEED_LOW)
|
||||||
port->ctrl |= UHCI_PORT_LSDA;
|
port->ctrl |= UHCI_PORT_LSDA;
|
||||||
@ -341,8 +340,9 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
|
|||||||
USB_MSG_ATTACH, 0, 0, NULL, 0);
|
USB_MSG_ATTACH, 0, 0, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
/* set connect status */
|
/* set connect status */
|
||||||
if (!(port->ctrl & UHCI_PORT_CCS)) {
|
if (port->ctrl & UHCI_PORT_CCS) {
|
||||||
port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
|
port->ctrl &= ~UHCI_PORT_CCS;
|
||||||
|
port->ctrl |= UHCI_PORT_CSC;
|
||||||
}
|
}
|
||||||
/* disable port */
|
/* disable port */
|
||||||
if (port->ctrl & UHCI_PORT_EN) {
|
if (port->ctrl & UHCI_PORT_EN) {
|
||||||
|
Loading…
Reference in New Issue
Block a user