Deleted Added
full compact
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 ---