usb_hub.c (188942) | usb_hub.c (188986) |
---|---|
1/* $FreeBSD: head/sys/dev/usb/usb_hub.c 188942 2009-02-23 18:31:00Z thompsa $ */ | 1/* $FreeBSD: head/sys/dev/usb/usb_hub.c 188986 2009-02-24 03:41:52Z thompsa $ */ |
2/*- 3 * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved. 4 * Copyright (c) 1998 Lennart Augustsson. All rights reserved. 5 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: --- 229 unchanged lines hidden (view full) --- 239 *------------------------------------------------------------------------*/ 240static usb2_error_t 241uhub_read_port_status(struct uhub_softc *sc, uint8_t portno) 242{ 243 struct usb2_port_status ps; 244 usb2_error_t err; 245 246 err = usb2_req_get_port_status( | 2/*- 3 * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved. 4 * Copyright (c) 1998 Lennart Augustsson. All rights reserved. 5 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: --- 229 unchanged lines hidden (view full) --- 239 *------------------------------------------------------------------------*/ 240static usb2_error_t 241uhub_read_port_status(struct uhub_softc *sc, uint8_t portno) 242{ 243 struct usb2_port_status ps; 244 usb2_error_t err; 245 246 err = usb2_req_get_port_status( |
247 sc->sc_udev, &Giant, &ps, portno); | 247 sc->sc_udev, NULL, &ps, portno); |
248 249 /* update status regardless of error */ 250 251 sc->sc_st.port_status = UGETW(ps.wPortStatus); 252 sc->sc_st.port_change = UGETW(ps.wPortChange); 253 254 /* debugging print */ 255 --- 28 unchanged lines hidden (view full) --- 284 udev = sc->sc_udev; 285 child = usb2_bus_port_get_device(udev->bus, 286 udev->hub->ports + portno - 1); 287 288repeat: 289 290 /* first clear the port connection change bit */ 291 | 248 249 /* update status regardless of error */ 250 251 sc->sc_st.port_status = UGETW(ps.wPortStatus); 252 sc->sc_st.port_change = UGETW(ps.wPortChange); 253 254 /* debugging print */ 255 --- 28 unchanged lines hidden (view full) --- 284 udev = sc->sc_udev; 285 child = usb2_bus_port_get_device(udev->bus, 286 udev->hub->ports + portno - 1); 287 288repeat: 289 290 /* first clear the port connection change bit */ 291 |
292 err = usb2_req_clear_port_feature(udev, &Giant, | 292 err = usb2_req_clear_port_feature(udev, NULL, |
293 portno, UHF_C_PORT_CONNECTION); 294 295 if (err) { 296 goto error; 297 } 298 /* detach any existing devices */ 299 300 if (child) { --- 23 unchanged lines hidden (view full) --- 324 if (!(sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)) { 325 326 DPRINTF("Port %d is in Host Mode\n", portno); 327 328 if (sc->sc_st.port_status & UPS_SUSPEND) { 329 DPRINTF("Port %d was still " 330 "suspended, clearing.\n", portno); 331 err = usb2_req_clear_port_feature(sc->sc_udev, | 293 portno, UHF_C_PORT_CONNECTION); 294 295 if (err) { 296 goto error; 297 } 298 /* detach any existing devices */ 299 300 if (child) { --- 23 unchanged lines hidden (view full) --- 324 if (!(sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)) { 325 326 DPRINTF("Port %d is in Host Mode\n", portno); 327 328 if (sc->sc_st.port_status & UPS_SUSPEND) { 329 DPRINTF("Port %d was still " 330 "suspended, clearing.\n", portno); 331 err = usb2_req_clear_port_feature(sc->sc_udev, |
332 &Giant, portno, UHF_PORT_SUSPEND); | 332 NULL, portno, UHF_PORT_SUSPEND); |
333 } 334 /* USB Host Mode */ 335 336 /* wait for maximum device power up time */ 337 | 333 } 334 /* USB Host Mode */ 335 336 /* wait for maximum device power up time */ 337 |
338 usb2_pause_mtx(&Giant, | 338 usb2_pause_mtx(NULL, |
339 USB_MS_TO_TICKS(USB_PORT_POWERUP_DELAY)); 340 341 /* reset port, which implies enabling it */ 342 | 339 USB_MS_TO_TICKS(USB_PORT_POWERUP_DELAY)); 340 341 /* reset port, which implies enabling it */ 342 |
343 err = usb2_req_reset_port(udev, &Giant, portno); | 343 err = usb2_req_reset_port(udev, NULL, portno); |
344 345 if (err) { 346 DPRINTFN(0, "port %d reset " 347 "failed, error=%s\n", 348 portno, usb2_errstr(err)); 349 goto error; 350 } 351 /* get port status again, it might have changed during reset */ --- 68 unchanged lines hidden (view full) --- 420 if (child) { 421 usb2_detach_device(child, USB_IFACE_INDEX_ANY, 1); 422 usb2_free_device(child); 423 child = NULL; 424 } 425 if (err == 0) { 426 if (sc->sc_st.port_status & UPS_PORT_ENABLED) { 427 err = usb2_req_clear_port_feature( | 344 345 if (err) { 346 DPRINTFN(0, "port %d reset " 347 "failed, error=%s\n", 348 portno, usb2_errstr(err)); 349 goto error; 350 } 351 /* get port status again, it might have changed during reset */ --- 68 unchanged lines hidden (view full) --- 420 if (child) { 421 usb2_detach_device(child, USB_IFACE_INDEX_ANY, 1); 422 usb2_free_device(child); 423 child = NULL; 424 } 425 if (err == 0) { 426 if (sc->sc_st.port_status & UPS_PORT_ENABLED) { 427 err = usb2_req_clear_port_feature( |
428 sc->sc_udev, &Giant, | 428 sc->sc_udev, NULL, |
429 portno, UHF_PORT_ENABLE); 430 } 431 } 432 if (err) { 433 DPRINTFN(0, "device problem (%s), " 434 "disabling port %d\n", usb2_errstr(err), portno); 435 } 436 return (err); --- 17 unchanged lines hidden (view full) --- 454 DPRINTF("port %d\n", portno); 455 456 udev = sc->sc_udev; 457 child = usb2_bus_port_get_device(udev->bus, 458 udev->hub->ports + portno - 1); 459 460 /* first clear the port suspend change bit */ 461 | 429 portno, UHF_PORT_ENABLE); 430 } 431 } 432 if (err) { 433 DPRINTFN(0, "device problem (%s), " 434 "disabling port %d\n", usb2_errstr(err), portno); 435 } 436 return (err); --- 17 unchanged lines hidden (view full) --- 454 DPRINTF("port %d\n", portno); 455 456 udev = sc->sc_udev; 457 child = usb2_bus_port_get_device(udev->bus, 458 udev->hub->ports + portno - 1); 459 460 /* first clear the port suspend change bit */ 461 |
462 err = usb2_req_clear_port_feature(udev, &Giant, | 462 err = usb2_req_clear_port_feature(udev, NULL, |
463 portno, UHF_C_PORT_SUSPEND); 464 if (err) { 465 DPRINTF("clearing suspend failed.\n"); 466 goto done; 467 } 468 /* get fresh status */ 469 470 err = uhub_read_port_status(sc, portno); --- 66 unchanged lines hidden (view full) --- 537 err = uhub_read_port_status(sc, portno); 538 if (err) { 539 /* most likely the HUB is gone */ 540 break; 541 } 542 if (sc->sc_st.port_change & UPS_C_OVERCURRENT_INDICATOR) { 543 DPRINTF("Overcurrent on port %u.\n", portno); 544 err = usb2_req_clear_port_feature( | 463 portno, UHF_C_PORT_SUSPEND); 464 if (err) { 465 DPRINTF("clearing suspend failed.\n"); 466 goto done; 467 } 468 /* get fresh status */ 469 470 err = uhub_read_port_status(sc, portno); --- 66 unchanged lines hidden (view full) --- 537 err = uhub_read_port_status(sc, portno); 538 if (err) { 539 /* most likely the HUB is gone */ 540 break; 541 } 542 if (sc->sc_st.port_change & UPS_C_OVERCURRENT_INDICATOR) { 543 DPRINTF("Overcurrent on port %u.\n", portno); 544 err = usb2_req_clear_port_feature( |
545 udev, &Giant, portno, UHF_C_PORT_OVER_CURRENT); | 545 udev, NULL, portno, UHF_C_PORT_OVER_CURRENT); |
546 if (err) { 547 /* most likely the HUB is gone */ 548 break; 549 } 550 } 551 if (!(sc->sc_flags & UHUB_FLAG_DID_EXPLORE)) { 552 /* 553 * Fake a connect status change so that the 554 * status gets checked initially! 555 */ 556 sc->sc_st.port_change |= 557 UPS_C_CONNECT_STATUS; 558 } 559 if (sc->sc_st.port_change & UPS_C_PORT_ENABLED) { 560 err = usb2_req_clear_port_feature( | 546 if (err) { 547 /* most likely the HUB is gone */ 548 break; 549 } 550 } 551 if (!(sc->sc_flags & UHUB_FLAG_DID_EXPLORE)) { 552 /* 553 * Fake a connect status change so that the 554 * status gets checked initially! 555 */ 556 sc->sc_st.port_change |= 557 UPS_C_CONNECT_STATUS; 558 } 559 if (sc->sc_st.port_change & UPS_C_PORT_ENABLED) { 560 err = usb2_req_clear_port_feature( |
561 udev, &Giant, portno, UHF_C_PORT_ENABLE); | 561 udev, NULL, portno, UHF_C_PORT_ENABLE); |
562 if (err) { 563 /* most likely the HUB is gone */ 564 break; 565 } 566 if (sc->sc_st.port_change & UPS_C_CONNECT_STATUS) { 567 /* 568 * Ignore the port error if the device 569 * has vanished ! --- 107 unchanged lines hidden (view full) --- 677 "bus powered HUB. HUB ignored!\n"); 678 goto error; 679 } 680 /* get HUB descriptor */ 681 682 DPRINTFN(2, "getting HUB descriptor\n"); 683 684 /* assuming that there is one port */ | 562 if (err) { 563 /* most likely the HUB is gone */ 564 break; 565 } 566 if (sc->sc_st.port_change & UPS_C_CONNECT_STATUS) { 567 /* 568 * Ignore the port error if the device 569 * has vanished ! --- 107 unchanged lines hidden (view full) --- 677 "bus powered HUB. HUB ignored!\n"); 678 goto error; 679 } 680 /* get HUB descriptor */ 681 682 DPRINTFN(2, "getting HUB descriptor\n"); 683 684 /* assuming that there is one port */ |
685 err = usb2_req_get_hub_descriptor(udev, &Giant, &hubdesc, 1); | 685 err = usb2_req_get_hub_descriptor(udev, NULL, &hubdesc, 1); |
686 687 nports = hubdesc.bNbrPorts; 688 689 if (!err && (nports >= 8)) { 690 /* get complete HUB descriptor */ | 686 687 nports = hubdesc.bNbrPorts; 688 689 if (!err && (nports >= 8)) { 690 /* get complete HUB descriptor */ |
691 err = usb2_req_get_hub_descriptor(udev, &Giant, &hubdesc, nports); | 691 err = usb2_req_get_hub_descriptor(udev, NULL, &hubdesc, nports); |
692 } 693 if (err) { 694 DPRINTFN(0, "getting hub descriptor failed," 695 "error=%s\n", usb2_errstr(err)); 696 goto error; 697 } 698 if (hubdesc.bNbrPorts != nports) { 699 DPRINTFN(0, "number of ports changed!\n"); --- 32 unchanged lines hidden (view full) --- 732 err = usb2_transfer_setup(udev, &iface_index, sc->sc_xfer, 733 uhub_config, UHUB_N_TRANSFER, sc, &Giant); 734 if (err) { 735 DPRINTFN(0, "cannot setup interrupt transfer, " 736 "errstr=%s!\n", usb2_errstr(err)); 737 goto error; 738 } 739 /* wait with power off for a while */ | 692 } 693 if (err) { 694 DPRINTFN(0, "getting hub descriptor failed," 695 "error=%s\n", usb2_errstr(err)); 696 goto error; 697 } 698 if (hubdesc.bNbrPorts != nports) { 699 DPRINTFN(0, "number of ports changed!\n"); --- 32 unchanged lines hidden (view full) --- 732 err = usb2_transfer_setup(udev, &iface_index, sc->sc_xfer, 733 uhub_config, UHUB_N_TRANSFER, sc, &Giant); 734 if (err) { 735 DPRINTFN(0, "cannot setup interrupt transfer, " 736 "errstr=%s!\n", usb2_errstr(err)); 737 goto error; 738 } 739 /* wait with power off for a while */ |
740 usb2_pause_mtx(&Giant, USB_MS_TO_TICKS(USB_POWER_DOWN_TIME)); | 740 usb2_pause_mtx(NULL, USB_MS_TO_TICKS(USB_POWER_DOWN_TIME)); |
741 742 /* 743 * To have the best chance of success we do things in the exact same 744 * order as Windoze98. This should not be necessary, but some 745 * devices do not follow the USB specs to the letter. 746 * 747 * These are the events on the bus when a hub is attached: 748 * Get device and config descriptors (see attach code) --- 30 unchanged lines hidden (view full) --- 779 portno = x + 1; 780 781 /* check if port is removable */ 782 if (!UHD_NOT_REMOV(&hubdesc, portno)) { 783 removable++; 784 } 785 if (!err) { 786 /* turn the power on */ | 741 742 /* 743 * To have the best chance of success we do things in the exact same 744 * order as Windoze98. This should not be necessary, but some 745 * devices do not follow the USB specs to the letter. 746 * 747 * These are the events on the bus when a hub is attached: 748 * Get device and config descriptors (see attach code) --- 30 unchanged lines hidden (view full) --- 779 portno = x + 1; 780 781 /* check if port is removable */ 782 if (!UHD_NOT_REMOV(&hubdesc, portno)) { 783 removable++; 784 } 785 if (!err) { 786 /* turn the power on */ |
787 err = usb2_req_set_port_feature(udev, &Giant, | 787 err = usb2_req_set_port_feature(udev, NULL, |
788 portno, UHF_PORT_POWER); 789 } 790 if (err) { 791 DPRINTFN(0, "port %d power on failed, %s\n", 792 portno, usb2_errstr(err)); 793 } 794 DPRINTF("turn on port %d power\n", 795 portno); 796 797 /* wait for stable power */ | 788 portno, UHF_PORT_POWER); 789 } 790 if (err) { 791 DPRINTFN(0, "port %d power on failed, %s\n", 792 portno, usb2_errstr(err)); 793 } 794 DPRINTF("turn on port %d power\n", 795 portno); 796 797 /* wait for stable power */ |
798 usb2_pause_mtx(&Giant, USB_MS_TO_TICKS(pwrdly)); | 798 usb2_pause_mtx(NULL, USB_MS_TO_TICKS(pwrdly)); |
799 } 800 801 device_printf(dev, "%d port%s with %d " 802 "removable, %s powered\n", nports, (nports != 1) ? "s" : "", 803 removable, udev->flags.self_powered ? "self" : "bus"); 804 805 /* start the interrupt endpoint */ 806 --- 849 unchanged lines hidden (view full) --- 1656 /* get bus pointer */ 1657 bus = udev->bus; 1658 1659 /* resume parent hub first */ 1660 usb2_dev_resume_peer(udev->parent_hub); 1661 1662 /* resume current port (Valid in Host and Device Mode) */ 1663 err = usb2_req_clear_port_feature(udev->parent_hub, | 799 } 800 801 device_printf(dev, "%d port%s with %d " 802 "removable, %s powered\n", nports, (nports != 1) ? "s" : "", 803 removable, udev->flags.self_powered ? "self" : "bus"); 804 805 /* start the interrupt endpoint */ 806 --- 849 unchanged lines hidden (view full) --- 1656 /* get bus pointer */ 1657 bus = udev->bus; 1658 1659 /* resume parent hub first */ 1660 usb2_dev_resume_peer(udev->parent_hub); 1661 1662 /* resume current port (Valid in Host and Device Mode) */ 1663 err = usb2_req_clear_port_feature(udev->parent_hub, |
1664 &Giant, udev->port_no, UHF_PORT_SUSPEND); | 1664 NULL, udev->port_no, UHF_PORT_SUSPEND); |
1665 if (err) { 1666 DPRINTFN(0, "Resuming port failed!\n"); 1667 return; 1668 } 1669 /* resume settle time */ | 1665 if (err) { 1666 DPRINTFN(0, "Resuming port failed!\n"); 1667 return; 1668 } 1669 /* resume settle time */ |
1670 usb2_pause_mtx(&Giant, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY)); | 1670 usb2_pause_mtx(NULL, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY)); |
1671 1672 if (bus->methods->device_resume != NULL) { 1673 /* resume USB device on the USB controller */ 1674 (bus->methods->device_resume) (udev); 1675 } 1676 USB_BUS_LOCK(bus); 1677 /* set that this device is now resumed */ 1678 udev->pwr_save.suspended = 0; --- 19 unchanged lines hidden (view full) --- 1698 /* notify all sub-devices about resume */ 1699 err = usb2_suspend_resume(udev, 0); 1700 sx_unlock(udev->default_sx + 1); 1701 1702 /* check if peer has wakeup capability */ 1703 if (usb2_peer_can_wakeup(udev)) { 1704 /* clear remote wakeup */ 1705 err = usb2_req_clear_device_feature(udev, | 1671 1672 if (bus->methods->device_resume != NULL) { 1673 /* resume USB device on the USB controller */ 1674 (bus->methods->device_resume) (udev); 1675 } 1676 USB_BUS_LOCK(bus); 1677 /* set that this device is now resumed */ 1678 udev->pwr_save.suspended = 0; --- 19 unchanged lines hidden (view full) --- 1698 /* notify all sub-devices about resume */ 1699 err = usb2_suspend_resume(udev, 0); 1700 sx_unlock(udev->default_sx + 1); 1701 1702 /* check if peer has wakeup capability */ 1703 if (usb2_peer_can_wakeup(udev)) { 1704 /* clear remote wakeup */ 1705 err = usb2_req_clear_device_feature(udev, |
1706 &Giant, UF_DEVICE_REMOTE_WAKEUP); | 1706 NULL, UF_DEVICE_REMOTE_WAKEUP); |
1707 if (err) { 1708 DPRINTFN(0, "Clearing device " 1709 "remote wakeup failed: %s!\n", 1710 usb2_errstr(err)); 1711 } 1712 } 1713 return; 1714} --- 62 unchanged lines hidden (view full) --- 1777 sx_xlock(udev->default_sx + 1); 1778 /* notify all sub-devices about suspend */ 1779 err = usb2_suspend_resume(udev, 1); 1780 sx_unlock(udev->default_sx + 1); 1781 1782 if (usb2_peer_can_wakeup(udev)) { 1783 /* allow device to do remote wakeup */ 1784 err = usb2_req_set_device_feature(udev, | 1707 if (err) { 1708 DPRINTFN(0, "Clearing device " 1709 "remote wakeup failed: %s!\n", 1710 usb2_errstr(err)); 1711 } 1712 } 1713 return; 1714} --- 62 unchanged lines hidden (view full) --- 1777 sx_xlock(udev->default_sx + 1); 1778 /* notify all sub-devices about suspend */ 1779 err = usb2_suspend_resume(udev, 1); 1780 sx_unlock(udev->default_sx + 1); 1781 1782 if (usb2_peer_can_wakeup(udev)) { 1783 /* allow device to do remote wakeup */ 1784 err = usb2_req_set_device_feature(udev, |
1785 &Giant, UF_DEVICE_REMOTE_WAKEUP); | 1785 NULL, UF_DEVICE_REMOTE_WAKEUP); |
1786 if (err) { 1787 DPRINTFN(0, "Setting device " 1788 "remote wakeup failed!\n"); 1789 } 1790 } 1791 USB_BUS_LOCK(udev->bus); 1792 /* 1793 * Set that this device is suspended. This variable must be set --- 4 unchanged lines hidden (view full) --- 1798 1799 if (udev->bus->methods->device_suspend != NULL) { 1800 1801 /* suspend device on the USB controller */ 1802 (udev->bus->methods->device_suspend) (udev); 1803 1804 /* do DMA delay */ 1805 temp = usb2_get_dma_delay(udev->bus); | 1786 if (err) { 1787 DPRINTFN(0, "Setting device " 1788 "remote wakeup failed!\n"); 1789 } 1790 } 1791 USB_BUS_LOCK(udev->bus); 1792 /* 1793 * Set that this device is suspended. This variable must be set --- 4 unchanged lines hidden (view full) --- 1798 1799 if (udev->bus->methods->device_suspend != NULL) { 1800 1801 /* suspend device on the USB controller */ 1802 (udev->bus->methods->device_suspend) (udev); 1803 1804 /* do DMA delay */ 1805 temp = usb2_get_dma_delay(udev->bus); |
1806 usb2_pause_mtx(&Giant, USB_MS_TO_TICKS(temp)); | 1806 usb2_pause_mtx(NULL, USB_MS_TO_TICKS(temp)); |
1807 1808 } 1809 /* suspend current port */ 1810 err = usb2_req_set_port_feature(udev->parent_hub, | 1807 1808 } 1809 /* suspend current port */ 1810 err = usb2_req_set_port_feature(udev->parent_hub, |
1811 &Giant, udev->port_no, UHF_PORT_SUSPEND); | 1811 NULL, udev->port_no, UHF_PORT_SUSPEND); |
1812 if (err) { 1813 DPRINTFN(0, "Suspending port failed\n"); 1814 return; 1815 } 1816 if (suspend_parent) { 1817 udev = udev->parent_hub; 1818 goto repeat; 1819 } --- 23 unchanged lines hidden --- | 1812 if (err) { 1813 DPRINTFN(0, "Suspending port failed\n"); 1814 return; 1815 } 1816 if (suspend_parent) { 1817 udev = udev->parent_hub; 1818 goto repeat; 1819 } --- 23 unchanged lines hidden --- |