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