ohci.c (227461) | ohci.c (228483) |
---|---|
1/*- 2 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 3 * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved. 4 * Copyright (c) 1998 Lennart Augustsson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 3 * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved. 4 * Copyright (c) 1998 Lennart Augustsson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 12 unchanged lines hidden (view full) --- 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28#include <sys/cdefs.h> |
29__FBSDID("$FreeBSD: head/sys/dev/usb/controller/ohci.c 227461 2011-11-12 08:16:45Z hselasky $"); | 29__FBSDID("$FreeBSD: head/sys/dev/usb/controller/ohci.c 228483 2011-12-14 00:28:54Z hselasky $"); |
30 31/* 32 * USB Open Host Controller driver. 33 * 34 * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html 35 * USB spec: http://www.usb.org/developers/docs/usbspec.zip 36 */ 37 --- 123 unchanged lines hidden (view full) --- 161 162 for (i = 0; i != OHCI_NO_EDS; i++) { 163 cb(bus, sc->sc_hw.intr_start_pc + i, sc->sc_hw.intr_start_pg + i, 164 sizeof(ohci_ed_t), OHCI_ED_ALIGN); 165 } 166} 167 168static usb_error_t | 30 31/* 32 * USB Open Host Controller driver. 33 * 34 * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html 35 * USB spec: http://www.usb.org/developers/docs/usbspec.zip 36 */ 37 --- 123 unchanged lines hidden (view full) --- 161 162 for (i = 0; i != OHCI_NO_EDS; i++) { 163 cb(bus, sc->sc_hw.intr_start_pc + i, sc->sc_hw.intr_start_pg + i, 164 sizeof(ohci_ed_t), OHCI_ED_ALIGN); 165 } 166} 167 168static usb_error_t |
169ohci_controller_init(ohci_softc_t *sc) | 169ohci_controller_init(ohci_softc_t *sc, int do_suspend) |
170{ 171 struct usb_page_search buf_res; 172 uint32_t i; 173 uint32_t ctl; 174 uint32_t ival; 175 uint32_t hcr; 176 uint32_t fm; 177 uint32_t per; --- 50 unchanged lines hidden (view full) --- 228 return (USB_ERR_IOERROR); 229 } 230#ifdef USB_DEBUG 231 if (ohcidebug > 15) { 232 ohci_dumpregs(sc); 233 } 234#endif 235 | 170{ 171 struct usb_page_search buf_res; 172 uint32_t i; 173 uint32_t ctl; 174 uint32_t ival; 175 uint32_t hcr; 176 uint32_t fm; 177 uint32_t per; --- 50 unchanged lines hidden (view full) --- 228 return (USB_ERR_IOERROR); 229 } 230#ifdef USB_DEBUG 231 if (ohcidebug > 15) { 232 ohci_dumpregs(sc); 233 } 234#endif 235 |
236 if (do_suspend) { 237 OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_SUSPEND); 238 return (USB_ERR_NORMAL_COMPLETION); 239 } 240 |
|
236 /* The controller is now in SUSPEND state, we have 2ms to finish. */ 237 238 /* set up HC registers */ 239 usbd_get_page(&sc->sc_hw.hcca_pc, 0, &buf_res); 240 OWRITE4(sc, OHCI_HCCA, buf_res.physaddr); 241 242 usbd_get_page(&sc->sc_hw.ctrl_start_pc, 0, &buf_res); 243 OWRITE4(sc, OHCI_CONTROL_HEAD_ED, buf_res.physaddr); --- 166 unchanged lines hidden (view full) --- 410 } 411 printf("iso "); 412 ohci_dump_ed(sc->sc_isoc_p_last); 413 } 414#endif 415 416 sc->sc_bus.usbrev = USB_REV_1_0; 417 | 241 /* The controller is now in SUSPEND state, we have 2ms to finish. */ 242 243 /* set up HC registers */ 244 usbd_get_page(&sc->sc_hw.hcca_pc, 0, &buf_res); 245 OWRITE4(sc, OHCI_HCCA, buf_res.physaddr); 246 247 usbd_get_page(&sc->sc_hw.ctrl_start_pc, 0, &buf_res); 248 OWRITE4(sc, OHCI_CONTROL_HEAD_ED, buf_res.physaddr); --- 166 unchanged lines hidden (view full) --- 415 } 416 printf("iso "); 417 ohci_dump_ed(sc->sc_isoc_p_last); 418 } 419#endif 420 421 sc->sc_bus.usbrev = USB_REV_1_0; 422 |
418 if (ohci_controller_init(sc)) { | 423 if (ohci_controller_init(sc, 0) != 0) |
419 return (USB_ERR_INVAL); | 424 return (USB_ERR_INVAL); |
420 } else { 421 /* catch any lost interrupts */ 422 ohci_do_poll(&sc->sc_bus); 423 return (USB_ERR_NORMAL_COMPLETION); 424 } | 425 426 /* catch any lost interrupts */ 427 ohci_do_poll(&sc->sc_bus); 428 return (USB_ERR_NORMAL_COMPLETION); |
425} 426 427/* 428 * shut down the controller when the system is going down 429 */ 430void 431ohci_detach(struct ohci_softc *sc) 432{ --- 7 unchanged lines hidden (view full) --- 440 USB_BUS_UNLOCK(&sc->sc_bus); 441 442 /* XXX let stray task complete */ 443 usb_pause_mtx(NULL, hz / 20); 444 445 usb_callout_drain(&sc->sc_tmo_rhsc); 446} 447 | 429} 430 431/* 432 * shut down the controller when the system is going down 433 */ 434void 435ohci_detach(struct ohci_softc *sc) 436{ --- 7 unchanged lines hidden (view full) --- 444 USB_BUS_UNLOCK(&sc->sc_bus); 445 446 /* XXX let stray task complete */ 447 usb_pause_mtx(NULL, hz / 20); 448 449 usb_callout_drain(&sc->sc_tmo_rhsc); 450} 451 |
448/* NOTE: suspend/resume is called from 449 * interrupt context and cannot sleep! 450 */ 451void | 452static void |
452ohci_suspend(ohci_softc_t *sc) 453{ | 453ohci_suspend(ohci_softc_t *sc) 454{ |
454 uint32_t ctl; | 455 DPRINTF("\n"); |
455 | 456 |
456 USB_BUS_LOCK(&sc->sc_bus); 457 | |
458#ifdef USB_DEBUG | 457#ifdef USB_DEBUG |
459 DPRINTF("\n"); 460 if (ohcidebug > 2) { | 458 if (ohcidebug > 2) |
461 ohci_dumpregs(sc); | 459 ohci_dumpregs(sc); |
462 } | |
463#endif 464 | 460#endif 461 |
465 ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK; 466 if (sc->sc_control == 0) { 467 /* 468 * Preserve register values, in case that APM BIOS 469 * does not recover them. 470 */ 471 sc->sc_control = ctl; 472 sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE); 473 } 474 ctl |= OHCI_HCFS_SUSPEND; 475 OWRITE4(sc, OHCI_CONTROL, ctl); 476 477 usb_pause_mtx(&sc->sc_bus.bus_mtx, 478 USB_MS_TO_TICKS(USB_RESUME_WAIT)); 479 480 USB_BUS_UNLOCK(&sc->sc_bus); | 462 /* reset HC and leave it suspended */ 463 ohci_controller_init(sc, 1); |
481} 482 | 464} 465 |
483void | 466static void |
484ohci_resume(ohci_softc_t *sc) 485{ | 467ohci_resume(ohci_softc_t *sc) 468{ |
486 uint32_t ctl; | 469 DPRINTF("\n"); |
487 488#ifdef USB_DEBUG | 470 471#ifdef USB_DEBUG |
489 DPRINTF("\n"); 490 if (ohcidebug > 2) { | 472 if (ohcidebug > 2) |
491 ohci_dumpregs(sc); | 473 ohci_dumpregs(sc); |
492 } | |
493#endif | 474#endif |
475 |
|
494 /* some broken BIOSes never initialize the Controller chip */ | 476 /* some broken BIOSes never initialize the Controller chip */ |
495 ohci_controller_init(sc); | 477 ohci_controller_init(sc, 0); |
496 | 478 |
497 USB_BUS_LOCK(&sc->sc_bus); 498 if (sc->sc_intre) { 499 OWRITE4(sc, OHCI_INTERRUPT_ENABLE, 500 sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE)); 501 } 502 if (sc->sc_control) 503 ctl = sc->sc_control; 504 else 505 ctl = OREAD4(sc, OHCI_CONTROL); 506 ctl |= OHCI_HCFS_RESUME; 507 OWRITE4(sc, OHCI_CONTROL, ctl); 508 usb_pause_mtx(&sc->sc_bus.bus_mtx, 509 USB_MS_TO_TICKS(USB_RESUME_DELAY)); 510 ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL; 511 OWRITE4(sc, OHCI_CONTROL, ctl); 512 usb_pause_mtx(&sc->sc_bus.bus_mtx, 513 USB_MS_TO_TICKS(USB_RESUME_RECOVERY)); 514 sc->sc_control = sc->sc_intre = 0; 515 516 USB_BUS_UNLOCK(&sc->sc_bus); 517 | |
518 /* catch any lost interrupts */ 519 ohci_do_poll(&sc->sc_bus); 520} 521 522#ifdef USB_DEBUG 523static void 524ohci_dumpregs(ohci_softc_t *sc) 525{ --- 2182 unchanged lines hidden (view full) --- 2708 } 2709 2710 USB_BUS_UNLOCK(udev->bus); 2711 2712 return; 2713} 2714 2715static void | 479 /* catch any lost interrupts */ 480 ohci_do_poll(&sc->sc_bus); 481} 482 483#ifdef USB_DEBUG 484static void 485ohci_dumpregs(ohci_softc_t *sc) 486{ --- 2182 unchanged lines hidden (view full) --- 2669 } 2670 2671 USB_BUS_UNLOCK(udev->bus); 2672 2673 return; 2674} 2675 2676static void |
2677ohci_set_hw_power_sleep(struct usb_bus *bus, uint32_t state) 2678{ 2679 struct ohci_softc *sc = OHCI_BUS2SC(bus); 2680 2681 switch (state) { 2682 case USB_HW_POWER_SUSPEND: 2683 case USB_HW_POWER_SHUTDOWN: 2684 ohci_suspend(sc); 2685 break; 2686 case USB_HW_POWER_RESUME: 2687 ohci_resume(sc); 2688 break; 2689 default: 2690 break; 2691 } 2692} 2693 2694static void |
|
2716ohci_set_hw_power(struct usb_bus *bus) 2717{ 2718 struct ohci_softc *sc = OHCI_BUS2SC(bus); 2719 uint32_t temp; 2720 uint32_t flags; 2721 2722 DPRINTF("\n"); 2723 --- 27 unchanged lines hidden (view full) --- 2751{ 2752 .endpoint_init = ohci_ep_init, 2753 .xfer_setup = ohci_xfer_setup, 2754 .xfer_unsetup = ohci_xfer_unsetup, 2755 .get_dma_delay = ohci_get_dma_delay, 2756 .device_resume = ohci_device_resume, 2757 .device_suspend = ohci_device_suspend, 2758 .set_hw_power = ohci_set_hw_power, | 2695ohci_set_hw_power(struct usb_bus *bus) 2696{ 2697 struct ohci_softc *sc = OHCI_BUS2SC(bus); 2698 uint32_t temp; 2699 uint32_t flags; 2700 2701 DPRINTF("\n"); 2702 --- 27 unchanged lines hidden (view full) --- 2730{ 2731 .endpoint_init = ohci_ep_init, 2732 .xfer_setup = ohci_xfer_setup, 2733 .xfer_unsetup = ohci_xfer_unsetup, 2734 .get_dma_delay = ohci_get_dma_delay, 2735 .device_resume = ohci_device_resume, 2736 .device_suspend = ohci_device_suspend, 2737 .set_hw_power = ohci_set_hw_power, |
2738 .set_hw_power_sleep = ohci_set_hw_power_sleep, |
|
2759 .roothub_exec = ohci_roothub_exec, 2760 .xfer_poll = ohci_do_poll, 2761}; | 2739 .roothub_exec = ohci_roothub_exec, 2740 .xfer_poll = ohci_do_poll, 2741}; |