1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 
27 /*
28  * EHCI Host Controller Driver (EHCI)
29  *
30  * The EHCI driver is a software driver which interfaces to the Universal
31  * Serial Bus layer (USBA) and the Host Controller (HC). The interface to
32  * the Host Controller is defined by the EHCI Host Controller Interface.
33  *
34  * This module contains the code for root hub related functions.
35  *
36  * NOTE:
37  *
38  * ONE_XFER is not supported on root hub interrupt polling
39  */
40 
41 #include <sys/usb/hcd/ehci/ehcid.h>
42 #include <sys/usb/hcd/ehci/ehci_util.h>
43 #include <sys/usb/usba/usba_types.h>
44 
45 /* Static function prototypes */
46 static int	ehci_handle_set_clear_port_feature(
47 				ehci_state_t		*ehcip,
48 				uchar_t 		bRequest,
49 				uint16_t		wValue,
50 				uint16_t		port);
51 static void	ehci_handle_port_power(
52 				ehci_state_t		*ehcip,
53 				uint16_t		port,
54 				uint_t			on);
55 static void	ehci_handle_port_enable(
56 				ehci_state_t		*ehcip,
57 				uint16_t		port,
58 				uint_t			on);
59 static void	ehci_handle_clrchng_port_enable(
60 				ehci_state_t		*ehcip,
61 				uint16_t		port);
62 static void	ehci_handle_port_suspend(
63 				ehci_state_t		*ehcip,
64 				uint16_t		port,
65 				uint_t			on);
66 static void	ehci_handle_clrchng_port_suspend(
67 				ehci_state_t		*ehcip,
68 				uint16_t		port);
69 static void	ehci_handle_port_reset(
70 				ehci_state_t		*ehcip,
71 				uint16_t		port);
72 static void	ehci_root_hub_reset_occured(
73 				ehci_state_t		*ehcip);
74 static void	ehci_handle_complete_port_reset(
75 				ehci_state_t		*ehcip,
76 				uint16_t		port);
77 static void	ehci_handle_clear_port_connection(
78 				ehci_state_t		*ehcip,
79 				uint16_t		port);
80 static void	ehci_handle_clrchng_port_over_current(
81 				ehci_state_t		*ehcip,
82 				uint16_t		port);
83 static void	ehci_handle_get_port_status(
84 				ehci_state_t		*ehcip,
85 				uint16_t		port);
86 static void	ehci_handle_get_hub_descriptor(
87 				ehci_state_t		*ehcip);
88 static void	ehci_handle_get_hub_status(
89 				ehci_state_t		*ehcip);
90 static void	ehci_handle_get_device_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 HUB_GET_DEVICE_STATUS_TYPE:
554 		ehci_handle_get_device_status(ehcip);
555 		break;
556 	case HUB_HANDLE_PORT_FEATURE_TYPE:
557 		error = ehci_handle_set_clear_port_feature(ehcip,
558 		    bRequest, wValue, port);
559 		break;
560 	case HUB_GET_PORT_STATUS_TYPE:
561 		ehci_handle_get_port_status(ehcip, port);
562 		break;
563 	case HUB_CLASS_REQ_TYPE:
564 		switch (bRequest) {
565 		case USB_REQ_GET_STATUS:
566 			ehci_handle_get_hub_status(ehcip);
567 			break;
568 		case USB_REQ_GET_DESCR:
569 			ehci_handle_get_hub_descriptor(ehcip);
570 			break;
571 		default:
572 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
573 			    "ehci_handle_root_hub_request:"
574 			    "Unsupported request 0x%x", bRequest);
575 
576 			error = USB_FAILURE;
577 			break;
578 		}
579 		break;
580 	default:
581 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
582 		    "ehci_handle_root_hub_request: "
583 		    "Unsupported request 0x%x", bmRequestType);
584 
585 		error = USB_FAILURE;
586 		break;
587 	}
588 
589 	completion_reason = (error) ? USB_CR_NOT_SUPPORTED : USB_CR_OK;
590 
591 	mutex_enter(&ehcip->ehci_int_mutex);
592 	ehci_root_hub_hcdi_callback(ph, completion_reason);
593 	mutex_exit(&ehcip->ehci_int_mutex);
594 
595 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
596 	    "ehci_handle_root_hub_request: error = %d", error);
597 
598 	return (USB_SUCCESS);
599 }
600 
601 
602 /*
603  * ehci_handle_set_clear_port_feature:
604  */
605 static int
606 ehci_handle_set_clear_port_feature(
607 	ehci_state_t		*ehcip,
608 	uchar_t 		bRequest,
609 	uint16_t		wValue,
610 	uint16_t		port)
611 {
612 	int			error = USB_SUCCESS;
613 
614 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
615 	    "ehci_handle_set_clear_port_feature: 0x%x 0x%x 0x%x",
616 	    bRequest, wValue, port);
617 
618 	switch (bRequest) {
619 	case USB_REQ_SET_FEATURE:
620 		switch (wValue) {
621 		case CFS_PORT_ENABLE:
622 			ehci_handle_port_enable(ehcip, port, 1);
623 			break;
624 		case CFS_PORT_SUSPEND:
625 			ehci_handle_port_suspend(ehcip, port, 1);
626 			break;
627 		case CFS_PORT_RESET:
628 			ehci_handle_port_reset(ehcip, port);
629 			break;
630 		case CFS_PORT_POWER:
631 			ehci_handle_port_power(ehcip, port, 1);
632 			break;
633 		default:
634 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
635 			    "ehci_handle_set_clear_port_feature: "
636 			    "Unsupported request 0x%x 0x%x", bRequest, wValue);
637 
638 			error = USB_FAILURE;
639 			break;
640 		}
641 		break;
642 	case USB_REQ_CLEAR_FEATURE:
643 		switch (wValue) {
644 		case CFS_PORT_ENABLE:
645 			ehci_handle_port_enable(ehcip, port, 0);
646 			break;
647 		case CFS_C_PORT_ENABLE:
648 			ehci_handle_clrchng_port_enable(ehcip, port);
649 			break;
650 		case CFS_PORT_SUSPEND:
651 			ehci_handle_port_suspend(ehcip, port, 0);
652 			break;
653 		case CFS_C_PORT_SUSPEND:
654 			ehci_handle_clrchng_port_suspend(ehcip, port);
655 			break;
656 		case CFS_C_PORT_RESET:
657 			ehci_handle_complete_port_reset(ehcip, port);
658 			break;
659 		case CFS_PORT_POWER:
660 			ehci_handle_port_power(ehcip, port, 0);
661 			break;
662 		case CFS_C_PORT_CONNECTION:
663 			ehci_handle_clear_port_connection(ehcip, port);
664 			break;
665 		case CFS_C_PORT_OVER_CURRENT:
666 			ehci_handle_clrchng_port_over_current(ehcip, port);
667 			break;
668 		default:
669 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
670 			    "ehci_handle_set_clear_port_feature: "
671 			    "Unsupported request 0x%x 0x%x", bRequest, wValue);
672 
673 			error = USB_FAILURE;
674 			break;
675 		}
676 		break;
677 	default:
678 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
679 		    "ehci_handle_set_clear_port_feature: "
680 		    "Unsupported request 0x%x 0x%x", bRequest, wValue);
681 
682 		error = USB_FAILURE;
683 		break;
684 	}
685 
686 	return (error);
687 }
688 
689 
690 /*
691  * ehci_handle_port_power:
692  *
693  * Turn on a root hub port.
694  */
695 static void
696 ehci_handle_port_power(
697 	ehci_state_t		*ehcip,
698 	uint16_t		port,
699 	uint_t			on)
700 {
701 	uint_t			port_status;
702 	ehci_root_hub_t		*rh;
703 
704 	mutex_enter(&ehcip->ehci_int_mutex);
705 
706 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
707 	    ~EHCI_RH_PORT_CLEAR_MASK;
708 
709 	rh = &ehcip->ehci_root_hub;
710 
711 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
712 	    "ehci_handle_port_power: port = 0x%x status = 0x%x on = %d",
713 	    port, port_status, on);
714 
715 	/* Check port is owned by ehci */
716 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
717 		mutex_exit(&ehcip->ehci_int_mutex);
718 
719 		return;
720 	}
721 
722 	if (on) {
723 		/* See if the port power is already on */
724 		if (!(port_status & EHCI_RH_PORT_POWER)) {
725 			/* Turn the port on */
726 			Set_OpReg(ehci_rh_port_status[port],
727 			    port_status | EHCI_RH_PORT_POWER);
728 		}
729 
730 		rh->rh_port_status[port] = 0;
731 		rh->rh_port_state[port] = DISCONNECTED;
732 	} else {
733 		/* See if the port power is already OFF */
734 		if (port_status & EHCI_RH_PORT_POWER) {
735 			/* Turn-off the port */
736 			Set_OpReg(ehci_rh_port_status[port],
737 			    port_status & ~EHCI_RH_PORT_POWER);
738 		}
739 
740 		rh->rh_port_status[port] = 0;
741 		rh->rh_port_state[port] = POWERED_OFF;
742 	}
743 
744 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
745 	    "ehci_handle_port_power done: port = 0x%x status = 0x%x on = %d",
746 	    port, Get_OpReg(ehci_rh_port_status[port]), on);
747 
748 	mutex_exit(&ehcip->ehci_int_mutex);
749 }
750 
751 
752 /*
753  * ehci_handle_port_enable:
754  *
755  * Handle port enable request.
756  */
757 static void
758 ehci_handle_port_enable(
759 	ehci_state_t		*ehcip,
760 	uint16_t		port,
761 	uint_t			on)
762 {
763 	uint_t			port_status;
764 
765 	mutex_enter(&ehcip->ehci_int_mutex);
766 
767 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
768 	    ~EHCI_RH_PORT_CLEAR_MASK;
769 
770 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
771 	    "ehci_handle_port_enable: port = 0x%x, status = 0x%x",
772 	    port, port_status);
773 
774 	/* Check port is owned by ehci */
775 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
776 		mutex_exit(&ehcip->ehci_int_mutex);
777 
778 		return;
779 	}
780 
781 	if (on) {
782 		/* See if the port enable is already on */
783 		if (!(port_status & EHCI_RH_PORT_ENABLE)) {
784 			/* Enable the port */
785 			Set_OpReg(ehci_rh_port_status[port],
786 			    port_status | EHCI_RH_PORT_ENABLE);
787 		}
788 	} else {
789 		/* See if the port enable is already off */
790 		if (port_status & EHCI_RH_PORT_ENABLE) {
791 			/* Disable the port */
792 			Set_OpReg(ehci_rh_port_status[port],
793 			    port_status & ~EHCI_RH_PORT_ENABLE);
794 		}
795 	}
796 
797 	mutex_exit(&ehcip->ehci_int_mutex);
798 }
799 
800 
801 /*
802  * ehci_handle_clrchng_port_enable:
803  *
804  * Handle clear port enable change bit.
805  */
806 static void
807 ehci_handle_clrchng_port_enable(
808 	ehci_state_t		*ehcip,
809 	uint16_t		port)
810 {
811 	uint_t			port_status;
812 
813 	mutex_enter(&ehcip->ehci_int_mutex);
814 
815 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
816 	    ~EHCI_RH_PORT_CLEAR_MASK;
817 
818 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
819 	    "ehci_handle_port_enable: port = 0x%x, status = 0x%x",
820 	    port, port_status);
821 
822 	/* Check port is owned by ehci */
823 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
824 		mutex_exit(&ehcip->ehci_int_mutex);
825 
826 		return;
827 	}
828 
829 	/* Clear the PortEnableStatusChange Bit */
830 	Set_OpReg(ehci_rh_port_status[port],
831 	    port_status | EHCI_RH_PORT_ENABLE_CHANGE);
832 
833 	mutex_exit(&ehcip->ehci_int_mutex);
834 }
835 
836 
837 /*
838  * ehci_handle_port_suspend:
839  *
840  * Handle port suspend/resume request.
841  */
842 static void
843 ehci_handle_port_suspend(
844 	ehci_state_t		*ehcip,
845 	uint16_t		port,
846 	uint_t			on)
847 {
848 	uint_t			port_status;
849 
850 	mutex_enter(&ehcip->ehci_int_mutex);
851 
852 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
853 	    ~EHCI_RH_PORT_CLEAR_MASK;
854 
855 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
856 	    "ehci_handle_port_suspend: port = 0x%x, status = 0x%x",
857 	    port, port_status);
858 
859 	/* Check port is owned by ehci */
860 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
861 		mutex_exit(&ehcip->ehci_int_mutex);
862 
863 		return;
864 	}
865 
866 	if (on) {
867 		/*
868 		 * Suspend port only if port is enabled and
869 		 * it is not already in suspend state.
870 		 */
871 		if ((port_status & EHCI_RH_PORT_ENABLE) &&
872 		    (!(port_status & EHCI_RH_PORT_SUSPEND))) {
873 			/* Suspend the port */
874 			Set_OpReg(ehci_rh_port_status[port],
875 			    port_status | EHCI_RH_PORT_SUSPEND);
876 
877 			mutex_exit(&ehcip->ehci_int_mutex);
878 
879 			/* Wait 10ms for port move to suspend state */
880 			delay(drv_usectohz(EHCI_PORT_SUSPEND_TIMEWAIT));
881 
882 			return;
883 		}
884 	} else {
885 		/* Perform resume only if port is in suspend state */
886 		if (port_status & EHCI_RH_PORT_SUSPEND) {
887 			/* Resume the port */
888 			Set_OpReg(ehci_rh_port_status[port],
889 			    port_status | EHCI_RH_PORT_RESUME);
890 		}
891 	}
892 
893 	mutex_exit(&ehcip->ehci_int_mutex);
894 }
895 
896 
897 /*
898  * ehci_handle_clrchng_port_suspend:
899  *
900  * Handle port clear port suspend change bit.
901  */
902 static void
903 ehci_handle_clrchng_port_suspend(
904 	ehci_state_t		*ehcip,
905 	uint16_t		port)
906 {
907 	uint_t			port_status;
908 	int			i;
909 
910 	mutex_enter(&ehcip->ehci_int_mutex);
911 
912 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
913 	    ~EHCI_RH_PORT_CLEAR_MASK;
914 
915 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
916 	    "ehci_handle_clrchng_port_suspend: port = 0x%x, "
917 	    "status = 0x%x", port, port_status);
918 
919 	/* Check port is owned by ehci */
920 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
921 		mutex_exit(&ehcip->ehci_int_mutex);
922 
923 		return;
924 	}
925 
926 	/* Return if port is not in resume state */
927 	if (!(port_status & EHCI_RH_PORT_RESUME)) {
928 		mutex_exit(&ehcip->ehci_int_mutex);
929 
930 		return;
931 	}
932 
933 	mutex_exit(&ehcip->ehci_int_mutex);
934 
935 	/* Wait for 20ms to terminate resume */
936 	delay(drv_usectohz(EHCI_PORT_RESUME_TIMEWAIT));
937 
938 	mutex_enter(&ehcip->ehci_int_mutex);
939 
940 	Set_OpReg(ehci_rh_port_status[port],
941 	    port_status & ~EHCI_RH_PORT_RESUME);
942 
943 	mutex_exit(&ehcip->ehci_int_mutex);
944 
945 	/*
946 	 * Wait for port to return to high speed mode. It's necessary to poll
947 	 * for resume completion for some high-speed devices to work correctly.
948 	 */
949 	for (i = 0; i < EHCI_PORT_RESUME_RETRY_MAX; i++) {
950 		delay(drv_usectohz(EHCI_PORT_RESUME_COMP_TIMEWAIT));
951 
952 		mutex_enter(&ehcip->ehci_int_mutex);
953 		port_status = Get_OpReg(ehci_rh_port_status[port]) &
954 		    ~EHCI_RH_PORT_CLEAR_MASK;
955 		mutex_exit(&ehcip->ehci_int_mutex);
956 
957 		if (!(port_status & EHCI_RH_PORT_RESUME)) {
958 			break;
959 		}
960 	}
961 }
962 
963 
964 /*
965  * ehci_handle_port_reset:
966  *
967  * Perform a port reset.
968  */
969 static void
970 ehci_handle_port_reset(
971 	ehci_state_t		*ehcip,
972 	uint16_t		port)
973 {
974 	ehci_root_hub_t		*rh;
975 	uint_t			port_status;
976 	int			i;
977 
978 	mutex_enter(&ehcip->ehci_int_mutex);
979 
980 	/* Get the root hub structure */
981 	rh = &ehcip->ehci_root_hub;
982 
983 	/* Get the port status information */
984 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
985 	    ~EHCI_RH_PORT_CLEAR_MASK;
986 
987 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
988 	    "ehci_handle_port_reset: port = 0x%x status = 0x%x",
989 	    port, port_status);
990 
991 	/* Check port is owned by ehci */
992 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
993 		mutex_exit(&ehcip->ehci_int_mutex);
994 
995 		return;
996 	}
997 
998 	if (port_status & EHCI_RH_PORT_LOW_SPEED) {
999 		/* Check for classic or companion host controllers */
1000 		if (rh->rh_companion_controllers) {
1001 			USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1002 			    "ehci_handle_port_reset: Low speed device "
1003 			    "and handover this port to Companion controller");
1004 
1005 			Set_OpReg(ehci_rh_port_status[port],
1006 			    port_status | EHCI_RH_PORT_OWNER_CLASSIC);
1007 		} else {
1008 			USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1009 			    "Low speed device is not supported");
1010 		}
1011 	} else {
1012 		Set_OpReg(ehci_rh_port_status[port],
1013 		    ((port_status | EHCI_RH_PORT_RESET) &
1014 		    ~EHCI_RH_PORT_ENABLE));
1015 
1016 		mutex_exit(&ehcip->ehci_int_mutex);
1017 
1018 		/* Wait 50ms for reset to complete */
1019 		delay(drv_usectohz(EHCI_PORT_RESET_TIMEWAIT));
1020 
1021 		mutex_enter(&ehcip->ehci_int_mutex);
1022 
1023 		port_status = Get_OpReg(ehci_rh_port_status[port]) &
1024 		    ~EHCI_RH_PORT_CLEAR_MASK;
1025 
1026 		Set_OpReg(ehci_rh_port_status[port],
1027 		    (port_status & ~EHCI_RH_PORT_RESET));
1028 
1029 		mutex_exit(&ehcip->ehci_int_mutex);
1030 
1031 		/*
1032 		 * Wait for hardware to enable this port, if the connected
1033 		 * usb device is high speed. It's necessary to poll for reset
1034 		 * completion for some high-speed devices to recognized
1035 		 * correctly.
1036 		 */
1037 		for (i = 0; i < EHCI_PORT_RESET_RETRY_MAX; i++) {
1038 			delay(drv_usectohz(EHCI_PORT_RESET_COMP_TIMEWAIT));
1039 
1040 			mutex_enter(&ehcip->ehci_int_mutex);
1041 			port_status = Get_OpReg(ehci_rh_port_status[port]) &
1042 			    ~EHCI_RH_PORT_CLEAR_MASK;
1043 			mutex_exit(&ehcip->ehci_int_mutex);
1044 
1045 			if (!(port_status & EHCI_RH_PORT_RESET)) {
1046 				break;
1047 			}
1048 		}
1049 
1050 		mutex_enter(&ehcip->ehci_int_mutex);
1051 
1052 		port_status = Get_OpReg(ehci_rh_port_status[port]) &
1053 		    ~EHCI_RH_PORT_CLEAR_MASK;
1054 
1055 		/*
1056 		 * If port is not enabled, connected device is a
1057 		 * Full-speed usb device.
1058 		 */
1059 		if (!(port_status & EHCI_RH_PORT_ENABLE)) {
1060 			/* Check for classic or companion host controllers */
1061 			if (rh->rh_companion_controllers) {
1062 				USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1063 				    ehcip->ehci_log_hdl,
1064 				    "ehci_handle_port_reset: Full speed device "
1065 				    "and handover this port to Companion host "
1066 				    "controller");
1067 
1068 				Set_OpReg(ehci_rh_port_status[port],
1069 				    port_status | EHCI_RH_PORT_OWNER_CLASSIC);
1070 			} else {
1071 				USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB,
1072 				    ehcip->ehci_log_hdl,
1073 				    "Full speed device is not supported");
1074 			}
1075 		} else {
1076 			USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1077 			    "ehci_handle_port_reset: High speed device ");
1078 
1079 			port_status = Get_OpReg(ehci_rh_port_status[port]) &
1080 			    ~EHCI_RH_PORT_CLEAR_MASK;
1081 
1082 			/*
1083 			 * Enable over-current, connect, and disconnect
1084 			 * wakeup bits.
1085 			 */
1086 			Set_OpReg(ehci_rh_port_status[port], (port_status |
1087 			    EHCI_RH_PORT_OVER_CURENT_ENABLE |
1088 			    EHCI_RH_PORT_DISCONNECT_ENABLE |
1089 			    EHCI_RH_PORT_CONNECT_ENABLE));
1090 
1091 			/*
1092 			 * The next function is only called if the interrupt
1093 			 * pipe is polling and the USBA is ready to receive
1094 			 * the data.
1095 			 */
1096 			ehcip->ehci_root_hub.
1097 			    rh_intr_pending_status |= (1 << port);
1098 
1099 			if (ehcip->ehci_root_hub.
1100 			    rh_intr_pipe_state == EHCI_PIPE_STATE_ACTIVE) {
1101 
1102 				ehci_root_hub_reset_occured(ehcip);
1103 			}
1104 		}
1105 	}
1106 
1107 	mutex_exit(&ehcip->ehci_int_mutex);
1108 }
1109 
1110 
1111 /*
1112  * ehci_root_hub_reset_occured:
1113  *
1114  * Inform the upper layer that reset has occured on the port. This is
1115  * required because the upper layer is expecting a an evernt immidiately
1116  * after doing reset. In case of OHCI, the controller gets an interrupt
1117  * for the change in the root hub status but in case of EHCI, we dont.
1118  * So, send a event to the upper layer as soon as we complete the reset.
1119  */
1120 void
1121 ehci_root_hub_reset_occured(
1122 	ehci_state_t		*ehcip)
1123 {
1124 	usb_intr_req_t		*curr_intr_reqp =
1125 	    ehcip->ehci_root_hub.rh_curr_intr_reqp;
1126 	usb_port_mask_t		port_mask;
1127 	usba_pipe_handle_data_t	*ph;
1128 
1129 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1130 	    "ehci_root_hub_reset_occured: curr_intr_reqp = 0x%p data = 0x%p",
1131 	    (void *)curr_intr_reqp, (void *)curr_intr_reqp->intr_data);
1132 
1133 	/* Get the interrupt pipe handle */
1134 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1135 
1136 	/* Get the pending status */
1137 	port_mask = ehcip->ehci_root_hub.rh_intr_pending_status << 1;
1138 
1139 	do {
1140 		*curr_intr_reqp->intr_data->b_wptr++ = (uchar_t)port_mask;
1141 		port_mask >>= 8;
1142 	} while (port_mask != 0);
1143 
1144 	ehci_root_hub_hcdi_callback(ph, USB_CR_OK);
1145 
1146 	/* Reset pending status */
1147 	ehcip->ehci_root_hub.rh_intr_pending_status = 0;
1148 
1149 	/* If needed, allocate new interrupt request */
1150 	if ((ehci_root_hub_allocate_intr_pipe_resource(
1151 	    ehcip, 0)) != USB_SUCCESS) {
1152 
1153 		/* Do interrupt pipe cleanup */
1154 		ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_NO_RESOURCES);
1155 	}
1156 }
1157 
1158 
1159 /*
1160  * ehci_handle_complete_port_reset:
1161  *
1162  * Perform a port reset change.
1163  */
1164 static void
1165 ehci_handle_complete_port_reset(
1166 	ehci_state_t		*ehcip,
1167 	uint16_t		port)
1168 {
1169 	uint_t			port_status;
1170 
1171 	mutex_enter(&ehcip->ehci_int_mutex);
1172 
1173 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1174 	    ~EHCI_RH_PORT_CLEAR_MASK;
1175 
1176 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1177 	    "ehci_handle_complete_port_reset: port = 0x%x status = 0x%x",
1178 	    port, port_status);
1179 
1180 	/* Check port is owned by ehci */
1181 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
1182 		mutex_exit(&ehcip->ehci_int_mutex);
1183 
1184 		return;
1185 	}
1186 
1187 	if (port_status & EHCI_RH_PORT_RESET) {
1188 		Set_OpReg(ehci_rh_port_status[port],
1189 		    port_status & ~EHCI_RH_PORT_RESET);
1190 
1191 	}
1192 
1193 	mutex_exit(&ehcip->ehci_int_mutex);
1194 }
1195 
1196 
1197 /*
1198  * ehci_handle_clear_port_connection:
1199  *
1200  * Perform a clear port connection.
1201  */
1202 static void
1203 ehci_handle_clear_port_connection(
1204 	ehci_state_t		*ehcip,
1205 	uint16_t		port)
1206 {
1207 	uint_t			port_status;
1208 
1209 	mutex_enter(&ehcip->ehci_int_mutex);
1210 
1211 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1212 	    ~EHCI_RH_PORT_CLEAR_MASK;
1213 
1214 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1215 	    "ehci_handle_clear_port_connection: port = 0x%x"
1216 	    "status = 0x%x", port, port_status);
1217 
1218 	Set_OpReg(ehci_rh_port_status[port],
1219 	    port_status | EHCI_RH_PORT_CONNECT_STS_CHANGE);
1220 
1221 	mutex_exit(&ehcip->ehci_int_mutex);
1222 }
1223 
1224 
1225 /*
1226  * ehci_handle_clrchng_port_over_current:
1227  *
1228  * Perform a clear port connection.
1229  */
1230 static void
1231 ehci_handle_clrchng_port_over_current(
1232 	ehci_state_t		*ehcip,
1233 	uint16_t		port)
1234 {
1235 	uint_t			port_status;
1236 
1237 	mutex_enter(&ehcip->ehci_int_mutex);
1238 
1239 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1240 	    ~EHCI_RH_PORT_CLEAR_MASK;
1241 
1242 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1243 	    "ehci_handle_clrchng_port_over_current: port = 0x%x"
1244 	    "status = 0x%x", port, port_status);
1245 
1246 	Set_OpReg(ehci_rh_port_status[port],
1247 	    port_status | EHCI_RH_PORT_OVER_CURR_CHANGE);
1248 
1249 	mutex_exit(&ehcip->ehci_int_mutex);
1250 }
1251 
1252 
1253 /*
1254  * ehci_handle_get_port_status:
1255  *
1256  * Handle a get port status request.
1257  */
1258 static void
1259 ehci_handle_get_port_status(
1260 	ehci_state_t		*ehcip,
1261 	uint16_t		port)
1262 {
1263 	usb_ctrl_req_t		*ctrl_reqp;
1264 	mblk_t			*message;
1265 	uint_t			new_port_status = 0;
1266 	uint_t			change_status = 0;
1267 	uint_t			port_status;
1268 
1269 	mutex_enter(&ehcip->ehci_int_mutex);
1270 
1271 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1272 
1273 	/* Get the root hub port status information */
1274 	port_status = ehci_get_root_hub_port_status(ehcip, port);
1275 
1276 	new_port_status = port_status & PORT_STATUS_MASK;
1277 	change_status = (port_status >> 16) & PORT_CHANGE_MASK;
1278 
1279 	ehcip->ehci_root_hub.rh_port_status[port] = new_port_status;
1280 
1281 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1282 	    "ehci_handle_get_port_status: port = %d new status = 0x%x"
1283 	    "change = 0x%x", port, new_port_status, change_status);
1284 
1285 	message = ctrl_reqp->ctrl_data;
1286 
1287 	ASSERT(message != NULL);
1288 
1289 	*message->b_wptr++ = (uchar_t)new_port_status;
1290 	*message->b_wptr++ = (uchar_t)(new_port_status >> 8);
1291 	*message->b_wptr++ = (uchar_t)change_status;
1292 	*message->b_wptr++ = (uchar_t)(change_status >> 8);
1293 
1294 	/* Save the data in control request */
1295 	ctrl_reqp->ctrl_data = message;
1296 
1297 	mutex_exit(&ehcip->ehci_int_mutex);
1298 }
1299 
1300 
1301 /*
1302  * ehci_handle_get_hub_descriptor:
1303  */
1304 static void
1305 ehci_handle_get_hub_descriptor(
1306 	ehci_state_t		*ehcip)
1307 {
1308 	usb_ctrl_req_t		*ctrl_reqp;
1309 	mblk_t			*message;
1310 	usb_hub_descr_t		*root_hub_descr;
1311 	size_t			length;
1312 	uchar_t			raw_descr[ROOT_HUB_DESCRIPTOR_LENGTH];
1313 
1314 	mutex_enter(&ehcip->ehci_int_mutex);
1315 
1316 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1317 	root_hub_descr = &ehcip->ehci_root_hub.rh_descr;
1318 	length = ctrl_reqp->ctrl_wLength;
1319 
1320 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1321 	    "ehci_handle_get_hub_descriptor: Ctrl Req  = 0x%p",
1322 	    (void *)ctrl_reqp);
1323 
1324 	message = ctrl_reqp->ctrl_data;
1325 
1326 	ASSERT(message != NULL);
1327 
1328 	bzero(&raw_descr, ROOT_HUB_DESCRIPTOR_LENGTH);
1329 
1330 	raw_descr[0] = root_hub_descr->bDescLength;
1331 	raw_descr[1] = root_hub_descr->bDescriptorType;
1332 	raw_descr[2] = root_hub_descr->bNbrPorts;
1333 	raw_descr[3] = root_hub_descr->wHubCharacteristics & 0x00FF;
1334 	raw_descr[4] = (root_hub_descr->wHubCharacteristics & 0xFF00) >> 8;
1335 	raw_descr[5] = root_hub_descr->bPwrOn2PwrGood;
1336 	raw_descr[6] = root_hub_descr->bHubContrCurrent;
1337 	raw_descr[7] = root_hub_descr->DeviceRemovable;
1338 	raw_descr[8] = root_hub_descr->PortPwrCtrlMask;
1339 
1340 	bcopy(raw_descr, message->b_wptr, length);
1341 	message->b_wptr += length;
1342 
1343 	/* Save the data in control request */
1344 	ctrl_reqp->ctrl_data = message;
1345 
1346 	mutex_exit(&ehcip->ehci_int_mutex);
1347 }
1348 
1349 
1350 /*
1351  * ehci_handle_get_hub_status:
1352  *
1353  * Handle a get hub status request.
1354  */
1355 static void
1356 ehci_handle_get_hub_status(
1357 	ehci_state_t		*ehcip)
1358 {
1359 	usb_ctrl_req_t		*ctrl_reqp;
1360 	mblk_t			*message;
1361 	uint_t			new_root_hub_status;
1362 
1363 	mutex_enter(&ehcip->ehci_int_mutex);
1364 
1365 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1366 
1367 	/*
1368 	 * For EHCI, there is no overall hub status information.
1369 	 * Only individual root hub port status information is
1370 	 * available. So return zero for the root hub status
1371 	 * request.
1372 	 */
1373 	new_root_hub_status = 0;
1374 
1375 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1376 	    "ehci_handle_get_hub_status: new root hub status = 0x%x",
1377 	    new_root_hub_status);
1378 
1379 	message = ctrl_reqp->ctrl_data;
1380 
1381 	ASSERT(message != NULL);
1382 
1383 	*message->b_wptr++ = (uchar_t)new_root_hub_status;
1384 	*message->b_wptr++ = (uchar_t)(new_root_hub_status >> 8);
1385 	*message->b_wptr++ = (uchar_t)(new_root_hub_status >> 16);
1386 	*message->b_wptr++ = (uchar_t)(new_root_hub_status >> 24);
1387 
1388 	/* Save the data in control request */
1389 	ctrl_reqp->ctrl_data = message;
1390 
1391 	mutex_exit(&ehcip->ehci_int_mutex);
1392 }
1393 
1394 
1395 /*
1396  * ehci_handle_get_device_status:
1397  *
1398  * Handle a get device status request.
1399  */
1400 static void
1401 ehci_handle_get_device_status(
1402 	ehci_state_t		*ehcip)
1403 {
1404 	usb_ctrl_req_t		*ctrl_reqp;
1405 	mblk_t			*message;
1406 	uint16_t		dev_status;
1407 
1408 	mutex_enter(&ehcip->ehci_int_mutex);
1409 
1410 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1411 
1412 	/*
1413 	 * For EHCI, there is no device status information.
1414 	 * Simply return what is desired for the request.
1415 	 */
1416 	dev_status = USB_DEV_SLF_PWRD_STATUS;
1417 
1418 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1419 	    "ehci_handle_get_device_status: device status = 0x%x",
1420 	    dev_status);
1421 
1422 	message = ctrl_reqp->ctrl_data;
1423 
1424 	ASSERT(message != NULL);
1425 
1426 	*message->b_wptr++ = (uchar_t)dev_status;
1427 	*message->b_wptr++ = (uchar_t)(dev_status >> 8);
1428 
1429 	/* Save the data in control request */
1430 	ctrl_reqp->ctrl_data = message;
1431 
1432 	mutex_exit(&ehcip->ehci_int_mutex);
1433 }
1434 
1435 
1436 /*
1437  * ehci_handle_root_hub_pipe_start_intr_polling:
1438  *
1439  * Handle start polling on root hub interrupt pipe.
1440  */
1441 /* ARGSUSED */
1442 int
1443 ehci_handle_root_hub_pipe_start_intr_polling(
1444 	usba_pipe_handle_data_t	*ph,
1445 	usb_intr_req_t		*client_intr_reqp,
1446 	usb_flags_t		flags)
1447 {
1448 	ehci_state_t		*ehcip = ehci_obtain_state(
1449 	    ph->p_usba_device->usb_root_hub_dip);
1450 	usb_ep_descr_t		*eptd = &ph->p_ep;
1451 	int			error = USB_SUCCESS;
1452 	uint_t			pipe_state;
1453 
1454 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1455 	    "ehci_handle_root_hub_pipe_start_intr_polling: "
1456 	    "Root hub pipe start polling");
1457 
1458 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1459 
1460 	ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1);
1461 
1462 	ASSERT((client_intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) == 0);
1463 
1464 	pipe_state = ehcip->ehci_root_hub.rh_intr_pipe_state;
1465 
1466 	switch (pipe_state) {
1467 	case EHCI_PIPE_STATE_IDLE:
1468 		ASSERT(ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0);
1469 
1470 		/*
1471 		 * Save the Original Client's Interrupt IN request
1472 		 * information. We use this for final callback
1473 		 */
1474 		ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp == NULL);
1475 		ehcip->ehci_root_hub.rh_client_intr_reqp = client_intr_reqp;
1476 
1477 		error = ehci_root_hub_allocate_intr_pipe_resource(ehcip, flags);
1478 
1479 		if (error != USB_SUCCESS) {
1480 			/* Reset client interrupt request pointer */
1481 			ehcip->ehci_root_hub.rh_client_intr_reqp = NULL;
1482 
1483 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1484 			    "ehci_handle_root_hub_pipe_start_intr_polling: "
1485 			    "No Resources");
1486 
1487 			return (error);
1488 		}
1489 
1490 		/* Check whether we need to send the reset data up */
1491 		if (ehcip->ehci_root_hub.rh_intr_pending_status) {
1492 			ehci_root_hub_reset_occured(ehcip);
1493 		}
1494 
1495 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1496 		    "ehci_handle_root_hub_pipe_start_intr_polling: "
1497 		    "Start polling for root hub successful");
1498 
1499 		break;
1500 	case EHCI_PIPE_STATE_ACTIVE:
1501 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1502 		    "ehci_handle_root_hub_pipe_start_intr_polling: "
1503 		    "Polling for root hub is already in progress");
1504 
1505 		break;
1506 	default:
1507 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1508 		    "ehci_handle_root_hub_pipe_start_intr_polling: "
1509 		    "Pipe is in error state 0x%x", pipe_state);
1510 
1511 		error = USB_FAILURE;
1512 
1513 		break;
1514 	}
1515 
1516 	return (error);
1517 }
1518 
1519 
1520 /*
1521  * ehci_handle_root_hub_pipe_stop_intr_polling:
1522  *
1523  * Handle stop polling on root hub intr pipe.
1524  */
1525 /* ARGSUSED */
1526 void
1527 ehci_handle_root_hub_pipe_stop_intr_polling(
1528 	usba_pipe_handle_data_t	*ph,
1529 	usb_flags_t		flags)
1530 {
1531 	ehci_state_t		*ehcip = ehci_obtain_state(
1532 	    ph->p_usba_device->usb_root_hub_dip);
1533 	usb_ep_descr_t		*eptd = &ph->p_ep;
1534 
1535 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1536 
1537 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1538 	    "ehci_handle_root_hub_pipe_stop_intr_polling: "
1539 	    "Root hub pipe stop polling");
1540 
1541 	ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1);
1542 
1543 	if (ehcip->ehci_root_hub.rh_intr_pipe_state ==
1544 	    EHCI_PIPE_STATE_ACTIVE) {
1545 
1546 		ehcip->ehci_root_hub.rh_intr_pipe_state =
1547 		    EHCI_PIPE_STATE_STOP_POLLING;
1548 
1549 		/* Do interrupt pipe cleanup */
1550 		ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_STOPPED_POLLING);
1551 
1552 		ASSERT(ehcip->ehci_root_hub.
1553 		    rh_intr_pipe_state == EHCI_PIPE_STATE_IDLE);
1554 
1555 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1556 		    "ehci_hcdi_pipe_stop_intr_polling: Stop polling for root"
1557 		    "hub successful");
1558 	} else {
1559 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB,
1560 		    ehcip->ehci_log_hdl, "ehci_hcdi_pipe_stop_intr_polling: "
1561 		    "Polling for root hub is already stopped");
1562 	}
1563 }
1564 
1565 
1566 /*
1567  * ehci_get_root_hub_port_status:
1568  *
1569  * Construct root hub port status and change information
1570  */
1571 static uint_t
1572 ehci_get_root_hub_port_status(
1573 	ehci_state_t		*ehcip,
1574 	uint16_t		port)
1575 {
1576 	uint_t			new_port_status = 0;
1577 	uint_t			change_status = 0;
1578 	uint_t			port_status;
1579 
1580 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1581 
1582 	/* Read the current port status */
1583 	port_status = Get_OpReg(ehci_rh_port_status[port]);
1584 
1585 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1586 	    "ehci_get_root_hub_port_status: port %d "
1587 	    "port status = 0x%x", port, port_status);
1588 
1589 	/*
1590 	 * EHCI root hub port status and control register information
1591 	 * format is different what Hub driver wants. So EHCI driver
1592 	 * needs to contruct the proper root hub port status information.
1593 	 *
1594 	 * Send all port status information only if port is owned by EHCI
1595 	 * host controller.
1596 	 */
1597 	if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_EHCI) {
1598 
1599 		/* First construct port change information */
1600 		if (port_status & EHCI_RH_PORT_ENABLE_CHANGE) {
1601 			change_status |= PORT_CHANGE_PESC;
1602 		}
1603 
1604 		if (port_status & EHCI_RH_PORT_RESUME) {
1605 			change_status |= PORT_CHANGE_PSSC;
1606 		}
1607 
1608 		if (port_status & EHCI_RH_PORT_OVER_CURR_CHANGE) {
1609 			change_status |= PORT_CHANGE_OCIC;
1610 		}
1611 
1612 		/* Now construct port status information */
1613 		if (port_status & EHCI_RH_PORT_CONNECT_STATUS) {
1614 			new_port_status |= PORT_STATUS_CCS;
1615 		}
1616 
1617 		if (port_status & EHCI_RH_PORT_ENABLE) {
1618 			new_port_status |=
1619 			    (PORT_STATUS_PES | PORT_STATUS_HSDA);
1620 		}
1621 
1622 		if (port_status & EHCI_RH_PORT_SUSPEND) {
1623 			new_port_status |= PORT_STATUS_PSS;
1624 		}
1625 
1626 		if (port_status & EHCI_RH_PORT_OVER_CURR_ACTIVE) {
1627 			new_port_status |= PORT_STATUS_POCI;
1628 		}
1629 
1630 		if (port_status & EHCI_RH_PORT_RESET) {
1631 			new_port_status |= PORT_STATUS_PRS;
1632 		}
1633 
1634 		if (port_status & EHCI_RH_PORT_INDICATOR) {
1635 			new_port_status |= PORT_STATUS_PIC;
1636 		}
1637 	}
1638 
1639 	/*
1640 	 * Send the following port status and change information
1641 	 * even if port is not owned by EHCI.
1642 	 *
1643 	 * Additional port change information.
1644 	 */
1645 	if (port_status & EHCI_RH_PORT_CONNECT_STS_CHANGE) {
1646 		change_status |= PORT_CHANGE_CSC;
1647 	}
1648 
1649 	/* Additional port status information */
1650 	if (port_status & EHCI_RH_PORT_POWER) {
1651 		new_port_status |= PORT_STATUS_PPS;
1652 	}
1653 
1654 	if ((!(port_status & EHCI_RH_PORT_ENABLE)) &&
1655 	    (port_status & EHCI_RH_PORT_LOW_SPEED)) {
1656 		new_port_status |= PORT_STATUS_LSDA;
1657 	}
1658 
1659 	/*
1660 	 * Construct complete root hub port status and change information.
1661 	 */
1662 	port_status = ((change_status << 16) | new_port_status);
1663 
1664 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1665 	    "ehci_get_root_hub_port_status: port = %d new status = 0x%x "
1666 	    "change status = 0x%x complete port status 0x%x", port,
1667 	    new_port_status, change_status, port_status);
1668 
1669 	return (port_status);
1670 }
1671 
1672 
1673 /*
1674  * ehci_is_port_owner:
1675  *
1676  * Check whether given port is owned by ehci.
1677  */
1678 static int
1679 ehci_is_port_owner(
1680 	ehci_state_t		*ehcip,
1681 	uint16_t		port)
1682 {
1683 	uint_t			port_status;
1684 
1685 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1686 
1687 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1688 	    ~EHCI_RH_PORT_CLEAR_MASK;
1689 
1690 	/*
1691 	 * Don't perform anything if port is owned by classis host
1692 	 * controller and return success.
1693 	 */
1694 	if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_CLASSIC) {
1695 
1696 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1697 		    "ehci_handle_set_clear_port_feature: "
1698 		    "Port %d is owned by classic host controller", port);
1699 
1700 		return (USB_FAILURE);
1701 	}
1702 
1703 	return (USB_SUCCESS);
1704 }
1705 
1706 
1707 /*
1708  * ehci_root_hub_allocate_intr_pipe_resource:
1709  *
1710  * Allocate interrupt requests and initialize them.
1711  */
1712 static int
1713 ehci_root_hub_allocate_intr_pipe_resource(
1714 	ehci_state_t		*ehcip,
1715 	usb_flags_t		flags)
1716 {
1717 	usba_pipe_handle_data_t	*ph;
1718 	size_t			length;
1719 	usb_intr_req_t		*curr_intr_reqp;
1720 
1721 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1722 	    "ehci_root_hub_allocate_intr_pipe_resource");
1723 
1724 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1725 
1726 	/* Get the interrupt pipe handle */
1727 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1728 
1729 	/* Get the current interrupt request pointer */
1730 	curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp;
1731 
1732 	/*
1733 	 * If current interrupt request pointer is null,
1734 	 * allocate new interrupt request.
1735 	 */
1736 	if (curr_intr_reqp == NULL) {
1737 		ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp);
1738 
1739 		/* Get the length of interrupt transfer */
1740 		length = ehcip->ehci_root_hub.
1741 		    rh_client_intr_reqp->intr_len;
1742 
1743 		curr_intr_reqp = usba_hcdi_dup_intr_req(ph->p_dip,
1744 		    ehcip->ehci_root_hub.rh_client_intr_reqp,
1745 		    length, flags);
1746 
1747 		if (curr_intr_reqp == NULL) {
1748 
1749 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1750 			    "ehci_root_hub_allocate_intr_pipe_resource:"
1751 			    "Interrupt request structure allocation failed");
1752 
1753 			return (USB_NO_RESOURCES);
1754 		}
1755 
1756 		ehcip->ehci_root_hub.rh_curr_intr_reqp = curr_intr_reqp;
1757 		mutex_enter(&ph->p_mutex);
1758 		ph->p_req_count++;
1759 		mutex_exit(&ph->p_mutex);
1760 	}
1761 
1762 	/* Start the timer for the root hub interrupt pipe polling */
1763 	if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0) {
1764 		ehcip->ehci_root_hub.rh_intr_pipe_timer_id =
1765 		    timeout(ehci_handle_root_hub_status_change,
1766 		    (void *)ehcip, drv_usectohz(EHCI_RH_POLL_TIME));
1767 
1768 		ehcip->ehci_root_hub.
1769 		    rh_intr_pipe_state = EHCI_PIPE_STATE_ACTIVE;
1770 	}
1771 
1772 	return (USB_SUCCESS);
1773 }
1774 
1775 
1776 /*
1777  * ehci_root_hub_intr_pipe_cleanup:
1778  *
1779  * Deallocate all interrupt requests and do callback
1780  * the original client interrupt request.
1781  */
1782 static void
1783 ehci_root_hub_intr_pipe_cleanup(
1784 	ehci_state_t		*ehcip,
1785 	usb_cr_t		completion_reason)
1786 {
1787 	usb_intr_req_t		*curr_intr_reqp;
1788 	usb_opaque_t		client_intr_reqp;
1789 	timeout_id_t		timer_id;
1790 	usba_pipe_handle_data_t	*ph;
1791 
1792 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1793 	    "ehci_root_hub_intr_pipe_cleanup");
1794 
1795 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1796 
1797 	/* Get the interrupt pipe handle */
1798 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1799 
1800 	/* Get the interrupt timerid */
1801 	timer_id = ehcip->ehci_root_hub.rh_intr_pipe_timer_id;
1802 
1803 	/* Stop the root hub interrupt timer */
1804 	if (timer_id) {
1805 		/* Reset the timer id to zero */
1806 		ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0;
1807 
1808 		mutex_exit(&ehcip->ehci_int_mutex);
1809 		(void) untimeout(timer_id);
1810 		mutex_enter(&ehcip->ehci_int_mutex);
1811 	}
1812 
1813 	/* Reset the current interrupt request pointer */
1814 	curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp;
1815 
1816 	/* Deallocate uncompleted interrupt request */
1817 	if (curr_intr_reqp) {
1818 		ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL;
1819 		usb_free_intr_req(curr_intr_reqp);
1820 
1821 		mutex_enter(&ph->p_mutex);
1822 		ph->p_req_count--;
1823 		mutex_exit(&ph->p_mutex);
1824 	}
1825 
1826 	client_intr_reqp = (usb_opaque_t)
1827 	    ehcip->ehci_root_hub.rh_client_intr_reqp;
1828 
1829 	/* Callback for original client interrupt request */
1830 	if (client_intr_reqp) {
1831 		ehci_root_hub_hcdi_callback(ph, completion_reason);
1832 	}
1833 }
1834 
1835 
1836 /*
1837  * ehci_handle_root_hub_status_change:
1838  *
1839  * A root hub status change interrupt will occur any time there is a change
1840  * in the root hub status register or one of the port status registers.
1841  */
1842 static void
1843 ehci_handle_root_hub_status_change(void *arg)
1844 {
1845 	ehci_state_t		*ehcip = (ehci_state_t *)arg;
1846 	usb_hub_descr_t		*root_hub_descr =
1847 	    &ehcip->ehci_root_hub.rh_descr;
1848 	usb_intr_req_t		*curr_intr_reqp;
1849 	usb_port_mask_t		port_mask = 0;
1850 	uint_t			new_port_status;
1851 	uint_t			change_status;
1852 	uint_t			port_status;
1853 	mblk_t			*message;
1854 	size_t			length;
1855 	usb_ep_descr_t		*eptd;
1856 	usba_pipe_handle_data_t	*ph;
1857 	int			i;
1858 
1859 	mutex_enter(&ehcip->ehci_int_mutex);
1860 
1861 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1862 	    "ehci_handle_root_hub_status_change: state = %d",
1863 	    ehcip->ehci_root_hub.rh_intr_pipe_state);
1864 
1865 #if defined(__x86)
1866 	/*
1867 	 * When ohci are attached in ferrari 4000, SMI will reset ehci
1868 	 * registers. If ehci registers have been reset, we must re-initialize
1869 	 * them. During booting, this function will be called 2~3 times. When
1870 	 * this function is called 16 times, ohci drivers have been attached
1871 	 * and stop checking the ehci registers.
1872 	 */
1873 	if (ehcip->ehci_polled_root_hub_count < 16) {
1874 
1875 		if (Get_OpReg(ehci_config_flag) == 0) {
1876 
1877 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB,
1878 			    ehcip->ehci_log_hdl,
1879 			    "ehci_handle_root_hub_status_change:"
1880 			    " EHCI have been reset");
1881 
1882 			/* Reinitialize the controller */
1883 			if (ehci_init_ctlr(ehcip, EHCI_REINITIALIZATION) !=
1884 			    DDI_SUCCESS) {
1885 				mutex_exit(&ehcip->ehci_int_mutex);
1886 
1887 				return;
1888 			}
1889 		}
1890 
1891 		ehcip->ehci_polled_root_hub_count++;
1892 	}
1893 #endif	/* __x86 */
1894 
1895 	/* Get the current interrupt request pointer */
1896 	curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp;
1897 
1898 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1899 
1900 	/* Check whether timeout handler is valid */
1901 	if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id) {
1902 		/* Check host controller is in operational state */
1903 		if ((ehci_state_is_operational(ehcip)) != USB_SUCCESS) {
1904 			/* Reset the timer id */
1905 			ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0;
1906 
1907 			/* Do interrupt pipe cleanup */
1908 			ehci_root_hub_intr_pipe_cleanup(
1909 			    ehcip, USB_CR_HC_HARDWARE_ERR);
1910 
1911 			mutex_exit(&ehcip->ehci_int_mutex);
1912 
1913 			return;
1914 		}
1915 	} else {
1916 		mutex_exit(&ehcip->ehci_int_mutex);
1917 
1918 		return;
1919 	}
1920 
1921 	eptd = &ehcip->ehci_root_hub.rh_intr_pipe_handle->p_ep;
1922 
1923 	/* Check each port */
1924 	for (i = 0; i < root_hub_descr->bNbrPorts; i++) {
1925 
1926 		port_status = ehci_get_root_hub_port_status(ehcip, i);
1927 
1928 		new_port_status = port_status & PORT_STATUS_MASK;
1929 		change_status = (port_status >> 16) & PORT_CHANGE_MASK;
1930 
1931 		/*
1932 		 * If there is change in the port status then set the bit in the
1933 		 * bitmap of changes and inform hub driver about these changes.
1934 		 * Hub driver will take care of these changes.
1935 		 */
1936 		if (change_status) {
1937 
1938 			/* See if a device was attached/detached */
1939 			if (change_status & PORT_CHANGE_CSC) {
1940 				/*
1941 				 * Update the state depending on whether
1942 				 * the port was attached or detached.
1943 				 */
1944 				if (new_port_status & PORT_STATUS_CCS) {
1945 					ehcip->ehci_root_hub.
1946 					    rh_port_state[i] = DISABLED;
1947 
1948 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1949 					    ehcip->ehci_log_hdl,
1950 					    "Port %d connected", i+1);
1951 				} else {
1952 					ehcip->ehci_root_hub.
1953 					    rh_port_state[i] = DISCONNECTED;
1954 
1955 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1956 					    ehcip->ehci_log_hdl,
1957 					    "Port %d disconnected", i+1);
1958 				}
1959 			}
1960 
1961 			/* See if port enable status changed */
1962 			if (change_status & PORT_CHANGE_PESC) {
1963 				/*
1964 				 * Update the state depending on whether
1965 				 * the port was enabled or disabled.
1966 				 */
1967 				if (new_port_status & PORT_STATUS_PES) {
1968 					ehcip->ehci_root_hub.
1969 					    rh_port_state[i] = ENABLED;
1970 
1971 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1972 					    ehcip->ehci_log_hdl,
1973 					    "Port %d enabled", i+1);
1974 				} else {
1975 					ehcip->ehci_root_hub.
1976 					    rh_port_state[i] = DISABLED;
1977 
1978 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1979 					    ehcip->ehci_log_hdl,
1980 					    "Port %d disabled", i+1);
1981 				}
1982 			}
1983 
1984 			port_mask |= 1 << (i + 1);
1985 
1986 			/* Update the status */
1987 			ehcip->ehci_root_hub.
1988 			    rh_port_status[i] = new_port_status;
1989 		}
1990 	}
1991 
1992 	if (ph && port_mask && curr_intr_reqp) {
1993 		length = eptd->wMaxPacketSize;
1994 
1995 		ASSERT(length != 0);
1996 
1997 		/* Get the  message block */
1998 		message = curr_intr_reqp->intr_data;
1999 
2000 		ASSERT(message != NULL);
2001 
2002 		do {
2003 			/*
2004 			 * check that the mblk is big enough when we
2005 			 * are writing bytes into it
2006 			 */
2007 			if (message->b_wptr >= message->b_datap->db_lim) {
2008 
2009 				USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB,
2010 				    ehcip->ehci_log_hdl,
2011 				    "ehci_handle_root_hub_status_change"
2012 				    "mblk data overflow.");
2013 
2014 				break;
2015 			}
2016 			*message->b_wptr++ = (uchar_t)port_mask;
2017 			port_mask >>= 8;
2018 		} while (port_mask != 0);
2019 
2020 		ehci_root_hub_hcdi_callback(ph, USB_CR_OK);
2021 	}
2022 
2023 	/* Reset the timer id */
2024 	ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0;
2025 
2026 	if (ehcip->ehci_root_hub.rh_intr_pipe_state ==
2027 	    EHCI_PIPE_STATE_ACTIVE) {
2028 		/*
2029 		 * If needed, allocate new interrupt request. Also
2030 		 * start the timer for the root hub interrupt polling.
2031 		 */
2032 		if ((ehci_root_hub_allocate_intr_pipe_resource(
2033 		    ehcip, 0)) != USB_SUCCESS) {
2034 
2035 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
2036 			    "ehci_handle_root_hub_status_change: No Resources");
2037 
2038 			/* Do interrupt pipe cleanup */
2039 			ehci_root_hub_intr_pipe_cleanup(
2040 			    ehcip, USB_CR_NO_RESOURCES);
2041 		}
2042 	}
2043 
2044 	mutex_exit(&ehcip->ehci_int_mutex);
2045 }
2046 
2047 
2048 /*
2049  * ehci_root_hub_hcdi_callback()
2050  *
2051  * Convenience wrapper around usba_hcdi_cb() for the root hub.
2052  */
2053 static void
2054 ehci_root_hub_hcdi_callback(
2055 	usba_pipe_handle_data_t	*ph,
2056 	usb_cr_t		completion_reason)
2057 {
2058 	ehci_state_t		*ehcip = ehci_obtain_state(
2059 	    ph->p_usba_device->usb_root_hub_dip);
2060 	uchar_t			attributes = ph->p_ep.bmAttributes &
2061 	    USB_EP_ATTR_MASK;
2062 	usb_opaque_t		curr_xfer_reqp;
2063 	uint_t			pipe_state = 0;
2064 
2065 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
2066 	    "ehci_root_hub_hcdi_callback: ph = 0x%p, cr = 0x%x",
2067 	    (void *)ph, completion_reason);
2068 
2069 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
2070 
2071 	/* Set the pipe state as per completion reason */
2072 	switch (completion_reason) {
2073 	case USB_CR_OK:
2074 		switch (attributes) {
2075 		case USB_EP_ATTR_CONTROL:
2076 			pipe_state = EHCI_PIPE_STATE_IDLE;
2077 			break;
2078 		case USB_EP_ATTR_INTR:
2079 			pipe_state = ehcip->ehci_root_hub.
2080 			    rh_intr_pipe_state;
2081 			break;
2082 		}
2083 		break;
2084 	case USB_CR_NO_RESOURCES:
2085 	case USB_CR_NOT_SUPPORTED:
2086 	case USB_CR_STOPPED_POLLING:
2087 	case USB_CR_PIPE_RESET:
2088 	case USB_CR_HC_HARDWARE_ERR:
2089 		/* Set pipe state to idle */
2090 		pipe_state = EHCI_PIPE_STATE_IDLE;
2091 		break;
2092 	case USB_CR_PIPE_CLOSING:
2093 		break;
2094 	default:
2095 		/* Set pipe state to error */
2096 		pipe_state = EHCI_PIPE_STATE_ERROR;
2097 		break;
2098 	}
2099 
2100 	switch (attributes) {
2101 	case USB_EP_ATTR_CONTROL:
2102 		curr_xfer_reqp = (usb_opaque_t)
2103 		    ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
2104 
2105 		ehcip->ehci_root_hub.rh_curr_ctrl_reqp = NULL;
2106 		ehcip->ehci_root_hub.rh_ctrl_pipe_state = pipe_state;
2107 		break;
2108 	case USB_EP_ATTR_INTR:
2109 		/* if curr_intr_reqp available then use this request */
2110 		if (ehcip->ehci_root_hub.rh_curr_intr_reqp) {
2111 			curr_xfer_reqp = (usb_opaque_t)ehcip->
2112 			    ehci_root_hub.rh_curr_intr_reqp;
2113 
2114 			ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL;
2115 		} else {
2116 			/* no current request, use client's request */
2117 			curr_xfer_reqp = (usb_opaque_t)
2118 			    ehcip->ehci_root_hub.rh_client_intr_reqp;
2119 
2120 			ehcip->ehci_root_hub.rh_client_intr_reqp = NULL;
2121 		}
2122 		ehcip->ehci_root_hub.rh_intr_pipe_state = pipe_state;
2123 		break;
2124 	}
2125 
2126 	ASSERT(curr_xfer_reqp != NULL);
2127 
2128 	mutex_exit(&ehcip->ehci_int_mutex);
2129 	usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason);
2130 	mutex_enter(&ehcip->ehci_int_mutex);
2131 }
2132