Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/usb/hcd/ehci/ehci.c
+++ new/usr/src/uts/common/io/usb/hcd/ehci/ehci.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 /*
28 28 * EHCI Host Controller Driver (EHCI)
29 29 *
30 30 * The EHCI driver is a software driver which interfaces to the Universal
31 31 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to
32 32 * the Host Controller is defined by the EHCI Host Controller Interface.
33 33 *
34 34 * This file contains code for Auto-configuration and HCDI entry points.
35 35 *
36 36 * NOTE:
37 37 *
38 38 * Currently EHCI driver does not support the following features
39 39 *
40 40 * - Alternate QTD for short xfer condition is only used in Bulk xfers.
41 41 * - Frame Span Traversal Nodes (FSTN).
42 42 * - Bandwidth allocation scheme needs to be updated for FSTN and USB2.0
43 43 * or High speed hub with multiple TT implementation. Currently bandwidth
44 44 * allocation scheme assumes one TT per USB2.0 or High speed hub.
45 45 * - 64 bit addressing capability.
46 46 * - Programmable periodic frame list size like 256, 512, 1024.
47 47 * It supports only 1024 periodic frame list size.
48 48 */
49 49
50 50 #include <sys/usb/hcd/ehci/ehcid.h>
51 51 #include <sys/usb/hcd/ehci/ehci_xfer.h>
52 52 #include <sys/usb/hcd/ehci/ehci_intr.h>
53 53 #include <sys/usb/hcd/ehci/ehci_util.h>
54 54 #include <sys/usb/hcd/ehci/ehci_isoch.h>
55 55
56 56 /* Pointer to the state structure */
57 57 void *ehci_statep;
58 58
59 59 /* Number of instances */
60 60 #define EHCI_INSTS 1
61 61
62 62 /* Debugging information */
63 63 uint_t ehci_errmask = (uint_t)PRINT_MASK_ALL;
64 64 uint_t ehci_errlevel = USB_LOG_L2;
65 65 uint_t ehci_instance_debug = (uint_t)-1;
66 66
67 67 /*
68 68 * Tunable to ensure host controller goes off even if a keyboard is attached.
69 69 */
70 70 int force_ehci_off = 1;
71 71
72 72 /* Enable all workarounds for VIA VT62x2 */
73 73 uint_t ehci_vt62x2_workaround = EHCI_VIA_WORKAROUNDS;
74 74
75 75 /*
76 76 * EHCI Auto-configuration entry points.
77 77 *
78 78 * Device operations (dev_ops) entries function prototypes.
79 79 *
80 80 * We use the hub cbops since all nexus ioctl operations defined so far will
81 81 * be executed by the root hub. The following are the Host Controller Driver
82 82 * (HCD) entry points.
83 83 *
84 84 * the open/close/ioctl functions call the corresponding usba_hubdi_*
85 85 * calls after looking up the dip thru the dev_t.
86 86 */
87 87 static int ehci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
88 88 static int ehci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
89 89 static int ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd);
90 90 static int ehci_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
91 91 void *arg, void **result);
92 92
93 93 static int ehci_open(dev_t *devp, int flags, int otyp, cred_t *credp);
94 94 static int ehci_close(dev_t dev, int flag, int otyp, cred_t *credp);
95 95 static int ehci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
96 96 cred_t *credp, int *rvalp);
97 97
98 98 int usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level);
99 99 static int ehci_quiesce(dev_info_t *dip);
100 100
101 101 static struct cb_ops ehci_cb_ops = {
102 102 ehci_open, /* EHCI */
103 103 ehci_close, /* Close */
104 104 nodev, /* Strategy */
105 105 nodev, /* Print */
106 106 nodev, /* Dump */
107 107 nodev, /* Read */
108 108 nodev, /* Write */
109 109 ehci_ioctl, /* Ioctl */
110 110 nodev, /* Devmap */
111 111 nodev, /* Mmap */
112 112 nodev, /* Segmap */
113 113 nochpoll, /* Poll */
114 114 ddi_prop_op, /* cb_prop_op */
115 115 NULL, /* Streamtab */
116 116 D_NEW | D_MP | D_HOTPLUG /* Driver compatibility flag */
117 117 };
118 118
119 119 static struct dev_ops ehci_ops = {
120 120 DEVO_REV, /* Devo_rev */
121 121 0, /* Refcnt */
122 122 ehci_info, /* Info */
123 123 nulldev, /* Identify */
124 124 nulldev, /* Probe */
125 125 ehci_attach, /* Attach */
126 126 ehci_detach, /* Detach */
127 127 ehci_reset, /* Reset */
128 128 &ehci_cb_ops, /* Driver operations */
129 129 &usba_hubdi_busops, /* Bus operations */
130 130 usba_hubdi_root_hub_power, /* Power */
131 131 ehci_quiesce /* Quiesce */
132 132 };
133 133
↓ open down ↓ |
133 lines elided |
↑ open up ↑ |
134 134 /*
135 135 * The USBA library must be loaded for this driver.
136 136 */
137 137 static struct modldrv modldrv = {
138 138 &mod_driverops, /* Type of module. This one is a driver */
139 139 "USB EHCI Driver", /* Name of the module. */
140 140 &ehci_ops, /* Driver ops */
141 141 };
142 142
143 143 static struct modlinkage modlinkage = {
144 - MODREV_1, (void *)&modldrv, NULL
144 + MODREV_1, { (void *)&modldrv, NULL }
145 145 };
146 146
147 147
148 148 int
149 149 _init(void)
150 150 {
151 151 int error;
152 152
153 153 /* Initialize the soft state structures */
154 154 if ((error = ddi_soft_state_init(&ehci_statep, sizeof (ehci_state_t),
155 155 EHCI_INSTS)) != 0) {
156 156 return (error);
157 157 }
158 158
159 159 /* Install the loadable module */
160 160 if ((error = mod_install(&modlinkage)) != 0) {
161 161 ddi_soft_state_fini(&ehci_statep);
162 162 }
163 163
164 164 return (error);
165 165 }
166 166
167 167
168 168 int
169 169 _info(struct modinfo *modinfop)
170 170 {
171 171 return (mod_info(&modlinkage, modinfop));
172 172 }
173 173
174 174
175 175 int
176 176 _fini(void)
177 177 {
178 178 int error;
179 179
180 180 if ((error = mod_remove(&modlinkage)) == 0) {
181 181
182 182 /* Release per module resources */
183 183 ddi_soft_state_fini(&ehci_statep);
184 184 }
185 185
186 186 return (error);
187 187 }
188 188
189 189
190 190 /*
191 191 * EHCI Auto configuration entry points.
192 192 */
193 193
194 194 /*
195 195 * ehci_attach:
196 196 *
197 197 * Description: Attach entry point is called by the Kernel.
198 198 * Allocates resources for each EHCI host controller instance.
199 199 * Initializes the EHCI Host Controller.
200 200 *
201 201 * Return : DDI_SUCCESS / DDI_FAILURE.
202 202 */
203 203 static int
204 204 ehci_attach(dev_info_t *dip,
205 205 ddi_attach_cmd_t cmd)
206 206 {
207 207 int instance;
208 208 ehci_state_t *ehcip = NULL;
209 209 usba_hcdi_register_args_t hcdi_args;
210 210
211 211 switch (cmd) {
212 212 case DDI_ATTACH:
213 213 break;
214 214 case DDI_RESUME:
215 215 ehcip = ehci_obtain_state(dip);
216 216
217 217 return (ehci_cpr_resume(ehcip));
218 218 default:
219 219 return (DDI_FAILURE);
220 220 }
221 221
222 222 /* Get the instance and create soft state */
223 223 instance = ddi_get_instance(dip);
224 224
225 225 if (ddi_soft_state_zalloc(ehci_statep, instance) != 0) {
226 226
227 227 return (DDI_FAILURE);
228 228 }
229 229
230 230 ehcip = ddi_get_soft_state(ehci_statep, instance);
231 231 if (ehcip == NULL) {
232 232
233 233 return (DDI_FAILURE);
234 234 }
235 235
236 236 ehcip->ehci_flags = EHCI_ATTACH;
237 237
238 238 ehcip->ehci_log_hdl = usb_alloc_log_hdl(dip, "ehci", &ehci_errlevel,
239 239 &ehci_errmask, &ehci_instance_debug, 0);
240 240
241 241 ehcip->ehci_flags |= EHCI_ZALLOC;
242 242
243 243 /* Set host controller soft state to initialization */
244 244 ehcip->ehci_hc_soft_state = EHCI_CTLR_INIT_STATE;
245 245
246 246 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
247 247 "ehcip = 0x%p", (void *)ehcip);
248 248
249 249 /* Save the dip and instance */
250 250 ehcip->ehci_dip = dip;
251 251 ehcip->ehci_instance = instance;
252 252
253 253 /* Map the registers */
254 254 if (ehci_map_regs(ehcip) != DDI_SUCCESS) {
255 255 (void) ehci_cleanup(ehcip);
256 256
257 257 return (DDI_FAILURE);
258 258 }
259 259
260 260 /* Get the ehci chip vendor and device id */
261 261 ehcip->ehci_vendor_id = pci_config_get16(
262 262 ehcip->ehci_config_handle, PCI_CONF_VENID);
263 263 ehcip->ehci_device_id = pci_config_get16(
264 264 ehcip->ehci_config_handle, PCI_CONF_DEVID);
265 265 ehcip->ehci_rev_id = pci_config_get8(
266 266 ehcip->ehci_config_handle, PCI_CONF_REVID);
267 267
268 268 /* Initialize the DMA attributes */
269 269 ehci_set_dma_attributes(ehcip);
270 270
271 271 /* Initialize kstat structures */
272 272 ehci_create_stats(ehcip);
273 273
274 274 /* Create the qtd and qh pools */
275 275 if (ehci_allocate_pools(ehcip) != DDI_SUCCESS) {
276 276 (void) ehci_cleanup(ehcip);
277 277
278 278 return (DDI_FAILURE);
279 279 }
280 280
281 281 /* Initialize the isochronous resources */
282 282 if (ehci_isoc_init(ehcip) != DDI_SUCCESS) {
283 283 (void) ehci_cleanup(ehcip);
284 284
285 285 return (DDI_FAILURE);
286 286 }
287 287
288 288 /* Register interrupts */
289 289 if (ehci_register_intrs_and_init_mutex(ehcip) != DDI_SUCCESS) {
290 290 (void) ehci_cleanup(ehcip);
291 291
292 292 return (DDI_FAILURE);
293 293 }
294 294
295 295 mutex_enter(&ehcip->ehci_int_mutex);
296 296
297 297 /* Initialize the controller */
298 298 if (ehci_init_ctlr(ehcip, EHCI_NORMAL_INITIALIZATION) != DDI_SUCCESS) {
299 299 mutex_exit(&ehcip->ehci_int_mutex);
300 300 (void) ehci_cleanup(ehcip);
301 301
302 302 return (DDI_FAILURE);
303 303 }
304 304
305 305 /*
306 306 * At this point, the hardware will be okay.
307 307 * Initialize the usba_hcdi structure
308 308 */
309 309 ehcip->ehci_hcdi_ops = ehci_alloc_hcdi_ops(ehcip);
310 310
311 311 mutex_exit(&ehcip->ehci_int_mutex);
312 312
313 313 /*
314 314 * Make this HCD instance known to USBA
315 315 * (dma_attr must be passed for USBA busctl's)
316 316 */
317 317 hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION;
318 318 hcdi_args.usba_hcdi_register_dip = dip;
319 319 hcdi_args.usba_hcdi_register_ops = ehcip->ehci_hcdi_ops;
320 320 hcdi_args.usba_hcdi_register_dma_attr = &ehcip->ehci_dma_attr;
321 321
322 322 /*
323 323 * Priority and iblock_cookie are one and the same
324 324 * (However, retaining hcdi_soft_iblock_cookie for now
325 325 * assigning it w/ priority. In future all iblock_cookie
326 326 * could just go)
327 327 */
328 328 hcdi_args.usba_hcdi_register_iblock_cookie =
329 329 (ddi_iblock_cookie_t)(uintptr_t)ehcip->ehci_intr_pri;
330 330
331 331 if (usba_hcdi_register(&hcdi_args, 0) != DDI_SUCCESS) {
332 332 (void) ehci_cleanup(ehcip);
333 333
334 334 return (DDI_FAILURE);
335 335 }
336 336
337 337 ehcip->ehci_flags |= EHCI_USBAREG;
338 338
339 339 mutex_enter(&ehcip->ehci_int_mutex);
340 340
341 341 if ((ehci_init_root_hub(ehcip)) != USB_SUCCESS) {
342 342 mutex_exit(&ehcip->ehci_int_mutex);
343 343 (void) ehci_cleanup(ehcip);
344 344
345 345 return (DDI_FAILURE);
346 346 }
347 347
348 348 mutex_exit(&ehcip->ehci_int_mutex);
349 349
350 350 /* Finally load the root hub driver */
351 351 if (ehci_load_root_hub_driver(ehcip) != USB_SUCCESS) {
352 352 (void) ehci_cleanup(ehcip);
353 353
354 354 return (DDI_FAILURE);
355 355 }
356 356 ehcip->ehci_flags |= EHCI_RHREG;
357 357
358 358 /* Display information in the banner */
359 359 ddi_report_dev(dip);
360 360
361 361 mutex_enter(&ehcip->ehci_int_mutex);
362 362
363 363 /* Reset the ehci initialization flag */
364 364 ehcip->ehci_flags &= ~EHCI_ATTACH;
365 365
366 366 /* Print the Host Control's Operational registers */
367 367 ehci_print_caps(ehcip);
368 368 ehci_print_regs(ehcip);
369 369
370 370 (void) pci_report_pmcap(dip, PCI_PM_IDLESPEED, (void *)4000);
371 371
372 372 mutex_exit(&ehcip->ehci_int_mutex);
373 373
374 374 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
375 375 "ehci_attach: dip = 0x%p done", (void *)dip);
376 376
377 377 return (DDI_SUCCESS);
378 378 }
379 379
380 380
381 381 /*
382 382 * ehci_detach:
383 383 *
384 384 * Description: Detach entry point is called by the Kernel.
385 385 * Deallocates all resource allocated.
386 386 * Unregisters the interrupt handler.
387 387 *
388 388 * Return : DDI_SUCCESS / DDI_FAILURE
389 389 */
390 390 int
391 391 ehci_detach(dev_info_t *dip,
392 392 ddi_detach_cmd_t cmd)
393 393 {
394 394 ehci_state_t *ehcip = ehci_obtain_state(dip);
395 395
396 396 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, "ehci_detach:");
397 397
398 398 switch (cmd) {
399 399 case DDI_DETACH:
400 400
401 401 return (ehci_cleanup(ehcip));
402 402 case DDI_SUSPEND:
403 403
404 404 return (ehci_cpr_suspend(ehcip));
405 405 default:
406 406
407 407 return (DDI_FAILURE);
408 408 }
409 409 }
410 410
411 411 /*
412 412 * ehci_reset:
413 413 *
414 414 * Description: Reset entry point - called by the Kernel
415 415 * on the way down.
416 416 * Toshiba Tecra laptop has been observed to hang
417 417 * on soft reboot. The resetting ehci on the way
418 418 * down solves the problem.
419 419 *
420 420 * Return : DDI_SUCCESS / DDI_FAILURE
421 421 */
422 422 /* ARGSUSED */
423 423 static int
424 424 ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
425 425 {
426 426 #if defined(__sparc)
427 427 /*
428 428 * Don't reset the host controller on SPARC, for OBP needs Solaris
429 429 * to continue to provide keyboard support after shutdown of SPARC,
430 430 * or the keyboard connected to a USB 2.0 port will not work after
431 431 * that. The incomplete reset problem on Toshiba Tecra laptop is
432 432 * specific to Tecra laptop or BIOS, not present on SPARC. The SPARC
433 433 * OBP guarantees good reset behavior during startup.
434 434 */
435 435 return (DDI_SUCCESS);
436 436 #else
437 437 ehci_state_t *ehcip = ehci_obtain_state(dip);
438 438
439 439 mutex_enter(&ehcip->ehci_int_mutex);
440 440
441 441 /*
442 442 * To reset the host controller, the HCRESET bit should be set to one.
443 443 * Software should not set this bit to a one when the HCHalted bit in
444 444 * the USBSTS register is a zero. Attempting to reset an actively
445 445 * running host controller will result in undefined behavior.
446 446 * see EHCI SPEC. for more information.
447 447 */
448 448 if (!(Get_OpReg(ehci_status) & EHCI_STS_HOST_CTRL_HALTED)) {
449 449
450 450 /* Stop the EHCI host controller */
451 451 Set_OpReg(ehci_command,
452 452 Get_OpReg(ehci_command) & ~EHCI_CMD_HOST_CTRL_RUN);
453 453 /*
454 454 * When this bit is set to 0, the Host Controller completes the
455 455 * current and any actively pipelined transactions on the USB
456 456 * and then halts. The Host Controller must halt within 16
457 457 * micro-frames after software clears the Run bit.
458 458 * The HC Halted bit in the status register indicates when the
459 459 * Host Controller has finished its pending pipelined
460 460 * transactions and has entered the stopped state.
461 461 */
462 462 drv_usecwait(EHCI_RESET_TIMEWAIT);
463 463 }
464 464
465 465 /* Reset the EHCI host controller */
466 466 Set_OpReg(ehci_command,
467 467 Get_OpReg(ehci_command) | EHCI_CMD_HOST_CTRL_RESET);
468 468
469 469 mutex_exit(&ehcip->ehci_int_mutex);
470 470
471 471 return (DDI_SUCCESS);
472 472 #endif
473 473 }
474 474
475 475 /*
476 476 * quiesce(9E) entry point.
477 477 *
478 478 * This function is called when the system is single-threaded at high
479 479 * PIL with preemption disabled. Therefore, this function must not be
480 480 * blocked.
481 481 *
482 482 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
483 483 * DDI_FAILURE indicates an error condition and should almost never happen.
484 484 */
485 485 static int
486 486 ehci_quiesce(dev_info_t *dip)
487 487 {
488 488 ehci_state_t *ehcip = ehci_obtain_state(dip);
489 489
490 490 if (ehcip == NULL)
491 491 return (DDI_FAILURE);
492 492
493 493 #ifndef lint
494 494 _NOTE(NO_COMPETING_THREADS_NOW);
495 495 #endif
496 496 /*
497 497 * To reset the host controller, the HCRESET bit should be set to one.
498 498 * Software should not set this bit to a one when the HCHalted bit in
499 499 * the USBSTS register is a zero. Attempting to reset an actively
500 500 * running host controller will result in undefined behavior.
501 501 * see EHCI SPEC. for more information.
502 502 */
503 503 if (!(Get_OpReg(ehci_status) & EHCI_STS_HOST_CTRL_HALTED)) {
504 504
505 505 /* Stop the EHCI host controller */
506 506 Set_OpReg(ehci_command,
507 507 Get_OpReg(ehci_command) & ~EHCI_CMD_HOST_CTRL_RUN);
508 508 /*
509 509 * When this bit is set to 0, the Host Controller completes the
510 510 * current and any actively pipelined transactions on the USB
511 511 * and then halts. The Host Controller must halt within 16
512 512 * micro-frames after software clears the Run bit.
513 513 * The HC Halted bit in the status register indicates when the
514 514 * Host Controller has finished its pending pipelined
515 515 * transactions and has entered the stopped state.
516 516 */
517 517 drv_usecwait(EHCI_RESET_TIMEWAIT);
518 518 }
519 519
520 520 /* Reset the EHCI host controller */
521 521 Set_OpReg(ehci_command,
522 522 Get_OpReg(ehci_command) | EHCI_CMD_HOST_CTRL_RESET);
523 523
524 524 #ifndef lint
525 525 _NOTE(COMPETING_THREADS_NOW);
526 526 #endif
527 527 return (DDI_SUCCESS);
528 528 }
529 529
530 530
531 531 /*
532 532 * ehci_info:
533 533 */
534 534 /* ARGSUSED */
535 535 static int
536 536 ehci_info(dev_info_t *dip,
537 537 ddi_info_cmd_t infocmd,
538 538 void *arg,
539 539 void **result)
540 540 {
541 541 dev_t dev;
542 542 ehci_state_t *ehcip;
543 543 int instance;
544 544 int error = DDI_FAILURE;
545 545
546 546 switch (infocmd) {
547 547 case DDI_INFO_DEVT2DEVINFO:
548 548 dev = (dev_t)arg;
549 549 instance = EHCI_UNIT(dev);
550 550 ehcip = ddi_get_soft_state(ehci_statep, instance);
551 551 if (ehcip != NULL) {
552 552 *result = (void *)ehcip->ehci_dip;
553 553 if (*result != NULL) {
554 554 error = DDI_SUCCESS;
555 555 }
556 556 } else {
557 557 *result = NULL;
558 558 }
559 559
560 560 break;
561 561 case DDI_INFO_DEVT2INSTANCE:
562 562 dev = (dev_t)arg;
563 563 instance = EHCI_UNIT(dev);
564 564 *result = (void *)(uintptr_t)instance;
565 565 error = DDI_SUCCESS;
566 566 break;
567 567 default:
568 568 break;
569 569 }
570 570
571 571 return (error);
572 572 }
573 573
574 574
575 575 /*
576 576 * EHCI CB_OPS entry points.
577 577 */
578 578 static dev_info_t *
579 579 ehci_get_dip(dev_t dev)
580 580 {
581 581 int instance = EHCI_UNIT(dev);
582 582 ehci_state_t *ehcip = ddi_get_soft_state(ehci_statep, instance);
583 583
584 584 if (ehcip) {
585 585
586 586 return (ehcip->ehci_dip);
587 587 } else {
588 588
589 589 return (NULL);
590 590 }
591 591 }
592 592
593 593
594 594 static int
595 595 ehci_open(dev_t *devp,
596 596 int flags,
597 597 int otyp,
598 598 cred_t *credp)
599 599 {
600 600 dev_info_t *dip = ehci_get_dip(*devp);
601 601
602 602 return (usba_hubdi_open(dip, devp, flags, otyp, credp));
603 603 }
604 604
605 605
606 606 static int
607 607 ehci_close(dev_t dev,
608 608 int flag,
609 609 int otyp,
610 610 cred_t *credp)
611 611 {
612 612 dev_info_t *dip = ehci_get_dip(dev);
613 613
614 614 return (usba_hubdi_close(dip, dev, flag, otyp, credp));
615 615 }
616 616
617 617
618 618 static int
619 619 ehci_ioctl(dev_t dev,
620 620 int cmd,
621 621 intptr_t arg,
622 622 int mode,
623 623 cred_t *credp,
624 624 int *rvalp)
625 625 {
626 626 dev_info_t *dip = ehci_get_dip(dev);
627 627
628 628 return (usba_hubdi_ioctl(dip,
629 629 dev, cmd, arg, mode, credp, rvalp));
630 630 }
631 631
632 632 /*
633 633 * EHCI Interrupt Handler entry point.
634 634 */
635 635
636 636 /*
637 637 * ehci_intr:
638 638 *
639 639 * EHCI (EHCI) interrupt handling routine.
640 640 */
641 641 uint_t
642 642 ehci_intr(caddr_t arg1, caddr_t arg2)
643 643 {
644 644 uint_t intr;
645 645 ehci_state_t *ehcip = (void *)arg1;
646 646
647 647 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
648 648 "ehci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p",
649 649 (void *)arg1, (void *)arg2);
650 650
651 651 /* Get the ehci global mutex */
652 652 mutex_enter(&ehcip->ehci_int_mutex);
653 653
654 654 /* Any interrupt is not handled for the suspended device. */
655 655 if (ehcip->ehci_hc_soft_state == EHCI_CTLR_SUSPEND_STATE) {
656 656 mutex_exit(&ehcip->ehci_int_mutex);
657 657
658 658 return (DDI_INTR_UNCLAIMED);
659 659 }
660 660
661 661 /*
662 662 * Now process the actual ehci interrupt events that caused
663 663 * invocation of this ehci interrupt handler.
664 664 */
665 665 intr = (Get_OpReg(ehci_status) & Get_OpReg(ehci_interrupt));
666 666
667 667 /* Update kstat values */
668 668 ehci_do_intrs_stats(ehcip, intr);
669 669
670 670 /*
671 671 * We could have gotten a spurious interrupts. If so, do not
672 672 * claim it. This is quite possible on some architectures
673 673 * where more than one PCI slots share the IRQs. If so, the
674 674 * associated driver's interrupt routine may get called even
675 675 * if the interrupt is not meant for them.
676 676 *
677 677 * By unclaiming the interrupt, the other driver gets chance
678 678 * to service its interrupt.
679 679 */
680 680 if (!intr) {
681 681 mutex_exit(&ehcip->ehci_int_mutex);
682 682
683 683 return (DDI_INTR_UNCLAIMED);
684 684 }
685 685
686 686 /* Acknowledge the interrupt */
687 687 Set_OpReg(ehci_status, intr);
688 688
689 689 if (ehcip->ehci_hc_soft_state == EHCI_CTLR_ERROR_STATE) {
690 690 mutex_exit(&ehcip->ehci_int_mutex);
691 691
692 692 return (DDI_INTR_CLAIMED);
693 693 }
694 694
695 695 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
696 696 "Interrupt status 0x%x", intr);
697 697
698 698 /*
699 699 * If necessary broadcast that an interrupt has occured. This
700 700 * is only necessary during controller init.
701 701 */
702 702 if (ehcip->ehci_flags & EHCI_CV_INTR) {
703 703 ehcip->ehci_flags &= ~EHCI_CV_INTR;
704 704 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv);
705 705 }
706 706
707 707 /* Check for Frame List Rollover */
708 708 if (intr & EHCI_INTR_FRAME_LIST_ROLLOVER) {
709 709 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
710 710 "ehci_intr: Frame List Rollover");
711 711
712 712 ehci_handle_frame_list_rollover(ehcip);
713 713
714 714 /* VIA VT6202 looses EHCI_INTR_USB interrupts, workaround. */
715 715 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) &&
716 716 (ehci_vt62x2_workaround & EHCI_VIA_LOST_INTERRUPTS)) {
717 717 ehcip->ehci_missed_intr_sts |= EHCI_INTR_USB;
718 718 }
719 719 }
720 720
721 721 /* Check for Advance on Asynchronous Schedule */
722 722 if (intr & EHCI_INTR_ASYNC_ADVANCE) {
723 723 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
724 724 "ehci_intr: Asynchronous Schedule Advance Notification");
725 725
726 726 /* Disable async list advance interrupt */
727 727 Set_OpReg(ehci_interrupt,
728 728 (Get_OpReg(ehci_interrupt) & ~EHCI_INTR_ASYNC_ADVANCE));
729 729
730 730 /*
731 731 * Call cv_broadcast on every this interrupt to wakeup
732 732 * all the threads that are waiting the async list advance
733 733 * event.
734 734 */
735 735 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv);
736 736 }
737 737
738 738 /* Always process completed itds */
739 739 ehci_traverse_active_isoc_list(ehcip);
740 740
741 741 /*
742 742 * Check for any USB transaction completion notification. Also
743 743 * process any missed USB transaction completion interrupts.
744 744 */
745 745 if ((intr & EHCI_INTR_USB) || (intr & EHCI_INTR_USB_ERROR) ||
746 746 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB) ||
747 747 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB_ERROR)) {
748 748
749 749 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
750 750 "ehci_intr: USB Transaction Completion Notification");
751 751
752 752 /* Clear missed interrupts */
753 753 if (ehcip->ehci_missed_intr_sts) {
754 754 ehcip->ehci_missed_intr_sts = 0;
755 755 }
756 756
757 757 /* Process completed qtds */
758 758 ehci_traverse_active_qtd_list(ehcip);
759 759 }
760 760
761 761 /* Process endpoint reclamation list */
762 762 if (ehcip->ehci_reclaim_list) {
763 763 ehci_handle_endpoint_reclaimation(ehcip);
764 764 }
765 765
766 766 /* Check for Host System Error */
767 767 if (intr & EHCI_INTR_HOST_SYSTEM_ERROR) {
768 768 USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
769 769 "ehci_intr: Unrecoverable error");
770 770
771 771 ehci_handle_ue(ehcip);
772 772 }
773 773
774 774 /*
775 775 * Read interrupt status register to make sure that any PIO
776 776 * store to clear the ISR has made it on the PCI bus before
777 777 * returning from its interrupt handler.
778 778 */
779 779 (void) Get_OpReg(ehci_status);
780 780
781 781 /* Release the ehci global mutex */
782 782 mutex_exit(&ehcip->ehci_int_mutex);
783 783
784 784 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
785 785 "Interrupt handling completed");
786 786
787 787 return (DDI_INTR_CLAIMED);
788 788 }
789 789
790 790
791 791 /*
792 792 * EHCI HCDI entry points
793 793 *
794 794 * The Host Controller Driver Interfaces (HCDI) are the software interfaces
795 795 * between the Universal Serial Bus Layer (USBA) and the Host Controller
796 796 * Driver (HCD). The HCDI interfaces or entry points are subject to change.
797 797 */
798 798
799 799 /*
800 800 * ehci_hcdi_pipe_open:
801 801 *
802 802 * Member of HCD Ops structure and called during client specific pipe open
803 803 * Add the pipe to the data structure representing the device and allocate
804 804 * bandwidth for the pipe if it is a interrupt or isochronous endpoint.
805 805 */
806 806 int
807 807 ehci_hcdi_pipe_open(
808 808 usba_pipe_handle_data_t *ph,
809 809 usb_flags_t flags)
810 810 {
811 811 ehci_state_t *ehcip = ehci_obtain_state(
812 812 ph->p_usba_device->usb_root_hub_dip);
813 813 usb_ep_descr_t *epdt = &ph->p_ep;
814 814 int rval, error = USB_SUCCESS;
815 815 int kmflag = (flags & USB_FLAGS_SLEEP) ?
816 816 KM_SLEEP : KM_NOSLEEP;
817 817 uchar_t smask = 0;
818 818 uchar_t cmask = 0;
819 819 uint_t pnode = 0;
820 820 ehci_pipe_private_t *pp;
821 821
822 822 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
823 823 "ehci_hcdi_pipe_open: addr = 0x%x, ep%d",
824 824 ph->p_usba_device->usb_addr,
825 825 epdt->bEndpointAddress & USB_EP_NUM_MASK);
826 826
827 827 mutex_enter(&ehcip->ehci_int_mutex);
828 828 rval = ehci_state_is_operational(ehcip);
829 829 mutex_exit(&ehcip->ehci_int_mutex);
830 830
831 831 if (rval != USB_SUCCESS) {
832 832
833 833 return (rval);
834 834 }
835 835
836 836 /*
837 837 * Check and handle root hub pipe open.
838 838 */
839 839 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
840 840
841 841 mutex_enter(&ehcip->ehci_int_mutex);
842 842 error = ehci_handle_root_hub_pipe_open(ph, flags);
843 843 mutex_exit(&ehcip->ehci_int_mutex);
844 844
845 845 return (error);
846 846 }
847 847
848 848 /*
849 849 * Opening of other pipes excluding root hub pipe are
850 850 * handled below. Check whether pipe is already opened.
851 851 */
852 852 if (ph->p_hcd_private) {
853 853 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
854 854 "ehci_hcdi_pipe_open: Pipe is already opened");
855 855
856 856 return (USB_FAILURE);
857 857 }
858 858
859 859 /*
860 860 * A portion of the bandwidth is reserved for the non-periodic
861 861 * transfers, i.e control and bulk transfers in each of one
862 862 * millisecond frame period & usually it will be 20% of frame
863 863 * period. Hence there is no need to check for the available
864 864 * bandwidth before adding the control or bulk endpoints.
865 865 *
866 866 * There is a need to check for the available bandwidth before
867 867 * adding the periodic transfers, i.e interrupt & isochronous,
868 868 * since all these periodic transfers are guaranteed transfers.
869 869 * Usually 80% of the total frame time is reserved for periodic
870 870 * transfers.
871 871 */
872 872 if (EHCI_PERIODIC_ENDPOINT(epdt)) {
873 873
874 874 mutex_enter(&ehcip->ehci_int_mutex);
875 875 mutex_enter(&ph->p_mutex);
876 876
877 877 error = ehci_allocate_bandwidth(ehcip,
878 878 ph, &pnode, &smask, &cmask);
879 879
880 880 if (error != USB_SUCCESS) {
881 881
882 882 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
883 883 "ehci_hcdi_pipe_open: Bandwidth allocation failed");
884 884
885 885 mutex_exit(&ph->p_mutex);
886 886 mutex_exit(&ehcip->ehci_int_mutex);
887 887
888 888 return (error);
889 889 }
890 890
891 891 mutex_exit(&ph->p_mutex);
892 892 mutex_exit(&ehcip->ehci_int_mutex);
893 893 }
894 894
895 895 /* Create the HCD pipe private structure */
896 896 pp = kmem_zalloc(sizeof (ehci_pipe_private_t), kmflag);
897 897
898 898 /*
899 899 * Return failure if ehci pipe private
900 900 * structure allocation fails.
901 901 */
902 902 if (pp == NULL) {
903 903
904 904 mutex_enter(&ehcip->ehci_int_mutex);
905 905
906 906 /* Deallocate bandwidth */
907 907 if (EHCI_PERIODIC_ENDPOINT(epdt)) {
908 908
909 909 mutex_enter(&ph->p_mutex);
910 910 ehci_deallocate_bandwidth(ehcip,
911 911 ph, pnode, smask, cmask);
912 912 mutex_exit(&ph->p_mutex);
913 913 }
914 914
915 915 mutex_exit(&ehcip->ehci_int_mutex);
916 916
917 917 return (USB_NO_RESOURCES);
918 918 }
919 919
920 920 mutex_enter(&ehcip->ehci_int_mutex);
921 921
922 922 /* Save periodic nodes */
923 923 pp->pp_pnode = pnode;
924 924
925 925 /* Save start and complete split mask values */
926 926 pp->pp_smask = smask;
927 927 pp->pp_cmask = cmask;
928 928
929 929 /* Create prototype for xfer completion condition variable */
930 930 cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL);
931 931
932 932 /* Set the state of pipe as idle */
933 933 pp->pp_state = EHCI_PIPE_STATE_IDLE;
934 934
935 935 /* Store a pointer to the pipe handle */
936 936 pp->pp_pipe_handle = ph;
937 937
938 938 mutex_enter(&ph->p_mutex);
939 939
940 940 /* Store the pointer in the pipe handle */
941 941 ph->p_hcd_private = (usb_opaque_t)pp;
942 942
943 943 /* Store a copy of the pipe policy */
944 944 bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t));
945 945
946 946 mutex_exit(&ph->p_mutex);
947 947
948 948 /* Allocate the host controller endpoint descriptor */
949 949 pp->pp_qh = ehci_alloc_qh(ehcip, ph, NULL);
950 950
951 951 /* Initialize the halting flag */
952 952 pp->pp_halt_state = EHCI_HALT_STATE_FREE;
953 953
954 954 /* Create prototype for halt completion condition variable */
955 955 cv_init(&pp->pp_halt_cmpl_cv, NULL, CV_DRIVER, NULL);
956 956
957 957 /* Isoch does not use QH, so ignore this */
958 958 if ((pp->pp_qh == NULL) && !(EHCI_ISOC_ENDPOINT(epdt))) {
959 959 ASSERT(pp->pp_qh == NULL);
960 960
961 961 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
962 962 "ehci_hcdi_pipe_open: QH allocation failed");
963 963
964 964 mutex_enter(&ph->p_mutex);
965 965
966 966 /* Deallocate bandwidth */
967 967 if (EHCI_PERIODIC_ENDPOINT(epdt)) {
968 968
969 969 ehci_deallocate_bandwidth(ehcip,
970 970 ph, pnode, smask, cmask);
971 971 }
972 972
973 973 /* Destroy the xfer completion condition variable */
974 974 cv_destroy(&pp->pp_xfer_cmpl_cv);
975 975
976 976 /*
977 977 * Deallocate the hcd private portion
978 978 * of the pipe handle.
979 979 */
980 980 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t));
981 981
982 982 /*
983 983 * Set the private structure in the
984 984 * pipe handle equal to NULL.
985 985 */
986 986 ph->p_hcd_private = NULL;
987 987
988 988 mutex_exit(&ph->p_mutex);
989 989 mutex_exit(&ehcip->ehci_int_mutex);
990 990
991 991 return (USB_NO_RESOURCES);
992 992 }
993 993
994 994 /*
995 995 * Isoch does not use QH so no need to
996 996 * restore data toggle or insert QH
997 997 */
998 998 if (!(EHCI_ISOC_ENDPOINT(epdt))) {
999 999 /* Restore the data toggle information */
1000 1000 ehci_restore_data_toggle(ehcip, ph);
1001 1001 }
1002 1002
1003 1003 /*
1004 1004 * Insert the endpoint onto the host controller's
1005 1005 * appropriate endpoint list. The host controller
1006 1006 * will not schedule this endpoint and will not have
1007 1007 * any QTD's to process. It will also update the pipe count.
1008 1008 */
1009 1009 ehci_insert_qh(ehcip, ph);
1010 1010
1011 1011 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1012 1012 "ehci_hcdi_pipe_open: ph = 0x%p", (void *)ph);
1013 1013
1014 1014 ehcip->ehci_open_pipe_count++;
1015 1015
1016 1016 mutex_exit(&ehcip->ehci_int_mutex);
1017 1017
1018 1018 return (USB_SUCCESS);
1019 1019 }
1020 1020
1021 1021
1022 1022 /*
1023 1023 * ehci_hcdi_pipe_close:
1024 1024 *
1025 1025 * Member of HCD Ops structure and called during the client specific pipe
1026 1026 * close. Remove the pipe and the data structure representing the device.
1027 1027 * Deallocate bandwidth for the pipe if it is a interrupt or isochronous
1028 1028 * endpoint.
1029 1029 */
1030 1030 /* ARGSUSED */
1031 1031 int
1032 1032 ehci_hcdi_pipe_close(
1033 1033 usba_pipe_handle_data_t *ph,
1034 1034 usb_flags_t flags)
1035 1035 {
1036 1036 ehci_state_t *ehcip = ehci_obtain_state(
1037 1037 ph->p_usba_device->usb_root_hub_dip);
1038 1038 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1039 1039 usb_ep_descr_t *eptd = &ph->p_ep;
1040 1040 int error = USB_SUCCESS;
1041 1041
1042 1042 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1043 1043 "ehci_hcdi_pipe_close: addr = 0x%x, ep%d",
1044 1044 ph->p_usba_device->usb_addr,
1045 1045 eptd->bEndpointAddress & USB_EP_NUM_MASK);
1046 1046
1047 1047 /* Check and handle root hub pipe close */
1048 1048 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
1049 1049
1050 1050 mutex_enter(&ehcip->ehci_int_mutex);
1051 1051 error = ehci_handle_root_hub_pipe_close(ph);
1052 1052 mutex_exit(&ehcip->ehci_int_mutex);
1053 1053
1054 1054 return (error);
1055 1055 }
1056 1056
1057 1057 ASSERT(ph->p_hcd_private != NULL);
1058 1058
1059 1059 mutex_enter(&ehcip->ehci_int_mutex);
1060 1060
1061 1061 /* Set pipe state to pipe close */
1062 1062 pp->pp_state = EHCI_PIPE_STATE_CLOSE;
1063 1063
1064 1064 ehci_pipe_cleanup(ehcip, ph);
1065 1065
1066 1066 /*
1067 1067 * Remove the endpoint descriptor from Host
1068 1068 * Controller's appropriate endpoint list.
1069 1069 */
1070 1070 ehci_remove_qh(ehcip, pp, B_TRUE);
1071 1071
1072 1072 /* Deallocate bandwidth */
1073 1073 if (EHCI_PERIODIC_ENDPOINT(eptd)) {
1074 1074
1075 1075 mutex_enter(&ph->p_mutex);
1076 1076 ehci_deallocate_bandwidth(ehcip, ph, pp->pp_pnode,
1077 1077 pp->pp_smask, pp->pp_cmask);
1078 1078 mutex_exit(&ph->p_mutex);
1079 1079 }
1080 1080
1081 1081 mutex_enter(&ph->p_mutex);
1082 1082
1083 1083 /* Destroy the xfer completion condition variable */
1084 1084 cv_destroy(&pp->pp_xfer_cmpl_cv);
1085 1085
1086 1086
1087 1087 /* Destory halt completion condition variable */
1088 1088 cv_destroy(&pp->pp_halt_cmpl_cv);
1089 1089
1090 1090 /*
1091 1091 * Deallocate the hcd private portion
1092 1092 * of the pipe handle.
1093 1093 */
1094 1094 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t));
1095 1095 ph->p_hcd_private = NULL;
1096 1096
1097 1097 mutex_exit(&ph->p_mutex);
1098 1098
1099 1099 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1100 1100 "ehci_hcdi_pipe_close: ph = 0x%p", (void *)ph);
1101 1101
1102 1102 ehcip->ehci_open_pipe_count--;
1103 1103
1104 1104 mutex_exit(&ehcip->ehci_int_mutex);
1105 1105
1106 1106 return (error);
1107 1107 }
1108 1108
1109 1109
1110 1110 /*
1111 1111 * ehci_hcdi_pipe_reset:
1112 1112 */
1113 1113 /* ARGSUSED */
1114 1114 int
1115 1115 ehci_hcdi_pipe_reset(
1116 1116 usba_pipe_handle_data_t *ph,
1117 1117 usb_flags_t usb_flags)
1118 1118 {
1119 1119 ehci_state_t *ehcip = ehci_obtain_state(
1120 1120 ph->p_usba_device->usb_root_hub_dip);
1121 1121 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1122 1122 int error = USB_SUCCESS;
1123 1123
1124 1124 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1125 1125 "ehci_hcdi_pipe_reset:");
1126 1126
1127 1127 /*
1128 1128 * Check and handle root hub pipe reset.
1129 1129 */
1130 1130 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
1131 1131
1132 1132 error = ehci_handle_root_hub_pipe_reset(ph, usb_flags);
1133 1133 return (error);
1134 1134 }
1135 1135
1136 1136 mutex_enter(&ehcip->ehci_int_mutex);
1137 1137
1138 1138 /* Set pipe state to pipe reset */
1139 1139 pp->pp_state = EHCI_PIPE_STATE_RESET;
1140 1140
1141 1141 ehci_pipe_cleanup(ehcip, ph);
1142 1142
1143 1143 mutex_exit(&ehcip->ehci_int_mutex);
1144 1144
1145 1145 return (error);
1146 1146 }
1147 1147
1148 1148 /*
1149 1149 * ehci_hcdi_pipe_reset_data_toggle:
1150 1150 */
1151 1151 void
1152 1152 ehci_hcdi_pipe_reset_data_toggle(
1153 1153 usba_pipe_handle_data_t *ph)
1154 1154 {
1155 1155 ehci_state_t *ehcip = ehci_obtain_state(
1156 1156 ph->p_usba_device->usb_root_hub_dip);
1157 1157 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1158 1158
1159 1159 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1160 1160 "ehci_hcdi_pipe_reset_data_toggle:");
1161 1161
1162 1162 mutex_enter(&ehcip->ehci_int_mutex);
1163 1163
1164 1164 mutex_enter(&ph->p_mutex);
1165 1165 usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
1166 1166 DATA0);
1167 1167 mutex_exit(&ph->p_mutex);
1168 1168
1169 1169 Set_QH(pp->pp_qh->qh_status,
1170 1170 Get_QH(pp->pp_qh->qh_status) & (~EHCI_QH_STS_DATA_TOGGLE));
1171 1171 mutex_exit(&ehcip->ehci_int_mutex);
1172 1172
1173 1173 }
1174 1174
1175 1175 /*
1176 1176 * ehci_hcdi_pipe_ctrl_xfer:
1177 1177 */
1178 1178 int
1179 1179 ehci_hcdi_pipe_ctrl_xfer(
1180 1180 usba_pipe_handle_data_t *ph,
1181 1181 usb_ctrl_req_t *ctrl_reqp,
1182 1182 usb_flags_t usb_flags)
1183 1183 {
1184 1184 ehci_state_t *ehcip = ehci_obtain_state(
1185 1185 ph->p_usba_device->usb_root_hub_dip);
1186 1186 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1187 1187 int rval;
1188 1188 int error = USB_SUCCESS;
1189 1189 ehci_trans_wrapper_t *tw;
1190 1190
1191 1191 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1192 1192 "ehci_hcdi_pipe_ctrl_xfer: ph = 0x%p reqp = 0x%p flags = %x",
1193 1193 (void *)ph, (void *)ctrl_reqp, usb_flags);
1194 1194
1195 1195 mutex_enter(&ehcip->ehci_int_mutex);
1196 1196 rval = ehci_state_is_operational(ehcip);
1197 1197 mutex_exit(&ehcip->ehci_int_mutex);
1198 1198
1199 1199 if (rval != USB_SUCCESS) {
1200 1200
1201 1201 return (rval);
1202 1202 }
1203 1203
1204 1204 /*
1205 1205 * Check and handle root hub control request.
1206 1206 */
1207 1207 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
1208 1208
1209 1209 error = ehci_handle_root_hub_request(ehcip, ph, ctrl_reqp);
1210 1210
1211 1211 return (error);
1212 1212 }
1213 1213
1214 1214 mutex_enter(&ehcip->ehci_int_mutex);
1215 1215
1216 1216 /*
1217 1217 * Check whether pipe is in halted state.
1218 1218 */
1219 1219 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) {
1220 1220
1221 1221 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1222 1222 "ehci_hcdi_pipe_ctrl_xfer: "
1223 1223 "Pipe is in error state, need pipe reset to continue");
1224 1224
1225 1225 mutex_exit(&ehcip->ehci_int_mutex);
1226 1226
1227 1227 return (USB_FAILURE);
1228 1228 }
1229 1229
1230 1230 /* Allocate a transfer wrapper */
1231 1231 if ((tw = ehci_allocate_ctrl_resources(ehcip, pp, ctrl_reqp,
1232 1232 usb_flags)) == NULL) {
1233 1233
1234 1234 error = USB_NO_RESOURCES;
1235 1235 } else {
1236 1236 /* Insert the qtd's on the endpoint */
1237 1237 ehci_insert_ctrl_req(ehcip, ph, ctrl_reqp, tw, usb_flags);
1238 1238 }
1239 1239
1240 1240 mutex_exit(&ehcip->ehci_int_mutex);
1241 1241
1242 1242 return (error);
1243 1243 }
1244 1244
1245 1245
1246 1246 /*
1247 1247 * ehci_hcdi_bulk_transfer_size:
1248 1248 *
1249 1249 * Return maximum bulk transfer size
1250 1250 */
1251 1251
1252 1252 /* ARGSUSED */
1253 1253 int
1254 1254 ehci_hcdi_bulk_transfer_size(
1255 1255 usba_device_t *usba_device,
1256 1256 size_t *size)
1257 1257 {
1258 1258 ehci_state_t *ehcip = ehci_obtain_state(
1259 1259 usba_device->usb_root_hub_dip);
1260 1260 int rval;
1261 1261
1262 1262 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1263 1263 "ehci_hcdi_bulk_transfer_size:");
1264 1264
1265 1265 mutex_enter(&ehcip->ehci_int_mutex);
1266 1266 rval = ehci_state_is_operational(ehcip);
1267 1267 mutex_exit(&ehcip->ehci_int_mutex);
1268 1268
1269 1269 if (rval != USB_SUCCESS) {
1270 1270
1271 1271 return (rval);
1272 1272 }
1273 1273
1274 1274 /* VIA VT6202 may not handle bigger xfers well, workaround. */
1275 1275 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) &&
1276 1276 (ehci_vt62x2_workaround & EHCI_VIA_REDUCED_MAX_BULK_XFER_SIZE)) {
1277 1277 *size = EHCI_VIA_MAX_BULK_XFER_SIZE;
1278 1278 } else {
1279 1279 *size = EHCI_MAX_BULK_XFER_SIZE;
1280 1280 }
1281 1281
1282 1282 return (USB_SUCCESS);
1283 1283 }
1284 1284
1285 1285
1286 1286 /*
1287 1287 * ehci_hcdi_pipe_bulk_xfer:
1288 1288 */
1289 1289 int
1290 1290 ehci_hcdi_pipe_bulk_xfer(
1291 1291 usba_pipe_handle_data_t *ph,
1292 1292 usb_bulk_req_t *bulk_reqp,
1293 1293 usb_flags_t usb_flags)
1294 1294 {
1295 1295 ehci_state_t *ehcip = ehci_obtain_state(
1296 1296 ph->p_usba_device->usb_root_hub_dip);
1297 1297 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1298 1298 int rval, error = USB_SUCCESS;
1299 1299 ehci_trans_wrapper_t *tw;
1300 1300
1301 1301 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1302 1302 "ehci_hcdi_pipe_bulk_xfer: ph = 0x%p reqp = 0x%p flags = %x",
1303 1303 (void *)ph, (void *)bulk_reqp, usb_flags);
1304 1304
1305 1305 mutex_enter(&ehcip->ehci_int_mutex);
1306 1306 rval = ehci_state_is_operational(ehcip);
1307 1307
1308 1308 if (rval != USB_SUCCESS) {
1309 1309 mutex_exit(&ehcip->ehci_int_mutex);
1310 1310
1311 1311 return (rval);
1312 1312 }
1313 1313
1314 1314 /*
1315 1315 * Check whether pipe is in halted state.
1316 1316 */
1317 1317 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) {
1318 1318
1319 1319 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1320 1320 "ehci_hcdi_pipe_bulk_xfer:"
1321 1321 "Pipe is in error state, need pipe reset to continue");
1322 1322
1323 1323 mutex_exit(&ehcip->ehci_int_mutex);
1324 1324
1325 1325 return (USB_FAILURE);
1326 1326 }
1327 1327
1328 1328 /* Allocate a transfer wrapper */
1329 1329 if ((tw = ehci_allocate_bulk_resources(ehcip, pp, bulk_reqp,
1330 1330 usb_flags)) == NULL) {
1331 1331
1332 1332 error = USB_NO_RESOURCES;
1333 1333 } else {
1334 1334 /* Add the QTD into the Host Controller's bulk list */
1335 1335 ehci_insert_bulk_req(ehcip, ph, bulk_reqp, tw, usb_flags);
1336 1336 }
1337 1337
1338 1338 mutex_exit(&ehcip->ehci_int_mutex);
1339 1339
1340 1340 return (error);
1341 1341 }
1342 1342
1343 1343
1344 1344 /*
1345 1345 * ehci_hcdi_pipe_intr_xfer:
1346 1346 */
1347 1347 int
1348 1348 ehci_hcdi_pipe_intr_xfer(
1349 1349 usba_pipe_handle_data_t *ph,
1350 1350 usb_intr_req_t *intr_reqp,
1351 1351 usb_flags_t usb_flags)
1352 1352 {
1353 1353 ehci_state_t *ehcip = ehci_obtain_state(
1354 1354 ph->p_usba_device->usb_root_hub_dip);
1355 1355 int pipe_dir, rval, error = USB_SUCCESS;
1356 1356 ehci_trans_wrapper_t *tw;
1357 1357
1358 1358 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1359 1359 "ehci_hcdi_pipe_intr_xfer: ph = 0x%p reqp = 0x%p flags = %x",
1360 1360 (void *)ph, (void *)intr_reqp, usb_flags);
1361 1361
1362 1362 mutex_enter(&ehcip->ehci_int_mutex);
1363 1363 rval = ehci_state_is_operational(ehcip);
1364 1364
1365 1365 if (rval != USB_SUCCESS) {
1366 1366 mutex_exit(&ehcip->ehci_int_mutex);
1367 1367
1368 1368 return (rval);
1369 1369 }
1370 1370
1371 1371 /* Get the pipe direction */
1372 1372 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
1373 1373
1374 1374 if (pipe_dir == USB_EP_DIR_IN) {
1375 1375 error = ehci_start_periodic_pipe_polling(ehcip, ph,
1376 1376 (usb_opaque_t)intr_reqp, usb_flags);
1377 1377 } else {
1378 1378 /* Allocate transaction resources */
1379 1379 if ((tw = ehci_allocate_intr_resources(ehcip, ph,
1380 1380 intr_reqp, usb_flags)) == NULL) {
1381 1381
1382 1382 error = USB_NO_RESOURCES;
1383 1383 } else {
1384 1384 ehci_insert_intr_req(ehcip,
1385 1385 (ehci_pipe_private_t *)ph->p_hcd_private,
1386 1386 tw, usb_flags);
1387 1387 }
1388 1388 }
1389 1389
1390 1390 mutex_exit(&ehcip->ehci_int_mutex);
1391 1391
1392 1392 return (error);
1393 1393 }
1394 1394
1395 1395 /*
1396 1396 * ehci_hcdi_pipe_stop_intr_polling()
1397 1397 */
1398 1398 int
1399 1399 ehci_hcdi_pipe_stop_intr_polling(
1400 1400 usba_pipe_handle_data_t *ph,
1401 1401 usb_flags_t flags)
1402 1402 {
1403 1403 ehci_state_t *ehcip = ehci_obtain_state(
1404 1404 ph->p_usba_device->usb_root_hub_dip);
1405 1405 int error = USB_SUCCESS;
1406 1406
1407 1407 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1408 1408 "ehci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x",
1409 1409 (void *)ph, flags);
1410 1410
1411 1411 mutex_enter(&ehcip->ehci_int_mutex);
1412 1412
1413 1413 error = ehci_stop_periodic_pipe_polling(ehcip, ph, flags);
1414 1414
1415 1415 mutex_exit(&ehcip->ehci_int_mutex);
1416 1416
1417 1417 return (error);
1418 1418 }
1419 1419
1420 1420
1421 1421 /*
1422 1422 * ehci_hcdi_get_current_frame_number:
1423 1423 *
1424 1424 * Get the current usb frame number.
1425 1425 * Return whether the request is handled successfully.
1426 1426 */
1427 1427 int
1428 1428 ehci_hcdi_get_current_frame_number(
1429 1429 usba_device_t *usba_device,
1430 1430 usb_frame_number_t *frame_number)
1431 1431 {
1432 1432 ehci_state_t *ehcip = ehci_obtain_state(
1433 1433 usba_device->usb_root_hub_dip);
1434 1434 int rval;
1435 1435
1436 1436 ehcip = ehci_obtain_state(usba_device->usb_root_hub_dip);
1437 1437
1438 1438 mutex_enter(&ehcip->ehci_int_mutex);
1439 1439 rval = ehci_state_is_operational(ehcip);
1440 1440
1441 1441 if (rval != USB_SUCCESS) {
1442 1442 mutex_exit(&ehcip->ehci_int_mutex);
1443 1443
1444 1444 return (rval);
1445 1445 }
1446 1446
1447 1447 *frame_number = ehci_get_current_frame_number(ehcip);
1448 1448
1449 1449 mutex_exit(&ehcip->ehci_int_mutex);
1450 1450
1451 1451 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1452 1452 "ehci_hcdi_get_current_frame_number: "
1453 1453 "Current frame number 0x%llx", (unsigned long long)(*frame_number));
1454 1454
1455 1455 return (rval);
1456 1456 }
1457 1457
1458 1458
1459 1459 /*
1460 1460 * ehci_hcdi_get_max_isoc_pkts:
1461 1461 *
1462 1462 * Get maximum isochronous packets per usb isochronous request.
1463 1463 * Return whether the request is handled successfully.
1464 1464 */
1465 1465 int
1466 1466 ehci_hcdi_get_max_isoc_pkts(
1467 1467 usba_device_t *usba_device,
1468 1468 uint_t *max_isoc_pkts_per_request)
1469 1469 {
1470 1470 ehci_state_t *ehcip = ehci_obtain_state(
1471 1471 usba_device->usb_root_hub_dip);
1472 1472 int rval;
1473 1473
1474 1474 mutex_enter(&ehcip->ehci_int_mutex);
1475 1475 rval = ehci_state_is_operational(ehcip);
1476 1476 mutex_exit(&ehcip->ehci_int_mutex);
1477 1477
1478 1478 if (rval != USB_SUCCESS) {
1479 1479
1480 1480 return (rval);
1481 1481 }
1482 1482
1483 1483 *max_isoc_pkts_per_request = EHCI_MAX_ISOC_PKTS_PER_XFER;
1484 1484
1485 1485 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1486 1486 "ehci_hcdi_get_max_isoc_pkts: maximum isochronous"
1487 1487 "packets per usb isochronous request = 0x%x",
1488 1488 *max_isoc_pkts_per_request);
1489 1489
1490 1490 return (rval);
1491 1491 }
1492 1492
1493 1493
1494 1494 /*
1495 1495 * ehci_hcdi_pipe_isoc_xfer:
1496 1496 */
1497 1497 int
1498 1498 ehci_hcdi_pipe_isoc_xfer(
1499 1499 usba_pipe_handle_data_t *ph,
1500 1500 usb_isoc_req_t *isoc_reqp,
1501 1501 usb_flags_t usb_flags)
1502 1502 {
1503 1503 ehci_state_t *ehcip = ehci_obtain_state(
1504 1504 ph->p_usba_device->usb_root_hub_dip);
1505 1505
1506 1506 int pipe_dir, rval;
1507 1507 ehci_isoc_xwrapper_t *itw;
1508 1508
1509 1509 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1510 1510 "ehci_hcdi_pipe_isoc_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
1511 1511 (void *)ph, (void *)isoc_reqp, usb_flags);
1512 1512
1513 1513 mutex_enter(&ehcip->ehci_int_mutex);
1514 1514 rval = ehci_state_is_operational(ehcip);
1515 1515
1516 1516 if (rval != USB_SUCCESS) {
1517 1517 mutex_exit(&ehcip->ehci_int_mutex);
1518 1518
1519 1519 return (rval);
1520 1520 }
1521 1521
1522 1522 /* Get the isochronous pipe direction */
1523 1523 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
1524 1524
1525 1525 if (pipe_dir == USB_EP_DIR_IN) {
1526 1526 rval = ehci_start_periodic_pipe_polling(ehcip, ph,
1527 1527 (usb_opaque_t)isoc_reqp, usb_flags);
1528 1528 } else {
1529 1529 /* Allocate transaction resources */
1530 1530 if ((itw = ehci_allocate_isoc_resources(ehcip, ph,
1531 1531 isoc_reqp, usb_flags)) == NULL) {
1532 1532 rval = USB_NO_RESOURCES;
1533 1533 } else {
1534 1534 rval = ehci_insert_isoc_req(ehcip,
1535 1535 (ehci_pipe_private_t *)ph->p_hcd_private,
1536 1536 itw, usb_flags);
1537 1537 }
1538 1538 }
1539 1539
1540 1540 mutex_exit(&ehcip->ehci_int_mutex);
1541 1541
1542 1542 return (rval);
1543 1543 }
1544 1544
1545 1545
1546 1546 /*
1547 1547 * ehci_hcdi_pipe_stop_isoc_polling()
1548 1548 */
1549 1549 /*ARGSUSED*/
1550 1550 int
1551 1551 ehci_hcdi_pipe_stop_isoc_polling(
1552 1552 usba_pipe_handle_data_t *ph,
1553 1553 usb_flags_t flags)
1554 1554 {
1555 1555 ehci_state_t *ehcip = ehci_obtain_state(
1556 1556 ph->p_usba_device->usb_root_hub_dip);
1557 1557 int rval;
1558 1558
1559 1559 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1560 1560 "ehci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x",
1561 1561 (void *)ph, flags);
1562 1562
1563 1563 mutex_enter(&ehcip->ehci_int_mutex);
1564 1564 rval = ehci_state_is_operational(ehcip);
1565 1565
1566 1566 if (rval != USB_SUCCESS) {
1567 1567 mutex_exit(&ehcip->ehci_int_mutex);
1568 1568
1569 1569 return (rval);
1570 1570 }
1571 1571
1572 1572 rval = ehci_stop_periodic_pipe_polling(ehcip, ph, flags);
1573 1573
1574 1574 mutex_exit(&ehcip->ehci_int_mutex);
1575 1575
1576 1576 return (rval);
1577 1577 }
↓ open down ↓ |
1423 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX