Commit 6106487019177fa2bf61fa1beab11b3b113ad858

Authored by pbrook
1 parent 6cb7ee85

Fix USB root hub hotplugging.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1931 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 34 additions and 29 deletions
hw/usb-ohci.c
@@ -248,19 +248,39 @@ struct ohci_td { @@ -248,19 +248,39 @@ struct ohci_td {
248 #define OHCI_CC_BUFFEROVERRUN 0xc 248 #define OHCI_CC_BUFFEROVERRUN 0xc
249 #define OHCI_CC_BUFFERUNDERRUN 0xd 249 #define OHCI_CC_BUFFERUNDERRUN 0xd
250 250
  251 +/* Update IRQ levels */
  252 +static inline void ohci_intr_update(OHCIState *ohci)
  253 +{
  254 + int level = 0;
  255 +
  256 + if ((ohci->intr & OHCI_INTR_MIE) &&
  257 + (ohci->intr_status & ohci->intr))
  258 + level = 1;
  259 +
  260 + pci_set_irq(&ohci->pci_dev, 0, level);
  261 +}
  262 +
  263 +/* Set an interrupt */
  264 +static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
  265 +{
  266 + ohci->intr_status |= intr;
  267 + ohci_intr_update(ohci);
  268 +}
  269 +
  270 +/* Attach or detach a device on a root hub port. */
251 static void ohci_attach(USBPort *port1, USBDevice *dev) 271 static void ohci_attach(USBPort *port1, USBDevice *dev)
252 { 272 {
253 OHCIState *s = port1->opaque; 273 OHCIState *s = port1->opaque;
254 OHCIPort *port = &s->rhport[port1->index]; 274 OHCIPort *port = &s->rhport[port1->index];
  275 + uint32_t old_state = port->ctrl;
255 276
256 if (dev) { 277 if (dev) {
257 if (port->port.dev) { 278 if (port->port.dev) {
258 usb_attach(port1, NULL); 279 usb_attach(port1, NULL);
259 } 280 }
260 /* set connect status */ 281 /* set connect status */
261 - if (!(port->ctrl & OHCI_PORT_CCS)) {  
262 - port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;  
263 - } 282 + port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
  283 +
264 /* update speed */ 284 /* update speed */
265 if (dev->speed == USB_SPEED_LOW) 285 if (dev->speed == USB_SPEED_LOW)
266 port->ctrl |= OHCI_PORT_LSDA; 286 port->ctrl |= OHCI_PORT_LSDA;
@@ -273,8 +293,9 @@ static void ohci_attach(USBPort *port1, USBDevice *dev) @@ -273,8 +293,9 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
273 dprintf("usb-ohci: Attached port %d\n", port1->index); 293 dprintf("usb-ohci: Attached port %d\n", port1->index);
274 } else { 294 } else {
275 /* set connect status */ 295 /* set connect status */
276 - if (!(port->ctrl & OHCI_PORT_CCS)) {  
277 - port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC; 296 + if (port->ctrl & OHCI_PORT_CCS) {
  297 + port->ctrl &= ~OHCI_PORT_CCS;
  298 + port->ctrl |= OHCI_PORT_CSC;
278 } 299 }
279 /* disable port */ 300 /* disable port */
280 if (port->ctrl & OHCI_PORT_PES) { 301 if (port->ctrl & OHCI_PORT_PES) {
@@ -290,6 +311,9 @@ static void ohci_attach(USBPort *port1, USBDevice *dev) @@ -290,6 +311,9 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
290 port->port.dev = NULL; 311 port->port.dev = NULL;
291 dprintf("usb-ohci: Detached port %d\n", port1->index); 312 dprintf("usb-ohci: Detached port %d\n", port1->index);
292 } 313 }
  314 +
  315 + if (old_state != port->ctrl)
  316 + ohci_set_interrupt(s, OHCI_INTR_RHSC);
293 } 317 }
294 318
295 /* Reset the controller */ 319 /* Reset the controller */
@@ -335,25 +359,6 @@ static void ohci_reset(OHCIState *ohci) @@ -335,25 +359,6 @@ static void ohci_reset(OHCIState *ohci)
335 dprintf("usb-ohci: Reset %s\n", ohci->pci_dev.name); 359 dprintf("usb-ohci: Reset %s\n", ohci->pci_dev.name);
336 } 360 }
337 361
338 -/* Update IRQ levels */  
339 -static inline void ohci_intr_update(OHCIState *ohci)  
340 -{  
341 - int level = 0;  
342 -  
343 - if ((ohci->intr & OHCI_INTR_MIE) &&  
344 - (ohci->intr_status & ohci->intr))  
345 - level = 1;  
346 -  
347 - pci_set_irq(&ohci->pci_dev, 0, level);  
348 -}  
349 -  
350 -/* Set an interrupt */  
351 -static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)  
352 -{  
353 - ohci->intr_status |= intr;  
354 - ohci_intr_update(ohci);  
355 -}  
356 -  
357 /* Get an array of dwords from main memory */ 362 /* Get an array of dwords from main memory */
358 static inline int get_dwords(uint32_t addr, uint32_t *buf, int num) 363 static inline int get_dwords(uint32_t addr, uint32_t *buf, int num)
359 { 364 {
hw/usb-uhci.c
@@ -327,9 +327,8 @@ static void uhci_attach(USBPort *port1, USBDevice *dev) @@ -327,9 +327,8 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
327 usb_attach(port1, NULL); 327 usb_attach(port1, NULL);
328 } 328 }
329 /* set connect status */ 329 /* set connect status */
330 - if (!(port->ctrl & UHCI_PORT_CCS)) {  
331 - port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;  
332 - } 330 + port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
  331 +
333 /* update speed */ 332 /* update speed */
334 if (dev->speed == USB_SPEED_LOW) 333 if (dev->speed == USB_SPEED_LOW)
335 port->ctrl |= UHCI_PORT_LSDA; 334 port->ctrl |= UHCI_PORT_LSDA;
@@ -341,8 +340,9 @@ static void uhci_attach(USBPort *port1, USBDevice *dev) @@ -341,8 +340,9 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
341 USB_MSG_ATTACH, 0, 0, NULL, 0); 340 USB_MSG_ATTACH, 0, 0, NULL, 0);
342 } else { 341 } else {
343 /* set connect status */ 342 /* set connect status */
344 - if (!(port->ctrl & UHCI_PORT_CCS)) {  
345 - port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC; 343 + if (port->ctrl & UHCI_PORT_CCS) {
  344 + port->ctrl &= ~UHCI_PORT_CCS;
  345 + port->ctrl |= UHCI_PORT_CSC;
346 } 346 }
347 /* disable port */ 347 /* disable port */
348 if (port->ctrl & UHCI_PORT_EN) { 348 if (port->ctrl & UHCI_PORT_EN) {