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 2008 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 
909 	mutex_enter(&ehcip->ehci_int_mutex);
910 
911 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
912 	    ~EHCI_RH_PORT_CLEAR_MASK;
913 
914 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
915 	    "ehci_handle_clrchng_port_suspend: port = 0x%x, "
916 	    "status = 0x%x", port, port_status);
917 
918 	/* Check port is owned by ehci */
919 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
920 		mutex_exit(&ehcip->ehci_int_mutex);
921 
922 		return;
923 	}
924 
925 	/* Return if port is not in resume state */
926 	if (!(port_status & EHCI_RH_PORT_RESUME)) {
927 		mutex_exit(&ehcip->ehci_int_mutex);
928 
929 		return;
930 	}
931 
932 	mutex_exit(&ehcip->ehci_int_mutex);
933 
934 	/* Wait for 20ms to terminate resume */
935 	delay(drv_usectohz(EHCI_PORT_RESUME_TIMEWAIT));
936 
937 	mutex_enter(&ehcip->ehci_int_mutex);
938 
939 	Set_OpReg(ehci_rh_port_status[port],
940 	    port_status & ~EHCI_RH_PORT_RESUME);
941 
942 	mutex_exit(&ehcip->ehci_int_mutex);
943 
944 	/* Wait 2ms for port to return to high speed mode */
945 	delay(drv_usectohz(EHCI_PORT_RESUME_COMP_TIMEWAIT));
946 }
947 
948 
949 /*
950  * ehci_handle_port_reset:
951  *
952  * Perform a port reset.
953  */
954 static void
955 ehci_handle_port_reset(
956 	ehci_state_t		*ehcip,
957 	uint16_t		port)
958 {
959 	ehci_root_hub_t		*rh;
960 	uint_t			port_status;
961 
962 	mutex_enter(&ehcip->ehci_int_mutex);
963 
964 	/* Get the root hub structure */
965 	rh = &ehcip->ehci_root_hub;
966 
967 	/* Get the port status information */
968 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
969 	    ~EHCI_RH_PORT_CLEAR_MASK;
970 
971 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
972 	    "ehci_handle_port_reset: port = 0x%x status = 0x%x",
973 	    port, port_status);
974 
975 	/* Check port is owned by ehci */
976 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
977 		mutex_exit(&ehcip->ehci_int_mutex);
978 
979 		return;
980 	}
981 
982 	if (port_status & EHCI_RH_PORT_LOW_SPEED) {
983 		/* Check for classic or companion host controllers */
984 		if (rh->rh_companion_controllers) {
985 			USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
986 			    "ehci_handle_port_reset: Low speed device "
987 			    "and handover this port to Companion controller");
988 
989 			Set_OpReg(ehci_rh_port_status[port],
990 			    port_status | EHCI_RH_PORT_OWNER_CLASSIC);
991 		} else {
992 			USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
993 			    "Low speed device is not supported");
994 		}
995 	} else {
996 		Set_OpReg(ehci_rh_port_status[port],
997 		    ((port_status | EHCI_RH_PORT_RESET) &
998 		    ~EHCI_RH_PORT_ENABLE));
999 
1000 		mutex_exit(&ehcip->ehci_int_mutex);
1001 
1002 		/* Wait 20ms for reset to complete */
1003 		delay(drv_usectohz(EHCI_PORT_RESET_TIMEWAIT));
1004 
1005 		mutex_enter(&ehcip->ehci_int_mutex);
1006 
1007 		port_status = Get_OpReg(ehci_rh_port_status[port]) &
1008 		    ~EHCI_RH_PORT_CLEAR_MASK;
1009 
1010 		Set_OpReg(ehci_rh_port_status[port],
1011 		    (port_status & ~EHCI_RH_PORT_RESET));
1012 
1013 		mutex_exit(&ehcip->ehci_int_mutex);
1014 
1015 		/*
1016 		 * Wait 2ms for hardware to enable this port
1017 		 * if connected usb device is high speed.
1018 		 */
1019 		delay(drv_usectohz(EHCI_PORT_RESET_COMP_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 		/*
1027 		 * If port is not enabled, connected device is a
1028 		 * Full-speed usb device.
1029 		 */
1030 		if (!(port_status & EHCI_RH_PORT_ENABLE)) {
1031 			/* Check for classic or companion host controllers */
1032 			if (rh->rh_companion_controllers) {
1033 				USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1034 				    ehcip->ehci_log_hdl,
1035 				    "ehci_handle_port_reset: Full speed device "
1036 				    "and handover this port to Companion host "
1037 				    "controller");
1038 
1039 				Set_OpReg(ehci_rh_port_status[port],
1040 				    port_status | EHCI_RH_PORT_OWNER_CLASSIC);
1041 			} else {
1042 				USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB,
1043 				    ehcip->ehci_log_hdl,
1044 				    "Full speed device is not supported");
1045 			}
1046 		} else {
1047 			USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1048 			    "ehci_handle_port_reset: High speed device ");
1049 
1050 			port_status = Get_OpReg(ehci_rh_port_status[port]) &
1051 			    ~EHCI_RH_PORT_CLEAR_MASK;
1052 
1053 			/*
1054 			 * Enable over-current, connect, and disconnect
1055 			 * wakeup bits.
1056 			 */
1057 			Set_OpReg(ehci_rh_port_status[port], (port_status |
1058 			    EHCI_RH_PORT_OVER_CURENT_ENABLE |
1059 			    EHCI_RH_PORT_DISCONNECT_ENABLE |
1060 			    EHCI_RH_PORT_CONNECT_ENABLE));
1061 
1062 			/*
1063 			 * The next function is only called if the interrupt
1064 			 * pipe is polling and the USBA is ready to receive
1065 			 * the data.
1066 			 */
1067 			ehcip->ehci_root_hub.
1068 			    rh_intr_pending_status |= (1 << port);
1069 
1070 			if (ehcip->ehci_root_hub.
1071 			    rh_intr_pipe_state == EHCI_PIPE_STATE_ACTIVE) {
1072 
1073 				ehci_root_hub_reset_occured(ehcip);
1074 			}
1075 		}
1076 	}
1077 
1078 	mutex_exit(&ehcip->ehci_int_mutex);
1079 }
1080 
1081 
1082 /*
1083  * ehci_root_hub_reset_occured:
1084  *
1085  * Inform the upper layer that reset has occured on the port. This is
1086  * required because the upper layer is expecting a an evernt immidiately
1087  * after doing reset. In case of OHCI, the controller gets an interrupt
1088  * for the change in the root hub status but in case of EHCI, we dont.
1089  * So, send a event to the upper layer as soon as we complete the reset.
1090  */
1091 void
1092 ehci_root_hub_reset_occured(
1093 	ehci_state_t		*ehcip)
1094 {
1095 	usb_intr_req_t		*curr_intr_reqp =
1096 	    ehcip->ehci_root_hub.rh_curr_intr_reqp;
1097 	usb_port_mask_t		port_mask;
1098 	usba_pipe_handle_data_t	*ph;
1099 
1100 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1101 	    "ehci_root_hub_reset_occured: curr_intr_reqp = 0x%p data = 0x%p",
1102 	    (void *)curr_intr_reqp, (void *)curr_intr_reqp->intr_data);
1103 
1104 	/* Get the interrupt pipe handle */
1105 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1106 
1107 	/* Get the pending status */
1108 	port_mask = ehcip->ehci_root_hub.rh_intr_pending_status << 1;
1109 
1110 	do {
1111 		*curr_intr_reqp->intr_data->b_wptr++ = (uchar_t)port_mask;
1112 		port_mask >>= 8;
1113 	} while (port_mask != 0);
1114 
1115 	ehci_root_hub_hcdi_callback(ph, USB_CR_OK);
1116 
1117 	/* Reset pending status */
1118 	ehcip->ehci_root_hub.rh_intr_pending_status = 0;
1119 
1120 	/* If needed, allocate new interrupt request */
1121 	if ((ehci_root_hub_allocate_intr_pipe_resource(
1122 	    ehcip, 0)) != USB_SUCCESS) {
1123 
1124 		/* Do interrupt pipe cleanup */
1125 		ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_NO_RESOURCES);
1126 	}
1127 }
1128 
1129 
1130 /*
1131  * ehci_handle_complete_port_reset:
1132  *
1133  * Perform a port reset change.
1134  */
1135 static void
1136 ehci_handle_complete_port_reset(
1137 	ehci_state_t		*ehcip,
1138 	uint16_t		port)
1139 {
1140 	uint_t			port_status;
1141 
1142 	mutex_enter(&ehcip->ehci_int_mutex);
1143 
1144 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1145 	    ~EHCI_RH_PORT_CLEAR_MASK;
1146 
1147 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1148 	    "ehci_handle_complete_port_reset: port = 0x%x status = 0x%x",
1149 	    port, port_status);
1150 
1151 	/* Check port is owned by ehci */
1152 	if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) {
1153 		mutex_exit(&ehcip->ehci_int_mutex);
1154 
1155 		return;
1156 	}
1157 
1158 	if (port_status & EHCI_RH_PORT_RESET) {
1159 		Set_OpReg(ehci_rh_port_status[port],
1160 		    port_status & ~EHCI_RH_PORT_RESET);
1161 
1162 	}
1163 
1164 	mutex_exit(&ehcip->ehci_int_mutex);
1165 }
1166 
1167 
1168 /*
1169  * ehci_handle_clear_port_connection:
1170  *
1171  * Perform a clear port connection.
1172  */
1173 static void
1174 ehci_handle_clear_port_connection(
1175 	ehci_state_t		*ehcip,
1176 	uint16_t		port)
1177 {
1178 	uint_t			port_status;
1179 
1180 	mutex_enter(&ehcip->ehci_int_mutex);
1181 
1182 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1183 	    ~EHCI_RH_PORT_CLEAR_MASK;
1184 
1185 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1186 	    "ehci_handle_clear_port_connection: port = 0x%x"
1187 	    "status = 0x%x", port, port_status);
1188 
1189 	Set_OpReg(ehci_rh_port_status[port],
1190 	    port_status | EHCI_RH_PORT_CONNECT_STS_CHANGE);
1191 
1192 	mutex_exit(&ehcip->ehci_int_mutex);
1193 }
1194 
1195 
1196 /*
1197  * ehci_handle_clrchng_port_over_current:
1198  *
1199  * Perform a clear port connection.
1200  */
1201 static void
1202 ehci_handle_clrchng_port_over_current(
1203 	ehci_state_t		*ehcip,
1204 	uint16_t		port)
1205 {
1206 	uint_t			port_status;
1207 
1208 	mutex_enter(&ehcip->ehci_int_mutex);
1209 
1210 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1211 	    ~EHCI_RH_PORT_CLEAR_MASK;
1212 
1213 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1214 	    "ehci_handle_clrchng_port_over_current: port = 0x%x"
1215 	    "status = 0x%x", port, port_status);
1216 
1217 	Set_OpReg(ehci_rh_port_status[port],
1218 	    port_status | EHCI_RH_PORT_OVER_CURR_CHANGE);
1219 
1220 	mutex_exit(&ehcip->ehci_int_mutex);
1221 }
1222 
1223 
1224 /*
1225  * ehci_handle_get_port_status:
1226  *
1227  * Handle a get port status request.
1228  */
1229 static void
1230 ehci_handle_get_port_status(
1231 	ehci_state_t		*ehcip,
1232 	uint16_t		port)
1233 {
1234 	usb_ctrl_req_t		*ctrl_reqp;
1235 	mblk_t			*message;
1236 	uint_t			new_port_status = 0;
1237 	uint_t			change_status = 0;
1238 	uint_t			port_status;
1239 
1240 	mutex_enter(&ehcip->ehci_int_mutex);
1241 
1242 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1243 
1244 	/* Get the root hub port status information */
1245 	port_status = ehci_get_root_hub_port_status(ehcip, port);
1246 
1247 	new_port_status = port_status & PORT_STATUS_MASK;
1248 	change_status = (port_status >> 16) & PORT_CHANGE_MASK;
1249 
1250 	ehcip->ehci_root_hub.rh_port_status[port] = new_port_status;
1251 
1252 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1253 	    "ehci_handle_get_port_status: port = %d new status = 0x%x"
1254 	    "change = 0x%x", port, new_port_status, change_status);
1255 
1256 	message = ctrl_reqp->ctrl_data;
1257 
1258 	ASSERT(message != NULL);
1259 
1260 	*message->b_wptr++ = (uchar_t)new_port_status;
1261 	*message->b_wptr++ = (uchar_t)(new_port_status >> 8);
1262 	*message->b_wptr++ = (uchar_t)change_status;
1263 	*message->b_wptr++ = (uchar_t)(change_status >> 8);
1264 
1265 	/* Save the data in control request */
1266 	ctrl_reqp->ctrl_data = message;
1267 
1268 	mutex_exit(&ehcip->ehci_int_mutex);
1269 }
1270 
1271 
1272 /*
1273  * ehci_handle_get_hub_descriptor:
1274  */
1275 static void
1276 ehci_handle_get_hub_descriptor(
1277 	ehci_state_t		*ehcip)
1278 {
1279 	usb_ctrl_req_t		*ctrl_reqp;
1280 	mblk_t			*message;
1281 	usb_hub_descr_t		*root_hub_descr;
1282 	size_t			length;
1283 	uchar_t			raw_descr[ROOT_HUB_DESCRIPTOR_LENGTH];
1284 
1285 	mutex_enter(&ehcip->ehci_int_mutex);
1286 
1287 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1288 	root_hub_descr = &ehcip->ehci_root_hub.rh_descr;
1289 	length = ctrl_reqp->ctrl_wLength;
1290 
1291 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1292 	    "ehci_handle_get_hub_descriptor: Ctrl Req  = 0x%p",
1293 	    (void *)ctrl_reqp);
1294 
1295 	message = ctrl_reqp->ctrl_data;
1296 
1297 	ASSERT(message != NULL);
1298 
1299 	bzero(&raw_descr, ROOT_HUB_DESCRIPTOR_LENGTH);
1300 
1301 	raw_descr[0] = root_hub_descr->bDescLength;
1302 	raw_descr[1] = root_hub_descr->bDescriptorType;
1303 	raw_descr[2] = root_hub_descr->bNbrPorts;
1304 	raw_descr[3] = root_hub_descr->wHubCharacteristics & 0x00FF;
1305 	raw_descr[4] = (root_hub_descr->wHubCharacteristics & 0xFF00) >> 8;
1306 	raw_descr[5] = root_hub_descr->bPwrOn2PwrGood;
1307 	raw_descr[6] = root_hub_descr->bHubContrCurrent;
1308 	raw_descr[7] = root_hub_descr->DeviceRemovable;
1309 	raw_descr[8] = root_hub_descr->PortPwrCtrlMask;
1310 
1311 	bcopy(raw_descr, message->b_wptr, length);
1312 	message->b_wptr += length;
1313 
1314 	/* Save the data in control request */
1315 	ctrl_reqp->ctrl_data = message;
1316 
1317 	mutex_exit(&ehcip->ehci_int_mutex);
1318 }
1319 
1320 
1321 /*
1322  * ehci_handle_get_hub_status:
1323  *
1324  * Handle a get hub status request.
1325  */
1326 static void
1327 ehci_handle_get_hub_status(
1328 	ehci_state_t		*ehcip)
1329 {
1330 	usb_ctrl_req_t		*ctrl_reqp;
1331 	mblk_t			*message;
1332 	uint_t			new_root_hub_status;
1333 
1334 	mutex_enter(&ehcip->ehci_int_mutex);
1335 
1336 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1337 
1338 	/*
1339 	 * For EHCI, there is no overall hub status information.
1340 	 * Only individual root hub port status information is
1341 	 * available. So return zero for the root hub status
1342 	 * request.
1343 	 */
1344 	new_root_hub_status = 0;
1345 
1346 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1347 	    "ehci_handle_get_hub_status: new root hub status = 0x%x",
1348 	    new_root_hub_status);
1349 
1350 	message = ctrl_reqp->ctrl_data;
1351 
1352 	ASSERT(message != NULL);
1353 
1354 	*message->b_wptr++ = (uchar_t)new_root_hub_status;
1355 	*message->b_wptr++ = (uchar_t)(new_root_hub_status >> 8);
1356 	*message->b_wptr++ = (uchar_t)(new_root_hub_status >> 16);
1357 	*message->b_wptr++ = (uchar_t)(new_root_hub_status >> 24);
1358 
1359 	/* Save the data in control request */
1360 	ctrl_reqp->ctrl_data = message;
1361 
1362 	mutex_exit(&ehcip->ehci_int_mutex);
1363 }
1364 
1365 
1366 /*
1367  * ehci_handle_get_device_status:
1368  *
1369  * Handle a get device status request.
1370  */
1371 static void
1372 ehci_handle_get_device_status(
1373 	ehci_state_t		*ehcip)
1374 {
1375 	usb_ctrl_req_t		*ctrl_reqp;
1376 	mblk_t			*message;
1377 	uint16_t		dev_status;
1378 
1379 	mutex_enter(&ehcip->ehci_int_mutex);
1380 
1381 	ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
1382 
1383 	/*
1384 	 * For EHCI, there is no device status information.
1385 	 * Simply return what is desired for the request.
1386 	 */
1387 	dev_status = USB_DEV_SLF_PWRD_STATUS;
1388 
1389 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1390 	    "ehci_handle_get_device_status: device status = 0x%x",
1391 	    dev_status);
1392 
1393 	message = ctrl_reqp->ctrl_data;
1394 
1395 	ASSERT(message != NULL);
1396 
1397 	*message->b_wptr++ = (uchar_t)dev_status;
1398 	*message->b_wptr++ = (uchar_t)(dev_status >> 8);
1399 
1400 	/* Save the data in control request */
1401 	ctrl_reqp->ctrl_data = message;
1402 
1403 	mutex_exit(&ehcip->ehci_int_mutex);
1404 }
1405 
1406 
1407 /*
1408  * ehci_handle_root_hub_pipe_start_intr_polling:
1409  *
1410  * Handle start polling on root hub interrupt pipe.
1411  */
1412 /* ARGSUSED */
1413 int
1414 ehci_handle_root_hub_pipe_start_intr_polling(
1415 	usba_pipe_handle_data_t	*ph,
1416 	usb_intr_req_t		*client_intr_reqp,
1417 	usb_flags_t		flags)
1418 {
1419 	ehci_state_t		*ehcip = ehci_obtain_state(
1420 	    ph->p_usba_device->usb_root_hub_dip);
1421 	usb_ep_descr_t		*eptd = &ph->p_ep;
1422 	int			error = USB_SUCCESS;
1423 	uint_t			pipe_state;
1424 
1425 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1426 	    "ehci_handle_root_hub_pipe_start_intr_polling: "
1427 	    "Root hub pipe start polling");
1428 
1429 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1430 
1431 	ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1);
1432 
1433 	ASSERT((client_intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) == 0);
1434 
1435 	pipe_state = ehcip->ehci_root_hub.rh_intr_pipe_state;
1436 
1437 	switch (pipe_state) {
1438 	case EHCI_PIPE_STATE_IDLE:
1439 		ASSERT(ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0);
1440 
1441 		/*
1442 		 * Save the Original Client's Interrupt IN request
1443 		 * information. We use this for final callback
1444 		 */
1445 		ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp == NULL);
1446 		ehcip->ehci_root_hub.rh_client_intr_reqp = client_intr_reqp;
1447 
1448 		error = ehci_root_hub_allocate_intr_pipe_resource(ehcip, flags);
1449 
1450 		if (error != USB_SUCCESS) {
1451 			/* Reset client interrupt request pointer */
1452 			ehcip->ehci_root_hub.rh_client_intr_reqp = NULL;
1453 
1454 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1455 			    "ehci_handle_root_hub_pipe_start_intr_polling: "
1456 			    "No Resources");
1457 
1458 			return (error);
1459 		}
1460 
1461 		/* Check whether we need to send the reset data up */
1462 		if (ehcip->ehci_root_hub.rh_intr_pending_status) {
1463 			ehci_root_hub_reset_occured(ehcip);
1464 		}
1465 
1466 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1467 		    "ehci_handle_root_hub_pipe_start_intr_polling: "
1468 		    "Start polling for root hub successful");
1469 
1470 		break;
1471 	case EHCI_PIPE_STATE_ACTIVE:
1472 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1473 		    "ehci_handle_root_hub_pipe_start_intr_polling: "
1474 		    "Polling for root hub is already in progress");
1475 
1476 		break;
1477 	default:
1478 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1479 		    "ehci_handle_root_hub_pipe_start_intr_polling: "
1480 		    "Pipe is in error state 0x%x", pipe_state);
1481 
1482 		error = USB_FAILURE;
1483 
1484 		break;
1485 	}
1486 
1487 	return (error);
1488 }
1489 
1490 
1491 /*
1492  * ehci_handle_root_hub_pipe_stop_intr_polling:
1493  *
1494  * Handle stop polling on root hub intr pipe.
1495  */
1496 /* ARGSUSED */
1497 void
1498 ehci_handle_root_hub_pipe_stop_intr_polling(
1499 	usba_pipe_handle_data_t	*ph,
1500 	usb_flags_t		flags)
1501 {
1502 	ehci_state_t		*ehcip = ehci_obtain_state(
1503 	    ph->p_usba_device->usb_root_hub_dip);
1504 	usb_ep_descr_t		*eptd = &ph->p_ep;
1505 
1506 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1507 
1508 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1509 	    "ehci_handle_root_hub_pipe_stop_intr_polling: "
1510 	    "Root hub pipe stop polling");
1511 
1512 	ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1);
1513 
1514 	if (ehcip->ehci_root_hub.rh_intr_pipe_state ==
1515 	    EHCI_PIPE_STATE_ACTIVE) {
1516 
1517 		ehcip->ehci_root_hub.rh_intr_pipe_state =
1518 		    EHCI_PIPE_STATE_STOP_POLLING;
1519 
1520 		/* Do interrupt pipe cleanup */
1521 		ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_STOPPED_POLLING);
1522 
1523 		ASSERT(ehcip->ehci_root_hub.
1524 		    rh_intr_pipe_state == EHCI_PIPE_STATE_IDLE);
1525 
1526 		USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1527 		    "ehci_hcdi_pipe_stop_intr_polling: Stop polling for root"
1528 		    "hub successful");
1529 	} else {
1530 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB,
1531 		    ehcip->ehci_log_hdl, "ehci_hcdi_pipe_stop_intr_polling: "
1532 		    "Polling for root hub is already stopped");
1533 	}
1534 }
1535 
1536 
1537 /*
1538  * ehci_get_root_hub_port_status:
1539  *
1540  * Construct root hub port status and change information
1541  */
1542 static uint_t
1543 ehci_get_root_hub_port_status(
1544 	ehci_state_t		*ehcip,
1545 	uint16_t		port)
1546 {
1547 	uint_t			new_port_status = 0;
1548 	uint_t			change_status = 0;
1549 	uint_t			port_status;
1550 
1551 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1552 
1553 	/* Read the current port status */
1554 	port_status = Get_OpReg(ehci_rh_port_status[port]);
1555 
1556 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1557 	    "ehci_get_root_hub_port_status: port %d "
1558 	    "port status = 0x%x", port, port_status);
1559 
1560 	/*
1561 	 * EHCI root hub port status and control register information
1562 	 * format is different what Hub driver wants. So EHCI driver
1563 	 * needs to contruct the proper root hub port status information.
1564 	 *
1565 	 * Send all port status information only if port is owned by EHCI
1566 	 * host controller.
1567 	 */
1568 	if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_EHCI) {
1569 
1570 		/* First construct port change information */
1571 		if (port_status & EHCI_RH_PORT_ENABLE_CHANGE) {
1572 			change_status |= PORT_CHANGE_PESC;
1573 		}
1574 
1575 		if (port_status & EHCI_RH_PORT_RESUME) {
1576 			change_status |= PORT_CHANGE_PSSC;
1577 		}
1578 
1579 		if (port_status & EHCI_RH_PORT_OVER_CURR_CHANGE) {
1580 			change_status |= PORT_CHANGE_OCIC;
1581 		}
1582 
1583 		/* Now construct port status information */
1584 		if (port_status & EHCI_RH_PORT_CONNECT_STATUS) {
1585 			new_port_status |= PORT_STATUS_CCS;
1586 		}
1587 
1588 		if (port_status & EHCI_RH_PORT_ENABLE) {
1589 			new_port_status |=
1590 			    (PORT_STATUS_PES | PORT_STATUS_HSDA);
1591 		}
1592 
1593 		if (port_status & EHCI_RH_PORT_SUSPEND) {
1594 			new_port_status |= PORT_STATUS_PSS;
1595 		}
1596 
1597 		if (port_status & EHCI_RH_PORT_OVER_CURR_ACTIVE) {
1598 			new_port_status |= PORT_STATUS_POCI;
1599 		}
1600 
1601 		if (port_status & EHCI_RH_PORT_RESET) {
1602 			new_port_status |= PORT_STATUS_PRS;
1603 		}
1604 
1605 		if (port_status & EHCI_RH_PORT_INDICATOR) {
1606 			new_port_status |= PORT_STATUS_PIC;
1607 		}
1608 	}
1609 
1610 	/*
1611 	 * Send the following port status and change information
1612 	 * even if port is not owned by EHCI.
1613 	 *
1614 	 * Additional port change information.
1615 	 */
1616 	if (port_status & EHCI_RH_PORT_CONNECT_STS_CHANGE) {
1617 		change_status |= PORT_CHANGE_CSC;
1618 	}
1619 
1620 	/* Additional port status information */
1621 	if (port_status & EHCI_RH_PORT_POWER) {
1622 		new_port_status |= PORT_STATUS_PPS;
1623 	}
1624 
1625 	if ((!(port_status & EHCI_RH_PORT_ENABLE)) &&
1626 	    (port_status & EHCI_RH_PORT_LOW_SPEED)) {
1627 		new_port_status |= PORT_STATUS_LSDA;
1628 	}
1629 
1630 	/*
1631 	 * Construct complete root hub port status and change information.
1632 	 */
1633 	port_status = ((change_status << 16) | new_port_status);
1634 
1635 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1636 	    "ehci_get_root_hub_port_status: port = %d new status = 0x%x "
1637 	    "change status = 0x%x complete port status 0x%x", port,
1638 	    new_port_status, change_status, port_status);
1639 
1640 	return (port_status);
1641 }
1642 
1643 
1644 /*
1645  * ehci_is_port_owner:
1646  *
1647  * Check whether given port is owned by ehci.
1648  */
1649 static int
1650 ehci_is_port_owner(
1651 	ehci_state_t		*ehcip,
1652 	uint16_t		port)
1653 {
1654 	uint_t			port_status;
1655 
1656 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1657 
1658 	port_status = Get_OpReg(ehci_rh_port_status[port]) &
1659 	    ~EHCI_RH_PORT_CLEAR_MASK;
1660 
1661 	/*
1662 	 * Don't perform anything if port is owned by classis host
1663 	 * controller and return success.
1664 	 */
1665 	if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_CLASSIC) {
1666 
1667 		USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1668 		    "ehci_handle_set_clear_port_feature: "
1669 		    "Port %d is owned by classic host controller", port);
1670 
1671 		return (USB_FAILURE);
1672 	}
1673 
1674 	return (USB_SUCCESS);
1675 }
1676 
1677 
1678 /*
1679  * ehci_root_hub_allocate_intr_pipe_resource:
1680  *
1681  * Allocate interrupt requests and initialize them.
1682  */
1683 static int
1684 ehci_root_hub_allocate_intr_pipe_resource(
1685 	ehci_state_t		*ehcip,
1686 	usb_flags_t		flags)
1687 {
1688 	usba_pipe_handle_data_t	*ph;
1689 	size_t			length;
1690 	usb_intr_req_t		*curr_intr_reqp;
1691 
1692 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1693 	    "ehci_root_hub_allocate_intr_pipe_resource");
1694 
1695 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1696 
1697 	/* Get the interrupt pipe handle */
1698 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1699 
1700 	/* Get the current interrupt request pointer */
1701 	curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp;
1702 
1703 	/*
1704 	 * If current interrupt request pointer is null,
1705 	 * allocate new interrupt request.
1706 	 */
1707 	if (curr_intr_reqp == NULL) {
1708 		ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp);
1709 
1710 		/* Get the length of interrupt transfer */
1711 		length = ehcip->ehci_root_hub.
1712 		    rh_client_intr_reqp->intr_len;
1713 
1714 		curr_intr_reqp = usba_hcdi_dup_intr_req(ph->p_dip,
1715 		    ehcip->ehci_root_hub.rh_client_intr_reqp,
1716 		    length, flags);
1717 
1718 		if (curr_intr_reqp == NULL) {
1719 
1720 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1721 			    "ehci_root_hub_allocate_intr_pipe_resource:"
1722 			    "Interrupt request structure allocation failed");
1723 
1724 			return (USB_NO_RESOURCES);
1725 		}
1726 
1727 		ehcip->ehci_root_hub.rh_curr_intr_reqp = curr_intr_reqp;
1728 		mutex_enter(&ph->p_mutex);
1729 		ph->p_req_count++;
1730 		mutex_exit(&ph->p_mutex);
1731 	}
1732 
1733 	/* Start the timer for the root hub interrupt pipe polling */
1734 	if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0) {
1735 		ehcip->ehci_root_hub.rh_intr_pipe_timer_id =
1736 		    timeout(ehci_handle_root_hub_status_change,
1737 		    (void *)ehcip, drv_usectohz(EHCI_RH_POLL_TIME));
1738 
1739 		ehcip->ehci_root_hub.
1740 		    rh_intr_pipe_state = EHCI_PIPE_STATE_ACTIVE;
1741 	}
1742 
1743 	return (USB_SUCCESS);
1744 }
1745 
1746 
1747 /*
1748  * ehci_root_hub_intr_pipe_cleanup:
1749  *
1750  * Deallocate all interrupt requests and do callback
1751  * the original client interrupt request.
1752  */
1753 static void
1754 ehci_root_hub_intr_pipe_cleanup(
1755 	ehci_state_t		*ehcip,
1756 	usb_cr_t		completion_reason)
1757 {
1758 	usb_intr_req_t		*curr_intr_reqp;
1759 	usb_opaque_t		client_intr_reqp;
1760 	timeout_id_t		timer_id;
1761 	usba_pipe_handle_data_t	*ph;
1762 
1763 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1764 	    "ehci_root_hub_intr_pipe_cleanup");
1765 
1766 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1767 
1768 	/* Get the interrupt pipe handle */
1769 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1770 
1771 	/* Get the interrupt timerid */
1772 	timer_id = ehcip->ehci_root_hub.rh_intr_pipe_timer_id;
1773 
1774 	/* Stop the root hub interrupt timer */
1775 	if (timer_id) {
1776 		/* Reset the timer id to zero */
1777 		ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0;
1778 
1779 		mutex_exit(&ehcip->ehci_int_mutex);
1780 		(void) untimeout(timer_id);
1781 		mutex_enter(&ehcip->ehci_int_mutex);
1782 	}
1783 
1784 	/* Reset the current interrupt request pointer */
1785 	curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp;
1786 
1787 	/* Deallocate uncompleted interrupt request */
1788 	if (curr_intr_reqp) {
1789 		ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL;
1790 		usb_free_intr_req(curr_intr_reqp);
1791 
1792 		mutex_enter(&ph->p_mutex);
1793 		ph->p_req_count--;
1794 		mutex_exit(&ph->p_mutex);
1795 	}
1796 
1797 	client_intr_reqp = (usb_opaque_t)
1798 	    ehcip->ehci_root_hub.rh_client_intr_reqp;
1799 
1800 	/* Callback for original client interrupt request */
1801 	if (client_intr_reqp) {
1802 		ehci_root_hub_hcdi_callback(ph, completion_reason);
1803 	}
1804 }
1805 
1806 
1807 /*
1808  * ehci_handle_root_hub_status_change:
1809  *
1810  * A root hub status change interrupt will occur any time there is a change
1811  * in the root hub status register or one of the port status registers.
1812  */
1813 static void
1814 ehci_handle_root_hub_status_change(void *arg)
1815 {
1816 	ehci_state_t		*ehcip = (ehci_state_t *)arg;
1817 	usb_hub_descr_t		*root_hub_descr =
1818 	    &ehcip->ehci_root_hub.rh_descr;
1819 	usb_intr_req_t		*curr_intr_reqp;
1820 	usb_port_mask_t		port_mask = 0;
1821 	uint_t			new_port_status;
1822 	uint_t			change_status;
1823 	uint_t			port_status;
1824 	mblk_t			*message;
1825 	size_t			length;
1826 	usb_ep_descr_t		*eptd;
1827 	usba_pipe_handle_data_t	*ph;
1828 	int			i;
1829 
1830 	mutex_enter(&ehcip->ehci_int_mutex);
1831 
1832 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
1833 	    "ehci_handle_root_hub_status_change: state = %d",
1834 	    ehcip->ehci_root_hub.rh_intr_pipe_state);
1835 
1836 #if defined(__x86)
1837 	/*
1838 	 * When ohci are attached in ferrari 4000, SMI will reset ehci
1839 	 * registers. If ehci registers have been reset, we must re-initialize
1840 	 * them. During booting, this function will be called 2~3 times. When
1841 	 * this function is called 16 times, ohci drivers have been attached
1842 	 * and stop checking the ehci registers.
1843 	 */
1844 	if (ehcip->ehci_polled_root_hub_count < 16) {
1845 
1846 		if (Get_OpReg(ehci_config_flag) == 0) {
1847 
1848 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB,
1849 			    ehcip->ehci_log_hdl,
1850 			    "ehci_handle_root_hub_status_change:"
1851 			    " EHCI have been reset");
1852 
1853 			/* Reinitialize the controller */
1854 			if (ehci_init_ctlr(ehcip, EHCI_REINITIALIZATION) !=
1855 			    DDI_SUCCESS) {
1856 				mutex_exit(&ehcip->ehci_int_mutex);
1857 
1858 				return;
1859 			}
1860 		}
1861 
1862 		ehcip->ehci_polled_root_hub_count++;
1863 	}
1864 #endif	/* __x86 */
1865 
1866 	/* Get the current interrupt request pointer */
1867 	curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp;
1868 
1869 	ph = ehcip->ehci_root_hub.rh_intr_pipe_handle;
1870 
1871 	/* Check whether timeout handler is valid */
1872 	if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id) {
1873 		/* Check host controller is in operational state */
1874 		if ((ehci_state_is_operational(ehcip)) != USB_SUCCESS) {
1875 			/* Reset the timer id */
1876 			ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0;
1877 
1878 			/* Do interrupt pipe cleanup */
1879 			ehci_root_hub_intr_pipe_cleanup(
1880 			    ehcip, USB_CR_HC_HARDWARE_ERR);
1881 
1882 			mutex_exit(&ehcip->ehci_int_mutex);
1883 
1884 			return;
1885 		}
1886 	} else {
1887 		mutex_exit(&ehcip->ehci_int_mutex);
1888 
1889 		return;
1890 	}
1891 
1892 	eptd = &ehcip->ehci_root_hub.rh_intr_pipe_handle->p_ep;
1893 
1894 	/* Check each port */
1895 	for (i = 0; i < root_hub_descr->bNbrPorts; i++) {
1896 
1897 		port_status = ehci_get_root_hub_port_status(ehcip, i);
1898 
1899 		new_port_status = port_status & PORT_STATUS_MASK;
1900 		change_status = (port_status >> 16) & PORT_CHANGE_MASK;
1901 
1902 		/*
1903 		 * If there is change in the port status then set the bit in the
1904 		 * bitmap of changes and inform hub driver about these changes.
1905 		 * Hub driver will take care of these changes.
1906 		 */
1907 		if (change_status) {
1908 
1909 			/* See if a device was attached/detached */
1910 			if (change_status & PORT_CHANGE_CSC) {
1911 				/*
1912 				 * Update the state depending on whether
1913 				 * the port was attached or detached.
1914 				 */
1915 				if (new_port_status & PORT_STATUS_CCS) {
1916 					ehcip->ehci_root_hub.
1917 					    rh_port_state[i] = DISABLED;
1918 
1919 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1920 					    ehcip->ehci_log_hdl,
1921 					    "Port %d connected", i+1);
1922 				} else {
1923 					ehcip->ehci_root_hub.
1924 					    rh_port_state[i] = DISCONNECTED;
1925 
1926 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1927 					    ehcip->ehci_log_hdl,
1928 					    "Port %d disconnected", i+1);
1929 				}
1930 			}
1931 
1932 			/* See if port enable status changed */
1933 			if (change_status & PORT_CHANGE_PESC) {
1934 				/*
1935 				 * Update the state depending on whether
1936 				 * the port was enabled or disabled.
1937 				 */
1938 				if (new_port_status & PORT_STATUS_PES) {
1939 					ehcip->ehci_root_hub.
1940 					    rh_port_state[i] = ENABLED;
1941 
1942 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1943 					    ehcip->ehci_log_hdl,
1944 					    "Port %d enabled", i+1);
1945 				} else {
1946 					ehcip->ehci_root_hub.
1947 					    rh_port_state[i] = DISABLED;
1948 
1949 					USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB,
1950 					    ehcip->ehci_log_hdl,
1951 					    "Port %d disabled", i+1);
1952 				}
1953 			}
1954 
1955 			port_mask |= 1 << (i + 1);
1956 
1957 			/* Update the status */
1958 			ehcip->ehci_root_hub.
1959 			    rh_port_status[i] = new_port_status;
1960 		}
1961 	}
1962 
1963 	if (ph && port_mask && curr_intr_reqp) {
1964 		length = eptd->wMaxPacketSize;
1965 
1966 		ASSERT(length != 0);
1967 
1968 		/* Get the  message block */
1969 		message = curr_intr_reqp->intr_data;
1970 
1971 		ASSERT(message != NULL);
1972 
1973 		do {
1974 			/*
1975 			 * check that the mblk is big enough when we
1976 			 * are writing bytes into it
1977 			 */
1978 			if (message->b_wptr >= message->b_datap->db_lim) {
1979 
1980 				USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB,
1981 				    ehcip->ehci_log_hdl,
1982 				    "ehci_handle_root_hub_status_change"
1983 				    "mblk data overflow.");
1984 
1985 				break;
1986 			}
1987 			*message->b_wptr++ = (uchar_t)port_mask;
1988 			port_mask >>= 8;
1989 		} while (port_mask != 0);
1990 
1991 		ehci_root_hub_hcdi_callback(ph, USB_CR_OK);
1992 	}
1993 
1994 	/* Reset the timer id */
1995 	ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0;
1996 
1997 	if (ehcip->ehci_root_hub.rh_intr_pipe_state ==
1998 	    EHCI_PIPE_STATE_ACTIVE) {
1999 		/*
2000 		 * If needed, allocate new interrupt request. Also
2001 		 * start the timer for the root hub interrupt polling.
2002 		 */
2003 		if ((ehci_root_hub_allocate_intr_pipe_resource(
2004 		    ehcip, 0)) != USB_SUCCESS) {
2005 
2006 			USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
2007 			    "ehci_handle_root_hub_status_change: No Resources");
2008 
2009 			/* Do interrupt pipe cleanup */
2010 			ehci_root_hub_intr_pipe_cleanup(
2011 			    ehcip, USB_CR_NO_RESOURCES);
2012 		}
2013 	}
2014 
2015 	mutex_exit(&ehcip->ehci_int_mutex);
2016 }
2017 
2018 
2019 /*
2020  * ehci_root_hub_hcdi_callback()
2021  *
2022  * Convenience wrapper around usba_hcdi_cb() for the root hub.
2023  */
2024 static void
2025 ehci_root_hub_hcdi_callback(
2026 	usba_pipe_handle_data_t	*ph,
2027 	usb_cr_t		completion_reason)
2028 {
2029 	ehci_state_t		*ehcip = ehci_obtain_state(
2030 	    ph->p_usba_device->usb_root_hub_dip);
2031 	uchar_t			attributes = ph->p_ep.bmAttributes &
2032 	    USB_EP_ATTR_MASK;
2033 	usb_opaque_t		curr_xfer_reqp;
2034 	uint_t			pipe_state = 0;
2035 
2036 	USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl,
2037 	    "ehci_root_hub_hcdi_callback: ph = 0x%p, cr = 0x%x",
2038 	    (void *)ph, completion_reason);
2039 
2040 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
2041 
2042 	/* Set the pipe state as per completion reason */
2043 	switch (completion_reason) {
2044 	case USB_CR_OK:
2045 		switch (attributes) {
2046 		case USB_EP_ATTR_CONTROL:
2047 			pipe_state = EHCI_PIPE_STATE_IDLE;
2048 			break;
2049 		case USB_EP_ATTR_INTR:
2050 			pipe_state = ehcip->ehci_root_hub.
2051 			    rh_intr_pipe_state;
2052 			break;
2053 		}
2054 		break;
2055 	case USB_CR_NO_RESOURCES:
2056 	case USB_CR_NOT_SUPPORTED:
2057 	case USB_CR_STOPPED_POLLING:
2058 	case USB_CR_PIPE_RESET:
2059 	case USB_CR_HC_HARDWARE_ERR:
2060 		/* Set pipe state to idle */
2061 		pipe_state = EHCI_PIPE_STATE_IDLE;
2062 		break;
2063 	case USB_CR_PIPE_CLOSING:
2064 		break;
2065 	default:
2066 		/* Set pipe state to error */
2067 		pipe_state = EHCI_PIPE_STATE_ERROR;
2068 		break;
2069 	}
2070 
2071 	switch (attributes) {
2072 	case USB_EP_ATTR_CONTROL:
2073 		curr_xfer_reqp = (usb_opaque_t)
2074 		    ehcip->ehci_root_hub.rh_curr_ctrl_reqp;
2075 
2076 		ehcip->ehci_root_hub.rh_curr_ctrl_reqp = NULL;
2077 		ehcip->ehci_root_hub.rh_ctrl_pipe_state = pipe_state;
2078 		break;
2079 	case USB_EP_ATTR_INTR:
2080 		/* if curr_intr_reqp available then use this request */
2081 		if (ehcip->ehci_root_hub.rh_curr_intr_reqp) {
2082 			curr_xfer_reqp = (usb_opaque_t)ehcip->
2083 			    ehci_root_hub.rh_curr_intr_reqp;
2084 
2085 			ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL;
2086 		} else {
2087 			/* no current request, use client's request */
2088 			curr_xfer_reqp = (usb_opaque_t)
2089 			    ehcip->ehci_root_hub.rh_client_intr_reqp;
2090 
2091 			ehcip->ehci_root_hub.rh_client_intr_reqp = NULL;
2092 		}
2093 		ehcip->ehci_root_hub.rh_intr_pipe_state = pipe_state;
2094 		break;
2095 	}
2096 
2097 	ASSERT(curr_xfer_reqp != NULL);
2098 
2099 	mutex_exit(&ehcip->ehci_int_mutex);
2100 	usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason);
2101 	mutex_enter(&ehcip->ehci_int_mutex);
2102 }
2103