Print this page
XXXX introduce drv_sectohz
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/usb/hcd/uhci/uhci.c
+++ new/usr/src/uts/common/io/usb/hcd/uhci/uhci.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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25
26 26 /*
27 27 * Universal Host Controller Driver (UHCI)
28 28 *
29 29 * The UHCI driver is a driver which interfaces to the Universal
30 30 * Serial Bus Architecture (USBA) and the Host Controller (HC). The interface to
31 31 * the Host Controller is defined by the Universal Host Controller Interface.
32 32 * This file contains code for auto-configuration entry points and interrupt
33 33 * handling.
34 34 */
35 35 #include <sys/usb/hcd/uhci/uhcid.h>
36 36 #include <sys/usb/hcd/uhci/uhcihub.h>
37 37 #include <sys/usb/hcd/uhci/uhciutil.h>
38 38
39 39 /*
40 40 * Prototype Declarations for cb_ops and dev_ops
41 41 */
42 42 static int uhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
43 43 static int uhci_add_intrs(uhci_state_t *uhcip, int intr_type);
44 44 static int uhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
45 45 static void uhci_rem_intrs(uhci_state_t *uhcip);
46 46 static int uhci_open(dev_t *devp, int flags, int otyp, cred_t *credp);
47 47 static int uhci_close(dev_t dev, int flag, int otyp, cred_t *credp);
48 48 static int uhci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
49 49 cred_t *credp, int *rvalp);
50 50 static int uhci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd);
51 51 static int uhci_quiesce(dev_info_t *dip);
52 52 static int uhci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
53 53 void **result);
54 54
55 55 /* extern */
56 56 int usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level);
57 57
58 58 static struct cb_ops uhci_cb_ops = {
59 59 uhci_open, /* Open */
60 60 uhci_close, /* Close */
61 61 nodev, /* Strategy */
62 62 nodev, /* Print */
63 63 nodev, /* Dump */
64 64 nodev, /* Read */
65 65 nodev, /* Write */
66 66 uhci_ioctl, /* Ioctl */
67 67 nodev, /* Devmap */
68 68 nodev, /* Mmap */
69 69 nodev, /* Segmap */
70 70 nochpoll, /* Poll */
71 71 ddi_prop_op, /* cb_prop_op */
72 72 NULL, /* Streamtab */
73 73 D_MP /* Driver compatibility flag */
74 74 };
75 75
76 76 static struct dev_ops uhci_ops = {
77 77 DEVO_REV, /* Devo_rev */
78 78 0, /* Refcnt */
79 79 uhci_info, /* Info */
80 80 nulldev, /* Identify */
81 81 nulldev, /* Probe */
82 82 uhci_attach, /* Attach */
83 83 uhci_detach, /* Detach */
84 84 uhci_reset, /* Reset */
85 85 &uhci_cb_ops, /* Driver operations */
86 86 &usba_hubdi_busops, /* Bus operations */
87 87 usba_hubdi_root_hub_power, /* Power */
88 88 uhci_quiesce /* quiesce */
89 89 };
90 90
91 91 static struct modldrv modldrv = {
92 92 &mod_driverops, /* Type of module. This one is a driver */
93 93 "USB UHCI Controller Driver", /* Name of the module. */
94 94 &uhci_ops, /* Driver ops */
95 95 };
96 96
97 97 static struct modlinkage modlinkage = {
98 98 MODREV_1, (void *)&modldrv, NULL
99 99 };
100 100
101 101 /*
102 102 * Globals
103 103 */
104 104 void *uhci_statep;
105 105 uint_t uhci_errlevel = USB_LOG_L2;
106 106 uint_t uhci_errmask = PRINT_MASK_ALL;
107 107 uint_t uhci_instance_debug = (uint_t)-1;
108 108
109 109 uint_t uhci_td_pool_size = 256; /* Num TDs */
110 110 uint_t uhci_qh_pool_size = 130; /* Num QHs */
111 111 ushort_t uhci_tree_bottom_nodes[NUM_FRAME_LST_ENTRIES];
112 112
113 113
114 114 /*
115 115 * UHCI MSI tunable:
116 116 *
117 117 * By default MSI is enabled on all supported platforms.
118 118 */
119 119 boolean_t uhci_enable_msi = B_TRUE;
120 120
121 121 /*
122 122 * tunable, delay during attach in seconds
123 123 */
124 124 int uhci_attach_wait = 0;
125 125
126 126 /* function prototypes */
127 127 static void uhci_handle_intr_td_errors(uhci_state_t *uhcip, uhci_td_t *td,
128 128 uhci_trans_wrapper_t *tw, uhci_pipe_private_t *pp);
129 129 static void uhci_handle_one_xfer_completion(uhci_state_t *uhcip,
130 130 usb_cr_t usb_err, uhci_td_t *td);
131 131 static uint_t uhci_intr(caddr_t arg1, caddr_t arg2);
132 132 static int uhci_cleanup(uhci_state_t *uhcip);
133 133 static int uhci_cpr_suspend(uhci_state_t *uhcip);
134 134 static int uhci_cpr_resume(uhci_state_t *uhcip);
135 135
136 136
137 137 int
138 138 _init(void)
139 139 {
140 140 int error;
141 141 ushort_t i, j, k, *temp, num_of_nodes;
142 142
143 143 /* Initialize the soft state structures */
144 144 if ((error = ddi_soft_state_init(&uhci_statep, sizeof (uhci_state_t),
145 145 UHCI_MAX_INSTS)) != 0) {
146 146
147 147 return (error);
148 148 }
149 149
150 150 /* Install the loadable module */
151 151 if ((error = mod_install(&modlinkage)) != 0) {
152 152 ddi_soft_state_fini(&uhci_statep);
153 153
154 154 return (error);
155 155 }
156 156
157 157 /*
158 158 * Build the tree bottom shared by all instances
159 159 */
160 160 temp = kmem_zalloc(NUM_FRAME_LST_ENTRIES * 2, KM_SLEEP);
161 161
162 162 num_of_nodes = 1;
163 163 for (i = 0; i < log_2(NUM_FRAME_LST_ENTRIES); i++) {
164 164 for (j = 0, k = 0; k < num_of_nodes; k++, j++) {
165 165 uhci_tree_bottom_nodes[j++] = temp[k];
166 166 uhci_tree_bottom_nodes[j] = temp[k] + pow_2(i);
167 167 }
168 168
169 169 num_of_nodes *= 2;
170 170 for (k = 0; k < num_of_nodes; k++)
171 171 temp[k] = uhci_tree_bottom_nodes[k];
172 172
173 173 }
174 174 kmem_free(temp, (NUM_FRAME_LST_ENTRIES*2));
175 175
176 176
177 177 return (error);
178 178 }
179 179
180 180
181 181 int
182 182 _info(struct modinfo *modinfop)
183 183 {
184 184 return (mod_info(&modlinkage, modinfop));
185 185 }
186 186
187 187
188 188 int
189 189 _fini(void)
190 190 {
191 191 int error;
192 192
193 193 error = mod_remove(&modlinkage);
194 194
195 195 if (error == 0) {
196 196 /* Release per module resources */
197 197 ddi_soft_state_fini(&uhci_statep);
198 198 }
199 199
200 200 return (error);
201 201 }
202 202
203 203 /*
204 204 * The following simulated polling is for debugging purposes only.
205 205 * It is activated on x86 by setting usb-polling=true in GRUB or uhci.conf.
206 206 */
207 207 static int
208 208 uhci_is_polled(dev_info_t *dip)
209 209 {
210 210 int ret;
211 211 char *propval;
212 212
213 213 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
214 214 "usb-polling", &propval) != DDI_SUCCESS)
215 215
216 216 return (0);
217 217
218 218 ret = (strcmp(propval, "true") == 0);
219 219 ddi_prop_free(propval);
220 220
221 221 return (ret);
222 222 }
223 223
224 224 static void
225 225 uhci_poll_intr(void *arg)
226 226 {
227 227 /* poll every msec */
228 228 for (;;) {
229 229 (void) uhci_intr(arg, NULL);
230 230 delay(drv_usectohz(1000));
231 231 }
232 232 }
233 233
234 234 /*
235 235 * Host Controller Driver (HCD) Auto configuration entry points
236 236 */
237 237
238 238 /*
239 239 * Function Name : uhci_attach:
240 240 * Description : Attach entry point - called by the Kernel.
241 241 * Allocates of per controller data structure.
242 242 * Initializes the controller.
243 243 * Output : DDI_SUCCESS / DDI_FAILURE
244 244 */
245 245 static int
246 246 uhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
247 247 {
248 248 int instance, polled;
249 249 int i, intr_types;
250 250 uhci_state_t *uhcip = NULL;
251 251 usba_hcdi_register_args_t hcdi_args;
252 252
253 253 USB_DPRINTF_L4(PRINT_MASK_ATTA, NULL, "uhci_attach:");
254 254
255 255 switch (cmd) {
256 256 case DDI_ATTACH:
257 257 break;
258 258 case DDI_RESUME:
259 259 uhcip = uhci_obtain_state(dip);
260 260
261 261 return (uhci_cpr_resume(uhcip));
262 262 default:
263 263
264 264 return (DDI_FAILURE);
265 265 }
266 266
267 267 /* Get the instance and create soft state */
268 268 instance = ddi_get_instance(dip);
269 269
270 270 /* Allocate the soft state structure for this instance of the driver */
271 271 if (ddi_soft_state_zalloc(uhci_statep, instance) != 0) {
272 272
273 273 return (DDI_FAILURE);
274 274 }
275 275
276 276 if ((uhcip = ddi_get_soft_state(uhci_statep, instance)) == NULL) {
277 277
278 278 return (DDI_FAILURE);
279 279 }
280 280
281 281 uhcip->uhci_log_hdl = usb_alloc_log_hdl(dip, "uhci", &uhci_errlevel,
282 282 &uhci_errmask, &uhci_instance_debug, 0);
283 283
284 284 /* Set host controller soft state to initialization */
285 285 uhcip->uhci_hc_soft_state = UHCI_CTLR_INIT_STATE;
286 286
287 287 /* Save the dip and instance */
288 288 uhcip->uhci_dip = dip;
289 289 uhcip->uhci_instance = instance;
290 290
291 291 polled = uhci_is_polled(dip);
292 292 if (polled)
293 293
294 294 goto skip_intr;
295 295
296 296 /* Get supported interrupt types */
297 297 if (ddi_intr_get_supported_types(uhcip->uhci_dip,
298 298 &intr_types) != DDI_SUCCESS) {
299 299 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
300 300 "uhci_attach: ddi_intr_get_supported_types failed");
301 301
302 302 usb_free_log_hdl(uhcip->uhci_log_hdl);
303 303 ddi_soft_state_free(uhci_statep, instance);
304 304
305 305 return (DDI_FAILURE);
306 306 }
307 307
308 308 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
309 309 "uhci_attach: supported interrupt types 0x%x", intr_types);
310 310
311 311 if ((intr_types & DDI_INTR_TYPE_MSI) && uhci_enable_msi) {
312 312 if (uhci_add_intrs(uhcip, DDI_INTR_TYPE_MSI)
313 313 != DDI_SUCCESS) {
314 314 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
315 315 "uhci_attach: MSI registration failed, "
316 316 "trying FIXED interrupt \n");
317 317 } else {
318 318 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
319 319 "uhci_attach: Using MSI interrupt type\n");
320 320
321 321 uhcip->uhci_intr_type = DDI_INTR_TYPE_MSI;
322 322 }
323 323 }
324 324
325 325 if (!(uhcip->uhci_htable) && (intr_types & DDI_INTR_TYPE_FIXED)) {
326 326 if (uhci_add_intrs(uhcip, DDI_INTR_TYPE_FIXED)
327 327 != DDI_SUCCESS) {
328 328 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
329 329 "uhci_attach: FIXED interrupt registration "
330 330 "failed\n");
331 331
332 332 usb_free_log_hdl(uhcip->uhci_log_hdl);
333 333 ddi_soft_state_free(uhci_statep, instance);
334 334
335 335 return (DDI_FAILURE);
336 336 }
337 337
338 338 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
339 339 "uhci_attach: Using FIXED interrupt type\n");
340 340
341 341 uhcip->uhci_intr_type = DDI_INTR_TYPE_FIXED;
342 342 }
343 343
344 344 skip_intr:
345 345 /* Semaphore to serialize opens and closes */
346 346 sema_init(&uhcip->uhci_ocsem, 1, NULL, SEMA_DRIVER, NULL);
347 347
348 348 /* Create prototype condition variable */
349 349 cv_init(&uhcip->uhci_cv_SOF, NULL, CV_DRIVER, NULL);
350 350
351 351 /* Initialize the DMA attributes */
352 352 uhci_set_dma_attributes(uhcip);
353 353
354 354 /* Initialize the kstat structures */
355 355 uhci_create_stats(uhcip);
356 356
357 357 /* Create the td and ed pools */
358 358 if (uhci_allocate_pools(uhcip) != USB_SUCCESS) {
359 359
360 360 goto fail;
361 361 }
362 362
363 363 /* Map the registers */
364 364 if (uhci_map_regs(uhcip) != USB_SUCCESS) {
365 365
366 366 goto fail;
367 367 }
368 368
369 369 /* Enable all interrupts */
370 370 if (polled) {
371 371 extern pri_t maxclsyspri;
372 372
373 373 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
374 374 "uhci_attach: running in simulated polled mode.");
375 375
376 376 /* create thread to poll */
377 377 (void) thread_create(NULL, 0, uhci_poll_intr, uhcip, 0, &p0,
378 378 TS_RUN, maxclsyspri);
379 379 } else if (uhcip->uhci_intr_cap & DDI_INTR_FLAG_BLOCK) {
380 380 /* Call ddi_intr_block_enable() for MSI interrupts */
381 381 (void) ddi_intr_block_enable(uhcip->uhci_htable,
382 382 uhcip->uhci_intr_cnt);
383 383 } else {
384 384 /* Call ddi_intr_enable for MSI or FIXED interrupts */
385 385 for (i = 0; i < uhcip->uhci_intr_cnt; i++)
386 386 (void) ddi_intr_enable(uhcip->uhci_htable[i]);
387 387 }
388 388
389 389
390 390 /* Initialize the controller */
391 391 if (uhci_init_ctlr(uhcip) != USB_SUCCESS) {
392 392
393 393 goto fail;
394 394 }
395 395
396 396 /*
397 397 * At this point, the hardware will be okay.
398 398 * Initialize the usba_hcdi structure
399 399 */
400 400 uhcip->uhci_hcdi_ops = uhci_alloc_hcdi_ops(uhcip);
401 401
402 402 /*
403 403 * Make this HCD instance known to USBA
404 404 * (dma_attr must be passed for USBA busctl's)
405 405 */
406 406 hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION;
407 407 hcdi_args.usba_hcdi_register_dip = dip;
408 408 hcdi_args.usba_hcdi_register_ops = uhcip->uhci_hcdi_ops;
409 409 hcdi_args.usba_hcdi_register_dma_attr = &uhcip->uhci_dma_attr;
410 410 hcdi_args.usba_hcdi_register_iblock_cookie =
411 411 (ddi_iblock_cookie_t)(uintptr_t)uhcip->uhci_intr_pri;
412 412
↓ open down ↓ |
412 lines elided |
↑ open up ↑ |
413 413 if (usba_hcdi_register(&hcdi_args, 0) != USB_SUCCESS) {
414 414
415 415 goto fail;
416 416 }
417 417
418 418 #ifndef __sparc
419 419 /*
420 420 * On NCR system, the driver seen failure of some commands
421 421 * while booting. This delay mysteriously solved the problem.
422 422 */
423 - delay(drv_usectohz(uhci_attach_wait*1000000));
423 + delay(drv_sectohz(uhci_attach_wait));
424 424 #endif
425 425
426 426 /*
427 427 * Create another timeout handler to check whether any
428 428 * control/bulk/interrupt commands failed.
429 429 * This gets called every second.
430 430 */
431 431 uhcip->uhci_cmd_timeout_id = timeout(uhci_cmd_timeout_hdlr,
432 432 (void *)uhcip, UHCI_ONE_SECOND);
433 433
434 434 mutex_enter(&uhcip->uhci_int_mutex);
435 435
436 436 /*
437 437 * Set HcInterruptEnable to enable all interrupts except Root
438 438 * Hub Status change and SOF interrupts.
439 439 */
440 440 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
441 441
442 442 /* Test the SOF interrupt */
443 443 if (uhci_wait_for_sof(uhcip) != USB_SUCCESS) {
444 444 USB_DPRINTF_L0(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
445 445 "No SOF interrupts have been received, this USB UHCI host"
446 446 " controller is unusable");
447 447 mutex_exit(&uhcip->uhci_int_mutex);
448 448
449 449 goto fail;
450 450 }
451 451
452 452 mutex_exit(&uhcip->uhci_int_mutex);
453 453
454 454 /* This should be the last step which might fail during attaching */
455 455 if (uhci_init_root_hub(uhcip) != USB_SUCCESS) {
456 456
457 457 goto fail;
458 458 }
459 459
460 460 /* Display information in the banner */
461 461 ddi_report_dev(dip);
462 462
463 463 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
464 464 "uhci_attach successful");
465 465
466 466 return (DDI_SUCCESS);
467 467
468 468 fail:
469 469 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
470 470 "failed to attach");
471 471
472 472 (void) uhci_cleanup(uhcip);
473 473
474 474 return (DDI_FAILURE);
475 475 }
476 476
477 477
478 478 /*
479 479 * uhci_add_intrs:
480 480 *
481 481 * Register FIXED or MSI interrupts.
482 482 */
483 483 static int
484 484 uhci_add_intrs(uhci_state_t *uhcip,
485 485 int intr_type)
486 486 {
487 487 int actual, avail, intr_size, count = 0;
488 488 int i, flag, ret;
489 489
490 490 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
491 491 "uhci_add_intrs: interrupt type 0x%x", intr_type);
492 492
493 493 /* Get number of interrupts */
494 494 ret = ddi_intr_get_nintrs(uhcip->uhci_dip, intr_type, &count);
495 495 if ((ret != DDI_SUCCESS) || (count == 0)) {
496 496 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
497 497 "uhci_add_intrs: ddi_intr_get_nintrs() failure, "
498 498 "ret: %d, count: %d", ret, count);
499 499
500 500 return (DDI_FAILURE);
501 501 }
502 502
503 503 /* Get number of available interrupts */
504 504 ret = ddi_intr_get_navail(uhcip->uhci_dip, intr_type, &avail);
505 505 if ((ret != DDI_SUCCESS) || (avail == 0)) {
506 506 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
507 507 "uhci_add_intrs: ddi_intr_get_navail() failure, "
508 508 "ret: %d, count: %d", ret, count);
509 509
510 510 return (DDI_FAILURE);
511 511 }
512 512
513 513 if (avail < count) {
514 514 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
515 515 "uhci_add_intrs: uhci_add_intrs: nintrs () "
516 516 "returned %d, navail returned %d\n", count, avail);
517 517 }
518 518
519 519 /* Allocate an array of interrupt handles */
520 520 intr_size = count * sizeof (ddi_intr_handle_t);
521 521 uhcip->uhci_htable = kmem_zalloc(intr_size, KM_SLEEP);
522 522
523 523 flag = (intr_type == DDI_INTR_TYPE_MSI) ?
524 524 DDI_INTR_ALLOC_STRICT:DDI_INTR_ALLOC_NORMAL;
525 525
526 526 /* call ddi_intr_alloc() */
527 527 ret = ddi_intr_alloc(uhcip->uhci_dip, uhcip->uhci_htable,
528 528 intr_type, 0, count, &actual, flag);
529 529
530 530 if ((ret != DDI_SUCCESS) || (actual == 0)) {
531 531 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
532 532 "uhci_add_intrs: ddi_intr_alloc() failed %d", ret);
533 533
534 534 kmem_free(uhcip->uhci_htable, intr_size);
535 535
536 536 return (DDI_FAILURE);
537 537 }
538 538
539 539 if (actual < count) {
540 540 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
541 541 "uhci_add_intrs: Requested: %d, Received: %d\n",
542 542 count, actual);
543 543
544 544 for (i = 0; i < actual; i++)
545 545 (void) ddi_intr_free(uhcip->uhci_htable[i]);
546 546
547 547 kmem_free(uhcip->uhci_htable, intr_size);
548 548
549 549 return (DDI_FAILURE);
550 550 }
551 551
552 552 uhcip->uhci_intr_cnt = actual;
553 553
554 554 if ((ret = ddi_intr_get_pri(uhcip->uhci_htable[0],
555 555 &uhcip->uhci_intr_pri)) != DDI_SUCCESS) {
556 556 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
557 557 "uhci_add_intrs: ddi_intr_get_pri() failed %d", ret);
558 558
559 559 for (i = 0; i < actual; i++)
560 560 (void) ddi_intr_free(uhcip->uhci_htable[i]);
561 561
562 562 kmem_free(uhcip->uhci_htable, intr_size);
563 563
564 564 return (DDI_FAILURE);
565 565 }
566 566
567 567 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
568 568 "uhci_add_intrs: Supported Interrupt priority 0x%x",
569 569 uhcip->uhci_intr_pri);
570 570
571 571 /* Test for high level mutex */
572 572 if (uhcip->uhci_intr_pri >= ddi_intr_get_hilevel_pri()) {
573 573 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
574 574 "uhci_add_intrs: Hi level interrupt not supported");
575 575
576 576 for (i = 0; i < actual; i++)
577 577 (void) ddi_intr_free(uhcip->uhci_htable[i]);
578 578
579 579 kmem_free(uhcip->uhci_htable, intr_size);
580 580
581 581 return (DDI_FAILURE);
582 582 }
583 583
584 584 /* Initialize the mutex */
585 585 mutex_init(&uhcip->uhci_int_mutex, NULL, MUTEX_DRIVER,
586 586 DDI_INTR_PRI(uhcip->uhci_intr_pri));
587 587
588 588 /* Call ddi_intr_add_handler() */
589 589 for (i = 0; i < actual; i++) {
590 590 if ((ret = ddi_intr_add_handler(uhcip->uhci_htable[i],
591 591 uhci_intr, (caddr_t)uhcip,
592 592 (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
593 593 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
594 594 "uhci_add_intrs: ddi_intr_add_handler() "
595 595 "failed %d", ret);
596 596
597 597 for (i = 0; i < actual; i++)
598 598 (void) ddi_intr_free(uhcip->uhci_htable[i]);
599 599
600 600 mutex_destroy(&uhcip->uhci_int_mutex);
601 601 kmem_free(uhcip->uhci_htable, intr_size);
602 602
603 603 return (DDI_FAILURE);
604 604 }
605 605 }
606 606
607 607 if ((ret = ddi_intr_get_cap(uhcip->uhci_htable[0],
608 608 &uhcip->uhci_intr_cap)) != DDI_SUCCESS) {
609 609 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
610 610 "uhci_add_intrs: ddi_intr_get_cap() failed %d", ret);
611 611
612 612 for (i = 0; i < actual; i++) {
613 613 (void) ddi_intr_remove_handler(uhcip->uhci_htable[i]);
614 614 (void) ddi_intr_free(uhcip->uhci_htable[i]);
615 615 }
616 616
617 617 mutex_destroy(&uhcip->uhci_int_mutex);
618 618 kmem_free(uhcip->uhci_htable, intr_size);
619 619
620 620 return (DDI_FAILURE);
621 621 }
622 622
623 623 return (DDI_SUCCESS);
624 624 }
625 625
626 626
627 627 /*
628 628 * Function Name: uhci_detach
629 629 * Description: Detach entry point - called by the Kernel.
630 630 * Deallocates all the memory
631 631 * Unregisters the interrupt handle and other resources.
632 632 * Output: DDI_SUCCESS / DDI_FAILURE
633 633 */
634 634 static int
635 635 uhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
636 636 {
637 637 uhci_state_t *uhcip = uhci_obtain_state(dip);
638 638
639 639 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
640 640 "uhci_detach:");
641 641
642 642 switch (cmd) {
643 643 case DDI_DETACH:
644 644
645 645 return (uhci_cleanup(uhcip) == USB_SUCCESS ?
646 646 DDI_SUCCESS : DDI_FAILURE);
647 647 case DDI_SUSPEND:
648 648
649 649 return (uhci_cpr_suspend(uhcip));
650 650 default:
651 651
652 652 return (DDI_FAILURE);
653 653 }
654 654 }
655 655
656 656
657 657 /*
658 658 * uhci_rem_intrs:
659 659 *
660 660 * Unregister FIXED or MSI interrupts
661 661 */
662 662 static void
663 663 uhci_rem_intrs(uhci_state_t *uhcip)
664 664 {
665 665 int i;
666 666
667 667 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
668 668 "uhci_rem_intrs: interrupt type 0x%x", uhcip->uhci_intr_type);
669 669
670 670 /* Disable all interrupts */
671 671 if (uhcip->uhci_intr_cap & DDI_INTR_FLAG_BLOCK) {
672 672 (void) ddi_intr_block_disable(uhcip->uhci_htable,
673 673 uhcip->uhci_intr_cnt);
674 674 } else {
675 675 for (i = 0; i < uhcip->uhci_intr_cnt; i++) {
676 676 (void) ddi_intr_disable(uhcip->uhci_htable[i]);
677 677 }
678 678 }
679 679
680 680 /* Call ddi_intr_remove_handler() */
681 681 for (i = 0; i < uhcip->uhci_intr_cnt; i++) {
682 682 (void) ddi_intr_remove_handler(uhcip->uhci_htable[i]);
683 683 (void) ddi_intr_free(uhcip->uhci_htable[i]);
684 684 }
685 685
686 686 kmem_free(uhcip->uhci_htable,
687 687 uhcip->uhci_intr_cnt * sizeof (ddi_intr_handle_t));
688 688 }
689 689
690 690
691 691 /*
692 692 * Function Name: uhci_reset
693 693 * Description: Reset entry point - called by the Kernel
694 694 * on the way down.
695 695 * The Toshiba laptop has been observed to hang
696 696 * on reboot when BIOS is set to suspend/resume.
697 697 * The resetting uhci on the way down solves the
698 698 * problem.
699 699 * Output: DDI_SUCCESS / DDI_FAILURE
700 700 */
701 701 /* ARGSUSED */
702 702 static int
703 703 uhci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
704 704 {
705 705 uhci_state_t *uhcip = uhci_obtain_state(dip);
706 706
707 707 /* Disable all HC ED list processing */
708 708 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
709 709 Set_OpReg16(USBCMD, 0);
710 710
711 711 return (DDI_SUCCESS);
712 712 }
713 713
714 714 /*
715 715 * quiesce(9E) entry point.
716 716 *
717 717 * This function is called when the system is single-threaded at high
718 718 * PIL with preemption disabled. Therefore, this function must not be
719 719 * blocked.
720 720 *
721 721 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
722 722 * DDI_FAILURE indicates an error condition and should almost never happen.
723 723 */
724 724 static int
725 725 uhci_quiesce(dev_info_t *dip)
726 726 {
727 727 uhci_state_t *uhcip = uhci_obtain_state(dip);
728 728
729 729 if (uhcip == NULL)
730 730 return (DDI_FAILURE);
731 731
732 732 /* Disable interrupts */
733 733 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
734 734
735 735 /* Stop the Host Controller */
736 736 Set_OpReg16(USBCMD, 0);
737 737
738 738 /* Clear all status bits */
739 739 Set_OpReg16(USBSTS, Get_OpReg16(USBSTS) & UHCI_INTR_MASK);
740 740
741 741 return (DDI_SUCCESS);
742 742 }
743 743
744 744
745 745 /*
746 746 * uhci_info:
747 747 */
748 748 /* ARGSUSED */
749 749 static int
750 750 uhci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
751 751 {
752 752 dev_t dev;
753 753 int instance;
754 754 int error = DDI_FAILURE;
755 755 uhci_state_t *uhcip;
756 756
757 757 switch (infocmd) {
758 758 case DDI_INFO_DEVT2DEVINFO:
759 759 dev = (dev_t)arg;
760 760 instance = UHCI_UNIT(dev);
761 761 uhcip = ddi_get_soft_state(uhci_statep, instance);
762 762 if (uhcip != NULL) {
763 763 *result = (void *)uhcip->uhci_dip;
764 764 if (*result != NULL) {
765 765 error = DDI_SUCCESS;
766 766 }
767 767 } else {
768 768 *result = NULL;
769 769 }
770 770
771 771 break;
772 772 case DDI_INFO_DEVT2INSTANCE:
773 773 dev = (dev_t)arg;
774 774 instance = UHCI_UNIT(dev);
775 775 *result = (void *)(uintptr_t)instance;
776 776 error = DDI_SUCCESS;
777 777
778 778 break;
779 779 default:
780 780 break;
781 781 }
782 782
783 783 return (error);
784 784 }
785 785
786 786
787 787 /*
788 788 * uhci_cleanup:
789 789 * Cleanup on attach failure or detach
790 790 */
791 791 static int
792 792 uhci_cleanup(uhci_state_t *uhcip)
793 793 {
794 794 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, "uhci_cleanup:");
795 795
796 796 if (usba_hubdi_unbind_root_hub(uhcip->uhci_dip) != USB_SUCCESS) {
797 797
798 798 return (USB_FAILURE);
799 799 }
800 800
801 801 mutex_enter(&uhcip->uhci_int_mutex);
802 802
803 803 if (uhcip->uhci_cmd_timeout_id) {
804 804 timeout_id_t timeout_id = uhcip->uhci_cmd_timeout_id;
805 805 uhcip->uhci_cmd_timeout_id = 0;
806 806 mutex_exit(&uhcip->uhci_int_mutex);
807 807 (void) untimeout(timeout_id);
808 808 mutex_enter(&uhcip->uhci_int_mutex);
809 809 }
810 810
811 811 uhci_uninit_ctlr(uhcip);
812 812
813 813 mutex_exit(&uhcip->uhci_int_mutex);
814 814
815 815 /* do interrupt cleanup */
816 816 if (uhcip->uhci_htable) {
817 817 uhci_rem_intrs(uhcip);
818 818 }
819 819
820 820 mutex_enter(&uhcip->uhci_int_mutex);
821 821
822 822 usba_hcdi_unregister(uhcip->uhci_dip);
823 823
824 824 uhci_unmap_regs(uhcip);
825 825
826 826 uhci_free_pools(uhcip);
827 827
828 828 mutex_exit(&uhcip->uhci_int_mutex);
829 829
830 830 mutex_destroy(&uhcip->uhci_int_mutex);
831 831 cv_destroy(&uhcip->uhci_cv_SOF);
832 832 sema_destroy(&uhcip->uhci_ocsem);
833 833
834 834 /* cleanup kstat structures */
835 835 uhci_destroy_stats(uhcip);
836 836
837 837 usba_free_hcdi_ops(uhcip->uhci_hcdi_ops);
838 838 usb_free_log_hdl(uhcip->uhci_log_hdl);
839 839 ddi_prop_remove_all(uhcip->uhci_dip);
840 840 ddi_soft_state_free(uhci_statep, uhcip->uhci_instance);
841 841
842 842 return (USB_SUCCESS);
843 843 }
844 844
845 845
846 846 /*
847 847 * uhci_cpr_suspend
848 848 */
849 849 static int
850 850 uhci_cpr_suspend(uhci_state_t *uhcip)
851 851 {
852 852 uint16_t cmd_reg;
853 853 int i;
854 854
855 855 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
856 856 "uhci_cpr_suspend:");
857 857
858 858 /* Call into the root hub and suspend it */
859 859 if (usba_hubdi_detach(uhcip->uhci_dip, DDI_SUSPEND) != DDI_SUCCESS) {
860 860
861 861 return (DDI_FAILURE);
862 862 }
863 863
864 864 mutex_enter(&uhcip->uhci_int_mutex);
865 865
866 866 /* Stop the Host Controller */
867 867 cmd_reg = Get_OpReg16(USBCMD);
868 868 cmd_reg &= ~USBCMD_REG_HC_RUN;
869 869 Set_OpReg16(USBCMD, cmd_reg);
870 870
871 871 /*
872 872 * Wait for the duration of an SOF period until the host controller
873 873 * reaches the stopped state, indicated by the HCHalted bit in the
874 874 * USB status register.
875 875 */
876 876 for (i = 0; i <= UHCI_TIMEWAIT / 1000; i++) {
877 877 if (Get_OpReg16(USBSTS) & USBSTS_REG_HC_HALTED)
878 878 break;
879 879 drv_usecwait(1000);
880 880 }
881 881
882 882 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
883 883 "uhci_cpr_suspend: waited %d milliseconds for hc to halt", i);
884 884
885 885 /* Disable interrupts */
886 886 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
887 887
888 888 /* Clear any scheduled pending interrupts */
889 889 Set_OpReg16(USBSTS, USBSTS_REG_HC_HALTED |
890 890 USBSTS_REG_HC_PROCESS_ERR | USBSTS_REG_HOST_SYS_ERR |
891 891 USBSTS_REG_RESUME_DETECT | USBSTS_REG_USB_ERR_INTR |
892 892 USBSTS_REG_USB_INTR);
893 893
894 894 /* Set Global Suspend bit */
895 895 Set_OpReg16(USBCMD, USBCMD_REG_ENTER_GBL_SUSPEND);
896 896
897 897 /* Set host controller soft state to suspend */
898 898 uhcip->uhci_hc_soft_state = UHCI_CTLR_SUSPEND_STATE;
899 899
900 900 mutex_exit(&uhcip->uhci_int_mutex);
901 901
902 902 return (USB_SUCCESS);
903 903 }
904 904
905 905
906 906 /*
907 907 * uhci_cpr_cleanup:
908 908 *
909 909 * Cleanup uhci specific information across resuming.
910 910 */
911 911 static void
912 912 uhci_cpr_cleanup(uhci_state_t *uhcip)
913 913 {
914 914 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
915 915
916 916 /* Reset software part of usb frame number */
917 917 uhcip->uhci_sw_frnum = 0;
918 918 }
919 919
920 920
921 921 /*
922 922 * uhci_cpr_resume
923 923 */
924 924 static int
925 925 uhci_cpr_resume(uhci_state_t *uhcip)
926 926 {
927 927 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
928 928 "uhci_cpr_resume: Restart the controller");
929 929
930 930 mutex_enter(&uhcip->uhci_int_mutex);
931 931
932 932 /* Cleanup uhci specific information across cpr */
933 933 uhci_cpr_cleanup(uhcip);
934 934
935 935 mutex_exit(&uhcip->uhci_int_mutex);
936 936
937 937 /* Restart the controller */
938 938 if (uhci_init_ctlr(uhcip) != DDI_SUCCESS) {
939 939
940 940 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
941 941 "uhci_cpr_resume: uhci host controller resume failed ");
942 942
943 943 return (DDI_FAILURE);
944 944 }
945 945
946 946 mutex_enter(&uhcip->uhci_int_mutex);
947 947
948 948 /*
949 949 * Set HcInterruptEnable to enable all interrupts except Root
950 950 * Hub Status change and SOF interrupts.
951 951 */
952 952 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
953 953
954 954 mutex_exit(&uhcip->uhci_int_mutex);
955 955
956 956 /* Now resume the root hub */
957 957 if (usba_hubdi_attach(uhcip->uhci_dip, DDI_RESUME) != DDI_SUCCESS) {
958 958
959 959 return (DDI_FAILURE);
960 960 }
961 961
962 962 return (DDI_SUCCESS);
963 963 }
964 964
965 965
966 966 /*
967 967 * uhci_intr:
968 968 * uhci interrupt handling routine.
969 969 */
970 970 static uint_t
971 971 uhci_intr(caddr_t arg1, caddr_t arg2)
972 972 {
973 973 ushort_t intr_status, cmd_reg, intr_reg;
974 974 uhci_state_t *uhcip = (uhci_state_t *)arg1;
975 975
976 976 USB_DPRINTF_L4(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
977 977 "uhci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p",
978 978 (void *)arg1, (void *)arg2);
979 979
980 980 mutex_enter(&uhcip->uhci_int_mutex);
981 981
982 982 /* Any interrupt is not handled for the suspended device. */
983 983 if (uhcip->uhci_hc_soft_state == UHCI_CTLR_SUSPEND_STATE) {
984 984 mutex_exit(&uhcip->uhci_int_mutex);
985 985
986 986 return (DDI_INTR_UNCLAIMED);
987 987 }
988 988
989 989 /* Get the status of the interrupts */
990 990 intr_status = Get_OpReg16(USBSTS);
991 991 intr_reg = Get_OpReg16(USBINTR);
992 992
993 993 USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
994 994 "uhci_intr: intr_status = %x, intr_reg = %x",
995 995 intr_status, intr_reg);
996 996
997 997 /*
998 998 * If uhci interrupts are all disabled, the driver should return
999 999 * unclaimed.
1000 1000 * HC Process Error and Host System Error interrupts cannot be
1001 1001 * disabled by intr register, and need to be judged separately.
1002 1002 */
1003 1003 if (((intr_reg & ENABLE_ALL_INTRS) == 0) &&
1004 1004 ((intr_status & USBSTS_REG_HC_PROCESS_ERR) == 0) &&
1005 1005 ((intr_status & USBSTS_REG_HOST_SYS_ERR) == 0)) {
1006 1006
1007 1007 USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1008 1008 "uhci_intr: interrupts disabled, unclaim");
1009 1009 mutex_exit(&uhcip->uhci_int_mutex);
1010 1010
1011 1011 return (DDI_INTR_UNCLAIMED);
1012 1012 }
1013 1013
1014 1014 /*
1015 1015 * If the intr is not from our controller, just return unclaimed.
1016 1016 * HCHalted status bit cannot generate interrupts and should be
1017 1017 * ignored.
1018 1018 */
1019 1019 if (!(intr_status & UHCI_INTR_MASK)) {
1020 1020
1021 1021 USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1022 1022 "uhci_intr: no interrupt status set, unclaim");
1023 1023 mutex_exit(&uhcip->uhci_int_mutex);
1024 1024
1025 1025 return (DDI_INTR_UNCLAIMED);
1026 1026 }
1027 1027
1028 1028 /* Update kstat values */
1029 1029 uhci_do_intrs_stats(uhcip, intr_status);
1030 1030
1031 1031 /* Acknowledge the interrupt */
1032 1032 Set_OpReg16(USBSTS, intr_status);
1033 1033
1034 1034 /*
1035 1035 * If uhci controller has not been initialized, just clear the
1036 1036 * interrupter status and return claimed.
1037 1037 */
1038 1038 if (uhcip->uhci_hc_soft_state != UHCI_CTLR_OPERATIONAL_STATE) {
1039 1039
1040 1040 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1041 1041 "uhci_intr: uhci controller is not in the operational "
1042 1042 "state");
1043 1043 mutex_exit(&uhcip->uhci_int_mutex);
1044 1044
1045 1045 return (DDI_INTR_CLAIMED);
1046 1046 }
1047 1047
1048 1048 /*
1049 1049 * We configured the hw incorrectly, disable future interrupts.
1050 1050 */
1051 1051 if ((intr_status & USBSTS_REG_HOST_SYS_ERR)) {
1052 1052 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1053 1053 "uhci_intr: Sys Err Disabling Interrupt");
1054 1054 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
1055 1055 uhcip->uhci_hc_soft_state = UHCI_CTLR_ERROR_STATE;
1056 1056
1057 1057 mutex_exit(&uhcip->uhci_int_mutex);
1058 1058
1059 1059 return (DDI_INTR_CLAIMED);
1060 1060 }
1061 1061
1062 1062 /*
1063 1063 * Check whether a frame number overflow occurred.
1064 1064 * if so, update the sw frame number.
1065 1065 */
1066 1066 uhci_isoc_update_sw_frame_number(uhcip);
1067 1067
1068 1068 /*
1069 1069 * Check whether any commands got completed. If so, process them.
1070 1070 */
1071 1071 uhci_process_submitted_td_queue(uhcip);
1072 1072
1073 1073 /*
1074 1074 * This should not occur. It occurs only if a HC controller
1075 1075 * experiences internal problem.
1076 1076 */
1077 1077 if (intr_status & USBSTS_REG_HC_HALTED) {
1078 1078 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1079 1079 "uhci_intr: Controller halted");
1080 1080 cmd_reg = Get_OpReg16(USBCMD);
1081 1081 Set_OpReg16(USBCMD, (cmd_reg | USBCMD_REG_HC_RUN));
1082 1082 }
1083 1083
1084 1084 /*
1085 1085 * Wake up all the threads which are waiting for the Start of Frame
1086 1086 */
1087 1087 if (uhcip->uhci_cv_signal == B_TRUE) {
1088 1088 cv_broadcast(&uhcip->uhci_cv_SOF);
1089 1089 uhcip->uhci_cv_signal = B_FALSE;
1090 1090 }
1091 1091
1092 1092 mutex_exit(&uhcip->uhci_int_mutex);
1093 1093
1094 1094 return (DDI_INTR_CLAIMED);
1095 1095 }
1096 1096
1097 1097
1098 1098 /*
1099 1099 * uhci_process_submitted_td_queue:
1100 1100 * Traverse thru the submitted queue and process the completed ones.
1101 1101 */
1102 1102 void
1103 1103 uhci_process_submitted_td_queue(uhci_state_t *uhcip)
1104 1104 {
1105 1105 uhci_td_t *head = uhcip->uhci_outst_tds_head;
1106 1106 uhci_trans_wrapper_t *tw;
1107 1107
1108 1108 while (head != NULL) {
1109 1109 if ((!(GetTD_status(uhcip, head) & UHCI_TD_ACTIVE)) &&
1110 1110 (head->tw->tw_claim == UHCI_NOT_CLAIMED)) {
1111 1111 tw = head->tw;
1112 1112
1113 1113 /*
1114 1114 * Call the corresponding handle_td routine
1115 1115 */
1116 1116 (*tw->tw_handle_td)(uhcip, head);
1117 1117
1118 1118 /* restart at the beginning again */
1119 1119 head = uhcip->uhci_outst_tds_head;
1120 1120 } else {
1121 1121 head = head->outst_td_next;
1122 1122 }
1123 1123 }
1124 1124 }
1125 1125
1126 1126
1127 1127 /*
1128 1128 * uhci_handle_intr_td:
1129 1129 * handles the completed interrupt transfer TD's.
1130 1130 */
1131 1131 void
1132 1132 uhci_handle_intr_td(uhci_state_t *uhcip, uhci_td_t *td)
1133 1133 {
1134 1134 usb_req_attrs_t attrs;
1135 1135 uint_t bytes_xfered;
1136 1136 usb_cr_t usb_err;
1137 1137 uhci_trans_wrapper_t *tw = td->tw;
1138 1138 uhci_pipe_private_t *pp = tw->tw_pipe_private;
1139 1139 usb_intr_req_t *intr_reqp =
1140 1140 (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
1141 1141 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
1142 1142
1143 1143 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1144 1144 "uhci_handle_intr_td: intr_reqp = 0x%p", (void *)intr_reqp);
1145 1145
1146 1146 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1147 1147
1148 1148 /* set tw->tw_claim flag, so that nobody else works on this td. */
1149 1149 tw->tw_claim = UHCI_INTR_HDLR_CLAIMED;
1150 1150
1151 1151 /* Interrupt OUT */
1152 1152 if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_OUT) {
1153 1153
1154 1154 /* process errors first */
1155 1155 usb_err = uhci_parse_td_error(uhcip, pp, td);
1156 1156
1157 1157 /* get the actual xfered data size */
1158 1158 bytes_xfered = GetTD_alen(uhcip, td);
1159 1159
1160 1160 /* check data underrun error */
1161 1161 if ((usb_err == USB_CR_OK) && (bytes_xfered !=
1162 1162 GetTD_mlen(uhcip, td))) {
1163 1163
1164 1164 USB_DPRINTF_L2(PRINT_MASK_LISTS,
1165 1165 uhcip->uhci_log_hdl, "uhci_handle_intr_td:"
1166 1166 " Intr out pipe, data underrun occurred");
1167 1167
1168 1168 usb_err = USB_CR_DATA_UNDERRUN;
1169 1169
1170 1170 }
1171 1171
1172 1172 bytes_xfered = (bytes_xfered == ZERO_LENGTH) ?
1173 1173 0 : bytes_xfered+1;
1174 1174 tw->tw_bytes_xfered += bytes_xfered;
1175 1175 uhci_do_byte_stats(uhcip, tw->tw_bytes_xfered,
1176 1176 ph->p_ep.bmAttributes, ph->p_ep.bEndpointAddress);
1177 1177
1178 1178
1179 1179 /*
1180 1180 * If error occurred or all data xfered, delete the current td,
1181 1181 * free tw, do the callback. Otherwise wait for the next td.
1182 1182 */
1183 1183 if (usb_err != USB_CR_OK) {
1184 1184
1185 1185 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1186 1186 "uhci_handle_intr_td: Intr out pipe error");
1187 1187
1188 1188 /* update the element pointer */
1189 1189 SetQH32(uhcip, pp->pp_qh->element_ptr, GetTD32(
1190 1190 uhcip, tw->tw_hctd_tail->link_ptr));
1191 1191
1192 1192
1193 1193 } else if (tw->tw_bytes_xfered == tw->tw_length) {
1194 1194
1195 1195 /* all data xfered */
1196 1196 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1197 1197 "uhci_handle_intr_td: Intr out pipe,"
1198 1198 " all data xfered");
1199 1199
1200 1200 } else {
1201 1201
1202 1202 /* remove the current td and wait for the next one. */
1203 1203 uhci_delete_td(uhcip, td);
1204 1204 tw->tw_claim = UHCI_NOT_CLAIMED;
1205 1205
1206 1206 return;
1207 1207 }
1208 1208
1209 1209 uhci_delete_td(uhcip, td);
1210 1210 uhci_hcdi_callback(uhcip, pp, ph, tw, usb_err);
1211 1211 uhci_deallocate_tw(uhcip, tw->tw_pipe_private, tw);
1212 1212
1213 1213 return;
1214 1214 }
1215 1215
1216 1216 /* Interrupt IN */
1217 1217
1218 1218 /* Get the actual received data size */
1219 1219 tw->tw_bytes_xfered = GetTD_alen(uhcip, td);
1220 1220 if (tw->tw_bytes_xfered == ZERO_LENGTH) {
1221 1221 tw->tw_bytes_xfered = 0;
1222 1222 } else {
1223 1223 tw->tw_bytes_xfered++;
1224 1224 }
1225 1225
1226 1226 /* process errors first */
1227 1227 if (GetTD_status(uhcip, td) & TD_STATUS_MASK) {
1228 1228 SetQH32(uhcip, pp->pp_qh->element_ptr,
1229 1229 GetTD32(uhcip, td->link_ptr));
1230 1230
1231 1231 uhci_handle_intr_td_errors(uhcip, td, tw, pp);
1232 1232
1233 1233 return;
1234 1234 }
1235 1235
1236 1236 /*
1237 1237 * Check for data underruns.
1238 1238 * For data underrun case, the host controller does not update
1239 1239 * element pointer. So, we update here.
1240 1240 */
1241 1241 if (GetTD_alen(uhcip, td) != GetTD_mlen(uhcip, td)) {
1242 1242 SetQH32(uhcip, pp->pp_qh->element_ptr,
1243 1243 GetTD32(uhcip, td->link_ptr));
1244 1244 }
1245 1245
1246 1246 /*
1247 1247 * Call uhci_sendup_td_message to send message upstream.
1248 1248 * The function uhci_sendup_td_message returns USB_NO_RESOURCES
1249 1249 * if allocb fails and also sends error message to upstream by
1250 1250 * calling USBA callback function. Under error conditions just
1251 1251 * drop the current message.
1252 1252 */
1253 1253
1254 1254 /* Get the interrupt xfer attributes */
1255 1255 attrs = intr_reqp->intr_attributes;
1256 1256
1257 1257 /*
1258 1258 * Check usb flag whether USB_FLAGS_ONE_XFER flag is set
1259 1259 * and if so, free duplicate request.
1260 1260 */
1261 1261 if (attrs & USB_ATTRS_ONE_XFER) {
1262 1262 uhci_handle_one_xfer_completion(uhcip, USB_CR_OK, td);
1263 1263
1264 1264 return;
1265 1265 }
1266 1266
1267 1267 /* save it temporarily */
1268 1268 if (tw->tw_bytes_xfered != 0) {
1269 1269 uhci_sendup_td_message(uhcip, USB_CR_OK, tw);
1270 1270 }
1271 1271
1272 1272 /* Clear the tw->tw_claim flag */
1273 1273 tw->tw_claim = UHCI_NOT_CLAIMED;
1274 1274
1275 1275 uhci_delete_td(uhcip, td);
1276 1276
1277 1277 /* allocate another interrupt periodic resource */
1278 1278 if (pp->pp_state == UHCI_PIPE_STATE_ACTIVE) {
1279 1279 if (uhci_allocate_periodic_in_resource(uhcip, pp, tw, 0) !=
1280 1280 USB_SUCCESS) {
1281 1281 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1282 1282 "uhci_insert_intr_req: Interrupt request structure"
1283 1283 "allocation failed");
1284 1284
1285 1285 uhci_hcdi_callback(uhcip, pp, ph,
1286 1286 tw, USB_CR_NO_RESOURCES);
1287 1287
1288 1288 return;
1289 1289 }
1290 1290
1291 1291 /* Insert another interrupt TD */
1292 1292 if (uhci_insert_hc_td(uhcip, 0,
1293 1293 tw->tw_length, pp, tw, PID_IN, attrs) != USB_SUCCESS) {
1294 1294
1295 1295 uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
1296 1296
1297 1297 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1298 1298 "uhci_handle_intr_td: TD exhausted");
1299 1299
1300 1300 uhci_hcdi_callback(uhcip, pp, ph,
1301 1301 tw, USB_CR_NO_RESOURCES);
1302 1302 }
1303 1303 }
1304 1304 }
1305 1305
1306 1306
1307 1307 /*
1308 1308 * uhci_sendup_td_message:
1309 1309 *
1310 1310 * Get a message block and send the received message upstream.
1311 1311 */
1312 1312 void
1313 1313 uhci_sendup_td_message(
1314 1314 uhci_state_t *uhcip,
1315 1315 usb_cr_t usb_err,
1316 1316 uhci_trans_wrapper_t *tw)
1317 1317 {
1318 1318 mblk_t *mp = NULL;
1319 1319 size_t length = 0;
1320 1320 size_t skip_len = 0;
1321 1321 uchar_t *buf;
1322 1322 usb_opaque_t curr_xfer_reqp = tw->tw_curr_xfer_reqp;
1323 1323 uhci_pipe_private_t *pp = tw->tw_pipe_private;
1324 1324 usb_ep_descr_t *ept = &pp->pp_pipe_handle->p_ep;
1325 1325
1326 1326 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1327 1327
1328 1328 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1329 1329 "uhci_sendup_td_message: bytes transferred=0x%x, "
1330 1330 "bytes pending=0x%x",
1331 1331 tw->tw_bytes_xfered, tw->tw_bytes_pending);
1332 1332
1333 1333 length = tw->tw_bytes_xfered;
1334 1334
1335 1335 switch (UHCI_XFER_TYPE(ept)) {
1336 1336 case USB_EP_ATTR_CONTROL:
1337 1337 skip_len = UHCI_CTRL_EPT_MAX_SIZE; /* length to skip */
1338 1338 mp = ((usb_ctrl_req_t *)curr_xfer_reqp)->ctrl_data;
1339 1339 break;
1340 1340 case USB_EP_ATTR_INTR:
1341 1341 mp = ((usb_intr_req_t *)curr_xfer_reqp)->intr_data;
1342 1342 break;
1343 1343 case USB_EP_ATTR_BULK:
1344 1344 mp = ((usb_bulk_req_t *)curr_xfer_reqp)->bulk_data;
1345 1345 break;
1346 1346 case USB_EP_ATTR_ISOCH:
1347 1347 length = tw->tw_length;
1348 1348 mp = ((usb_isoc_req_t *)curr_xfer_reqp)->isoc_data;
1349 1349 break;
1350 1350 default:
1351 1351 break;
1352 1352 }
1353 1353
1354 1354 /* Copy the data into the mblk_t */
1355 1355 buf = (uchar_t *)tw->tw_buf + skip_len;
1356 1356
1357 1357 ASSERT(mp != NULL);
1358 1358
1359 1359 /*
1360 1360 * Update kstat byte counts
1361 1361 * The control endpoints don't have direction bits so in
1362 1362 * order for control stats to be counted correctly an IN
1363 1363 * bit must be faked on a control read.
1364 1364 */
1365 1365 uhci_do_byte_stats(uhcip, length, ept->bmAttributes,
1366 1366 (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_CONTROL) ?
1367 1367 USB_EP_DIR_IN : ept->bEndpointAddress);
1368 1368
1369 1369 if (length) {
1370 1370 int rval, i;
1371 1371 uchar_t *p = mp->b_rptr;
1372 1372
1373 1373 if (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_ISOCH) {
1374 1374 /* Deal with isoc data by packets */
1375 1375 for (i = 0; i < tw->tw_ncookies; i++) {
1376 1376 rval = ddi_dma_sync(
1377 1377 tw->tw_isoc_bufs[i].dma_handle, 0,
1378 1378 tw->tw_isoc_bufs[i].length,
1379 1379 DDI_DMA_SYNC_FORCPU);
1380 1380 ASSERT(rval == DDI_SUCCESS);
1381 1381
1382 1382 ddi_rep_get8(tw->tw_isoc_bufs[i].mem_handle,
1383 1383 p, (uint8_t *)tw->tw_isoc_bufs[i].buf_addr,
1384 1384 tw->tw_isoc_bufs[i].length,
1385 1385 DDI_DEV_AUTOINCR);
1386 1386 p += tw->tw_isoc_bufs[i].length;
1387 1387 }
1388 1388 } else {
1389 1389 /* Sync the streaming buffer */
1390 1390 rval = ddi_dma_sync(tw->tw_dmahandle, 0,
1391 1391 (skip_len + length), DDI_DMA_SYNC_FORCPU);
1392 1392 ASSERT(rval == DDI_SUCCESS);
1393 1393
1394 1394 /* Copy the data into the message */
1395 1395 ddi_rep_get8(tw->tw_accesshandle,
1396 1396 mp->b_rptr, buf, length, DDI_DEV_AUTOINCR);
1397 1397 }
1398 1398
1399 1399 /* Increment the write pointer */
1400 1400 mp->b_wptr += length;
1401 1401 } else {
1402 1402 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1403 1403 "uhci_sendup_td_message: Zero length packet");
1404 1404 }
1405 1405
1406 1406 /* Do the callback */
1407 1407 uhci_hcdi_callback(uhcip, pp, pp->pp_pipe_handle, tw, usb_err);
1408 1408 }
1409 1409
1410 1410
1411 1411 /*
1412 1412 * uhci_handle_ctrl_td:
1413 1413 * Handle a control Transfer Descriptor (TD).
1414 1414 */
1415 1415 void
1416 1416 uhci_handle_ctrl_td(uhci_state_t *uhcip, uhci_td_t *td)
1417 1417 {
1418 1418 ushort_t direction;
1419 1419 ushort_t bytes_for_xfer;
1420 1420 ushort_t bytes_xfered;
1421 1421 ushort_t MaxPacketSize;
1422 1422 usb_cr_t error;
1423 1423 uhci_trans_wrapper_t *tw = td->tw;
1424 1424 uhci_pipe_private_t *pp = tw->tw_pipe_private;
1425 1425 usba_pipe_handle_data_t *usb_pp = pp->pp_pipe_handle;
1426 1426 usb_ep_descr_t *eptd = &usb_pp->p_ep;
1427 1427 usb_ctrl_req_t *reqp = (usb_ctrl_req_t *)tw->tw_curr_xfer_reqp;
1428 1428
1429 1429 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1430 1430 "uhci_handle_ctrl_td: pp = 0x%p tw = 0x%p td = 0x%p "
1431 1431 "state = 0x%x len = 0x%lx", (void *)pp, (void *)tw,
1432 1432 (void *)td, tw->tw_ctrl_state, tw->tw_length);
1433 1433
1434 1434 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1435 1435
1436 1436 error = uhci_parse_td_error(uhcip, pp, td);
1437 1437
1438 1438 /*
1439 1439 * In case of control transfers, the device can send NAK when it
1440 1440 * is busy. If a NAK is received, then send the status TD again.
1441 1441 */
1442 1442 if (error != USB_CR_OK) {
1443 1443 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1444 1444 "uhci_handle_ctrl_td: Ctrl cmd failed, error = %x", error);
1445 1445
1446 1446 SetQH32(uhcip, pp->pp_qh->element_ptr,
1447 1447 GetTD32(uhcip, td->link_ptr));
1448 1448 uhci_delete_td(uhcip, td);
1449 1449
1450 1450 /* Return number of bytes xfered */
1451 1451 if (GetTD_alen(uhcip, td) != ZERO_LENGTH) {
1452 1452 tw->tw_bytes_xfered = GetTD_alen(uhcip, td) + 1;
1453 1453 }
1454 1454
1455 1455 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1456 1456 "uhci_handle_ctrl_td: Bytes transferred = %x",
1457 1457 tw->tw_bytes_xfered);
1458 1458
1459 1459 if ((tw->tw_ctrl_state == DATA) &&
1460 1460 (tw->tw_direction == PID_IN)) {
1461 1461 uhci_sendup_td_message(uhcip, error, tw);
1462 1462 } else {
1463 1463 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, error);
1464 1464
1465 1465 uhci_deallocate_tw(uhcip, pp, tw);
1466 1466 }
1467 1467
1468 1468 return;
1469 1469 }
1470 1470
1471 1471 /*
1472 1472 * A control transfer consists of three phases:
1473 1473 * - Setup
1474 1474 * - Data (optional)
1475 1475 * - Status
1476 1476 *
1477 1477 * There is a TD per phase. A TD for a given phase isn't
1478 1478 * enqueued until the previous phase is finished.
1479 1479 */
1480 1480 switch (tw->tw_ctrl_state) {
1481 1481 case SETUP:
1482 1482 /*
1483 1483 * Enqueue either the data or the status
1484 1484 * phase depending on the length.
1485 1485 */
1486 1486 pp->pp_data_toggle = 1;
1487 1487 uhci_delete_td(uhcip, td);
1488 1488
1489 1489 /*
1490 1490 * If the length is 0, move to the status.
1491 1491 * If length is not 0, then we have some data
1492 1492 * to move on the bus to device either IN or OUT.
1493 1493 */
1494 1494 if ((tw->tw_length - SETUP_SIZE) == 0) {
1495 1495 /*
1496 1496 * There is no data stage, then
1497 1497 * initiate status phase from the host.
1498 1498 */
1499 1499 if ((uhci_insert_hc_td(uhcip, 0, 0, pp, tw, PID_IN,
1500 1500 reqp->ctrl_attributes)) != USB_SUCCESS) {
1501 1501 USB_DPRINTF_L2(PRINT_MASK_LISTS,
1502 1502 uhcip->uhci_log_hdl,
1503 1503 "uhci_handle_ctrl_td: No resources");
1504 1504
1505 1505 uhci_hcdi_callback(uhcip, pp, usb_pp, tw,
1506 1506 USB_CR_NO_RESOURCES);
1507 1507
1508 1508 return;
1509 1509 }
1510 1510
1511 1511 tw->tw_ctrl_state = STATUS;
1512 1512 } else {
1513 1513 uint_t xx;
1514 1514
1515 1515 /*
1516 1516 * Each USB device can send/receive 8/16/32/64
1517 1517 * depending on wMaxPacketSize's implementation.
1518 1518 * We need to insert 'N = Number of byte/
1519 1519 * MaxpktSize" TD's in the lattice to send/
1520 1520 * receive the data. Though the USB protocol
1521 1521 * allows to insert more than one TD in the same
1522 1522 * frame, we are inserting only one TD in one
1523 1523 * frame. This is bcos OHCI has seen some problem
1524 1524 * when multiple TD's are inserted at the same time.
1525 1525 */
1526 1526 tw->tw_length -= UHCI_CTRL_EPT_MAX_SIZE;
1527 1527 MaxPacketSize = eptd->wMaxPacketSize;
1528 1528
1529 1529 /*
1530 1530 * We dont know the maximum packet size that
1531 1531 * the device can handle(MaxPAcketSize=0).
1532 1532 * In that case insert a data phase with
1533 1533 * eight bytes or less.
1534 1534 */
1535 1535 if (MaxPacketSize == 0) {
1536 1536 xx = (tw->tw_length > 8) ? 8 : tw->tw_length;
1537 1537 } else {
1538 1538 xx = (tw->tw_length > MaxPacketSize) ?
1539 1539 MaxPacketSize : tw->tw_length;
1540 1540 }
1541 1541
1542 1542 tw->tw_tmp = xx;
1543 1543
1544 1544 /*
1545 1545 * Create the TD. If this is an OUT
1546 1546 * transaction, the data is already
1547 1547 * in the buffer of the TW.
1548 1548 * Get first 8 bytes of the command only.
1549 1549 */
1550 1550 if ((uhci_insert_hc_td(uhcip,
1551 1551 UHCI_CTRL_EPT_MAX_SIZE, xx,
1552 1552 pp, tw, tw->tw_direction,
1553 1553 reqp->ctrl_attributes)) != USB_SUCCESS) {
1554 1554
1555 1555 USB_DPRINTF_L2(PRINT_MASK_LISTS,
1556 1556 uhcip->uhci_log_hdl,
1557 1557 "uhci_handle_ctrl_td: No resources");
1558 1558
1559 1559 uhci_hcdi_callback(uhcip, pp, usb_pp, tw,
1560 1560 USB_CR_NO_RESOURCES);
1561 1561
1562 1562 return;
1563 1563 }
1564 1564
1565 1565 tw->tw_ctrl_state = DATA;
1566 1566 }
1567 1567
1568 1568 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1569 1569 "Setup complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
1570 1570
1571 1571 break;
1572 1572 case DATA:
1573 1573 uhci_delete_td(uhcip, td);
1574 1574
1575 1575 MaxPacketSize = eptd->wMaxPacketSize;
1576 1576
1577 1577 /*
1578 1578 * Decrement pending bytes and increment the total
1579 1579 * number bytes transferred by the actual number of bytes
1580 1580 * transferred in this TD. If the number of bytes transferred
1581 1581 * is less than requested, that means an underrun has
1582 1582 * occurred. Set the tw_tmp varible to indicate UNDER run.
1583 1583 */
1584 1584 bytes_xfered = GetTD_alen(uhcip, td);
1585 1585 if (bytes_xfered == ZERO_LENGTH) {
1586 1586 bytes_xfered = 0;
1587 1587 } else {
1588 1588 bytes_xfered++;
1589 1589 }
1590 1590
1591 1591 tw->tw_bytes_pending -= bytes_xfered;
1592 1592 tw->tw_bytes_xfered += bytes_xfered;
1593 1593
1594 1594 if (bytes_xfered < tw->tw_tmp) {
1595 1595 tw->tw_bytes_pending = 0;
1596 1596 tw->tw_tmp = UHCI_UNDERRUN_OCCURRED;
1597 1597
1598 1598 /*
1599 1599 * Controller does not update the queue head
1600 1600 * element pointer when a data underrun occurs.
1601 1601 */
1602 1602 SetQH32(uhcip, pp->pp_qh->element_ptr,
1603 1603 GetTD32(uhcip, td->link_ptr));
1604 1604 }
1605 1605
1606 1606 if (bytes_xfered > tw->tw_tmp) {
1607 1607 tw->tw_bytes_pending = 0;
1608 1608 tw->tw_tmp = UHCI_OVERRUN_OCCURRED;
1609 1609 }
1610 1610
1611 1611 /*
1612 1612 * If no more bytes are pending, insert status
1613 1613 * phase. Otherwise insert data phase.
1614 1614 */
1615 1615 if (tw->tw_bytes_pending) {
1616 1616 bytes_for_xfer = (tw->tw_bytes_pending >
1617 1617 MaxPacketSize) ? MaxPacketSize :
1618 1618 tw->tw_bytes_pending;
1619 1619
1620 1620 tw->tw_tmp = bytes_for_xfer;
1621 1621
1622 1622 if ((uhci_insert_hc_td(uhcip,
1623 1623 UHCI_CTRL_EPT_MAX_SIZE + tw->tw_bytes_xfered,
1624 1624 bytes_for_xfer, pp, tw,
1625 1625 tw->tw_direction,
1626 1626 reqp->ctrl_attributes)) != USB_SUCCESS) {
1627 1627 USB_DPRINTF_L2(PRINT_MASK_LISTS,
1628 1628 uhcip->uhci_log_hdl,
1629 1629 "uhci_handle_ctrl_td: No TD");
1630 1630
1631 1631 uhci_hcdi_callback(uhcip, pp, usb_pp,
1632 1632 tw, USB_NO_RESOURCES);
1633 1633
1634 1634 return;
1635 1635 }
1636 1636
1637 1637 tw->tw_ctrl_state = DATA;
1638 1638
1639 1639 break;
1640 1640 }
1641 1641
1642 1642 pp->pp_data_toggle = 1;
1643 1643 direction = (tw->tw_direction == PID_IN) ? PID_OUT : PID_IN;
1644 1644
1645 1645 if ((uhci_insert_hc_td(uhcip, 0, 0, pp, tw, direction,
1646 1646 reqp->ctrl_attributes)) != USB_SUCCESS) {
1647 1647 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1648 1648 "uhci_handle_ctrl_td: TD exhausted");
1649 1649
1650 1650 uhci_hcdi_callback(uhcip, pp, usb_pp, tw,
1651 1651 USB_NO_RESOURCES);
1652 1652
1653 1653 return;
1654 1654 }
1655 1655
1656 1656 tw->tw_ctrl_state = STATUS;
1657 1657 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1658 1658 "Data complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
1659 1659
1660 1660 break;
1661 1661 case STATUS:
1662 1662 /*
1663 1663 * Send the data to the client if it is a DATA IN,
1664 1664 * else send just return status for DATA OUT commnads.
1665 1665 * And set the tw_claim flag.
1666 1666 */
1667 1667 tw->tw_claim = UHCI_INTR_HDLR_CLAIMED;
1668 1668
1669 1669 if ((tw->tw_length != 0) && (tw->tw_direction == PID_IN)) {
1670 1670 usb_req_attrs_t attrs = ((usb_ctrl_req_t *)
1671 1671 tw->tw_curr_xfer_reqp)->ctrl_attributes;
1672 1672 /*
1673 1673 * Call uhci_sendup_td_message to send message
1674 1674 * upstream. The function uhci_sendup_td_message
1675 1675 * returns USB_NO_RESOURCES if allocb fails and
1676 1676 * also sends error message to upstream by calling
1677 1677 * USBA callback function.
1678 1678 *
1679 1679 * Under error conditions just drop the current msg.
1680 1680 */
1681 1681 if ((tw->tw_tmp == UHCI_UNDERRUN_OCCURRED) &&
1682 1682 (!(attrs & USB_ATTRS_SHORT_XFER_OK))) {
1683 1683 error = USB_CR_DATA_UNDERRUN;
1684 1684 } else if (tw->tw_tmp == UHCI_OVERRUN_OCCURRED) {
1685 1685 error = USB_CR_DATA_OVERRUN;
1686 1686 }
1687 1687 uhci_sendup_td_message(uhcip, error, tw);
1688 1688
1689 1689 } else {
1690 1690 uhci_do_byte_stats(uhcip, tw->tw_length,
1691 1691 eptd->bmAttributes, eptd->bEndpointAddress);
1692 1692
1693 1693 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, USB_CR_OK);
1694 1694 }
1695 1695
1696 1696 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1697 1697 "Status complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
1698 1698
1699 1699 uhci_delete_td(uhcip, td);
1700 1700 uhci_deallocate_tw(uhcip, pp, tw);
1701 1701
1702 1702 break;
1703 1703 default:
1704 1704 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1705 1705 "uhci_handle_ctrl_td: Bad control state");
1706 1706
1707 1707 uhci_hcdi_callback(uhcip, pp, usb_pp, tw,
1708 1708 USB_CR_UNSPECIFIED_ERR);
1709 1709 }
1710 1710 }
1711 1711
1712 1712
1713 1713 /*
1714 1714 * uhci_handle_intr_td_errors:
1715 1715 * Handles the errors encountered for the interrupt transfers.
1716 1716 */
1717 1717 static void
1718 1718 uhci_handle_intr_td_errors(uhci_state_t *uhcip, uhci_td_t *td,
1719 1719 uhci_trans_wrapper_t *tw, uhci_pipe_private_t *pp)
1720 1720 {
1721 1721 usb_cr_t usb_err;
1722 1722 usb_intr_req_t *intr_reqp =
1723 1723 (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
1724 1724
1725 1725 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1726 1726 "uhci_handle_intr_td_errors: td = 0x%p tw = 0x%p",
1727 1727 (void *)td, (void *)tw);
1728 1728
1729 1729 usb_err = uhci_parse_td_error(uhcip, pp, td);
1730 1730
1731 1731 if (intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) {
1732 1732 uhci_handle_one_xfer_completion(uhcip, usb_err, td);
1733 1733
1734 1734 return;
1735 1735 }
1736 1736
1737 1737 uhci_delete_td(uhcip, td);
1738 1738 uhci_sendup_td_message(uhcip, usb_err, tw);
1739 1739 uhci_deallocate_tw(uhcip, tw->tw_pipe_private, tw);
1740 1740 }
1741 1741
1742 1742
1743 1743 /*
1744 1744 * uhci_handle_one_xfer_completion:
1745 1745 */
1746 1746 static void
1747 1747 uhci_handle_one_xfer_completion(
1748 1748 uhci_state_t *uhcip,
1749 1749 usb_cr_t usb_err,
1750 1750 uhci_td_t *td)
1751 1751 {
1752 1752 uhci_trans_wrapper_t *tw = td->tw;
1753 1753 uhci_pipe_private_t *pp = tw->tw_pipe_private;
1754 1754 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
1755 1755 usb_intr_req_t *intr_reqp =
1756 1756 (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
1757 1757
1758 1758 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1759 1759 "uhci_handle_one_xfer_completion: td = 0x%p", (void *)td);
1760 1760
1761 1761 ASSERT(intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER);
1762 1762
1763 1763 /* set state to idle */
1764 1764 pp->pp_state = UHCI_PIPE_STATE_IDLE;
1765 1765
1766 1766 ((usb_intr_req_t *)(pp->pp_client_periodic_in_reqp))->
1767 1767 intr_data = ((usb_intr_req_t *)(tw->tw_curr_xfer_reqp))->intr_data;
1768 1768
1769 1769 ((usb_intr_req_t *)tw->tw_curr_xfer_reqp)->intr_data = NULL;
1770 1770
1771 1771 /* now free duplicate current request */
1772 1772 usb_free_intr_req((usb_intr_req_t *)tw->tw_curr_xfer_reqp);
1773 1773 mutex_enter(&ph->p_mutex);
1774 1774 ph->p_req_count--;
1775 1775 mutex_exit(&ph->p_mutex);
1776 1776
1777 1777 /* make client's request the current request */
1778 1778 tw->tw_curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
1779 1779 pp->pp_client_periodic_in_reqp = NULL;
1780 1780
1781 1781 uhci_sendup_td_message(uhcip, usb_err, tw);
1782 1782 /* Clear the tw->tw_claim flag */
1783 1783 tw->tw_claim = UHCI_NOT_CLAIMED;
1784 1784
1785 1785 uhci_delete_td(uhcip, td);
1786 1786 uhci_deallocate_tw(uhcip, pp, tw);
1787 1787 }
1788 1788
1789 1789
1790 1790 /*
1791 1791 * uhci_parse_td_error
1792 1792 * Parses the Transfer Descriptors error
1793 1793 */
1794 1794 usb_cr_t
1795 1795 uhci_parse_td_error(uhci_state_t *uhcip, uhci_pipe_private_t *pp, uhci_td_t *td)
1796 1796 {
1797 1797 uint_t status;
1798 1798
1799 1799 status = GetTD_status(uhcip, td) & TD_STATUS_MASK;
1800 1800
1801 1801 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1802 1802 "uhci_parse_td_error: status_bits=0x%x", status);
1803 1803
1804 1804 if (UHCI_XFER_TYPE(&pp->pp_pipe_handle->p_ep) == USB_EP_ATTR_ISOCH) {
1805 1805
1806 1806 return (USB_CR_OK);
1807 1807 }
1808 1808
1809 1809 if (!status) {
1810 1810
1811 1811 return (USB_CR_OK);
1812 1812 }
1813 1813
1814 1814 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1815 1815 "uhci_parse_td_error: status_bits=0x%x", status);
1816 1816
1817 1817
1818 1818 if (status & UHCI_TD_BITSTUFF_ERR) {
1819 1819
1820 1820 return (USB_CR_BITSTUFFING);
1821 1821 }
1822 1822
1823 1823 if (status & UHCI_TD_CRC_TIMEOUT) {
1824 1824 pp->pp_data_toggle = GetTD_dtogg(uhcip, td);
1825 1825
1826 1826 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1827 1827 "uhci_parse_td_error: timeout & data toggle reset; "
1828 1828 "data toggle: %x", pp->pp_data_toggle);
1829 1829
1830 1830 return ((GetTD_PID(uhcip, td) == PID_IN) ? USB_CR_DEV_NOT_RESP :
1831 1831 USB_CR_TIMEOUT);
1832 1832 }
1833 1833
1834 1834 if (status & UHCI_TD_BABBLE_ERR) {
1835 1835 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1836 1836 "babble error");
1837 1837
1838 1838 return (USB_CR_UNSPECIFIED_ERR);
1839 1839 }
1840 1840
1841 1841 if (status & UHCI_TD_DATA_BUFFER_ERR) {
1842 1842 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1843 1843 "buffer error");
1844 1844
1845 1845 return ((GetTD_PID(uhcip, td) == PID_IN) ?
1846 1846 USB_CR_BUFFER_OVERRUN : USB_CR_BUFFER_UNDERRUN);
1847 1847 }
1848 1848
1849 1849 if (status & UHCI_TD_STALLED) {
1850 1850 pp->pp_data_toggle = 0;
1851 1851 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1852 1852 "uhci_parse_td_error: stall; data toggle reset; "
1853 1853 "data toggle: %x", pp->pp_data_toggle);
1854 1854
1855 1855 return (USB_CR_STALL);
1856 1856 }
1857 1857
1858 1858 if (status) {
1859 1859 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1860 1860 "unspecified error=0x%x", status);
1861 1861 }
1862 1862
1863 1863 return (USB_CR_OK);
1864 1864 }
1865 1865
1866 1866
1867 1867 static dev_info_t *
1868 1868 uhci_get_dip(dev_t dev)
1869 1869 {
1870 1870 int instance = UHCI_UNIT(dev);
1871 1871 uhci_state_t *uhcip = ddi_get_soft_state(uhci_statep, instance);
1872 1872
1873 1873 return (uhcip ? uhcip->uhci_dip : NULL);
1874 1874 }
1875 1875
1876 1876
1877 1877 /*
1878 1878 * cb_ops entry points
1879 1879 */
1880 1880 static int
1881 1881 uhci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
1882 1882 {
1883 1883 dev_info_t *dip = uhci_get_dip(*devp);
1884 1884
1885 1885 return (usba_hubdi_open(dip, devp, flags, otyp, credp));
1886 1886 }
1887 1887
1888 1888
1889 1889 static int
1890 1890 uhci_close(dev_t dev, int flag, int otyp, cred_t *credp)
1891 1891 {
1892 1892 dev_info_t *dip = uhci_get_dip(dev);
1893 1893
1894 1894 return (usba_hubdi_close(dip, dev, flag, otyp, credp));
1895 1895 }
1896 1896
1897 1897
1898 1898 static int
1899 1899 uhci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
1900 1900 cred_t *credp, int *rvalp)
1901 1901 {
1902 1902 dev_info_t *dip = uhci_get_dip(dev);
1903 1903
1904 1904 return (usba_hubdi_ioctl(dip, dev, cmd, arg, mode, credp, rvalp));
1905 1905 }
↓ open down ↓ |
1472 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX