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 248 #define OHCI_CC_BUFFEROVERRUN 0xc
249 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 271 static void ohci_attach(USBPort *port1, USBDevice *dev)
252 272 {
253 273 OHCIState *s = port1->opaque;
254 274 OHCIPort *port = &s->rhport[port1->index];
  275 + uint32_t old_state = port->ctrl;
255 276  
256 277 if (dev) {
257 278 if (port->port.dev) {
258 279 usb_attach(port1, NULL);
259 280 }
260 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 284 /* update speed */
265 285 if (dev->speed == USB_SPEED_LOW)
266 286 port->ctrl |= OHCI_PORT_LSDA;
... ... @@ -273,8 +293,9 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
273 293 dprintf("usb-ohci: Attached port %d\n", port1->index);
274 294 } else {
275 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 300 /* disable port */
280 301 if (port->ctrl & OHCI_PORT_PES) {
... ... @@ -290,6 +311,9 @@ static void ohci_attach(USBPort *port1, USBDevice *dev)
290 311 port->port.dev = NULL;
291 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 319 /* Reset the controller */
... ... @@ -335,25 +359,6 @@ static void ohci_reset(OHCIState *ohci)
335 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 362 /* Get an array of dwords from main memory */
358 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 327 usb_attach(port1, NULL);
328 328 }
329 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 332 /* update speed */
334 333 if (dev->speed == USB_SPEED_LOW)
335 334 port->ctrl |= UHCI_PORT_LSDA;
... ... @@ -341,8 +340,9 @@ static void uhci_attach(USBPort *port1, USBDevice *dev)
341 340 USB_MSG_ATTACH, 0, 0, NULL, 0);
342 341 } else {
343 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 347 /* disable port */
348 348 if (port->ctrl & UHCI_PORT_EN) {
... ...