1f9f848faSopenharmony_ci/*- 2f9f848faSopenharmony_ci * SPDX-License-Identifier: BSD-2-Clause 3f9f848faSopenharmony_ci * 4f9f848faSopenharmony_ci * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 5f9f848faSopenharmony_ci * 6f9f848faSopenharmony_ci * Redistribution and use in source and binary forms, with or without 7f9f848faSopenharmony_ci * modification, are permitted provided that the following conditions 8f9f848faSopenharmony_ci * are met: 9f9f848faSopenharmony_ci * 1. Redistributions of source code must retain the above copyright 10f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer. 11f9f848faSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 12f9f848faSopenharmony_ci * notice, this list of conditions and the following disclaimer in the 13f9f848faSopenharmony_ci * documentation and/or other materials provided with the distribution. 14f9f848faSopenharmony_ci * 15f9f848faSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16f9f848faSopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17f9f848faSopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18f9f848faSopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19f9f848faSopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20f9f848faSopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21f9f848faSopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22f9f848faSopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23f9f848faSopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24f9f848faSopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25f9f848faSopenharmony_ci * SUCH DAMAGE. 26f9f848faSopenharmony_ci */ 27f9f848faSopenharmony_ci 28f9f848faSopenharmony_ci#include "implementation/global_implementation.h" 29f9f848faSopenharmony_ci#if USB_HAVE_DEVICE_TOPOLOGY 30f9f848faSopenharmony_ci#include "implementation/usb_btree.h" 31f9f848faSopenharmony_ci#endif 32f9f848faSopenharmony_ci 33f9f848faSopenharmony_ci/* function prototypes */ 34f9f848faSopenharmony_ci 35f9f848faSopenharmony_cistatic device_probe_t usb_probe; 36f9f848faSopenharmony_cistatic device_attach_t usb_attach; 37f9f848faSopenharmony_cistatic device_detach_t usb_detach; 38f9f848faSopenharmony_cistatic device_suspend_t usb_suspend; 39f9f848faSopenharmony_cistatic device_resume_t usb_resume; 40f9f848faSopenharmony_cistatic device_shutdown_t usb_shutdown; 41f9f848faSopenharmony_ci 42f9f848faSopenharmony_cistatic void usb_attach_sub(device_t, struct usb_bus *); 43f9f848faSopenharmony_ci 44f9f848faSopenharmony_ci#undef USB_DEBUG_VAR 45f9f848faSopenharmony_ci#define USB_DEBUG_VAR usb_ctrl_debug 46f9f848faSopenharmony_ci#ifdef LOSCFG_USB_DEBUG 47f9f848faSopenharmony_cistatic int usb_ctrl_debug = 0; 48f9f848faSopenharmony_civoid 49f9f848faSopenharmony_ciusb_controller_debug_func(int level) 50f9f848faSopenharmony_ci{ 51f9f848faSopenharmony_ci usb_ctrl_debug = level; 52f9f848faSopenharmony_ci PRINTK("The level of usb controller debug is %d\n", level); 53f9f848faSopenharmony_ci} 54f9f848faSopenharmony_ciDEBUG_MODULE(controller, usb_controller_debug_func); 55f9f848faSopenharmony_ci#endif 56f9f848faSopenharmony_ci 57f9f848faSopenharmony_cistatic int usb_no_suspend_wait = 0; 58f9f848faSopenharmony_cistatic int usb_no_resume_wait = 0; 59f9f848faSopenharmony_cistatic int usb_no_shutdown_wait = 0; 60f9f848faSopenharmony_cistatic devclass_t usb_devclass; 61f9f848faSopenharmony_ci 62f9f848faSopenharmony_cistatic device_method_t usb_methods[] = { 63f9f848faSopenharmony_ci DEVMETHOD(device_probe, usb_probe), 64f9f848faSopenharmony_ci DEVMETHOD(device_attach, usb_attach), 65f9f848faSopenharmony_ci DEVMETHOD(device_detach, usb_detach), 66f9f848faSopenharmony_ci DEVMETHOD(device_suspend, usb_suspend), 67f9f848faSopenharmony_ci DEVMETHOD(device_resume, usb_resume), 68f9f848faSopenharmony_ci DEVMETHOD(device_shutdown, usb_shutdown), 69f9f848faSopenharmony_ci 70f9f848faSopenharmony_ci DEVMETHOD_END 71f9f848faSopenharmony_ci}; 72f9f848faSopenharmony_ci 73f9f848faSopenharmony_cistatic driver_t usb_driver = { 74f9f848faSopenharmony_ci .name = "usbus", 75f9f848faSopenharmony_ci .methods = usb_methods, 76f9f848faSopenharmony_ci .size = 0, 77f9f848faSopenharmony_ci}; 78f9f848faSopenharmony_ci 79f9f848faSopenharmony_ci/* Host Only Drivers */ 80f9f848faSopenharmony_ciDRIVER_MODULE(usbus, ehci, usb_driver, usb_devclass, 0, 0); 81f9f848faSopenharmony_ciDRIVER_MODULE(usbus, xhci, usb_driver, usb_devclass, 0, 0); 82f9f848faSopenharmony_ci 83f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 84f9f848faSopenharmony_ci * usb_probe 85f9f848faSopenharmony_ci * 86f9f848faSopenharmony_ci * This function is called from "{ehci,ohci,uhci}_pci_attach()". 87f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 88f9f848faSopenharmony_cistatic int 89f9f848faSopenharmony_ciusb_probe(device_t dev) 90f9f848faSopenharmony_ci{ 91f9f848faSopenharmony_ci DPRINTF("\n"); 92f9f848faSopenharmony_ci return (0); 93f9f848faSopenharmony_ci} 94f9f848faSopenharmony_ci 95f9f848faSopenharmony_ci#if USB_HAVE_ROOT_MOUNT_HOLD 96f9f848faSopenharmony_cistatic void 97f9f848faSopenharmony_ciusb_root_mount_rel(struct usb_bus *bus) 98f9f848faSopenharmony_ci{ 99f9f848faSopenharmony_ci if (bus->bus_roothold != NULL) { 100f9f848faSopenharmony_ci DPRINTF("Releasing root mount hold %p\n", bus->bus_roothold); 101f9f848faSopenharmony_ci root_mount_rel(bus->bus_roothold); 102f9f848faSopenharmony_ci bus->bus_roothold = NULL; 103f9f848faSopenharmony_ci } 104f9f848faSopenharmony_ci} 105f9f848faSopenharmony_ci#endif 106f9f848faSopenharmony_ci 107f9f848faSopenharmony_ci#if USB_HAVE_DEVICE_TOPOLOGY 108f9f848faSopenharmony_ciusbd_bt_tree hub_tree; 109f9f848faSopenharmony_ci#endif 110f9f848faSopenharmony_ci 111f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 112f9f848faSopenharmony_ci * usb_attach 113f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 114f9f848faSopenharmony_cistatic int 115f9f848faSopenharmony_ciusb_attach(device_t dev) 116f9f848faSopenharmony_ci{ 117f9f848faSopenharmony_ci struct usb_bus *bus = (struct usb_bus *)device_get_ivars(dev); 118f9f848faSopenharmony_ci#if USB_HAVE_DEVICE_TOPOLOGY 119f9f848faSopenharmony_ci struct node_info info; 120f9f848faSopenharmony_ci#endif 121f9f848faSopenharmony_ci DPRINTF("\n"); 122f9f848faSopenharmony_ci 123f9f848faSopenharmony_ci if (bus == NULL) { 124f9f848faSopenharmony_ci device_printf(dev, "USB device has no ivars\n"); 125f9f848faSopenharmony_ci return (ENXIO); 126f9f848faSopenharmony_ci } 127f9f848faSopenharmony_ci 128f9f848faSopenharmony_ci#if USB_HAVE_ROOT_MOUNT_HOLD 129f9f848faSopenharmony_ci if (usb_no_boot_wait == 0) { 130f9f848faSopenharmony_ci /* delay vfs_mountroot until the bus is explored */ 131f9f848faSopenharmony_ci bus->bus_roothold = root_mount_hold(device_get_nameunit(dev)); 132f9f848faSopenharmony_ci } 133f9f848faSopenharmony_ci#endif 134f9f848faSopenharmony_ci 135f9f848faSopenharmony_ci#if USB_HAVE_DEVICE_TOPOLOGY 136f9f848faSopenharmony_ci info.port_no = 0; 137f9f848faSopenharmony_ci info.nameunit = device_get_nameunit(dev); 138f9f848faSopenharmony_ci hub_tree = usbd_create_bt_node(&info); 139f9f848faSopenharmony_ci if (hub_tree == NULL) { 140f9f848faSopenharmony_ci PRINT_ERR("Root node create failed!\n"); 141f9f848faSopenharmony_ci } 142f9f848faSopenharmony_ci#endif 143f9f848faSopenharmony_ci usb_attach_sub(dev, bus); 144f9f848faSopenharmony_ci return (0); /* return success */ 145f9f848faSopenharmony_ci} 146f9f848faSopenharmony_ci 147f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 148f9f848faSopenharmony_ci * usb_detach 149f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 150f9f848faSopenharmony_cistatic int 151f9f848faSopenharmony_ciusb_detach(device_t dev) 152f9f848faSopenharmony_ci{ 153f9f848faSopenharmony_ci struct usb_bus *bus = (struct usb_bus *)device_get_softc(dev); 154f9f848faSopenharmony_ci 155f9f848faSopenharmony_ci DPRINTF("\n"); 156f9f848faSopenharmony_ci 157f9f848faSopenharmony_ci if (bus == NULL) { 158f9f848faSopenharmony_ci /* was never setup properly */ 159f9f848faSopenharmony_ci return (0); 160f9f848faSopenharmony_ci } 161f9f848faSopenharmony_ci /* Stop power watchdog */ 162f9f848faSopenharmony_ci usb_callout_drain(&bus->power_wdog); 163f9f848faSopenharmony_ci 164f9f848faSopenharmony_ci#if USB_HAVE_ROOT_MOUNT_HOLD 165f9f848faSopenharmony_ci /* Let the USB explore process detach all devices. */ 166f9f848faSopenharmony_ci usb_root_mount_rel(bus); 167f9f848faSopenharmony_ci#endif 168f9f848faSopenharmony_ci 169f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 170f9f848faSopenharmony_ci 171f9f848faSopenharmony_ci /* Queue detach job */ 172f9f848faSopenharmony_ci (void)usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), 173f9f848faSopenharmony_ci &bus->detach_msg[0], &bus->detach_msg[1]); 174f9f848faSopenharmony_ci 175f9f848faSopenharmony_ci /* Wait for detach to complete */ 176f9f848faSopenharmony_ci usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), 177f9f848faSopenharmony_ci &bus->detach_msg[0], &bus->detach_msg[1]); 178f9f848faSopenharmony_ci 179f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 180f9f848faSopenharmony_ci 181f9f848faSopenharmony_ci#if USB_HAVE_PER_BUS_PROCESS 182f9f848faSopenharmony_ci /* Get rid of USB callback processes */ 183f9f848faSopenharmony_ci 184f9f848faSopenharmony_ci usb_proc_free(USB_BUS_GIANT_PROC(bus)); 185f9f848faSopenharmony_ci usb_proc_free(USB_BUS_NON_GIANT_ISOC_PROC(bus)); 186f9f848faSopenharmony_ci usb_proc_free(USB_BUS_NON_GIANT_BULK_PROC(bus)); 187f9f848faSopenharmony_ci 188f9f848faSopenharmony_ci /* Get rid of USB explore process */ 189f9f848faSopenharmony_ci 190f9f848faSopenharmony_ci usb_proc_free(USB_BUS_EXPLORE_PROC(bus)); 191f9f848faSopenharmony_ci 192f9f848faSopenharmony_ci /* Get rid of control transfer process */ 193f9f848faSopenharmony_ci 194f9f848faSopenharmony_ci usb_proc_free(USB_BUS_CONTROL_XFER_PROC(bus)); 195f9f848faSopenharmony_ci#endif 196f9f848faSopenharmony_ci 197f9f848faSopenharmony_ci#if USB_HAVE_PF 198f9f848faSopenharmony_ci usbpf_detach(bus); 199f9f848faSopenharmony_ci#endif 200f9f848faSopenharmony_ci 201f9f848faSopenharmony_ci#if USB_HAVE_DEVICE_TOPOLOGY 202f9f848faSopenharmony_ci usbd_free_bt_node(hub_tree); 203f9f848faSopenharmony_ci hub_tree = NULL; 204f9f848faSopenharmony_ci#endif 205f9f848faSopenharmony_ci 206f9f848faSopenharmony_ci return (0); 207f9f848faSopenharmony_ci} 208f9f848faSopenharmony_ci 209f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 210f9f848faSopenharmony_ci * usb_suspend 211f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 212f9f848faSopenharmony_cistatic int 213f9f848faSopenharmony_ciusb_suspend(device_t dev) 214f9f848faSopenharmony_ci{ 215f9f848faSopenharmony_ci struct usb_bus *bus = (struct usb_bus *)device_get_softc(dev); 216f9f848faSopenharmony_ci 217f9f848faSopenharmony_ci DPRINTF("\n"); 218f9f848faSopenharmony_ci 219f9f848faSopenharmony_ci if (bus == NULL) { 220f9f848faSopenharmony_ci /* was never setup properly */ 221f9f848faSopenharmony_ci return (0); 222f9f848faSopenharmony_ci } 223f9f848faSopenharmony_ci 224f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 225f9f848faSopenharmony_ci (void)usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), 226f9f848faSopenharmony_ci &bus->suspend_msg[0], &bus->suspend_msg[1]); 227f9f848faSopenharmony_ci if (usb_no_suspend_wait == 0) { 228f9f848faSopenharmony_ci /* wait for suspend callback to be executed */ 229f9f848faSopenharmony_ci usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), 230f9f848faSopenharmony_ci &bus->suspend_msg[0], &bus->suspend_msg[1]); 231f9f848faSopenharmony_ci } 232f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 233f9f848faSopenharmony_ci 234f9f848faSopenharmony_ci return (0); 235f9f848faSopenharmony_ci} 236f9f848faSopenharmony_ci 237f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 238f9f848faSopenharmony_ci * usb_resume 239f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 240f9f848faSopenharmony_cistatic int 241f9f848faSopenharmony_ciusb_resume(device_t dev) 242f9f848faSopenharmony_ci{ 243f9f848faSopenharmony_ci struct usb_bus *bus = (struct usb_bus *)device_get_softc(dev); 244f9f848faSopenharmony_ci 245f9f848faSopenharmony_ci DPRINTF("\n"); 246f9f848faSopenharmony_ci 247f9f848faSopenharmony_ci if (bus == NULL) { 248f9f848faSopenharmony_ci /* was never setup properly */ 249f9f848faSopenharmony_ci return (0); 250f9f848faSopenharmony_ci } 251f9f848faSopenharmony_ci 252f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 253f9f848faSopenharmony_ci (void)usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), 254f9f848faSopenharmony_ci &bus->resume_msg[0], &bus->resume_msg[1]); 255f9f848faSopenharmony_ci if (usb_no_resume_wait == 0) { 256f9f848faSopenharmony_ci /* wait for resume callback to be executed */ 257f9f848faSopenharmony_ci usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), 258f9f848faSopenharmony_ci &bus->resume_msg[0], &bus->resume_msg[1]); 259f9f848faSopenharmony_ci } 260f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 261f9f848faSopenharmony_ci 262f9f848faSopenharmony_ci return (0); 263f9f848faSopenharmony_ci} 264f9f848faSopenharmony_ci 265f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 266f9f848faSopenharmony_ci * usb_bus_reset_async_locked 267f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 268f9f848faSopenharmony_civoid 269f9f848faSopenharmony_ciusb_bus_reset_async_locked(struct usb_bus *bus) 270f9f848faSopenharmony_ci{ 271f9f848faSopenharmony_ci USB_BUS_LOCK_ASSERT(bus, MA_OWNED); 272f9f848faSopenharmony_ci 273f9f848faSopenharmony_ci DPRINTF("\n"); 274f9f848faSopenharmony_ci 275f9f848faSopenharmony_ci if ((bus->reset_msg[0].hdr.pm_qentry.tqe_prev != NULL) || 276f9f848faSopenharmony_ci (bus->reset_msg[1].hdr.pm_qentry.tqe_prev != NULL)) { 277f9f848faSopenharmony_ci DPRINTF("Reset already pending\n"); 278f9f848faSopenharmony_ci return; 279f9f848faSopenharmony_ci } 280f9f848faSopenharmony_ci 281f9f848faSopenharmony_ci device_printf(bus->parent, "Resetting controller\n"); 282f9f848faSopenharmony_ci 283f9f848faSopenharmony_ci (void)usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), 284f9f848faSopenharmony_ci &bus->reset_msg[0], &bus->reset_msg[1]); 285f9f848faSopenharmony_ci} 286f9f848faSopenharmony_ci 287f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 288f9f848faSopenharmony_ci * usb_shutdown 289f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 290f9f848faSopenharmony_cistatic int 291f9f848faSopenharmony_ciusb_shutdown(device_t dev) 292f9f848faSopenharmony_ci{ 293f9f848faSopenharmony_ci struct usb_bus *bus = device_get_softc(dev); 294f9f848faSopenharmony_ci 295f9f848faSopenharmony_ci DPRINTF("\n"); 296f9f848faSopenharmony_ci 297f9f848faSopenharmony_ci if (bus == NULL) { 298f9f848faSopenharmony_ci /* was never setup properly */ 299f9f848faSopenharmony_ci return (0); 300f9f848faSopenharmony_ci } 301f9f848faSopenharmony_ci 302f9f848faSopenharmony_ci DPRINTF("%s: Controller shutdown\n", device_get_nameunit(bus->bdev)); 303f9f848faSopenharmony_ci 304f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 305f9f848faSopenharmony_ci (void)usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), 306f9f848faSopenharmony_ci &bus->shutdown_msg[0], &bus->shutdown_msg[1]); 307f9f848faSopenharmony_ci if (usb_no_shutdown_wait == 0) { 308f9f848faSopenharmony_ci /* wait for shutdown callback to be executed */ 309f9f848faSopenharmony_ci usb_proc_mwait(USB_BUS_EXPLORE_PROC(bus), 310f9f848faSopenharmony_ci &bus->shutdown_msg[0], &bus->shutdown_msg[1]); 311f9f848faSopenharmony_ci } 312f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 313f9f848faSopenharmony_ci 314f9f848faSopenharmony_ci DPRINTF("%s: Controller shutdown complete\n", 315f9f848faSopenharmony_ci device_get_nameunit(bus->bdev)); 316f9f848faSopenharmony_ci 317f9f848faSopenharmony_ci return (0); 318f9f848faSopenharmony_ci} 319f9f848faSopenharmony_ci 320f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 321f9f848faSopenharmony_ci * usb_bus_explore 322f9f848faSopenharmony_ci * 323f9f848faSopenharmony_ci * This function is used to explore the device tree from the root. 324f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 325f9f848faSopenharmony_cistatic void 326f9f848faSopenharmony_ciusb_bus_explore(struct usb_proc_msg *pm) 327f9f848faSopenharmony_ci{ 328f9f848faSopenharmony_ci struct usb_bus *bus; 329f9f848faSopenharmony_ci struct usb_device *udev; 330f9f848faSopenharmony_ci 331f9f848faSopenharmony_ci bus = ((struct usb_bus_msg *)pm)->bus; 332f9f848faSopenharmony_ci udev = bus->devices[USB_ROOT_HUB_ADDR]; 333f9f848faSopenharmony_ci 334f9f848faSopenharmony_ci if (bus->no_explore != 0) 335f9f848faSopenharmony_ci return; 336f9f848faSopenharmony_ci 337f9f848faSopenharmony_ci if (udev != NULL) { 338f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 339f9f848faSopenharmony_ci uhub_explore_handle_re_enumerate(udev); 340f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 341f9f848faSopenharmony_ci } 342f9f848faSopenharmony_ci 343f9f848faSopenharmony_ci if ((udev != NULL) && (udev->hub != NULL)) { 344f9f848faSopenharmony_ci if (bus->do_probe) { 345f9f848faSopenharmony_ci bus->do_probe = 0; 346f9f848faSopenharmony_ci bus->driver_added_refcount++; 347f9f848faSopenharmony_ci } 348f9f848faSopenharmony_ci if (bus->driver_added_refcount == 0) { 349f9f848faSopenharmony_ci /* avoid zero, hence that is memory default */ 350f9f848faSopenharmony_ci bus->driver_added_refcount = 1; 351f9f848faSopenharmony_ci } 352f9f848faSopenharmony_ci 353f9f848faSopenharmony_ci#ifdef DDB 354f9f848faSopenharmony_ci /* 355f9f848faSopenharmony_ci * The following three lines of code are only here to 356f9f848faSopenharmony_ci * recover from DDB: 357f9f848faSopenharmony_ci */ 358f9f848faSopenharmony_ci usb_proc_rewakeup(USB_BUS_CONTROL_XFER_PROC(bus)); 359f9f848faSopenharmony_ci usb_proc_rewakeup(USB_BUS_GIANT_PROC(bus)); 360f9f848faSopenharmony_ci usb_proc_rewakeup(USB_BUS_NON_GIANT_ISOC_PROC(bus)); 361f9f848faSopenharmony_ci usb_proc_rewakeup(USB_BUS_NON_GIANT_BULK_PROC(bus)); 362f9f848faSopenharmony_ci#endif 363f9f848faSopenharmony_ci 364f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 365f9f848faSopenharmony_ci 366f9f848faSopenharmony_ci#if USB_HAVE_POWERD 367f9f848faSopenharmony_ci /* 368f9f848faSopenharmony_ci * First update the USB power state! 369f9f848faSopenharmony_ci */ 370f9f848faSopenharmony_ci usb_bus_powerd(bus); 371f9f848faSopenharmony_ci#endif 372f9f848faSopenharmony_ci /* Explore the Root USB HUB. */ 373f9f848faSopenharmony_ci (void)(udev->hub->explore) (udev); 374f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 375f9f848faSopenharmony_ci } 376f9f848faSopenharmony_ci#if USB_HAVE_ROOT_MOUNT_HOLD 377f9f848faSopenharmony_ci usb_root_mount_rel(bus); 378f9f848faSopenharmony_ci#endif 379f9f848faSopenharmony_ci} 380f9f848faSopenharmony_ci 381f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 382f9f848faSopenharmony_ci * usb_bus_detach 383f9f848faSopenharmony_ci * 384f9f848faSopenharmony_ci * This function is used to detach the device tree from the root. 385f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 386f9f848faSopenharmony_cistatic void 387f9f848faSopenharmony_ciusb_bus_detach(struct usb_proc_msg *pm) 388f9f848faSopenharmony_ci{ 389f9f848faSopenharmony_ci struct usb_bus *bus; 390f9f848faSopenharmony_ci struct usb_device *udev; 391f9f848faSopenharmony_ci device_t dev; 392f9f848faSopenharmony_ci 393f9f848faSopenharmony_ci bus = ((struct usb_bus_msg *)pm)->bus; 394f9f848faSopenharmony_ci udev = bus->devices[USB_ROOT_HUB_ADDR]; 395f9f848faSopenharmony_ci dev = bus->bdev; 396f9f848faSopenharmony_ci /* clear the softc */ 397f9f848faSopenharmony_ci device_set_softc(dev, NULL); 398f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 399f9f848faSopenharmony_ci 400f9f848faSopenharmony_ci /* detach children first */ 401f9f848faSopenharmony_ci mtx_lock(&Giant); 402f9f848faSopenharmony_ci (void)bus_generic_detach(dev); 403f9f848faSopenharmony_ci mtx_unlock(&Giant); 404f9f848faSopenharmony_ci 405f9f848faSopenharmony_ci /* 406f9f848faSopenharmony_ci * Free USB device and all subdevices, if any. 407f9f848faSopenharmony_ci */ 408f9f848faSopenharmony_ci usb_free_device(udev, 0); 409f9f848faSopenharmony_ci 410f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 411f9f848faSopenharmony_ci /* clear bdev variable last */ 412f9f848faSopenharmony_ci bus->bdev = NULL; 413f9f848faSopenharmony_ci} 414f9f848faSopenharmony_ci 415f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 416f9f848faSopenharmony_ci * usb_bus_suspend 417f9f848faSopenharmony_ci * 418f9f848faSopenharmony_ci * This function is used to suspend the USB controller. 419f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 420f9f848faSopenharmony_cistatic void 421f9f848faSopenharmony_ciusb_bus_suspend(struct usb_proc_msg *pm) 422f9f848faSopenharmony_ci{ 423f9f848faSopenharmony_ci struct usb_bus *bus; 424f9f848faSopenharmony_ci struct usb_device *udev; 425f9f848faSopenharmony_ci usb_error_t err; 426f9f848faSopenharmony_ci uint8_t do_unlock; 427f9f848faSopenharmony_ci 428f9f848faSopenharmony_ci DPRINTF("\n"); 429f9f848faSopenharmony_ci 430f9f848faSopenharmony_ci bus = ((struct usb_bus_msg *)pm)->bus; 431f9f848faSopenharmony_ci udev = bus->devices[USB_ROOT_HUB_ADDR]; 432f9f848faSopenharmony_ci 433f9f848faSopenharmony_ci if ((udev == NULL) || (bus->bdev == NULL)) 434f9f848faSopenharmony_ci return; 435f9f848faSopenharmony_ci 436f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 437f9f848faSopenharmony_ci 438f9f848faSopenharmony_ci /* 439f9f848faSopenharmony_ci * We use the shutdown event here because the suspend and 440f9f848faSopenharmony_ci * resume events are reserved for the USB port suspend and 441f9f848faSopenharmony_ci * resume. The USB system suspend is implemented like full 442f9f848faSopenharmony_ci * shutdown and all connected USB devices will be disconnected 443f9f848faSopenharmony_ci * subsequently. At resume all USB devices will be 444f9f848faSopenharmony_ci * re-connected again. 445f9f848faSopenharmony_ci */ 446f9f848faSopenharmony_ci 447f9f848faSopenharmony_ci (void)bus_generic_shutdown(bus->bdev); 448f9f848faSopenharmony_ci 449f9f848faSopenharmony_ci do_unlock = usbd_enum_lock(udev); 450f9f848faSopenharmony_ci 451f9f848faSopenharmony_ci err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX); 452f9f848faSopenharmony_ci if (err) 453f9f848faSopenharmony_ci device_printf(bus->bdev, "Could not unconfigure root HUB\n"); 454f9f848faSopenharmony_ci 455f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 456f9f848faSopenharmony_ci bus->hw_power_state = 0; 457f9f848faSopenharmony_ci bus->no_explore = 1; 458f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 459f9f848faSopenharmony_ci 460f9f848faSopenharmony_ci if (bus->methods->set_hw_power != NULL) 461f9f848faSopenharmony_ci (bus->methods->set_hw_power) (bus); 462f9f848faSopenharmony_ci 463f9f848faSopenharmony_ci if (bus->methods->set_hw_power_sleep != NULL) 464f9f848faSopenharmony_ci (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SUSPEND); 465f9f848faSopenharmony_ci 466f9f848faSopenharmony_ci if (do_unlock) 467f9f848faSopenharmony_ci usbd_enum_unlock(udev); 468f9f848faSopenharmony_ci 469f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 470f9f848faSopenharmony_ci} 471f9f848faSopenharmony_ci 472f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 473f9f848faSopenharmony_ci * usb_bus_resume 474f9f848faSopenharmony_ci * 475f9f848faSopenharmony_ci * This function is used to resume the USB controller. 476f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 477f9f848faSopenharmony_cistatic void 478f9f848faSopenharmony_ciusb_bus_resume(struct usb_proc_msg *pm) 479f9f848faSopenharmony_ci{ 480f9f848faSopenharmony_ci struct usb_bus *bus; 481f9f848faSopenharmony_ci struct usb_device *udev; 482f9f848faSopenharmony_ci usb_error_t err; 483f9f848faSopenharmony_ci uint8_t do_unlock; 484f9f848faSopenharmony_ci 485f9f848faSopenharmony_ci DPRINTF("\n"); 486f9f848faSopenharmony_ci 487f9f848faSopenharmony_ci bus = ((struct usb_bus_msg *)pm)->bus; 488f9f848faSopenharmony_ci udev = bus->devices[USB_ROOT_HUB_ADDR]; 489f9f848faSopenharmony_ci 490f9f848faSopenharmony_ci if ((udev == NULL) || (bus->bdev == NULL)) 491f9f848faSopenharmony_ci return; 492f9f848faSopenharmony_ci 493f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 494f9f848faSopenharmony_ci 495f9f848faSopenharmony_ci do_unlock = usbd_enum_lock(udev); 496f9f848faSopenharmony_ci 497f9f848faSopenharmony_ci USB_TAKE_CONTROLLER(device_get_parent(bus->bdev)); 498f9f848faSopenharmony_ci 499f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 500f9f848faSopenharmony_ci bus->hw_power_state = 501f9f848faSopenharmony_ci USB_HW_POWER_CONTROL | 502f9f848faSopenharmony_ci USB_HW_POWER_BULK | 503f9f848faSopenharmony_ci USB_HW_POWER_INTERRUPT | 504f9f848faSopenharmony_ci USB_HW_POWER_ISOC | 505f9f848faSopenharmony_ci USB_HW_POWER_NON_ROOT_HUB; 506f9f848faSopenharmony_ci bus->no_explore = 0; 507f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 508f9f848faSopenharmony_ci 509f9f848faSopenharmony_ci if (bus->methods->set_hw_power_sleep != NULL) 510f9f848faSopenharmony_ci (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_RESUME); 511f9f848faSopenharmony_ci 512f9f848faSopenharmony_ci if (bus->methods->set_hw_power != NULL) 513f9f848faSopenharmony_ci (bus->methods->set_hw_power) (bus); 514f9f848faSopenharmony_ci 515f9f848faSopenharmony_ci /* restore USB configuration to index 0 */ 516f9f848faSopenharmony_ci err = usbd_set_config_index(udev, 0); 517f9f848faSopenharmony_ci if (err) 518f9f848faSopenharmony_ci device_printf(bus->bdev, "Could not configure root HUB\n"); 519f9f848faSopenharmony_ci 520f9f848faSopenharmony_ci /* probe and attach */ 521f9f848faSopenharmony_ci err = usb_probe_and_attach(udev, USB_IFACE_INDEX_ANY); 522f9f848faSopenharmony_ci if (err) { 523f9f848faSopenharmony_ci device_printf(bus->bdev, "Could not probe and " 524f9f848faSopenharmony_ci "attach root HUB\n"); 525f9f848faSopenharmony_ci } 526f9f848faSopenharmony_ci 527f9f848faSopenharmony_ci if (do_unlock) 528f9f848faSopenharmony_ci usbd_enum_unlock(udev); 529f9f848faSopenharmony_ci 530f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 531f9f848faSopenharmony_ci} 532f9f848faSopenharmony_ci 533f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 534f9f848faSopenharmony_ci * usb_bus_reset 535f9f848faSopenharmony_ci * 536f9f848faSopenharmony_ci * This function is used to reset the USB controller. 537f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 538f9f848faSopenharmony_cistatic void 539f9f848faSopenharmony_ciusb_bus_reset(struct usb_proc_msg *pm) 540f9f848faSopenharmony_ci{ 541f9f848faSopenharmony_ci struct usb_bus *bus; 542f9f848faSopenharmony_ci 543f9f848faSopenharmony_ci DPRINTF("\n"); 544f9f848faSopenharmony_ci 545f9f848faSopenharmony_ci bus = ((struct usb_bus_msg *)pm)->bus; 546f9f848faSopenharmony_ci 547f9f848faSopenharmony_ci if ((bus->bdev == NULL) || (bus->no_explore != 0)) 548f9f848faSopenharmony_ci return; 549f9f848faSopenharmony_ci 550f9f848faSopenharmony_ci /* a suspend and resume will reset the USB controller */ 551f9f848faSopenharmony_ci usb_bus_suspend(pm); 552f9f848faSopenharmony_ci usb_bus_resume(pm); 553f9f848faSopenharmony_ci} 554f9f848faSopenharmony_ci 555f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 556f9f848faSopenharmony_ci * usb_bus_shutdown 557f9f848faSopenharmony_ci * 558f9f848faSopenharmony_ci * This function is used to shutdown the USB controller. 559f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 560f9f848faSopenharmony_cistatic void 561f9f848faSopenharmony_ciusb_bus_shutdown(struct usb_proc_msg *pm) 562f9f848faSopenharmony_ci{ 563f9f848faSopenharmony_ci struct usb_bus *bus; 564f9f848faSopenharmony_ci struct usb_device *udev; 565f9f848faSopenharmony_ci usb_error_t err; 566f9f848faSopenharmony_ci uint8_t do_unlock; 567f9f848faSopenharmony_ci 568f9f848faSopenharmony_ci DPRINTF("\n"); 569f9f848faSopenharmony_ci bus = ((struct usb_bus_msg *)pm)->bus; 570f9f848faSopenharmony_ci udev = bus->devices[USB_ROOT_HUB_ADDR]; 571f9f848faSopenharmony_ci 572f9f848faSopenharmony_ci if ((udev == NULL) || (bus->bdev == NULL)) 573f9f848faSopenharmony_ci return; 574f9f848faSopenharmony_ci 575f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 576f9f848faSopenharmony_ci 577f9f848faSopenharmony_ci (void)bus_generic_shutdown(bus->bdev); 578f9f848faSopenharmony_ci 579f9f848faSopenharmony_ci do_unlock = usbd_enum_lock(udev); 580f9f848faSopenharmony_ci 581f9f848faSopenharmony_ci err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX); 582f9f848faSopenharmony_ci if (err) 583f9f848faSopenharmony_ci device_printf(bus->bdev, "Could not unconfigure root HUB\n"); 584f9f848faSopenharmony_ci 585f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 586f9f848faSopenharmony_ci bus->hw_power_state = 0; 587f9f848faSopenharmony_ci bus->no_explore = 1; 588f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 589f9f848faSopenharmony_ci 590f9f848faSopenharmony_ci if (bus->methods->set_hw_power != NULL) 591f9f848faSopenharmony_ci (bus->methods->set_hw_power) (bus); 592f9f848faSopenharmony_ci 593f9f848faSopenharmony_ci if (bus->methods->set_hw_power_sleep != NULL) 594f9f848faSopenharmony_ci (bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SHUTDOWN); 595f9f848faSopenharmony_ci 596f9f848faSopenharmony_ci if (do_unlock) 597f9f848faSopenharmony_ci usbd_enum_unlock(udev); 598f9f848faSopenharmony_ci 599f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 600f9f848faSopenharmony_ci} 601f9f848faSopenharmony_ci 602f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 603f9f848faSopenharmony_ci * usb_bus_attach 604f9f848faSopenharmony_ci * 605f9f848faSopenharmony_ci * This function attaches USB in context of the explore thread. 606f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 607f9f848faSopenharmony_cistatic void 608f9f848faSopenharmony_ciusb_bus_attach(struct usb_proc_msg *pm) 609f9f848faSopenharmony_ci{ 610f9f848faSopenharmony_ci struct usb_bus *bus; 611f9f848faSopenharmony_ci struct usb_device *child; 612f9f848faSopenharmony_ci device_t dev; 613f9f848faSopenharmony_ci usb_error_t err; 614f9f848faSopenharmony_ci enum usb_dev_speed speed; 615f9f848faSopenharmony_ci 616f9f848faSopenharmony_ci bus = ((struct usb_bus_msg *)pm)->bus; 617f9f848faSopenharmony_ci dev = bus->bdev; 618f9f848faSopenharmony_ci 619f9f848faSopenharmony_ci DPRINTF("\n"); 620f9f848faSopenharmony_ci 621f9f848faSopenharmony_ci switch (bus->usbrev) { 622f9f848faSopenharmony_ci case USB_REV_1_0: 623f9f848faSopenharmony_ci speed = USB_SPEED_FULL; 624f9f848faSopenharmony_ci device_printf(bus->bdev, "12Mbps Full Speed USB v1.0\n"); 625f9f848faSopenharmony_ci break; 626f9f848faSopenharmony_ci 627f9f848faSopenharmony_ci case USB_REV_1_1: 628f9f848faSopenharmony_ci speed = USB_SPEED_FULL; 629f9f848faSopenharmony_ci device_printf(bus->bdev, "12Mbps Full Speed USB v1.1\n"); 630f9f848faSopenharmony_ci break; 631f9f848faSopenharmony_ci 632f9f848faSopenharmony_ci case USB_REV_2_0: 633f9f848faSopenharmony_ci speed = USB_SPEED_HIGH; 634f9f848faSopenharmony_ci device_printf(bus->bdev, "480Mbps High Speed USB v2.0\n"); 635f9f848faSopenharmony_ci break; 636f9f848faSopenharmony_ci 637f9f848faSopenharmony_ci case USB_REV_2_5: 638f9f848faSopenharmony_ci speed = USB_SPEED_VARIABLE; 639f9f848faSopenharmony_ci device_printf(bus->bdev, "480Mbps Wireless USB v2.5\n"); 640f9f848faSopenharmony_ci break; 641f9f848faSopenharmony_ci 642f9f848faSopenharmony_ci case USB_REV_3_0: 643f9f848faSopenharmony_ci speed = USB_SPEED_SUPER; 644f9f848faSopenharmony_ci device_printf(bus->bdev, "5.0Gbps Super Speed USB v3.0\n"); 645f9f848faSopenharmony_ci break; 646f9f848faSopenharmony_ci 647f9f848faSopenharmony_ci default: 648f9f848faSopenharmony_ci device_printf(bus->bdev, "Unsupported USB revision\n"); 649f9f848faSopenharmony_ci#if USB_HAVE_ROOT_MOUNT_HOLD 650f9f848faSopenharmony_ci usb_root_mount_rel(bus); 651f9f848faSopenharmony_ci#endif 652f9f848faSopenharmony_ci return; 653f9f848faSopenharmony_ci } 654f9f848faSopenharmony_ci 655f9f848faSopenharmony_ci /* default power_mask value */ 656f9f848faSopenharmony_ci bus->hw_power_state = 657f9f848faSopenharmony_ci USB_HW_POWER_CONTROL | 658f9f848faSopenharmony_ci USB_HW_POWER_BULK | 659f9f848faSopenharmony_ci USB_HW_POWER_INTERRUPT | 660f9f848faSopenharmony_ci USB_HW_POWER_ISOC | 661f9f848faSopenharmony_ci USB_HW_POWER_NON_ROOT_HUB; 662f9f848faSopenharmony_ci 663f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 664f9f848faSopenharmony_ci 665f9f848faSopenharmony_ci /* make sure power is set at least once */ 666f9f848faSopenharmony_ci 667f9f848faSopenharmony_ci if (bus->methods->set_hw_power != NULL) { 668f9f848faSopenharmony_ci (bus->methods->set_hw_power) (bus); 669f9f848faSopenharmony_ci } 670f9f848faSopenharmony_ci 671f9f848faSopenharmony_ci /* allocate the Root USB device */ 672f9f848faSopenharmony_ci 673f9f848faSopenharmony_ci child = usb_alloc_device(bus->bdev, bus, NULL, 0, 0, 1, 674f9f848faSopenharmony_ci speed, USB_MODE_HOST); 675f9f848faSopenharmony_ci if (child) { 676f9f848faSopenharmony_ci err = usb_probe_and_attach(child, 677f9f848faSopenharmony_ci USB_IFACE_INDEX_ANY); 678f9f848faSopenharmony_ci if (!err) { 679f9f848faSopenharmony_ci if ((bus->devices[USB_ROOT_HUB_ADDR] == NULL) || 680f9f848faSopenharmony_ci (bus->devices[USB_ROOT_HUB_ADDR]->hub == NULL)) { 681f9f848faSopenharmony_ci err = USB_ERR_NO_ROOT_HUB; 682f9f848faSopenharmony_ci } 683f9f848faSopenharmony_ci } 684f9f848faSopenharmony_ci } else { 685f9f848faSopenharmony_ci err = USB_ERR_NOMEM; 686f9f848faSopenharmony_ci } 687f9f848faSopenharmony_ci 688f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 689f9f848faSopenharmony_ci 690f9f848faSopenharmony_ci if (err) { 691f9f848faSopenharmony_ci device_printf(bus->bdev, "Root HUB problem, error=%s\n", 692f9f848faSopenharmony_ci usbd_errstr(err)); 693f9f848faSopenharmony_ci#if USB_HAVE_ROOT_MOUNT_HOLD 694f9f848faSopenharmony_ci usb_root_mount_rel(bus); 695f9f848faSopenharmony_ci#endif 696f9f848faSopenharmony_ci } 697f9f848faSopenharmony_ci 698f9f848faSopenharmony_ci /* set softc - we are ready */ 699f9f848faSopenharmony_ci device_set_softc(dev, bus); 700f9f848faSopenharmony_ci} 701f9f848faSopenharmony_ci 702f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 703f9f848faSopenharmony_ci * usb_attach_sub 704f9f848faSopenharmony_ci * 705f9f848faSopenharmony_ci * This function creates a thread which runs the USB attach code. 706f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 707f9f848faSopenharmony_ci 708f9f848faSopenharmony_cistatic void 709f9f848faSopenharmony_ciusb_attach_sub(device_t dev, struct usb_bus *bus) 710f9f848faSopenharmony_ci{ 711f9f848faSopenharmony_ci mtx_lock(&Giant); 712f9f848faSopenharmony_ci if (usb_devclass_ptr == NULL) 713f9f848faSopenharmony_ci usb_devclass_ptr = devclass_find("usbus"); 714f9f848faSopenharmony_ci mtx_unlock(&Giant); 715f9f848faSopenharmony_ci 716f9f848faSopenharmony_ci#if USB_HAVE_PF 717f9f848faSopenharmony_ci usbpf_attach(bus); 718f9f848faSopenharmony_ci#endif 719f9f848faSopenharmony_ci /* Initialise USB process messages */ 720f9f848faSopenharmony_ci bus->explore_msg[0].hdr.pm_callback = &usb_bus_explore; 721f9f848faSopenharmony_ci bus->explore_msg[0].bus = bus; 722f9f848faSopenharmony_ci bus->explore_msg[1].hdr.pm_callback = &usb_bus_explore; 723f9f848faSopenharmony_ci bus->explore_msg[1].bus = bus; 724f9f848faSopenharmony_ci 725f9f848faSopenharmony_ci bus->detach_msg[0].hdr.pm_callback = &usb_bus_detach; 726f9f848faSopenharmony_ci bus->detach_msg[0].bus = bus; 727f9f848faSopenharmony_ci bus->detach_msg[1].hdr.pm_callback = &usb_bus_detach; 728f9f848faSopenharmony_ci bus->detach_msg[1].bus = bus; 729f9f848faSopenharmony_ci 730f9f848faSopenharmony_ci bus->attach_msg[0].hdr.pm_callback = &usb_bus_attach; 731f9f848faSopenharmony_ci bus->attach_msg[0].bus = bus; 732f9f848faSopenharmony_ci bus->attach_msg[1].hdr.pm_callback = &usb_bus_attach; 733f9f848faSopenharmony_ci bus->attach_msg[1].bus = bus; 734f9f848faSopenharmony_ci 735f9f848faSopenharmony_ci bus->suspend_msg[0].hdr.pm_callback = &usb_bus_suspend; 736f9f848faSopenharmony_ci bus->suspend_msg[0].bus = bus; 737f9f848faSopenharmony_ci bus->suspend_msg[1].hdr.pm_callback = &usb_bus_suspend; 738f9f848faSopenharmony_ci bus->suspend_msg[1].bus = bus; 739f9f848faSopenharmony_ci 740f9f848faSopenharmony_ci bus->resume_msg[0].hdr.pm_callback = &usb_bus_resume; 741f9f848faSopenharmony_ci bus->resume_msg[0].bus = bus; 742f9f848faSopenharmony_ci bus->resume_msg[1].hdr.pm_callback = &usb_bus_resume; 743f9f848faSopenharmony_ci bus->resume_msg[1].bus = bus; 744f9f848faSopenharmony_ci 745f9f848faSopenharmony_ci bus->reset_msg[0].hdr.pm_callback = &usb_bus_reset; 746f9f848faSopenharmony_ci bus->reset_msg[0].bus = bus; 747f9f848faSopenharmony_ci bus->reset_msg[1].hdr.pm_callback = &usb_bus_reset; 748f9f848faSopenharmony_ci bus->reset_msg[1].bus = bus; 749f9f848faSopenharmony_ci 750f9f848faSopenharmony_ci bus->shutdown_msg[0].hdr.pm_callback = &usb_bus_shutdown; 751f9f848faSopenharmony_ci bus->shutdown_msg[0].bus = bus; 752f9f848faSopenharmony_ci bus->shutdown_msg[1].hdr.pm_callback = &usb_bus_shutdown; 753f9f848faSopenharmony_ci bus->shutdown_msg[1].bus = bus; 754f9f848faSopenharmony_ci 755f9f848faSopenharmony_ci#if USB_HAVE_PER_BUS_PROCESS 756f9f848faSopenharmony_ci /* Create USB explore and callback processes */ 757f9f848faSopenharmony_ci if (usb_proc_create(USB_BUS_GIANT_PROC(bus), 758f9f848faSopenharmony_ci &bus->bus_mtx, "USB_GIANT_Task", USB_PRI_MED)) { 759f9f848faSopenharmony_ci device_printf(dev, "WARNING: Creation of USB Giant " 760f9f848faSopenharmony_ci "callback process failed.\n"); 761f9f848faSopenharmony_ci } else if (usb_proc_create(USB_BUS_NON_GIANT_ISOC_PROC(bus), 762f9f848faSopenharmony_ci &bus->bus_mtx, "USB_NGIAN_ISOC_Task", USB_PRI_HIGHEST)) { 763f9f848faSopenharmony_ci device_printf(dev, "WARNING: Creation of USB non-Giant ISOC" 764f9f848faSopenharmony_ci "callback process failed.\n"); 765f9f848faSopenharmony_ci } else if (usb_proc_create(USB_BUS_NON_GIANT_BULK_PROC(bus), 766f9f848faSopenharmony_ci &bus->bus_mtx, "USB_NGIAN_BULK_Task", USB_PRI_HIGH)) { 767f9f848faSopenharmony_ci device_printf(dev, "WARNING: Creation of USB non-Giant BULK" 768f9f848faSopenharmony_ci "callback process failed.\n"); 769f9f848faSopenharmony_ci } else if (usb_proc_create(USB_BUS_EXPLORE_PROC(bus), 770f9f848faSopenharmony_ci &bus->bus_mtx, "USB_EXPLR_Task", USB_PRI_MED)) { 771f9f848faSopenharmony_ci device_printf(dev, "WARNING: Creation of USB explore " 772f9f848faSopenharmony_ci "process failed.\n"); 773f9f848faSopenharmony_ci } else if (usb_proc_create(USB_BUS_CONTROL_XFER_PROC(bus), 774f9f848faSopenharmony_ci &bus->bus_mtx, "USB_CXFER_Task", USB_PRI_MED)) { 775f9f848faSopenharmony_ci device_printf(dev, "WARNING: Creation of USB control transfer " 776f9f848faSopenharmony_ci "process failed.\n"); 777f9f848faSopenharmony_ci } else 778f9f848faSopenharmony_ci#endif 779f9f848faSopenharmony_ci { 780f9f848faSopenharmony_ci /* Get final attach going */ 781f9f848faSopenharmony_ci USB_BUS_LOCK(bus); 782f9f848faSopenharmony_ci (void)usb_proc_msignal(USB_BUS_EXPLORE_PROC(bus), 783f9f848faSopenharmony_ci &bus->attach_msg[0], &bus->attach_msg[1]); 784f9f848faSopenharmony_ci USB_BUS_UNLOCK(bus); 785f9f848faSopenharmony_ci 786f9f848faSopenharmony_ci /* Do initial explore */ 787f9f848faSopenharmony_ci if (usb_port_status_get()) { 788f9f848faSopenharmony_ci usb_needs_explore(bus, 1); 789f9f848faSopenharmony_ci } 790f9f848faSopenharmony_ci } 791f9f848faSopenharmony_ci} 792f9f848faSopenharmony_ci 793f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 794f9f848faSopenharmony_ci * usb_bus_mem_flush_all_cb 795f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 796f9f848faSopenharmony_ci#if USB_HAVE_BUSDMA 797f9f848faSopenharmony_cistatic void 798f9f848faSopenharmony_ciusb_bus_mem_flush_all_cb(struct usb_bus *bus, struct usb_page_cache *pc, 799f9f848faSopenharmony_ci struct usb_page *pg, usb_size_t nsize, usb_size_t align) 800f9f848faSopenharmony_ci{ 801f9f848faSopenharmony_ci usb_pc_cpu_flush(pc); 802f9f848faSopenharmony_ci} 803f9f848faSopenharmony_ci#endif 804f9f848faSopenharmony_ci 805f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 806f9f848faSopenharmony_ci * usb_bus_mem_flush_all - factored out code 807f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 808f9f848faSopenharmony_ci#if USB_HAVE_BUSDMA 809f9f848faSopenharmony_civoid 810f9f848faSopenharmony_ciusb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb) 811f9f848faSopenharmony_ci{ 812f9f848faSopenharmony_ci if (cb) { 813f9f848faSopenharmony_ci cb(bus, &usb_bus_mem_flush_all_cb); 814f9f848faSopenharmony_ci } 815f9f848faSopenharmony_ci} 816f9f848faSopenharmony_ci#endif 817f9f848faSopenharmony_ci 818f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 819f9f848faSopenharmony_ci * usb_bus_mem_alloc_all_cb 820f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 821f9f848faSopenharmony_ci#if USB_HAVE_BUSDMA 822f9f848faSopenharmony_cistatic void 823f9f848faSopenharmony_ciusb_bus_mem_alloc_all_cb(struct usb_bus *bus, struct usb_page_cache *pc, 824f9f848faSopenharmony_ci struct usb_page *pg, usb_size_t nsize, usb_size_t align) 825f9f848faSopenharmony_ci{ 826f9f848faSopenharmony_ci /* need to initialize the page cache */ 827f9f848faSopenharmony_ci pc->tag_parent = bus->dma_parent_tag; 828f9f848faSopenharmony_ci 829f9f848faSopenharmony_ci if (usb_pc_alloc_mem(pc, pg, nsize, align)) { 830f9f848faSopenharmony_ci bus->alloc_failed = 1; 831f9f848faSopenharmony_ci } 832f9f848faSopenharmony_ci} 833f9f848faSopenharmony_ci#endif 834f9f848faSopenharmony_ci 835f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 836f9f848faSopenharmony_ci * usb_bus_mem_alloc_all - factored out code 837f9f848faSopenharmony_ci * 838f9f848faSopenharmony_ci * Returns: 839f9f848faSopenharmony_ci * 0: Success 840f9f848faSopenharmony_ci * Else: Failure 841f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 842f9f848faSopenharmony_ciuint8_t 843f9f848faSopenharmony_ciusb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat, 844f9f848faSopenharmony_ci usb_bus_mem_cb_t *cb) 845f9f848faSopenharmony_ci{ 846f9f848faSopenharmony_ci bus->alloc_failed = 0; 847f9f848faSopenharmony_ci 848f9f848faSopenharmony_ci mtx_init(&bus->bus_mtx, device_get_nameunit(bus->parent), 849f9f848faSopenharmony_ci "usb_def_mtx", MTX_DEF | MTX_RECURSE); 850f9f848faSopenharmony_ci 851f9f848faSopenharmony_ci mtx_init(&bus->bus_spin_lock, device_get_nameunit(bus->parent), 852f9f848faSopenharmony_ci "usb_spin_mtx", MTX_SPIN | MTX_RECURSE); 853f9f848faSopenharmony_ci 854f9f848faSopenharmony_ci usb_callout_init_mtx(&bus->power_wdog, 855f9f848faSopenharmony_ci &bus->bus_mtx, 0); 856f9f848faSopenharmony_ci 857f9f848faSopenharmony_ci TAILQ_INIT(&bus->intr_q.head); 858f9f848faSopenharmony_ci 859f9f848faSopenharmony_ci#if USB_HAVE_BUSDMA 860f9f848faSopenharmony_ci usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags, 861f9f848faSopenharmony_ci dmat, &bus->bus_mtx, NULL, bus->dma_bits, USB_BUS_DMA_TAG_MAX); 862f9f848faSopenharmony_ci#endif 863f9f848faSopenharmony_ci if ((bus->devices_max > USB_MAX_DEVICES) || 864f9f848faSopenharmony_ci (bus->devices_max < USB_MIN_DEVICES) || 865f9f848faSopenharmony_ci (bus->devices == NULL)) { 866f9f848faSopenharmony_ci DPRINTFN(0, "Devices field has not been " 867f9f848faSopenharmony_ci "initialised properly\n"); 868f9f848faSopenharmony_ci bus->alloc_failed = 1; /* failure */ 869f9f848faSopenharmony_ci } 870f9f848faSopenharmony_ci#if USB_HAVE_BUSDMA 871f9f848faSopenharmony_ci if (cb) { 872f9f848faSopenharmony_ci cb(bus, &usb_bus_mem_alloc_all_cb); 873f9f848faSopenharmony_ci } 874f9f848faSopenharmony_ci#endif 875f9f848faSopenharmony_ci if (bus->alloc_failed) { 876f9f848faSopenharmony_ci usb_bus_mem_free_all(bus, cb); 877f9f848faSopenharmony_ci } 878f9f848faSopenharmony_ci return (bus->alloc_failed); 879f9f848faSopenharmony_ci} 880f9f848faSopenharmony_ci 881f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 882f9f848faSopenharmony_ci * usb_bus_mem_free_all_cb 883f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 884f9f848faSopenharmony_ci#if USB_HAVE_BUSDMA 885f9f848faSopenharmony_cistatic void 886f9f848faSopenharmony_ciusb_bus_mem_free_all_cb(struct usb_bus *bus, struct usb_page_cache *pc, 887f9f848faSopenharmony_ci struct usb_page *pg, usb_size_t nsize, usb_size_t align) 888f9f848faSopenharmony_ci{ 889f9f848faSopenharmony_ci usb_pc_free_mem(pc); 890f9f848faSopenharmony_ci} 891f9f848faSopenharmony_ci#endif 892f9f848faSopenharmony_ci 893f9f848faSopenharmony_ci/*------------------------------------------------------------------------* 894f9f848faSopenharmony_ci * usb_bus_mem_free_all - factored out code 895f9f848faSopenharmony_ci *------------------------------------------------------------------------*/ 896f9f848faSopenharmony_civoid 897f9f848faSopenharmony_ciusb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb) 898f9f848faSopenharmony_ci{ 899f9f848faSopenharmony_ci#if USB_HAVE_BUSDMA 900f9f848faSopenharmony_ci if (cb) { 901f9f848faSopenharmony_ci cb(bus, &usb_bus_mem_free_all_cb); 902f9f848faSopenharmony_ci } 903f9f848faSopenharmony_ci usb_dma_tag_unsetup(bus->dma_parent_tag); 904f9f848faSopenharmony_ci#endif 905f9f848faSopenharmony_ci 906f9f848faSopenharmony_ci mtx_destroy(&bus->bus_mtx); 907f9f848faSopenharmony_ci mtx_destroy(&bus->bus_spin_lock); 908f9f848faSopenharmony_ci} 909f9f848faSopenharmony_ci 910f9f848faSopenharmony_ci/* convenience wrappers */ 911f9f848faSopenharmony_civoid 912f9f848faSopenharmony_ciusb_proc_explore_mwait(struct usb_device *udev, void *pm1, void *pm2) 913f9f848faSopenharmony_ci{ 914f9f848faSopenharmony_ci usb_proc_mwait(USB_BUS_EXPLORE_PROC(udev->bus), pm1, pm2); 915f9f848faSopenharmony_ci} 916f9f848faSopenharmony_ci 917f9f848faSopenharmony_civoid * 918f9f848faSopenharmony_ciusb_proc_explore_msignal(struct usb_device *udev, void *pm1, void *pm2) 919f9f848faSopenharmony_ci{ 920f9f848faSopenharmony_ci return (usb_proc_msignal(USB_BUS_EXPLORE_PROC(udev->bus), pm1, pm2)); 921f9f848faSopenharmony_ci} 922f9f848faSopenharmony_ci 923f9f848faSopenharmony_civoid 924f9f848faSopenharmony_ciusb_proc_explore_lock(struct usb_device *udev) 925f9f848faSopenharmony_ci{ 926f9f848faSopenharmony_ci USB_BUS_LOCK(udev->bus); 927f9f848faSopenharmony_ci} 928f9f848faSopenharmony_ci 929f9f848faSopenharmony_civoid 930f9f848faSopenharmony_ciusb_proc_explore_unlock(struct usb_device *udev) 931f9f848faSopenharmony_ci{ 932f9f848faSopenharmony_ci USB_BUS_UNLOCK(udev->bus); 933f9f848faSopenharmony_ci} 934f9f848faSopenharmony_ci 935f9f848faSopenharmony_ci#undef USB_DEBUG_VAR 936