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