1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * EHCI Host Controller Driver (EHCI)
30  *
31  * The EHCI driver is a software driver which interfaces to the Universal
32  * Serial Bus layer (USBA) and the Host Controller (HC). The interface to
33  * the Host Controller is defined by the EHCI Host Controller Interface.
34  *
35  * This module contains the code for root hub related functions.
36  *
37  * NOTE:
38  *
39  * ONE_XFER is not supported on root hub interrupt polling
40  */
41 
42 #include <sys/usb/hcd/ehci/ehcid.h>
43 #include <sys/usb/hcd/ehci/ehci_util.h>
44 #include <sys/usb/usba/usba_types.h>
45 
46 /* Static function prototypes */
47 static int	ehci_handle_set_clear_port_feature(
48 				ehci_state_t		*ehcip,
49 				uchar_t 		bRequest,
50 				uint16_t		wValue,
51 				uint16_t		port);
52 static void	ehci_handle_port_power(
53 				ehci_state_t		*ehcip,
54 				uint16_t		port,
55 				uint_t			on);
56 static void	ehci_handle_port_enable(
57 				ehci_state_t		*ehcip,
58 				uint16_t		port,
59 				uint_t			on);
60 static void	ehci_handle_clrchng_port_enable(
61 				ehci_state_t		*ehcip,
62 				uint16_t		port);
63 static void	ehci_handle_port_suspend(
64 				ehci_state_t		*ehcip,
65 				uint16_t		port,
66 				uint_t			on);
67 static void	ehci_handle_clrchng_port_suspend(
68 				ehci_state_t		*ehcip,
69 				uint16_t		port);
70 static void	ehci_handle_port_reset(
71 				ehci_state_t		*ehcip,
72 				uint16_t		port);
73 static void	ehci_root_hub_reset_occured(
74 				ehci_state_t		*ehcip);
75 static void	ehci_handle_complete_port_reset(
76 				ehci_state_t		*ehcip,
77 				uint16_t		port);
78 static void	ehci_handle_clear_port_connection(
79 				ehci_state_t		*ehcip,
80 				uint16_t		port);
81 static void	ehci_handle_clrchng_port_over_current(
82 				ehci_state_t		*ehcip,
83 				uint16_t		port);
84 static void	ehci_handle_get_port_status(
85 				ehci_state_t		*ehcip,
86 				uint16_t		port);
87 static void	ehci_handle_get_hub_descriptor(
88 				ehci_state_t		*ehcip);
89 static void	ehci_handle_get_hub_status(
90 				ehci_state_t		*ehcip);
91 static void	ehci_handle_get_device_status(
92 				ehci_state_t		*ehcip);
93 static uint_t	ehci_get_root_hub_port_status(
94 				ehci_state_t		*ehcip,
95 				uint16_t		port);
96 static int	ehci_is_port_owner(
97 				ehci_state_t		*ehcip,
98 				uint16_t		port);
99 static int	ehci_root_hub_allocate_intr_pipe_resource(
100 				ehci_state_t		*ehcip,
101 				usb_flags_t		flags);
102 static void	ehci_root_hub_intr_pipe_cleanup(
103 				ehci_state_t		*ehcip,
104 				usb_cr_t		completion_reason);
105 static void	ehci_handle_root_hub_status_change(void *arg);
106 static void	ehci_root_hub_hcdi_callback(
107 				usba_pipe_handle_data_t	*ph,
108 				usb_cr_t		completion_reason);
109 
110 
111 /*
112  * ehci_init_root_hub:
113  *
114  * Initialize the root hub
115  */
116 int
117 ehci_init_root_hub(ehci_state_t	*ehcip)
118 {
119 	usb_hub_descr_t		*root_hub_descr =
120 				    &ehcip->ehci_root_hub.rh_descr;
121 	uint_t			i, length, port_state;
122 	uint32_t		capability;
123 
124 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
125 	    "ehci_init_root_hub:");
126 
127 	/* Read the EHCI capability register */
128 	capability = Get_Cap(ehci_hcs_params);
129 
130 	/*
131 	 * Build the Root hub descriptor by looking EHCI capability
132 	 * and operational registers.
133 	 */
134 	root_hub_descr->bDescriptorType = ROOT_HUB_DESCRIPTOR_TYPE;
135 
136 	if ((capability & EHCI_HCS_NUM_PORTS) > EHCI_MAX_RH_PORTS) {
137 
138 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
139 		    "ehci_init_root_hub: Invalid no of root hub ports 0x%x",
140 		    capability & EHCI_HCS_NUM_PORTS);
141 
142 		return (USB_FAILURE);
143 	}
144 
145 	/* Obtain the number of downstream ports */
146 	root_hub_descr->bNbrPorts = capability & EHCI_HCS_NUM_PORTS;
147 
148 	length = root_hub_descr->bNbrPorts / 8;
149 
150 	if (length) {
151 		root_hub_descr->bDescLength = 7 + (2 * (length + 1));
152 	} else {
153 		root_hub_descr->bDescLength = ROOT_HUB_DESCRIPTOR_LENGTH;
154 	}
155 
156 	/*
157 	 * Obtain the number of Classic or Companion USB 1.1 (OHCI/UHCI)
158 	 * Host Controllers information.
159 	 */
160 	ehcip->ehci_root_hub.rh_companion_controllers = (capability &
161 	    EHCI_HCS_NUM_COMP_CTRLS) >> EHCI_HCS_NUM_COMP_CTRL_SHIFT;
162 
163 	/*
164 	 * Determine the Power Switching Mode
165 	 *
166 	 * EHCI Specification, root hub supports either no power switching
167 	 * individual port power switching. Also determine the Over-current
168 	 * Protection Mode.
169 	 */
170 	if (capability & EHCI_HCS_PORT_POWER_CONTROL) {
171 		/* Each port is powered individually */
172 		root_hub_descr-> wHubCharacteristics =
173 		    HUB_CHARS_INDIVIDUAL_PORT_POWER;
174 
175 		/* Assume individual overcurrent reporting */
176 		root_hub_descr->wHubCharacteristics |=
177 		    HUB_CHARS_INDIV_OVER_CURRENT;
178 
179 		/* Each port will start off in the POWERED_OFF mode */
180 		port_state = POWERED_OFF;
181 	} else {
182 		/* The ports are powered when the ctlr is powered */
183 		root_hub_descr->
184 		    wHubCharacteristics = HUB_CHARS_NO_POWER_SWITCHING;
185 
186 		/* Assume no overcurrent reporting */
187 		root_hub_descr->wHubCharacteristics |=
188 		    HUB_CHARS_NO_OVER_CURRENT;
189 
190 		port_state = DISCONNECTED;
191 	}
192 
193 	/* Look at the port indicator information */
194 	if (capability & EHCI_HCS_PORT_INDICATOR) {
195 		root_hub_descr->wHubCharacteristics |= HUB_CHARS_PORT_INDICATOR;
196 	}
197 
198 	/*
199 	 * Obtain the power on to power good time of the ports.
200 	 *
201 	 * Assume: Zero for this field.
202 	 */
203 	root_hub_descr->bPwrOn2PwrGood = 2;
204 
205 	USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
206 	    "Power on to power good %d", root_hub_descr->bPwrOn2PwrGood);
207 
208 	/* Indicate if the device is removable */
209 	root_hub_descr->DeviceRemovable = 0;
210 
211 	/* Set PortPowerControlMask to zero */
212 	root_hub_descr->PortPwrCtrlMask = 0;
213 
214 	/* Set the state of each port and initialize the status */
215 	for (i = 0; i < root_hub_descr->bNbrPorts; i++) {
216 
217 		/* Initilize state/status of each root hub port */
218 		ehcip->ehci_root_hub.rh_port_state[i] = port_state;
219 		ehcip->ehci_root_hub.rh_port_status[i] = 0;
220 	}
221 
222 	return (USB_SUCCESS);
223 }
224 
225 
226 /*
227  * ehci_load_root_hub_driver:
228  *
229  * Attach the root hub
230  */
231 static usb_dev_descr_t ehci_root_hub_device_descriptor = {
232 	0x12,		/* bLength */
233 	0x01,		/* bDescriptorType, Device */
234 	0x200,		/* bcdUSB, v2.0 */
235 	0x09,		/* bDeviceClass */
236 	0x00,		/* bDeviceSubClass */
237 	0x01,		/* bDeviceProtocol */
238 	0x40,		/* bMaxPacketSize0 */
239 	0x00,		/* idVendor */
240 	0x00,		/* idProduct */
241 	0x00,		/* bcdDevice */
242 	0x00,		/* iManufacturer */
243 	0x00,		/* iProduct */
244 	0x00,		/* iSerialNumber */
245 	0x01		/* bNumConfigurations */
246 };
247 
248 static uchar_t ehci_root_hub_config_descriptor[] = {
249 	/* One configuartion */
250 	0x09,		/* bLength */
251 	0x02,		/* bDescriptorType, Configuartion */
252 	0x19, 0x00,	/* wTotalLength */
253 	0x01,		/* bNumInterfaces */
254 	0x01,		/* bConfigurationValue */
255 	0x00,		/* iConfiguration */
256 	0x40,		/* bmAttributes */
257 	0x00,		/* MaxPower */
258 
259 	/* One Interface */
260 	0x09,		/* bLength */
261 	0x04,		/* bDescriptorType, Interface */
262 	0x00,		/* bInterfaceNumber */
263 	0x00,		/* bAlternateSetting */
264 	0x01,		/* bNumEndpoints */
265 	0x09,		/* bInterfaceClass */
266 	0x01,		/* bInterfaceSubClass */
267 	0x00,		/* bInterfaceProtocol */
268 	0x00,		/* iInterface */
269 
270 	/* One Endpoint (status change endpoint) */
271 	0x07,		/* bLength */
272 	0x05,		/* bDescriptorType, Endpoint */
273 	0x81,		/* bEndpointAddress */
274 	0x03,		/* bmAttributes */
275 	0x01, 0x00,	/* wMaxPacketSize, 1 +  (EHCI_MAX_RH_PORTS / 8) */
276 	0xff		/* bInterval */
277 };
278 
279 int
280 ehci_load_root_hub_driver(ehci_state_t	*ehcip)
281 {
282 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
283 	    "ehci_load_root_hub_driver:");
284 
285 	return (usba_hubdi_bind_root_hub(ehcip->ehci_dip,
286 	    ehci_root_hub_config_descriptor,
287 	    sizeof (ehci_root_hub_config_descriptor),
288 	    &ehci_root_hub_device_descriptor));
289 }
290 
291 
292 /*
293  * ehci_unload_root_hub_driver:
294  */
295 int
296 ehci_unload_root_hub_driver(ehci_state_t	*ehcip)
297 {
298 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
299 	    "ehci_unload_root_hub_driver:");
300 
301 	return (usba_hubdi_unbind_root_hub(ehcip->ehci_dip));
302 }
303 
304 
305 /*
306  * ehci_handle_root_hub_pipe_open:
307  *
308  * Handle opening of control and interrupt pipes on root hub.
309  */
310 /* ARGSUSED */
311 int
312 ehci_handle_root_hub_pipe_open(
313 	usba_pipe_handle_data_t	*ph,
314 	usb_flags_t		usb_flags)
315 {
316 	ehci_state_t		*ehcip = ehci_obtain_state(
317 				    ph->p_usba_device->usb_root_hub_dip);
318 	usb_ep_descr_t		*eptd = &ph->p_ep;
319 
320 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
321 	    "ehci_handle_root_hub_pipe_open: Root hub pipe open");
322 
323 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
324 
325 	switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
326 	case USB_EP_ATTR_CONTROL:
327 		/* Save control pipe handle */
328 		ehcip->ehci_root_hub.rh_ctrl_pipe_handle = ph;
329 
330 		/* Set state of the root hub control pipe as idle */
331 		ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_IDLE;
332 
333 		ehcip->ehci_root_hub.rh_curr_ctrl_reqp = NULL;
334 
335 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
336 		    "ehci_handle_root_hub_pipe_open: Root hub control "
337 		    "pipe open succeeded");
338 
339 		break;
340 	case USB_EP_ATTR_INTR:
341 		/* Save interrupt pipe handle */
342 		ehcip->ehci_root_hub.rh_intr_pipe_handle = ph;
343 
344 		/* Set state of the root hub interrupt pipe as idle */
345 		ehcip->ehci_root_hub.rh_intr_pipe_state = EHCI_PIPE_STATE_IDLE;
346 
347 		ehcip->ehci_root_hub.rh_client_intr_reqp = NULL;
348 
349 		ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL;
350 
351 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
352 		    "ehci_handle_root_hub_pipe_open: Root hub interrupt "
353 		    "pipe open succeeded");
354 
355 		break;
356 	default:
357 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
358 		    "ehci_handle_root_hub_pipe_open: Root hub pipe open"
359 		    "failed");
360 
361 		return (USB_FAILURE);
362 	}
363 
364 	ehcip->ehci_open_pipe_count++;
365 
366 	return (USB_SUCCESS);
367 }
368 
369 
370 /*
371  * ehci_handle_root_hub_pipe_close:
372  *
373  * Handle closing of control and interrupt pipes on root hub.
374  */
375 /* ARGSUSED */
376 int
377 ehci_handle_root_hub_pipe_close(usba_pipe_handle_data_t	*ph)
378 {
379 	ehci_state_t		*ehcip = ehci_obtain_state(
380 				    ph->p_usba_device->usb_root_hub_dip);
381 	usb_ep_descr_t		*eptd = &ph->p_ep;
382 
383 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
384 	    "ehci_handle_root_hub_pipe_close: Root hub pipe close");
385 
386 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
387 
388 	switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
389 	case USB_EP_ATTR_CONTROL:
390 		ASSERT(ehcip->ehci_root_hub.
391 		    rh_ctrl_pipe_state != EHCI_PIPE_STATE_CLOSE);
392 
393 		/* Set state of the root hub control pipe as close */
394 		ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_CLOSE;
395 
396 		/* Set root hub control pipe handle to null */
397 		ehcip->ehci_root_hub.rh_ctrl_pipe_handle = NULL;
398 
399 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
400 		    "ehci_handle_root_hub_pipe_close: "
401 		    "Root hub control pipe close succeeded");
402 		break;
403 	case USB_EP_ATTR_INTR:
404 		ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1);
405 
406 		ASSERT(ehcip->ehci_root_hub.
407 		    rh_intr_pipe_state != EHCI_PIPE_STATE_CLOSE);
408 
409 		/* Set state of the root hub interrupt pipe as close */
410 		ehcip->ehci_root_hub.rh_intr_pipe_state = EHCI_PIPE_STATE_CLOSE;
411 
412 		/* Do interrupt pipe cleanup */
413 		ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_PIPE_CLOSING);
414 
415 		/* Set root hub interrupt pipe handle to null */
416 		ehcip->ehci_root_hub.rh_intr_pipe_handle = NULL;
417 
418 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
419 		    "ehci_handle_root_hub_pipe_close: "
420 		    "Root hub interrupt pipe close succeeded");
421 
422 		break;
423 	default:
424 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
425 		    "ehci_handle_root_hub_pipe_close: "
426 		    "Root hub pipe close failed");
427 
428 		return (USB_FAILURE);
429 	}
430 
431 	ehcip->ehci_open_pipe_count--;
432 
433 	return (USB_SUCCESS);
434 }
435 
436 
437 /*
438  * ehci_handle_root_hub_pipe_reset:
439  *
440  * Handle resetting of control and interrupt pipes on root hub.
441  */
442 /* ARGSUSED */
443 int
444 ehci_handle_root_hub_pipe_reset(
445 	usba_pipe_handle_data_t	*ph,
446 	usb_flags_t		usb_flags)
447 {
448 	ehci_state_t		*ehcip = ehci_obtain_state(
449 				    ph->p_usba_device->usb_root_hub_dip);
450 	usb_ep_descr_t		*eptd = &ph->p_ep;
451 	int			error = USB_SUCCESS;
452 
453 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
454 	    "ehci_handle_root_hub_pipe_reset: Root hub pipe reset");
455 
456 	mutex_enter(&ehcip->ehci_int_mutex);
457 
458 	switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
459 	case USB_EP_ATTR_CONTROL:
460 		ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_IDLE;
461 
462 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
463 		    "ehci_handle_root_hub_pipe_reset: Pipe reset"
464 		    "for the root hub control pipe successful");
465 
466 		break;
467 	case USB_EP_ATTR_INTR:
468 		ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1);
469 
470 		if ((ehcip->ehci_root_hub.rh_client_intr_reqp) &&
471 		    (ehcip->ehci_root_hub.rh_intr_pipe_state !=
472 		    EHCI_PIPE_STATE_IDLE)) {
473 
474 			ehcip->ehci_root_hub.
475 			    rh_intr_pipe_state = EHCI_PIPE_STATE_RESET;
476 
477 			/* Do interrupt pipe cleanup */
478 			ehci_root_hub_intr_pipe_cleanup(
479 			    ehcip, USB_CR_PIPE_RESET);
480 		}
481 
482 		ASSERT(ehcip->ehci_root_hub.
483 		    rh_intr_pipe_state == EHCI_PIPE_STATE_IDLE);
484 
485 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
486 		    "ehci_handle_root_hub_pipe_reset: "
487 		    "Pipe reset for root hub interrupt pipe successful");
488 
489 		break;
490 	default:
491 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
492 		    "ehci_handle_root_hub_pipe_reset: "
493 		    "Root hub pipe reset failed");
494 
495 		error = USB_FAILURE;
496 		break;
497 	}
498 
499 	mutex_exit(&ehcip->ehci_int_mutex);
500 
501 	return (error);
502 }
503 
504 
505 /*
506  * ehci_handle_root_hub_request:
507  *
508  * Intercept a root hub request. Handle the  root hub request through the
509  * registers
510  */
511 /* ARGSUSED */
512 int
513 ehci_handle_root_hub_request(
514 	ehci_state_t		*ehcip,
515 	usba_pipe_handle_data_t	*ph,
516 	usb_ctrl_req_t		*ctrl_reqp)
517 {
518 	uchar_t			bmRequestType = ctrl_reqp->ctrl_bmRequestType;
519 	uchar_t			bRequest = ctrl_reqp->ctrl_bRequest;
520 	uint16_t		wValue = ctrl_reqp->ctrl_wValue;
521 	uint16_t		wIndex = ctrl_reqp->ctrl_wIndex;
522 	uint16_t		wLength = ctrl_reqp->ctrl_wLength;
523 	mblk_t			*data = ctrl_reqp->ctrl_data;
524 	uint16_t		port = wIndex - 1;
525 	usb_cr_t		completion_reason;
526 	int			error = USB_SUCCESS;
527 
528 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
529 	    "ehci_handle_root_hub_request: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%p",
530 	    bmRequestType, bRequest, wValue, wIndex, wLength, (void *)data);
531 
532 	mutex_enter(&ehcip->ehci_int_mutex);
533 
534 	if (ehcip->ehci_root_hub.
535 	    rh_ctrl_pipe_state != EHCI_PIPE_STATE_IDLE) {
536 
537 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
538 		    "ehci_handle_root_hub_request: Pipe is not idle");
539 
540 		mutex_exit(&ehcip->ehci_int_mutex);
541 
542 		return (USB_FAILURE);
543 	}
544 
545 	/* Save the current control request pointer */
546 	ehcip->ehci_root_hub.rh_curr_ctrl_reqp = ctrl_reqp;
547 
548 	/* Set pipe state to active */
549 	ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_ACTIVE;
550 
551 	mutex_exit(&ehcip->ehci_int_mutex);
552 
553 	switch (bmRequestType) {
554 	case HUB_GET_DEVICE_STATUS_TYPE:
555 		ehci_handle_get_device_status(ehcip);
556 		break;
557 	case HUB_HANDLE_PORT_FEATURE_TYPE:
558 		error = ehci_handle_set_clear_port_feature(ehcip,
559 		    bRequest, wValue, port);
560 		break;
561 	case HUB_GET_PORT_STATUS_TYPE:
562 		ehci_handle_get_port_status(ehcip, port);
563 		break;
564 	case HUB_CLASS_REQ_TYPE:
565 		switch (bRequest) {
566 		case USB_REQ_GET_STATUS:
567 			ehci_handle_get_hub_status(ehcip);
568 			break;
569 		case USB_REQ_GET_DESCR:
570 			ehci_handle_get_hub_descriptor(ehcip);
571 			break;
572 		default:
573 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
574 			    "ehci_handle_root_hub_request:"
575 			    "Unsupported request 0x%x", bRequest);
576 
577 			error = USB_FAILURE;
578 			break;
579 		}
580 		break;
581 	default:
582 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
583 		    "ehci_handle_root_hub_request: "
584 		    "Unsupported request 0x%x", bmRequestType);
585 
586 		error = USB_FAILURE;
587 		break;
588 	}
589 
590 	completion_reason = (error) ? USB_CR_NOT_SUPPORTED : USB_CR_OK;
591 
592 	mutex_enter(&ehcip->ehci_int_mutex);
593 	ehci_root_hub_hcdi_callback(ph, completion_reason);
594 	mutex_exit(&ehcip->ehci_int_mutex);
595 
596 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
597 	    "ehci_handle_root_hub_request: error = %d", error);
598 
599 	return (USB_SUCCESS);
600 }
601 
602 
603 /*
604  * ehci_handle_set_clear_port_feature:
605  */
606 static int
607 ehci_handle_set_clear_port_feature(
608 	ehci_state_t		*ehcip,
609 	uchar_t 		bRequest,
610 	uint16_t		wValue,
611 	uint16_t		port)
612 {
613 	int			error = USB_SUCCESS;
614 
615 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
616 	    "ehci_handle_set_clear_port_feature: 0x%x 0x%x 0x%x",
617 	    bRequest, wValue, port);
618 
619 	switch (bRequest) {
620 	case USB_REQ_SET_FEATURE:
621 		switch (wValue) {
622 		case CFS_PORT_ENABLE:
623 			ehci_handle_port_enable(ehcip, port, 1);
624 			break;
625 		case CFS_PORT_SUSPEND:
626 			ehci_handle_port_suspend(ehcip, port, 1);
627 			break;
628 		case CFS_PORT_RESET:
629 			ehci_handle_port_reset(ehcip, port);
630 			break;
631 		case CFS_PORT_POWER:
632 			ehci_handle_port_power(ehcip, port, 1);
633 			break;
634 		default:
635 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
636 			    "ehci_handle_set_clear_port_feature: "
637 			    "Unsupported request 0x%x 0x%x", bRequest, wValue);
638 
639 			error = USB_FAILURE;
640 			break;
641 		}
642 		break;
643 	case USB_REQ_CLEAR_FEATURE:
644 		switch (wValue) {
645 		case CFS_PORT_ENABLE:
646 			ehci_handle_port_enable(ehcip, port, 0);
647 			break;
648 		case CFS_C_PORT_ENABLE:
649 			ehci_handle_clrchng_port_enable(ehcip, port);
650 			break;
651 		case CFS_PORT_SUSPEND:
652 			ehci_handle_port_suspend(ehcip, port, 0);
653 			break;
654 		case CFS_C_PORT_SUSPEND:
655 			ehci_handle_clrchng_port_suspend(ehcip, port);
656 			break;
657 		case CFS_C_PORT_RESET:
658 			ehci_handle_complete_port_reset(ehcip, port);
659 			break;
660 		case CFS_PORT_POWER:
661 			ehci_handle_port_power(ehcip, port, 0);
662 			break;
663 		case CFS_C_PORT_CONNECTION:
664 			ehci_handle_clear_port_connection(ehcip, port);
665 			break;
666 		case CFS_C_PORT_OVER_CURRENT:
667 			ehci_handle_clrchng_port_over_current(ehcip, port);
668 			break;
669 		default:
670 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
671 			    "ehci_handle_set_clear_port_feature: "
672 			    "Unsupported request 0x%x 0x%x", bRequest, wValue);
673 
674 			error = USB_FAILURE;
675 			break;
676 		}
677 		    break;
678 	default:
679 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
680 		    "ehci_handle_set_clear_port_feature: "
681 		    "Unsupported request 0x%x 0x%x", bRequest, wValue);
682 
683 		error = USB_FAILURE;
684 		break;
685 	}
686 
687 	return (error);
688 }
689 
690 
691 /*
692  * ehci_handle_port_power:
693  *
694  * Turn on a root hub port.
695  */
696 static void
697 ehci_handle_port_power(
698 	ehci_state_t		*ehcip,
699 	uint16_t		port,
700 	uint_t			on)
701 {
702 	uint_t			port_status;
703 	ehci_root_hub_t		*rh;
704 
705 	mutex_enter(&ehcip->ehci_int_mutex);
706 
707 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
708 	    ~EHCI_RH_PORT_CLEAR_MASK;
709 
710 	rh = &ehcip->ehci_root_hub;
711 
712 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
713 	    "ehci_handle_port_power: port = 0x%x status = 0x%x on = %d",
714 	    port, port_status, on);
715 
716 	/* Check port is owned by ehci */
717 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
718 		mutex_exit(&ehcip->ehci_int_mutex);
719 
720 		return;
721 	}
722 
723 	if (on) {
724 		/* See if the port power is already on */
725 		if (!(port_status & EHCI_RH_PORT_POWER)) {
726 			/* Turn the port on */
727 			Set_OpReg(ehci_rh_port_status[port],
728 			    port_status | EHCI_RH_PORT_POWER);
729 		}
730 
731 		rh->rh_port_status[port] = 0;
732 		rh->rh_port_state[port] = DISCONNECTED;
733 	} else {
734 		/* See if the port power is already OFF */
735 		if (port_status & EHCI_RH_PORT_POWER) {
736 			/* Turn-off the port */
737 			Set_OpReg(ehci_rh_port_status[port],
738 			    port_status & ~EHCI_RH_PORT_POWER);
739 		}
740 
741 		rh->rh_port_status[port] = 0;
742 		rh->rh_port_state[port] = POWERED_OFF;
743 	}
744 
745 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
746 	    "ehci_handle_port_power done: port = 0x%x status = 0x%x on = %d",
747 	    port, Get_OpReg(ehci_rh_port_status[port]), on);
748 
749 	mutex_exit(&ehcip->ehci_int_mutex);
750 }
751 
752 
753 /*
754  * ehci_handle_port_enable:
755  *
756  * Handle port enable request.
757  */
758 static void
759 ehci_handle_port_enable(
760 	ehci_state_t		*ehcip,
761 	uint16_t		port,
762 	uint_t			on)
763 {
764 	uint_t			port_status;
765 
766 	mutex_enter(&ehcip->ehci_int_mutex);
767 
768 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
769 	    ~EHCI_RH_PORT_CLEAR_MASK;
770 
771 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
772 	    "ehci_handle_port_enable: port = 0x%x, status = 0x%x",
773 	    port, port_status);
774 
775 	/* Check port is owned by ehci */
776 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
777 		mutex_exit(&ehcip->ehci_int_mutex);
778 
779 		return;
780 	}
781 
782 	if (on) {
783 		/* See if the port enable is already on */
784 		if (!(port_status & EHCI_RH_PORT_ENABLE)) {
785 			/* Enable the port */
786 			Set_OpReg(ehci_rh_port_status[port],
787 			    port_status | EHCI_RH_PORT_ENABLE);
788 		}
789 	} else {
790 		/* See if the port enable is already off */
791 		if (port_status & EHCI_RH_PORT_ENABLE) {
792 			/* Disable the port */
793 			Set_OpReg(ehci_rh_port_status[port],
794 			    port_status & ~EHCI_RH_PORT_ENABLE);
795 		}
796 	}
797 
798 	mutex_exit(&ehcip->ehci_int_mutex);
799 }
800 
801 
802 /*
803  * ehci_handle_clrchng_port_enable:
804  *
805  * Handle clear port enable change bit.
806  */
807 static void
808 ehci_handle_clrchng_port_enable(
809 	ehci_state_t		*ehcip,
810 	uint16_t		port)
811 {
812 	uint_t			port_status;
813 
814 	mutex_enter(&ehcip->ehci_int_mutex);
815 
816 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
817 	    ~EHCI_RH_PORT_CLEAR_MASK;
818 
819 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
820 	    "ehci_handle_port_enable: port = 0x%x, status = 0x%x",
821 	    port, port_status);
822 
823 	/* Check port is owned by ehci */
824 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
825 		mutex_exit(&ehcip->ehci_int_mutex);
826 
827 		return;
828 	}
829 
830 	/* Clear the PortEnableStatusChange Bit */
831 	Set_OpReg(ehci_rh_port_status[port],
832 	    port_status | EHCI_RH_PORT_ENABLE_CHANGE);
833 
834 	mutex_exit(&ehcip->ehci_int_mutex);
835 }
836 
837 
838 /*
839  * ehci_handle_port_suspend:
840  *
841  * Handle port suspend/resume request.
842  */
843 static void
844 ehci_handle_port_suspend(
845 	ehci_state_t		*ehcip,
846 	uint16_t		port,
847 	uint_t			on)
848 {
849 	uint_t			port_status;
850 
851 	mutex_enter(&ehcip->ehci_int_mutex);
852 
853 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
854 	    ~EHCI_RH_PORT_CLEAR_MASK;
855 
856 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
857 	    "ehci_handle_port_suspend: port = 0x%x, status = 0x%x",
858 	    port, port_status);
859 
860 	/* Check port is owned by ehci */
861 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
862 		mutex_exit(&ehcip->ehci_int_mutex);
863 
864 		return;
865 	}
866 
867 	if (on) {
868 		/*
869 		 * Suspend port only if port is enabled and
870 		 * it is not already in suspend state.
871 		 */
872 		if ((port_status & EHCI_RH_PORT_ENABLE) &&
873 		    (!(port_status & EHCI_RH_PORT_SUSPEND))) {
874 			/* Suspend the port */
875 			Set_OpReg(ehci_rh_port_status[port],
876 			    port_status | EHCI_RH_PORT_SUSPEND);
877 
878 			mutex_exit(&ehcip->ehci_int_mutex);
879 
880 			/* Wait 10ms for port move to suspend state */
881 			delay(drv_usectohz(EHCI_PORT_SUSPEND_TIMEWAIT));
882 
883 			return;
884 		}
885 	} else {
886 		/* Perform resume only if port is in suspend state */
887 		if (port_status & EHCI_RH_PORT_SUSPEND) {
888 			/* Resume the port */
889 			Set_OpReg(ehci_rh_port_status[port],
890 			    port_status | EHCI_RH_PORT_RESUME);
891 		}
892 	}
893 
894 	mutex_exit(&ehcip->ehci_int_mutex);
895 }
896 
897 
898 /*
899  * ehci_handle_clrchng_port_suspend:
900  *
901  * Handle port clear port suspend change bit.
902  */
903 static void
904 ehci_handle_clrchng_port_suspend(
905 	ehci_state_t		*ehcip,
906 	uint16_t		port)
907 {
908 	uint_t			port_status;
909 
910 	mutex_enter(&ehcip->ehci_int_mutex);
911 
912 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
913 	    ~EHCI_RH_PORT_CLEAR_MASK;
914 
915 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
916 	    "ehci_handle_clrchng_port_suspend: port = 0x%x, "
917 	    "status = 0x%x", port, port_status);
918 
919 	/* Check port is owned by ehci */
920 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
921 		mutex_exit(&ehcip->ehci_int_mutex);
922 
923 		return;
924 	}
925 
926 	/* Return if port is not in resume state */
927 	if (!(port_status & EHCI_RH_PORT_RESUME)) {
928 		mutex_exit(&ehcip->ehci_int_mutex);
929 
930 		return;
931 	}
932 
933 	mutex_exit(&ehcip->ehci_int_mutex);
934 
935 	/* Wait for 20ms to terminate resume */
936 	delay(drv_usectohz(EHCI_PORT_RESUME_TIMEWAIT));
937 
938 	mutex_enter(&ehcip->ehci_int_mutex);
939 
940 	Set_OpReg(ehci_rh_port_status[port],
941 	    port_status & ~EHCI_RH_PORT_RESUME);
942 
943 	mutex_exit(&ehcip->ehci_int_mutex);
944 
945 	/* Wait 2ms for port to return to high speed mode */
946 	delay(drv_usectohz(EHCI_PORT_RESUME_COMP_TIMEWAIT));
947 }
948 
949 
950 /*
951  * ehci_handle_port_reset:
952  *
953  * Perform a port reset.
954  */
955 static void
956 ehci_handle_port_reset(
957 	ehci_state_t		*ehcip,
958 	uint16_t		port)
959 {
960 	ehci_root_hub_t		*rh;
961 	uint_t			port_status;
962 
963 	mutex_enter(&ehcip->ehci_int_mutex);
964 
965 	/* Get the root hub structure */
966 	rh = &ehcip->ehci_root_hub;
967 
968 	/* Get the port status information */
969 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
970 	    ~EHCI_RH_PORT_CLEAR_MASK;
971 
972 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
973 	    "ehci_handle_port_reset: port = 0x%x status = 0x%x",
974 	    port, port_status);
975 
976 	/* Check port is owned by ehci */
977 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
978 		mutex_exit(&ehcip->ehci_int_mutex);
979 
980 		return;
981 	}
982 
983 	if (port_status & EHCI_RH_PORT_LOW_SPEED) {
984 		/* Check for classic or companion host controllers */
985 		if (rh->rh_companion_controllers) {
986 			USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
987 			    "ehci_handle_port_reset: Low speed device "
988 			    "and handover this port to Companion controller");
989 
990 			Set_OpReg(ehci_rh_port_status[port],
991 			    port_status | EHCI_RH_PORT_OWNER_CLASSIC);
992 		} else {
993 			USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
994 			    "Low speed device is not supported");
995 		}
996 	} else {
997 		Set_OpReg(ehci_rh_port_status[port],
998 		    ((port_status | EHCI_RH_PORT_RESET) &
999 		    ~EHCI_RH_PORT_ENABLE));
1000 
1001 		mutex_exit(&ehcip->ehci_int_mutex);
1002 
1003 		/* Wait 10ms for reset to complete */
1004 		delay(drv_usectohz(EHCI_PORT_RESET_TIMEWAIT));
1005 
1006 		mutex_enter(&ehcip->ehci_int_mutex);
1007 
1008 		port_status = Get_OpReg(ehci_rh_port_status[port]) &
1009 		    ~EHCI_RH_PORT_CLEAR_MASK;
1010 
1011 		Set_OpReg(ehci_rh_port_status[port],
1012 		    (port_status & ~EHCI_RH_PORT_RESET));
1013 
1014 		mutex_exit(&ehcip->ehci_int_mutex);
1015 
1016 		/*
1017 		 * Wait 2ms for hardware to enable this port
1018 		 * if connected usb device is high speed.
1019 		 */
1020 		delay(drv_usectohz(EHCI_PORT_RESET_COMP_TIMEWAIT));
1021 
1022 		mutex_enter(&ehcip->ehci_int_mutex);
1023 
1024 		port_status = Get_OpReg(ehci_rh_port_status[port]) &
1025 		    ~EHCI_RH_PORT_CLEAR_MASK;
1026 
1027 		/*
1028 		 * If port is not enabled, connected device is a
1029 		 * Full-speed usb device.
1030 		 */
1031 		if (!(port_status & EHCI_RH_PORT_ENABLE)) {
1032 			/* Check for classic or companion host controllers */
1033 			if (rh->rh_companion_controllers) {
1034 				USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1035 				    ehcip->ehci_log_hdl,
1036 				    "ehci_handle_port_reset: Full speed device "
1037 				    "and handover this port to Companion host "
1038 				    "controller");
1039 
1040 				Set_OpReg(ehci_rh_port_status[port],
1041 				    port_status | EHCI_RH_PORT_OWNER_CLASSIC);
1042 			} else {
1043 				USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB,
1044 				    ehcip->ehci_log_hdl,
1045 				    "Full speed device is not supported");
1046 			}
1047 		} else {
1048 			USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1049 			    "ehci_handle_port_reset: High speed device ");
1050 
1051 			port_status = Get_OpReg(ehci_rh_port_status[port]) &
1052 			    ~EHCI_RH_PORT_CLEAR_MASK;
1053 
1054 			/*
1055 			 * Enable over-current, connect, and disconnect
1056 			 * wakeup bits.
1057 			 */
1058 			Set_OpReg(ehci_rh_port_status[port], (port_status |
1059 			    EHCI_RH_PORT_OVER_CURENT_ENABLE |
1060 			    EHCI_RH_PORT_DISCONNECT_ENABLE |
1061 			    EHCI_RH_PORT_CONNECT_ENABLE));
1062 
1063 			/*
1064 			 * The next function is only called if the interrupt
1065 			 * pipe is polling and the USBA is ready to receive
1066 			 * the data.
1067 			 */
1068 			ehcip->ehci_root_hub.
1069 			    rh_intr_pending_status |= (1 << port);
1070 
1071 			if (ehcip->ehci_root_hub.
1072 			    rh_intr_pipe_state == EHCI_PIPE_STATE_ACTIVE) {
1073 
1074 				ehci_root_hub_reset_occured(ehcip);
1075 			}
1076 		}
1077 	}
1078 
1079 	mutex_exit(&ehcip->ehci_int_mutex);
1080 }
1081 
1082 
1083 /*
1084  * ehci_root_hub_reset_occured:
1085  *
1086  * Inform the upper layer that reset has occured on the port. This is
1087  * required because the upper layer is expecting a an evernt immidiately
1088  * after doing reset. In case of OHCI, the controller gets an interrupt
1089  * for the change in the root hub status but in case of EHCI, we dont.
1090  * So, send a event to the upper layer as soon as we complete the reset.
1091  */
1092 void
1093 ehci_root_hub_reset_occured(
1094 	ehci_state_t		*ehcip)
1095 {
1096 	usb_intr_req_t		*curr_intr_reqp =
1097 				    ehcip->ehci_root_hub.rh_curr_intr_reqp;
1098 	usb_port_mask_t		port_mask;
1099 	usba_pipe_handle_data_t	*ph;
1100 
1101 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1102 	    "ehci_root_hub_reset_occured: curr_intr_reqp = 0x%p data = 0x%p",
1103 	    curr_intr_reqp, curr_intr_reqp->intr_data);
1104 
1105 	/* Get the interrupt pipe handle */
1106 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1107 
1108 	/* Get the pending status */
1109 	port_mask = ehcip->ehci_root_hub.rh_intr_pending_status << 1;
1110 
1111 	do {
1112 		*curr_intr_reqp->intr_data->b_wptr++ = (uchar_t)port_mask;
1113 		port_mask >>= 8;
1114 	} while (port_mask != 0);
1115 
1116 	ehci_root_hub_hcdi_callback(ph, USB_CR_OK);
1117 
1118 	/* Reset pending status */
1119 	ehcip->ehci_root_hub.rh_intr_pending_status = 0;
1120 
1121 	/* If needed, allocate new interrupt request */
1122 	if ((ehci_root_hub_allocate_intr_pipe_resource(
1123 	    ehcip, 0)) != USB_SUCCESS) {
1124 
1125 		/* Do interrupt pipe cleanup */
1126 		ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_NO_RESOURCES);
1127 	}
1128 }
1129 
1130 
1131 /*
1132  * ehci_handle_complete_port_reset:
1133  *
1134  * Perform a port reset change.
1135  */
1136 static void
1137 ehci_handle_complete_port_reset(
1138 	ehci_state_t		*ehcip,
1139 	uint16_t		port)
1140 {
1141 	uint_t			port_status;
1142 
1143 	mutex_enter(&ehcip->ehci_int_mutex);
1144 
1145 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1146 	    ~EHCI_RH_PORT_CLEAR_MASK;
1147 
1148 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1149 	    "ehci_handle_complete_port_reset: port = 0x%x status = 0x%x",
1150 	    port, port_status);
1151 
1152 	/* Check port is owned by ehci */
1153 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
1154 		mutex_exit(&ehcip->ehci_int_mutex);
1155 
1156 		return;
1157 	}
1158 
1159 	if (port_status & EHCI_RH_PORT_RESET) {
1160 		Set_OpReg(ehci_rh_port_status[port],
1161 		    port_status & ~EHCI_RH_PORT_RESET);
1162 
1163 	}
1164 
1165 	mutex_exit(&ehcip->ehci_int_mutex);
1166 }
1167 
1168 
1169 /*
1170  * ehci_handle_clear_port_connection:
1171  *
1172  * Perform a clear port connection.
1173  */
1174 static void
1175 ehci_handle_clear_port_connection(
1176 	ehci_state_t		*ehcip,
1177 	uint16_t		port)
1178 {
1179 	uint_t			port_status;
1180 
1181 	mutex_enter(&ehcip->ehci_int_mutex);
1182 
1183 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1184 	    ~EHCI_RH_PORT_CLEAR_MASK;
1185 
1186 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1187 	    "ehci_handle_clear_port_connection: port = 0x%x"
1188 	    "status = 0x%x", port, port_status);
1189 
1190 	Set_OpReg(ehci_rh_port_status[port],
1191 	    port_status | EHCI_RH_PORT_CONNECT_STS_CHANGE);
1192 
1193 	mutex_exit(&ehcip->ehci_int_mutex);
1194 }
1195 
1196 
1197 /*
1198  * ehci_handle_clrchng_port_over_current:
1199  *
1200  * Perform a clear port connection.
1201  */
1202 static void
1203 ehci_handle_clrchng_port_over_current(
1204 	ehci_state_t		*ehcip,
1205 	uint16_t		port)
1206 {
1207 	uint_t			port_status;
1208 
1209 	mutex_enter(&ehcip->ehci_int_mutex);
1210 
1211 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1212 	    ~EHCI_RH_PORT_CLEAR_MASK;
1213 
1214 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1215 	    "ehci_handle_clrchng_port_over_current: port = 0x%x"
1216 	    "status = 0x%x", port, port_status);
1217 
1218 	Set_OpReg(ehci_rh_port_status[port],
1219 	    port_status | EHCI_RH_PORT_OVER_CURR_CHANGE);
1220 
1221 	mutex_exit(&ehcip->ehci_int_mutex);
1222 }
1223 
1224 
1225 /*
1226  * ehci_handle_get_port_status:
1227  *
1228  * Handle a get port status request.
1229  */
1230 static void
1231 ehci_handle_get_port_status(
1232 	ehci_state_t		*ehcip,
1233 	uint16_t		port)
1234 {
1235 	usb_ctrl_req_t		*ctrl_reqp;
1236 	mblk_t			*message;
1237 	uint_t			new_port_status = 0;
1238 	uint_t			change_status = 0;
1239 	uint_t			port_status;
1240 
1241 	mutex_enter(&ehcip->ehci_int_mutex);
1242 
1243 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1244 
1245 	/* Get the root hub port status information */
1246 	port_status = ehci_get_root_hub_port_status(ehcip, port);
1247 
1248 	new_port_status = port_status & PORT_STATUS_MASK;
1249 	change_status = (port_status >> 16) & PORT_CHANGE_MASK;
1250 
1251 	ehcip->ehci_root_hub.rh_port_status[port] = new_port_status;
1252 
1253 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1254 	    "ehci_handle_get_port_status: port = %d new status = 0x%x"
1255 	    "change = 0x%x", port, new_port_status, change_status);
1256 
1257 	message = ctrl_reqp->ctrl_data;
1258 
1259 	ASSERT(message != NULL);
1260 
1261 	*message->b_wptr++ = (uchar_t)new_port_status;
1262 	*message->b_wptr++ = (uchar_t)(new_port_status >> 8);
1263 	*message->b_wptr++ = (uchar_t)change_status;
1264 	*message->b_wptr++ = (uchar_t)(change_status >> 8);
1265 
1266 	/* Save the data in control request */
1267 	ctrl_reqp->ctrl_data = message;
1268 
1269 	mutex_exit(&ehcip->ehci_int_mutex);
1270 }
1271 
1272 
1273 /*
1274  * ehci_handle_get_hub_descriptor:
1275  */
1276 static void
1277 ehci_handle_get_hub_descriptor(
1278 	ehci_state_t		*ehcip)
1279 {
1280 	usb_ctrl_req_t		*ctrl_reqp;
1281 	mblk_t			*message;
1282 	usb_hub_descr_t		*root_hub_descr;
1283 	size_t			length;
1284 	uchar_t			raw_descr[ROOT_HUB_DESCRIPTOR_LENGTH];
1285 
1286 	mutex_enter(&ehcip->ehci_int_mutex);
1287 
1288 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1289 	root_hub_descr = &ehcip->ehci_root_hub.rh_descr;
1290 	length = ctrl_reqp->ctrl_wLength;
1291 
1292 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1293 	    "ehci_handle_get_hub_descriptor: Ctrl Req  = 0x%p", ctrl_reqp);
1294 
1295 	message = ctrl_reqp->ctrl_data;
1296 
1297 	ASSERT(message != NULL);
1298 
1299 	bzero(&raw_descr, ROOT_HUB_DESCRIPTOR_LENGTH);
1300 
1301 	raw_descr[0] = root_hub_descr->bDescLength;
1302 	raw_descr[1] = root_hub_descr->bDescriptorType;
1303 	raw_descr[2] = root_hub_descr->bNbrPorts;
1304 	raw_descr[3] = root_hub_descr->wHubCharacteristics & 0x00FF;
1305 	raw_descr[4] = (root_hub_descr->wHubCharacteristics & 0xFF00) >> 8;
1306 	raw_descr[5] = root_hub_descr->bPwrOn2PwrGood;
1307 	raw_descr[6] = root_hub_descr->bHubContrCurrent;
1308 	raw_descr[7] = root_hub_descr->DeviceRemovable;
1309 	raw_descr[8] = root_hub_descr->PortPwrCtrlMask;
1310 
1311 	bcopy(raw_descr, message->b_wptr, length);
1312 	message->b_wptr += length;
1313 
1314 	/* Save the data in control request */
1315 	ctrl_reqp->ctrl_data = message;
1316 
1317 	mutex_exit(&ehcip->ehci_int_mutex);
1318 }
1319 
1320 
1321 /*
1322  * ehci_handle_get_hub_status:
1323  *
1324  * Handle a get hub status request.
1325  */
1326 static void
1327 ehci_handle_get_hub_status(
1328 	ehci_state_t		*ehcip)
1329 {
1330 	usb_ctrl_req_t		*ctrl_reqp;
1331 	mblk_t			*message;
1332 	uint_t			new_root_hub_status;
1333 
1334 	mutex_enter(&ehcip->ehci_int_mutex);
1335 
1336 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1337 
1338 	/*
1339 	 * For EHCI, there is no overall hub status information.
1340 	 * Only individual root hub port status information is
1341 	 * available. So return zero for the root hub status
1342 	 * request.
1343 	 */
1344 	new_root_hub_status = 0;
1345 
1346 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1347 	    "ehci_handle_get_hub_status: new root hub status = 0x%x",
1348 	    new_root_hub_status);
1349 
1350 	message = ctrl_reqp->ctrl_data;
1351 
1352 	ASSERT(message != NULL);
1353 
1354 	*message->b_wptr++ = (uchar_t)new_root_hub_status;
1355 	*message->b_wptr++ = (uchar_t)(new_root_hub_status >> 8);
1356 	*message->b_wptr++ = (uchar_t)(new_root_hub_status >> 16);
1357 	*message->b_wptr++ = (uchar_t)(new_root_hub_status >> 24);
1358 
1359 	/* Save the data in control request */
1360 	ctrl_reqp->ctrl_data = message;
1361 
1362 	mutex_exit(&ehcip->ehci_int_mutex);
1363 }
1364 
1365 
1366 /*
1367  * ehci_handle_get_device_status:
1368  *
1369  * Handle a get device status request.
1370  */
1371 static void
1372 ehci_handle_get_device_status(
1373 	ehci_state_t		*ehcip)
1374 {
1375 	usb_ctrl_req_t		*ctrl_reqp;
1376 	mblk_t			*message;
1377 	uint16_t		dev_status;
1378 
1379 	mutex_enter(&ehcip->ehci_int_mutex);
1380 
1381 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1382 
1383 	/*
1384 	 * For EHCI, there is no device status information.
1385 	 * Simply return what is desired for the request.
1386 	 */
1387 	dev_status = USB_DEV_SLF_PWRD_STATUS;
1388 
1389 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1390 	    "ehci_handle_get_device_status: device status = 0x%x",
1391 	    dev_status);
1392 
1393 	message = ctrl_reqp->ctrl_data;
1394 
1395 	ASSERT(message != NULL);
1396 
1397 	*message->b_wptr++ = (uchar_t)dev_status;
1398 	*message->b_wptr++ = (uchar_t)(dev_status >> 8);
1399 
1400 	/* Save the data in control request */
1401 	ctrl_reqp->ctrl_data = message;
1402 
1403 	mutex_exit(&ehcip->ehci_int_mutex);
1404 }
1405 
1406 
1407 /*
1408  * ehci_handle_root_hub_pipe_start_intr_polling:
1409  *
1410  * Handle start polling on root hub interrupt pipe.
1411  */
1412 /* ARGSUSED */
1413 int
1414 ehci_handle_root_hub_pipe_start_intr_polling(
1415 	usba_pipe_handle_data_t	*ph,
1416 	usb_intr_req_t		*client_intr_reqp,
1417 	usb_flags_t		flags)
1418 {
1419 	ehci_state_t		*ehcip = ehci_obtain_state(
1420 				    ph->p_usba_device->usb_root_hub_dip);
1421 	usb_ep_descr_t		*eptd = &ph->p_ep;
1422 	int			error = USB_SUCCESS;
1423 	uint_t			pipe_state;
1424 
1425 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1426 	    "ehci_handle_root_hub_pipe_start_intr_polling: "
1427 	    "Root hub pipe start polling");
1428 
1429 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1430 
1431 	ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1);
1432 
1433 	ASSERT((client_intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) == 0);
1434 
1435 	pipe_state = ehcip->ehci_root_hub.rh_intr_pipe_state;
1436 
1437 	switch (pipe_state) {
1438 	case EHCI_PIPE_STATE_IDLE:
1439 		ASSERT(ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0);
1440 
1441 		/*
1442 		 * Save the Original Client's Interrupt IN request
1443 		 * information. We use this for final callback
1444 		 */
1445 		ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp == NULL);
1446 		ehcip->ehci_root_hub.rh_client_intr_reqp = client_intr_reqp;
1447 
1448 		error = ehci_root_hub_allocate_intr_pipe_resource(ehcip, flags);
1449 
1450 		if (error != USB_SUCCESS) {
1451 			/* Reset client interrupt request pointer */
1452 			ehcip->ehci_root_hub.rh_client_intr_reqp = NULL;
1453 
1454 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1455 			    "ehci_handle_root_hub_pipe_start_intr_polling: "
1456 			    "No Resources");
1457 
1458 			return (error);
1459 		}
1460 
1461 		/* Check whether we need to send the reset data up */
1462 		if (ehcip->ehci_root_hub.rh_intr_pending_status) {
1463 			ehci_root_hub_reset_occured(ehcip);
1464 		}
1465 
1466 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1467 		    "ehci_handle_root_hub_pipe_start_intr_polling: "
1468 		    "Start polling for root hub successful");
1469 
1470 		break;
1471 	case EHCI_PIPE_STATE_ACTIVE:
1472 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1473 		    "ehci_handle_root_hub_pipe_start_intr_polling: "
1474 		    "Polling for root hub is already in progress");
1475 
1476 		break;
1477 	default:
1478 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1479 		    "ehci_handle_root_hub_pipe_start_intr_polling: "
1480 		    "Pipe is in error state 0x%x", pipe_state);
1481 
1482 		error = USB_FAILURE;
1483 
1484 		break;
1485 	}
1486 
1487 	return (error);
1488 }
1489 
1490 
1491 /*
1492  * ehci_handle_root_hub_pipe_stop_intr_polling:
1493  *
1494  * Handle stop polling on root hub intr pipe.
1495  */
1496 /* ARGSUSED */
1497 void
1498 ehci_handle_root_hub_pipe_stop_intr_polling(
1499 	usba_pipe_handle_data_t	*ph,
1500 	usb_flags_t		flags)
1501 {
1502 	ehci_state_t		*ehcip = ehci_obtain_state(
1503 				    ph->p_usba_device->usb_root_hub_dip);
1504 	usb_ep_descr_t		*eptd = &ph->p_ep;
1505 
1506 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1507 
1508 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1509 	    "ehci_handle_root_hub_pipe_stop_intr_polling: "
1510 	    "Root hub pipe stop polling");
1511 
1512 	ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1);
1513 
1514 	if (ehcip->ehci_root_hub.rh_intr_pipe_state ==
1515 	    EHCI_PIPE_STATE_ACTIVE) {
1516 
1517 		ehcip->ehci_root_hub.rh_intr_pipe_state =
1518 		    EHCI_PIPE_STATE_STOP_POLLING;
1519 
1520 		/* Do interrupt pipe cleanup */
1521 		ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_STOPPED_POLLING);
1522 
1523 		ASSERT(ehcip->ehci_root_hub.
1524 		    rh_intr_pipe_state == EHCI_PIPE_STATE_IDLE);
1525 
1526 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1527 		    "ehci_hcdi_pipe_stop_intr_polling: Stop polling for root"
1528 		    "hub successful");
1529 	} else {
1530 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB,
1531 		    ehcip->ehci_log_hdl, "ehci_hcdi_pipe_stop_intr_polling: "
1532 		    "Polling for root hub is already stopped");
1533 	}
1534 }
1535 
1536 
1537 /*
1538  * ehci_get_root_hub_port_status:
1539  *
1540  * Construct root hub port status and change information
1541  */
1542 static uint_t
1543 ehci_get_root_hub_port_status(
1544 	ehci_state_t		*ehcip,
1545 	uint16_t		port)
1546 {
1547 	uint_t			new_port_status = 0;
1548 	uint_t			change_status = 0;
1549 	uint_t			port_status;
1550 
1551 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1552 
1553 	/* Read the current port status */
1554 	port_status = Get_OpReg(ehci_rh_port_status[port]);
1555 
1556 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1557 	    "ehci_get_root_hub_port_status: port %d "
1558 	    "port status = 0x%x", port, port_status);
1559 
1560 	/*
1561 	 * EHCI root hub port status and control register information
1562 	 * format is different what Hub driver wants. So EHCI driver
1563 	 * needs to contruct the proper root hub port status information.
1564 	 *
1565 	 * Send all port status information only if port is owned by EHCI
1566 	 * host controller.
1567 	 */
1568 	if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_EHCI) {
1569 
1570 		/* First construct port change information */
1571 		if (port_status & EHCI_RH_PORT_ENABLE_CHANGE) {
1572 			change_status |= PORT_CHANGE_PESC;
1573 		}
1574 
1575 		if (port_status & EHCI_RH_PORT_RESUME) {
1576 			change_status |= PORT_CHANGE_PSSC;
1577 		}
1578 
1579 		if (port_status & EHCI_RH_PORT_OVER_CURR_CHANGE) {
1580 			change_status |= PORT_CHANGE_OCIC;
1581 		}
1582 
1583 		/* Now construct port status information */
1584 		if (port_status & EHCI_RH_PORT_CONNECT_STATUS) {
1585 			new_port_status |= PORT_STATUS_CCS;
1586 		}
1587 
1588 		if (port_status & EHCI_RH_PORT_ENABLE) {
1589 			new_port_status |=
1590 			    (PORT_STATUS_PES | PORT_STATUS_HSDA);
1591 		}
1592 
1593 		if (port_status & EHCI_RH_PORT_SUSPEND) {
1594 			new_port_status |= PORT_STATUS_PSS;
1595 		}
1596 
1597 		if (port_status & EHCI_RH_PORT_OVER_CURR_ACTIVE) {
1598 			new_port_status |= PORT_STATUS_POCI;
1599 		}
1600 
1601 		if (port_status & EHCI_RH_PORT_RESET) {
1602 			new_port_status |= PORT_STATUS_PRS;
1603 		}
1604 
1605 		if (port_status & EHCI_RH_PORT_INDICATOR) {
1606 			new_port_status |= PORT_STATUS_PIC;
1607 		}
1608 	}
1609 
1610 	/*
1611 	 * Send the following port status and change information
1612 	 * even if port is not owned by EHCI.
1613 	 *
1614 	 * Additional port change information.
1615 	 */
1616 	if (port_status & EHCI_RH_PORT_CONNECT_STS_CHANGE) {
1617 		change_status |= PORT_CHANGE_CSC;
1618 	}
1619 
1620 	/* Additional port status information */
1621 	if (port_status & EHCI_RH_PORT_POWER) {
1622 		new_port_status |= PORT_STATUS_PPS;
1623 	}
1624 
1625 	if ((!(port_status & EHCI_RH_PORT_ENABLE)) &&
1626 	    (port_status & EHCI_RH_PORT_LOW_SPEED)) {
1627 		new_port_status |= PORT_STATUS_LSDA;
1628 	}
1629 
1630 	/*
1631 	 * Construct complete root hub port status and change information.
1632 	 */
1633 	port_status = ((change_status << 16) | new_port_status);
1634 
1635 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1636 	    "ehci_get_root_hub_port_status: port = %d new status = 0x%x "
1637 	    "change status = 0x%x complete port status 0x%x", port,
1638 	    new_port_status, change_status, port_status);
1639 
1640 	return (port_status);
1641 }
1642 
1643 
1644 /*
1645  * ehci_is_port_owner:
1646  *
1647  * Check whether given port is owned by ehci.
1648  */
1649 static int
1650 ehci_is_port_owner(
1651 	ehci_state_t		*ehcip,
1652 	uint16_t		port)
1653 {
1654 	uint_t			port_status;
1655 
1656 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1657 
1658 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1659 	    ~EHCI_RH_PORT_CLEAR_MASK;
1660 
1661 	/*
1662 	 * Don't perform anything if port is owned by classis host
1663 	 * controller and return success.
1664 	 */
1665 	if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_CLASSIC) {
1666 
1667 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1668 		    "ehci_handle_set_clear_port_feature: "
1669 		    "Port %d is owned by classic host controller", port);
1670 
1671 		return (USB_FAILURE);
1672 	}
1673 
1674 	return (USB_SUCCESS);
1675 }
1676 
1677 
1678 /*
1679  * ehci_root_hub_allocate_intr_pipe_resource:
1680  *
1681  * Allocate interrupt requests and initialize them.
1682  */
1683 static int
1684 ehci_root_hub_allocate_intr_pipe_resource(
1685 	ehci_state_t		*ehcip,
1686 	usb_flags_t		flags)
1687 {
1688 	usba_pipe_handle_data_t	*ph;
1689 	size_t			length;
1690 	usb_intr_req_t		*curr_intr_reqp;
1691 
1692 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1693 	    "ehci_root_hub_allocate_intr_pipe_resource");
1694 
1695 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1696 
1697 	/* Get the interrupt pipe handle */
1698 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1699 
1700 	/* Get the current interrupt request pointer */
1701 	curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp;
1702 
1703 	/*
1704 	 * If current interrupt request pointer is null,
1705 	 * allocate new interrupt request.
1706 	 */
1707 	if (curr_intr_reqp == NULL) {
1708 		ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp);
1709 
1710 		/* Get the length of interrupt transfer */
1711 		length = ehcip->ehci_root_hub.
1712 		    rh_client_intr_reqp->intr_len;
1713 
1714 		curr_intr_reqp = usba_hcdi_dup_intr_req(ph->p_dip,
1715 		    ehcip->ehci_root_hub.rh_client_intr_reqp,
1716 		    length, flags);
1717 
1718 		if (curr_intr_reqp == NULL) {
1719 
1720 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1721 			    "ehci_root_hub_allocate_intr_pipe_resource:"
1722 			    "Interrupt request structure allocation failed");
1723 
1724 			return (USB_NO_RESOURCES);
1725 		}
1726 
1727 		ehcip->ehci_root_hub.rh_curr_intr_reqp = curr_intr_reqp;
1728 		mutex_enter(&ph->p_mutex);
1729 		ph->p_req_count++;
1730 		mutex_exit(&ph->p_mutex);
1731 	}
1732 
1733 	/* Start the timer for the root hub interrupt pipe polling */
1734 	if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0) {
1735 		ehcip->ehci_root_hub.rh_intr_pipe_timer_id =
1736 		    timeout(ehci_handle_root_hub_status_change,
1737 		    (void *)ehcip, drv_usectohz(EHCI_RH_POLL_TIME));
1738 
1739 		ehcip->ehci_root_hub.
1740 		    rh_intr_pipe_state = EHCI_PIPE_STATE_ACTIVE;
1741 	}
1742 
1743 	return (USB_SUCCESS);
1744 }
1745 
1746 
1747 /*
1748  * ehci_root_hub_intr_pipe_cleanup:
1749  *
1750  * Deallocate all interrupt requests and do callback
1751  * the original client interrupt request.
1752  */
1753 static void
1754 ehci_root_hub_intr_pipe_cleanup(
1755 	ehci_state_t		*ehcip,
1756 	usb_cr_t		completion_reason)
1757 {
1758 	usb_intr_req_t		*curr_intr_reqp;
1759 	usb_opaque_t		client_intr_reqp;
1760 	timeout_id_t		timer_id;
1761 	usba_pipe_handle_data_t	*ph;
1762 
1763 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1764 	    "ehci_root_hub_intr_pipe_cleanup");
1765 
1766 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1767 
1768 	/* Get the interrupt pipe handle */
1769 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1770 
1771 	/* Get the interrupt timerid */
1772 	timer_id = ehcip->ehci_root_hub.rh_intr_pipe_timer_id;
1773 
1774 	/* Stop the root hub interrupt timer */
1775 	if (timer_id) {
1776 		/* Reset the timer id to zero */
1777 		ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0;
1778 
1779 		mutex_exit(&ehcip->ehci_int_mutex);
1780 		(void) untimeout(timer_id);
1781 		mutex_enter(&ehcip->ehci_int_mutex);
1782 	}
1783 
1784 	/* Reset the current interrupt request pointer */
1785 	curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp;
1786 
1787 	/* Deallocate uncompleted interrupt request */
1788 	if (curr_intr_reqp) {
1789 		ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL;
1790 		usb_free_intr_req(curr_intr_reqp);
1791 
1792 		mutex_enter(&ph->p_mutex);
1793 		ph->p_req_count--;
1794 		mutex_exit(&ph->p_mutex);
1795 	}
1796 
1797 	client_intr_reqp = (usb_opaque_t)
1798 	    ehcip->ehci_root_hub.rh_client_intr_reqp;
1799 
1800 	/* Callback for original client interrupt request */
1801 	if (client_intr_reqp) {
1802 		ehci_root_hub_hcdi_callback(ph, completion_reason);
1803 	}
1804 }
1805 
1806 
1807 /*
1808  * ehci_handle_root_hub_status_change:
1809  *
1810  * A root hub status change interrupt will occur any time there is a change
1811  * in the root hub status register or one of the port status registers.
1812  */
1813 static void
1814 ehci_handle_root_hub_status_change(void *arg)
1815 {
1816 	ehci_state_t		*ehcip = (ehci_state_t *)arg;
1817 	usb_hub_descr_t		*root_hub_descr =
1818 				&ehcip->ehci_root_hub.rh_descr;
1819 	usb_intr_req_t		*curr_intr_reqp;
1820 	usb_port_mask_t		port_mask = 0;
1821 	uint_t			new_port_status;
1822 	uint_t			change_status;
1823 	uint_t			port_status;
1824 	mblk_t			*message;
1825 	size_t			length;
1826 	usb_ep_descr_t		*eptd;
1827 	usba_pipe_handle_data_t	*ph;
1828 	int			i;
1829 
1830 	mutex_enter(&ehcip->ehci_int_mutex);
1831 
1832 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1833 	    "ehci_handle_root_hub_status_change: state = %d",
1834 	    ehcip->ehci_root_hub.rh_intr_pipe_state);
1835 
1836 #if defined(__x86)
1837 	/*
1838 	 * When ohci are attached in ferrari 4000, SMI will reset ehci
1839 	 * registers. If ehci registers have been reset, we must re-initialize
1840 	 * them. During booting, this function will be called 2~3 times. When
1841 	 * this function is called 16 times, ohci drivers have been attached
1842 	 * and stop checking the ehci registers.
1843 	 */
1844 	if (ehcip->ehci_polled_root_hub_count < 16) {
1845 
1846 		if (Get_OpReg(ehci_config_flag) == 0) {
1847 
1848 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB,
1849 			    ehcip->ehci_log_hdl,
1850 			    "ehci_handle_root_hub_status_change:",
1851 			    " EHCI have been reset");
1852 
1853 			/* Reinitialize the controller */
1854 			if (ehci_init_ctlr(ehcip, EHCI_REINITIALIZATION) !=
1855 			    DDI_SUCCESS) {
1856 				mutex_exit(&ehcip->ehci_int_mutex);
1857 
1858 				return;
1859 			}
1860 		}
1861 
1862 		ehcip->ehci_polled_root_hub_count++;
1863 	}
1864 #endif	/* __x86 */
1865 
1866 	/* Get the current interrupt request pointer */
1867 	curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp;
1868 
1869 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1870 
1871 	/* Check whether timeout handler is valid */
1872 	if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id) {
1873 		/* Check host controller is in operational state */
1874 		if ((ehci_state_is_operational(ehcip)) != USB_SUCCESS) {
1875 			/* Reset the timer id */
1876 			ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0;
1877 
1878 			/* Do interrupt pipe cleanup */
1879 			ehci_root_hub_intr_pipe_cleanup(
1880 			    ehcip, USB_CR_HC_HARDWARE_ERR);
1881 
1882 			mutex_exit(&ehcip->ehci_int_mutex);
1883 
1884 			return;
1885 		}
1886 	} else {
1887 		mutex_exit(&ehcip->ehci_int_mutex);
1888 
1889 		return;
1890 	}
1891 
1892 	eptd = &ehcip->ehci_root_hub.rh_intr_pipe_handle->p_ep;
1893 
1894 	/* Check each port */
1895 	for (i = 0; i < root_hub_descr->bNbrPorts; i++) {
1896 
1897 		port_status = ehci_get_root_hub_port_status(ehcip, i);
1898 
1899 		new_port_status = port_status & PORT_STATUS_MASK;
1900 		change_status = (port_status >> 16) & PORT_CHANGE_MASK;
1901 
1902 		/*
1903 		 * If there is change in the port status then set the bit in the
1904 		 * bitmap of changes and inform hub driver about these changes.
1905 		 * Hub driver will take care of these changes.
1906 		 */
1907 		if (change_status) {
1908 
1909 			/* See if a device was attached/detached */
1910 			if (change_status & PORT_CHANGE_CSC) {
1911 				/*
1912 				 * Update the state depending on whether
1913 				 * the port was attached or detached.
1914 				 */
1915 				if (new_port_status & PORT_STATUS_CCS) {
1916 					ehcip->ehci_root_hub.
1917 					    rh_port_state[i] = DISABLED;
1918 
1919 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1920 					    ehcip->ehci_log_hdl,
1921 					    "Port %d connected", i+1);
1922 				} else {
1923 					ehcip->ehci_root_hub.
1924 					    rh_port_state[i] = DISCONNECTED;
1925 
1926 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1927 					    ehcip->ehci_log_hdl,
1928 					    "Port %d disconnected", i+1);
1929 				}
1930 			}
1931 
1932 			/* See if port enable status changed */
1933 			if (change_status & PORT_CHANGE_PESC) {
1934 				/*
1935 				 * Update the state depending on whether
1936 				 * the port was enabled or disabled.
1937 				 */
1938 				if (new_port_status & PORT_STATUS_PES) {
1939 					ehcip->ehci_root_hub.
1940 					    rh_port_state[i] = ENABLED;
1941 
1942 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1943 					    ehcip->ehci_log_hdl,
1944 					    "Port %d enabled", i+1);
1945 				} else {
1946 					ehcip->ehci_root_hub.
1947 					    rh_port_state[i] = DISABLED;
1948 
1949 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1950 					    ehcip->ehci_log_hdl,
1951 					    "Port %d disabled", i+1);
1952 				}
1953 			}
1954 
1955 			port_mask |= 1 << (i + 1);
1956 
1957 			/* Update the status */
1958 			ehcip->ehci_root_hub.
1959 			    rh_port_status[i] = new_port_status;
1960 		}
1961 	}
1962 
1963 	if (ph && port_mask && curr_intr_reqp) {
1964 		length = eptd->wMaxPacketSize;
1965 
1966 		ASSERT(length != 0);
1967 
1968 		/* Get the  message block */
1969 		message = curr_intr_reqp->intr_data;
1970 
1971 		ASSERT(message != NULL);
1972 
1973 		do {
1974 			/*
1975 			 * check that the mblk is big enough when we
1976 			 * are writing bytes into it
1977 			 */
1978 			if (message->b_wptr >= message->b_datap->db_lim) {
1979 
1980 				USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB,
1981 				    ehcip->ehci_log_hdl,
1982 				    "ehci_handle_root_hub_status_change"
1983 				    "mblk data overflow.");
1984 
1985 				break;
1986 			}
1987 			*message->b_wptr++ = (uchar_t)port_mask;
1988 			port_mask >>= 8;
1989 		} while (port_mask != 0);
1990 
1991 		ehci_root_hub_hcdi_callback(ph, USB_CR_OK);
1992 	}
1993 
1994 	/* Reset the timer id */
1995 	ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0;
1996 
1997 	if (ehcip->ehci_root_hub.rh_intr_pipe_state ==
1998 	    EHCI_PIPE_STATE_ACTIVE) {
1999 		/*
2000 		 * If needed, allocate new interrupt request. Also
2001 		 * start the timer for the root hub interrupt polling.
2002 		 */
2003 		if ((ehci_root_hub_allocate_intr_pipe_resource(
2004 		    ehcip, 0)) != USB_SUCCESS) {
2005 
2006 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
2007 			    "ehci_handle_root_hub_status_change: No Resources");
2008 
2009 			/* Do interrupt pipe cleanup */
2010 			ehci_root_hub_intr_pipe_cleanup(
2011 			    ehcip, USB_CR_NO_RESOURCES);
2012 		}
2013 	}
2014 
2015 	mutex_exit(&ehcip->ehci_int_mutex);
2016 }
2017 
2018 
2019 /*
2020  * ehci_root_hub_hcdi_callback()
2021  *
2022  * Convenience wrapper around usba_hcdi_cb() for the root hub.
2023  */
2024 static void
2025 ehci_root_hub_hcdi_callback(
2026 	usba_pipe_handle_data_t	*ph,
2027 	usb_cr_t		completion_reason)
2028 {
2029 	ehci_state_t		*ehcip = ehci_obtain_state(
2030 				    ph->p_usba_device->usb_root_hub_dip);
2031 	uchar_t			attributes = ph->p_ep.bmAttributes &
2032 							USB_EP_ATTR_MASK;
2033 	usb_opaque_t		curr_xfer_reqp;
2034 	uint_t			pipe_state = 0;
2035 
2036 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
2037 	    "ehci_root_hub_hcdi_callback: ph = 0x%p, cr = 0x%x",
2038 	    ph, completion_reason);
2039 
2040 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
2041 
2042 	/* Set the pipe state as per completion reason */
2043 	switch (completion_reason) {
2044 	case USB_CR_OK:
2045 		switch (attributes) {
2046 		case USB_EP_ATTR_CONTROL:
2047 			pipe_state = EHCI_PIPE_STATE_IDLE;
2048 			break;
2049 		case USB_EP_ATTR_INTR:
2050 			pipe_state = ehcip->ehci_root_hub.
2051 			    rh_intr_pipe_state;
2052 			break;
2053 		}
2054 		break;
2055 	case USB_CR_NO_RESOURCES:
2056 	case USB_CR_NOT_SUPPORTED:
2057 	case USB_CR_STOPPED_POLLING:
2058 	case USB_CR_PIPE_RESET:
2059 	case USB_CR_HC_HARDWARE_ERR:
2060 		/* Set pipe state to idle */
2061 		pipe_state = EHCI_PIPE_STATE_IDLE;
2062 		break;
2063 	case USB_CR_PIPE_CLOSING:
2064 		break;
2065 	default:
2066 		/* Set pipe state to error */
2067 		pipe_state = EHCI_PIPE_STATE_ERROR;
2068 		break;
2069 	}
2070 
2071 	switch (attributes) {
2072 	case USB_EP_ATTR_CONTROL:
2073 		curr_xfer_reqp = (usb_opaque_t)
2074 		    ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
2075 
2076 		ehcip->ehci_root_hub.rh_curr_ctrl_reqp = NULL;
2077 		ehcip->ehci_root_hub.rh_ctrl_pipe_state = pipe_state;
2078 		break;
2079 	case USB_EP_ATTR_INTR:
2080 		/* if curr_intr_reqp available then use this request */
2081 		if (ehcip->ehci_root_hub.rh_curr_intr_reqp) {
2082 			curr_xfer_reqp = (usb_opaque_t)ehcip->
2083 			    ehci_root_hub.rh_curr_intr_reqp;
2084 
2085 			ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL;
2086 		} else {
2087 			/* no current request, use client's request */
2088 			curr_xfer_reqp = (usb_opaque_t)
2089 			    ehcip->ehci_root_hub.rh_client_intr_reqp;
2090 
2091 			ehcip->ehci_root_hub.rh_client_intr_reqp = NULL;
2092 		}
2093 		ehcip->ehci_root_hub.rh_intr_pipe_state = pipe_state;
2094 		break;
2095 	}
2096 
2097 	ASSERT(curr_xfer_reqp != NULL);
2098 
2099 	mutex_exit(&ehcip->ehci_int_mutex);
2100 	usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason);
2101 	mutex_enter(&ehcip->ehci_int_mutex);
2102 }
2103