ohci_hub.c revision 35f36846429327ed1512f8098c6a6b337055d875
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License, Version 1.0 only 2N/A * (the "License"). You may not use this file except in compliance 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A * Open Host Controller Driver (OHCI) 2N/A * The USB Open Host Controller driver is a software driver which interfaces 2N/A * to the Universal Serial Bus layer (USBA) and the USB Open Host Controller. 2N/A * The interface to USB Open Host Controller is defined by the OpenHCI Host 2N/A * Controller Interface. 2N/A * This module contains the code for root hub related functions. 2N/A * Note: ONE_XFER is not supported on root hub interrupt polling. 2N/A/* static function prototypes */ 2N/A * ohci_init_root_hub: 2N/A * Initialize the root hub 2N/A "ohci_init_root_hub:");
2N/A /* Read the descriptor registers */ 2N/A /* Obtain the root hub status */ 2N/A * Build the hub descriptor based on HcRhDescriptorA and 2N/A "ohci_init_root_hub:" "Invalid no of root hub ports 0x%x",
2N/A /* Obtain the number of downstream ports */ 2N/A /* Determine the Power Switching Mode */ 2N/A * The ports are power switched. Check for either individual 2N/A * or gang power switching. 2N/A /* each port is powered individually */ 2N/A /* the ports are gang powered */ 2N/A /* Each port will start off in the POWERED_OFF mode */ 2N/A /* The ports are powered when the ctlr is powered */ 2N/A /* The root hub should never be a compound device */ 2N/A /* Determine the Over-current Protection Mode */ 2N/A /* No over current protection */ 2N/A /* See if over current protection is provided */ 2N/A /* reported on a per port basis */ 2N/A /* Obtain the power on to power good time of the ports */ 2N/A /* Indicate if the device is removable */ 2N/A * Fill in the port power control mask: 2N/A * Each bit in the PortPowerControlMask 2N/A * should be set. Refer to USB 2.0, table 11-13 2N/A /* Set the state of each port and initialize the status */ 2N/A /* Turn off the power on each port for now */ 2N/A * Initialize each of the root hub port status 2N/A * equal to zero. This initialization makes sure 2N/A * that all devices connected to root hub will 2N/A * enumerates when the first RHSC interrupt occurs 2N/A * since definitely there will be changes in 2N/A * the root hub port status. 2N/A * ohci_load_root_hub_driver: 2N/A * Attach the root hub 2N/A 0x01,
/* bDescriptorType, Device */ 2N/A 0x110,
/* bcdUSB, v1.1 */ 2N/A 0x09,
/* bDeviceClass */ 2N/A 0x00,
/* bDeviceSubClass */ 2N/A 0x00,
/* bDeviceProtocol */ 2N/A 0x08,
/* bMaxPacketSize0 */ 2N/A 0x00,
/* idVendor */ 2N/A 0x00,
/* idProduct */ 2N/A 0x00,
/* bcdDevice */ 2N/A 0x00,
/* iManufacturer */ 2N/A 0x00,
/* iProduct */ 2N/A 0x00,
/* iSerialNumber */ 2N/A 0x01 /* bNumConfigurations */ 2N/A /* One configuartion */ 2N/A 0x02,
/* bDescriptorType, Configuartion */ 2N/A 0x19,
0x00,
/* wTotalLength */ 2N/A 0x01,
/* bNumInterfaces */ 2N/A 0x01,
/* bConfigurationValue */ 2N/A 0x00,
/* iConfiguration */ 2N/A 0x40,
/* bmAttributes */ 2N/A 0x00,
/* MaxPower */ 2N/A 0x04,
/* bDescriptorType, Interface */ 2N/A 0x00,
/* bInterfaceNumber */ 2N/A 0x00,
/* bAlternateSetting */ 2N/A 0x01,
/* bNumEndpoints */ 2N/A 0x09,
/* bInterfaceClass */ 2N/A 0x01,
/* bInterfaceSubClass */ 2N/A 0x00,
/* bInterfaceProtocol */ 2N/A 0x00,
/* iInterface */ 2N/A /* One Endpoint (status change endpoint) */ 2N/A 0x05,
/* bDescriptorType, Endpoint */ 2N/A 0x81,
/* bEndpointAddress */ 2N/A 0x03,
/* bmAttributes */ 2N/A 0x01,
0x00,
/* wMaxPacketSize, 1 + (OHCI_MAX_RH_PORTS / 8) */ 2N/A 0xff /* bInterval */ 2N/A "ohci_load_root_hub_driver:");
2N/A * ohci_unload_root_hub_driver: 2N/A "ohci_unload_root_hub_driver:");
2N/A * ohci_handle_root_hub_pipe_open: 2N/A * Handle opening of control and interrupt pipes on root hub. 2N/A "ohci_handle_root_hub_pipe_open: Root hub pipe open");
2N/A /* Save control pipe handle */ 2N/A /* Set state of the root hub control pipe as idle */ 2N/A "ohci_handle_root_hub_pipe_open: Root hub control " 2N/A "pipe open succeeded");
2N/A /* Save interrupt pipe handle */ 2N/A /* Set state of the root hub interrupt pipe as idle */ 2N/A "ohci_handle_root_hub_pipe_open: Root hub interrupt " 2N/A "pipe open succeeded");
2N/A "ohci_handle_root_hub_pipe_open: Root hub pipe open" 2N/A * ohci_handle_root_hub_pipe_close: 2N/A * Handle closing of control and interrupt pipes on root hub. 2N/A "ohci_handle_root_hub_pipe_close: Root hub pipe close");
2N/A /* Set state of the root hub control pipe as close */ 2N/A /* Set root hub control pipe handle to null */ 2N/A "ohci_handle_root_hub_pipe_close: " 2N/A "Root hub control pipe close succeeded");
2N/A /* Set state of the root hub interrupt pipe as close */ 2N/A /* Do interrupt pipe cleanup */ 2N/A /* Set root hub interrupt pipe handle to null */ 2N/A "ohci_handle_root_hub_pipe_close: " 2N/A "Root hub interrupt pipe close succeeded");
2N/A "ohci_handle_root_hub_pipe_close: " 2N/A "Root hub pipe close failed");
2N/A * ohci_handle_root_hub_pipe_reset: 2N/A * Handle resetting of control and interrupt pipes on root hub. 2N/A "ohci_handle_root_hub_pipe_reset: Root hub pipe reset");
2N/A "ohci_handle_root_hub_pipe_reset: Pipe reset" 2N/A "for the root hub control pipe successful");
2N/A /* Do interrupt pipe cleanup */ 2N/A "ohci_handle_root_hub_pipe_reset: " 2N/A "Pipe reset for root hub interrupt pipe successful");
2N/A "ohci_handle_root_hub_pipe_reset: " 2N/A "Root hub pipe reset failed");
2N/A * ohci_handle_root_hub_request: 2N/A * Intercept a root hub request. Handle the root hub request through the 2N/A "ohci_handle_root_hub_request: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%p",
2N/A "ohci_handle_root_hub_request: Pipe is not idle");
2N/A /* Save the current control request pointer */ 2N/A /* Set pipe state to active */ 2N/A "ohci_handle_root_hub_request:" 2N/A "ohci_handle_root_hub_request: " 2N/A "ohci_handle_root_hub_request: error = %d",
error);
2N/A * ohci_handle_set_clear_port_feature: 2N/A "ohci_handle_set_clear_port_feature: 0x%x 0x%x 0x%x",
2N/A "ohci_handle_set_clear_port_feature: " 2N/A "ohci_handle_set_clear_port_feature: " 2N/A "ohci_handle_set_clear_port_feature: " 2N/A * ohci_handle_port_power: 2N/A * Turn on a root hub port. 2N/A "ohci_handle_port_power: port = 0x%x status = 0x%x on = %d",
2N/A * If the port power is ganged, enable the power through 2N/A * the status registers, else enable the port power. 2N/A /* See if the port power is already on */ 2N/A /* Turn the port on */ 2N/A * If the port power is ganged, disable the power through 2N/A * the status registers, else disable the port power. 2N/A /* See if the port power is already OFF */ 2N/A /* Turn the port OFF by writing LSSA bit */ 2N/A "ohci_handle_port_power done: " 2N/A "port = 0x%x status = 0x%x on = %d",
2N/A * ohci_handle_port_enable: 2N/A * Handle port enable request. 2N/A "ohci_handle_port_enable: port = 0x%x, status = 0x%x",
2N/A /* See if the port enable is already on */ 2N/A /* Enable the port */ 2N/A /* See if the port enable is already off */ 2N/A /* disable the port by writing CCS bit */ 2N/A * ohci_handle_clrchng_port_enable: 2N/A * Handle clear port enable change bit. 2N/A "ohci_handle_port_enable: port = 0x%x, status = 0x%x",
2N/A /* Clear the PortEnableStatusChange Bit */ 2N/A * ohci_handle_port_suspend: 2N/A "ohci_handle_port_suspend: port = 0x%x, status = 0x%x",
2N/A /* Suspend the port */ 2N/A /* To Resume, we write the POCI bit */ 2N/A * ohci_handle_clrchng_port_suspend: 2N/A * Handle port clear port suspend change bit. 2N/A "ohci_handle_clrchng_port_suspend: port = 0x%x, status = 0x%x",
2N/A * ohci_handle_port_reset: 2N/A * Perform a port reset. 2N/A "ohci_handle_port_reset: port = 0x%x status = 0x%x",
2N/A "port_status & HCR_PORT_CCS == 0: " 2N/A * ohci_handle_complete_port_reset: 2N/A * Perform a port reset change. 2N/A "ohci_handle_complete_port_reset: port = 0x%x status = 0x%x",
2N/A "port_status & HCR_PORT_CCS == 0: " 2N/A * ohci_handle_clear_port_connection: 2N/A * Perform a clear port connection. 2N/A "ohci_handle_clear_port_connection: port = 0x%x" 2N/A * ohci_handle_clrchng_port_over_current: 2N/A * Perform a clear over current condition. 2N/A "ohci_handle_clrchng_port_over_current: port = 0x%x" 2N/A * ohci_handle_get_port_status: 2N/A * Handle a get port status request. 2N/A /* Read the current port status and return it */ 2N/A "ohci_handle_get_port_status: port = %d new status = 0x%x" 2N/A /* Save the data in control request */ 2N/A * ohci_handle_get_hub_descriptor: 2N/A "ohci_handle_get_hub_descriptor: Ctrl Req = 0x%p",
2N/A /* Save the data in control request */ 2N/A * ohci_handle_get_hub_status: 2N/A * Handle a get hub status request. 2N/A "ohci_handle_get_hub_status: new root hub status = 0x%x",
2N/A /* Save the data in control request */ 2N/A * ohci_handle_get_device_status: 2N/A * Handle a get device status request. 2N/A * OHCI doesn't have device status information. 2N/A * Simply return what is desired for the request. 2N/A "ohci_handle_get_device_status: device status = 0x%x",
2N/A /* Save the data in control request */ 2N/A * ohci_handle_root_hub_pipe_start_intr_polling: 2N/A * Handle start polling on root hub interrupt pipe. 2N/A "ohci_handle_root_hub_pipe_start_intr_polling: " 2N/A "Root hub pipe start polling");
2N/A /* ONE_XFER not supported for root hub interrupt pipe */ 2N/A /* Get root hub intr pipe state */ 2N/A * Save the Original Client's Interrupt IN request 2N/A * information. We use this for final callback 2N/A /* Reset client interrupt request pointer */ 2N/A "ohci_handle_root_hub_pipe_start_intr_polling: " 2N/A "ohci_handle_root_hub_pipe_start_intr_polling: " 2N/A "Start polling for root hub successful");
2N/A "ohci_handle_root_hub_pipe_start_intr_polling: " 2N/A "Polling for root hub is already in progress");
2N/A "ohci_handle_root_hub_pipe_start_intr_polling: " 2N/A * ohci_handle_root_hub_pipe_stop_intr_polling: 2N/A * Handle stop polling on root hub intr pipe. 2N/A "ohci_handle_root_hub_pipe_stop_intr_polling: " 2N/A "Root hub pipe stop polling");
2N/A /* Do interrupt pipe cleanup */ 2N/A "ohci_hcdi_pipe_stop_intr_polling: Stop polling for root" 2N/A "ohci_hcdi_pipe_stop_intr_polling: " 2N/A "Polling for root hub is already stopped");
2N/A * ohci_root_hub_allocate_intr_pipe_resource: 2N/A * Allocate interrupt requests and initialize them. 2N/A "ohci_root_hub_allocate_intr_pipe_resource");
2N/A /* Get the interrupt pipe handle */ 2N/A /* Get the current interrupt request pointer */ 2N/A * If current interrupt request pointer is null, 2N/A * allocate new interrupt request. 2N/A /* Get the length of interrupt transfer */ 2N/A "ohci_root_hub_allocate_intr_pipe_resource:" 2N/A "Interrupt request structure allocation failed");
2N/A /* Start the timer for the root hub interrupt pipe polling */ 2N/A * ohci_root_hub_intr_pipe_cleanup: 2N/A * Deallocate all interrupt requests and do callback 2N/A * the original client interrupt request. 2N/A "ohci_root_hub_intr_pipe_cleanup");
2N/A /* Get the interrupt pipe handle */ 2N/A /* Get the interrupt timerid */ 2N/A /* Stop the root hub interrupt timer */ 2N/A /* Reset the timer id to zero */ 2N/A /* Reset the current interrupt request pointer */ 2N/A /* Deallocate uncompleted interrupt request */ 2N/A /* Callback for original client interrupt request */ 2N/A * ohci_handle_root_hub_status_change: 2N/A * A root hub status change interrupt will occur any time there is a change 2N/A * in the root hub status register or one of the port status registers. 2N/A "ohci_handle_root_hub_status_change: state = %d",
2N/A /* Get the pointer to root hub descriptor */ 2N/A /* Get the current interrupt request pointer */ 2N/A /* Check whether timeout handler is valid */ 2N/A /* Check host controller is in operational state */ 2N/A /* Reset the timer id */ 2N/A /* Do interrupt pipe cleanup */ 2N/A /* See if the root hub status has changed */ 2N/A "ohci_handle_root_hub_status_change: " 2N/A "Root hub status has changed!");
2N/A /* Check each port */ 2N/A * If there is change in the port status then set 2N/A * the bit in the bitmap of changes and inform hub 2N/A * driver about these changes. Hub driver will take 2N/A * care of these changes. 2N/A * Update the state depending on whether 2N/A * the port was attached or detached. 2N/A "Port %d connected", i+
1);
2N/A "Port %d disconnected", i+
1);
2N/A /* See if port enable status changed */ 2N/A * Update the state depending on whether 2N/A * the port was enabled or disabled. 2N/A "Port %d enabled", i+
1);
2N/A "Port %d disabled", i+
1);
2N/A /* Update the status */ 2N/A /* Get the message block */ 2N/A * check that mblk is big enough when we 2N/A * are writing bytes into it 2N/A "ohci_handle_root_hub_status_change: " 2N/A "mblk data overflow.");
2N/A /* Reset the timer id */ 2N/A * If needed, allocate new interrupt request. Also 2N/A * start the timer for the root hub interrupt polling. 2N/A "ohci_handle_root_hub_status_change: No Resources");
2N/A /* Do interrupt pipe cleanup */ 2N/A * ohci_root_hub_hcdi_callback() 2N/A * Convenience wrapper around usba_hcdi_cb() for the root hub. 2N/A "ohci_root_hub_hcdi_callback: ph = 0x%p, cr = 0x%x",
2N/A /* Set the pipe state as per completion reason */ 2N/A /* Set pipe state to idle */ 2N/A /* Set pipe state to error */ 2N/A /* if curr_intr_reqp available then use this request */ 2N/A /* no current request, use client's request */