ehci_hub.c revision 8f1c3597a4068ed1b69c3da9a3937d938078ce94
* Initialize the root hub /* Read the EHCI capability register */ * Build the Root hub descriptor by looking EHCI capability * and operational registers. "ehci_init_root_hub: Invalid no of root hub ports 0x%x",
/* Obtain the number of downstream ports */ * Obtain the number of Classic or Companion USB 1.1 (OHCI/UHCI) * Host Controllers information. * Determine the Power Switching Mode * EHCI Specification, root hub supports either no power switching * individual port power switching. Also determine the Over-current /* Each port is powered individually */ /* Assume individual overcurrent reporting */ /* Each port will start off in the POWERED_OFF mode */ /* The ports are powered when the ctlr is powered */ /* Assume no overcurrent reporting */ /* Look at the port indicator information */ * Obtain the power on to power good time of the ports. * Assume: Zero for this field. /* Indicate if the device is removable */ /* Set PortPowerControlMask to zero */ /* Set the state of each port and initialize the status */ * ehci_load_root_hub_driver: 0x01,
/* bDescriptorType, Device */ 0x200,
/* bcdUSB, v2.0 */ 0x00,
/* bDeviceSubClass */ 0x01,
/* bDeviceProtocol */ 0x40,
/* bMaxPacketSize0 */ 0x00,
/* iManufacturer */ 0x00,
/* iSerialNumber */ 0x01 /* bNumConfigurations */ 0x02,
/* bDescriptorType, Configuartion */ 0x19,
0x00,
/* wTotalLength */ 0x01,
/* bNumInterfaces */ 0x01,
/* bConfigurationValue */ 0x00,
/* iConfiguration */ 0x04,
/* bDescriptorType, Interface */ 0x00,
/* bInterfaceNumber */ 0x00,
/* bAlternateSetting */ 0x01,
/* bNumEndpoints */ 0x09,
/* bInterfaceClass */ 0x01,
/* bInterfaceSubClass */ 0x00,
/* bInterfaceProtocol */ /* One Endpoint (status change endpoint) */ 0x05,
/* bDescriptorType, Endpoint */ 0x81,
/* bEndpointAddress */ 0x01,
0x00,
/* wMaxPacketSize, 1 + (EHCI_MAX_RH_PORTS / 8) */ "ehci_load_root_hub_driver:");
* ehci_unload_root_hub_driver: "ehci_unload_root_hub_driver:");
* ehci_handle_root_hub_pipe_open: * Handle opening of control and interrupt pipes on root hub. "ehci_handle_root_hub_pipe_open: Root hub pipe open");
/* Save control pipe handle */ /* Set state of the root hub control pipe as idle */ "ehci_handle_root_hub_pipe_open: Root hub control " /* Save interrupt pipe handle */ /* Set state of the root hub interrupt pipe as idle */ "ehci_handle_root_hub_pipe_open: Root hub interrupt " "ehci_handle_root_hub_pipe_open: Root hub pipe open" * ehci_handle_root_hub_pipe_close: * Handle closing of control and interrupt pipes on root hub. "ehci_handle_root_hub_pipe_close: Root hub pipe close");
/* Set state of the root hub control pipe as close */ /* Set root hub control pipe handle to null */ "ehci_handle_root_hub_pipe_close: " "Root hub control pipe close succeeded");
/* Set state of the root hub interrupt pipe as close */ /* Do interrupt pipe cleanup */ /* Set root hub interrupt pipe handle to null */ "ehci_handle_root_hub_pipe_close: " "Root hub interrupt pipe close succeeded");
"ehci_handle_root_hub_pipe_close: " "Root hub pipe close failed");
* ehci_handle_root_hub_pipe_reset: * Handle resetting of control and interrupt pipes on root hub. "ehci_handle_root_hub_pipe_reset: Root hub pipe reset");
"ehci_handle_root_hub_pipe_reset: Pipe reset" "for the root hub control pipe successful");
/* Do interrupt pipe cleanup */ "ehci_handle_root_hub_pipe_reset: " "Pipe reset for root hub interrupt pipe successful");
"ehci_handle_root_hub_pipe_reset: " "Root hub pipe reset failed");
* ehci_handle_root_hub_request: * Intercept a root hub request. Handle the root hub request through the "ehci_handle_root_hub_request: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%p",
"ehci_handle_root_hub_request: Pipe is not idle");
/* Save the current control request pointer */ /* Set pipe state to active */ "ehci_handle_root_hub_request:" "ehci_handle_root_hub_request: " "ehci_handle_root_hub_request: error = %d",
error);
* ehci_handle_set_clear_port_feature: "ehci_handle_set_clear_port_feature: 0x%x 0x%x 0x%x",
"ehci_handle_set_clear_port_feature: " "ehci_handle_set_clear_port_feature: " "ehci_handle_set_clear_port_feature: " * ehci_handle_port_power: * Turn on a root hub port. "ehci_handle_port_power: port = 0x%x status = 0x%x on = %d",
/* Check port is owned by ehci */ /* See if the port power is already on */ /* See if the port power is already OFF */ "ehci_handle_port_power done: port = 0x%x status = 0x%x on = %d",
* ehci_handle_port_enable: * Handle port enable request. "ehci_handle_port_enable: port = 0x%x, status = 0x%x",
/* Check port is owned by ehci */ /* See if the port enable is already on */ /* See if the port enable is already off */ * ehci_handle_clrchng_port_enable: * Handle clear port enable change bit. "ehci_handle_port_enable: port = 0x%x, status = 0x%x",
/* Check port is owned by ehci */ /* Clear the PortEnableStatusChange Bit */ * ehci_handle_port_suspend: "ehci_handle_port_suspend: port = 0x%x, status = 0x%x",
/* Check port is owned by ehci */ * Suspend port only if port is enabled and * it is not already in suspend state. /* Wait 10ms for port move to suspend state */ /* Perform resume only if port is in suspend state */ * ehci_handle_clrchng_port_suspend: * Handle port clear port suspend change bit. "ehci_handle_clrchng_port_suspend: port = 0x%x, " /* Check port is owned by ehci */ /* Return if port is not in resume state */ /* Wait for 20ms to terminate resume */ /* Wait 2ms for port to return to high speed mode */ * ehci_handle_port_reset: /* Get the root hub structure */ /* Get the port status information */ "ehci_handle_port_reset: port = 0x%x status = 0x%x",
/* Check port is owned by ehci */ /* Check for classic or companion host controllers */ "ehci_handle_port_reset: Low speed device " "and handover this port to Companion controller");
"Low speed device is not supported");
/* Wait 10ms for reset to complete */ * Wait 2ms for hardware to enable this port * if connected usb device is high speed. * If port is not enabled, connected device is a /* Check for classic or companion host controllers */ "ehci_handle_port_reset: Full speed device " "and handover this port to Companion host " "Full speed device is not supported");
"ehci_handle_port_reset: High speed device ");
* Enable over-current, connect, and disconnect * The next function is only called if the interrupt * pipe is polling and the USBA is ready to receive * ehci_root_hub_reset_occured: * Inform the upper layer that reset has occured on the port. This is * required because the upper layer is expecting a an evernt immidiately * after doing reset. In case of OHCI, the controller gets an interrupt * for the change in the root hub status but in case of EHCI, we dont. * So, send a event to the upper layer as soon as we complete the reset. "ehci_root_hub_reset_occured: curr_intr_reqp = 0x%p data = 0x%p",
/* Get the interrupt pipe handle */ /* Get the pending status */ /* Reset pending status */ /* If needed, allocate new interrupt request */ /* Do interrupt pipe cleanup */ * ehci_handle_complete_port_reset: * Perform a port reset change. "ehci_handle_complete_port_reset: port = 0x%x status = 0x%x",
/* Check port is owned by ehci */ * ehci_handle_clear_port_connection: * Perform a clear port connection. "ehci_handle_clear_port_connection: port = 0x%x" * ehci_handle_clrchng_port_over_current: * Perform a clear port connection. "ehci_handle_clrchng_port_over_current: port = 0x%x" * ehci_handle_get_port_status: * Handle a get port status request. /* Get the root hub port status information */ "ehci_handle_get_port_status: port = %d new status = 0x%x" /* Save the data in control request */ * ehci_handle_get_hub_descriptor: "ehci_handle_get_hub_descriptor: Ctrl Req = 0x%p",
ctrl_reqp);
/* Save the data in control request */ * ehci_handle_get_hub_status: * Handle a get hub status request. * For EHCI, there is no overall hub status information. * Only individual root hub port status information is * available. So return zero for the root hub status "ehci_handle_get_hub_status: new root hub status = 0x%x",
/* Save the data in control request */ * ehci_handle_root_hub_pipe_start_intr_polling: * Handle start polling on root hub interrupt pipe. "ehci_handle_root_hub_pipe_start_intr_polling: " "Root hub pipe start polling");
* Save the Original Client's Interrupt IN request * information. We use this for final callback /* Reset client interrupt request pointer */ "ehci_handle_root_hub_pipe_start_intr_polling: " /* Check whether we need to send the reset data up */ "ehci_handle_root_hub_pipe_start_intr_polling: " "Start polling for root hub successful");
"ehci_handle_root_hub_pipe_start_intr_polling: " "Polling for root hub is already in progress");
"ehci_handle_root_hub_pipe_start_intr_polling: " * ehci_handle_root_hub_pipe_stop_intr_polling: * Handle stop polling on root hub intr pipe. "ehci_handle_root_hub_pipe_stop_intr_polling: " "Root hub pipe stop polling");
/* Do interrupt pipe cleanup */ "ehci_hcdi_pipe_stop_intr_polling: Stop polling for root" "Polling for root hub is already stopped");
* ehci_get_root_hub_port_status: * Construct root hub port status and change information /* Read the current port status */ "ehci_get_root_hub_port_status: port %d " * EHCI root hub port status and control register information * format is different what Hub driver wants. So EHCI driver * needs to contruct the proper root hub port status information. * Send all port status information only if port is owned by EHCI /* First construct port change information */ /* Now construct port status information */ * Send the following port status and change information * even if port is not owned by EHCI. * Additional port change information. /* Additional port status information */ * Construct complete root hub port status and change information. "ehci_get_root_hub_port_status: port = %d new status = 0x%x " "change status = 0x%x complete port status 0x%x",
port,
* Check whether given port is owned by ehci. * Don't perform anything if port is owned by classis host * controller and return success. "ehci_handle_set_clear_port_feature: " "Port %d is owned by classic host controller",
port);
* ehci_root_hub_allocate_intr_pipe_resource: * Allocate interrupt requests and initialize them. "ehci_root_hub_allocate_intr_pipe_resource");
/* Get the interrupt pipe handle */ /* Get the current interrupt request pointer */ * If current interrupt request pointer is null, * allocate new interrupt request. /* Get the length of interrupt transfer */ "ehci_root_hub_allocate_intr_pipe_resource:" "Interrupt request structure allocation failed");
/* Start the timer for the root hub interrupt pipe polling */ * ehci_root_hub_intr_pipe_cleanup: * Deallocate all interrupt requests and do callback * the original client interrupt request. "ehci_root_hub_intr_pipe_cleanup");
/* Get the interrupt pipe handle */ /* Get the interrupt timerid */ /* Stop the root hub interrupt timer */ /* Reset the timer id to zero */ /* Reset the current interrupt request pointer */ /* Deallocate uncompleted interrupt request */ /* Callback for original client interrupt request */ * ehci_handle_root_hub_status_change: * A root hub status change interrupt will occur any time there is a change * in the root hub status register or one of the port status registers. "ehci_handle_root_hub_status_change: state = %d",
/* Get the current interrupt request pointer */ /* Check whether timeout handler is valid */ /* Check host controller is in operational state */ /* Do interrupt pipe cleanup */ * If there is change in the port status then set the bit in the * bitmap of changes and inform hub driver about these changes. * Hub driver will take care of these changes. * Update the state depending on whether * the port was attached or detached. "Port %d connected", i+
1);
"Port %d disconnected", i+
1);
/* See if port enable status changed */ * Update the state depending on whether * the port was enabled or disabled. "Port %d disabled", i+
1);
/* Get the message block */ * check that the mblk is big enough when we * are writing bytes into it "ehci_handle_root_hub_status_change" * If needed, allocate new interrupt request. Also * start the timer for the root hub interrupt polling. "ehci_handle_root_hub_status_change: No Resources");
/* Do interrupt pipe cleanup */ * ehci_root_hub_hcdi_callback() * Convenience wrapper around usba_hcdi_cb() for the root hub. "ehci_root_hub_hcdi_callback: ph = 0x%p, cr = 0x%x",
/* Set the pipe state as per completion reason */ /* Set pipe state to idle */ /* Set pipe state to error */ /* if curr_intr_reqp available then use this request */ /* no current request, use client's request */