Fix USB root hub hotplugging.
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 22 May 2006 17:17:06 +0000 (17:17 +0000)
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 22 May 2006 17:17:06 +0000 (17:17 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1931 c046a42c-6fe2-441c-8c8c-71466251a162

hw/usb-ohci.c
hw/usb-uhci.c

index 73d2620..0cc2723 100644 (file)
@@ -248,19 +248,39 @@ struct ohci_td {
 #define OHCI_CC_BUFFEROVERRUN       0xc
 #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)
 {
     OHCIState *s = port1->opaque;
     OHCIPort *port = &s->rhport[port1->index];
+    uint32_t old_state = port->ctrl;
 
     if (dev) {
         if (port->port.dev) {
             usb_attach(port1, NULL);
         }
         /* 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 */
         if (dev->speed == USB_SPEED_LOW)
             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);
     } else {
         /* set connect status */
-        if (!(port->ctrl & OHCI_PORT_CCS)) {
-            port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
+        if (port->ctrl & OHCI_PORT_CCS) {
+            port->ctrl &= ~OHCI_PORT_CCS;
+            port->ctrl |= OHCI_PORT_CSC;
         }
         /* disable port */
         if (port->ctrl & OHCI_PORT_PES) {
@@ -290,6 +311,9 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
         port->port.dev = NULL;
         dprintf("usb-ohci: Detached port %d\n", port1->index);
     }
+
+    if (old_state != port->ctrl)
+        ohci_set_interrupt(s, OHCI_INTR_RHSC);
 }
 
 /* Reset the controller */
@@ -335,25 +359,6 @@ static void ohci_reset(OHCIState *ohci)
     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 */
 static inline int get_dwords(uint32_t addr, uint32_t *buf, int num)
 {
index d3358fe..1a6e013 100644 (file)
@@ -327,9 +327,8 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
             usb_attach(port1, NULL);
         }
         /* 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 */
         if (dev->speed == USB_SPEED_LOW)
             port->ctrl |= UHCI_PORT_LSDA;
@@ -341,8 +340,9 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
                            USB_MSG_ATTACH, 0, 0, NULL, 0);
     } else {
         /* set connect status */
-        if (!(port->ctrl & UHCI_PORT_CCS)) {
-            port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
+        if (port->ctrl & UHCI_PORT_CCS) {
+            port->ctrl &= ~UHCI_PORT_CCS;
+            port->ctrl |= UHCI_PORT_CSC;
         }
         /* disable port */
         if (port->ctrl & UHCI_PORT_EN) {