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