1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * Open Host Controller Driver (OHCI)
29 *
30 * The USB Open Host Controller driver is a software driver which interfaces
31 * to the Universal Serial Bus layer (USBA) and the USB Open Host Controller.
32 * The interface to USB Open Host Controller is defined by the OpenHCI Host
33 * Controller Interface.
34 *
35 * NOTE:
36 *
37 * Currently OHCI driver does not support the following features
38 *
39 * - Handle request with multiple TDs under short xfer conditions except for
40 * bulk transfers.
41 */
42 #include <sys/usb/hcd/openhci/ohcid.h>
43
44 #include <sys/disp.h>
45 #include <sys/strsun.h>
46
47 /* Pointer to the state structure */
48 static void *ohci_statep;
49
50 int force_ohci_off = 1;
51
52 /* Number of instances */
53 #define OHCI_INSTS 1
54
55 /* Adjustable variables for the size of the pools */
56 int ohci_ed_pool_size = OHCI_ED_POOL_SIZE;
57 int ohci_td_pool_size = OHCI_TD_POOL_SIZE;
58
59 /*
60 * Initialize the values which are used for setting up head pointers for
61 * the 32ms scheduling lists which starts from the HCCA.
62 */
63 static uchar_t ohci_index[NUM_INTR_ED_LISTS / 2] = {0x0, 0x8, 0x4, 0xc,
64 0x2, 0xa, 0x6, 0xe,
65 0x1, 0x9, 0x5, 0xd,
66 0x3, 0xb, 0x7, 0xf};
67 /* Debugging information */
68 uint_t ohci_errmask = (uint_t)PRINT_MASK_ALL;
69 uint_t ohci_errlevel = USB_LOG_L2;
70 uint_t ohci_instance_debug = (uint_t)-1;
71
72 /*
73 * OHCI MSI tunable:
74 *
75 * By default MSI is enabled on all supported platforms.
76 */
77 boolean_t ohci_enable_msi = B_TRUE;
78
79 /*
80 * HCDI entry points
81 *
82 * The Host Controller Driver Interfaces (HCDI) are the software interfaces
83 * between the Universal Serial Bus Driver (USBA) and the Host Controller
84 * Driver (HCD). The HCDI interfaces or entry points are subject to change.
85 */
86 static int ohci_hcdi_pipe_open(
87 usba_pipe_handle_data_t *ph,
88 usb_flags_t usb_flags);
89 static int ohci_hcdi_pipe_close(
90 usba_pipe_handle_data_t *ph,
91 usb_flags_t usb_flags);
92 static int ohci_hcdi_pipe_reset(
93 usba_pipe_handle_data_t *ph,
94 usb_flags_t usb_flags);
95 static void ohci_hcdi_pipe_reset_data_toggle(
96 usba_pipe_handle_data_t *ph);
97 static int ohci_hcdi_pipe_ctrl_xfer(
98 usba_pipe_handle_data_t *ph,
99 usb_ctrl_req_t *ctrl_reqp,
100 usb_flags_t usb_flags);
101 static int ohci_hcdi_bulk_transfer_size(
102 usba_device_t *usba_device,
103 size_t *size);
104 static int ohci_hcdi_pipe_bulk_xfer(
105 usba_pipe_handle_data_t *ph,
106 usb_bulk_req_t *bulk_reqp,
107 usb_flags_t usb_flags);
108 static int ohci_hcdi_pipe_intr_xfer(
109 usba_pipe_handle_data_t *ph,
110 usb_intr_req_t *intr_req,
111 usb_flags_t usb_flags);
112 static int ohci_hcdi_pipe_stop_intr_polling(
113 usba_pipe_handle_data_t *ph,
114 usb_flags_t usb_flags);
115 static int ohci_hcdi_get_current_frame_number(
116 usba_device_t *usba_device,
117 usb_frame_number_t *frame_number);
118 static int ohci_hcdi_get_max_isoc_pkts(
119 usba_device_t *usba_device,
120 uint_t *max_isoc_pkts_per_request);
121 static int ohci_hcdi_pipe_isoc_xfer(
122 usba_pipe_handle_data_t *ph,
123 usb_isoc_req_t *isoc_reqp,
124 usb_flags_t usb_flags);
125 static int ohci_hcdi_pipe_stop_isoc_polling(
126 usba_pipe_handle_data_t *ph,
127 usb_flags_t usb_flags);
128
129 /*
130 * Internal Function Prototypes
131 */
132
133 /* Host Controller Driver (HCD) initialization functions */
134 static void ohci_set_dma_attributes(ohci_state_t *ohcip);
135 static int ohci_allocate_pools(ohci_state_t *ohcip);
136 static void ohci_decode_ddi_dma_addr_bind_handle_result(
137 ohci_state_t *ohcip,
138 int result);
139 static int ohci_map_regs(ohci_state_t *ohcip);
140 static int ohci_register_intrs_and_init_mutex(
141 ohci_state_t *ohcip);
142 static int ohci_add_intrs(ohci_state_t *ohcip,
143 int intr_type);
144 static int ohci_init_ctlr(ohci_state_t *ohcip);
145 static int ohci_init_hcca(ohci_state_t *ohcip);
146 static void ohci_build_interrupt_lattice(
147 ohci_state_t *ohcip);
148 static int ohci_take_control(ohci_state_t *ohcip);
149 static usba_hcdi_ops_t *ohci_alloc_hcdi_ops(
150 ohci_state_t *ohcip);
151
152 /* Host Controller Driver (HCD) deinitialization functions */
153 static int ohci_cleanup(ohci_state_t *ohcip);
154 static void ohci_rem_intrs(ohci_state_t *ohcip);
155 static int ohci_cpr_suspend(ohci_state_t *ohcip);
156 static int ohci_cpr_resume(ohci_state_t *ohcip);
157
158 /* Bandwidth Allocation functions */
159 static int ohci_allocate_bandwidth(ohci_state_t *ohcip,
160 usba_pipe_handle_data_t *ph,
161 uint_t *node);
162 static void ohci_deallocate_bandwidth(ohci_state_t *ohcip,
163 usba_pipe_handle_data_t *ph);
164 static int ohci_compute_total_bandwidth(
165 usb_ep_descr_t *endpoint,
166 usb_port_status_t port_status,
167 uint_t *bandwidth);
168 static int ohci_adjust_polling_interval(
169 ohci_state_t *ohcip,
170 usb_ep_descr_t *endpoint,
171 usb_port_status_t port_status);
172 static uint_t ohci_lattice_height(uint_t interval);
173 static uint_t ohci_lattice_parent(uint_t node);
174 static uint_t ohci_leftmost_leaf(uint_t node,
175 uint_t height);
176 static uint_t ohci_hcca_intr_index(
177 uint_t node);
178 static uint_t ohci_hcca_leaf_index(
179 uint_t leaf);
180 static uint_t ohci_pow_2(uint_t x);
181 static uint_t ohci_log_2(uint_t x);
182
183 /* Endpoint Descriptor (ED) related functions */
184 static uint_t ohci_unpack_endpoint(ohci_state_t *ohcip,
185 usba_pipe_handle_data_t *ph);
186 static void ohci_insert_ed(ohci_state_t *ohcip,
187 usba_pipe_handle_data_t *ph);
188 static void ohci_insert_ctrl_ed(
189 ohci_state_t *ohcip,
190 ohci_pipe_private_t *pp);
191 static void ohci_insert_bulk_ed(
192 ohci_state_t *ohcip,
193 ohci_pipe_private_t *pp);
194 static void ohci_insert_intr_ed(
195 ohci_state_t *ohcip,
196 ohci_pipe_private_t *pp);
197 static void ohci_insert_isoc_ed(
198 ohci_state_t *ohcip,
199 ohci_pipe_private_t *pp);
200 static void ohci_modify_sKip_bit(ohci_state_t *ohcip,
201 ohci_pipe_private_t *pp,
202 skip_bit_t action,
203 usb_flags_t flag);
204 static void ohci_remove_ed(ohci_state_t *ohcip,
205 ohci_pipe_private_t *pp);
206 static void ohci_remove_ctrl_ed(
207 ohci_state_t *ohcip,
208 ohci_pipe_private_t *pp);
209 static void ohci_remove_bulk_ed(
210 ohci_state_t *ohcip,
211 ohci_pipe_private_t *pp);
212 static void ohci_remove_periodic_ed(
213 ohci_state_t *ohcip,
214 ohci_pipe_private_t *pp);
215 static void ohci_insert_ed_on_reclaim_list(
216 ohci_state_t *ohcip,
217 ohci_pipe_private_t *pp);
218 static void ohci_detach_ed_from_list(
219 ohci_state_t *ohcip,
220 ohci_ed_t *ept,
221 uint_t ept_type);
222 static ohci_ed_t *ohci_ed_iommu_to_cpu(
223 ohci_state_t *ohcip,
224 uintptr_t addr);
225
226 /* Transfer Descriptor (TD) related functions */
227 static int ohci_initialize_dummy(ohci_state_t *ohcip,
228 ohci_ed_t *ept);
229 static ohci_trans_wrapper_t *ohci_allocate_ctrl_resources(
230 ohci_state_t *ohcip,
231 ohci_pipe_private_t *pp,
232 usb_ctrl_req_t *ctrl_reqp,
233 usb_flags_t usb_flags);
234 static void ohci_insert_ctrl_req(
235 ohci_state_t *ohcip,
236 usba_pipe_handle_data_t *ph,
237 usb_ctrl_req_t *ctrl_reqp,
238 ohci_trans_wrapper_t *tw,
239 usb_flags_t usb_flags);
240 static ohci_trans_wrapper_t *ohci_allocate_bulk_resources(
241 ohci_state_t *ohcip,
242 ohci_pipe_private_t *pp,
243 usb_bulk_req_t *bulk_reqp,
244 usb_flags_t usb_flags);
245 static void ohci_insert_bulk_req(ohci_state_t *ohcip,
246 usba_pipe_handle_data_t *ph,
247 usb_bulk_req_t *bulk_reqp,
248 ohci_trans_wrapper_t *tw,
249 usb_flags_t flags);
250 static int ohci_start_pipe_polling(ohci_state_t *ohcip,
251 usba_pipe_handle_data_t *ph,
252 usb_flags_t flags);
253 static void ohci_set_periodic_pipe_polling(
254 ohci_state_t *ohcip,
255 usba_pipe_handle_data_t *ph);
256 static ohci_trans_wrapper_t *ohci_allocate_intr_resources(
257 ohci_state_t *ohcip,
258 usba_pipe_handle_data_t *ph,
259 usb_intr_req_t *intr_reqp,
260 usb_flags_t usb_flags);
261 static void ohci_insert_intr_req(ohci_state_t *ohcip,
262 ohci_pipe_private_t *pp,
263 ohci_trans_wrapper_t *tw,
264 usb_flags_t flags);
265 static int ohci_stop_periodic_pipe_polling(
266 ohci_state_t *ohcip,
267 usba_pipe_handle_data_t *ph,
268 usb_flags_t flags);
269 static ohci_trans_wrapper_t *ohci_allocate_isoc_resources(
270 ohci_state_t *ohcip,
271 usba_pipe_handle_data_t *ph,
272 usb_isoc_req_t *isoc_reqp,
273 usb_flags_t usb_flags);
274 static int ohci_insert_isoc_req(ohci_state_t *ohcip,
275 ohci_pipe_private_t *pp,
276 ohci_trans_wrapper_t *tw,
277 uint_t flags);
278 static int ohci_insert_hc_td(ohci_state_t *ohcip,
279 uint_t hctd_ctrl,
280 uint32_t hctd_dma_offs,
281 size_t hctd_length,
282 uint32_t hctd_ctrl_phase,
283 ohci_pipe_private_t *pp,
284 ohci_trans_wrapper_t *tw);
285 static ohci_td_t *ohci_allocate_td_from_pool(
286 ohci_state_t *ohcip);
287 static void ohci_fill_in_td(ohci_state_t *ohcip,
288 ohci_td_t *td,
289 ohci_td_t *new_dummy,
290 uint_t hctd_ctrl,
291 uint32_t hctd_dma_offs,
292 size_t hctd_length,
293 uint32_t hctd_ctrl_phase,
294 ohci_pipe_private_t *pp,
295 ohci_trans_wrapper_t *tw);
296 static void ohci_init_itd(
297 ohci_state_t *ohcip,
298 ohci_trans_wrapper_t *tw,
299 uint_t hctd_ctrl,
300 uint32_t index,
301 ohci_td_t *td);
302 static int ohci_insert_td_with_frame_number(
303 ohci_state_t *ohcip,
304 ohci_pipe_private_t *pp,
305 ohci_trans_wrapper_t *tw,
306 ohci_td_t *current_td,
307 ohci_td_t *dummy_td);
308 static void ohci_insert_td_on_tw(ohci_state_t *ohcip,
309 ohci_trans_wrapper_t *tw,
310 ohci_td_t *td);
311 static void ohci_done_list_tds(ohci_state_t *ohcip,
312 usba_pipe_handle_data_t *ph);
313
314 /* Transfer Wrapper (TW) functions */
315 static ohci_trans_wrapper_t *ohci_create_transfer_wrapper(
316 ohci_state_t *ohcip,
317 ohci_pipe_private_t *pp,
318 size_t length,
319 uint_t usb_flags);
320 static ohci_trans_wrapper_t *ohci_create_isoc_transfer_wrapper(
321 ohci_state_t *ohcip,
322 ohci_pipe_private_t *pp,
323 size_t length,
324 usb_isoc_pkt_descr_t *descr,
325 ushort_t pkt_count,
326 size_t td_count,
327 uint_t usb_flags);
328 int ohci_allocate_tds_for_tw(
329 ohci_state_t *ohcip,
330 ohci_trans_wrapper_t *tw,
331 size_t td_count);
332 static ohci_trans_wrapper_t *ohci_allocate_tw_resources(
333 ohci_state_t *ohcip,
334 ohci_pipe_private_t *pp,
335 size_t length,
336 usb_flags_t usb_flags,
337 size_t td_count);
338 static void ohci_free_tw_tds_resources(
339 ohci_state_t *ohcip,
340 ohci_trans_wrapper_t *tw);
341 static void ohci_start_xfer_timer(
342 ohci_state_t *ohcip,
343 ohci_pipe_private_t *pp,
344 ohci_trans_wrapper_t *tw);
345 static void ohci_stop_xfer_timer(
346 ohci_state_t *ohcip,
347 ohci_trans_wrapper_t *tw,
348 uint_t flag);
349 static void ohci_xfer_timeout_handler(void *arg);
350 static void ohci_remove_tw_from_timeout_list(
351 ohci_state_t *ohcip,
352 ohci_trans_wrapper_t *tw);
353 static void ohci_start_timer(ohci_state_t *ohcip);
354 static void ohci_free_dma_resources(ohci_state_t *ohcip,
355 usba_pipe_handle_data_t *ph);
356 static void ohci_free_tw(ohci_state_t *ohcip,
357 ohci_trans_wrapper_t *tw);
358 static int ohci_tw_rebind_cookie(
359 ohci_state_t *ohcip,
360 ohci_pipe_private_t *pp,
361 ohci_trans_wrapper_t *tw);
362
363 /* Interrupt Handling functions */
364 static uint_t ohci_intr(caddr_t arg1,
365 caddr_t arg2);
366 static void ohci_handle_missed_intr(
367 ohci_state_t *ohcip);
368 static void ohci_handle_ue(ohci_state_t *ohcip);
369 static void ohci_handle_endpoint_reclaimation(
370 ohci_state_t *ohcip);
371 static void ohci_traverse_done_list(
372 ohci_state_t *ohcip,
373 ohci_td_t *head_done_list);
374 static ohci_td_t *ohci_reverse_done_list(
375 ohci_state_t *ohcip,
376 ohci_td_t *head_done_list);
377 static usb_cr_t ohci_parse_error(ohci_state_t *ohcip,
378 ohci_td_t *td);
379 static void ohci_parse_isoc_error(
380 ohci_state_t *ohcip,
381 ohci_pipe_private_t *pp,
382 ohci_trans_wrapper_t *tw,
383 ohci_td_t *td);
384 static usb_cr_t ohci_check_for_error(
385 ohci_state_t *ohcip,
386 ohci_pipe_private_t *pp,
387 ohci_trans_wrapper_t *tw,
388 ohci_td_t *td,
389 uint_t ctrl);
390 static void ohci_handle_error(
391 ohci_state_t *ohcip,
392 ohci_td_t *td,
393 usb_cr_t error);
394 static int ohci_cleanup_data_underrun(
395 ohci_state_t *ohcip,
396 ohci_pipe_private_t *pp,
397 ohci_trans_wrapper_t *tw,
398 ohci_td_t *td);
399 static void ohci_handle_normal_td(
400 ohci_state_t *ohcip,
401 ohci_td_t *td,
402 ohci_trans_wrapper_t *tw);
403 static void ohci_handle_ctrl_td(ohci_state_t *ohcip,
404 ohci_pipe_private_t *pp,
405 ohci_trans_wrapper_t *tw,
406 ohci_td_t *td,
407 void *);
408 static void ohci_handle_bulk_td(ohci_state_t *ohcip,
409 ohci_pipe_private_t *pp,
410 ohci_trans_wrapper_t *tw,
411 ohci_td_t *td,
412 void *);
413 static void ohci_handle_intr_td(ohci_state_t *ohcip,
414 ohci_pipe_private_t *pp,
415 ohci_trans_wrapper_t *tw,
416 ohci_td_t *td,
417 void *);
418 static void ohci_handle_one_xfer_completion(
419 ohci_state_t *ohcip,
420 ohci_trans_wrapper_t *tw);
421 static void ohci_handle_isoc_td(ohci_state_t *ohcip,
422 ohci_pipe_private_t *pp,
423 ohci_trans_wrapper_t *tw,
424 ohci_td_t *td,
425 void *);
426 static void ohci_sendup_td_message(
427 ohci_state_t *ohcip,
428 ohci_pipe_private_t *pp,
429 ohci_trans_wrapper_t *tw,
430 ohci_td_t *td,
431 usb_cr_t error);
432 static int ohci_check_done_head(
433 ohci_state_t *ohcip,
434 ohci_td_t *done_head);
435
436 /* Miscillaneous functions */
437 static void ohci_cpr_cleanup(
438 ohci_state_t *ohcip);
439 static usb_req_attrs_t ohci_get_xfer_attrs(ohci_state_t *ohcip,
440 ohci_pipe_private_t *pp,
441 ohci_trans_wrapper_t *tw);
442 static int ohci_allocate_periodic_in_resource(
443 ohci_state_t *ohcip,
444 ohci_pipe_private_t *pp,
445 ohci_trans_wrapper_t *tw,
446 usb_flags_t flags);
447 static int ohci_wait_for_sof(
448 ohci_state_t *ohcip);
449 static void ohci_pipe_cleanup(
450 ohci_state_t *ohcip,
451 usba_pipe_handle_data_t *ph);
452 static void ohci_wait_for_transfers_completion(
453 ohci_state_t *ohcip,
454 ohci_pipe_private_t *pp);
455 static void ohci_check_for_transfers_completion(
456 ohci_state_t *ohcip,
457 ohci_pipe_private_t *pp);
458 static void ohci_save_data_toggle(ohci_state_t *ohcip,
459 usba_pipe_handle_data_t *ph);
460 static void ohci_restore_data_toggle(ohci_state_t *ohcip,
461 usba_pipe_handle_data_t *ph);
462 static void ohci_deallocate_periodic_in_resource(
463 ohci_state_t *ohcip,
464 ohci_pipe_private_t *pp,
465 ohci_trans_wrapper_t *tw);
466 static void ohci_do_client_periodic_in_req_callback(
467 ohci_state_t *ohcip,
468 ohci_pipe_private_t *pp,
469 usb_cr_t completion_reason);
470 static void ohci_hcdi_callback(
471 usba_pipe_handle_data_t *ph,
472 ohci_trans_wrapper_t *tw,
473 usb_cr_t completion_reason);
474
475 /* Kstat Support */
476 static void ohci_create_stats(ohci_state_t *ohcip);
477 static void ohci_destroy_stats(ohci_state_t *ohcip);
478 static void ohci_do_byte_stats(
479 ohci_state_t *ohcip,
480 size_t len,
481 uint8_t attr,
482 uint8_t addr);
483 static void ohci_do_intrs_stats(
484 ohci_state_t *ohcip,
485 int val);
486 static void ohci_print_op_regs(ohci_state_t *ohcip);
487 static void ohci_print_ed(ohci_state_t *ohcip,
488 ohci_ed_t *ed);
489 static void ohci_print_td(ohci_state_t *ohcip,
490 ohci_td_t *td);
491
492 /* extern */
493 int usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level);
494
495 /*
496 * Device operations (dev_ops) entries function prototypes.
497 *
498 * We use the hub cbops since all nexus ioctl operations defined so far will
499 * be executed by the root hub. The following are the Host Controller Driver
500 * (HCD) entry points.
501 *
502 * the open/close/ioctl functions call the corresponding usba_hubdi_*
503 * calls after looking up the dip thru the dev_t.
504 */
505 static int ohci_open(dev_t *devp, int flags, int otyp, cred_t *credp);
506 static int ohci_close(dev_t dev, int flag, int otyp, cred_t *credp);
507 static int ohci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
508 cred_t *credp, int *rvalp);
509
510 static int ohci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
511 static int ohci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
512 static int ohci_quiesce(dev_info_t *dip);
513
514 static int ohci_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
515 void *arg, void **result);
516
517 static struct cb_ops ohci_cb_ops = {
518 ohci_open, /* Open */
519 ohci_close, /* Close */
520 nodev, /* Strategy */
521 nodev, /* Print */
522 nodev, /* Dump */
523 nodev, /* Read */
524 nodev, /* Write */
525 ohci_ioctl, /* Ioctl */
526 nodev, /* Devmap */
527 nodev, /* Mmap */
528 nodev, /* Segmap */
529 nochpoll, /* Poll */
530 ddi_prop_op, /* cb_prop_op */
531 NULL, /* Streamtab */
532 D_MP /* Driver compatibility flag */
533 };
534
535 static struct dev_ops ohci_ops = {
536 DEVO_REV, /* Devo_rev */
537 0, /* Refcnt */
538 ohci_info, /* Info */
539 nulldev, /* Identify */
540 nulldev, /* Probe */
541 ohci_attach, /* Attach */
542 ohci_detach, /* Detach */
543 nodev, /* Reset */
544 &ohci_cb_ops, /* Driver operations */
545 &usba_hubdi_busops, /* Bus operations */
546 usba_hubdi_root_hub_power, /* Power */
547 ohci_quiesce, /* Quiesce */
548 };
549
550 /*
551 * The USBA library must be loaded for this driver.
552 */
553 static struct modldrv modldrv = {
554 &mod_driverops, /* Type of module. This one is a driver */
555 "USB OpenHCI Driver", /* Name of the module. */
556 &ohci_ops, /* Driver ops */
557 };
558
559 static struct modlinkage modlinkage = {
560 MODREV_1, (void *)&modldrv, NULL
561 };
562
563
564 int
_init(void)565 _init(void)
566 {
567 int error;
568
569 /* Initialize the soft state structures */
570 if ((error = ddi_soft_state_init(&ohci_statep, sizeof (ohci_state_t),
571 OHCI_INSTS)) != 0) {
572 return (error);
573 }
574
575 /* Install the loadable module */
576 if ((error = mod_install(&modlinkage)) != 0) {
577 ddi_soft_state_fini(&ohci_statep);
578 }
579
580 return (error);
581 }
582
583
584 int
_info(struct modinfo * modinfop)585 _info(struct modinfo *modinfop)
586 {
587 return (mod_info(&modlinkage, modinfop));
588 }
589
590
591 int
_fini(void)592 _fini(void)
593 {
594 int error;
595
596 if ((error = mod_remove(&modlinkage)) == 0) {
597 /* Release per module resources */
598 ddi_soft_state_fini(&ohci_statep);
599 }
600
601 return (error);
602 }
603
604
605 /*
606 * Host Controller Driver (HCD) entry points
607 */
608
609 /*
610 * ohci_attach:
611 */
612 static int
ohci_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)613 ohci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
614 {
615 int instance;
616 ohci_state_t *ohcip = NULL;
617 usba_hcdi_register_args_t hcdi_args;
618
619 switch (cmd) {
620 case DDI_ATTACH:
621 break;
622 case DDI_RESUME:
623 ohcip = ohci_obtain_state(dip);
624
625 return (ohci_cpr_resume(ohcip));
626 default:
627 return (DDI_FAILURE);
628 }
629
630 /* Get the instance and create soft state */
631 instance = ddi_get_instance(dip);
632
633 if (ddi_soft_state_zalloc(ohci_statep, instance) != 0) {
634
635 return (DDI_FAILURE);
636 }
637
638 ohcip = ddi_get_soft_state(ohci_statep, instance);
639 if (ohcip == NULL) {
640
641 return (DDI_FAILURE);
642 }
643
644 ohcip->ohci_flags = OHCI_ATTACH;
645
646 ohcip->ohci_log_hdl = usb_alloc_log_hdl(dip, "ohci", &ohci_errlevel,
647 &ohci_errmask, &ohci_instance_debug, 0);
648
649 ohcip->ohci_flags |= OHCI_ZALLOC;
650
651 /* Set host controller soft state to initilization */
652 ohcip->ohci_hc_soft_state = OHCI_CTLR_INIT_STATE;
653
654 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
655 "ohcip = 0x%p", (void *)ohcip);
656
657 /* Initialize the DMA attributes */
658 ohci_set_dma_attributes(ohcip);
659
660 /* Save the dip and instance */
661 ohcip->ohci_dip = dip;
662 ohcip->ohci_instance = instance;
663
664 /* Initialize the kstat structures */
665 ohci_create_stats(ohcip);
666
667 /* Create the td and ed pools */
668 if (ohci_allocate_pools(ohcip) != DDI_SUCCESS) {
669 (void) ohci_cleanup(ohcip);
670
671 return (DDI_FAILURE);
672 }
673
674 /* Map the registers */
675 if (ohci_map_regs(ohcip) != DDI_SUCCESS) {
676 (void) ohci_cleanup(ohcip);
677
678 return (DDI_FAILURE);
679 }
680
681 /* Get the ohci chip vendor and device id */
682 ohcip->ohci_vendor_id = pci_config_get16(
683 ohcip->ohci_config_handle, PCI_CONF_VENID);
684 ohcip->ohci_device_id = pci_config_get16(
685 ohcip->ohci_config_handle, PCI_CONF_DEVID);
686 ohcip->ohci_rev_id = pci_config_get8(
687 ohcip->ohci_config_handle, PCI_CONF_REVID);
688
689 /* Register interrupts */
690 if (ohci_register_intrs_and_init_mutex(ohcip) != DDI_SUCCESS) {
691 (void) ohci_cleanup(ohcip);
692
693 return (DDI_FAILURE);
694 }
695
696 mutex_enter(&ohcip->ohci_int_mutex);
697
698 /* Initialize the controller */
699 if (ohci_init_ctlr(ohcip) != DDI_SUCCESS) {
700 mutex_exit(&ohcip->ohci_int_mutex);
701 (void) ohci_cleanup(ohcip);
702
703 return (DDI_FAILURE);
704 }
705
706 /*
707 * At this point, the hardware wiil be okay.
708 * Initialize the usba_hcdi structure
709 */
710 ohcip->ohci_hcdi_ops = ohci_alloc_hcdi_ops(ohcip);
711
712 mutex_exit(&ohcip->ohci_int_mutex);
713
714 /*
715 * Make this HCD instance known to USBA
716 * (dma_attr must be passed for USBA busctl's)
717 */
718 hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION;
719 hcdi_args.usba_hcdi_register_dip = dip;
720 hcdi_args.usba_hcdi_register_ops = ohcip->ohci_hcdi_ops;
721 hcdi_args.usba_hcdi_register_dma_attr = &ohcip->ohci_dma_attr;
722
723 /*
724 * Priority and iblock_cookie are one and the same
725 * (However, retaining hcdi_soft_iblock_cookie for now
726 * assigning it w/ priority. In future all iblock_cookie
727 * could just go)
728 */
729 hcdi_args.usba_hcdi_register_iblock_cookie =
730 (ddi_iblock_cookie_t)(uintptr_t)ohcip->ohci_intr_pri;
731
732 if (usba_hcdi_register(&hcdi_args, 0) != DDI_SUCCESS) {
733 (void) ohci_cleanup(ohcip);
734
735 return (DDI_FAILURE);
736 }
737 ohcip->ohci_flags |= OHCI_USBAREG;
738
739 mutex_enter(&ohcip->ohci_int_mutex);
740
741 if ((ohci_init_root_hub(ohcip)) != USB_SUCCESS) {
742 mutex_exit(&ohcip->ohci_int_mutex);
743 (void) ohci_cleanup(ohcip);
744
745 return (DDI_FAILURE);
746 }
747
748 mutex_exit(&ohcip->ohci_int_mutex);
749
750 /* Finally load the root hub driver */
751 if (ohci_load_root_hub_driver(ohcip) != USB_SUCCESS) {
752 (void) ohci_cleanup(ohcip);
753
754 return (DDI_FAILURE);
755 }
756 ohcip->ohci_flags |= OHCI_RHREG;
757
758 /* Display information in the banner */
759 ddi_report_dev(dip);
760
761 mutex_enter(&ohcip->ohci_int_mutex);
762
763 /* Reset the ohci initilization flag */
764 ohcip->ohci_flags &= ~OHCI_ATTACH;
765
766 /* Print the Host Control's Operational registers */
767 ohci_print_op_regs(ohcip);
768
769 /* For RIO we need to call pci_report_pmcap */
770 if (OHCI_IS_RIO(ohcip)) {
771
772 (void) pci_report_pmcap(dip, PCI_PM_IDLESPEED, (void *)4000);
773 }
774
775 mutex_exit(&ohcip->ohci_int_mutex);
776
777 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
778 "ohci_attach: dip = 0x%p done", (void *)dip);
779
780 return (DDI_SUCCESS);
781 }
782
783
784 /*
785 * ohci_detach:
786 */
787 int
ohci_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)788 ohci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
789 {
790 ohci_state_t *ohcip = ohci_obtain_state(dip);
791
792 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_detach:");
793
794 switch (cmd) {
795 case DDI_DETACH:
796
797 return (ohci_cleanup(ohcip));
798
799 case DDI_SUSPEND:
800
801 return (ohci_cpr_suspend(ohcip));
802 default:
803
804 return (DDI_FAILURE);
805 }
806 }
807
808
809 /*
810 * ohci_info:
811 */
812 /* ARGSUSED */
813 static int
ohci_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)814 ohci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
815 {
816 dev_t dev;
817 ohci_state_t *ohcip;
818 int instance;
819 int error = DDI_FAILURE;
820
821 switch (infocmd) {
822 case DDI_INFO_DEVT2DEVINFO:
823 dev = (dev_t)arg;
824 instance = OHCI_UNIT(dev);
825 ohcip = ddi_get_soft_state(ohci_statep, instance);
826 if (ohcip != NULL) {
827 *result = (void *)ohcip->ohci_dip;
828 if (*result != NULL) {
829 error = DDI_SUCCESS;
830 }
831 } else {
832 *result = NULL;
833 }
834
835 break;
836 case DDI_INFO_DEVT2INSTANCE:
837 dev = (dev_t)arg;
838 instance = OHCI_UNIT(dev);
839 *result = (void *)(uintptr_t)instance;
840 error = DDI_SUCCESS;
841 break;
842 default:
843 break;
844 }
845
846 return (error);
847 }
848
849
850 /*
851 * cb_ops entry points
852 */
853 static dev_info_t *
ohci_get_dip(dev_t dev)854 ohci_get_dip(dev_t dev)
855 {
856 int instance = OHCI_UNIT(dev);
857 ohci_state_t *ohcip = ddi_get_soft_state(ohci_statep, instance);
858
859 if (ohcip) {
860
861 return (ohcip->ohci_dip);
862 } else {
863
864 return (NULL);
865 }
866 }
867
868
869 static int
ohci_open(dev_t * devp,int flags,int otyp,cred_t * credp)870 ohci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
871 {
872 dev_info_t *dip = ohci_get_dip(*devp);
873
874 return (usba_hubdi_open(dip, devp, flags, otyp, credp));
875 }
876
877
878 static int
ohci_close(dev_t dev,int flag,int otyp,cred_t * credp)879 ohci_close(dev_t dev, int flag, int otyp, cred_t *credp)
880 {
881 dev_info_t *dip = ohci_get_dip(dev);
882
883 return (usba_hubdi_close(dip, dev, flag, otyp, credp));
884 }
885
886
887 static int
ohci_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)888 ohci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp,
889 int *rvalp)
890 {
891 dev_info_t *dip = ohci_get_dip(dev);
892
893 return (usba_hubdi_ioctl(dip,
894 dev, cmd, arg, mode, credp, rvalp));
895 }
896
897
898 /*
899 * Host Controller Driver (HCD) initialization functions
900 */
901
902 /*
903 * ohci_set_dma_attributes:
904 *
905 * Set the limits in the DMA attributes structure. Most of the values used
906 * in the DMA limit structres are the default values as specified by the
907 * Writing PCI device drivers document.
908 */
909 static void
ohci_set_dma_attributes(ohci_state_t * ohcip)910 ohci_set_dma_attributes(ohci_state_t *ohcip)
911 {
912 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
913 "ohci_set_dma_attributes:");
914
915 /* Initialize the DMA attributes */
916 ohcip->ohci_dma_attr.dma_attr_version = DMA_ATTR_V0;
917 ohcip->ohci_dma_attr.dma_attr_addr_lo = 0x00000000ull;
918 ohcip->ohci_dma_attr.dma_attr_addr_hi = 0xfffffffeull;
919
920 /* 32 bit addressing */
921 ohcip->ohci_dma_attr.dma_attr_count_max = OHCI_DMA_ATTR_COUNT_MAX;
922
923 /* Byte alignment */
924 ohcip->ohci_dma_attr.dma_attr_align = OHCI_DMA_ATTR_ALIGNMENT;
925
926 /*
927 * Since PCI specification is byte alignment, the
928 * burstsize field should be set to 1 for PCI devices.
929 */
930 ohcip->ohci_dma_attr.dma_attr_burstsizes = 0x1;
931
932 ohcip->ohci_dma_attr.dma_attr_minxfer = 0x1;
933 ohcip->ohci_dma_attr.dma_attr_maxxfer = OHCI_DMA_ATTR_MAX_XFER;
934 ohcip->ohci_dma_attr.dma_attr_seg = 0xffffffffull;
935 ohcip->ohci_dma_attr.dma_attr_sgllen = 1;
936 ohcip->ohci_dma_attr.dma_attr_granular = OHCI_DMA_ATTR_GRANULAR;
937 ohcip->ohci_dma_attr.dma_attr_flags = 0;
938 }
939
940
941 /*
942 * ohci_allocate_pools:
943 *
944 * Allocate the system memory for the Endpoint Descriptor (ED) and for the
945 * Transfer Descriptor (TD) pools. Both ED and TD structures must be aligned
946 * to a 16 byte boundary.
947 */
948 static int
ohci_allocate_pools(ohci_state_t * ohcip)949 ohci_allocate_pools(ohci_state_t *ohcip)
950 {
951 ddi_device_acc_attr_t dev_attr;
952 size_t real_length;
953 int result;
954 uint_t ccount;
955 int i;
956
957 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
958 "ohci_allocate_pools:");
959
960 /* The host controller will be little endian */
961 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
962 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
963 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
964
965 /* Byte alignment to TD alignment */
966 ohcip->ohci_dma_attr.dma_attr_align = OHCI_DMA_ATTR_TD_ALIGNMENT;
967
968 /* Allocate the TD pool DMA handle */
969 if (ddi_dma_alloc_handle(ohcip->ohci_dip, &ohcip->ohci_dma_attr,
970 DDI_DMA_SLEEP, 0,
971 &ohcip->ohci_td_pool_dma_handle) != DDI_SUCCESS) {
972
973 return (DDI_FAILURE);
974 }
975
976 /* Allocate the memory for the TD pool */
977 if (ddi_dma_mem_alloc(ohcip->ohci_td_pool_dma_handle,
978 ohci_td_pool_size * sizeof (ohci_td_t),
979 &dev_attr,
980 DDI_DMA_CONSISTENT,
981 DDI_DMA_SLEEP,
982 0,
983 (caddr_t *)&ohcip->ohci_td_pool_addr,
984 &real_length,
985 &ohcip->ohci_td_pool_mem_handle)) {
986
987 return (DDI_FAILURE);
988 }
989
990 /* Map the TD pool into the I/O address space */
991 result = ddi_dma_addr_bind_handle(
992 ohcip->ohci_td_pool_dma_handle,
993 NULL,
994 (caddr_t)ohcip->ohci_td_pool_addr,
995 real_length,
996 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
997 DDI_DMA_SLEEP,
998 NULL,
999 &ohcip->ohci_td_pool_cookie,
1000 &ccount);
1001
1002 bzero((void *)ohcip->ohci_td_pool_addr,
1003 ohci_td_pool_size * sizeof (ohci_td_t));
1004
1005 /* Process the result */
1006 if (result == DDI_DMA_MAPPED) {
1007 /* The cookie count should be 1 */
1008 if (ccount != 1) {
1009 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1010 "ohci_allocate_pools: More than 1 cookie");
1011
1012 return (DDI_FAILURE);
1013 }
1014 } else {
1015 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1016 "ohci_allocate_pools: Result = %d", result);
1017
1018 ohci_decode_ddi_dma_addr_bind_handle_result(ohcip, result);
1019
1020 return (DDI_FAILURE);
1021 }
1022
1023 /*
1024 * DMA addresses for TD pools are bound
1025 */
1026 ohcip->ohci_dma_addr_bind_flag |= OHCI_TD_POOL_BOUND;
1027
1028 /* Initialize the TD pool */
1029 for (i = 0; i < ohci_td_pool_size; i ++) {
1030 Set_TD(ohcip->ohci_td_pool_addr[i].hctd_state, HC_TD_FREE);
1031 }
1032
1033 /* Byte alignment to ED alignment */
1034 ohcip->ohci_dma_attr.dma_attr_align = OHCI_DMA_ATTR_ED_ALIGNMENT;
1035
1036 /* Allocate the ED pool DMA handle */
1037 if (ddi_dma_alloc_handle(ohcip->ohci_dip,
1038 &ohcip->ohci_dma_attr,
1039 DDI_DMA_SLEEP,
1040 0,
1041 &ohcip->ohci_ed_pool_dma_handle) != DDI_SUCCESS) {
1042
1043 return (DDI_FAILURE);
1044 }
1045
1046 /* Allocate the memory for the ED pool */
1047 if (ddi_dma_mem_alloc(ohcip->ohci_ed_pool_dma_handle,
1048 ohci_ed_pool_size * sizeof (ohci_ed_t),
1049 &dev_attr,
1050 DDI_DMA_CONSISTENT,
1051 DDI_DMA_SLEEP,
1052 0,
1053 (caddr_t *)&ohcip->ohci_ed_pool_addr,
1054 &real_length,
1055 &ohcip->ohci_ed_pool_mem_handle) != DDI_SUCCESS) {
1056
1057 return (DDI_FAILURE);
1058 }
1059
1060 result = ddi_dma_addr_bind_handle(ohcip->ohci_ed_pool_dma_handle,
1061 NULL,
1062 (caddr_t)ohcip->ohci_ed_pool_addr,
1063 real_length,
1064 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1065 DDI_DMA_SLEEP,
1066 NULL,
1067 &ohcip->ohci_ed_pool_cookie,
1068 &ccount);
1069
1070 bzero((void *)ohcip->ohci_ed_pool_addr,
1071 ohci_ed_pool_size * sizeof (ohci_ed_t));
1072
1073 /* Process the result */
1074 if (result == DDI_DMA_MAPPED) {
1075 /* The cookie count should be 1 */
1076 if (ccount != 1) {
1077 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1078 "ohci_allocate_pools: More than 1 cookie");
1079
1080 return (DDI_FAILURE);
1081 }
1082 } else {
1083 ohci_decode_ddi_dma_addr_bind_handle_result(ohcip, result);
1084
1085 return (DDI_FAILURE);
1086 }
1087
1088 /*
1089 * DMA addresses for ED pools are bound
1090 */
1091 ohcip->ohci_dma_addr_bind_flag |= OHCI_ED_POOL_BOUND;
1092
1093 /* Initialize the ED pool */
1094 for (i = 0; i < ohci_ed_pool_size; i ++) {
1095 Set_ED(ohcip->ohci_ed_pool_addr[i].hced_state, HC_EPT_FREE);
1096 }
1097
1098 return (DDI_SUCCESS);
1099 }
1100
1101
1102 /*
1103 * ohci_decode_ddi_dma_addr_bind_handle_result:
1104 *
1105 * Process the return values of ddi_dma_addr_bind_handle()
1106 */
1107 static void
ohci_decode_ddi_dma_addr_bind_handle_result(ohci_state_t * ohcip,int result)1108 ohci_decode_ddi_dma_addr_bind_handle_result(
1109 ohci_state_t *ohcip,
1110 int result)
1111 {
1112 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
1113 "ohci_decode_ddi_dma_addr_bind_handle_result:");
1114
1115 switch (result) {
1116 case DDI_DMA_PARTIAL_MAP:
1117 USB_DPRINTF_L2(PRINT_MASK_ALL, ohcip->ohci_log_hdl,
1118 "Partial transfers not allowed");
1119 break;
1120 case DDI_DMA_INUSE:
1121 USB_DPRINTF_L2(PRINT_MASK_ALL, ohcip->ohci_log_hdl,
1122 "Handle is in use");
1123 break;
1124 case DDI_DMA_NORESOURCES:
1125 USB_DPRINTF_L2(PRINT_MASK_ALL, ohcip->ohci_log_hdl,
1126 "No resources");
1127 break;
1128 case DDI_DMA_NOMAPPING:
1129 USB_DPRINTF_L2(PRINT_MASK_ALL, ohcip->ohci_log_hdl,
1130 "No mapping");
1131 break;
1132 case DDI_DMA_TOOBIG:
1133 USB_DPRINTF_L2(PRINT_MASK_ALL, ohcip->ohci_log_hdl,
1134 "Object is too big");
1135 break;
1136 default:
1137 USB_DPRINTF_L2(PRINT_MASK_ALL, ohcip->ohci_log_hdl,
1138 "Unknown dma error");
1139 }
1140 }
1141
1142
1143 /*
1144 * ohci_map_regs:
1145 *
1146 * The Host Controller (HC) contains a set of on-chip operational registers
1147 * and which should be mapped into a non-cacheable portion of the system
1148 * addressable space.
1149 */
1150 static int
ohci_map_regs(ohci_state_t * ohcip)1151 ohci_map_regs(ohci_state_t *ohcip)
1152 {
1153 ddi_device_acc_attr_t attr;
1154 uint16_t cmd_reg;
1155
1156 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_map_regs:");
1157
1158 /* The host controller will be little endian */
1159 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1160 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
1161 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1162
1163 /* Map in operational registers */
1164 if (ddi_regs_map_setup(ohcip->ohci_dip, 1,
1165 (caddr_t *)&ohcip->ohci_regsp, 0,
1166 sizeof (ohci_regs_t), &attr,
1167 &ohcip->ohci_regs_handle) != DDI_SUCCESS) {
1168
1169 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1170 "ohci_map_regs: Map setup error");
1171
1172 return (DDI_FAILURE);
1173 }
1174
1175 if (pci_config_setup(ohcip->ohci_dip,
1176 &ohcip->ohci_config_handle) != DDI_SUCCESS) {
1177
1178 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1179 "ohci_map_regs: Config error");
1180
1181 return (DDI_FAILURE);
1182 }
1183
1184 /* Make sure Memory Access Enable and Master Enable are set */
1185 cmd_reg = pci_config_get16(ohcip->ohci_config_handle, PCI_CONF_COMM);
1186
1187 if (!(cmd_reg & PCI_COMM_MAE)) {
1188
1189 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1190 "ohci_map_regs: Memory base address access disabled");
1191
1192 return (DDI_FAILURE);
1193 }
1194
1195 cmd_reg |= (PCI_COMM_MAE | PCI_COMM_ME);
1196
1197 pci_config_put16(ohcip->ohci_config_handle, PCI_CONF_COMM, cmd_reg);
1198
1199 return (DDI_SUCCESS);
1200 }
1201
1202 /*
1203 * The following simulated polling is for debugging purposes only.
1204 * It is activated on x86 by setting usb-polling=true in GRUB or ohci.conf.
1205 */
1206 static int
ohci_is_polled(dev_info_t * dip)1207 ohci_is_polled(dev_info_t *dip)
1208 {
1209 int ret;
1210 char *propval;
1211
1212 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
1213 "usb-polling", &propval) != DDI_SUCCESS)
1214
1215 return (0);
1216
1217 ret = (strcmp(propval, "true") == 0);
1218 ddi_prop_free(propval);
1219
1220 return (ret);
1221 }
1222
1223 static void
ohci_poll_intr(void * arg)1224 ohci_poll_intr(void *arg)
1225 {
1226 /* poll every millisecond */
1227 for (;;) {
1228 (void) ohci_intr(arg, NULL);
1229 delay(drv_usectohz(1000));
1230 }
1231 }
1232
1233 /*
1234 * ohci_register_intrs_and_init_mutex:
1235 *
1236 * Register interrupts and initialize each mutex and condition variables
1237 */
1238 static int
ohci_register_intrs_and_init_mutex(ohci_state_t * ohcip)1239 ohci_register_intrs_and_init_mutex(ohci_state_t *ohcip)
1240 {
1241 int intr_types;
1242
1243 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1244 "ohci_register_intrs_and_init_mutex:");
1245
1246 /*
1247 * Sometimes the OHCI controller of ULI1575 southbridge
1248 * could not receive SOF intrs when enable MSI. Hence
1249 * MSI is disabled for this chip.
1250 */
1251 if ((ohcip->ohci_vendor_id == PCI_ULI1575_VENID) &&
1252 (ohcip->ohci_device_id == PCI_ULI1575_DEVID)) {
1253 ohcip->ohci_msi_enabled = B_FALSE;
1254 } else {
1255 ohcip->ohci_msi_enabled = ohci_enable_msi;
1256 }
1257
1258 if (ohci_is_polled(ohcip->ohci_dip)) {
1259 extern pri_t maxclsyspri;
1260
1261 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1262 "ohci_register_intrs_and_init_mutex: "
1263 "running in simulated polled mode");
1264
1265 (void) thread_create(NULL, 0, ohci_poll_intr, ohcip, 0, &p0,
1266 TS_RUN, maxclsyspri);
1267
1268 goto skip_intr;
1269 }
1270
1271 /* Get supported interrupt types */
1272 if (ddi_intr_get_supported_types(ohcip->ohci_dip,
1273 &intr_types) != DDI_SUCCESS) {
1274 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1275 "ohci_register_intrs_and_init_mutex: "
1276 "ddi_intr_get_supported_types failed");
1277
1278 return (DDI_FAILURE);
1279 }
1280
1281 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1282 "ohci_register_intrs_and_init_mutex: "
1283 "supported interrupt types 0x%x", intr_types);
1284
1285 if ((intr_types & DDI_INTR_TYPE_MSI) && ohcip->ohci_msi_enabled) {
1286 if (ohci_add_intrs(ohcip, DDI_INTR_TYPE_MSI)
1287 != DDI_SUCCESS) {
1288 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1289 "ohci_register_intrs_and_init_mutex: MSI "
1290 "registration failed, trying FIXED interrupt \n");
1291 } else {
1292 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1293 "ohci_register_intrs_and_init_mutex: "
1294 "Using MSI interrupt type\n");
1295
1296 ohcip->ohci_intr_type = DDI_INTR_TYPE_MSI;
1297 ohcip->ohci_flags |= OHCI_INTR;
1298 }
1299 }
1300
1301 if ((!(ohcip->ohci_flags & OHCI_INTR)) &&
1302 (intr_types & DDI_INTR_TYPE_FIXED)) {
1303 if (ohci_add_intrs(ohcip, DDI_INTR_TYPE_FIXED)
1304 != DDI_SUCCESS) {
1305 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1306 "ohci_register_intrs_and_init_mutex: "
1307 "FIXED interrupt registration failed\n");
1308
1309 return (DDI_FAILURE);
1310 }
1311
1312 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1313 "ohci_register_intrs_and_init_mutex: "
1314 "Using FIXED interrupt type\n");
1315
1316 ohcip->ohci_intr_type = DDI_INTR_TYPE_FIXED;
1317 ohcip->ohci_flags |= OHCI_INTR;
1318 }
1319
1320 skip_intr:
1321 /* Create prototype for SOF condition variable */
1322 cv_init(&ohcip->ohci_SOF_cv, NULL, CV_DRIVER, NULL);
1323
1324 /* Semaphore to serialize opens and closes */
1325 sema_init(&ohcip->ohci_ocsem, 1, NULL, SEMA_DRIVER, NULL);
1326
1327 return (DDI_SUCCESS);
1328 }
1329
1330
1331 /*
1332 * ohci_add_intrs:
1333 *
1334 * Register FIXED or MSI interrupts.
1335 */
1336 static int
ohci_add_intrs(ohci_state_t * ohcip,int intr_type)1337 ohci_add_intrs(ohci_state_t *ohcip, int intr_type)
1338 {
1339 int actual, avail, intr_size, count = 0;
1340 int i, flag, ret;
1341
1342 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1343 "ohci_add_intrs: interrupt type 0x%x", intr_type);
1344
1345 /* Get number of interrupts */
1346 ret = ddi_intr_get_nintrs(ohcip->ohci_dip, intr_type, &count);
1347 if ((ret != DDI_SUCCESS) || (count == 0)) {
1348 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1349 "ohci_add_intrs: ddi_intr_get_nintrs() failure, "
1350 "ret: %d, count: %d", ret, count);
1351
1352 return (DDI_FAILURE);
1353 }
1354
1355 /* Get number of available interrupts */
1356 ret = ddi_intr_get_navail(ohcip->ohci_dip, intr_type, &avail);
1357 if ((ret != DDI_SUCCESS) || (avail == 0)) {
1358 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1359 "ohci_add_intrs: ddi_intr_get_navail() failure, "
1360 "ret: %d, count: %d", ret, count);
1361
1362 return (DDI_FAILURE);
1363 }
1364
1365 if (avail < count) {
1366 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1367 "ohci_add_intrs: ohci_add_intrs: nintrs () "
1368 "returned %d, navail returned %d\n", count, avail);
1369 }
1370
1371 /* Allocate an array of interrupt handles */
1372 intr_size = count * sizeof (ddi_intr_handle_t);
1373 ohcip->ohci_htable = kmem_zalloc(intr_size, KM_SLEEP);
1374
1375 flag = (intr_type == DDI_INTR_TYPE_MSI) ?
1376 DDI_INTR_ALLOC_STRICT:DDI_INTR_ALLOC_NORMAL;
1377
1378 /* call ddi_intr_alloc() */
1379 ret = ddi_intr_alloc(ohcip->ohci_dip, ohcip->ohci_htable,
1380 intr_type, 0, count, &actual, flag);
1381
1382 if ((ret != DDI_SUCCESS) || (actual == 0)) {
1383 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1384 "ohci_add_intrs: ddi_intr_alloc() failed %d", ret);
1385
1386 kmem_free(ohcip->ohci_htable, intr_size);
1387
1388 return (DDI_FAILURE);
1389 }
1390
1391 if (actual < count) {
1392 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1393 "ohci_add_intrs: Requested: %d, Received: %d\n",
1394 count, actual);
1395
1396 for (i = 0; i < actual; i++)
1397 (void) ddi_intr_free(ohcip->ohci_htable[i]);
1398
1399 kmem_free(ohcip->ohci_htable, intr_size);
1400
1401 return (DDI_FAILURE);
1402 }
1403
1404 ohcip->ohci_intr_cnt = actual;
1405
1406 if ((ret = ddi_intr_get_pri(ohcip->ohci_htable[0],
1407 &ohcip->ohci_intr_pri)) != DDI_SUCCESS) {
1408 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1409 "ohci_add_intrs: ddi_intr_get_pri() failed %d", ret);
1410
1411 for (i = 0; i < actual; i++)
1412 (void) ddi_intr_free(ohcip->ohci_htable[i]);
1413
1414 kmem_free(ohcip->ohci_htable, intr_size);
1415
1416 return (DDI_FAILURE);
1417 }
1418
1419 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1420 "ohci_add_intrs: Supported Interrupt priority 0x%x",
1421 ohcip->ohci_intr_pri);
1422
1423 /* Test for high level mutex */
1424 if (ohcip->ohci_intr_pri >= ddi_intr_get_hilevel_pri()) {
1425 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1426 "ohci_add_intrs: Hi level interrupt not supported");
1427
1428 for (i = 0; i < actual; i++)
1429 (void) ddi_intr_free(ohcip->ohci_htable[i]);
1430
1431 kmem_free(ohcip->ohci_htable, intr_size);
1432
1433 return (DDI_FAILURE);
1434 }
1435
1436 /* Initialize the mutex */
1437 mutex_init(&ohcip->ohci_int_mutex, NULL, MUTEX_DRIVER,
1438 DDI_INTR_PRI(ohcip->ohci_intr_pri));
1439
1440 /* Call ddi_intr_add_handler() */
1441 for (i = 0; i < actual; i++) {
1442 if ((ret = ddi_intr_add_handler(ohcip->ohci_htable[i],
1443 ohci_intr, (caddr_t)ohcip,
1444 (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
1445 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1446 "ohci_add_intrs: ddi_intr_add_handler() "
1447 "failed %d", ret);
1448
1449 for (i = 0; i < actual; i++)
1450 (void) ddi_intr_free(ohcip->ohci_htable[i]);
1451
1452 mutex_destroy(&ohcip->ohci_int_mutex);
1453 kmem_free(ohcip->ohci_htable, intr_size);
1454
1455 return (DDI_FAILURE);
1456 }
1457 }
1458
1459 if ((ret = ddi_intr_get_cap(ohcip->ohci_htable[0],
1460 &ohcip->ohci_intr_cap)) != DDI_SUCCESS) {
1461 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1462 "ohci_add_intrs: ddi_intr_get_cap() failed %d", ret);
1463
1464 for (i = 0; i < actual; i++) {
1465 (void) ddi_intr_remove_handler(ohcip->ohci_htable[i]);
1466 (void) ddi_intr_free(ohcip->ohci_htable[i]);
1467 }
1468
1469 mutex_destroy(&ohcip->ohci_int_mutex);
1470 kmem_free(ohcip->ohci_htable, intr_size);
1471
1472 return (DDI_FAILURE);
1473 }
1474
1475 /* Enable all interrupts */
1476 if (ohcip->ohci_intr_cap & DDI_INTR_FLAG_BLOCK) {
1477 /* Call ddi_intr_block_enable() for MSI interrupts */
1478 (void) ddi_intr_block_enable(ohcip->ohci_htable,
1479 ohcip->ohci_intr_cnt);
1480 } else {
1481 /* Call ddi_intr_enable for MSI or FIXED interrupts */
1482 for (i = 0; i < ohcip->ohci_intr_cnt; i++)
1483 (void) ddi_intr_enable(ohcip->ohci_htable[i]);
1484 }
1485
1486 return (DDI_SUCCESS);
1487 }
1488
1489
1490 /*
1491 * ohci_init_ctlr:
1492 *
1493 * Initialize the Host Controller (HC).
1494 */
1495 static int
ohci_init_ctlr(ohci_state_t * ohcip)1496 ohci_init_ctlr(ohci_state_t *ohcip)
1497 {
1498 int revision, curr_control, max_packet = 0;
1499 clock_t sof_time_wait;
1500 int retry = 0;
1501 int ohci_frame_interval;
1502
1503 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_init_ctlr:");
1504
1505 if (ohci_take_control(ohcip) != DDI_SUCCESS) {
1506 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1507 "ohci_init_ctlr: ohci_take_control failed\n");
1508
1509 return (DDI_FAILURE);
1510 }
1511
1512 /*
1513 * Soft reset the host controller.
1514 *
1515 * On soft reset, the ohci host controller moves to the
1516 * USB Suspend state in which most of the ohci operational
1517 * registers are reset except stated ones. The soft reset
1518 * doesn't cause a reset to the ohci root hub and even no
1519 * subsequent reset signaling should be asserterd to its
1520 * down stream.
1521 */
1522 Set_OpReg(hcr_cmd_status, HCR_STATUS_RESET);
1523
1524 mutex_exit(&ohcip->ohci_int_mutex);
1525 /* Wait 10ms for reset to complete */
1526 delay(drv_usectohz(OHCI_RESET_TIMEWAIT));
1527 mutex_enter(&ohcip->ohci_int_mutex);
1528
1529 /*
1530 * Do hard reset the host controller.
1531 *
1532 * Now perform USB reset in order to reset the ohci root
1533 * hub.
1534 */
1535 Set_OpReg(hcr_control, HCR_CONTROL_RESET);
1536
1537 /*
1538 * According to Section 5.1.2.3 of the specification, the
1539 * host controller will go into suspend state immediately
1540 * after the reset.
1541 */
1542
1543 /* Verify the version number */
1544 revision = Get_OpReg(hcr_revision);
1545
1546 if ((revision & HCR_REVISION_MASK) != HCR_REVISION_1_0) {
1547
1548 return (DDI_FAILURE);
1549 }
1550
1551 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1552 "ohci_init_ctlr: Revision verified");
1553
1554 /* hcca area need not be initialized on resume */
1555 if (ohcip->ohci_hc_soft_state == OHCI_CTLR_INIT_STATE) {
1556
1557 /* Initialize the hcca area */
1558 if (ohci_init_hcca(ohcip) != DDI_SUCCESS) {
1559
1560 return (DDI_FAILURE);
1561 }
1562 }
1563
1564 /*
1565 * Workaround for ULI1575 chipset. Following OHCI Operational Memory
1566 * Registers are not cleared to their default value on reset.
1567 * Explicitly set the registers to default value.
1568 */
1569 if (ohcip->ohci_vendor_id == PCI_ULI1575_VENID &&
1570 ohcip->ohci_device_id == PCI_ULI1575_DEVID) {
1571 Set_OpReg(hcr_control, HCR_CONTROL_DEFAULT);
1572 Set_OpReg(hcr_intr_enable, HCR_INT_ENABLE_DEFAULT);
1573 Set_OpReg(hcr_HCCA, HCR_HCCA_DEFAULT);
1574 Set_OpReg(hcr_ctrl_head, HCR_CONTROL_HEAD_ED_DEFAULT);
1575 Set_OpReg(hcr_bulk_head, HCR_BULK_HEAD_ED_DEFAULT);
1576 Set_OpReg(hcr_frame_interval, HCR_FRAME_INTERVAL_DEFAULT);
1577 Set_OpReg(hcr_periodic_strt, HCR_PERIODIC_START_DEFAULT);
1578 }
1579
1580 /* Set the HcHCCA to the physical address of the HCCA block */
1581 Set_OpReg(hcr_HCCA, (uint_t)ohcip->ohci_hcca_cookie.dmac_address);
1582
1583 /*
1584 * Set HcInterruptEnable to enable all interrupts except Root
1585 * Hub Status change and SOF interrupts.
1586 */
1587 Set_OpReg(hcr_intr_enable, HCR_INTR_SO | HCR_INTR_WDH |
1588 HCR_INTR_RD | HCR_INTR_UE | HCR_INTR_FNO | HCR_INTR_MIE);
1589
1590 /*
1591 * For non-periodic transfers, reserve atleast for one low-speed
1592 * device transaction. According to USB Bandwidth Analysis white
1593 * paper and also as per OHCI Specification 1.0a, section 7.3.5,
1594 * page 123, one low-speed transaction takes 0x628h full speed
1595 * bits (197 bytes), which comes to around 13% of USB frame time.
1596 *
1597 * The periodic transfers will get around 87% of USB frame time.
1598 */
1599 Set_OpReg(hcr_periodic_strt,
1600 ((PERIODIC_XFER_STARTS * BITS_PER_BYTE) - 1));
1601
1602 /* Save the contents of the Frame Interval Registers */
1603 ohcip->ohci_frame_interval = Get_OpReg(hcr_frame_interval);
1604
1605 /*
1606 * Initialize the FSLargestDataPacket value in the frame interval
1607 * register. The controller compares the value of MaxPacketSize to
1608 * this value to see if the entire packet may be sent out before
1609 * the EOF.
1610 */
1611 max_packet = ((((ohcip->ohci_frame_interval -
1612 MAX_OVERHEAD) * 6) / 7) << HCR_FRME_FSMPS_SHFT);
1613
1614 Set_OpReg(hcr_frame_interval,
1615 (max_packet | ohcip->ohci_frame_interval));
1616
1617 /*
1618 * Sometimes the HcFmInterval register in OHCI controller does not
1619 * maintain its value after the first write. This problem is found
1620 * on ULI M1575 South Bridge. To workaround the hardware problem,
1621 * check the value after write and retry if the last write failed.
1622 */
1623 if (ohcip->ohci_vendor_id == PCI_ULI1575_VENID &&
1624 ohcip->ohci_device_id == PCI_ULI1575_DEVID) {
1625 ohci_frame_interval = Get_OpReg(hcr_frame_interval);
1626 while ((ohci_frame_interval != (max_packet |
1627 ohcip->ohci_frame_interval))) {
1628 if (retry >= 10) {
1629 USB_DPRINTF_L1(PRINT_MASK_ATTA,
1630 ohcip->ohci_log_hdl, "Failed to program"
1631 " Frame Interval Register.");
1632
1633 return (DDI_FAILURE);
1634 }
1635 retry++;
1636 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1637 "ohci_init_ctlr: Failed to program Frame"
1638 " Interval Register, retry=%d", retry);
1639 Set_OpReg(hcr_frame_interval,
1640 (max_packet | ohcip->ohci_frame_interval));
1641 ohci_frame_interval = Get_OpReg(hcr_frame_interval);
1642 }
1643 }
1644
1645 /* Begin sending SOFs */
1646 curr_control = Get_OpReg(hcr_control);
1647
1648 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1649 "ohci_init_ctlr: curr_control=0x%x", curr_control);
1650
1651 /* Set the state to operational */
1652 curr_control = (curr_control &
1653 (~HCR_CONTROL_HCFS)) | HCR_CONTROL_OPERAT;
1654
1655 Set_OpReg(hcr_control, curr_control);
1656
1657 ASSERT((Get_OpReg(hcr_control) &
1658 HCR_CONTROL_HCFS) == HCR_CONTROL_OPERAT);
1659
1660 /* Set host controller soft state to operational */
1661 ohcip->ohci_hc_soft_state = OHCI_CTLR_OPERATIONAL_STATE;
1662
1663 /* Get the number of clock ticks to wait */
1664 sof_time_wait = drv_usectohz(OHCI_MAX_SOF_TIMEWAIT * 1000000);
1665
1666 /* Clear ohci_sof_flag indicating waiting for SOF interrupt */
1667 ohcip->ohci_sof_flag = B_FALSE;
1668
1669 /* Enable the SOF interrupt */
1670 Set_OpReg(hcr_intr_enable, HCR_INTR_SOF);
1671
1672 ASSERT(Get_OpReg(hcr_intr_enable) & HCR_INTR_SOF);
1673
1674 (void) cv_reltimedwait(&ohcip->ohci_SOF_cv,
1675 &ohcip->ohci_int_mutex, sof_time_wait, TR_CLOCK_TICK);
1676
1677 /* Wait for the SOF or timeout event */
1678 if (ohcip->ohci_sof_flag == B_FALSE) {
1679
1680 /* Set host controller soft state to error */
1681 ohcip->ohci_hc_soft_state = OHCI_CTLR_ERROR_STATE;
1682
1683 USB_DPRINTF_L0(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1684 "No SOF interrupts have been received, this USB OHCI host"
1685 "controller is unusable");
1686 return (DDI_FAILURE);
1687 }
1688
1689 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1690 "ohci_init_ctlr: SOF's have started");
1691
1692 return (DDI_SUCCESS);
1693 }
1694
1695
1696 /*
1697 * ohci_init_hcca:
1698 *
1699 * Allocate the system memory and initialize Host Controller Communication
1700 * Area (HCCA). The HCCA structure must be aligned to a 256-byte boundary.
1701 */
1702 static int
ohci_init_hcca(ohci_state_t * ohcip)1703 ohci_init_hcca(ohci_state_t *ohcip)
1704 {
1705 ddi_device_acc_attr_t dev_attr;
1706 size_t real_length;
1707 uint_t mask, ccount;
1708 int result;
1709 uintptr_t addr;
1710
1711 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
1712
1713 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_init_hcca:");
1714
1715 /* The host controller will be little endian */
1716 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1717 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
1718 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1719
1720 /* Byte alignment to HCCA alignment */
1721 ohcip->ohci_dma_attr.dma_attr_align = OHCI_DMA_ATTR_HCCA_ALIGNMENT;
1722
1723 /* Create space for the HCCA block */
1724 if (ddi_dma_alloc_handle(ohcip->ohci_dip, &ohcip->ohci_dma_attr,
1725 DDI_DMA_SLEEP,
1726 0,
1727 &ohcip->ohci_hcca_dma_handle)
1728 != DDI_SUCCESS) {
1729
1730 return (DDI_FAILURE);
1731 }
1732
1733 if (ddi_dma_mem_alloc(ohcip->ohci_hcca_dma_handle,
1734 2 * sizeof (ohci_hcca_t),
1735 &dev_attr,
1736 DDI_DMA_CONSISTENT,
1737 DDI_DMA_SLEEP,
1738 0,
1739 (caddr_t *)&ohcip->ohci_hccap,
1740 &real_length,
1741 &ohcip->ohci_hcca_mem_handle)) {
1742
1743 return (DDI_FAILURE);
1744 }
1745
1746 bzero((void *)ohcip->ohci_hccap, real_length);
1747
1748 /* Figure out the alignment requirements */
1749 Set_OpReg(hcr_HCCA, 0xFFFFFFFF);
1750
1751 /*
1752 * Read the hcr_HCCA register until
1753 * contenets are non-zero.
1754 */
1755 mask = Get_OpReg(hcr_HCCA);
1756
1757 mutex_exit(&ohcip->ohci_int_mutex);
1758 while (mask == 0) {
1759 delay(drv_usectohz(OHCI_TIMEWAIT));
1760 mask = Get_OpReg(hcr_HCCA);
1761 }
1762 mutex_enter(&ohcip->ohci_int_mutex);
1763
1764 ASSERT(mask != 0);
1765
1766 addr = (uintptr_t)ohcip->ohci_hccap;
1767
1768 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1769 "ohci_init_hcca: addr=0x%lx, mask=0x%x", addr, mask);
1770
1771 while (addr & (~mask)) {
1772 addr++;
1773 }
1774
1775 ohcip->ohci_hccap = (ohci_hcca_t *)addr;
1776
1777 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1778 "ohci_init_hcca: Real length %lu", real_length);
1779
1780 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1781 "ohci_init_hcca: virtual hcca 0x%p", (void *)ohcip->ohci_hccap);
1782
1783 /* Map the whole HCCA into the I/O address space */
1784 result = ddi_dma_addr_bind_handle(ohcip->ohci_hcca_dma_handle,
1785 NULL,
1786 (caddr_t)ohcip->ohci_hccap,
1787 real_length,
1788 DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1789 DDI_DMA_SLEEP, NULL,
1790 &ohcip->ohci_hcca_cookie,
1791 &ccount);
1792
1793 if (result == DDI_DMA_MAPPED) {
1794 /* The cookie count should be 1 */
1795 if (ccount != 1) {
1796 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1797 "ohci_init_hcca: More than 1 cookie");
1798
1799 return (DDI_FAILURE);
1800 }
1801 } else {
1802 ohci_decode_ddi_dma_addr_bind_handle_result(ohcip, result);
1803
1804 return (DDI_FAILURE);
1805 }
1806
1807 /*
1808 * DMA addresses for HCCA are bound
1809 */
1810 ohcip->ohci_dma_addr_bind_flag |= OHCI_HCCA_DMA_BOUND;
1811
1812 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1813 "ohci_init_hcca: physical 0x%p",
1814 (void *)(uintptr_t)ohcip->ohci_hcca_cookie.dmac_address);
1815
1816 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1817 "ohci_init_hcca: size %lu", ohcip->ohci_hcca_cookie.dmac_size);
1818
1819 /* Initialize the interrupt lists */
1820 ohci_build_interrupt_lattice(ohcip);
1821
1822 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1823 "ohci_init_hcca: End");
1824
1825 return (DDI_SUCCESS);
1826 }
1827
1828
1829 /*
1830 * ohci_build_interrupt_lattice:
1831 *
1832 * Construct the interrupt lattice tree using static Endpoint Descriptors
1833 * (ED). This interrupt lattice tree will have total of 32 interrupt ED
1834 * lists and the Host Controller (HC) processes one interrupt ED list in
1835 * every frame. The lower five bits of the current frame number indexes
1836 * into an array of 32 interrupt Endpoint Descriptor lists found in the
1837 * HCCA.
1838 */
1839 static void
ohci_build_interrupt_lattice(ohci_state_t * ohcip)1840 ohci_build_interrupt_lattice(ohci_state_t *ohcip)
1841 {
1842 ohci_ed_t *list_array = ohcip->ohci_ed_pool_addr;
1843 int half_list = NUM_INTR_ED_LISTS / 2;
1844 ohci_hcca_t *hccap = ohcip->ohci_hccap;
1845 uintptr_t addr;
1846 int i;
1847
1848 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1849 "ohci_build_interrupt_lattice:");
1850
1851 /*
1852 * Reserve the first 31 Endpoint Descriptor (ED) structures
1853 * in the pool as static endpoints & these are required for
1854 * constructing interrupt lattice tree.
1855 */
1856 for (i = 0; i < NUM_STATIC_NODES; i++) {
1857 Set_ED(list_array[i].hced_ctrl, HC_EPT_sKip);
1858
1859 Set_ED(list_array[i].hced_state, HC_EPT_STATIC);
1860 }
1861
1862 /* Build the interrupt lattice tree */
1863 for (i = 0; i < half_list - 1; i++) {
1864
1865 /*
1866 * The next pointer in the host controller endpoint
1867 * descriptor must contain an iommu address. Calculate
1868 * the offset into the cpu address and add this to the
1869 * starting iommu address.
1870 */
1871 addr = ohci_ed_cpu_to_iommu(ohcip, (ohci_ed_t *)&list_array[i]);
1872
1873 Set_ED(list_array[2*i + 1].hced_next, addr);
1874 Set_ED(list_array[2*i + 2].hced_next, addr);
1875 }
1876
1877 /*
1878 * Initialize the interrupt list in the HCCA so that it points
1879 * to the bottom of the tree.
1880 */
1881 for (i = 0; i < half_list; i++) {
1882 addr = ohci_ed_cpu_to_iommu(ohcip,
1883 (ohci_ed_t *)&list_array[half_list - 1 + ohci_index[i]]);
1884
1885 ASSERT(Get_ED(list_array[half_list - 1 +
1886 ohci_index[i]].hced_ctrl));
1887
1888 ASSERT(addr != 0);
1889
1890 Set_HCCA(hccap->HccaIntTble[i], addr);
1891 Set_HCCA(hccap->HccaIntTble[i + half_list], addr);
1892 }
1893 }
1894
1895
1896 /*
1897 * ohci_take_control:
1898 *
1899 * Take control of the host controller. OpenHCI allows for optional support
1900 * of legacy devices through the use of System Management Mode software and
1901 * system Management interrupt hardware. See section 5.1.1.3 of the OpenHCI
1902 * spec for more details.
1903 */
1904 static int
ohci_take_control(ohci_state_t * ohcip)1905 ohci_take_control(ohci_state_t *ohcip)
1906 {
1907 #if defined(__x86)
1908 uint32_t hcr_control_val;
1909 uint32_t hcr_cmd_status_val;
1910 int wait;
1911 #endif /* __x86 */
1912
1913 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1914 "ohci_take_control:");
1915
1916 #if defined(__x86)
1917 /*
1918 * On x86, we must tell the BIOS we want the controller,
1919 * and wait for it to respond that we can have it.
1920 */
1921 hcr_control_val = Get_OpReg(hcr_control);
1922 if ((hcr_control_val & HCR_CONTROL_IR) == 0) {
1923 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1924 "ohci_take_control: InterruptRouting off\n");
1925
1926 return (DDI_SUCCESS);
1927 }
1928
1929 /* attempt the OwnershipChange request */
1930 hcr_cmd_status_val = Get_OpReg(hcr_cmd_status);
1931 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1932 "ohci_take_control: hcr_cmd_status: 0x%x\n",
1933 hcr_cmd_status_val);
1934 hcr_cmd_status_val |= HCR_STATUS_OCR;
1935
1936 Set_OpReg(hcr_cmd_status, hcr_cmd_status_val);
1937
1938
1939 mutex_exit(&ohcip->ohci_int_mutex);
1940 /* now wait for 5 seconds for InterruptRouting to go away */
1941 for (wait = 0; wait < 5000; wait++) {
1942 if ((Get_OpReg(hcr_control) & HCR_CONTROL_IR) == 0)
1943 break;
1944 delay(drv_usectohz(1000));
1945 }
1946 mutex_enter(&ohcip->ohci_int_mutex);
1947
1948 if (wait >= 5000) {
1949 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1950 "ohci_take_control: couldn't take control from BIOS\n");
1951
1952 return (DDI_FAILURE);
1953 }
1954 #else /* __x86 */
1955 /*
1956 * On Sparc, there won't be special System Management Mode
1957 * hardware for legacy devices, while the x86 platforms may
1958 * have to deal with this. This function may be platform
1959 * specific.
1960 *
1961 * The interrupt routing bit should not be set.
1962 */
1963 if (Get_OpReg(hcr_control) & HCR_CONTROL_IR) {
1964 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1965 "ohci_take_control: Routing bit set");
1966
1967 return (DDI_FAILURE);
1968 }
1969 #endif /* __x86 */
1970
1971 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1972 "ohci_take_control: End");
1973
1974 return (DDI_SUCCESS);
1975 }
1976
1977 /*
1978 * ohci_pm_support:
1979 * always return success since PM has been quite reliable on ohci
1980 */
1981 /*ARGSUSED*/
1982 int
ohci_hcdi_pm_support(dev_info_t * dip)1983 ohci_hcdi_pm_support(dev_info_t *dip)
1984 {
1985 return (USB_SUCCESS);
1986 }
1987
1988 /*
1989 * ohci_alloc_hcdi_ops:
1990 *
1991 * The HCDI interfaces or entry points are the software interfaces used by
1992 * the Universal Serial Bus Driver (USBA) to access the services of the
1993 * Host Controller Driver (HCD). During HCD initialization, inform USBA
1994 * about all available HCDI interfaces or entry points.
1995 */
1996 static usba_hcdi_ops_t *
ohci_alloc_hcdi_ops(ohci_state_t * ohcip)1997 ohci_alloc_hcdi_ops(ohci_state_t *ohcip)
1998 {
1999 usba_hcdi_ops_t *usba_hcdi_ops;
2000
2001 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2002 "ohci_alloc_hcdi_ops:");
2003
2004 usba_hcdi_ops = usba_alloc_hcdi_ops();
2005
2006 usba_hcdi_ops->usba_hcdi_ops_version = HCDI_OPS_VERSION;
2007
2008 usba_hcdi_ops->usba_hcdi_pm_support = ohci_hcdi_pm_support;
2009 usba_hcdi_ops->usba_hcdi_pipe_open = ohci_hcdi_pipe_open;
2010 usba_hcdi_ops->usba_hcdi_pipe_close = ohci_hcdi_pipe_close;
2011
2012 usba_hcdi_ops->usba_hcdi_pipe_reset = ohci_hcdi_pipe_reset;
2013 usba_hcdi_ops->usba_hcdi_pipe_reset_data_toggle =
2014 ohci_hcdi_pipe_reset_data_toggle;
2015
2016 usba_hcdi_ops->usba_hcdi_pipe_ctrl_xfer = ohci_hcdi_pipe_ctrl_xfer;
2017 usba_hcdi_ops->usba_hcdi_pipe_bulk_xfer = ohci_hcdi_pipe_bulk_xfer;
2018 usba_hcdi_ops->usba_hcdi_pipe_intr_xfer = ohci_hcdi_pipe_intr_xfer;
2019 usba_hcdi_ops->usba_hcdi_pipe_isoc_xfer = ohci_hcdi_pipe_isoc_xfer;
2020
2021 usba_hcdi_ops->usba_hcdi_bulk_transfer_size =
2022 ohci_hcdi_bulk_transfer_size;
2023
2024 usba_hcdi_ops->usba_hcdi_pipe_stop_intr_polling =
2025 ohci_hcdi_pipe_stop_intr_polling;
2026 usba_hcdi_ops->usba_hcdi_pipe_stop_isoc_polling =
2027 ohci_hcdi_pipe_stop_isoc_polling;
2028
2029 usba_hcdi_ops->usba_hcdi_get_current_frame_number =
2030 ohci_hcdi_get_current_frame_number;
2031 usba_hcdi_ops->usba_hcdi_get_max_isoc_pkts =
2032 ohci_hcdi_get_max_isoc_pkts;
2033 usba_hcdi_ops->usba_hcdi_console_input_init =
2034 ohci_hcdi_polled_input_init;
2035 usba_hcdi_ops->usba_hcdi_console_input_enter =
2036 ohci_hcdi_polled_input_enter;
2037 usba_hcdi_ops->usba_hcdi_console_read = ohci_hcdi_polled_read;
2038 usba_hcdi_ops->usba_hcdi_console_input_exit =
2039 ohci_hcdi_polled_input_exit;
2040 usba_hcdi_ops->usba_hcdi_console_input_fini =
2041 ohci_hcdi_polled_input_fini;
2042
2043 usba_hcdi_ops->usba_hcdi_console_output_init =
2044 ohci_hcdi_polled_output_init;
2045 usba_hcdi_ops->usba_hcdi_console_output_enter =
2046 ohci_hcdi_polled_output_enter;
2047 usba_hcdi_ops->usba_hcdi_console_write = ohci_hcdi_polled_write;
2048 usba_hcdi_ops->usba_hcdi_console_output_exit =
2049 ohci_hcdi_polled_output_exit;
2050 usba_hcdi_ops->usba_hcdi_console_output_fini =
2051 ohci_hcdi_polled_output_fini;
2052
2053 return (usba_hcdi_ops);
2054 }
2055
2056
2057 /*
2058 * Host Controller Driver (HCD) deinitialization functions
2059 */
2060
2061 /*
2062 * ohci_cleanup:
2063 *
2064 * Cleanup on attach failure or detach
2065 */
2066 static int
ohci_cleanup(ohci_state_t * ohcip)2067 ohci_cleanup(ohci_state_t *ohcip)
2068 {
2069 ohci_trans_wrapper_t *tw;
2070 ohci_pipe_private_t *pp;
2071 ohci_td_t *td;
2072 int i, state, rval;
2073 int flags = ohcip->ohci_flags;
2074
2075 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_cleanup:");
2076
2077 if (flags & OHCI_RHREG) {
2078 /* Unload the root hub driver */
2079 if (ohci_unload_root_hub_driver(ohcip) != USB_SUCCESS) {
2080
2081 return (DDI_FAILURE);
2082 }
2083 }
2084
2085 if (flags & OHCI_USBAREG) {
2086 /* Unregister this HCD instance with USBA */
2087 usba_hcdi_unregister(ohcip->ohci_dip);
2088 }
2089
2090 if (flags & OHCI_INTR) {
2091
2092 mutex_enter(&ohcip->ohci_int_mutex);
2093
2094 /* Disable all HC ED list processing */
2095 Set_OpReg(hcr_control,
2096 (Get_OpReg(hcr_control) & ~(HCR_CONTROL_CLE |
2097 HCR_CONTROL_BLE | HCR_CONTROL_PLE | HCR_CONTROL_IE)));
2098
2099 /* Disable all HC interrupts */
2100 Set_OpReg(hcr_intr_disable,
2101 (HCR_INTR_SO | HCR_INTR_WDH | HCR_INTR_RD | HCR_INTR_UE));
2102
2103 /* Wait for the next SOF */
2104 (void) ohci_wait_for_sof(ohcip);
2105
2106 /* Disable Master and SOF interrupts */
2107 Set_OpReg(hcr_intr_disable, (HCR_INTR_MIE | HCR_INTR_SOF));
2108
2109 /* Set the Host Controller Functional State to Reset */
2110 Set_OpReg(hcr_control, ((Get_OpReg(hcr_control) &
2111 (~HCR_CONTROL_HCFS)) | HCR_CONTROL_RESET));
2112
2113 mutex_exit(&ohcip->ohci_int_mutex);
2114 /* Wait for sometime */
2115 delay(drv_usectohz(OHCI_TIMEWAIT));
2116 mutex_enter(&ohcip->ohci_int_mutex);
2117
2118 /*
2119 * Workaround for ULI1575 chipset. Following OHCI Operational
2120 * Memory Registers are not cleared to their default value
2121 * on reset. Explicitly set the registers to default value.
2122 */
2123 if (ohcip->ohci_vendor_id == PCI_ULI1575_VENID &&
2124 ohcip->ohci_device_id == PCI_ULI1575_DEVID) {
2125 Set_OpReg(hcr_control, HCR_CONTROL_DEFAULT);
2126 Set_OpReg(hcr_intr_enable, HCR_INT_ENABLE_DEFAULT);
2127 Set_OpReg(hcr_HCCA, HCR_HCCA_DEFAULT);
2128 Set_OpReg(hcr_ctrl_head, HCR_CONTROL_HEAD_ED_DEFAULT);
2129 Set_OpReg(hcr_bulk_head, HCR_BULK_HEAD_ED_DEFAULT);
2130 Set_OpReg(hcr_frame_interval,
2131 HCR_FRAME_INTERVAL_DEFAULT);
2132 Set_OpReg(hcr_periodic_strt,
2133 HCR_PERIODIC_START_DEFAULT);
2134 }
2135
2136 mutex_exit(&ohcip->ohci_int_mutex);
2137
2138 ohci_rem_intrs(ohcip);
2139 }
2140
2141 /* Unmap the OHCI registers */
2142 if (ohcip->ohci_regs_handle) {
2143 /* Reset the host controller */
2144 Set_OpReg(hcr_cmd_status, HCR_STATUS_RESET);
2145
2146 ddi_regs_map_free(&ohcip->ohci_regs_handle);
2147 }
2148
2149 if (ohcip->ohci_config_handle) {
2150 pci_config_teardown(&ohcip->ohci_config_handle);
2151 }
2152
2153 /* Free all the buffers */
2154 if (ohcip->ohci_td_pool_addr && ohcip->ohci_td_pool_mem_handle) {
2155 for (i = 0; i < ohci_td_pool_size; i ++) {
2156 td = &ohcip->ohci_td_pool_addr[i];
2157 state = Get_TD(ohcip->ohci_td_pool_addr[i].hctd_state);
2158
2159 if ((state != HC_TD_FREE) && (state != HC_TD_DUMMY) &&
2160 (td->hctd_trans_wrapper)) {
2161
2162 mutex_enter(&ohcip->ohci_int_mutex);
2163
2164 tw = (ohci_trans_wrapper_t *)
2165 OHCI_LOOKUP_ID((uint32_t)
2166 Get_TD(td->hctd_trans_wrapper));
2167
2168 /* Obtain the pipe private structure */
2169 pp = tw->tw_pipe_private;
2170
2171 /* Stop the the transfer timer */
2172 ohci_stop_xfer_timer(ohcip, tw,
2173 OHCI_REMOVE_XFER_ALWAYS);
2174
2175 ohci_deallocate_tw_resources(ohcip, pp, tw);
2176
2177 mutex_exit(&ohcip->ohci_int_mutex);
2178 }
2179 }
2180
2181 /*
2182 * If OHCI_TD_POOL_BOUND flag is set, then unbind
2183 * the handle for TD pools.
2184 */
2185 if ((ohcip->ohci_dma_addr_bind_flag &
2186 OHCI_TD_POOL_BOUND) == OHCI_TD_POOL_BOUND) {
2187
2188 rval = ddi_dma_unbind_handle(
2189 ohcip->ohci_td_pool_dma_handle);
2190
2191 ASSERT(rval == DDI_SUCCESS);
2192 }
2193 ddi_dma_mem_free(&ohcip->ohci_td_pool_mem_handle);
2194 }
2195
2196 /* Free the TD pool */
2197 if (ohcip->ohci_td_pool_dma_handle) {
2198 ddi_dma_free_handle(&ohcip->ohci_td_pool_dma_handle);
2199 }
2200
2201 if (ohcip->ohci_ed_pool_addr && ohcip->ohci_ed_pool_mem_handle) {
2202 /*
2203 * If OHCI_ED_POOL_BOUND flag is set, then unbind
2204 * the handle for ED pools.
2205 */
2206 if ((ohcip->ohci_dma_addr_bind_flag &
2207 OHCI_ED_POOL_BOUND) == OHCI_ED_POOL_BOUND) {
2208
2209 rval = ddi_dma_unbind_handle(
2210 ohcip->ohci_ed_pool_dma_handle);
2211
2212 ASSERT(rval == DDI_SUCCESS);
2213 }
2214
2215 ddi_dma_mem_free(&ohcip->ohci_ed_pool_mem_handle);
2216 }
2217
2218 /* Free the ED pool */
2219 if (ohcip->ohci_ed_pool_dma_handle) {
2220 ddi_dma_free_handle(&ohcip->ohci_ed_pool_dma_handle);
2221 }
2222
2223 /* Free the HCCA area */
2224 if (ohcip->ohci_hccap && ohcip->ohci_hcca_mem_handle) {
2225 /*
2226 * If OHCI_HCCA_DMA_BOUND flag is set, then unbind
2227 * the handle for HCCA.
2228 */
2229 if ((ohcip->ohci_dma_addr_bind_flag &
2230 OHCI_HCCA_DMA_BOUND) == OHCI_HCCA_DMA_BOUND) {
2231
2232 rval = ddi_dma_unbind_handle(
2233 ohcip->ohci_hcca_dma_handle);
2234
2235 ASSERT(rval == DDI_SUCCESS);
2236 }
2237
2238 ddi_dma_mem_free(&ohcip->ohci_hcca_mem_handle);
2239 }
2240
2241 if (ohcip->ohci_hcca_dma_handle) {
2242 ddi_dma_free_handle(&ohcip->ohci_hcca_dma_handle);
2243 }
2244
2245 if (flags & OHCI_INTR) {
2246
2247 /* Destroy the mutex */
2248 mutex_destroy(&ohcip->ohci_int_mutex);
2249
2250 /* Destroy the SOF condition varibale */
2251 cv_destroy(&ohcip->ohci_SOF_cv);
2252
2253 /* Destroy the serialize opens and closes semaphore */
2254 sema_destroy(&ohcip->ohci_ocsem);
2255 }
2256
2257 /* clean up kstat structs */
2258 ohci_destroy_stats(ohcip);
2259
2260 /* Free ohci hcdi ops */
2261 if (ohcip->ohci_hcdi_ops) {
2262 usba_free_hcdi_ops(ohcip->ohci_hcdi_ops);
2263 }
2264
2265 if (flags & OHCI_ZALLOC) {
2266
2267 usb_free_log_hdl(ohcip->ohci_log_hdl);
2268
2269 /* Remove all properties that might have been created */
2270 ddi_prop_remove_all(ohcip->ohci_dip);
2271
2272 /* Free the soft state */
2273 ddi_soft_state_free(ohci_statep,
2274 ddi_get_instance(ohcip->ohci_dip));
2275 }
2276
2277 return (DDI_SUCCESS);
2278 }
2279
2280
2281 /*
2282 * ohci_rem_intrs:
2283 *
2284 * Unregister FIXED or MSI interrupts
2285 */
2286 static void
ohci_rem_intrs(ohci_state_t * ohcip)2287 ohci_rem_intrs(ohci_state_t *ohcip)
2288 {
2289 int i;
2290
2291 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2292 "ohci_rem_intrs: interrupt type 0x%x", ohcip->ohci_intr_type);
2293
2294 /* Disable all interrupts */
2295 if (ohcip->ohci_intr_cap & DDI_INTR_FLAG_BLOCK) {
2296 (void) ddi_intr_block_disable(ohcip->ohci_htable,
2297 ohcip->ohci_intr_cnt);
2298 } else {
2299 for (i = 0; i < ohcip->ohci_intr_cnt; i++) {
2300 (void) ddi_intr_disable(ohcip->ohci_htable[i]);
2301 }
2302 }
2303
2304 /* Call ddi_intr_remove_handler() */
2305 for (i = 0; i < ohcip->ohci_intr_cnt; i++) {
2306 (void) ddi_intr_remove_handler(ohcip->ohci_htable[i]);
2307 (void) ddi_intr_free(ohcip->ohci_htable[i]);
2308 }
2309
2310 kmem_free(ohcip->ohci_htable,
2311 ohcip->ohci_intr_cnt * sizeof (ddi_intr_handle_t));
2312 }
2313
2314
2315 /*
2316 * ohci_cpr_suspend
2317 */
2318 static int
ohci_cpr_suspend(ohci_state_t * ohcip)2319 ohci_cpr_suspend(ohci_state_t *ohcip)
2320 {
2321 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2322 "ohci_cpr_suspend:");
2323
2324 /* Call into the root hub and suspend it */
2325 if (usba_hubdi_detach(ohcip->ohci_dip, DDI_SUSPEND) != DDI_SUCCESS) {
2326
2327 return (DDI_FAILURE);
2328 }
2329
2330 /* Only root hub's intr pipe should be open at this time */
2331 mutex_enter(&ohcip->ohci_int_mutex);
2332
2333 if (ohcip->ohci_open_pipe_count > 1) {
2334
2335 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2336 "ohci_cpr_suspend: fails as open pipe count = %d",
2337 ohcip->ohci_open_pipe_count);
2338
2339 mutex_exit(&ohcip->ohci_int_mutex);
2340
2341 return (DDI_FAILURE);
2342 }
2343
2344 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2345 "ohci_cpr_suspend: Disable HC ED list processing");
2346
2347 /* Disable all HC ED list processing */
2348 Set_OpReg(hcr_control, (Get_OpReg(hcr_control) & ~(HCR_CONTROL_CLE |
2349 HCR_CONTROL_BLE | HCR_CONTROL_PLE | HCR_CONTROL_IE)));
2350
2351 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2352 "ohci_cpr_suspend: Disable HC interrupts");
2353
2354 /* Disable all HC interrupts */
2355 Set_OpReg(hcr_intr_disable, ~(HCR_INTR_MIE|HCR_INTR_SOF));
2356
2357 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2358 "ohci_cpr_suspend: Wait for the next SOF");
2359
2360 /* Wait for the next SOF */
2361 if (ohci_wait_for_sof(ohcip) != USB_SUCCESS) {
2362
2363 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2364 "ohci_cpr_suspend: ohci host controller suspend failed");
2365
2366 mutex_exit(&ohcip->ohci_int_mutex);
2367 return (DDI_FAILURE);
2368 }
2369
2370 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2371 "ohci_cpr_suspend: Disable Master interrupt");
2372
2373 /*
2374 * Disable Master interrupt so that ohci driver don't
2375 * get any ohci interrupts.
2376 */
2377 Set_OpReg(hcr_intr_disable, HCR_INTR_MIE);
2378
2379 /*
2380 * Suspend the ohci host controller
2381 * if usb keyboard is not connected.
2382 */
2383 if (ohcip->ohci_polled_kbd_count == 0 || force_ohci_off != 0) {
2384 Set_OpReg(hcr_control, HCR_CONTROL_SUSPD);
2385 }
2386
2387 /* Set host controller soft state to suspend */
2388 ohcip->ohci_hc_soft_state = OHCI_CTLR_SUSPEND_STATE;
2389
2390 mutex_exit(&ohcip->ohci_int_mutex);
2391
2392 return (DDI_SUCCESS);
2393 }
2394
2395
2396 /*
2397 * ohci_cpr_resume
2398 */
2399 static int
ohci_cpr_resume(ohci_state_t * ohcip)2400 ohci_cpr_resume(ohci_state_t *ohcip)
2401 {
2402 mutex_enter(&ohcip->ohci_int_mutex);
2403
2404 USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2405 "ohci_cpr_resume: Restart the controller");
2406
2407 /* Cleanup ohci specific information across cpr */
2408 ohci_cpr_cleanup(ohcip);
2409
2410 /* Restart the controller */
2411 if (ohci_init_ctlr(ohcip) != DDI_SUCCESS) {
2412
2413 USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2414 "ohci_cpr_resume: ohci host controller resume failed ");
2415
2416 mutex_exit(&ohcip->ohci_int_mutex);
2417
2418 return (DDI_FAILURE);
2419 }
2420
2421 mutex_exit(&ohcip->ohci_int_mutex);
2422
2423 /* Now resume the root hub */
2424 if (usba_hubdi_attach(ohcip->ohci_dip, DDI_RESUME) != DDI_SUCCESS) {
2425
2426 return (DDI_FAILURE);
2427 }
2428
2429 return (DDI_SUCCESS);
2430 }
2431
2432
2433 /*
2434 * HCDI entry points
2435 *
2436 * The Host Controller Driver Interfaces (HCDI) are the software interfaces
2437 * between the Universal Serial Bus Layer (USBA) and the Host Controller
2438 * Driver (HCD). The HCDI interfaces or entry points are subject to change.
2439 */
2440
2441 /*
2442 * ohci_hcdi_pipe_open:
2443 *
2444 * Member of HCD Ops structure and called during client specific pipe open
2445 * Add the pipe to the data structure representing the device and allocate
2446 * bandwidth for the pipe if it is a interrupt or isochronous endpoint.
2447 */
2448 static int
ohci_hcdi_pipe_open(usba_pipe_handle_data_t * ph,usb_flags_t flags)2449 ohci_hcdi_pipe_open(
2450 usba_pipe_handle_data_t *ph,
2451 usb_flags_t flags)
2452 {
2453 ohci_state_t *ohcip = ohci_obtain_state(
2454 ph->p_usba_device->usb_root_hub_dip);
2455 usb_ep_descr_t *epdt = &ph->p_ep;
2456 int rval, error = USB_SUCCESS;
2457 int kmflag = (flags & USB_FLAGS_SLEEP) ?
2458 KM_SLEEP : KM_NOSLEEP;
2459 uint_t node = 0;
2460 ohci_pipe_private_t *pp;
2461
2462 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2463 "ohci_hcdi_pipe_open: addr = 0x%x, ep%d",
2464 ph->p_usba_device->usb_addr,
2465 epdt->bEndpointAddress & USB_EP_NUM_MASK);
2466
2467 sema_p(&ohcip->ohci_ocsem);
2468
2469 mutex_enter(&ohcip->ohci_int_mutex);
2470 rval = ohci_state_is_operational(ohcip);
2471 mutex_exit(&ohcip->ohci_int_mutex);
2472
2473 if (rval != USB_SUCCESS) {
2474 sema_v(&ohcip->ohci_ocsem);
2475
2476 return (rval);
2477 }
2478
2479 /*
2480 * Check and handle root hub pipe open.
2481 */
2482 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
2483
2484 mutex_enter(&ohcip->ohci_int_mutex);
2485 error = ohci_handle_root_hub_pipe_open(ph, flags);
2486 mutex_exit(&ohcip->ohci_int_mutex);
2487 sema_v(&ohcip->ohci_ocsem);
2488
2489 return (error);
2490 }
2491
2492 /*
2493 * Opening of other pipes excluding root hub pipe are
2494 * handled below. Check whether pipe is already opened.
2495 */
2496 if (ph->p_hcd_private) {
2497 USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2498 "ohci_hcdi_pipe_open: Pipe is already opened");
2499
2500 sema_v(&ohcip->ohci_ocsem);
2501
2502 return (USB_FAILURE);
2503 }
2504
2505 /*
2506 * A portion of the bandwidth is reserved for the non-periodic
2507 * transfers, i.e control and bulk transfers in each of one
2508 * millisecond frame period & usually it will be 10% of frame
2509 * period. Hence there is no need to check for the available
2510 * bandwidth before adding the control or bulk endpoints.
2511 *
2512 * There is a need to check for the available bandwidth before
2513 * adding the periodic transfers, i.e interrupt & isochronous,
2514 * since all these periodic transfers are guaranteed transfers.
2515 * Usually 90% of the total frame time is reserved for periodic
2516 * transfers.
2517 */
2518 if (OHCI_PERIODIC_ENDPOINT(epdt)) {
2519
2520 mutex_enter(&ohcip->ohci_int_mutex);
2521 mutex_enter(&ph->p_mutex);
2522
2523 error = ohci_allocate_bandwidth(ohcip, ph, &node);
2524
2525 if (error != USB_SUCCESS) {
2526
2527 USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2528 "ohci_hcdi_pipe_open: Bandwidth allocation failed");
2529
2530 mutex_exit(&ph->p_mutex);
2531 mutex_exit(&ohcip->ohci_int_mutex);
2532 sema_v(&ohcip->ohci_ocsem);
2533
2534 return (error);
2535 }
2536
2537 mutex_exit(&ph->p_mutex);
2538 mutex_exit(&ohcip->ohci_int_mutex);
2539 }
2540
2541 /* Create the HCD pipe private structure */
2542 pp = kmem_zalloc(sizeof (ohci_pipe_private_t), kmflag);
2543
2544 /*
2545 * Return failure if ohci pipe private
2546 * structure allocation fails.
2547 */
2548 if (pp == NULL) {
2549
2550 mutex_enter(&ohcip->ohci_int_mutex);
2551
2552 /* Deallocate bandwidth */
2553 if (OHCI_PERIODIC_ENDPOINT(epdt)) {
2554
2555 mutex_enter(&ph->p_mutex);
2556 ohci_deallocate_bandwidth(ohcip, ph);
2557 mutex_exit(&ph->p_mutex);
2558 }
2559
2560 mutex_exit(&ohcip->ohci_int_mutex);
2561 sema_v(&ohcip->ohci_ocsem);
2562
2563 return (USB_NO_RESOURCES);
2564 }
2565
2566 mutex_enter(&ohcip->ohci_int_mutex);
2567
2568 /* Store the node in the interrupt lattice */
2569 pp->pp_node = node;
2570
2571 /* Create prototype for xfer completion condition variable */
2572 cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL);
2573
2574 /* Set the state of pipe as idle */
2575 pp->pp_state = OHCI_PIPE_STATE_IDLE;
2576
2577 /* Store a pointer to the pipe handle */
2578 pp->pp_pipe_handle = ph;
2579
2580 mutex_enter(&ph->p_mutex);
2581
2582 /* Store the pointer in the pipe handle */
2583 ph->p_hcd_private = (usb_opaque_t)pp;
2584
2585 /* Store a copy of the pipe policy */
2586 bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t));
2587
2588 mutex_exit(&ph->p_mutex);
2589
2590 /* Allocate the host controller endpoint descriptor */
2591 pp->pp_ept = ohci_alloc_hc_ed(ohcip, ph);
2592
2593 if (pp->pp_ept == NULL) {
2594 USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2595 "ohci_hcdi_pipe_open: ED allocation failed");
2596
2597 mutex_enter(&ph->p_mutex);
2598
2599 /* Deallocate bandwidth */
2600 if (OHCI_PERIODIC_ENDPOINT(epdt)) {
2601
2602 ohci_deallocate_bandwidth(ohcip, ph);
2603 }
2604
2605 /* Destroy the xfer completion condition varibale */
2606 cv_destroy(&pp->pp_xfer_cmpl_cv);
2607
2608 /*
2609 * Deallocate the hcd private portion
2610 * of the pipe handle.
2611 */
2612 kmem_free(ph->p_hcd_private, sizeof (ohci_pipe_private_t));
2613
2614 /*
2615 * Set the private structure in the
2616 * pipe handle equal to NULL.
2617 */
2618 ph->p_hcd_private = NULL;
2619 mutex_exit(&ph->p_mutex);
2620
2621 mutex_exit(&ohcip->ohci_int_mutex);
2622 sema_v(&ohcip->ohci_ocsem);
2623
2624 return (USB_NO_RESOURCES);
2625 }
2626
2627 /* Restore the data toggle information */
2628 ohci_restore_data_toggle(ohcip, ph);
2629
2630 /*
2631 * Insert the endpoint onto the host controller's
2632 * appropriate endpoint list. The host controller
2633 * will not schedule this endpoint and will not have
2634 * any TD's to process.
2635 */
2636 ohci_insert_ed(ohcip, ph);
2637
2638 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2639 "ohci_hcdi_pipe_open: ph = 0x%p", (void *)ph);
2640
2641 ohcip->ohci_open_pipe_count++;
2642
2643 mutex_exit(&ohcip->ohci_int_mutex);
2644
2645 sema_v(&ohcip->ohci_ocsem);
2646
2647 return (USB_SUCCESS);
2648 }
2649
2650
2651 /*
2652 * ohci_hcdi_pipe_close:
2653 *
2654 * Member of HCD Ops structure and called during the client specific pipe
2655 * close. Remove the pipe and the data structure representing the device.
2656 * Deallocate bandwidth for the pipe if it is a interrupt or isochronous
2657 * endpoint.
2658 */
2659 /* ARGSUSED */
2660 static int
ohci_hcdi_pipe_close(usba_pipe_handle_data_t * ph,usb_flags_t flags)2661 ohci_hcdi_pipe_close(
2662 usba_pipe_handle_data_t *ph,
2663 usb_flags_t flags)
2664 {
2665 ohci_state_t *ohcip = ohci_obtain_state(
2666 ph->p_usba_device->usb_root_hub_dip);
2667 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2668 usb_ep_descr_t *eptd = &ph->p_ep;
2669 int error = USB_SUCCESS;
2670
2671 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2672 "ohci_hcdi_pipe_close: addr = 0x%x, ep%d",
2673 ph->p_usba_device->usb_addr,
2674 eptd->bEndpointAddress & USB_EP_NUM_MASK);
2675
2676 sema_p(&ohcip->ohci_ocsem);
2677
2678 /* Check and handle root hub pipe close */
2679 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
2680
2681 mutex_enter(&ohcip->ohci_int_mutex);
2682 error = ohci_handle_root_hub_pipe_close(ph);
2683 mutex_exit(&ohcip->ohci_int_mutex);
2684 sema_v(&ohcip->ohci_ocsem);
2685
2686 return (error);
2687 }
2688
2689 ASSERT(ph->p_hcd_private != NULL);
2690
2691 mutex_enter(&ohcip->ohci_int_mutex);
2692
2693 /* Set pipe state to pipe close */
2694 pp->pp_state = OHCI_PIPE_STATE_CLOSE;
2695
2696 ohci_pipe_cleanup(ohcip, ph);
2697
2698 /*
2699 * Remove the endoint descriptor from Host
2700 * Controller's appropriate endpoint list.
2701 */
2702 ohci_remove_ed(ohcip, pp);
2703
2704 /* Deallocate bandwidth */
2705 if (OHCI_PERIODIC_ENDPOINT(eptd)) {
2706
2707 mutex_enter(&ph->p_mutex);
2708 ohci_deallocate_bandwidth(ohcip, ph);
2709 mutex_exit(&ph->p_mutex);
2710 }
2711
2712 mutex_enter(&ph->p_mutex);
2713
2714 /* Destroy the xfer completion condition varibale */
2715 cv_destroy(&pp->pp_xfer_cmpl_cv);
2716
2717 /*
2718 * Deallocate the hcd private portion
2719 * of the pipe handle.
2720 */
2721 kmem_free(ph->p_hcd_private, sizeof (ohci_pipe_private_t));
2722 ph->p_hcd_private = NULL;
2723
2724 mutex_exit(&ph->p_mutex);
2725
2726 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2727 "ohci_hcdi_pipe_close: ph = 0x%p", (void *)ph);
2728
2729 ohcip->ohci_open_pipe_count--;
2730
2731 mutex_exit(&ohcip->ohci_int_mutex);
2732 sema_v(&ohcip->ohci_ocsem);
2733
2734 return (error);
2735 }
2736
2737
2738 /*
2739 * ohci_hcdi_pipe_reset:
2740 */
2741 /* ARGSUSED */
2742 static int
ohci_hcdi_pipe_reset(usba_pipe_handle_data_t * ph,usb_flags_t usb_flags)2743 ohci_hcdi_pipe_reset(
2744 usba_pipe_handle_data_t *ph,
2745 usb_flags_t usb_flags)
2746 {
2747 ohci_state_t *ohcip = ohci_obtain_state(
2748 ph->p_usba_device->usb_root_hub_dip);
2749 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2750 int error = USB_SUCCESS;
2751
2752 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2753 "ohci_hcdi_pipe_reset: ph = 0x%p ", (void *)ph);
2754
2755 /*
2756 * Check and handle root hub pipe reset.
2757 */
2758 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
2759
2760 error = ohci_handle_root_hub_pipe_reset(ph, usb_flags);
2761 return (error);
2762 }
2763
2764 mutex_enter(&ohcip->ohci_int_mutex);
2765
2766 /* Set pipe state to pipe reset */
2767 pp->pp_state = OHCI_PIPE_STATE_RESET;
2768
2769 ohci_pipe_cleanup(ohcip, ph);
2770
2771 mutex_exit(&ohcip->ohci_int_mutex);
2772
2773 return (error);
2774 }
2775
2776 /*
2777 * ohci_hcdi_pipe_reset_data_toggle:
2778 */
2779 void
ohci_hcdi_pipe_reset_data_toggle(usba_pipe_handle_data_t * ph)2780 ohci_hcdi_pipe_reset_data_toggle(
2781 usba_pipe_handle_data_t *ph)
2782 {
2783 ohci_state_t *ohcip = ohci_obtain_state(
2784 ph->p_usba_device->usb_root_hub_dip);
2785 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2786
2787 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2788 "ohci_hcdi_pipe_reset_data_toggle:");
2789
2790 mutex_enter(&ohcip->ohci_int_mutex);
2791
2792 mutex_enter(&ph->p_mutex);
2793 usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
2794 DATA0);
2795 mutex_exit(&ph->p_mutex);
2796
2797 Set_ED(pp->pp_ept->hced_headp,
2798 Get_ED(pp->pp_ept->hced_headp) & (~HC_EPT_Carry));
2799 mutex_exit(&ohcip->ohci_int_mutex);
2800
2801 }
2802
2803 /*
2804 * ohci_hcdi_pipe_ctrl_xfer:
2805 */
2806 static int
ohci_hcdi_pipe_ctrl_xfer(usba_pipe_handle_data_t * ph,usb_ctrl_req_t * ctrl_reqp,usb_flags_t usb_flags)2807 ohci_hcdi_pipe_ctrl_xfer(
2808 usba_pipe_handle_data_t *ph,
2809 usb_ctrl_req_t *ctrl_reqp,
2810 usb_flags_t usb_flags)
2811 {
2812 ohci_state_t *ohcip = ohci_obtain_state(
2813 ph->p_usba_device->usb_root_hub_dip);
2814 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2815 int rval;
2816 int error = USB_SUCCESS;
2817 ohci_trans_wrapper_t *tw;
2818
2819 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2820 "ohci_hcdi_pipe_ctrl_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
2821 (void *)ph, (void *)ctrl_reqp, usb_flags);
2822
2823 mutex_enter(&ohcip->ohci_int_mutex);
2824 rval = ohci_state_is_operational(ohcip);
2825 mutex_exit(&ohcip->ohci_int_mutex);
2826
2827 if (rval != USB_SUCCESS) {
2828
2829 return (rval);
2830 }
2831
2832 /*
2833 * Check and handle root hub control request.
2834 */
2835 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
2836
2837 error = ohci_handle_root_hub_request(ohcip, ph, ctrl_reqp);
2838
2839 return (error);
2840 }
2841
2842 mutex_enter(&ohcip->ohci_int_mutex);
2843
2844 /*
2845 * Check whether pipe is in halted state.
2846 */
2847 if (pp->pp_state == OHCI_PIPE_STATE_ERROR) {
2848
2849 USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2850 "ohci_hcdi_pipe_ctrl_xfer:"
2851 "Pipe is in error state, need pipe reset to continue");
2852
2853 mutex_exit(&ohcip->ohci_int_mutex);
2854
2855 return (USB_FAILURE);
2856 }
2857
2858 /* Allocate a transfer wrapper */
2859 if ((tw = ohci_allocate_ctrl_resources(ohcip, pp, ctrl_reqp,
2860 usb_flags)) == NULL) {
2861
2862 error = USB_NO_RESOURCES;
2863 } else {
2864 /* Insert the td's on the endpoint */
2865 ohci_insert_ctrl_req(ohcip, ph, ctrl_reqp, tw, usb_flags);
2866 }
2867
2868 mutex_exit(&ohcip->ohci_int_mutex);
2869
2870 return (error);
2871 }
2872
2873
2874 /*
2875 * ohci_hcdi_bulk_transfer_size:
2876 *
2877 * Return maximum bulk transfer size
2878 */
2879
2880 /* ARGSUSED */
2881 static int
ohci_hcdi_bulk_transfer_size(usba_device_t * usba_device,size_t * size)2882 ohci_hcdi_bulk_transfer_size(
2883 usba_device_t *usba_device,
2884 size_t *size)
2885 {
2886 ohci_state_t *ohcip = ohci_obtain_state(
2887 usba_device->usb_root_hub_dip);
2888 int rval;
2889
2890 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2891 "ohci_hcdi_bulk_transfer_size:");
2892
2893 mutex_enter(&ohcip->ohci_int_mutex);
2894 rval = ohci_state_is_operational(ohcip);
2895 mutex_exit(&ohcip->ohci_int_mutex);
2896
2897 if (rval != USB_SUCCESS) {
2898
2899 return (rval);
2900 }
2901
2902 *size = OHCI_MAX_BULK_XFER_SIZE;
2903
2904 return (USB_SUCCESS);
2905 }
2906
2907
2908 /*
2909 * ohci_hcdi_pipe_bulk_xfer:
2910 */
2911 static int
ohci_hcdi_pipe_bulk_xfer(usba_pipe_handle_data_t * ph,usb_bulk_req_t * bulk_reqp,usb_flags_t usb_flags)2912 ohci_hcdi_pipe_bulk_xfer(
2913 usba_pipe_handle_data_t *ph,
2914 usb_bulk_req_t *bulk_reqp,
2915 usb_flags_t usb_flags)
2916 {
2917 ohci_state_t *ohcip = ohci_obtain_state(
2918 ph->p_usba_device->usb_root_hub_dip);
2919 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2920 int rval, error = USB_SUCCESS;
2921 ohci_trans_wrapper_t *tw;
2922
2923 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2924 "ohci_hcdi_pipe_bulk_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
2925 (void *)ph, (void *)bulk_reqp, usb_flags);
2926
2927 mutex_enter(&ohcip->ohci_int_mutex);
2928 rval = ohci_state_is_operational(ohcip);
2929
2930 if (rval != USB_SUCCESS) {
2931 mutex_exit(&ohcip->ohci_int_mutex);
2932
2933 return (rval);
2934 }
2935
2936 /*
2937 * Check whether pipe is in halted state.
2938 */
2939 if (pp->pp_state == OHCI_PIPE_STATE_ERROR) {
2940
2941 USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2942 "ohci_hcdi_pipe_bulk_xfer:"
2943 "Pipe is in error state, need pipe reset to continue");
2944
2945 mutex_exit(&ohcip->ohci_int_mutex);
2946
2947 return (USB_FAILURE);
2948 }
2949
2950 /* Allocate a transfer wrapper */
2951 if ((tw = ohci_allocate_bulk_resources(ohcip, pp, bulk_reqp,
2952 usb_flags)) == NULL) {
2953
2954 error = USB_NO_RESOURCES;
2955 } else {
2956 /* Add the TD into the Host Controller's bulk list */
2957 ohci_insert_bulk_req(ohcip, ph, bulk_reqp, tw, usb_flags);
2958 }
2959
2960 mutex_exit(&ohcip->ohci_int_mutex);
2961
2962 return (error);
2963 }
2964
2965
2966 /*
2967 * ohci_hcdi_pipe_intr_xfer:
2968 */
2969 static int
ohci_hcdi_pipe_intr_xfer(usba_pipe_handle_data_t * ph,usb_intr_req_t * intr_reqp,usb_flags_t usb_flags)2970 ohci_hcdi_pipe_intr_xfer(
2971 usba_pipe_handle_data_t *ph,
2972 usb_intr_req_t *intr_reqp,
2973 usb_flags_t usb_flags)
2974 {
2975 ohci_state_t *ohcip = ohci_obtain_state(
2976 ph->p_usba_device->usb_root_hub_dip);
2977 int pipe_dir, rval, error = USB_SUCCESS;
2978 ohci_trans_wrapper_t *tw;
2979
2980 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2981 "ohci_hcdi_pipe_intr_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
2982 (void *)ph, (void *)intr_reqp, usb_flags);
2983
2984 mutex_enter(&ohcip->ohci_int_mutex);
2985 rval = ohci_state_is_operational(ohcip);
2986
2987 if (rval != USB_SUCCESS) {
2988 mutex_exit(&ohcip->ohci_int_mutex);
2989
2990 return (rval);
2991 }
2992
2993 /* Get the pipe direction */
2994 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
2995
2996 if (pipe_dir == USB_EP_DIR_IN) {
2997 error = ohci_start_periodic_pipe_polling(ohcip, ph,
2998 (usb_opaque_t)intr_reqp, usb_flags);
2999 } else {
3000 /* Allocate transaction resources */
3001 if ((tw = ohci_allocate_intr_resources(ohcip, ph,
3002 intr_reqp, usb_flags)) == NULL) {
3003 error = USB_NO_RESOURCES;
3004 } else {
3005 ohci_insert_intr_req(ohcip,
3006 (ohci_pipe_private_t *)ph->p_hcd_private,
3007 tw, usb_flags);
3008 }
3009 }
3010
3011 mutex_exit(&ohcip->ohci_int_mutex);
3012
3013 return (error);
3014 }
3015
3016
3017 /*
3018 * ohci_hcdi_pipe_stop_intr_polling()
3019 */
3020 static int
ohci_hcdi_pipe_stop_intr_polling(usba_pipe_handle_data_t * ph,usb_flags_t flags)3021 ohci_hcdi_pipe_stop_intr_polling(
3022 usba_pipe_handle_data_t *ph,
3023 usb_flags_t flags)
3024 {
3025 ohci_state_t *ohcip = ohci_obtain_state(
3026 ph->p_usba_device->usb_root_hub_dip);
3027 int error = USB_SUCCESS;
3028
3029 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3030 "ohci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x",
3031 (void *)ph, flags);
3032
3033 mutex_enter(&ohcip->ohci_int_mutex);
3034
3035 error = ohci_stop_periodic_pipe_polling(ohcip, ph, flags);
3036
3037 mutex_exit(&ohcip->ohci_int_mutex);
3038
3039 return (error);
3040 }
3041
3042
3043 /*
3044 * ohci_hcdi_get_current_frame_number:
3045 *
3046 * Get the current usb frame number.
3047 * Return whether the request is handled successfully.
3048 */
3049 static int
ohci_hcdi_get_current_frame_number(usba_device_t * usba_device,usb_frame_number_t * frame_number)3050 ohci_hcdi_get_current_frame_number(
3051 usba_device_t *usba_device,
3052 usb_frame_number_t *frame_number)
3053 {
3054 ohci_state_t *ohcip = ohci_obtain_state(
3055 usba_device->usb_root_hub_dip);
3056 int rval;
3057
3058 ohcip = ohci_obtain_state(usba_device->usb_root_hub_dip);
3059
3060 mutex_enter(&ohcip->ohci_int_mutex);
3061 rval = ohci_state_is_operational(ohcip);
3062
3063 if (rval != USB_SUCCESS) {
3064 mutex_exit(&ohcip->ohci_int_mutex);
3065
3066 return (rval);
3067 }
3068
3069 *frame_number = ohci_get_current_frame_number(ohcip);
3070
3071 mutex_exit(&ohcip->ohci_int_mutex);
3072
3073 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3074 "ohci_hcdi_get_current_frame_number:"
3075 "Current frame number 0x%llx", (unsigned long long)(*frame_number));
3076
3077 return (rval);
3078 }
3079
3080
3081 /*
3082 * ohci_hcdi_get_max_isoc_pkts:
3083 *
3084 * Get maximum isochronous packets per usb isochronous request.
3085 * Return whether the request is handled successfully.
3086 */
3087 static int
ohci_hcdi_get_max_isoc_pkts(usba_device_t * usba_device,uint_t * max_isoc_pkts_per_request)3088 ohci_hcdi_get_max_isoc_pkts(
3089 usba_device_t *usba_device,
3090 uint_t *max_isoc_pkts_per_request)
3091 {
3092 ohci_state_t *ohcip = ohci_obtain_state(
3093 usba_device->usb_root_hub_dip);
3094 int rval;
3095
3096 mutex_enter(&ohcip->ohci_int_mutex);
3097 rval = ohci_state_is_operational(ohcip);
3098 mutex_exit(&ohcip->ohci_int_mutex);
3099
3100 if (rval != USB_SUCCESS) {
3101
3102 return (rval);
3103 }
3104
3105 *max_isoc_pkts_per_request = OHCI_MAX_ISOC_PKTS_PER_XFER;
3106
3107 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3108 "ohci_hcdi_get_max_isoc_pkts: maximum isochronous"
3109 "packets per usb isochronous request = 0x%x",
3110 *max_isoc_pkts_per_request);
3111
3112 return (rval);
3113 }
3114
3115
3116 /*
3117 * ohci_hcdi_pipe_isoc_xfer:
3118 */
3119 static int
ohci_hcdi_pipe_isoc_xfer(usba_pipe_handle_data_t * ph,usb_isoc_req_t * isoc_reqp,usb_flags_t usb_flags)3120 ohci_hcdi_pipe_isoc_xfer(
3121 usba_pipe_handle_data_t *ph,
3122 usb_isoc_req_t *isoc_reqp,
3123 usb_flags_t usb_flags)
3124 {
3125 ohci_state_t *ohcip = ohci_obtain_state(
3126 ph->p_usba_device->usb_root_hub_dip);
3127 int error = USB_SUCCESS;
3128 int pipe_dir, rval;
3129 ohci_trans_wrapper_t *tw;
3130
3131 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3132 "ohci_hcdi_pipe_isoc_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
3133 (void *)ph, (void *)isoc_reqp, usb_flags);
3134
3135 mutex_enter(&ohcip->ohci_int_mutex);
3136 rval = ohci_state_is_operational(ohcip);
3137
3138 if (rval != USB_SUCCESS) {
3139 mutex_exit(&ohcip->ohci_int_mutex);
3140
3141 return (rval);
3142 }
3143
3144 /* Get the isochronous pipe direction */
3145 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
3146
3147 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3148 "ohci_hcdi_pipe_isoc_xfer: isoc_reqp = 0x%p, uf = 0x%x",
3149 (void *)isoc_reqp, usb_flags);
3150
3151 if (pipe_dir == USB_EP_DIR_IN) {
3152 error = ohci_start_periodic_pipe_polling(ohcip, ph,
3153 (usb_opaque_t)isoc_reqp, usb_flags);
3154 } else {
3155 /* Allocate transaction resources */
3156 if ((tw = ohci_allocate_isoc_resources(ohcip, ph,
3157 isoc_reqp, usb_flags)) == NULL) {
3158 error = USB_NO_RESOURCES;
3159 } else {
3160 error = ohci_insert_isoc_req(ohcip,
3161 (ohci_pipe_private_t *)ph->p_hcd_private,
3162 tw, usb_flags);
3163 }
3164 }
3165
3166 mutex_exit(&ohcip->ohci_int_mutex);
3167
3168 return (error);
3169 }
3170
3171
3172 /*
3173 * ohci_hcdi_pipe_stop_isoc_polling()
3174 */
3175 static int
ohci_hcdi_pipe_stop_isoc_polling(usba_pipe_handle_data_t * ph,usb_flags_t flags)3176 ohci_hcdi_pipe_stop_isoc_polling(
3177 usba_pipe_handle_data_t *ph,
3178 usb_flags_t flags)
3179 {
3180 ohci_state_t *ohcip = ohci_obtain_state(
3181 ph->p_usba_device->usb_root_hub_dip);
3182 int rval, error = USB_SUCCESS;
3183
3184 USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3185 "ohci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x",
3186 (void *)ph, flags);
3187
3188 mutex_enter(&ohcip->ohci_int_mutex);
3189 rval = ohci_state_is_operational(ohcip);
3190
3191 if (rval != USB_SUCCESS) {
3192 mutex_exit(&ohcip->ohci_int_mutex);
3193 return (rval);
3194 }
3195
3196 error = ohci_stop_periodic_pipe_polling(ohcip, ph, flags);
3197
3198 mutex_exit(&ohcip->ohci_int_mutex);
3199 return (error);
3200 }
3201
3202
3203 /*
3204 * Bandwidth Allocation functions
3205 */
3206
3207 /*
3208 * ohci_allocate_bandwidth:
3209 *
3210 * Figure out whether or not this interval may be supported. Return the index
3211 * into the lattice if it can be supported. Return allocation failure if it
3212 * can not be supported.
3213 *
3214 * The lattice structure looks like this with the bottom leaf actually
3215 * being an array. There is a total of 63 nodes in this tree. The lattice tree
3216 * itself is 0 based, while the bottom leaf array is 0 based. The 0 bucket in
3217 * the bottom leaf array is used to store the smalled allocated bandwidth of all
3218 * the leaves.
3219 *
3220 * 0
3221 * 1 2
3222 * 3 4 5 6
3223 * ...
3224 * (32 33 ... 62 63) <-- last row does not exist in lattice, but an array
3225 * 0 1 2 3 ... 30 31
3226 *
3227 * We keep track of the bandwidth that each leaf uses. First we search for the
3228 * first leaf with the smallest used bandwidth. Based on that leaf we find the
3229 * parent node of that leaf based on the interval time.
3230 *
3231 * From the parent node, we find all the leafs of that subtree and update the
3232 * additional bandwidth needed. In order to balance the load the leaves are not
3233 * executed directly from left to right, but scattered. For a better picture
3234 * refer to Section 3.3.2 in the OpenHCI 1.0 spec, there should be a figure
3235 * showing the Interrupt ED Structure.
3236 */
3237 static int
ohci_allocate_bandwidth(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph,uint_t * node)3238 ohci_allocate_bandwidth(
3239 ohci_state_t *ohcip,
3240 usba_pipe_handle_data_t *ph,
3241 uint_t *node)
3242 {
3243 int interval, error, i;
3244 uint_t min, min_index, height;
3245 uint_t leftmost, list, bandwidth;
3246 usb_ep_descr_t *endpoint = &ph->p_ep;
3247
3248 /* This routine is protected by the ohci_int_mutex */
3249 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3250
3251 /*
3252 * Calculate the length in bytes of a transaction on this
3253 * periodic endpoint.
3254 */
3255 mutex_enter(&ph->p_usba_device->usb_mutex);
3256 error = ohci_compute_total_bandwidth(
3257 endpoint, ph->p_usba_device->usb_port_status, &bandwidth);
3258 mutex_exit(&ph->p_usba_device->usb_mutex);
3259
3260 /*
3261 * If length is zero, then, it means endpoint maximum packet
3262 * supported is zero. In that case, return failure without
3263 * allocating any bandwidth.
3264 */
3265 if (error != USB_SUCCESS) {
3266 USB_DPRINTF_L2(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3267 "ohci_allocate_bandwidth: Periodic endpoint with "
3268 "zero endpoint maximum packet size is not supported");
3269
3270 return (USB_NOT_SUPPORTED);
3271 }
3272
3273 /*
3274 * If the length in bytes plus the allocated bandwidth exceeds
3275 * the maximum, return bandwidth allocation failure.
3276 */
3277 if ((ohcip->ohci_periodic_minimum_bandwidth + bandwidth) >
3278 (MAX_PERIODIC_BANDWIDTH)) {
3279
3280 USB_DPRINTF_L2(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3281 "ohci_allocate_bandwidth: Reached maximum "
3282 "bandwidth value and cannot allocate bandwidth "
3283 "for a given periodic endpoint");
3284
3285 return (USB_NO_BANDWIDTH);
3286 }
3287
3288 /* Adjust polling interval to be a power of 2 */
3289 mutex_enter(&ph->p_usba_device->usb_mutex);
3290 interval = ohci_adjust_polling_interval(ohcip,
3291 endpoint, ph->p_usba_device->usb_port_status);
3292 mutex_exit(&ph->p_usba_device->usb_mutex);
3293
3294 /*
3295 * If this interval can't be supported,
3296 * return allocation failure.
3297 */
3298 if (interval == USB_FAILURE) {
3299
3300 return (USB_FAILURE);
3301 }
3302
3303 USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3304 "The new interval is %d", interval);
3305
3306 /* Find the leaf with the smallest allocated bandwidth */
3307 min_index = 0;
3308 min = ohcip->ohci_periodic_bandwidth[0];
3309
3310 for (i = 1; i < NUM_INTR_ED_LISTS; i++) {
3311 if (ohcip->ohci_periodic_bandwidth[i] < min) {
3312 min_index = i;
3313 min = ohcip->ohci_periodic_bandwidth[i];
3314 }
3315 }
3316
3317 USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3318 "The leaf %d for minimal bandwidth %d", min_index, min);
3319
3320 /* Adjust min for the lattice */
3321 min_index = min_index + NUM_INTR_ED_LISTS - 1;
3322
3323 /*
3324 * Find the index into the lattice given the
3325 * leaf with the smallest allocated bandwidth.
3326 */
3327 height = ohci_lattice_height(interval);
3328
3329 USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3330 "The height is %d", height);
3331
3332 *node = min_index;
3333
3334 for (i = 0; i < height; i++) {
3335 *node = ohci_lattice_parent(*node);
3336 }
3337
3338 USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3339 "Real node is %d", *node);
3340
3341 /*
3342 * Find the leftmost leaf in the subtree
3343 * specified by the node.
3344 */
3345 leftmost = ohci_leftmost_leaf(*node, height);
3346
3347 USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3348 "Leftmost %d", leftmost);
3349
3350 for (i = 0; i < (NUM_INTR_ED_LISTS/interval); i++) {
3351 list = ohci_hcca_leaf_index(leftmost + i);
3352 if ((ohcip->ohci_periodic_bandwidth[list] +
3353 bandwidth) > MAX_PERIODIC_BANDWIDTH) {
3354
3355 USB_DPRINTF_L2(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3356 "ohci_allocate_bandwidth: Reached maximum "
3357 "bandwidth value and cannot allocate bandwidth "
3358 "for periodic endpoint");
3359
3360 return (USB_NO_BANDWIDTH);
3361 }
3362 }
3363
3364 /*
3365 * All the leaves for this node must be updated with the bandwidth.
3366 */
3367 for (i = 0; i < (NUM_INTR_ED_LISTS/interval); i++) {
3368 list = ohci_hcca_leaf_index(leftmost + i);
3369 ohcip->ohci_periodic_bandwidth[list] += bandwidth;
3370 }
3371
3372 /* Find the leaf with the smallest allocated bandwidth */
3373 min_index = 0;
3374 min = ohcip->ohci_periodic_bandwidth[0];
3375
3376 for (i = 1; i < NUM_INTR_ED_LISTS; i++) {
3377 if (ohcip->ohci_periodic_bandwidth[i] < min) {
3378 min_index = i;
3379 min = ohcip->ohci_periodic_bandwidth[i];
3380 }
3381 }
3382
3383 /* Save the minimum for later use */
3384 ohcip->ohci_periodic_minimum_bandwidth = min;
3385
3386 return (USB_SUCCESS);
3387 }
3388
3389
3390 /*
3391 * ohci_deallocate_bandwidth:
3392 *
3393 * Deallocate bandwidth for the given node in the lattice and the length
3394 * of transfer.
3395 */
3396 static void
ohci_deallocate_bandwidth(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)3397 ohci_deallocate_bandwidth(
3398 ohci_state_t *ohcip,
3399 usba_pipe_handle_data_t *ph)
3400 {
3401 uint_t min, node, bandwidth;
3402 uint_t height, leftmost, list;
3403 int i, interval;
3404 usb_ep_descr_t *endpoint = &ph->p_ep;
3405 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
3406
3407 /* This routine is protected by the ohci_int_mutex */
3408 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3409
3410 /* Obtain the length */
3411 mutex_enter(&ph->p_usba_device->usb_mutex);
3412 (void) ohci_compute_total_bandwidth(
3413 endpoint, ph->p_usba_device->usb_port_status, &bandwidth);
3414 mutex_exit(&ph->p_usba_device->usb_mutex);
3415
3416 /* Obtain the node */
3417 node = pp->pp_node;
3418
3419 /* Adjust polling interval to be a power of 2 */
3420 mutex_enter(&ph->p_usba_device->usb_mutex);
3421 interval = ohci_adjust_polling_interval(ohcip,
3422 endpoint, ph->p_usba_device->usb_port_status);
3423 mutex_exit(&ph->p_usba_device->usb_mutex);
3424
3425 /* Find the height in the tree */
3426 height = ohci_lattice_height(interval);
3427
3428 /*
3429 * Find the leftmost leaf in the subtree specified by the node
3430 */
3431 leftmost = ohci_leftmost_leaf(node, height);
3432
3433 /* Delete the bandwith from the appropriate lists */
3434 for (i = 0; i < (NUM_INTR_ED_LISTS/interval); i++) {
3435 list = ohci_hcca_leaf_index(leftmost + i);
3436 ohcip->ohci_periodic_bandwidth[list] -= bandwidth;
3437 }
3438
3439 min = ohcip->ohci_periodic_bandwidth[0];
3440
3441 /* Recompute the minimum */
3442 for (i = 1; i < NUM_INTR_ED_LISTS; i++) {
3443 if (ohcip->ohci_periodic_bandwidth[i] < min) {
3444 min = ohcip->ohci_periodic_bandwidth[i];
3445 }
3446 }
3447
3448 /* Save the minimum for later use */
3449 ohcip->ohci_periodic_minimum_bandwidth = min;
3450 }
3451
3452
3453 /*
3454 * ohci_compute_total_bandwidth:
3455 *
3456 * Given a periodic endpoint (interrupt or isochronous) determine the total
3457 * bandwidth for one transaction. The OpenHCI host controller traverses the
3458 * endpoint descriptor lists on a first-come-first-serve basis. When the HC
3459 * services an endpoint, only a single transaction attempt is made. The HC
3460 * moves to the next Endpoint Descriptor after the first transaction attempt
3461 * rather than finishing the entire Transfer Descriptor. Therefore, when a
3462 * Transfer Descriptor is inserted into the lattice, we will only count the
3463 * number of bytes for one transaction.
3464 *
3465 * The following are the formulas used for calculating bandwidth in terms
3466 * bytes and it is for the single USB full speed and low speed transaction
3467 * respectively. The protocol overheads will be different for each of type
3468 * of USB transfer and all these formulas & protocol overheads are derived
3469 * from the 5.9.3 section of USB Specification & with the help of Bandwidth
3470 * Analysis white paper which is posted on the USB developer forum.
3471 *
3472 * Full-Speed:
3473 * Protocol overhead + ((MaxPacketSize * 7)/6 ) + Host_Delay
3474 *
3475 * Low-Speed:
3476 * Protocol overhead + Hub LS overhead +
3477 * (Low-Speed clock * ((MaxPacketSize * 7)/6 )) + Host_Delay
3478 */
3479 static int
ohci_compute_total_bandwidth(usb_ep_descr_t * endpoint,usb_port_status_t port_status,uint_t * bandwidth)3480 ohci_compute_total_bandwidth(
3481 usb_ep_descr_t *endpoint,
3482 usb_port_status_t port_status,
3483 uint_t *bandwidth)
3484 {
3485 ushort_t maxpacketsize = endpoint->wMaxPacketSize;
3486
3487 /*
3488 * If endpoint maximum packet is zero, then return immediately.
3489 */
3490 if (maxpacketsize == 0) {
3491
3492 return (USB_NOT_SUPPORTED);
3493 }
3494
3495 /* Add Host Controller specific delay to required bandwidth */
3496 *bandwidth = HOST_CONTROLLER_DELAY;
3497
3498 /* Add bit-stuffing overhead */
3499 maxpacketsize = (ushort_t)((maxpacketsize * 7) / 6);
3500
3501 /* Low Speed interrupt transaction */
3502 if (port_status == USBA_LOW_SPEED_DEV) {
3503 /* Low Speed interrupt transaction */
3504 *bandwidth += (LOW_SPEED_PROTO_OVERHEAD +
3505 HUB_LOW_SPEED_PROTO_OVERHEAD +
3506 (LOW_SPEED_CLOCK * maxpacketsize));
3507 } else {
3508 /* Full Speed transaction */
3509 *bandwidth += maxpacketsize;
3510
3511 if ((endpoint->bmAttributes &
3512 USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR) {
3513 /* Full Speed interrupt transaction */
3514 *bandwidth += FS_NON_ISOC_PROTO_OVERHEAD;
3515 } else {
3516 /* Isochronous and input transaction */
3517 if ((endpoint->bEndpointAddress &
3518 USB_EP_DIR_MASK) == USB_EP_DIR_IN) {
3519 *bandwidth += FS_ISOC_INPUT_PROTO_OVERHEAD;
3520 } else {
3521 /* Isochronous and output transaction */
3522 *bandwidth += FS_ISOC_OUTPUT_PROTO_OVERHEAD;
3523 }
3524 }
3525 }
3526
3527 return (USB_SUCCESS);
3528 }
3529
3530
3531 /*
3532 * ohci_adjust_polling_interval:
3533 */
3534 static int
ohci_adjust_polling_interval(ohci_state_t * ohcip,usb_ep_descr_t * endpoint,usb_port_status_t port_status)3535 ohci_adjust_polling_interval(
3536 ohci_state_t *ohcip,
3537 usb_ep_descr_t *endpoint,
3538 usb_port_status_t port_status)
3539 {
3540 uint_t interval;
3541 int i = 0;
3542
3543 /*
3544 * Get the polling interval from the endpoint descriptor
3545 */
3546 interval = endpoint->bInterval;
3547
3548 /*
3549 * The bInterval value in the endpoint descriptor can range
3550 * from 1 to 255ms. The interrupt lattice has 32 leaf nodes,
3551 * and the host controller cycles through these nodes every
3552 * 32ms. The longest polling interval that the controller
3553 * supports is 32ms.
3554 */
3555
3556 /*
3557 * Return an error if the polling interval is less than 1ms
3558 * and greater than 255ms
3559 */
3560 if ((interval < MIN_POLL_INTERVAL) ||
3561 (interval > MAX_POLL_INTERVAL)) {
3562
3563 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3564 "ohci_adjust_polling_interval: "
3565 "Endpoint's poll interval must be between %d and %d ms",
3566 MIN_POLL_INTERVAL, MAX_POLL_INTERVAL);
3567
3568 return (USB_FAILURE);
3569 }
3570
3571 /*
3572 * According USB Specifications, a full-speed endpoint can
3573 * specify a desired polling interval 1ms to 255ms and a low
3574 * speed endpoints are limited to specifying only 10ms to
3575 * 255ms. But some old keyboards & mice uses polling interval
3576 * of 8ms. For compatibility purpose, we are using polling
3577 * interval between 8ms & 255ms for low speed endpoints. But
3578 * ohci driver will reject the any low speed endpoints which
3579 * request polling interval less than 8ms.
3580 */
3581 if ((port_status == USBA_LOW_SPEED_DEV) &&
3582 (interval < MIN_LOW_SPEED_POLL_INTERVAL)) {
3583
3584 USB_DPRINTF_L2(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3585 "ohci_adjust_polling_interval: "
3586 "Low speed endpoint's poll interval of %d ms "
3587 "is below threshold. Rounding up to %d ms",
3588 interval, MIN_LOW_SPEED_POLL_INTERVAL);
3589
3590 interval = MIN_LOW_SPEED_POLL_INTERVAL;
3591 }
3592
3593 /*
3594 * If polling interval is greater than 32ms,
3595 * adjust polling interval equal to 32ms.
3596 */
3597 if (interval > NUM_INTR_ED_LISTS) {
3598 interval = NUM_INTR_ED_LISTS;
3599 }
3600
3601 /*
3602 * Find the nearest power of 2 that'sless
3603 * than interval.
3604 */
3605 while ((ohci_pow_2(i)) <= interval) {
3606 i++;
3607 }
3608
3609 return (ohci_pow_2((i - 1)));
3610 }
3611
3612
3613 /*
3614 * ohci_lattice_height:
3615 *
3616 * Given the requested bandwidth, find the height in the tree at which the
3617 * nodes for this bandwidth fall. The height is measured as the number of
3618 * nodes from the leaf to the level specified by bandwidth The root of the
3619 * tree is at height TREE_HEIGHT.
3620 */
3621 static uint_t
ohci_lattice_height(uint_t interval)3622 ohci_lattice_height(uint_t interval)
3623 {
3624 return (TREE_HEIGHT - (ohci_log_2(interval)));
3625 }
3626
3627
3628 /*
3629 * ohci_lattice_parent:
3630 */
3631 static uint_t
ohci_lattice_parent(uint_t node)3632 ohci_lattice_parent(uint_t node)
3633 {
3634 if ((node % 2) == 0) {
3635 return ((node/2) - 1);
3636 } else {
3637 return ((node + 1)/2 - 1);
3638 }
3639 }
3640
3641
3642 /*
3643 * ohci_leftmost_leaf:
3644 *
3645 * Find the leftmost leaf in the subtree specified by the node. Height refers
3646 * to number of nodes from the bottom of the tree to the node, including the
3647 * node.
3648 *
3649 * The formula for a zero based tree is:
3650 * 2^H * Node + 2^H - 1
3651 * The leaf of the tree is an array, convert the number for the array.
3652 * Subtract the size of nodes not in the array
3653 * 2^H * Node + 2^H - 1 - (NUM_INTR_ED_LIST - 1) =
3654 * 2^H * Node + 2^H - NUM_INTR_ED_LIST =
3655 * 2^H * (Node + 1) - NUM_INTR_ED_LIST
3656 * 0
3657 * 1 2
3658 * 0 1 2 3
3659 */
3660 static uint_t
ohci_leftmost_leaf(uint_t node,uint_t height)3661 ohci_leftmost_leaf(
3662 uint_t node,
3663 uint_t height)
3664 {
3665 return ((ohci_pow_2(height) * (node + 1)) - NUM_INTR_ED_LISTS);
3666 }
3667
3668 /*
3669 * ohci_hcca_intr_index:
3670 *
3671 * Given a node in the lattice, find the index for the hcca interrupt table
3672 */
3673 static uint_t
ohci_hcca_intr_index(uint_t node)3674 ohci_hcca_intr_index(uint_t node)
3675 {
3676 /*
3677 * Adjust the node to the array representing
3678 * the bottom of the tree.
3679 */
3680 node = node - NUM_STATIC_NODES;
3681
3682 if ((node % 2) == 0) {
3683 return (ohci_index[node / 2]);
3684 } else {
3685 return (ohci_index[node / 2] + (NUM_INTR_ED_LISTS / 2));
3686 }
3687 }
3688
3689 /*
3690 * ohci_hcca_leaf_index:
3691 *
3692 * Given a node in the bottom leaf array of the lattice, find the index
3693 * for the hcca interrupt table
3694 */
3695 static uint_t
ohci_hcca_leaf_index(uint_t leaf)3696 ohci_hcca_leaf_index(uint_t leaf)
3697 {
3698 if ((leaf % 2) == 0) {
3699 return (ohci_index[leaf / 2]);
3700 } else {
3701 return (ohci_index[leaf / 2] + (NUM_INTR_ED_LISTS / 2));
3702 }
3703 }
3704
3705 /*
3706 * ohci_pow_2:
3707 *
3708 * Compute 2 to the power
3709 */
3710 static uint_t
ohci_pow_2(uint_t x)3711 ohci_pow_2(uint_t x)
3712 {
3713 if (x == 0) {
3714 return (1);
3715 } else {
3716 return (2 << (x - 1));
3717 }
3718 }
3719
3720
3721 /*
3722 * ohci_log_2:
3723 *
3724 * Compute log base 2 of x
3725 */
3726 static uint_t
ohci_log_2(uint_t x)3727 ohci_log_2(uint_t x)
3728 {
3729 int i = 0;
3730
3731 while (x != 1) {
3732 x = x >> 1;
3733 i++;
3734 }
3735
3736 return (i);
3737 }
3738
3739
3740 /*
3741 * Endpoint Descriptor (ED) manipulations functions
3742 */
3743
3744 /*
3745 * ohci_alloc_hc_ed:
3746 * NOTE: This function is also called from POLLED MODE.
3747 *
3748 * Allocate an endpoint descriptor (ED)
3749 */
3750 ohci_ed_t *
ohci_alloc_hc_ed(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)3751 ohci_alloc_hc_ed(
3752 ohci_state_t *ohcip,
3753 usba_pipe_handle_data_t *ph)
3754 {
3755 int i, state;
3756 ohci_ed_t *hc_ed;
3757
3758 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
3759 "ohci_alloc_hc_ed: ph = 0x%p", (void *)ph);
3760
3761 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3762
3763 /*
3764 * The first 31 endpoints in the Endpoint Descriptor (ED)
3765 * buffer pool are reserved for building interrupt lattice
3766 * tree. Search for a blank endpoint descriptor in the ED
3767 * buffer pool.
3768 */
3769 for (i = NUM_STATIC_NODES; i < ohci_ed_pool_size; i ++) {
3770 state = Get_ED(ohcip->ohci_ed_pool_addr[i].hced_state);
3771
3772 if (state == HC_EPT_FREE) {
3773 break;
3774 }
3775 }
3776
3777 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
3778 "ohci_alloc_hc_ed: Allocated %d", i);
3779
3780 if (i == ohci_ed_pool_size) {
3781 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
3782 "ohci_alloc_hc_ed: ED exhausted");
3783
3784 return (NULL);
3785 } else {
3786
3787 hc_ed = &ohcip->ohci_ed_pool_addr[i];
3788
3789 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
3790 "ohci_alloc_hc_ed: Allocated address 0x%p", (void *)hc_ed);
3791
3792 ohci_print_ed(ohcip, hc_ed);
3793
3794 /* Unpack the endpoint descriptor into a control field */
3795 if (ph) {
3796 if ((ohci_initialize_dummy(ohcip,
3797 hc_ed)) == USB_NO_RESOURCES) {
3798 bzero((void *)hc_ed, sizeof (ohci_ed_t));
3799 Set_ED(hc_ed->hced_state, HC_EPT_FREE);
3800 return (NULL);
3801 }
3802
3803 Set_ED(hc_ed->hced_prev, 0);
3804 Set_ED(hc_ed->hced_next, 0);
3805
3806 /* Change ED's state Active */
3807 Set_ED(hc_ed->hced_state, HC_EPT_ACTIVE);
3808
3809 Set_ED(hc_ed->hced_ctrl,
3810 ohci_unpack_endpoint(ohcip, ph));
3811 } else {
3812 Set_ED(hc_ed->hced_ctrl, HC_EPT_sKip);
3813
3814 /* Change ED's state Static */
3815 Set_ED(hc_ed->hced_state, HC_EPT_STATIC);
3816 }
3817
3818 return (hc_ed);
3819 }
3820 }
3821
3822
3823 /*
3824 * ohci_unpack_endpoint:
3825 *
3826 * Unpack the information in the pipe handle and create the first byte
3827 * of the Host Controller's (HC) Endpoint Descriptor (ED).
3828 */
3829 static uint_t
ohci_unpack_endpoint(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)3830 ohci_unpack_endpoint(
3831 ohci_state_t *ohcip,
3832 usba_pipe_handle_data_t *ph)
3833 {
3834 usb_ep_descr_t *endpoint = &ph->p_ep;
3835 uint_t maxpacketsize, addr, ctrl = 0;
3836
3837 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3838 "ohci_unpack_endpoint:");
3839
3840 ctrl = ph->p_usba_device->usb_addr;
3841
3842 addr = endpoint->bEndpointAddress;
3843
3844 /* Assign the endpoint's address */
3845 ctrl = ctrl | ((addr & USB_EP_NUM_MASK) << HC_EPT_EP_SHFT);
3846
3847 /*
3848 * Assign the direction. If the endpoint is a control endpoint,
3849 * the direction is assigned by the Transfer Descriptor (TD).
3850 */
3851 if ((endpoint->bmAttributes &
3852 USB_EP_ATTR_MASK) != USB_EP_ATTR_CONTROL) {
3853 if (addr & USB_EP_DIR_MASK) {
3854 /* The direction is IN */
3855 ctrl = ctrl | HC_EPT_DF_IN;
3856 } else {
3857 /* The direction is OUT */
3858 ctrl = ctrl | HC_EPT_DF_OUT;
3859 }
3860 }
3861
3862 /* Assign the speed */
3863 mutex_enter(&ph->p_usba_device->usb_mutex);
3864 if (ph->p_usba_device->usb_port_status == USBA_LOW_SPEED_DEV) {
3865 ctrl = ctrl | HC_EPT_Speed;
3866 }
3867 mutex_exit(&ph->p_usba_device->usb_mutex);
3868
3869 /* Assign the format */
3870 if ((endpoint->bmAttributes &
3871 USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH) {
3872 ctrl = ctrl | HC_EPT_Format;
3873 }
3874
3875 maxpacketsize = endpoint->wMaxPacketSize;
3876 maxpacketsize = maxpacketsize << HC_EPT_MAXPKTSZ;
3877 ctrl = ctrl | (maxpacketsize & HC_EPT_MPS);
3878
3879 return (ctrl);
3880 }
3881
3882
3883 /*
3884 * ohci_insert_ed:
3885 *
3886 * Add the Endpoint Descriptor (ED) into the Host Controller's
3887 * (HC) appropriate endpoint list.
3888 */
3889 static void
ohci_insert_ed(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)3890 ohci_insert_ed(
3891 ohci_state_t *ohcip,
3892 usba_pipe_handle_data_t *ph)
3893 {
3894 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
3895
3896 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3897 "ohci_insert_ed:");
3898
3899 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3900
3901 switch (ph->p_ep.bmAttributes & USB_EP_ATTR_MASK) {
3902 case USB_EP_ATTR_CONTROL:
3903 ohci_insert_ctrl_ed(ohcip, pp);
3904 break;
3905 case USB_EP_ATTR_BULK:
3906 ohci_insert_bulk_ed(ohcip, pp);
3907 break;
3908 case USB_EP_ATTR_INTR:
3909 ohci_insert_intr_ed(ohcip, pp);
3910 break;
3911 case USB_EP_ATTR_ISOCH:
3912 ohci_insert_isoc_ed(ohcip, pp);
3913 break;
3914 }
3915 }
3916
3917
3918 /*
3919 * ohci_insert_ctrl_ed:
3920 *
3921 * Insert a control endpoint into the Host Controller's (HC)
3922 * control endpoint list.
3923 */
3924 static void
ohci_insert_ctrl_ed(ohci_state_t * ohcip,ohci_pipe_private_t * pp)3925 ohci_insert_ctrl_ed(
3926 ohci_state_t *ohcip,
3927 ohci_pipe_private_t *pp)
3928 {
3929 ohci_ed_t *ept = pp->pp_ept;
3930 ohci_ed_t *prev_ept;
3931
3932 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3933 "ohci_insert_ctrl_ed:");
3934
3935 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3936
3937 /* Obtain a ptr to the head of the list */
3938 if (Get_OpReg(hcr_ctrl_head)) {
3939 prev_ept = ohci_ed_iommu_to_cpu(ohcip,
3940 Get_OpReg(hcr_ctrl_head));
3941
3942 /* Set up the backwards pointer */
3943 Set_ED(prev_ept->hced_prev, ohci_ed_cpu_to_iommu(ohcip, ept));
3944 }
3945
3946 /* The new endpoint points to the head of the list */
3947 Set_ED(ept->hced_next, Get_OpReg(hcr_ctrl_head));
3948
3949 /* Set the head ptr to the new endpoint */
3950 Set_OpReg(hcr_ctrl_head, ohci_ed_cpu_to_iommu(ohcip, ept));
3951
3952 /*
3953 * Enable Control list processing if control open
3954 * pipe count is zero.
3955 */
3956 if (!ohcip->ohci_open_ctrl_pipe_count) {
3957 /* Start Control list processing */
3958 Set_OpReg(hcr_control,
3959 (Get_OpReg(hcr_control) | HCR_CONTROL_CLE));
3960 }
3961
3962 ohcip->ohci_open_ctrl_pipe_count++;
3963 }
3964
3965
3966 /*
3967 * ohci_insert_bulk_ed:
3968 *
3969 * Insert a bulk endpoint into the Host Controller's (HC) bulk endpoint list.
3970 */
3971 static void
ohci_insert_bulk_ed(ohci_state_t * ohcip,ohci_pipe_private_t * pp)3972 ohci_insert_bulk_ed(
3973 ohci_state_t *ohcip,
3974 ohci_pipe_private_t *pp)
3975 {
3976 ohci_ed_t *ept = pp->pp_ept;
3977 ohci_ed_t *prev_ept;
3978
3979 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3980 "ohci_insert_bulk_ed:");
3981
3982 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3983
3984 /* Obtain a ptr to the head of the Bulk list */
3985 if (Get_OpReg(hcr_bulk_head)) {
3986 prev_ept = ohci_ed_iommu_to_cpu(ohcip,
3987 Get_OpReg(hcr_bulk_head));
3988
3989 /* Set up the backwards pointer */
3990 Set_ED(prev_ept->hced_prev, ohci_ed_cpu_to_iommu(ohcip, ept));
3991 }
3992
3993 /* The new endpoint points to the head of the Bulk list */
3994 Set_ED(ept->hced_next, Get_OpReg(hcr_bulk_head));
3995
3996 /* Set the Bulk head ptr to the new endpoint */
3997 Set_OpReg(hcr_bulk_head, ohci_ed_cpu_to_iommu(ohcip, ept));
3998
3999 /*
4000 * Enable Bulk list processing if bulk open pipe
4001 * count is zero.
4002 */
4003 if (!ohcip->ohci_open_bulk_pipe_count) {
4004 /* Start Bulk list processing */
4005 Set_OpReg(hcr_control,
4006 (Get_OpReg(hcr_control) | HCR_CONTROL_BLE));
4007 }
4008
4009 ohcip->ohci_open_bulk_pipe_count++;
4010 }
4011
4012
4013 /*
4014 * ohci_insert_intr_ed:
4015 *
4016 * Insert a interrupt endpoint into the Host Controller's (HC) interrupt
4017 * lattice tree.
4018 */
4019 static void
ohci_insert_intr_ed(ohci_state_t * ohcip,ohci_pipe_private_t * pp)4020 ohci_insert_intr_ed(
4021 ohci_state_t *ohcip,
4022 ohci_pipe_private_t *pp)
4023 {
4024 ohci_ed_t *ept = pp->pp_ept;
4025 ohci_ed_t *next_lattice_ept, *lattice_ept;
4026 uint_t node;
4027
4028 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4029
4030 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4031 "ohci_insert_intr_ed:");
4032
4033 /*
4034 * The appropriate node was found
4035 * during the opening of the pipe.
4036 */
4037 node = pp->pp_node;
4038
4039 if (node >= NUM_STATIC_NODES) {
4040 /* Get the hcca interrupt table index */
4041 node = ohci_hcca_intr_index(node);
4042
4043 /* Get the first endpoint on the list */
4044 next_lattice_ept = ohci_ed_iommu_to_cpu(ohcip,
4045 Get_HCCA(ohcip->ohci_hccap->HccaIntTble[node]));
4046
4047 /* Update this endpoint to point to it */
4048 Set_ED(ept->hced_next,
4049 ohci_ed_cpu_to_iommu(ohcip, next_lattice_ept));
4050
4051 /* Put this endpoint at the head of the list */
4052 Set_HCCA(ohcip->ohci_hccap->HccaIntTble[node],
4053 ohci_ed_cpu_to_iommu(ohcip, ept));
4054
4055 /* The previous pointer is NULL */
4056 Set_ED(ept->hced_prev, 0);
4057
4058 /* Update the previous pointer of ept->hced_next */
4059 if (Get_ED(next_lattice_ept->hced_state) != HC_EPT_STATIC) {
4060 Set_ED(next_lattice_ept->hced_prev,
4061 ohci_ed_cpu_to_iommu(ohcip, ept));
4062 }
4063 } else {
4064 /* Find the lattice endpoint */
4065 lattice_ept = &ohcip->ohci_ed_pool_addr[node];
4066
4067 /* Find the next lattice endpoint */
4068 next_lattice_ept = ohci_ed_iommu_to_cpu(
4069 ohcip, Get_ED(lattice_ept->hced_next));
4070
4071 /*
4072 * Update this endpoint to point to the next one in the
4073 * lattice.
4074 */
4075 Set_ED(ept->hced_next, Get_ED(lattice_ept->hced_next));
4076
4077 /* Insert this endpoint into the lattice */
4078 Set_ED(lattice_ept->hced_next,
4079 ohci_ed_cpu_to_iommu(ohcip, ept));
4080
4081 /* Update the previous pointer */
4082 Set_ED(ept->hced_prev,
4083 ohci_ed_cpu_to_iommu(ohcip, lattice_ept));
4084
4085 /* Update the previous pointer of ept->hced_next */
4086 if ((next_lattice_ept) &&
4087 (Get_ED(next_lattice_ept->hced_state) != HC_EPT_STATIC)) {
4088
4089 Set_ED(next_lattice_ept->hced_prev,
4090 ohci_ed_cpu_to_iommu(ohcip, ept));
4091 }
4092 }
4093
4094 /*
4095 * Enable periodic list processing if periodic (interrupt
4096 * and isochronous) open pipe count is zero.
4097 */
4098 if (!ohcip->ohci_open_periodic_pipe_count) {
4099 ASSERT(!ohcip->ohci_open_isoch_pipe_count);
4100
4101 Set_OpReg(hcr_control,
4102 (Get_OpReg(hcr_control) | HCR_CONTROL_PLE));
4103 }
4104
4105 ohcip->ohci_open_periodic_pipe_count++;
4106 }
4107
4108
4109 /*
4110 * ohci_insert_isoc_ed:
4111 *
4112 * Insert a isochronous endpoint into the Host Controller's (HC) interrupt
4113 * lattice tree. A isochronous endpoint will be inserted at the end of the
4114 * 1ms interrupt endpoint list.
4115 */
4116 static void
ohci_insert_isoc_ed(ohci_state_t * ohcip,ohci_pipe_private_t * pp)4117 ohci_insert_isoc_ed(
4118 ohci_state_t *ohcip,
4119 ohci_pipe_private_t *pp)
4120 {
4121 ohci_ed_t *next_lattice_ept, *lattice_ept;
4122 ohci_ed_t *ept = pp->pp_ept;
4123 uint_t node;
4124
4125 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4126
4127 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4128 "ohci_insert_isoc_ed:");
4129
4130 /*
4131 * The appropriate node was found during the opening of the pipe.
4132 * This node must be root of the interrupt lattice tree.
4133 */
4134 node = pp->pp_node;
4135
4136 ASSERT(node == 0);
4137
4138 /* Find the 1ms interrupt lattice endpoint */
4139 lattice_ept = &ohcip->ohci_ed_pool_addr[node];
4140
4141 /* Find the next lattice endpoint */
4142 next_lattice_ept = ohci_ed_iommu_to_cpu(
4143 ohcip, Get_ED(lattice_ept->hced_next));
4144
4145 while (next_lattice_ept) {
4146 lattice_ept = next_lattice_ept;
4147
4148 /* Find the next lattice endpoint */
4149 next_lattice_ept = ohci_ed_iommu_to_cpu(
4150 ohcip, Get_ED(lattice_ept->hced_next));
4151 }
4152
4153 /* The next pointer is NULL */
4154 Set_ED(ept->hced_next, 0);
4155
4156 /* Update the previous pointer */
4157 Set_ED(ept->hced_prev, ohci_ed_cpu_to_iommu(ohcip, lattice_ept));
4158
4159 /* Insert this endpoint into the lattice */
4160 Set_ED(lattice_ept->hced_next, ohci_ed_cpu_to_iommu(ohcip, ept));
4161
4162 /*
4163 * Enable periodic and isoch lists processing if isoch
4164 * open pipe count is zero.
4165 */
4166 if (!ohcip->ohci_open_isoch_pipe_count) {
4167
4168 Set_OpReg(hcr_control, (Get_OpReg(hcr_control) |
4169 HCR_CONTROL_PLE | HCR_CONTROL_IE));
4170 }
4171
4172 ohcip->ohci_open_periodic_pipe_count++;
4173 ohcip->ohci_open_isoch_pipe_count++;
4174 }
4175
4176
4177 /*
4178 * ohci_modify_sKip_bit:
4179 *
4180 * Modify the sKip bit on the Host Controller (HC) Endpoint Descriptor (ED).
4181 */
4182 static void
ohci_modify_sKip_bit(ohci_state_t * ohcip,ohci_pipe_private_t * pp,skip_bit_t action,usb_flags_t flag)4183 ohci_modify_sKip_bit(
4184 ohci_state_t *ohcip,
4185 ohci_pipe_private_t *pp,
4186 skip_bit_t action,
4187 usb_flags_t flag)
4188 {
4189 ohci_ed_t *ept = pp->pp_ept;
4190
4191 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4192 "ohci_modify_sKip_bit: action = 0x%x flag = 0x%x",
4193 action, flag);
4194
4195 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4196
4197 if (action == CLEAR_sKip) {
4198 /*
4199 * If the skip bit is to be cleared, just clear it.
4200 * there shouldn't be any race condition problems.
4201 * If the host controller reads the bit before the
4202 * driver has a chance to set the bit, the bit will
4203 * be reread on the next frame.
4204 */
4205 Set_ED(ept->hced_ctrl, (Get_ED(ept->hced_ctrl) & ~HC_EPT_sKip));
4206 } else {
4207 /* Sync ED and TD pool */
4208 if (flag & OHCI_FLAGS_DMA_SYNC) {
4209 Sync_ED_TD_Pool(ohcip);
4210 }
4211
4212 /* Check Halt or Skip bit is already set */
4213 if ((Get_ED(ept->hced_headp) & HC_EPT_Halt) ||
4214 (Get_ED(ept->hced_ctrl) & HC_EPT_sKip)) {
4215
4216 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4217 "ohci_modify_sKip_bit: "
4218 "Halt or Skip bit is already set");
4219 } else {
4220 /*
4221 * The action is to set the skip bit. In order to
4222 * be sure that the HCD has seen the sKip bit, wait
4223 * for the next start of frame.
4224 */
4225 Set_ED(ept->hced_ctrl,
4226 (Get_ED(ept->hced_ctrl) | HC_EPT_sKip));
4227
4228 if (flag & OHCI_FLAGS_SLEEP) {
4229 /* Wait for the next SOF */
4230 (void) ohci_wait_for_sof(ohcip);
4231
4232 /* Sync ED and TD pool */
4233 if (flag & OHCI_FLAGS_DMA_SYNC) {
4234 Sync_ED_TD_Pool(ohcip);
4235 }
4236 }
4237 }
4238 }
4239 }
4240
4241
4242 /*
4243 * ohci_remove_ed:
4244 *
4245 * Remove the Endpoint Descriptor (ED) from the Host Controller's appropriate
4246 * endpoint list.
4247 */
4248 static void
ohci_remove_ed(ohci_state_t * ohcip,ohci_pipe_private_t * pp)4249 ohci_remove_ed(
4250 ohci_state_t *ohcip,
4251 ohci_pipe_private_t *pp)
4252 {
4253 uchar_t attributes;
4254
4255 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4256
4257 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4258 "ohci_remove_ed:");
4259
4260 attributes = pp->pp_pipe_handle->p_ep.bmAttributes & USB_EP_ATTR_MASK;
4261
4262 switch (attributes) {
4263 case USB_EP_ATTR_CONTROL:
4264 ohci_remove_ctrl_ed(ohcip, pp);
4265 break;
4266 case USB_EP_ATTR_BULK:
4267 ohci_remove_bulk_ed(ohcip, pp);
4268 break;
4269 case USB_EP_ATTR_INTR:
4270 case USB_EP_ATTR_ISOCH:
4271 ohci_remove_periodic_ed(ohcip, pp);
4272 break;
4273 }
4274 }
4275
4276
4277 /*
4278 * ohci_remove_ctrl_ed:
4279 *
4280 * Remove a control Endpoint Descriptor (ED) from the Host Controller's (HC)
4281 * control endpoint list.
4282 */
4283 static void
ohci_remove_ctrl_ed(ohci_state_t * ohcip,ohci_pipe_private_t * pp)4284 ohci_remove_ctrl_ed(
4285 ohci_state_t *ohcip,
4286 ohci_pipe_private_t *pp)
4287 {
4288 ohci_ed_t *ept = pp->pp_ept; /* ept to be removed */
4289
4290 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4291 "ohci_remove_ctrl_ed:");
4292
4293 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4294
4295 /* The control list should already be stopped */
4296 ASSERT(!(Get_OpReg(hcr_control) & HCR_CONTROL_CLE));
4297
4298 ohcip->ohci_open_ctrl_pipe_count--;
4299
4300 /* Detach the endpoint from the list that it's on */
4301 ohci_detach_ed_from_list(ohcip, ept, USB_EP_ATTR_CONTROL);
4302
4303 /*
4304 * If next endpoint pointed by endpoint to be removed is not NULL
4305 * then set current control pointer to the next endpoint pointed by
4306 * endpoint to be removed. Otherwise set current control pointer to
4307 * the beginning of the control list.
4308 */
4309 if (Get_ED(ept->hced_next)) {
4310 Set_OpReg(hcr_ctrl_curr, Get_ED(ept->hced_next));
4311 } else {
4312 Set_OpReg(hcr_ctrl_curr, Get_OpReg(hcr_ctrl_head));
4313 }
4314
4315 if (ohcip->ohci_open_ctrl_pipe_count) {
4316 ASSERT(Get_OpReg(hcr_ctrl_head));
4317
4318 /* Reenable the control list */
4319 Set_OpReg(hcr_control,
4320 (Get_OpReg(hcr_control) | HCR_CONTROL_CLE));
4321 }
4322
4323 ohci_insert_ed_on_reclaim_list(ohcip, pp);
4324 }
4325
4326
4327 /*
4328 * ohci_remove_bulk_ed:
4329 *
4330 * Remove free the bulk Endpoint Descriptor (ED) from the Host Controller's
4331 * (HC) bulk endpoint list.
4332 */
4333 static void
ohci_remove_bulk_ed(ohci_state_t * ohcip,ohci_pipe_private_t * pp)4334 ohci_remove_bulk_ed(
4335 ohci_state_t *ohcip,
4336 ohci_pipe_private_t *pp)
4337 {
4338 ohci_ed_t *ept = pp->pp_ept; /* ept to be removed */
4339
4340 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4341 "ohci_remove_bulk_ed:");
4342
4343 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4344
4345 /* The bulk list should already be stopped */
4346 ASSERT(!(Get_OpReg(hcr_control) & HCR_CONTROL_BLE));
4347
4348 ohcip->ohci_open_bulk_pipe_count--;
4349
4350 /* Detach the endpoint from the bulk list */
4351 ohci_detach_ed_from_list(ohcip, ept, USB_EP_ATTR_BULK);
4352
4353 /*
4354 * If next endpoint pointed by endpoint to be removed is not NULL
4355 * then set current bulk pointer to the next endpoint pointed by
4356 * endpoint to be removed. Otherwise set current bulk pointer to
4357 * the beginning of the bulk list.
4358 */
4359 if (Get_ED(ept->hced_next)) {
4360 Set_OpReg(hcr_bulk_curr, Get_ED(ept->hced_next));
4361 } else {
4362 Set_OpReg(hcr_bulk_curr, Get_OpReg(hcr_bulk_head));
4363 }
4364
4365 if (ohcip->ohci_open_bulk_pipe_count) {
4366 ASSERT(Get_OpReg(hcr_bulk_head));
4367
4368 /* Re-enable the bulk list */
4369 Set_OpReg(hcr_control,
4370 (Get_OpReg(hcr_control) | HCR_CONTROL_BLE));
4371 }
4372
4373 ohci_insert_ed_on_reclaim_list(ohcip, pp);
4374 }
4375
4376
4377 /*
4378 * ohci_remove_periodic_ed:
4379 *
4380 * Set up an periodic endpoint to be removed from the Host Controller's (HC)
4381 * interrupt lattice tree. The Endpoint Descriptor (ED) will be freed in the
4382 * interrupt handler.
4383 */
4384 static void
ohci_remove_periodic_ed(ohci_state_t * ohcip,ohci_pipe_private_t * pp)4385 ohci_remove_periodic_ed(
4386 ohci_state_t *ohcip,
4387 ohci_pipe_private_t *pp)
4388 {
4389 ohci_ed_t *ept = pp->pp_ept; /* ept to be removed */
4390 uint_t ept_type;
4391
4392 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4393 "ohci_remove_periodic_ed:");
4394
4395 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4396
4397 ASSERT((Get_ED(ept->hced_tailp) & HC_EPT_TD_TAIL) ==
4398 (Get_ED(ept->hced_headp) & HC_EPT_TD_HEAD));
4399
4400 ohcip->ohci_open_periodic_pipe_count--;
4401
4402 ept_type = pp->pp_pipe_handle->
4403 p_ep.bmAttributes & USB_EP_ATTR_MASK;
4404
4405 if (ept_type == USB_EP_ATTR_ISOCH) {
4406 ohcip->ohci_open_isoch_pipe_count--;
4407 }
4408
4409 /* Store the node number */
4410 Set_ED(ept->hced_node, pp->pp_node);
4411
4412 /* Remove the endpoint from interrupt lattice tree */
4413 ohci_detach_ed_from_list(ohcip, ept, ept_type);
4414
4415 /*
4416 * Disable isoch list processing if isoch open pipe count
4417 * is zero.
4418 */
4419 if (!ohcip->ohci_open_isoch_pipe_count) {
4420 Set_OpReg(hcr_control,
4421 (Get_OpReg(hcr_control) & ~(HCR_CONTROL_IE)));
4422 }
4423
4424 /*
4425 * Disable periodic list processing if periodic (interrupt
4426 * and isochrous) open pipe count is zero.
4427 */
4428 if (!ohcip->ohci_open_periodic_pipe_count) {
4429 ASSERT(!ohcip->ohci_open_isoch_pipe_count);
4430
4431 Set_OpReg(hcr_control,
4432 (Get_OpReg(hcr_control) & ~(HCR_CONTROL_PLE)));
4433 }
4434
4435 ohci_insert_ed_on_reclaim_list(ohcip, pp);
4436 }
4437
4438
4439 /*
4440 * ohci_detach_ed_from_list:
4441 *
4442 * Remove the Endpoint Descriptor (ED) from the appropriate Host Controller's
4443 * (HC) endpoint list.
4444 */
4445 static void
ohci_detach_ed_from_list(ohci_state_t * ohcip,ohci_ed_t * ept,uint_t ept_type)4446 ohci_detach_ed_from_list(
4447 ohci_state_t *ohcip,
4448 ohci_ed_t *ept,
4449 uint_t ept_type)
4450 {
4451 ohci_ed_t *prev_ept; /* Previous endpoint */
4452 ohci_ed_t *next_ept; /* Endpoint after one to be removed */
4453 uint_t node;
4454
4455 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4456 "ohci_detach_ed_from_list:");
4457
4458 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4459
4460 prev_ept = ohci_ed_iommu_to_cpu(ohcip, Get_ED(ept->hced_prev));
4461 next_ept = ohci_ed_iommu_to_cpu(ohcip, Get_ED(ept->hced_next));
4462
4463 /*
4464 * If there is no previous endpoint, then this
4465 * endpoint is at the head of the endpoint list.
4466 */
4467 if (prev_ept == NULL) {
4468 if (next_ept) {
4469 /*
4470 * If this endpoint is the first element of the
4471 * list and there is more than one endpoint on
4472 * the list then perform specific actions based
4473 * on the type of endpoint list.
4474 */
4475 switch (ept_type) {
4476 case USB_EP_ATTR_CONTROL:
4477 /* Set the head of list to next ept */
4478 Set_OpReg(hcr_ctrl_head,
4479 Get_ED(ept->hced_next));
4480
4481 /* Clear prev ptr of next endpoint */
4482 Set_ED(next_ept->hced_prev, 0);
4483 break;
4484 case USB_EP_ATTR_BULK:
4485 /* Set the head of list to next ept */
4486 Set_OpReg(hcr_bulk_head,
4487 Get_ED(ept->hced_next));
4488
4489 /* Clear prev ptr of next endpoint */
4490 Set_ED(next_ept->hced_prev, 0);
4491 break;
4492 case USB_EP_ATTR_INTR:
4493 /*
4494 * HCCA area should point
4495 * directly to this ept.
4496 */
4497 ASSERT(Get_ED(ept->hced_node) >=
4498 NUM_STATIC_NODES);
4499
4500 /* Get the hcca interrupt table index */
4501 node = ohci_hcca_intr_index(
4502 Get_ED(ept->hced_node));
4503
4504 /*
4505 * Delete the ept from the
4506 * bottom of the tree.
4507 */
4508 Set_HCCA(ohcip->ohci_hccap->
4509 HccaIntTble[node], Get_ED(ept->hced_next));
4510
4511 /*
4512 * Update the previous pointer
4513 * of ept->hced_next
4514 */
4515 if (Get_ED(next_ept->hced_state) !=
4516 HC_EPT_STATIC) {
4517
4518 Set_ED(next_ept->hced_prev, 0);
4519 }
4520
4521 break;
4522 case USB_EP_ATTR_ISOCH:
4523 default:
4524 break;
4525 }
4526 } else {
4527 /*
4528 * If there was only one element on the list
4529 * perform specific actions based on the type
4530 * of the list.
4531 */
4532 switch (ept_type) {
4533 case USB_EP_ATTR_CONTROL:
4534 /* Set the head to NULL */
4535 Set_OpReg(hcr_ctrl_head, 0);
4536 break;
4537 case USB_EP_ATTR_BULK:
4538 /* Set the head to NULL */
4539 Set_OpReg(hcr_bulk_head, 0);
4540 break;
4541 case USB_EP_ATTR_INTR:
4542 case USB_EP_ATTR_ISOCH:
4543 default:
4544 break;
4545 }
4546 }
4547 } else {
4548 /* The previous ept points to the next one */
4549 Set_ED(prev_ept->hced_next, Get_ED(ept->hced_next));
4550
4551 /*
4552 * Set the previous ptr of the next_ept to prev_ept
4553 * if this isn't the last endpoint on the list
4554 */
4555 if ((next_ept) &&
4556 (Get_ED(next_ept->hced_state) != HC_EPT_STATIC)) {
4557
4558 /* Set the previous ptr of the next one */
4559 Set_ED(next_ept->hced_prev, Get_ED(ept->hced_prev));
4560 }
4561 }
4562 }
4563
4564
4565 /*
4566 * ohci_insert_ed_on_reclaim_list:
4567 *
4568 * Insert Endpoint onto the reclaim list
4569 */
4570 static void
ohci_insert_ed_on_reclaim_list(ohci_state_t * ohcip,ohci_pipe_private_t * pp)4571 ohci_insert_ed_on_reclaim_list(
4572 ohci_state_t *ohcip,
4573 ohci_pipe_private_t *pp)
4574 {
4575 ohci_ed_t *ept = pp->pp_ept; /* ept to be removed */
4576 ohci_ed_t *next_ept, *prev_ept;
4577 usb_frame_number_t frame_number;
4578
4579 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4580
4581 /*
4582 * Read current usb frame number and add appropriate number of
4583 * usb frames needs to wait before reclaiming current endpoint.
4584 */
4585 frame_number =
4586 ohci_get_current_frame_number(ohcip) + MAX_SOF_WAIT_COUNT;
4587
4588 /* Store 32bit ID */
4589 Set_ED(ept->hced_reclaim_frame,
4590 ((uint32_t)(OHCI_GET_ID((void *)(uintptr_t)frame_number))));
4591
4592 /* Insert the endpoint onto the reclaimation list */
4593 if (ohcip->ohci_reclaim_list) {
4594 next_ept = ohcip->ohci_reclaim_list;
4595
4596 while (next_ept) {
4597 prev_ept = next_ept;
4598 next_ept = ohci_ed_iommu_to_cpu(ohcip,
4599 Get_ED(next_ept->hced_reclaim_next));
4600 }
4601
4602 Set_ED(prev_ept->hced_reclaim_next,
4603 ohci_ed_cpu_to_iommu(ohcip, ept));
4604 } else {
4605 ohcip->ohci_reclaim_list = ept;
4606 }
4607
4608 ASSERT(Get_ED(ept->hced_reclaim_next) == 0);
4609
4610 /* Enable the SOF interrupt */
4611 Set_OpReg(hcr_intr_enable, HCR_INTR_SOF);
4612 }
4613
4614
4615 /*
4616 * ohci_deallocate_ed:
4617 * NOTE: This function is also called from POLLED MODE.
4618 *
4619 * Deallocate a Host Controller's (HC) Endpoint Descriptor (ED).
4620 */
4621 void
ohci_deallocate_ed(ohci_state_t * ohcip,ohci_ed_t * old_ed)4622 ohci_deallocate_ed(
4623 ohci_state_t *ohcip,
4624 ohci_ed_t *old_ed)
4625 {
4626 ohci_td_t *dummy_td;
4627
4628 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
4629 "ohci_deallocate_ed:");
4630
4631 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4632
4633 dummy_td = ohci_td_iommu_to_cpu(ohcip, Get_ED(old_ed->hced_headp));
4634
4635 if (dummy_td) {
4636
4637 ASSERT(Get_TD(dummy_td->hctd_state) == HC_TD_DUMMY);
4638 ohci_deallocate_td(ohcip, dummy_td);
4639 }
4640
4641 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
4642 "ohci_deallocate_ed: Deallocated 0x%p", (void *)old_ed);
4643
4644 bzero((void *)old_ed, sizeof (ohci_ed_t));
4645 Set_ED(old_ed->hced_state, HC_EPT_FREE);
4646 }
4647
4648
4649 /*
4650 * ohci_ed_cpu_to_iommu:
4651 * NOTE: This function is also called from POLLED MODE.
4652 *
4653 * This function converts for the given Endpoint Descriptor (ED) CPU address
4654 * to IO address.
4655 */
4656 uint32_t
ohci_ed_cpu_to_iommu(ohci_state_t * ohcip,ohci_ed_t * addr)4657 ohci_ed_cpu_to_iommu(
4658 ohci_state_t *ohcip,
4659 ohci_ed_t *addr)
4660 {
4661 uint32_t ed;
4662
4663 ed = (uint32_t)ohcip->ohci_ed_pool_cookie.dmac_address +
4664 (uint32_t)((uintptr_t)addr - (uintptr_t)(ohcip->ohci_ed_pool_addr));
4665
4666 ASSERT(ed >= ohcip->ohci_ed_pool_cookie.dmac_address);
4667 ASSERT(ed <= ohcip->ohci_ed_pool_cookie.dmac_address +
4668 sizeof (ohci_ed_t) * ohci_ed_pool_size);
4669
4670 return (ed);
4671 }
4672
4673
4674 /*
4675 * ohci_ed_iommu_to_cpu:
4676 *
4677 * This function converts for the given Endpoint Descriptor (ED) IO address
4678 * to CPU address.
4679 */
4680 static ohci_ed_t *
ohci_ed_iommu_to_cpu(ohci_state_t * ohcip,uintptr_t addr)4681 ohci_ed_iommu_to_cpu(
4682 ohci_state_t *ohcip,
4683 uintptr_t addr)
4684 {
4685 ohci_ed_t *ed;
4686
4687 if (addr == 0)
4688 return (NULL);
4689
4690 ed = (ohci_ed_t *)((uintptr_t)
4691 (addr - ohcip->ohci_ed_pool_cookie.dmac_address) +
4692 (uintptr_t)ohcip->ohci_ed_pool_addr);
4693
4694 ASSERT(ed >= ohcip->ohci_ed_pool_addr);
4695 ASSERT((uintptr_t)ed <= (uintptr_t)ohcip->ohci_ed_pool_addr +
4696 (uintptr_t)(sizeof (ohci_ed_t) * ohci_ed_pool_size));
4697
4698 return (ed);
4699 }
4700
4701
4702 /*
4703 * Transfer Descriptor manipulations functions
4704 */
4705
4706 /*
4707 * ohci_initialize_dummy:
4708 *
4709 * An Endpoint Descriptor (ED) has a dummy Transfer Descriptor (TD) on the
4710 * end of its TD list. Initially, both the head and tail pointers of the ED
4711 * point to the dummy TD.
4712 */
4713 static int
ohci_initialize_dummy(ohci_state_t * ohcip,ohci_ed_t * ept)4714 ohci_initialize_dummy(
4715 ohci_state_t *ohcip,
4716 ohci_ed_t *ept)
4717 {
4718 ohci_td_t *dummy;
4719
4720 /* Obtain a dummy TD */
4721 dummy = ohci_allocate_td_from_pool(ohcip);
4722
4723 if (dummy == NULL) {
4724 return (USB_NO_RESOURCES);
4725 }
4726
4727 /*
4728 * Both the head and tail pointers of an ED point
4729 * to this new dummy TD.
4730 */
4731 Set_ED(ept->hced_headp, (ohci_td_cpu_to_iommu(ohcip, dummy)));
4732 Set_ED(ept->hced_tailp, (ohci_td_cpu_to_iommu(ohcip, dummy)));
4733
4734 return (USB_SUCCESS);
4735 }
4736
4737 /*
4738 * ohci_allocate_ctrl_resources:
4739 *
4740 * Calculates the number of tds necessary for a ctrl transfer, and allocates
4741 * all the resources necessary.
4742 *
4743 * Returns NULL if there is insufficient resources otherwise TW.
4744 */
4745 static ohci_trans_wrapper_t *
ohci_allocate_ctrl_resources(ohci_state_t * ohcip,ohci_pipe_private_t * pp,usb_ctrl_req_t * ctrl_reqp,usb_flags_t usb_flags)4746 ohci_allocate_ctrl_resources(
4747 ohci_state_t *ohcip,
4748 ohci_pipe_private_t *pp,
4749 usb_ctrl_req_t *ctrl_reqp,
4750 usb_flags_t usb_flags)
4751 {
4752 size_t td_count = 2;
4753 size_t ctrl_buf_size;
4754 ohci_trans_wrapper_t *tw;
4755
4756 /* Add one more td for data phase */
4757 if (ctrl_reqp->ctrl_wLength) {
4758 td_count++;
4759 }
4760
4761 /*
4762 * If we have a control data phase, the data buffer starts
4763 * on the next 4K page boundary. So the TW buffer is allocated
4764 * to be larger than required. The buffer in the range of
4765 * [SETUP_SIZE, OHCI_MAX_TD_BUF_SIZE) is just for padding
4766 * and not to be transferred.
4767 */
4768 if (ctrl_reqp->ctrl_wLength) {
4769 ctrl_buf_size = OHCI_MAX_TD_BUF_SIZE +
4770 ctrl_reqp->ctrl_wLength;
4771 } else {
4772 ctrl_buf_size = SETUP_SIZE;
4773 }
4774
4775 tw = ohci_allocate_tw_resources(ohcip, pp, ctrl_buf_size,
4776 usb_flags, td_count);
4777
4778 return (tw);
4779 }
4780
4781 /*
4782 * ohci_insert_ctrl_req:
4783 *
4784 * Create a Transfer Descriptor (TD) and a data buffer for a control endpoint.
4785 */
4786 /* ARGSUSED */
4787 static void
ohci_insert_ctrl_req(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph,usb_ctrl_req_t * ctrl_reqp,ohci_trans_wrapper_t * tw,usb_flags_t usb_flags)4788 ohci_insert_ctrl_req(
4789 ohci_state_t *ohcip,
4790 usba_pipe_handle_data_t *ph,
4791 usb_ctrl_req_t *ctrl_reqp,
4792 ohci_trans_wrapper_t *tw,
4793 usb_flags_t usb_flags)
4794 {
4795 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
4796 uchar_t bmRequestType = ctrl_reqp->ctrl_bmRequestType;
4797 uchar_t bRequest = ctrl_reqp->ctrl_bRequest;
4798 uint16_t wValue = ctrl_reqp->ctrl_wValue;
4799 uint16_t wIndex = ctrl_reqp->ctrl_wIndex;
4800 uint16_t wLength = ctrl_reqp->ctrl_wLength;
4801 mblk_t *data = ctrl_reqp->ctrl_data;
4802 uint32_t ctrl = 0;
4803 int sdata;
4804
4805 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4806 "ohci_insert_ctrl_req:");
4807
4808 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4809
4810 /*
4811 * Save current control request pointer and timeout values
4812 * in transfer wrapper.
4813 */
4814 tw->tw_curr_xfer_reqp = (usb_opaque_t)ctrl_reqp;
4815 tw->tw_timeout = ctrl_reqp->ctrl_timeout ?
4816 ctrl_reqp->ctrl_timeout : OHCI_DEFAULT_XFER_TIMEOUT;
4817
4818 /*
4819 * Initialize the callback and any callback data for when
4820 * the td completes.
4821 */
4822 tw->tw_handle_td = ohci_handle_ctrl_td;
4823 tw->tw_handle_callback_value = NULL;
4824
4825 /* Create the first four bytes of the setup packet */
4826 sdata = (bmRequestType << 24) | (bRequest << 16) |
4827 (((wValue >> 8) | (wValue << 8)) & 0x0000FFFF);
4828
4829 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4830 "ohci_create_setup_pkt: sdata = 0x%x", sdata);
4831
4832 ddi_put32(tw->tw_accesshandle, (uint_t *)tw->tw_buf, sdata);
4833
4834 /* Create the second four bytes */
4835 sdata = (uint32_t)(((((wIndex >> 8) |
4836 (wIndex << 8)) << 16) & 0xFFFF0000) |
4837 (((wLength >> 8) | (wLength << 8)) & 0x0000FFFF));
4838
4839 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
4840 "ohci_create_setup_pkt: sdata = 0x%x", sdata);
4841
4842 ddi_put32(tw->tw_accesshandle,
4843 (uint_t *)((uintptr_t)tw->tw_buf + sizeof (uint_t)), sdata);
4844
4845 ctrl = HC_TD_SETUP|HC_TD_MS_DT|HC_TD_DT_0|HC_TD_6I;
4846
4847 /*
4848 * The TD's are placed on the ED one at a time.
4849 * Once this TD is placed on the done list, the
4850 * data or status phase TD will be enqueued.
4851 */
4852 (void) ohci_insert_hc_td(ohcip, ctrl, 0, SETUP_SIZE,
4853 OHCI_CTRL_SETUP_PHASE, pp, tw);
4854
4855 USB_DPRINTF_L3(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
4856 "Create_setup: pp 0x%p", (void *)pp);
4857
4858 /*
4859 * If this control transfer has a data phase, record the
4860 * direction. If the data phase is an OUT transaction,
4861 * copy the data into the buffer of the transfer wrapper.
4862 */
4863 if (wLength != 0) {
4864 /* There is a data stage. Find the direction */
4865 if (bmRequestType & USB_DEV_REQ_DEV_TO_HOST) {
4866 tw->tw_direction = HC_TD_IN;
4867 } else {
4868 tw->tw_direction = HC_TD_OUT;
4869
4870 /* Copy the data into the message */
4871 ddi_rep_put8(tw->tw_accesshandle, data->b_rptr,
4872 (uint8_t *)(tw->tw_buf + OHCI_MAX_TD_BUF_SIZE),
4873 wLength, DDI_DEV_AUTOINCR);
4874
4875 }
4876
4877 ctrl = (ctrl_reqp->ctrl_attributes & USB_ATTRS_SHORT_XFER_OK) ?
4878 HC_TD_R : 0;
4879
4880 /*
4881 * There is a data stage.
4882 * Find the direction.
4883 */
4884 if (tw->tw_direction == HC_TD_IN) {
4885 ctrl = ctrl|HC_TD_IN|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_6I;
4886 } else {
4887 ctrl = ctrl|HC_TD_OUT|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_6I;
4888 }
4889
4890 /*
4891 * Create the TD. If this is an OUT transaction,
4892 * the data is already in the buffer of the TW.
4893 */
4894 (void) ohci_insert_hc_td(ohcip, ctrl, OHCI_MAX_TD_BUF_SIZE,
4895 wLength, OHCI_CTRL_DATA_PHASE, pp, tw);
4896
4897 /*
4898 * The direction of the STATUS TD depends on
4899 * the direction of the transfer.
4900 */
4901 if (tw->tw_direction == HC_TD_IN) {
4902 ctrl = HC_TD_OUT|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_1I;
4903 } else {
4904 ctrl = HC_TD_IN|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_1I;
4905 }
4906 } else {
4907 ctrl = HC_TD_IN|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_1I;
4908 }
4909
4910 /* Status stage */
4911 (void) ohci_insert_hc_td(ohcip, ctrl, 0,
4912 0, OHCI_CTRL_STATUS_PHASE, pp, tw);
4913
4914 /* Indicate that the control list is filled */
4915 Set_OpReg(hcr_cmd_status, HCR_STATUS_CLF);
4916
4917 /* Start the timer for this control transfer */
4918 ohci_start_xfer_timer(ohcip, pp, tw);
4919 }
4920
4921 /*
4922 * ohci_allocate_bulk_resources:
4923 *
4924 * Calculates the number of tds necessary for a ctrl transfer, and allocates
4925 * all the resources necessary.
4926 *
4927 * Returns NULL if there is insufficient resources otherwise TW.
4928 */
4929 static ohci_trans_wrapper_t *
ohci_allocate_bulk_resources(ohci_state_t * ohcip,ohci_pipe_private_t * pp,usb_bulk_req_t * bulk_reqp,usb_flags_t usb_flags)4930 ohci_allocate_bulk_resources(
4931 ohci_state_t *ohcip,
4932 ohci_pipe_private_t *pp,
4933 usb_bulk_req_t *bulk_reqp,
4934 usb_flags_t usb_flags)
4935 {
4936 size_t td_count = 0;
4937 ohci_trans_wrapper_t *tw;
4938
4939 /* Check the size of bulk request */
4940 if (bulk_reqp->bulk_len > OHCI_MAX_BULK_XFER_SIZE) {
4941
4942 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4943 "ohci_allocate_bulk_resources: Bulk request size 0x%x is "
4944 "more than 0x%x", bulk_reqp->bulk_len,
4945 OHCI_MAX_BULK_XFER_SIZE);
4946
4947 return (NULL);
4948 }
4949
4950 /* Get the required bulk packet size */
4951 td_count = bulk_reqp->bulk_len / OHCI_MAX_TD_XFER_SIZE;
4952 if (bulk_reqp->bulk_len % OHCI_MAX_TD_XFER_SIZE ||
4953 bulk_reqp->bulk_len == 0) {
4954 td_count++;
4955 }
4956
4957 tw = ohci_allocate_tw_resources(ohcip, pp, bulk_reqp->bulk_len,
4958 usb_flags, td_count);
4959
4960 return (tw);
4961 }
4962
4963 /*
4964 * ohci_insert_bulk_req:
4965 *
4966 * Create a Transfer Descriptor (TD) and a data buffer for a bulk
4967 * endpoint.
4968 */
4969 /* ARGSUSED */
4970 static void
ohci_insert_bulk_req(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph,usb_bulk_req_t * bulk_reqp,ohci_trans_wrapper_t * tw,usb_flags_t flags)4971 ohci_insert_bulk_req(
4972 ohci_state_t *ohcip,
4973 usba_pipe_handle_data_t *ph,
4974 usb_bulk_req_t *bulk_reqp,
4975 ohci_trans_wrapper_t *tw,
4976 usb_flags_t flags)
4977 {
4978 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
4979 uint_t bulk_pkt_size, count;
4980 size_t residue = 0, len = 0;
4981 uint32_t ctrl = 0;
4982 int pipe_dir;
4983
4984 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4985 "ohci_insert_bulk_req: bulk_reqp = 0x%p flags = 0x%x",
4986 (void *)bulk_reqp, flags);
4987
4988 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4989
4990 /* Get the bulk pipe direction */
4991 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
4992
4993 /* Get the required bulk packet size */
4994 bulk_pkt_size = min(bulk_reqp->bulk_len, OHCI_MAX_TD_XFER_SIZE);
4995
4996 if (bulk_pkt_size)
4997 residue = tw->tw_length % bulk_pkt_size;
4998
4999 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5000 "ohci_insert_bulk_req: bulk_pkt_size = %d", bulk_pkt_size);
5001
5002 /*
5003 * Save current bulk request pointer and timeout values
5004 * in transfer wrapper.
5005 */
5006 tw->tw_curr_xfer_reqp = (usb_opaque_t)bulk_reqp;
5007 tw->tw_timeout = bulk_reqp->bulk_timeout;
5008
5009 /*
5010 * Initialize the callback and any callback
5011 * data required when the td completes.
5012 */
5013 tw->tw_handle_td = ohci_handle_bulk_td;
5014 tw->tw_handle_callback_value = NULL;
5015
5016 tw->tw_direction =
5017 (pipe_dir == USB_EP_DIR_OUT) ? HC_TD_OUT : HC_TD_IN;
5018
5019 if (tw->tw_direction == HC_TD_OUT && bulk_reqp->bulk_len) {
5020
5021 ASSERT(bulk_reqp->bulk_data != NULL);
5022
5023 /* Copy the data into the message */
5024 ddi_rep_put8(tw->tw_accesshandle,
5025 bulk_reqp->bulk_data->b_rptr, (uint8_t *)tw->tw_buf,
5026 bulk_reqp->bulk_len, DDI_DEV_AUTOINCR);
5027 }
5028
5029 ctrl = tw->tw_direction|HC_TD_DT_0|HC_TD_6I;
5030
5031 /* Insert all the bulk TDs */
5032 for (count = 0; count < tw->tw_num_tds; count++) {
5033
5034 /* Check for last td */
5035 if (count == (tw->tw_num_tds - 1)) {
5036
5037 ctrl = ((ctrl & ~HC_TD_DI) | HC_TD_1I);
5038
5039 /* Check for inserting residue data */
5040 if (residue) {
5041 bulk_pkt_size = (uint_t)residue;
5042 }
5043
5044 /*
5045 * Only set the round bit on the last TD, to ensure
5046 * the controller will always HALT the ED in case of
5047 * a short transfer.
5048 */
5049 if (bulk_reqp->bulk_attributes &
5050 USB_ATTRS_SHORT_XFER_OK) {
5051 ctrl |= HC_TD_R;
5052 }
5053 }
5054
5055 /* Insert the TD onto the endpoint */
5056 (void) ohci_insert_hc_td(ohcip, ctrl, len,
5057 bulk_pkt_size, 0, pp, tw);
5058
5059 len = len + bulk_pkt_size;
5060 }
5061
5062 /* Indicate that the bulk list is filled */
5063 Set_OpReg(hcr_cmd_status, HCR_STATUS_BLF);
5064
5065 /* Start the timer for this bulk transfer */
5066 ohci_start_xfer_timer(ohcip, pp, tw);
5067 }
5068
5069
5070 /*
5071 * ohci_start_periodic_pipe_polling:
5072 * NOTE: This function is also called from POLLED MODE.
5073 */
5074 int
ohci_start_periodic_pipe_polling(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph,usb_opaque_t periodic_in_reqp,usb_flags_t flags)5075 ohci_start_periodic_pipe_polling(
5076 ohci_state_t *ohcip,
5077 usba_pipe_handle_data_t *ph,
5078 usb_opaque_t periodic_in_reqp,
5079 usb_flags_t flags)
5080 {
5081 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5082 usb_ep_descr_t *eptd = &ph->p_ep;
5083 int error = USB_SUCCESS;
5084
5085 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5086 "ohci_start_periodic_pipe_polling: ep%d",
5087 ph->p_ep.bEndpointAddress & USB_EP_NUM_MASK);
5088
5089 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5090
5091 /*
5092 * Check and handle start polling on root hub interrupt pipe.
5093 */
5094 if ((ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) &&
5095 ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
5096 USB_EP_ATTR_INTR)) {
5097
5098 error = ohci_handle_root_hub_pipe_start_intr_polling(ph,
5099 (usb_intr_req_t *)periodic_in_reqp, flags);
5100
5101 return (error);
5102 }
5103
5104 switch (pp->pp_state) {
5105 case OHCI_PIPE_STATE_IDLE:
5106 /* Save the Original client's Periodic IN request */
5107 pp->pp_client_periodic_in_reqp = periodic_in_reqp;
5108
5109 /*
5110 * This pipe is uninitialized or if a valid TD is
5111 * not found then insert a TD on the interrupt or
5112 * isochronous IN endpoint.
5113 */
5114 error = ohci_start_pipe_polling(ohcip, ph, flags);
5115
5116 if (error != USB_SUCCESS) {
5117 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5118 "ohci_start_periodic_pipe_polling: "
5119 "Start polling failed");
5120
5121 pp->pp_client_periodic_in_reqp = NULL;
5122
5123 return (error);
5124 }
5125
5126 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
5127 "ohci_start_periodic_pipe_polling: PP = 0x%p", (void *)pp);
5128
5129 ASSERT((pp->pp_tw_head != NULL) && (pp->pp_tw_tail != NULL));
5130
5131 break;
5132 case OHCI_PIPE_STATE_ACTIVE:
5133 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5134 "ohci_start_periodic_pipe_polling: "
5135 "Polling is already in progress");
5136
5137 error = USB_FAILURE;
5138 break;
5139 case OHCI_PIPE_STATE_ERROR:
5140 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5141 "ohci_start_periodic_pipe_polling: "
5142 "Pipe is halted and perform reset before restart polling");
5143
5144 error = USB_FAILURE;
5145 break;
5146 default:
5147 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5148 "ohci_start_periodic_pipe_polling: Undefined state");
5149
5150 error = USB_FAILURE;
5151 break;
5152 }
5153
5154 return (error);
5155 }
5156
5157
5158 /*
5159 * ohci_start_pipe_polling:
5160 *
5161 * Insert the number of periodic requests corresponding to polling
5162 * interval as calculated during pipe open.
5163 */
5164 static int
ohci_start_pipe_polling(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph,usb_flags_t flags)5165 ohci_start_pipe_polling(
5166 ohci_state_t *ohcip,
5167 usba_pipe_handle_data_t *ph,
5168 usb_flags_t flags)
5169 {
5170 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5171 usb_ep_descr_t *eptd = &ph->p_ep;
5172 ohci_trans_wrapper_t *tw_list, *tw;
5173 int i, total_tws;
5174 int error = USB_SUCCESS;
5175
5176 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5177 "ohci_start_pipe_polling:");
5178
5179 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5180
5181 /*
5182 * For the start polling, pp_max_periodic_req_cnt will be zero
5183 * and for the restart polling request, it will be non zero.
5184 *
5185 * In case of start polling request, find out number of requests
5186 * required for the Interrupt IN endpoints corresponding to the
5187 * endpoint polling interval. For Isochronous IN endpoints, it is
5188 * always fixed since its polling interval will be one ms.
5189 */
5190 if (pp->pp_max_periodic_req_cnt == 0) {
5191
5192 ohci_set_periodic_pipe_polling(ohcip, ph);
5193 }
5194
5195 ASSERT(pp->pp_max_periodic_req_cnt != 0);
5196
5197 /* Allocate all the necessary resources for the IN transfer */
5198 tw_list = NULL;
5199 total_tws = pp->pp_max_periodic_req_cnt - pp->pp_cur_periodic_req_cnt;
5200 for (i = 0; i < total_tws; i++) {
5201 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
5202 case USB_EP_ATTR_INTR:
5203 tw = ohci_allocate_intr_resources(
5204 ohcip, ph, NULL, flags);
5205 break;
5206 case USB_EP_ATTR_ISOCH:
5207 tw = ohci_allocate_isoc_resources(
5208 ohcip, ph, NULL, flags);
5209 break;
5210 }
5211 if (tw == NULL) {
5212 error = USB_NO_RESOURCES;
5213 /* There are not enough resources, deallocate the TWs */
5214 tw = tw_list;
5215 while (tw != NULL) {
5216 tw_list = tw->tw_next;
5217 ohci_deallocate_periodic_in_resource(
5218 ohcip, pp, tw);
5219 ohci_deallocate_tw_resources(ohcip, pp, tw);
5220 tw = tw_list;
5221 }
5222 return (error);
5223 } else {
5224 if (tw_list == NULL) {
5225 tw_list = tw;
5226 }
5227 }
5228 }
5229
5230 i = 0;
5231 while (pp->pp_cur_periodic_req_cnt < pp->pp_max_periodic_req_cnt) {
5232
5233 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5234 "ohci_start_pipe_polling: max = %d curr = %d tw = %p:",
5235 pp->pp_max_periodic_req_cnt, pp->pp_cur_periodic_req_cnt,
5236 (void *)tw_list);
5237
5238 tw = tw_list;
5239 tw_list = tw->tw_next;
5240
5241 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
5242 case USB_EP_ATTR_INTR:
5243 ohci_insert_intr_req(ohcip, pp, tw, flags);
5244 break;
5245 case USB_EP_ATTR_ISOCH:
5246 error = ohci_insert_isoc_req(ohcip, pp, tw, flags);
5247 break;
5248 }
5249 if (error == USB_SUCCESS) {
5250 pp->pp_cur_periodic_req_cnt++;
5251 } else {
5252 /*
5253 * Deallocate the remaining tw
5254 * The current tw should have already been deallocated
5255 */
5256 tw = tw_list;
5257 while (tw != NULL) {
5258 tw_list = tw->tw_next;
5259 ohci_deallocate_periodic_in_resource(
5260 ohcip, pp, tw);
5261 ohci_deallocate_tw_resources(ohcip, pp, tw);
5262 tw = tw_list;
5263 }
5264 /*
5265 * If this is the first req return an error.
5266 * Otherwise return success.
5267 */
5268 if (i != 0) {
5269 error = USB_SUCCESS;
5270 }
5271
5272 break;
5273 }
5274 i++;
5275 }
5276
5277 return (error);
5278 }
5279
5280
5281 /*
5282 * ohci_set_periodic_pipe_polling:
5283 *
5284 * Calculate the number of periodic requests needed corresponding to the
5285 * interrupt/isochronous IN endpoints polling interval. Table below gives
5286 * the number of periodic requests needed for the interrupt/isochronous
5287 * IN endpoints according to endpoint polling interval.
5288 *
5289 * Polling interval Number of periodic requests
5290 *
5291 * 1ms 4
5292 * 2ms 2
5293 * 4ms to 32ms 1
5294 */
5295 static void
ohci_set_periodic_pipe_polling(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)5296 ohci_set_periodic_pipe_polling(
5297 ohci_state_t *ohcip,
5298 usba_pipe_handle_data_t *ph)
5299 {
5300 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5301 usb_ep_descr_t *endpoint = &ph->p_ep;
5302 uchar_t ep_attr = endpoint->bmAttributes;
5303 uint_t interval;
5304
5305 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5306 "ohci_set_periodic_pipe_polling:");
5307
5308 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5309
5310 pp->pp_cur_periodic_req_cnt = 0;
5311
5312 /*
5313 * Check usb flag whether USB_FLAGS_ONE_TIME_POLL flag is
5314 * set and if so, set pp->pp_max_periodic_req_cnt to one.
5315 */
5316 if (((ep_attr & USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR) &&
5317 (pp->pp_client_periodic_in_reqp)) {
5318 usb_intr_req_t *intr_reqp =
5319 (usb_intr_req_t *)pp->pp_client_periodic_in_reqp;
5320
5321 if (intr_reqp->intr_attributes &
5322 USB_ATTRS_ONE_XFER) {
5323
5324 pp->pp_max_periodic_req_cnt = INTR_XMS_REQS;
5325
5326 return;
5327 }
5328 }
5329
5330 mutex_enter(&ph->p_usba_device->usb_mutex);
5331
5332 /*
5333 * The ohci_adjust_polling_interval function will not fail
5334 * at this instance since bandwidth allocation is already
5335 * done. Here we are getting only the periodic interval.
5336 */
5337 interval = ohci_adjust_polling_interval(ohcip, endpoint,
5338 ph->p_usba_device->usb_port_status);
5339
5340 mutex_exit(&ph->p_usba_device->usb_mutex);
5341
5342 switch (interval) {
5343 case INTR_1MS_POLL:
5344 pp->pp_max_periodic_req_cnt = INTR_1MS_REQS;
5345 break;
5346 case INTR_2MS_POLL:
5347 pp->pp_max_periodic_req_cnt = INTR_2MS_REQS;
5348 break;
5349 default:
5350 pp->pp_max_periodic_req_cnt = INTR_XMS_REQS;
5351 break;
5352 }
5353
5354 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5355 "ohci_set_periodic_pipe_polling: Max periodic requests = %d",
5356 pp->pp_max_periodic_req_cnt);
5357 }
5358
5359 /*
5360 * ohci_allocate_intr_resources:
5361 *
5362 * Calculates the number of tds necessary for a intr transfer, and allocates
5363 * all the necessary resources.
5364 *
5365 * Returns NULL if there is insufficient resources otherwise TW.
5366 */
5367 static ohci_trans_wrapper_t *
ohci_allocate_intr_resources(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph,usb_intr_req_t * intr_reqp,usb_flags_t flags)5368 ohci_allocate_intr_resources(
5369 ohci_state_t *ohcip,
5370 usba_pipe_handle_data_t *ph,
5371 usb_intr_req_t *intr_reqp,
5372 usb_flags_t flags)
5373 {
5374 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5375 int pipe_dir;
5376 size_t td_count = 1;
5377 size_t tw_length;
5378 ohci_trans_wrapper_t *tw;
5379
5380 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5381 "ohci_allocate_intr_resources:");
5382
5383 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5384
5385 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
5386
5387 /* Get the length of interrupt transfer & alloc data */
5388 if (intr_reqp) {
5389 tw_length = intr_reqp->intr_len;
5390 } else {
5391 ASSERT(pipe_dir == USB_EP_DIR_IN);
5392 tw_length = (pp->pp_client_periodic_in_reqp) ?
5393 (((usb_intr_req_t *)pp->
5394 pp_client_periodic_in_reqp)->intr_len) :
5395 ph->p_ep.wMaxPacketSize;
5396 }
5397
5398 /* Check the size of interrupt request */
5399 if (tw_length > OHCI_MAX_TD_XFER_SIZE) {
5400
5401 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5402 "ohci_allocate_intr_resources: Intr request size 0x%lx is "
5403 "more than 0x%x", tw_length, OHCI_MAX_TD_XFER_SIZE);
5404
5405 return (NULL);
5406 }
5407
5408 if ((tw = ohci_allocate_tw_resources(ohcip, pp, tw_length,
5409 flags, td_count)) == NULL) {
5410
5411 return (NULL);
5412 }
5413
5414 if (pipe_dir == USB_EP_DIR_IN) {
5415 if (ohci_allocate_periodic_in_resource(ohcip, pp, tw, flags) !=
5416 USB_SUCCESS) {
5417
5418 ohci_deallocate_tw_resources(ohcip, pp, tw);
5419 return (NULL);
5420 }
5421 tw->tw_direction = HC_TD_IN;
5422 } else {
5423 if (tw_length) {
5424 ASSERT(intr_reqp->intr_data != NULL);
5425
5426 /* Copy the data into the message */
5427 ddi_rep_put8(tw->tw_accesshandle,
5428 intr_reqp->intr_data->b_rptr, (uint8_t *)tw->tw_buf,
5429 intr_reqp->intr_len, DDI_DEV_AUTOINCR);
5430 }
5431
5432 tw->tw_curr_xfer_reqp = (usb_opaque_t)intr_reqp;
5433 tw->tw_direction = HC_TD_OUT;
5434 }
5435
5436 if (intr_reqp) {
5437 tw->tw_timeout = intr_reqp->intr_timeout;
5438 }
5439
5440 /*
5441 * Initialize the callback and any callback
5442 * data required when the td completes.
5443 */
5444 tw->tw_handle_td = ohci_handle_intr_td;
5445 tw->tw_handle_callback_value = NULL;
5446
5447 return (tw);
5448 }
5449
5450 /*
5451 * ohci_insert_intr_req:
5452 *
5453 * Insert an Interrupt request into the Host Controller's periodic list.
5454 */
5455 /* ARGSUSED */
5456 static void
ohci_insert_intr_req(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,usb_flags_t flags)5457 ohci_insert_intr_req(
5458 ohci_state_t *ohcip,
5459 ohci_pipe_private_t *pp,
5460 ohci_trans_wrapper_t *tw,
5461 usb_flags_t flags)
5462 {
5463 usb_intr_req_t *curr_intr_reqp = NULL;
5464 uint_t ctrl = 0;
5465
5466 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5467
5468 ASSERT(tw->tw_curr_xfer_reqp != NULL);
5469
5470 /* Get the current interrupt request pointer */
5471 curr_intr_reqp = (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
5472
5473 ctrl = tw->tw_direction | HC_TD_DT_0 | HC_TD_1I;
5474
5475 if (curr_intr_reqp->intr_attributes & USB_ATTRS_SHORT_XFER_OK) {
5476 ctrl |= HC_TD_R;
5477 }
5478
5479 /* Insert another interrupt TD */
5480 (void) ohci_insert_hc_td(ohcip, ctrl, 0, tw->tw_length, 0, pp, tw);
5481
5482 /* Start the timer for this Interrupt transfer */
5483 ohci_start_xfer_timer(ohcip, pp, tw);
5484 }
5485
5486
5487 /*
5488 * ohci_stop_periodic_pipe_polling:
5489 */
5490 /* ARGSUSED */
5491 static int
ohci_stop_periodic_pipe_polling(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph,usb_flags_t flags)5492 ohci_stop_periodic_pipe_polling(
5493 ohci_state_t *ohcip,
5494 usba_pipe_handle_data_t *ph,
5495 usb_flags_t flags)
5496 {
5497 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5498 usb_ep_descr_t *eptd = &ph->p_ep;
5499
5500 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5501 "ohci_stop_periodic_pipe_polling: Flags = 0x%x", flags);
5502
5503 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5504
5505 /*
5506 * Check and handle stop polling on root hub interrupt pipe.
5507 */
5508 if ((ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) &&
5509 ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
5510 USB_EP_ATTR_INTR)) {
5511
5512 ohci_handle_root_hub_pipe_stop_intr_polling(
5513 ph, flags);
5514 return (USB_SUCCESS);
5515 }
5516
5517 if (pp->pp_state != OHCI_PIPE_STATE_ACTIVE) {
5518
5519 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5520 "ohci_stop_periodic_pipe_polling: Polling already stopped");
5521
5522 return (USB_SUCCESS);
5523 }
5524
5525 /* Set pipe state to pipe stop polling */
5526 pp->pp_state = OHCI_PIPE_STATE_STOP_POLLING;
5527
5528 ohci_pipe_cleanup(ohcip, ph);
5529
5530 return (USB_SUCCESS);
5531 }
5532
5533 /*
5534 * ohci_allocate_isoc_resources:
5535 *
5536 * Calculates the number of tds necessary for a intr transfer, and allocates
5537 * all the necessary resources.
5538 *
5539 * Returns NULL if there is insufficient resources otherwise TW.
5540 */
5541 static ohci_trans_wrapper_t *
ohci_allocate_isoc_resources(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph,usb_isoc_req_t * isoc_reqp,usb_flags_t flags)5542 ohci_allocate_isoc_resources(
5543 ohci_state_t *ohcip,
5544 usba_pipe_handle_data_t *ph,
5545 usb_isoc_req_t *isoc_reqp,
5546 usb_flags_t flags)
5547 {
5548 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5549 int pipe_dir;
5550 uint_t max_pkt_size = ph->p_ep.wMaxPacketSize;
5551 uint_t max_isoc_xfer_size;
5552 usb_isoc_pkt_descr_t *isoc_pkt_descr, *start_isoc_pkt_descr;
5553 ushort_t isoc_pkt_count;
5554 size_t count, td_count;
5555 size_t tw_length;
5556 size_t isoc_pkts_length;
5557 ohci_trans_wrapper_t *tw;
5558
5559
5560 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5561 "ohci_allocate_isoc_resources: flags = ox%x", flags);
5562
5563 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5564
5565 /*
5566 * Check whether pipe is in halted state.
5567 */
5568 if (pp->pp_state == OHCI_PIPE_STATE_ERROR) {
5569 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5570 "ohci_allocate_isoc_resources:"
5571 "Pipe is in error state, need pipe reset to continue");
5572
5573 return (NULL);
5574 }
5575
5576 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
5577
5578 /* Calculate the maximum isochronous transfer size */
5579 max_isoc_xfer_size = OHCI_MAX_ISOC_PKTS_PER_XFER * max_pkt_size;
5580
5581 if (isoc_reqp) {
5582 isoc_pkt_descr = isoc_reqp->isoc_pkt_descr;
5583 isoc_pkt_count = isoc_reqp->isoc_pkts_count;
5584 isoc_pkts_length = isoc_reqp->isoc_pkts_length;
5585 } else {
5586 isoc_pkt_descr = ((usb_isoc_req_t *)
5587 pp->pp_client_periodic_in_reqp)->isoc_pkt_descr;
5588
5589 isoc_pkt_count = ((usb_isoc_req_t *)
5590 pp->pp_client_periodic_in_reqp)->isoc_pkts_count;
5591
5592 isoc_pkts_length = ((usb_isoc_req_t *)
5593 pp->pp_client_periodic_in_reqp)->isoc_pkts_length;
5594 }
5595
5596 start_isoc_pkt_descr = isoc_pkt_descr;
5597
5598 /*
5599 * For isochronous IN pipe, get value of number of isochronous
5600 * packets per usb isochronous request
5601 */
5602 if (pipe_dir == USB_EP_DIR_IN) {
5603 for (count = 0, tw_length = 0;
5604 count < isoc_pkt_count; count++) {
5605 tw_length += isoc_pkt_descr->isoc_pkt_length;
5606 isoc_pkt_descr++;
5607 }
5608
5609 if ((isoc_pkts_length) && (isoc_pkts_length != tw_length)) {
5610
5611 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5612 "ohci_allocate_isoc_resources: "
5613 "isoc_pkts_length 0x%lx is not equal to the sum of "
5614 "all pkt lengths 0x%lx in an isoc request",
5615 isoc_pkts_length, tw_length);
5616
5617 return (NULL);
5618 }
5619
5620 } else {
5621 ASSERT(isoc_reqp != NULL);
5622 tw_length = MBLKL(isoc_reqp->isoc_data);
5623 }
5624
5625 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5626 "ohci_allocate_isoc_resources: length = 0x%lx", tw_length);
5627
5628 /* Check the size of isochronous request */
5629 if (tw_length > max_isoc_xfer_size) {
5630
5631 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5632 "ohci_allocate_isoc_resources: Maximum isoc request"
5633 "size 0x%x Given isoc request size 0x%lx",
5634 max_isoc_xfer_size, tw_length);
5635
5636 return (NULL);
5637 }
5638
5639 /*
5640 * Each isochronous TD can hold data upto eight isochronous
5641 * data packets. Calculate the number of isochronous TDs needs
5642 * to be insert to complete current isochronous request.
5643 */
5644 td_count = isoc_pkt_count / OHCI_ISOC_PKTS_PER_TD;
5645
5646 if (isoc_pkt_count % OHCI_ISOC_PKTS_PER_TD) {
5647 td_count++;
5648 }
5649
5650 tw = ohci_create_isoc_transfer_wrapper(ohcip, pp, tw_length,
5651 start_isoc_pkt_descr, isoc_pkt_count, td_count, flags);
5652
5653 if (tw == NULL) {
5654 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5655 "ohci_create_isoc_transfer_wrapper: "
5656 "Unable to allocate TW");
5657
5658 return (NULL);
5659 }
5660
5661 if (ohci_allocate_tds_for_tw(ohcip, tw, td_count) ==
5662 USB_SUCCESS) {
5663 tw->tw_num_tds = (uint_t)td_count;
5664 } else {
5665 ohci_deallocate_tw_resources(ohcip, pp, tw);
5666
5667 return (NULL);
5668 }
5669
5670 if (pipe_dir == USB_EP_DIR_IN) {
5671 if (ohci_allocate_periodic_in_resource(ohcip, pp, tw, flags) !=
5672 USB_SUCCESS) {
5673
5674 ohci_deallocate_tw_resources(ohcip, pp, tw);
5675 return (NULL);
5676 }
5677 tw->tw_direction = HC_TD_IN;
5678 } else {
5679 if (tw->tw_length) {
5680 uchar_t *p;
5681 int i;
5682
5683 ASSERT(isoc_reqp->isoc_data != NULL);
5684 p = isoc_reqp->isoc_data->b_rptr;
5685
5686 /* Copy the data into the message */
5687 for (i = 0; i < td_count; i++) {
5688 ddi_rep_put8(
5689 tw->tw_isoc_bufs[i].mem_handle, p,
5690 (uint8_t *)tw->tw_isoc_bufs[i].buf_addr,
5691 tw->tw_isoc_bufs[i].length,
5692 DDI_DEV_AUTOINCR);
5693 p += tw->tw_isoc_bufs[i].length;
5694 }
5695 }
5696 tw->tw_curr_xfer_reqp = (usb_opaque_t)isoc_reqp;
5697 tw->tw_direction = HC_TD_OUT;
5698 }
5699
5700 /*
5701 * Initialize the callback and any callback
5702 * data required when the td completes.
5703 */
5704 tw->tw_handle_td = ohci_handle_isoc_td;
5705 tw->tw_handle_callback_value = NULL;
5706
5707 return (tw);
5708 }
5709
5710 /*
5711 * ohci_insert_isoc_req:
5712 *
5713 * Insert an isochronous request into the Host Controller's
5714 * isochronous list. If there is an error is will appropriately
5715 * deallocate the unused resources.
5716 */
5717 static int
ohci_insert_isoc_req(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,uint_t flags)5718 ohci_insert_isoc_req(
5719 ohci_state_t *ohcip,
5720 ohci_pipe_private_t *pp,
5721 ohci_trans_wrapper_t *tw,
5722 uint_t flags)
5723 {
5724 size_t curr_isoc_xfer_offset, curr_isoc_xfer_len;
5725 uint_t isoc_pkts, residue, count;
5726 uint_t i, ctrl, frame_count;
5727 uint_t error = USB_SUCCESS;
5728 usb_isoc_req_t *curr_isoc_reqp;
5729 usb_isoc_pkt_descr_t *curr_isoc_pkt_descr;
5730
5731 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5732 "ohci_insert_isoc_req: flags = 0x%x", flags);
5733
5734 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5735
5736 /*
5737 * Get the current isochronous request and packet
5738 * descriptor pointers.
5739 */
5740 curr_isoc_reqp = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
5741 curr_isoc_pkt_descr = curr_isoc_reqp->isoc_pkt_descr;
5742
5743 ASSERT(curr_isoc_reqp != NULL);
5744 ASSERT(curr_isoc_reqp->isoc_pkt_descr != NULL);
5745
5746 /*
5747 * Save address of first usb isochronous packet descriptor.
5748 */
5749 tw->tw_curr_isoc_pktp = curr_isoc_reqp->isoc_pkt_descr;
5750
5751 /* Insert all the isochronous TDs */
5752 for (count = 0, curr_isoc_xfer_offset = 0,
5753 isoc_pkts = 0; count < tw->tw_num_tds; count++) {
5754
5755 residue = curr_isoc_reqp->isoc_pkts_count - isoc_pkts;
5756
5757 /* Check for inserting residue data */
5758 if ((count == (tw->tw_num_tds - 1)) &&
5759 (residue < OHCI_ISOC_PKTS_PER_TD)) {
5760 frame_count = residue;
5761 } else {
5762 frame_count = OHCI_ISOC_PKTS_PER_TD;
5763 }
5764
5765 curr_isoc_pkt_descr = tw->tw_curr_isoc_pktp;
5766
5767 /*
5768 * Calculate length of isochronous transfer
5769 * for the current TD.
5770 */
5771 for (i = 0, curr_isoc_xfer_len = 0;
5772 i < frame_count; i++, curr_isoc_pkt_descr++) {
5773 curr_isoc_xfer_len +=
5774 curr_isoc_pkt_descr->isoc_pkt_length;
5775 }
5776
5777 /*
5778 * Programm td control field by checking whether this
5779 * is last td.
5780 */
5781 if (count == (tw->tw_num_tds - 1)) {
5782 ctrl = ((((frame_count - 1) << HC_ITD_FC_SHIFT) &
5783 HC_ITD_FC) | HC_TD_DT_0 | HC_TD_0I);
5784 } else {
5785 ctrl = ((((frame_count - 1) << HC_ITD_FC_SHIFT) &
5786 HC_ITD_FC) | HC_TD_DT_0 | HC_TD_6I);
5787 }
5788
5789 /* Insert the TD into the endpoint */
5790 if ((error = ohci_insert_hc_td(ohcip, ctrl, count,
5791 curr_isoc_xfer_len, 0, pp, tw)) !=
5792 USB_SUCCESS) {
5793 tw->tw_num_tds = count;
5794 tw->tw_length = curr_isoc_xfer_offset;
5795 break;
5796 }
5797
5798 isoc_pkts += frame_count;
5799 tw->tw_curr_isoc_pktp += frame_count;
5800 curr_isoc_xfer_offset += curr_isoc_xfer_len;
5801 }
5802
5803 if (error != USB_SUCCESS) {
5804 /* Free periodic in resources */
5805 if (tw->tw_direction == USB_EP_DIR_IN) {
5806 ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
5807 }
5808
5809 /* Free all resources if IN or if count == 0(for both IN/OUT) */
5810 if (tw->tw_direction == USB_EP_DIR_IN || count == 0) {
5811
5812 ohci_deallocate_tw_resources(ohcip, pp, tw);
5813
5814 if (pp->pp_cur_periodic_req_cnt) {
5815 /*
5816 * Set pipe state to stop polling and
5817 * error to no resource. Don't insert
5818 * any more isochronous polling requests.
5819 */
5820 pp->pp_state = OHCI_PIPE_STATE_STOP_POLLING;
5821 pp->pp_error = error;
5822 } else {
5823 /* Set periodic in pipe state to idle */
5824 pp->pp_state = OHCI_PIPE_STATE_IDLE;
5825 }
5826 }
5827 } else {
5828
5829 /*
5830 * Reset back to the address of first usb isochronous
5831 * packet descriptor.
5832 */
5833 tw->tw_curr_isoc_pktp = curr_isoc_reqp->isoc_pkt_descr;
5834
5835 /* Reset the CONTINUE flag */
5836 pp->pp_flag &= ~OHCI_ISOC_XFER_CONTINUE;
5837 }
5838
5839 return (error);
5840 }
5841
5842
5843 /*
5844 * ohci_insert_hc_td:
5845 *
5846 * Insert a Transfer Descriptor (TD) on an Endpoint Descriptor (ED).
5847 * Always returns USB_SUCCESS, except for ISOCH.
5848 */
5849 static int
ohci_insert_hc_td(ohci_state_t * ohcip,uint_t hctd_ctrl,uint32_t hctd_dma_offs,size_t hctd_length,uint32_t hctd_ctrl_phase,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw)5850 ohci_insert_hc_td(
5851 ohci_state_t *ohcip,
5852 uint_t hctd_ctrl,
5853 uint32_t hctd_dma_offs,
5854 size_t hctd_length,
5855 uint32_t hctd_ctrl_phase,
5856 ohci_pipe_private_t *pp,
5857 ohci_trans_wrapper_t *tw)
5858 {
5859 ohci_td_t *new_dummy;
5860 ohci_td_t *cpu_current_dummy;
5861 ohci_ed_t *ept = pp->pp_ept;
5862 int error;
5863
5864 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5865
5866 /* Retrieve preallocated td from the TW */
5867 new_dummy = tw->tw_hctd_free_list;
5868
5869 ASSERT(new_dummy != NULL);
5870
5871 tw->tw_hctd_free_list = ohci_td_iommu_to_cpu(ohcip,
5872 Get_TD(new_dummy->hctd_tw_next_td));
5873 Set_TD(new_dummy->hctd_tw_next_td, NULL);
5874
5875 /* Fill in the current dummy */
5876 cpu_current_dummy = (ohci_td_t *)
5877 (ohci_td_iommu_to_cpu(ohcip, Get_ED(ept->hced_tailp)));
5878
5879 /*
5880 * Fill in the current dummy td and
5881 * add the new dummy to the end.
5882 */
5883 ohci_fill_in_td(ohcip, cpu_current_dummy, new_dummy,
5884 hctd_ctrl, hctd_dma_offs, hctd_length, hctd_ctrl_phase, pp, tw);
5885
5886 /*
5887 * If this is an isochronous TD, first write proper
5888 * starting usb frame number in which this TD must
5889 * can be processed. After writing the frame number
5890 * insert this TD into the ED's list.
5891 */
5892 if ((pp->pp_pipe_handle->p_ep.bmAttributes &
5893 USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH) {
5894
5895 error = ohci_insert_td_with_frame_number(
5896 ohcip, pp, tw, cpu_current_dummy, new_dummy);
5897
5898 if (error != USB_SUCCESS) {
5899 /* Reset the current dummy back to a dummy */
5900 bzero((char *)cpu_current_dummy, sizeof (ohci_td_t));
5901 Set_TD(cpu_current_dummy->hctd_state, HC_TD_DUMMY);
5902
5903 /* return the new dummy back to the free list */
5904 bzero((char *)new_dummy, sizeof (ohci_td_t));
5905 Set_TD(new_dummy->hctd_state, HC_TD_DUMMY);
5906 if (tw->tw_hctd_free_list != NULL) {
5907 Set_TD(new_dummy->hctd_tw_next_td,
5908 ohci_td_cpu_to_iommu(ohcip,
5909 tw->tw_hctd_free_list));
5910 }
5911 tw->tw_hctd_free_list = new_dummy;
5912
5913 return (error);
5914 }
5915 } else {
5916 /*
5917 * For control, bulk and interrupt TD, just
5918 * add the new dummy to the ED's list. When
5919 * this occurs, the Host Controller ill see
5920 * the newly filled in dummy TD.
5921 */
5922 Set_ED(ept->hced_tailp,
5923 (ohci_td_cpu_to_iommu(ohcip, new_dummy)));
5924 }
5925
5926 /* Insert this td onto the tw */
5927 ohci_insert_td_on_tw(ohcip, tw, cpu_current_dummy);
5928
5929 return (USB_SUCCESS);
5930 }
5931
5932
5933 /*
5934 * ohci_allocate_td_from_pool:
5935 *
5936 * Allocate a Transfer Descriptor (TD) from the TD buffer pool.
5937 */
5938 static ohci_td_t *
ohci_allocate_td_from_pool(ohci_state_t * ohcip)5939 ohci_allocate_td_from_pool(ohci_state_t *ohcip)
5940 {
5941 int i, state;
5942 ohci_td_t *td;
5943
5944 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5945
5946 /*
5947 * Search for a blank Transfer Descriptor (TD)
5948 * in the TD buffer pool.
5949 */
5950 for (i = 0; i < ohci_td_pool_size; i ++) {
5951 state = Get_TD(ohcip->ohci_td_pool_addr[i].hctd_state);
5952 if (state == HC_TD_FREE) {
5953 break;
5954 }
5955 }
5956
5957 if (i >= ohci_td_pool_size) {
5958 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
5959 "ohci_allocate_td_from_pool: TD exhausted");
5960
5961 return (NULL);
5962 }
5963
5964 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
5965 "ohci_allocate_td_from_pool: Allocated %d", i);
5966
5967 /* Create a new dummy for the end of the TD list */
5968 td = &ohcip->ohci_td_pool_addr[i];
5969
5970 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5971 "ohci_allocate_td_from_pool: td 0x%p", (void *)td);
5972
5973 /* Mark the newly allocated TD as a dummy */
5974 Set_TD(td->hctd_state, HC_TD_DUMMY);
5975
5976 return (td);
5977 }
5978
5979 /*
5980 * ohci_fill_in_td:
5981 *
5982 * Fill in the fields of a Transfer Descriptor (TD).
5983 *
5984 * hctd_dma_offs - different meanings for non-isoc and isoc TDs:
5985 * starting offset into the TW buffer for a non-isoc TD
5986 * and the index into the isoc TD list for an isoc TD.
5987 * For non-isoc TDs, the starting offset should be 4k
5988 * aligned and the TDs in one transfer must be filled in
5989 * increasing order.
5990 */
5991 static void
ohci_fill_in_td(ohci_state_t * ohcip,ohci_td_t * td,ohci_td_t * new_dummy,uint_t hctd_ctrl,uint32_t hctd_dma_offs,size_t hctd_length,uint32_t hctd_ctrl_phase,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw)5992 ohci_fill_in_td(
5993 ohci_state_t *ohcip,
5994 ohci_td_t *td,
5995 ohci_td_t *new_dummy,
5996 uint_t hctd_ctrl,
5997 uint32_t hctd_dma_offs,
5998 size_t hctd_length,
5999 uint32_t hctd_ctrl_phase,
6000 ohci_pipe_private_t *pp,
6001 ohci_trans_wrapper_t *tw)
6002 {
6003 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6004 "ohci_fill_in_td: td 0x%p bufoffs 0x%x len 0x%lx",
6005 (void *)td, hctd_dma_offs, hctd_length);
6006
6007 /* Assert that the td to be filled in is a dummy */
6008 ASSERT(Get_TD(td->hctd_state) == HC_TD_DUMMY);
6009
6010 /* Change TD's state Active */
6011 Set_TD(td->hctd_state, HC_TD_ACTIVE);
6012
6013 /* Update the TD special fields */
6014 if ((pp->pp_pipe_handle->p_ep.bmAttributes &
6015 USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH) {
6016 ohci_init_itd(ohcip, tw, hctd_ctrl, hctd_dma_offs, td);
6017 } else {
6018 /* Update the dummy with control information */
6019 Set_TD(td->hctd_ctrl, (hctd_ctrl | HC_TD_CC_NA));
6020
6021 ohci_init_td(ohcip, tw, hctd_dma_offs, hctd_length, td);
6022 }
6023
6024 /* The current dummy now points to the new dummy */
6025 Set_TD(td->hctd_next_td, (ohci_td_cpu_to_iommu(ohcip, new_dummy)));
6026
6027 /*
6028 * For Control transfer, hctd_ctrl_phase is a valid field.
6029 */
6030 if (hctd_ctrl_phase) {
6031 Set_TD(td->hctd_ctrl_phase, hctd_ctrl_phase);
6032 }
6033
6034 /* Print the td */
6035 ohci_print_td(ohcip, td);
6036
6037 /* Fill in the wrapper portion of the TD */
6038
6039 /* Set the transfer wrapper */
6040 ASSERT(tw != NULL);
6041 ASSERT(tw->tw_id != 0);
6042
6043 Set_TD(td->hctd_trans_wrapper, tw->tw_id);
6044 Set_TD(td->hctd_tw_next_td, NULL);
6045 }
6046
6047
6048 /*
6049 * ohci_init_td:
6050 *
6051 * Initialize the buffer address portion of non-isoc Transfer
6052 * Descriptor (TD).
6053 */
6054 void
ohci_init_td(ohci_state_t * ohcip,ohci_trans_wrapper_t * tw,uint32_t hctd_dma_offs,size_t hctd_length,ohci_td_t * td)6055 ohci_init_td(
6056 ohci_state_t *ohcip,
6057 ohci_trans_wrapper_t *tw,
6058 uint32_t hctd_dma_offs,
6059 size_t hctd_length,
6060 ohci_td_t *td)
6061 {
6062 uint32_t page_addr, start_addr = 0, end_addr = 0;
6063 size_t buf_len = hctd_length;
6064 int rem_len, i;
6065
6066 /*
6067 * TDs must be filled in increasing DMA offset order.
6068 * tw_dma_offs is initialized to be 0 at TW creation and
6069 * is only increased in this function.
6070 */
6071 ASSERT(buf_len == 0 || hctd_dma_offs >= tw->tw_dma_offs);
6072
6073 Set_TD(td->hctd_xfer_offs, hctd_dma_offs);
6074 Set_TD(td->hctd_xfer_len, buf_len);
6075
6076 /* Computing the starting buffer address and end buffer address */
6077 for (i = 0; (i < 2) && (buf_len > 0); i++) {
6078 /* Advance to the next DMA cookie if necessary */
6079 if ((tw->tw_dma_offs + tw->tw_cookie.dmac_size) <=
6080 hctd_dma_offs) {
6081 /*
6082 * tw_dma_offs always points to the starting offset
6083 * of a cookie
6084 */
6085 tw->tw_dma_offs += tw->tw_cookie.dmac_size;
6086 ddi_dma_nextcookie(tw->tw_dmahandle, &tw->tw_cookie);
6087 tw->tw_cookie_idx++;
6088 ASSERT(tw->tw_cookie_idx < tw->tw_ncookies);
6089 }
6090
6091 ASSERT((tw->tw_dma_offs + tw->tw_cookie.dmac_size) >
6092 hctd_dma_offs);
6093
6094 /*
6095 * Counting the remained buffer length to be filled in
6096 * the TD for current DMA cookie
6097 */
6098 rem_len = (tw->tw_dma_offs + tw->tw_cookie.dmac_size) -
6099 hctd_dma_offs;
6100
6101 /* Get the beginning address of the buffer */
6102 page_addr = (hctd_dma_offs - tw->tw_dma_offs) +
6103 tw->tw_cookie.dmac_address;
6104 ASSERT((page_addr % OHCI_4K_ALIGN) == 0);
6105
6106 if (i == 0) {
6107 start_addr = page_addr;
6108 }
6109
6110 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6111 "ohci_init_td: page_addr 0x%x dmac_size "
6112 "0x%lx idx %d", page_addr, tw->tw_cookie.dmac_size,
6113 tw->tw_cookie_idx);
6114
6115 if (buf_len <= OHCI_MAX_TD_BUF_SIZE) {
6116 ASSERT(buf_len <= rem_len);
6117 end_addr = page_addr + buf_len - 1;
6118 buf_len = 0;
6119 break;
6120 } else {
6121 ASSERT(rem_len >= OHCI_MAX_TD_BUF_SIZE);
6122 buf_len -= OHCI_MAX_TD_BUF_SIZE;
6123 hctd_dma_offs += OHCI_MAX_TD_BUF_SIZE;
6124 }
6125 }
6126
6127 ASSERT(buf_len == 0);
6128
6129 Set_TD(td->hctd_cbp, start_addr);
6130 Set_TD(td->hctd_buf_end, end_addr);
6131 }
6132
6133
6134 /*
6135 * ohci_init_itd:
6136 *
6137 * Initialize the buffer address portion of isoc Transfer Descriptor (TD).
6138 */
6139 static void
ohci_init_itd(ohci_state_t * ohcip,ohci_trans_wrapper_t * tw,uint_t hctd_ctrl,uint32_t index,ohci_td_t * td)6140 ohci_init_itd(
6141 ohci_state_t *ohcip,
6142 ohci_trans_wrapper_t *tw,
6143 uint_t hctd_ctrl,
6144 uint32_t index,
6145 ohci_td_t *td)
6146 {
6147 uint32_t start_addr, end_addr, offset, offset_addr;
6148 ohci_isoc_buf_t *bufp;
6149 size_t buf_len;
6150 uint_t buf, fc, toggle, flag;
6151 usb_isoc_pkt_descr_t *temp_pkt_descr;
6152 int i;
6153
6154 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6155
6156 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6157 "ohci_init_itd: ctrl = 0x%x", hctd_ctrl);
6158
6159 /*
6160 * Write control information except starting
6161 * usb frame number.
6162 */
6163 Set_TD(td->hctd_ctrl, (hctd_ctrl | HC_TD_CC_NA));
6164
6165 bufp = &tw->tw_isoc_bufs[index];
6166 Set_TD(td->hctd_xfer_offs, index);
6167 Set_TD(td->hctd_xfer_len, bufp->length);
6168
6169 start_addr = bufp->cookie.dmac_address;
6170 ASSERT((start_addr % OHCI_4K_ALIGN) == 0);
6171
6172 buf_len = bufp->length;
6173 if (bufp->ncookies == OHCI_DMA_ATTR_TD_SGLLEN) {
6174 buf_len = bufp->length - bufp->cookie.dmac_size;
6175 ddi_dma_nextcookie(bufp->dma_handle, &bufp->cookie);
6176 }
6177 end_addr = bufp->cookie.dmac_address + buf_len - 1;
6178
6179 /*
6180 * For an isochronous transfer, the hctd_cbp contains,
6181 * the 4k page, and not the actual start of the buffer.
6182 */
6183 Set_TD(td->hctd_cbp, ((uint32_t)start_addr & HC_ITD_PAGE_MASK));
6184 Set_TD(td->hctd_buf_end, end_addr);
6185
6186 fc = (hctd_ctrl & HC_ITD_FC) >> HC_ITD_FC_SHIFT;
6187 toggle = 0;
6188 buf = start_addr;
6189
6190 /*
6191 * Get the address of first isochronous data packet
6192 * for the current isochronous TD.
6193 */
6194 temp_pkt_descr = tw->tw_curr_isoc_pktp;
6195
6196 /* The offsets are actually offsets into the page */
6197 for (i = 0; i <= fc; i++) {
6198 offset_addr = (uint32_t)((buf &
6199 HC_ITD_OFFSET_ADDR) | (HC_ITD_OFFSET_CC));
6200
6201 flag = ((start_addr &
6202 HC_ITD_PAGE_MASK) ^ (buf & HC_ITD_PAGE_MASK));
6203
6204 if (flag) {
6205 offset_addr |= HC_ITD_4KBOUNDARY_CROSS;
6206 }
6207
6208 if (toggle) {
6209 offset = (uint32_t)((offset_addr <<
6210 HC_ITD_OFFSET_SHIFT) & HC_ITD_ODD_OFFSET);
6211
6212 Set_TD(td->hctd_offsets[i / 2],
6213 Get_TD(td->hctd_offsets[i / 2]) | offset);
6214 toggle = 0;
6215 } else {
6216 offset = (uint32_t)(offset_addr & HC_ITD_EVEN_OFFSET);
6217
6218 Set_TD(td->hctd_offsets[i / 2],
6219 Get_TD(td->hctd_offsets[i / 2]) | offset);
6220 toggle = 1;
6221 }
6222
6223 buf = (uint32_t)(buf + temp_pkt_descr->isoc_pkt_length);
6224 temp_pkt_descr++;
6225 }
6226 }
6227
6228
6229 /*
6230 * ohci_insert_td_with_frame_number:
6231 *
6232 * Insert current isochronous TD into the ED's list. with proper
6233 * usb frame number in which this TD can be processed.
6234 */
6235 static int
ohci_insert_td_with_frame_number(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,ohci_td_t * current_td,ohci_td_t * dummy_td)6236 ohci_insert_td_with_frame_number(
6237 ohci_state_t *ohcip,
6238 ohci_pipe_private_t *pp,
6239 ohci_trans_wrapper_t *tw,
6240 ohci_td_t *current_td,
6241 ohci_td_t *dummy_td)
6242 {
6243 usb_isoc_req_t *isoc_reqp =
6244 (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
6245 usb_frame_number_t current_frame_number, start_frame_number;
6246 uint_t ddic, ctrl, isoc_pkts;
6247 ohci_ed_t *ept = pp->pp_ept;
6248
6249 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6250 "ohci_insert_td_with_frame_number:"
6251 "isoc flags 0x%x", isoc_reqp->isoc_attributes);
6252
6253 /* Get the TD ctrl information */
6254 isoc_pkts = ((Get_TD(current_td->hctd_ctrl) &
6255 HC_ITD_FC) >> HC_ITD_FC_SHIFT) + 1;
6256
6257 /*
6258 * Enter critical, while programming the usb frame number
6259 * and inserting current isochronous TD into the ED's list.
6260 */
6261 ddic = ddi_enter_critical();
6262
6263 /* Get the current frame number */
6264 current_frame_number = ohci_get_current_frame_number(ohcip);
6265
6266 /* Check the given isochronous flags */
6267 switch (isoc_reqp->isoc_attributes &
6268 (USB_ATTRS_ISOC_START_FRAME | USB_ATTRS_ISOC_XFER_ASAP)) {
6269 case USB_ATTRS_ISOC_START_FRAME:
6270 /* Starting frame number is specified */
6271 if (pp->pp_flag & OHCI_ISOC_XFER_CONTINUE) {
6272 /* Get the starting usb frame number */
6273 start_frame_number = pp->pp_next_frame_number;
6274 } else {
6275 /* Check for the Starting usb frame number */
6276 if ((isoc_reqp->isoc_frame_no == 0) ||
6277 ((isoc_reqp->isoc_frame_no +
6278 isoc_reqp->isoc_pkts_count) <
6279 current_frame_number)) {
6280
6281 /* Exit the critical */
6282 ddi_exit_critical(ddic);
6283
6284 USB_DPRINTF_L2(PRINT_MASK_LISTS,
6285 ohcip->ohci_log_hdl,
6286 "ohci_insert_td_with_frame_number:"
6287 "Invalid starting frame number");
6288
6289 return (USB_INVALID_START_FRAME);
6290 }
6291
6292 /* Get the starting usb frame number */
6293 start_frame_number = isoc_reqp->isoc_frame_no;
6294
6295 pp->pp_next_frame_number = 0;
6296 }
6297 break;
6298 case USB_ATTRS_ISOC_XFER_ASAP:
6299 /* ohci has to specify starting frame number */
6300 if ((pp->pp_next_frame_number) &&
6301 (pp->pp_next_frame_number > current_frame_number)) {
6302 /*
6303 * Get the next usb frame number.
6304 */
6305 start_frame_number = pp->pp_next_frame_number;
6306 } else {
6307 /*
6308 * Add appropriate offset to the current usb
6309 * frame number and use it as a starting frame
6310 * number.
6311 */
6312 start_frame_number =
6313 current_frame_number + OHCI_FRAME_OFFSET;
6314 }
6315
6316 if (!(pp->pp_flag & OHCI_ISOC_XFER_CONTINUE)) {
6317 isoc_reqp->isoc_frame_no = start_frame_number;
6318 }
6319 break;
6320 default:
6321 /* Exit the critical */
6322 ddi_exit_critical(ddic);
6323
6324 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6325 "ohci_insert_td_with_frame_number: Either starting "
6326 "frame number or ASAP flags are not set, attrs = 0x%x",
6327 isoc_reqp->isoc_attributes);
6328
6329 return (USB_NO_FRAME_NUMBER);
6330 }
6331
6332 /* Get the TD ctrl information */
6333 ctrl = Get_TD(current_td->hctd_ctrl) & (~(HC_ITD_SF));
6334
6335 /* Set the frame number field */
6336 Set_TD(current_td->hctd_ctrl, ctrl | (start_frame_number & HC_ITD_SF));
6337
6338 /*
6339 * Add the new dummy to the ED's list. When this occurs,
6340 * the Host Controller will see newly filled in dummy TD.
6341 */
6342 Set_ED(ept->hced_tailp, (ohci_td_cpu_to_iommu(ohcip, dummy_td)));
6343
6344 /* Exit the critical */
6345 ddi_exit_critical(ddic);
6346
6347 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6348 "ohci_insert_td_with_frame_number:"
6349 "current frame number 0x%llx start frame number 0x%llx",
6350 (unsigned long long)current_frame_number,
6351 (unsigned long long)start_frame_number);
6352
6353 /*
6354 * Increment this saved frame number by current number
6355 * of data packets needs to be transfer.
6356 */
6357 pp->pp_next_frame_number = start_frame_number + isoc_pkts;
6358
6359 /*
6360 * Set OHCI_ISOC_XFER_CONTINUE flag in order to send other
6361 * isochronous packets, part of the current isoch request
6362 * in the subsequent frames.
6363 */
6364 pp->pp_flag |= OHCI_ISOC_XFER_CONTINUE;
6365
6366 return (USB_SUCCESS);
6367 }
6368
6369
6370 /*
6371 * ohci_insert_td_on_tw:
6372 *
6373 * The transfer wrapper keeps a list of all Transfer Descriptors (TD) that
6374 * are allocated for this transfer. Insert a TD onto this list. The list
6375 * of TD's does not include the dummy TD that is at the end of the list of
6376 * TD's for the endpoint.
6377 */
6378 static void
ohci_insert_td_on_tw(ohci_state_t * ohcip,ohci_trans_wrapper_t * tw,ohci_td_t * td)6379 ohci_insert_td_on_tw(
6380 ohci_state_t *ohcip,
6381 ohci_trans_wrapper_t *tw,
6382 ohci_td_t *td)
6383 {
6384 /*
6385 * Set the next pointer to NULL because
6386 * this is the last TD on list.
6387 */
6388 Set_TD(td->hctd_tw_next_td, NULL);
6389
6390 if (tw->tw_hctd_head == NULL) {
6391 ASSERT(tw->tw_hctd_tail == NULL);
6392 tw->tw_hctd_head = td;
6393 tw->tw_hctd_tail = td;
6394 } else {
6395 ohci_td_t *dummy = (ohci_td_t *)tw->tw_hctd_tail;
6396
6397 ASSERT(dummy != NULL);
6398 ASSERT(dummy != td);
6399 ASSERT(Get_TD(td->hctd_state) != HC_TD_DUMMY);
6400
6401 /* Add the td to the end of the list */
6402 Set_TD(dummy->hctd_tw_next_td,
6403 ohci_td_cpu_to_iommu(ohcip, td));
6404
6405 tw->tw_hctd_tail = td;
6406
6407 ASSERT(Get_TD(td->hctd_tw_next_td) == 0);
6408 }
6409 }
6410
6411
6412 /*
6413 * ohci_traverse_tds:
6414 * NOTE: This function is also called from POLLED MODE.
6415 *
6416 * Traverse the list of TD's for an endpoint. Since the endpoint is marked
6417 * as sKipped, the Host Controller (HC) is no longer accessing these TD's.
6418 * Remove all the TD's that are attached to the endpoint.
6419 */
6420 void
ohci_traverse_tds(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)6421 ohci_traverse_tds(
6422 ohci_state_t *ohcip,
6423 usba_pipe_handle_data_t *ph)
6424 {
6425 ohci_trans_wrapper_t *tw;
6426 ohci_ed_t *ept;
6427 ohci_pipe_private_t *pp;
6428 uint32_t addr;
6429 ohci_td_t *tailp, *headp, *next;
6430
6431 pp = (ohci_pipe_private_t *)ph->p_hcd_private;
6432 ept = pp->pp_ept;
6433
6434 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6435 "ohci_traverse_tds: ph = 0x%p ept = 0x%p",
6436 (void *)ph, (void *)ept);
6437
6438 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6439
6440 addr = Get_ED(ept->hced_headp) & (uint32_t)HC_EPT_TD_HEAD;
6441
6442 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6443 "ohci_traverse_tds: addr (head) = 0x%x", addr);
6444
6445 headp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip, addr));
6446
6447 addr = Get_ED(ept->hced_tailp) & (uint32_t)HC_EPT_TD_TAIL;
6448
6449 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6450 "ohci_traverse_tds: addr (tail) = 0x%x", addr);
6451
6452 tailp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip, addr));
6453
6454 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6455 "ohci_traverse_tds: cpu head = 0x%p cpu tail = 0x%p",
6456 (void *)headp, (void *)tailp);
6457
6458 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6459 "ohci_traverse_tds: iommu head = 0x%x iommu tail = 0x%x",
6460 ohci_td_cpu_to_iommu(ohcip, headp),
6461 ohci_td_cpu_to_iommu(ohcip, tailp));
6462
6463 /*
6464 * Traverse the list of TD's that are currently on the endpoint.
6465 * These TD's have not been processed and will not be processed
6466 * because the endpoint processing is stopped.
6467 */
6468 while (headp != tailp) {
6469 next = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
6470 (Get_TD(headp->hctd_next_td) & HC_EPT_TD_TAIL)));
6471
6472 tw = (ohci_trans_wrapper_t *)OHCI_LOOKUP_ID(
6473 (uint32_t)Get_TD(headp->hctd_trans_wrapper));
6474
6475 /* Stop the the transfer timer */
6476 ohci_stop_xfer_timer(ohcip, tw, OHCI_REMOVE_XFER_ALWAYS);
6477
6478 ohci_deallocate_td(ohcip, headp);
6479 headp = next;
6480 }
6481
6482 /* Both head and tail pointers must be same */
6483 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6484 "ohci_traverse_tds: head = 0x%p tail = 0x%p",
6485 (void *)headp, (void *)tailp);
6486
6487 /* Update the pointer in the endpoint descriptor */
6488 Set_ED(ept->hced_headp, (ohci_td_cpu_to_iommu(ohcip, headp)));
6489
6490 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6491 "ohci_traverse_tds: new head = 0x%x",
6492 (ohci_td_cpu_to_iommu(ohcip, headp)));
6493
6494 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6495 "ohci_traverse_tds: tailp = 0x%x headp = 0x%x",
6496 (Get_ED(ept->hced_tailp) & HC_EPT_TD_TAIL),
6497 (Get_ED(ept->hced_headp) & HC_EPT_TD_HEAD));
6498
6499 ASSERT((Get_ED(ept->hced_tailp) & HC_EPT_TD_TAIL) ==
6500 (Get_ED(ept->hced_headp) & HC_EPT_TD_HEAD));
6501 }
6502
6503
6504 /*
6505 * ohci_done_list_tds:
6506 *
6507 * There may be TD's on the done list that have not been processed yet. Walk
6508 * through these TD's and mark them as RECLAIM. All the mappings for the TD
6509 * will be torn down, so the interrupt handle is alerted of this fact through
6510 * the RECLAIM flag.
6511 */
6512 static void
ohci_done_list_tds(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)6513 ohci_done_list_tds(
6514 ohci_state_t *ohcip,
6515 usba_pipe_handle_data_t *ph)
6516 {
6517 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
6518 ohci_trans_wrapper_t *head_tw = pp->pp_tw_head;
6519 ohci_trans_wrapper_t *next_tw;
6520 ohci_td_t *head_td, *next_td;
6521
6522 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6523
6524 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6525 "ohci_done_list_tds:");
6526
6527 /* Process the transfer wrappers for this pipe */
6528 next_tw = head_tw;
6529 while (next_tw) {
6530 head_td = (ohci_td_t *)next_tw->tw_hctd_head;
6531 next_td = head_td;
6532
6533 if (head_td) {
6534 /*
6535 * Walk through each TD for this transfer
6536 * wrapper. If a TD still exists, then it
6537 * is currently on the done list.
6538 */
6539 while (next_td) {
6540
6541 /* To free TD, set TD state to RECLAIM */
6542 Set_TD(next_td->hctd_state, HC_TD_RECLAIM);
6543
6544 Set_TD(next_td->hctd_trans_wrapper, NULL);
6545
6546 next_td = ohci_td_iommu_to_cpu(ohcip,
6547 Get_TD(next_td->hctd_tw_next_td));
6548 }
6549 }
6550
6551 /* Stop the the transfer timer */
6552 ohci_stop_xfer_timer(ohcip, next_tw, OHCI_REMOVE_XFER_ALWAYS);
6553
6554 next_tw = next_tw->tw_next;
6555 }
6556 }
6557
6558
6559 /*
6560 * Remove old_td from tw and update the links.
6561 */
6562 void
ohci_unlink_td_from_tw(ohci_state_t * ohcip,ohci_td_t * old_td,ohci_trans_wrapper_t * tw)6563 ohci_unlink_td_from_tw(
6564 ohci_state_t *ohcip,
6565 ohci_td_t *old_td,
6566 ohci_trans_wrapper_t *tw)
6567 {
6568 ohci_td_t *next, *head, *tail;
6569
6570 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6571 "ohci_unlink_td_from_tw: ohcip = 0x%p, old_td = 0x%p, tw = 0x%p",
6572 (void *)ohcip, (void *)old_td, (void *)tw);
6573
6574 if (old_td == NULL || tw == NULL) {
6575
6576 return;
6577 }
6578
6579 head = tw->tw_hctd_head;
6580 tail = tw->tw_hctd_tail;
6581
6582 if (head == NULL) {
6583
6584 return;
6585 }
6586
6587 /* if this old_td is on head */
6588 if (old_td == head) {
6589 if (old_td == tail) {
6590 tw->tw_hctd_head = NULL;
6591 tw->tw_hctd_tail = NULL;
6592 } else {
6593 tw->tw_hctd_head = ohci_td_iommu_to_cpu(ohcip,
6594 Get_TD(head->hctd_tw_next_td));
6595 }
6596
6597 return;
6598 }
6599
6600 /* find this old_td's position in the tw */
6601 next = ohci_td_iommu_to_cpu(ohcip, Get_TD(head->hctd_tw_next_td));
6602 while (next && (old_td != next)) {
6603 head = next;
6604 next = ohci_td_iommu_to_cpu(ohcip,
6605 Get_TD(next->hctd_tw_next_td));
6606 }
6607
6608 /* unlink the found old_td from the tw */
6609 if (old_td == next) {
6610 Set_TD(head->hctd_tw_next_td, Get_TD(next->hctd_tw_next_td));
6611 if (old_td == tail) {
6612 tw->tw_hctd_tail = head;
6613 }
6614 }
6615 }
6616
6617
6618 /*
6619 * ohci_deallocate_td:
6620 * NOTE: This function is also called from POLLED MODE.
6621 *
6622 * Deallocate a Host Controller's (HC) Transfer Descriptor (TD).
6623 */
6624 void
ohci_deallocate_td(ohci_state_t * ohcip,ohci_td_t * old_td)6625 ohci_deallocate_td(
6626 ohci_state_t *ohcip,
6627 ohci_td_t *old_td)
6628 {
6629 ohci_trans_wrapper_t *tw;
6630
6631 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6632 "ohci_deallocate_td: old_td = 0x%p", (void *)old_td);
6633
6634 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6635
6636 /*
6637 * Obtain the transaction wrapper and tw will be
6638 * NULL for the dummy and for the reclaim TD's.
6639 */
6640 if ((Get_TD(old_td->hctd_state) == HC_TD_DUMMY) ||
6641 (Get_TD(old_td->hctd_state) == HC_TD_RECLAIM)) {
6642 tw = (ohci_trans_wrapper_t *)((uintptr_t)
6643 Get_TD(old_td->hctd_trans_wrapper));
6644 ASSERT(tw == NULL);
6645 } else {
6646 tw = (ohci_trans_wrapper_t *)
6647 OHCI_LOOKUP_ID((uint32_t)
6648 Get_TD(old_td->hctd_trans_wrapper));
6649 ASSERT(tw != NULL);
6650 }
6651
6652 /*
6653 * If this TD should be reclaimed, don't try to access its
6654 * transfer wrapper.
6655 */
6656 if ((Get_TD(old_td->hctd_state) != HC_TD_RECLAIM) && tw) {
6657
6658 ohci_unlink_td_from_tw(ohcip, old_td, tw);
6659 }
6660
6661 bzero((void *)old_td, sizeof (ohci_td_t));
6662 Set_TD(old_td->hctd_state, HC_TD_FREE);
6663
6664 USB_DPRINTF_L3(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6665 "ohci_deallocate_td: td 0x%p", (void *)old_td);
6666 }
6667
6668
6669 /*
6670 * ohci_td_cpu_to_iommu:
6671 * NOTE: This function is also called from POLLED MODE.
6672 *
6673 * This function converts for the given Transfer Descriptor (TD) CPU address
6674 * to IO address.
6675 */
6676 uint32_t
ohci_td_cpu_to_iommu(ohci_state_t * ohcip,ohci_td_t * addr)6677 ohci_td_cpu_to_iommu(
6678 ohci_state_t *ohcip,
6679 ohci_td_t *addr)
6680 {
6681 uint32_t td;
6682
6683 td = (uint32_t)ohcip->ohci_td_pool_cookie.dmac_address +
6684 (uint32_t)((uintptr_t)addr - (uintptr_t)(ohcip->ohci_td_pool_addr));
6685
6686 ASSERT((ohcip->ohci_td_pool_cookie.dmac_address +
6687 (uint32_t) (sizeof (ohci_td_t) *
6688 (addr - ohcip->ohci_td_pool_addr))) ==
6689 (ohcip->ohci_td_pool_cookie.dmac_address +
6690 (uint32_t)((uintptr_t)addr - (uintptr_t)
6691 (ohcip->ohci_td_pool_addr))));
6692
6693 ASSERT(td >= ohcip->ohci_td_pool_cookie.dmac_address);
6694 ASSERT(td <= ohcip->ohci_td_pool_cookie.dmac_address +
6695 sizeof (ohci_td_t) * ohci_td_pool_size);
6696
6697 return (td);
6698 }
6699
6700
6701 /*
6702 * ohci_td_iommu_to_cpu:
6703 * NOTE: This function is also called from POLLED MODE.
6704 *
6705 * This function converts for the given Transfer Descriptor (TD) IO address
6706 * to CPU address.
6707 */
6708 ohci_td_t *
ohci_td_iommu_to_cpu(ohci_state_t * ohcip,uintptr_t addr)6709 ohci_td_iommu_to_cpu(
6710 ohci_state_t *ohcip,
6711 uintptr_t addr)
6712 {
6713 ohci_td_t *td;
6714
6715 if (addr == 0)
6716 return (NULL);
6717
6718 td = (ohci_td_t *)((uintptr_t)
6719 (addr - ohcip->ohci_td_pool_cookie.dmac_address) +
6720 (uintptr_t)ohcip->ohci_td_pool_addr);
6721
6722 ASSERT(td >= ohcip->ohci_td_pool_addr);
6723 ASSERT((uintptr_t)td <= (uintptr_t)ohcip->ohci_td_pool_addr +
6724 (uintptr_t)(sizeof (ohci_td_t) * ohci_td_pool_size));
6725
6726 return (td);
6727 }
6728
6729 /*
6730 * ohci_allocate_tds_for_tw:
6731 *
6732 * Allocate n Transfer Descriptors (TD) from the TD buffer pool and places it
6733 * into the TW.
6734 *
6735 * Returns USB_NO_RESOURCES if it was not able to allocate all the requested TD
6736 * otherwise USB_SUCCESS.
6737 */
6738 int
ohci_allocate_tds_for_tw(ohci_state_t * ohcip,ohci_trans_wrapper_t * tw,size_t td_count)6739 ohci_allocate_tds_for_tw(
6740 ohci_state_t *ohcip,
6741 ohci_trans_wrapper_t *tw,
6742 size_t td_count)
6743 {
6744 ohci_td_t *td;
6745 uint32_t td_addr;
6746 int i;
6747 int error = USB_SUCCESS;
6748
6749 for (i = 0; i < td_count; i++) {
6750 td = ohci_allocate_td_from_pool(ohcip);
6751 if (td == NULL) {
6752 error = USB_NO_RESOURCES;
6753 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6754 "ohci_allocate_tds_for_tw: "
6755 "Unable to allocate %lu TDs",
6756 td_count);
6757 break;
6758 }
6759 if (tw->tw_hctd_free_list != NULL) {
6760 td_addr = ohci_td_cpu_to_iommu(ohcip,
6761 tw->tw_hctd_free_list);
6762 Set_TD(td->hctd_tw_next_td, td_addr);
6763 }
6764 tw->tw_hctd_free_list = td;
6765 }
6766
6767 return (error);
6768 }
6769
6770 /*
6771 * ohci_allocate_tw_resources:
6772 *
6773 * Allocate a Transaction Wrapper (TW) and n Transfer Descriptors (TD)
6774 * from the TD buffer pool and places it into the TW. It does an all
6775 * or nothing transaction.
6776 *
6777 * Returns NULL if there is insufficient resources otherwise TW.
6778 */
6779 static ohci_trans_wrapper_t *
ohci_allocate_tw_resources(ohci_state_t * ohcip,ohci_pipe_private_t * pp,size_t tw_length,usb_flags_t usb_flags,size_t td_count)6780 ohci_allocate_tw_resources(
6781 ohci_state_t *ohcip,
6782 ohci_pipe_private_t *pp,
6783 size_t tw_length,
6784 usb_flags_t usb_flags,
6785 size_t td_count)
6786 {
6787 ohci_trans_wrapper_t *tw;
6788
6789 tw = ohci_create_transfer_wrapper(ohcip, pp, tw_length, usb_flags);
6790
6791 if (tw == NULL) {
6792 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6793 "ohci_allocate_tw_resources: Unable to allocate TW");
6794 } else {
6795 if (ohci_allocate_tds_for_tw(ohcip, tw, td_count) ==
6796 USB_SUCCESS) {
6797 tw->tw_num_tds = (uint_t)td_count;
6798 } else {
6799 ohci_deallocate_tw_resources(ohcip, pp, tw);
6800 tw = NULL;
6801 }
6802 }
6803
6804 return (tw);
6805 }
6806
6807 /*
6808 * ohci_free_tw_tds_resources:
6809 *
6810 * Free all allocated resources for Transaction Wrapper (TW).
6811 * Does not free the TW itself.
6812 */
6813 static void
ohci_free_tw_tds_resources(ohci_state_t * ohcip,ohci_trans_wrapper_t * tw)6814 ohci_free_tw_tds_resources(
6815 ohci_state_t *ohcip,
6816 ohci_trans_wrapper_t *tw)
6817 {
6818 ohci_td_t *td;
6819 ohci_td_t *temp_td;
6820
6821 td = tw->tw_hctd_free_list;
6822 while (td != NULL) {
6823 /* Save the pointer to the next td before destroying it */
6824 temp_td = ohci_td_iommu_to_cpu(ohcip,
6825 Get_TD(td->hctd_tw_next_td));
6826 ohci_deallocate_td(ohcip, td);
6827 td = temp_td;
6828 }
6829 tw->tw_hctd_free_list = NULL;
6830 }
6831
6832
6833 /*
6834 * Transfer Wrapper functions
6835 *
6836 * ohci_create_transfer_wrapper:
6837 *
6838 * Create a Transaction Wrapper (TW) for non-isoc transfer types
6839 * and this involves the allocating of DMA resources.
6840 */
6841 static ohci_trans_wrapper_t *
ohci_create_transfer_wrapper(ohci_state_t * ohcip,ohci_pipe_private_t * pp,size_t length,uint_t usb_flags)6842 ohci_create_transfer_wrapper(
6843 ohci_state_t *ohcip,
6844 ohci_pipe_private_t *pp,
6845 size_t length,
6846 uint_t usb_flags)
6847 {
6848 ddi_device_acc_attr_t dev_attr;
6849 int result;
6850 size_t real_length;
6851 ohci_trans_wrapper_t *tw;
6852 ddi_dma_attr_t dma_attr;
6853 int kmem_flag;
6854 int (*dmamem_wait)(caddr_t);
6855 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
6856
6857 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6858 "ohci_create_transfer_wrapper: length = 0x%lx flags = 0x%x",
6859 length, usb_flags);
6860
6861 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6862
6863 /* isochronous pipe should not call into this function */
6864 if ((ph->p_ep.bmAttributes & USB_EP_ATTR_MASK) ==
6865 USB_EP_ATTR_ISOCH) {
6866
6867 return (NULL);
6868 }
6869
6870 /* SLEEP flag should not be used while holding mutex */
6871 kmem_flag = KM_NOSLEEP;
6872 dmamem_wait = DDI_DMA_DONTWAIT;
6873
6874 /* Allocate space for the transfer wrapper */
6875 tw = kmem_zalloc(sizeof (ohci_trans_wrapper_t), kmem_flag);
6876
6877 if (tw == NULL) {
6878 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6879 "ohci_create_transfer_wrapper: kmem_zalloc failed");
6880
6881 return (NULL);
6882 }
6883
6884 /* zero-length packet doesn't need to allocate dma memory */
6885 if (length == 0) {
6886
6887 goto dmadone;
6888 }
6889
6890 /* allow sg lists for transfer wrapper dma memory */
6891 bcopy(&ohcip->ohci_dma_attr, &dma_attr, sizeof (ddi_dma_attr_t));
6892 dma_attr.dma_attr_sgllen = OHCI_DMA_ATTR_TW_SGLLEN;
6893 dma_attr.dma_attr_align = OHCI_DMA_ATTR_ALIGNMENT;
6894
6895 /* Allocate the DMA handle */
6896 result = ddi_dma_alloc_handle(ohcip->ohci_dip,
6897 &dma_attr, dmamem_wait, 0, &tw->tw_dmahandle);
6898
6899 if (result != DDI_SUCCESS) {
6900 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6901 "ohci_create_transfer_wrapper: Alloc handle failed");
6902
6903 kmem_free(tw, sizeof (ohci_trans_wrapper_t));
6904
6905 return (NULL);
6906 }
6907
6908 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
6909
6910 /* The host controller will be little endian */
6911 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC;
6912 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
6913
6914 /* Allocate the memory */
6915 result = ddi_dma_mem_alloc(tw->tw_dmahandle, length,
6916 &dev_attr, DDI_DMA_CONSISTENT, dmamem_wait, NULL,
6917 (caddr_t *)&tw->tw_buf, &real_length, &tw->tw_accesshandle);
6918
6919 if (result != DDI_SUCCESS) {
6920 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6921 "ohci_create_transfer_wrapper: dma_mem_alloc fail");
6922
6923 ddi_dma_free_handle(&tw->tw_dmahandle);
6924 kmem_free(tw, sizeof (ohci_trans_wrapper_t));
6925
6926 return (NULL);
6927 }
6928
6929 ASSERT(real_length >= length);
6930
6931 /* Bind the handle */
6932 result = ddi_dma_addr_bind_handle(tw->tw_dmahandle, NULL,
6933 (caddr_t)tw->tw_buf, real_length, DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
6934 dmamem_wait, NULL, &tw->tw_cookie, &tw->tw_ncookies);
6935
6936 if (result != DDI_DMA_MAPPED) {
6937 ohci_decode_ddi_dma_addr_bind_handle_result(ohcip, result);
6938
6939 ddi_dma_mem_free(&tw->tw_accesshandle);
6940 ddi_dma_free_handle(&tw->tw_dmahandle);
6941 kmem_free(tw, sizeof (ohci_trans_wrapper_t));
6942
6943 return (NULL);
6944 }
6945
6946 tw->tw_cookie_idx = 0;
6947 tw->tw_dma_offs = 0;
6948
6949 dmadone:
6950 /*
6951 * Only allow one wrapper to be added at a time. Insert the
6952 * new transaction wrapper into the list for this pipe.
6953 */
6954 if (pp->pp_tw_head == NULL) {
6955 pp->pp_tw_head = tw;
6956 pp->pp_tw_tail = tw;
6957 } else {
6958 pp->pp_tw_tail->tw_next = tw;
6959 pp->pp_tw_tail = tw;
6960 }
6961
6962 /* Store the transfer length */
6963 tw->tw_length = length;
6964
6965 /* Store a back pointer to the pipe private structure */
6966 tw->tw_pipe_private = pp;
6967
6968 /* Store the transfer type - synchronous or asynchronous */
6969 tw->tw_flags = usb_flags;
6970
6971 /* Get and Store 32bit ID */
6972 tw->tw_id = OHCI_GET_ID((void *)tw);
6973
6974 ASSERT(tw->tw_id != 0);
6975
6976 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6977 "ohci_create_transfer_wrapper: tw = 0x%p, ncookies = %u",
6978 (void *)tw, tw->tw_ncookies);
6979
6980 return (tw);
6981 }
6982
6983
6984 /*
6985 * Transfer Wrapper functions
6986 *
6987 * ohci_create_isoc_transfer_wrapper:
6988 *
6989 * Create a Transaction Wrapper (TW) for isoc transfer
6990 * and this involves the allocating of DMA resources.
6991 */
6992 static ohci_trans_wrapper_t *
ohci_create_isoc_transfer_wrapper(ohci_state_t * ohcip,ohci_pipe_private_t * pp,size_t length,usb_isoc_pkt_descr_t * descr,ushort_t pkt_count,size_t td_count,uint_t usb_flags)6993 ohci_create_isoc_transfer_wrapper(
6994 ohci_state_t *ohcip,
6995 ohci_pipe_private_t *pp,
6996 size_t length,
6997 usb_isoc_pkt_descr_t *descr,
6998 ushort_t pkt_count,
6999 size_t td_count,
7000 uint_t usb_flags)
7001 {
7002 ddi_device_acc_attr_t dev_attr;
7003 int result;
7004 size_t real_length, xfer_size;
7005 uint_t ccount;
7006 ohci_trans_wrapper_t *tw;
7007 ddi_dma_attr_t dma_attr;
7008 int kmem_flag;
7009 uint_t i, j, frame_count, residue;
7010 int (*dmamem_wait)(caddr_t);
7011 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
7012 usb_isoc_pkt_descr_t *isoc_pkt_descr = descr;
7013
7014 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7015 "ohci_create_isoc_transfer_wrapper: length = 0x%lx flags = 0x%x",
7016 length, usb_flags);
7017
7018 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7019
7020 /* non-isochronous pipe should not call into this function */
7021 if ((ph->p_ep.bmAttributes & USB_EP_ATTR_MASK) !=
7022 USB_EP_ATTR_ISOCH) {
7023
7024 return (NULL);
7025 }
7026
7027 /* SLEEP flag should not be used in interrupt context */
7028 if (servicing_interrupt()) {
7029 kmem_flag = KM_NOSLEEP;
7030 dmamem_wait = DDI_DMA_DONTWAIT;
7031 } else {
7032 kmem_flag = KM_SLEEP;
7033 dmamem_wait = DDI_DMA_SLEEP;
7034 }
7035
7036 /* Allocate space for the transfer wrapper */
7037 tw = kmem_zalloc(sizeof (ohci_trans_wrapper_t), kmem_flag);
7038
7039 if (tw == NULL) {
7040 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7041 "ohci_create_transfer_wrapper: kmem_zalloc failed");
7042
7043 return (NULL);
7044 }
7045
7046 /* Allocate space for the isoc buffer handles */
7047 tw->tw_isoc_strtlen = sizeof (ohci_isoc_buf_t) * td_count;
7048 if ((tw->tw_isoc_bufs = kmem_zalloc(tw->tw_isoc_strtlen,
7049 kmem_flag)) == NULL) {
7050 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
7051 "ohci_create_isoc_transfer_wrapper: kmem_alloc "
7052 "isoc buffer failed");
7053 kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7054
7055 return (NULL);
7056 }
7057
7058 /* allow sg lists for transfer wrapper dma memory */
7059 bcopy(&ohcip->ohci_dma_attr, &dma_attr, sizeof (ddi_dma_attr_t));
7060 dma_attr.dma_attr_sgllen = OHCI_DMA_ATTR_TD_SGLLEN;
7061 dma_attr.dma_attr_align = OHCI_DMA_ATTR_ALIGNMENT;
7062
7063 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
7064
7065 /* The host controller will be little endian */
7066 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC;
7067 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
7068
7069 residue = pkt_count % OHCI_ISOC_PKTS_PER_TD;
7070
7071 for (i = 0; i < td_count; i++) {
7072 tw->tw_isoc_bufs[i].index = i;
7073
7074 if ((i == (td_count - 1)) && (residue != 0)) {
7075 frame_count = residue;
7076 } else {
7077 frame_count = OHCI_ISOC_PKTS_PER_TD;
7078 }
7079
7080 /* Allocate the DMA handle */
7081 result = ddi_dma_alloc_handle(ohcip->ohci_dip, &dma_attr,
7082 dmamem_wait, 0, &tw->tw_isoc_bufs[i].dma_handle);
7083
7084 if (result != DDI_SUCCESS) {
7085 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7086 "ohci_create_isoc_transfer_wrapper: "
7087 "Alloc handle failed");
7088
7089 for (j = 0; j < i; j++) {
7090 result = ddi_dma_unbind_handle(
7091 tw->tw_isoc_bufs[j].dma_handle);
7092 ASSERT(result == USB_SUCCESS);
7093 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
7094 mem_handle);
7095 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
7096 dma_handle);
7097 }
7098 kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
7099 kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7100
7101 return (NULL);
7102 }
7103
7104 /* Compute the memory length */
7105 for (xfer_size = 0, j = 0; j < frame_count; j++) {
7106 ASSERT(isoc_pkt_descr != NULL);
7107 xfer_size += isoc_pkt_descr->isoc_pkt_length;
7108 isoc_pkt_descr++;
7109 }
7110
7111 /* Allocate the memory */
7112 result = ddi_dma_mem_alloc(tw->tw_isoc_bufs[i].dma_handle,
7113 xfer_size, &dev_attr, DDI_DMA_CONSISTENT, dmamem_wait,
7114 NULL, (caddr_t *)&tw->tw_isoc_bufs[i].buf_addr,
7115 &real_length, &tw->tw_isoc_bufs[i].mem_handle);
7116
7117 if (result != DDI_SUCCESS) {
7118 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7119 "ohci_create_isoc_transfer_wrapper: "
7120 "dma_mem_alloc %d fail", i);
7121 ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
7122
7123 for (j = 0; j < i; j++) {
7124 result = ddi_dma_unbind_handle(
7125 tw->tw_isoc_bufs[j].dma_handle);
7126 ASSERT(result == USB_SUCCESS);
7127 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
7128 mem_handle);
7129 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
7130 dma_handle);
7131 }
7132 kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
7133 kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7134
7135 return (NULL);
7136 }
7137
7138 ASSERT(real_length >= xfer_size);
7139
7140 /* Bind the handle */
7141 result = ddi_dma_addr_bind_handle(
7142 tw->tw_isoc_bufs[i].dma_handle, NULL,
7143 (caddr_t)tw->tw_isoc_bufs[i].buf_addr, real_length,
7144 DDI_DMA_RDWR|DDI_DMA_CONSISTENT, dmamem_wait, NULL,
7145 &tw->tw_isoc_bufs[i].cookie, &ccount);
7146
7147 if ((result == DDI_DMA_MAPPED) &&
7148 (ccount <= OHCI_DMA_ATTR_TD_SGLLEN)) {
7149 tw->tw_isoc_bufs[i].length = xfer_size;
7150 tw->tw_isoc_bufs[i].ncookies = ccount;
7151
7152 continue;
7153 } else {
7154 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7155 "ohci_create_isoc_transfer_wrapper: "
7156 "Bind handle %d failed", i);
7157 if (result == DDI_DMA_MAPPED) {
7158 result = ddi_dma_unbind_handle(
7159 tw->tw_isoc_bufs[i].dma_handle);
7160 ASSERT(result == USB_SUCCESS);
7161 }
7162 ddi_dma_mem_free(&tw->tw_isoc_bufs[i].mem_handle);
7163 ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
7164
7165 for (j = 0; j < i; j++) {
7166 result = ddi_dma_unbind_handle(
7167 tw->tw_isoc_bufs[j].dma_handle);
7168 ASSERT(result == USB_SUCCESS);
7169 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
7170 mem_handle);
7171 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
7172 dma_handle);
7173 }
7174 kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
7175 kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7176
7177 return (NULL);
7178 }
7179 }
7180
7181 /*
7182 * Only allow one wrapper to be added at a time. Insert the
7183 * new transaction wrapper into the list for this pipe.
7184 */
7185 if (pp->pp_tw_head == NULL) {
7186 pp->pp_tw_head = tw;
7187 pp->pp_tw_tail = tw;
7188 } else {
7189 pp->pp_tw_tail->tw_next = tw;
7190 pp->pp_tw_tail = tw;
7191 }
7192
7193 /* Store the transfer length */
7194 tw->tw_length = length;
7195
7196 /* Store the td numbers */
7197 tw->tw_ncookies = (uint_t)td_count;
7198
7199 /* Store a back pointer to the pipe private structure */
7200 tw->tw_pipe_private = pp;
7201
7202 /* Store the transfer type - synchronous or asynchronous */
7203 tw->tw_flags = usb_flags;
7204
7205 /* Get and Store 32bit ID */
7206 tw->tw_id = OHCI_GET_ID((void *)tw);
7207
7208 ASSERT(tw->tw_id != 0);
7209
7210 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7211 "ohci_create_isoc_transfer_wrapper: tw = 0x%p", (void *)tw);
7212
7213 return (tw);
7214 }
7215
7216
7217 /*
7218 * ohci_start_xfer_timer:
7219 *
7220 * Start the timer for the control, bulk and for one time interrupt
7221 * transfers.
7222 */
7223 /* ARGSUSED */
7224 static void
ohci_start_xfer_timer(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw)7225 ohci_start_xfer_timer(
7226 ohci_state_t *ohcip,
7227 ohci_pipe_private_t *pp,
7228 ohci_trans_wrapper_t *tw)
7229 {
7230 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
7231 "ohci_start_xfer_timer: tw = 0x%p", (void *)tw);
7232
7233 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7234
7235 /*
7236 * The timeout handling is done only for control, bulk and for
7237 * one time Interrupt transfers.
7238 *
7239 * NOTE: If timeout is zero; Assume infinite timeout and don't
7240 * insert this transfer on the timeout list.
7241 */
7242 if (tw->tw_timeout) {
7243 /*
7244 * Increase timeout value by one second and this extra one
7245 * second is used to halt the endpoint if given transfer
7246 * times out.
7247 */
7248 tw->tw_timeout++;
7249
7250 /*
7251 * Add this transfer wrapper into the transfer timeout list.
7252 */
7253 if (ohcip->ohci_timeout_list) {
7254 tw->tw_timeout_next = ohcip->ohci_timeout_list;
7255 }
7256
7257 ohcip->ohci_timeout_list = tw;
7258 ohci_start_timer(ohcip);
7259 }
7260 }
7261
7262
7263 /*
7264 * ohci_stop_xfer_timer:
7265 *
7266 * Start the timer for the control, bulk and for one time interrupt
7267 * transfers.
7268 */
7269 void
ohci_stop_xfer_timer(ohci_state_t * ohcip,ohci_trans_wrapper_t * tw,uint_t flag)7270 ohci_stop_xfer_timer(
7271 ohci_state_t *ohcip,
7272 ohci_trans_wrapper_t *tw,
7273 uint_t flag)
7274 {
7275 timeout_id_t timer_id;
7276
7277 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
7278 "ohci_stop_xfer_timer: tw = 0x%p", (void *)tw);
7279
7280 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7281
7282 /*
7283 * The timeout handling is done only for control, bulk
7284 * and for one time Interrupt transfers.
7285 */
7286 if (ohcip->ohci_timeout_list == NULL) {
7287 return;
7288 }
7289
7290 switch (flag) {
7291 case OHCI_REMOVE_XFER_IFLAST:
7292 if (tw->tw_hctd_head != tw->tw_hctd_tail) {
7293 break;
7294 }
7295 /* FALLTHRU */
7296 case OHCI_REMOVE_XFER_ALWAYS:
7297 ohci_remove_tw_from_timeout_list(ohcip, tw);
7298
7299 if ((ohcip->ohci_timeout_list == NULL) &&
7300 (ohcip->ohci_timer_id)) {
7301
7302 timer_id = ohcip->ohci_timer_id;
7303
7304 /* Reset the timer id to zero */
7305 ohcip->ohci_timer_id = 0;
7306
7307 mutex_exit(&ohcip->ohci_int_mutex);
7308
7309 (void) untimeout(timer_id);
7310
7311 mutex_enter(&ohcip->ohci_int_mutex);
7312 }
7313 break;
7314 default:
7315 break;
7316 }
7317 }
7318
7319
7320 /*
7321 * ohci_xfer_timeout_handler:
7322 *
7323 * Control or bulk transfer timeout handler.
7324 */
7325 static void
ohci_xfer_timeout_handler(void * arg)7326 ohci_xfer_timeout_handler(void *arg)
7327 {
7328 ohci_state_t *ohcip = (ohci_state_t *)arg;
7329 ohci_trans_wrapper_t *exp_xfer_list_head = NULL;
7330 ohci_trans_wrapper_t *exp_xfer_list_tail = NULL;
7331 ohci_trans_wrapper_t *tw, *next;
7332 ohci_td_t *td;
7333 usb_flags_t flags;
7334
7335 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
7336 "ohci_xfer_timeout_handler: ohcip = 0x%p", (void *)ohcip);
7337
7338 mutex_enter(&ohcip->ohci_int_mutex);
7339
7340 /* Set the required flags */
7341 flags = OHCI_FLAGS_NOSLEEP | OHCI_FLAGS_DMA_SYNC;
7342
7343 /*
7344 * Check whether still timeout handler is valid.
7345 */
7346 if (ohcip->ohci_timer_id) {
7347
7348 /* Reset the timer id to zero */
7349 ohcip->ohci_timer_id = 0;
7350 } else {
7351 mutex_exit(&ohcip->ohci_int_mutex);
7352
7353 return;
7354 }
7355
7356 /* Get the transfer timeout list head */
7357 tw = ohcip->ohci_timeout_list;
7358
7359 /*
7360 * Process ohci timeout list and look whether the timer
7361 * has expired for any transfers. Create a temporary list
7362 * of expired transfers and process them later.
7363 */
7364 while (tw) {
7365 /* Get the transfer on the timeout list */
7366 next = tw->tw_timeout_next;
7367
7368 tw->tw_timeout--;
7369
7370 /*
7371 * Set the sKip bit to stop all transactions on
7372 * this pipe
7373 */
7374 if (tw->tw_timeout == 1) {
7375 ohci_modify_sKip_bit(ohcip,
7376 tw->tw_pipe_private, SET_sKip, flags);
7377
7378 /* Reset dma sync flag */
7379 flags &= ~OHCI_FLAGS_DMA_SYNC;
7380 }
7381
7382 /* Remove tw from the timeout list */
7383 if (tw->tw_timeout == 0) {
7384
7385 ohci_remove_tw_from_timeout_list(ohcip, tw);
7386
7387 /* Add tw to the end of expire list */
7388 if (exp_xfer_list_head) {
7389 exp_xfer_list_tail->tw_timeout_next = tw;
7390 } else {
7391 exp_xfer_list_head = tw;
7392 }
7393 exp_xfer_list_tail = tw;
7394 tw->tw_timeout_next = NULL;
7395 }
7396
7397 tw = next;
7398 }
7399
7400 /* Get the expired transfer timeout list head */
7401 tw = exp_xfer_list_head;
7402
7403 if (tw && (flags & OHCI_FLAGS_DMA_SYNC)) {
7404 /* Sync ED and TD pool */
7405 Sync_ED_TD_Pool(ohcip);
7406 }
7407
7408 /*
7409 * Process the expired transfers by notifing the corrsponding
7410 * client driver through the exception callback.
7411 */
7412 while (tw) {
7413 /* Get the transfer on the expired transfer timeout list */
7414 next = tw->tw_timeout_next;
7415
7416 td = tw->tw_hctd_head;
7417
7418 while (td) {
7419 /* Set TD state to TIMEOUT */
7420 Set_TD(td->hctd_state, HC_TD_TIMEOUT);
7421
7422 /* Get the next TD from the wrapper */
7423 td = ohci_td_iommu_to_cpu(ohcip,
7424 Get_TD(td->hctd_tw_next_td));
7425 }
7426
7427 ohci_handle_error(ohcip, tw->tw_hctd_head, USB_CR_TIMEOUT);
7428
7429 tw = next;
7430 }
7431
7432 ohci_start_timer(ohcip);
7433 mutex_exit(&ohcip->ohci_int_mutex);
7434 }
7435
7436
7437 /*
7438 * ohci_remove_tw_from_timeout_list:
7439 *
7440 * Remove Control or bulk transfer from the timeout list.
7441 */
7442 static void
ohci_remove_tw_from_timeout_list(ohci_state_t * ohcip,ohci_trans_wrapper_t * tw)7443 ohci_remove_tw_from_timeout_list(
7444 ohci_state_t *ohcip,
7445 ohci_trans_wrapper_t *tw)
7446 {
7447 ohci_trans_wrapper_t *prev, *next;
7448
7449 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
7450 "ohci_remove_tw_from_timeout_list: tw = 0x%p", (void *)tw);
7451
7452 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7453
7454 if (ohcip->ohci_timeout_list == tw) {
7455 ohcip->ohci_timeout_list = tw->tw_timeout_next;
7456 } else {
7457 prev = ohcip->ohci_timeout_list;
7458 next = prev->tw_timeout_next;
7459
7460 while (next && (next != tw)) {
7461 prev = next;
7462 next = next->tw_timeout_next;
7463 }
7464
7465 if (next == tw) {
7466 prev->tw_timeout_next = next->tw_timeout_next;
7467 }
7468 }
7469
7470 /* Reset the xfer timeout */
7471 tw->tw_timeout_next = NULL;
7472 }
7473
7474
7475 /*
7476 * ohci_start_timer:
7477 *
7478 * Start the ohci timer
7479 */
7480 static void
ohci_start_timer(ohci_state_t * ohcip)7481 ohci_start_timer(ohci_state_t *ohcip)
7482 {
7483 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
7484 "ohci_start_timer: ohcip = 0x%p", (void *)ohcip);
7485
7486 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7487
7488 /*
7489 * Start the global timer only if currently timer is not
7490 * running and if there are any transfers on the timeout
7491 * list. This timer will be per USB Host Controller.
7492 */
7493 if ((!ohcip->ohci_timer_id) && (ohcip->ohci_timeout_list)) {
7494 ohcip->ohci_timer_id = timeout(ohci_xfer_timeout_handler,
7495 (void *)ohcip, drv_usectohz(1000000));
7496 }
7497 }
7498
7499
7500 /*
7501 * ohci_deallocate_tw_resources:
7502 * NOTE: This function is also called from POLLED MODE.
7503 *
7504 * Deallocate of a Transaction Wrapper (TW) and this involves the freeing of
7505 * of DMA resources.
7506 */
7507 void
ohci_deallocate_tw_resources(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw)7508 ohci_deallocate_tw_resources(
7509 ohci_state_t *ohcip,
7510 ohci_pipe_private_t *pp,
7511 ohci_trans_wrapper_t *tw)
7512 {
7513 ohci_trans_wrapper_t *prev, *next;
7514
7515 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7516 "ohci_deallocate_tw_resources: tw = 0x%p", (void *)tw);
7517
7518 /*
7519 * If the transfer wrapper has no Host Controller (HC)
7520 * Transfer Descriptors (TD) associated with it, then
7521 * remove the transfer wrapper.
7522 */
7523 if (tw->tw_hctd_head) {
7524 ASSERT(tw->tw_hctd_tail != NULL);
7525
7526 return;
7527 }
7528
7529 ASSERT(tw->tw_hctd_tail == NULL);
7530
7531 /* Make sure we return all the unused td's to the pool as well */
7532 ohci_free_tw_tds_resources(ohcip, tw);
7533
7534 /*
7535 * If pp->pp_tw_head and pp->pp_tw_tail are pointing to
7536 * given TW then set the head and tail equal to NULL.
7537 * Otherwise search for this TW in the linked TW's list
7538 * and then remove this TW from the list.
7539 */
7540 if (pp->pp_tw_head == tw) {
7541 if (pp->pp_tw_tail == tw) {
7542 pp->pp_tw_head = NULL;
7543 pp->pp_tw_tail = NULL;
7544 } else {
7545 pp->pp_tw_head = tw->tw_next;
7546 }
7547 } else {
7548 prev = pp->pp_tw_head;
7549 next = prev->tw_next;
7550
7551 while (next && (next != tw)) {
7552 prev = next;
7553 next = next->tw_next;
7554 }
7555
7556 if (next == tw) {
7557 prev->tw_next = next->tw_next;
7558
7559 if (pp->pp_tw_tail == tw) {
7560 pp->pp_tw_tail = prev;
7561 }
7562 }
7563 }
7564
7565 ohci_free_tw(ohcip, tw);
7566 }
7567
7568
7569 /*
7570 * ohci_free_dma_resources:
7571 *
7572 * Free dma resources of a Transfer Wrapper (TW) and also free the TW.
7573 */
7574 static void
ohci_free_dma_resources(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)7575 ohci_free_dma_resources(
7576 ohci_state_t *ohcip,
7577 usba_pipe_handle_data_t *ph)
7578 {
7579 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
7580 ohci_trans_wrapper_t *head_tw = pp->pp_tw_head;
7581 ohci_trans_wrapper_t *next_tw, *tw;
7582
7583 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7584 "ohci_free_dma_resources: ph = 0x%p", (void *)ph);
7585
7586 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7587
7588 /* Process the Transfer Wrappers */
7589 next_tw = head_tw;
7590 while (next_tw) {
7591 tw = next_tw;
7592 next_tw = tw->tw_next;
7593
7594 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7595 "ohci_free_dma_resources: Free TW = 0x%p", (void *)tw);
7596
7597 ohci_free_tw(ohcip, tw);
7598 }
7599
7600 /* Adjust the head and tail pointers */
7601 pp->pp_tw_head = NULL;
7602 pp->pp_tw_tail = NULL;
7603 }
7604
7605
7606 /*
7607 * ohci_free_tw:
7608 *
7609 * Free the Transfer Wrapper (TW).
7610 */
7611 static void
ohci_free_tw(ohci_state_t * ohcip,ohci_trans_wrapper_t * tw)7612 ohci_free_tw(
7613 ohci_state_t *ohcip,
7614 ohci_trans_wrapper_t *tw)
7615 {
7616 int rval, i;
7617
7618 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7619 "ohci_free_tw: tw = 0x%p", (void *)tw);
7620
7621 ASSERT(tw != NULL);
7622 ASSERT(tw->tw_id != 0);
7623
7624 /* Free 32bit ID */
7625 OHCI_FREE_ID((uint32_t)tw->tw_id);
7626
7627 if (tw->tw_isoc_strtlen > 0) {
7628 ASSERT(tw->tw_isoc_bufs != NULL);
7629 for (i = 0; i < tw->tw_ncookies; i++) {
7630 if (tw->tw_isoc_bufs[i].ncookies > 0) {
7631 rval = ddi_dma_unbind_handle(
7632 tw->tw_isoc_bufs[i].dma_handle);
7633 ASSERT(rval == USB_SUCCESS);
7634 }
7635 ddi_dma_mem_free(&tw->tw_isoc_bufs[i].mem_handle);
7636 ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
7637 }
7638 kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
7639 } else if (tw->tw_dmahandle != NULL) {
7640 if (tw->tw_ncookies > 0) {
7641 rval = ddi_dma_unbind_handle(tw->tw_dmahandle);
7642 ASSERT(rval == DDI_SUCCESS);
7643 }
7644 ddi_dma_mem_free(&tw->tw_accesshandle);
7645 ddi_dma_free_handle(&tw->tw_dmahandle);
7646 }
7647
7648 /* Free transfer wrapper */
7649 kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7650 }
7651
7652
7653 /*
7654 * Interrupt Handling functions
7655 */
7656
7657 /*
7658 * ohci_intr:
7659 *
7660 * OpenHCI (OHCI) interrupt handling routine.
7661 */
7662 static uint_t
ohci_intr(caddr_t arg1,caddr_t arg2)7663 ohci_intr(caddr_t arg1, caddr_t arg2)
7664 {
7665 ohci_state_t *ohcip = (ohci_state_t *)arg1;
7666 uint_t intr;
7667 ohci_td_t *done_head = NULL;
7668 ohci_save_intr_sts_t *ohci_intr_sts = &ohcip->ohci_save_intr_sts;
7669
7670 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7671 "ohci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p",
7672 (void *)arg1, (void *)arg2);
7673
7674 mutex_enter(&ohcip->ohci_int_mutex);
7675
7676 /* Any interrupt is not handled for the suspended device. */
7677 if (ohcip->ohci_hc_soft_state == OHCI_CTLR_SUSPEND_STATE) {
7678 mutex_exit(&ohcip->ohci_int_mutex);
7679
7680 return (DDI_INTR_UNCLAIMED);
7681 }
7682
7683 /*
7684 * Suppose if we switched to the polled mode from the normal
7685 * mode when interrupt handler is executing then we need to
7686 * save the interrupt status information in the polled mode
7687 * to avoid race conditions. The following flag will be set
7688 * and reset on entering & exiting of ohci interrupt handler
7689 * respectively. This flag will be used in the polled mode
7690 * to check whether the interrupt handler was running when we
7691 * switched to the polled mode from the normal mode.
7692 */
7693 ohci_intr_sts->ohci_intr_flag = OHCI_INTR_HANDLING;
7694
7695 /* Temporarily turn off interrupts */
7696 Set_OpReg(hcr_intr_disable, HCR_INTR_MIE);
7697
7698 /*
7699 * Handle any missed ohci interrupt especially WriteDoneHead
7700 * and SOF interrupts because of previous polled mode switch.
7701 */
7702 ohci_handle_missed_intr(ohcip);
7703
7704 /*
7705 * Now process the actual ohci interrupt events that caused
7706 * invocation of this ohci interrupt handler.
7707 */
7708
7709 /*
7710 * Updating the WriteDoneHead interrupt:
7711 *
7712 * (a) Host Controller
7713 *
7714 * - First Host controller (HC) checks whether WDH bit
7715 * in the interrupt status register is cleared.
7716 *
7717 * - If WDH bit is cleared then HC writes new done head
7718 * list information into the HCCA done head field.
7719 *
7720 * - Set WDH bit in the interrupt status register.
7721 *
7722 * (b) Host Controller Driver (HCD)
7723 *
7724 * - First read the interrupt status register. The HCCA
7725 * done head and WDH bit may be set or may not be set
7726 * while reading the interrupt status register.
7727 *
7728 * - Read the HCCA done head list. By this time may be
7729 * HC has updated HCCA done head and WDH bit in ohci
7730 * interrupt status register.
7731 *
7732 * - If done head is non-null and if WDH bit is not set
7733 * then Host Controller has updated HCCA done head &
7734 * WDH bit in the interrupt stats register in between
7735 * reading the interrupt status register & HCCA done
7736 * head. In that case, definitely WDH bit will be set
7737 * in the interrupt status register & driver can take
7738 * it for granted.
7739 *
7740 * Now read the Interrupt Status & Interrupt enable register
7741 * to determine the exact interrupt events.
7742 */
7743 intr = ohci_intr_sts->ohci_curr_intr_sts =
7744 (Get_OpReg(hcr_intr_status) & Get_OpReg(hcr_intr_enable));
7745
7746 if (ohcip->ohci_hccap) {
7747 /* Sync HCCA area */
7748 Sync_HCCA(ohcip);
7749
7750 /* Read and Save the HCCA DoneHead value */
7751 done_head = ohci_intr_sts->ohci_curr_done_lst =
7752 (ohci_td_t *)(uintptr_t)
7753 (Get_HCCA(ohcip->ohci_hccap->HccaDoneHead) &
7754 HCCA_DONE_HEAD_MASK);
7755
7756 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7757 "ohci_intr: Done head! 0x%p", (void *)done_head);
7758 }
7759
7760 /* Update kstat values */
7761 ohci_do_intrs_stats(ohcip, intr);
7762
7763 /*
7764 * Look at the HccaDoneHead, if it is a non-zero valid address,
7765 * a done list update interrupt is indicated. Otherwise, this
7766 * intr bit is cleared.
7767 */
7768 if (ohci_check_done_head(ohcip, done_head) == USB_SUCCESS) {
7769
7770 /* Set the WriteDoneHead bit in the interrupt events */
7771 intr |= HCR_INTR_WDH;
7772 } else {
7773
7774 /* Clear the WriteDoneHead bit */
7775 intr &= ~HCR_INTR_WDH;
7776 }
7777
7778 /*
7779 * We could have gotten a spurious interrupts. If so, do not
7780 * claim it. This is quite possible on some architectures
7781 * where more than one PCI slots share the IRQs. If so, the
7782 * associated driver's interrupt routine may get called even
7783 * if the interrupt is not meant for them.
7784 *
7785 * By unclaiming the interrupt, the other driver gets chance
7786 * to service its interrupt.
7787 */
7788 if (!intr) {
7789
7790 /* Reset the interrupt handler flag */
7791 ohci_intr_sts->ohci_intr_flag &= ~OHCI_INTR_HANDLING;
7792
7793 Set_OpReg(hcr_intr_enable, HCR_INTR_MIE);
7794 mutex_exit(&ohcip->ohci_int_mutex);
7795 return (DDI_INTR_UNCLAIMED);
7796 }
7797
7798 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7799 "Interrupt status 0x%x", intr);
7800
7801 /*
7802 * Check for Frame Number Overflow.
7803 */
7804 if (intr & HCR_INTR_FNO) {
7805 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7806 "ohci_intr: Frame Number Overflow");
7807
7808 ohci_handle_frame_number_overflow(ohcip);
7809 }
7810
7811 if (intr & HCR_INTR_SOF) {
7812 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7813 "ohci_intr: Start of Frame");
7814
7815 /* Set ohci_sof_flag indicating SOF interrupt occurred */
7816 ohcip->ohci_sof_flag = B_TRUE;
7817
7818 /* Disabel SOF interrupt */
7819 Set_OpReg(hcr_intr_disable, HCR_INTR_SOF);
7820
7821 /*
7822 * Call cv_broadcast on every SOF interrupt to wakeup
7823 * all the threads that are waiting the SOF. Calling
7824 * cv_broadcast on every SOF has no effect even if no
7825 * threads are waiting for the SOF.
7826 */
7827 cv_broadcast(&ohcip->ohci_SOF_cv);
7828 }
7829
7830 if (intr & HCR_INTR_SO) {
7831 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7832 "ohci_intr: Schedule overrun");
7833
7834 ohcip->ohci_so_error++;
7835 }
7836
7837 if ((intr & HCR_INTR_WDH) && (done_head)) {
7838 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7839 "ohci_intr: Done Head");
7840
7841 /*
7842 * Currently if we are processing one WriteDoneHead
7843 * interrupt and also if we switched to the polled
7844 * mode at least once during this time, then there
7845 * may be chance that Host Controller generates one
7846 * more Write DoneHead or Start of Frame interrupts
7847 * for the normal since the polled code clears WDH &
7848 * SOF interrupt bits before returning to the normal
7849 * mode. Under this condition, we must not clear the
7850 * HCCA done head field & also we must not clear WDH
7851 * interrupt bit in the interrupt status register.
7852 */
7853 if (done_head == (ohci_td_t *)(uintptr_t)
7854 (Get_HCCA(ohcip->ohci_hccap->HccaDoneHead) &
7855 HCCA_DONE_HEAD_MASK)) {
7856
7857 /* Reset the done head to NULL */
7858 Set_HCCA(ohcip->ohci_hccap->HccaDoneHead, 0);
7859 } else {
7860 intr &= ~HCR_INTR_WDH;
7861 }
7862
7863 /* Clear the current done head field */
7864 ohci_intr_sts->ohci_curr_done_lst = NULL;
7865
7866 ohci_traverse_done_list(ohcip, done_head);
7867 }
7868
7869 /* Process endpoint reclaimation list */
7870 if (ohcip->ohci_reclaim_list) {
7871 ohci_handle_endpoint_reclaimation(ohcip);
7872 }
7873
7874 if (intr & HCR_INTR_RD) {
7875 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7876 "ohci_intr: Resume Detected");
7877 }
7878
7879 if (intr & HCR_INTR_RHSC) {
7880 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7881 "ohci_intr: Root hub status change");
7882 }
7883
7884 if (intr & HCR_INTR_OC) {
7885 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7886 "ohci_intr: Change ownership");
7887
7888 }
7889
7890 if (intr & HCR_INTR_UE) {
7891 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7892 "ohci_intr: Unrecoverable error");
7893
7894 ohci_handle_ue(ohcip);
7895 }
7896
7897 /* Acknowledge the interrupt */
7898 Set_OpReg(hcr_intr_status, intr);
7899
7900 /* Clear the current interrupt event field */
7901 ohci_intr_sts->ohci_curr_intr_sts = 0;
7902
7903 /*
7904 * Reset the following flag indicating exiting the interrupt
7905 * handler and this flag will be used in the polled mode to
7906 * do some extra processing.
7907 */
7908 ohci_intr_sts->ohci_intr_flag &= ~OHCI_INTR_HANDLING;
7909
7910 Set_OpReg(hcr_intr_enable, HCR_INTR_MIE);
7911
7912 /*
7913 * Read interrupt status register to make sure that any PIO
7914 * store to clear the ISR has made it on the PCI bus before
7915 * returning from its interrupt handler.
7916 */
7917 (void) Get_OpReg(hcr_intr_status);
7918
7919 mutex_exit(&ohcip->ohci_int_mutex);
7920
7921 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7922 "Interrupt handling completed");
7923
7924 return (DDI_INTR_CLAIMED);
7925 }
7926
7927 /*
7928 * Check whether done_head is a valid td point address.
7929 * It should be non-zero, 16-byte aligned, and fall in ohci_td_pool.
7930 */
7931 static int
ohci_check_done_head(ohci_state_t * ohcip,ohci_td_t * done_head)7932 ohci_check_done_head(ohci_state_t *ohcip, ohci_td_t *done_head)
7933 {
7934 uintptr_t lower, upper, headp;
7935 lower = ohcip->ohci_td_pool_cookie.dmac_address;
7936 upper = lower + ohcip->ohci_td_pool_cookie.dmac_size;
7937 headp = (uintptr_t)done_head;
7938
7939 if (headp && !(headp & ~HCCA_DONE_HEAD_MASK) &&
7940 (headp >= lower) && (headp < upper)) {
7941
7942 return (USB_SUCCESS);
7943 } else {
7944
7945 return (USB_FAILURE);
7946 }
7947 }
7948
7949 /*
7950 * ohci_handle_missed_intr:
7951 *
7952 * Handle any ohci missed interrupts because of polled mode switch.
7953 */
7954 static void
ohci_handle_missed_intr(ohci_state_t * ohcip)7955 ohci_handle_missed_intr(ohci_state_t *ohcip)
7956 {
7957 ohci_save_intr_sts_t *ohci_intr_sts =
7958 &ohcip->ohci_save_intr_sts;
7959 ohci_td_t *done_head;
7960 uint_t intr;
7961
7962 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7963
7964 /*
7965 * Check whether we have missed any ohci interrupts because
7966 * of the polled mode switch during previous ohci interrupt
7967 * handler execution. Only Write Done Head & SOF interrupts
7968 * saved in the polled mode. First process these interrupts
7969 * before processing actual interrupts that caused invocation
7970 * of ohci interrupt handler.
7971 */
7972 if (!ohci_intr_sts->ohci_missed_intr_sts) {
7973 /* No interrupts are missed, simply return */
7974
7975 return;
7976 }
7977
7978 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7979 "ohci_handle_missed_intr: Handle ohci missed interrupts");
7980
7981 /*
7982 * The functionality and importance of critical code section
7983 * in the normal mode ohci interrupt handler & its usage in
7984 * the polled mode is explained below.
7985 *
7986 * (a) Normal mode:
7987 *
7988 * - Set the flag indicating that processing critical
7989 * code in ohci interrupt handler.
7990 *
7991 * - Process the missed ohci interrupts by copying the
7992 * miised interrupt events and done head list fields
7993 * information to the critical interrupt event & done
7994 * list fields.
7995 *
7996 * - Reset the missed ohci interrupt events & done head
7997 * list fields so that the new missed interrupt event
7998 * and done head list information can be saved.
7999 *
8000 * - All above steps will be executed with in critical
8001 * section of the interrupt handler.Then ohci missed
8002 * interrupt handler will be called to service missed
8003 * ohci interrupts.
8004 *
8005 * (b) Polled mode:
8006 *
8007 * - On entering the polled code,it checks for critical
8008 * section code execution within the normal mode ohci
8009 * interrupt handler.
8010 *
8011 * - If the critical section code is executing in normal
8012 * mode ohci interrupt handler and if copying of ohci
8013 * missed interrupt events & done head list fields to
8014 * the critical fields is finished then save the "any
8015 * missed interrupt events & done head list" because
8016 * of current polled mode switch into "critical missed
8017 * interrupt events & done list fields" instead actual
8018 * missed events and done list fields.
8019 *
8020 * - Otherwise save "any missed interrupt events & done
8021 * list" because of this current polled mode switch
8022 * in the actual missed interrupt events & done head
8023 * list fields.
8024 */
8025
8026 /*
8027 * Set flag indicating that interrupt handler is processing
8028 * critical interrupt code, so that polled mode code checks
8029 * for this condition & will do extra processing as explained
8030 * above in order to aviod the race conditions.
8031 */
8032 ohci_intr_sts->ohci_intr_flag |= OHCI_INTR_CRITICAL;
8033 ohci_intr_sts->ohci_critical_intr_sts |=
8034 ohci_intr_sts->ohci_missed_intr_sts;
8035
8036 if (ohci_intr_sts->ohci_missed_done_lst) {
8037
8038 ohci_intr_sts->ohci_critical_done_lst =
8039 ohci_intr_sts->ohci_missed_done_lst;
8040 }
8041
8042 ohci_intr_sts->ohci_missed_intr_sts = 0;
8043 ohci_intr_sts->ohci_missed_done_lst = NULL;
8044 ohci_intr_sts->ohci_intr_flag &= ~OHCI_INTR_CRITICAL;
8045
8046 intr = ohci_intr_sts->ohci_critical_intr_sts;
8047 done_head = ohci_intr_sts->ohci_critical_done_lst;
8048
8049 if (intr & HCR_INTR_SOF) {
8050 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8051 "ohci_handle_missed_intr: Start of Frame");
8052
8053 /*
8054 * Call cv_broadcast on every SOF interrupt to wakeup
8055 * all the threads that are waiting the SOF. Calling
8056 * cv_broadcast on every SOF has no effect even if no
8057 * threads are waiting for the SOF.
8058 */
8059 cv_broadcast(&ohcip->ohci_SOF_cv);
8060 }
8061
8062 if ((intr & HCR_INTR_WDH) && (done_head)) {
8063 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8064 "ohci_handle_missed_intr: Done Head");
8065
8066 /* Clear the critical done head field */
8067 ohci_intr_sts->ohci_critical_done_lst = NULL;
8068
8069 ohci_traverse_done_list(ohcip, done_head);
8070 }
8071
8072 /* Clear the critical interrupt event field */
8073 ohci_intr_sts->ohci_critical_intr_sts = 0;
8074 }
8075
8076
8077 /*
8078 * ohci_handle_ue:
8079 *
8080 * Handling of Unrecoverable Error interrupt (UE).
8081 */
8082 static void
ohci_handle_ue(ohci_state_t * ohcip)8083 ohci_handle_ue(ohci_state_t *ohcip)
8084 {
8085 usb_frame_number_t before_frame_number, after_frame_number;
8086
8087 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8088
8089 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8090 "ohci_handle_ue: Handling of UE interrupt");
8091
8092 /*
8093 * First check whether current UE error occured due to USB or
8094 * due to some other subsystem. This can be verified by reading
8095 * usb frame numbers before & after a delay of few milliseconds.
8096 * If usb frame number read after delay is greater than the one
8097 * read before delay, then, USB subsystem is fine. In this case,
8098 * disable UE error interrupt and return without shutdowning the
8099 * USB subsystem.
8100 *
8101 * Otherwise, if usb frame number read after delay is less than
8102 * or equal to one read before the delay, then, current UE error
8103 * occured from USB susbsystem. In this case,go ahead with actual
8104 * UE error recovery procedure.
8105 *
8106 * Get the current usb frame number before waiting for few
8107 * milliseconds.
8108 */
8109 before_frame_number = ohci_get_current_frame_number(ohcip);
8110
8111 /* Wait for few milliseconds */
8112 drv_usecwait(OHCI_TIMEWAIT);
8113
8114 /*
8115 * Get the current usb frame number after waiting for
8116 * milliseconds.
8117 */
8118 after_frame_number = ohci_get_current_frame_number(ohcip);
8119
8120 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8121 "ohci_handle_ue: Before Frm No 0x%llx After Frm No 0x%llx",
8122 (unsigned long long)before_frame_number,
8123 (unsigned long long)after_frame_number);
8124
8125 if (after_frame_number > before_frame_number) {
8126
8127 /* Disable UE interrupt */
8128 Set_OpReg(hcr_intr_disable, HCR_INTR_UE);
8129
8130 return;
8131 }
8132
8133 /*
8134 * This UE is due to USB hardware error. Reset ohci controller
8135 * and reprogram to bring it back to functional state.
8136 */
8137 if ((ohci_do_soft_reset(ohcip)) != USB_SUCCESS) {
8138 USB_DPRINTF_L0(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8139 "Unrecoverable USB Hardware Error");
8140
8141 /* Disable UE interrupt */
8142 Set_OpReg(hcr_intr_disable, HCR_INTR_UE);
8143
8144 /* Set host controller soft state to error */
8145 ohcip->ohci_hc_soft_state = OHCI_CTLR_ERROR_STATE;
8146 }
8147 }
8148
8149
8150 /*
8151 * ohci_handle_frame_number_overflow:
8152 *
8153 * Update software based usb frame number part on every frame number
8154 * overflow interrupt.
8155 *
8156 * NOTE: This function is also called from POLLED MODE.
8157 *
8158 * Refer ohci spec 1.0a, section 5.3, page 81 for more details.
8159 */
8160 void
ohci_handle_frame_number_overflow(ohci_state_t * ohcip)8161 ohci_handle_frame_number_overflow(ohci_state_t *ohcip)
8162 {
8163 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8164 "ohci_handle_frame_number_overflow:");
8165
8166 ohcip->ohci_fno += (0x10000 -
8167 (((Get_HCCA(ohcip->ohci_hccap->HccaFrameNo) &
8168 0xFFFF) ^ ohcip->ohci_fno) & 0x8000));
8169
8170 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8171 "ohci_handle_frame_number_overflow:"
8172 "Frame Number Higher Part 0x%llx\n",
8173 (unsigned long long)(ohcip->ohci_fno));
8174 }
8175
8176
8177 /*
8178 * ohci_handle_endpoint_reclaimation:
8179 *
8180 * Reclamation of Host Controller (HC) Endpoint Descriptors (ED).
8181 */
8182 static void
ohci_handle_endpoint_reclaimation(ohci_state_t * ohcip)8183 ohci_handle_endpoint_reclaimation(ohci_state_t *ohcip)
8184 {
8185 usb_frame_number_t current_frame_number;
8186 usb_frame_number_t endpoint_frame_number;
8187 ohci_ed_t *reclaim_ed;
8188
8189 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8190 "ohci_handle_endpoint_reclaimation:");
8191
8192 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8193
8194 current_frame_number = ohci_get_current_frame_number(ohcip);
8195
8196 /*
8197 * Deallocate all Endpoint Descriptors (ED) which are on the
8198 * reclaimation list. These ED's are already removed from the
8199 * interrupt lattice tree.
8200 */
8201 while (ohcip->ohci_reclaim_list) {
8202 reclaim_ed = ohcip->ohci_reclaim_list;
8203
8204 endpoint_frame_number = (usb_frame_number_t)(uintptr_t)
8205 (OHCI_LOOKUP_ID(Get_ED(reclaim_ed->hced_reclaim_frame)));
8206
8207 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8208 "ohci_handle_endpoint_reclaimation:"
8209 "current frame number 0x%llx endpoint frame number 0x%llx",
8210 (unsigned long long)current_frame_number,
8211 (unsigned long long)endpoint_frame_number);
8212
8213 /*
8214 * Deallocate current endpoint only if endpoint's usb frame
8215 * number is less than or equal to current usb frame number.
8216 *
8217 * If endpoint's usb frame number is greater than the current
8218 * usb frame number, ignore rest of the endpoints in the list
8219 * since rest of the endpoints are inserted into the reclaim
8220 * list later than the current reclaim endpoint.
8221 */
8222 if (endpoint_frame_number > current_frame_number) {
8223 break;
8224 }
8225
8226 /* Get the next endpoint from the rec. list */
8227 ohcip->ohci_reclaim_list = ohci_ed_iommu_to_cpu(ohcip,
8228 Get_ED(reclaim_ed->hced_reclaim_next));
8229
8230 /* Free 32bit ID */
8231 OHCI_FREE_ID((uint32_t)Get_ED(reclaim_ed->hced_reclaim_frame));
8232
8233 /* Deallocate the endpoint */
8234 ohci_deallocate_ed(ohcip, reclaim_ed);
8235 }
8236 }
8237
8238
8239 /*
8240 * ohci_traverse_done_list:
8241 */
8242 static void
ohci_traverse_done_list(ohci_state_t * ohcip,ohci_td_t * head_done_list)8243 ohci_traverse_done_list(
8244 ohci_state_t *ohcip,
8245 ohci_td_t *head_done_list)
8246 {
8247 uint_t state; /* TD state */
8248 ohci_td_t *td, *old_td; /* TD pointers */
8249 usb_cr_t error; /* Error from TD */
8250 ohci_trans_wrapper_t *tw = NULL; /* Transfer wrapper */
8251 ohci_pipe_private_t *pp = NULL; /* Pipe private field */
8252
8253 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8254 "ohci_traverse_done_list:");
8255
8256 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8257
8258 /* Sync ED and TD pool */
8259 Sync_ED_TD_Pool(ohcip);
8260
8261 /* Reverse the done list */
8262 td = ohci_reverse_done_list(ohcip, head_done_list);
8263
8264 /* Traverse the list of transfer descriptors */
8265 while (td) {
8266 /* Check for TD state */
8267 state = Get_TD(td->hctd_state);
8268
8269 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8270 "ohci_traverse_done_list:\n\t"
8271 "td = 0x%p state = 0x%x", (void *)td, state);
8272
8273 /*
8274 * Obtain the transfer wrapper only if the TD is
8275 * not marked as RECLAIM.
8276 *
8277 * A TD that is marked as RECLAIM has had its DMA
8278 * mappings, ED, TD and pipe private structure are
8279 * ripped down. Just deallocate this TD.
8280 */
8281 if (state != HC_TD_RECLAIM) {
8282
8283 tw = (ohci_trans_wrapper_t *)OHCI_LOOKUP_ID(
8284 (uint32_t)Get_TD(td->hctd_trans_wrapper));
8285
8286 ASSERT(tw != NULL);
8287
8288 pp = tw->tw_pipe_private;
8289
8290 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8291 "ohci_traverse_done_list: PP = 0x%p TW = 0x%p",
8292 (void *)pp, (void *)tw);
8293 }
8294
8295 /*
8296 * Don't process the TD if its state is marked as
8297 * either RECLAIM or TIMEOUT.
8298 *
8299 * A TD that is marked as TIMEOUT has already been
8300 * processed by TD timeout handler & client driver
8301 * has been informed through exception callback.
8302 */
8303 if ((state != HC_TD_RECLAIM) && (state != HC_TD_TIMEOUT)) {
8304
8305 /* Look at the error status */
8306 error = ohci_parse_error(ohcip, td);
8307
8308 if (error == USB_CR_OK) {
8309 ohci_handle_normal_td(ohcip, td, tw);
8310 } else {
8311 /* handle the error condition */
8312 ohci_handle_error(ohcip, td, error);
8313 }
8314 } else {
8315 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8316 "ohci_traverse_done_list: TD State = %d", state);
8317 }
8318
8319 /*
8320 * Save a pointer to the current transfer descriptor
8321 */
8322 old_td = td;
8323
8324 td = ohci_td_iommu_to_cpu(ohcip, Get_TD(td->hctd_next_td));
8325
8326 /* Deallocate this transfer descriptor */
8327 ohci_deallocate_td(ohcip, old_td);
8328
8329 /*
8330 * Deallocate the transfer wrapper if there are no more
8331 * TD's for the transfer wrapper. ohci_deallocate_tw_resources()
8332 * will not deallocate the tw for a periodic endpoint
8333 * since it will always have a TD attached to it.
8334 *
8335 * Do not deallocate the TW if it is a isoc or intr pipe in.
8336 * The tw's are reused.
8337 *
8338 * An TD that is marked as reclaim doesn't have a pipe
8339 * or a TW associated with it anymore so don't call this
8340 * function.
8341 */
8342 if (state != HC_TD_RECLAIM) {
8343 ASSERT(tw != NULL);
8344 ohci_deallocate_tw_resources(ohcip, pp, tw);
8345 }
8346 }
8347 }
8348
8349
8350 /*
8351 * ohci_reverse_done_list:
8352 *
8353 * Reverse the order of the Transfer Descriptor (TD) Done List.
8354 */
8355 static ohci_td_t *
ohci_reverse_done_list(ohci_state_t * ohcip,ohci_td_t * head_done_list)8356 ohci_reverse_done_list(
8357 ohci_state_t *ohcip,
8358 ohci_td_t *head_done_list)
8359 {
8360 ohci_td_t *cpu_new_tail, *cpu_new_head, *cpu_save;
8361
8362 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8363 "ohci_reverse_done_list:");
8364
8365 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8366 ASSERT(head_done_list != NULL);
8367
8368 /* At first, both the tail and head pointers point to the same elem */
8369 cpu_new_tail = cpu_new_head =
8370 ohci_td_iommu_to_cpu(ohcip, (uintptr_t)head_done_list);
8371
8372 /* See if the list has only one element */
8373 if (Get_TD(cpu_new_head->hctd_next_td) == 0) {
8374
8375 return (cpu_new_head);
8376 }
8377
8378 /* Advance the head pointer */
8379 cpu_new_head = (ohci_td_t *)
8380 ohci_td_iommu_to_cpu(ohcip, Get_TD(cpu_new_head->hctd_next_td));
8381
8382 /* The new tail now points to nothing */
8383 Set_TD(cpu_new_tail->hctd_next_td, NULL);
8384
8385 cpu_save = (ohci_td_t *)
8386 ohci_td_iommu_to_cpu(ohcip, Get_TD(cpu_new_head->hctd_next_td));
8387
8388 /* Reverse the list and store the pointers as CPU addresses */
8389 while (cpu_save) {
8390 Set_TD(cpu_new_head->hctd_next_td,
8391 ohci_td_cpu_to_iommu(ohcip, cpu_new_tail));
8392
8393 cpu_new_tail = cpu_new_head;
8394 cpu_new_head = cpu_save;
8395
8396 cpu_save = (ohci_td_t *)
8397 ohci_td_iommu_to_cpu(ohcip,
8398 Get_TD(cpu_new_head->hctd_next_td));
8399 }
8400
8401 Set_TD(cpu_new_head->hctd_next_td,
8402 ohci_td_cpu_to_iommu(ohcip, cpu_new_tail));
8403
8404 return (cpu_new_head);
8405 }
8406
8407
8408 /*
8409 * ohci_parse_error:
8410 *
8411 * Parse the result for any errors.
8412 */
8413 static usb_cr_t
ohci_parse_error(ohci_state_t * ohcip,ohci_td_t * td)8414 ohci_parse_error(
8415 ohci_state_t *ohcip,
8416 ohci_td_t *td)
8417 {
8418 uint_t ctrl;
8419 usb_ep_descr_t *eptd;
8420 ohci_trans_wrapper_t *tw;
8421 ohci_pipe_private_t *pp;
8422 uint_t flag;
8423 usb_cr_t error;
8424
8425 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8426 "ohci_parse_error:");
8427
8428 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8429
8430 ASSERT(td != NULL);
8431
8432 /* Obtain the transfer wrapper from the TD */
8433 tw = (ohci_trans_wrapper_t *)
8434 OHCI_LOOKUP_ID((uint32_t)Get_TD(td->hctd_trans_wrapper));
8435
8436 ASSERT(tw != NULL);
8437
8438 /* Obtain the pipe private structure */
8439 pp = tw->tw_pipe_private;
8440
8441 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8442 "ohci_parse_error: PP 0x%p TW 0x%p", (void *)pp, (void *)tw);
8443
8444 eptd = &pp->pp_pipe_handle->p_ep;
8445
8446 ctrl = (uint_t)Get_TD(td->hctd_ctrl) & (uint32_t)HC_TD_CC;
8447
8448 /*
8449 * Check the condition code of completed TD and report errors
8450 * if any. This checking will be done both for the general and
8451 * the isochronous TDs.
8452 */
8453 if ((error = ohci_check_for_error(ohcip, pp, tw, td, ctrl)) !=
8454 USB_CR_OK) {
8455 flag = OHCI_REMOVE_XFER_ALWAYS;
8456 } else {
8457 flag = OHCI_REMOVE_XFER_IFLAST;
8458 }
8459
8460 /* Stop the the transfer timer */
8461 ohci_stop_xfer_timer(ohcip, tw, flag);
8462
8463 /*
8464 * The isochronous endpoint needs additional error checking
8465 * and special processing.
8466 */
8467 if ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
8468 USB_EP_ATTR_ISOCH) {
8469
8470 ohci_parse_isoc_error(ohcip, pp, tw, td);
8471
8472 /* always reset error */
8473 error = USB_CR_OK;
8474 }
8475
8476 return (error);
8477 }
8478
8479
8480 /*
8481 * ohci_parse_isoc_error:
8482 *
8483 * Check for any errors in the isochronous data packets. Also fillup
8484 * the status for each of the isochrnous data packets.
8485 */
8486 void
ohci_parse_isoc_error(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,ohci_td_t * td)8487 ohci_parse_isoc_error(
8488 ohci_state_t *ohcip,
8489 ohci_pipe_private_t *pp,
8490 ohci_trans_wrapper_t *tw,
8491 ohci_td_t *td)
8492 {
8493 usb_isoc_req_t *isoc_reqp;
8494 usb_isoc_pkt_descr_t *isoc_pkt_descr;
8495 uint_t toggle = 0, fc, ctrl, psw;
8496 int i;
8497
8498 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8499 "ohci_parse_isoc_error: td 0x%p", (void *)td);
8500
8501 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8502
8503 fc = ((uint_t)Get_TD(td->hctd_ctrl) &
8504 HC_ITD_FC) >> HC_ITD_FC_SHIFT;
8505
8506 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
8507 "ohci_parse_isoc_error: frame count %d", fc);
8508
8509 /*
8510 * Get the address of current usb isochronous request
8511 * and array of packet descriptors.
8512 */
8513 isoc_reqp = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
8514 isoc_pkt_descr = isoc_reqp->isoc_pkt_descr;
8515 isoc_pkt_descr += tw->tw_pkt_idx;
8516
8517 for (i = 0; i <= fc; i++) {
8518
8519 psw = Get_TD(td->hctd_offsets[i / 2]);
8520
8521 if (toggle) {
8522 ctrl = psw & HC_ITD_ODD_OFFSET;
8523 toggle = 0;
8524 } else {
8525 ctrl = (psw & HC_ITD_EVEN_OFFSET) <<
8526 HC_ITD_OFFSET_SHIFT;
8527 toggle = 1;
8528 }
8529
8530 isoc_pkt_descr->isoc_pkt_actual_length =
8531 (ctrl >> HC_ITD_OFFSET_SHIFT) & HC_ITD_OFFSET_ADDR;
8532
8533 ctrl = (uint_t)(ctrl & (uint32_t)HC_TD_CC);
8534
8535 /* Write the status of isoc data packet */
8536 isoc_pkt_descr->isoc_pkt_status =
8537 ohci_check_for_error(ohcip, pp, tw, td, ctrl);
8538
8539 if (isoc_pkt_descr->isoc_pkt_status) {
8540 /* Increment isoc data packet error count */
8541 isoc_reqp->isoc_error_count++;
8542 }
8543
8544 /*
8545 * Get the address of next isoc data packet descriptor.
8546 */
8547 isoc_pkt_descr++;
8548 }
8549 tw->tw_pkt_idx = tw->tw_pkt_idx + fc + 1;
8550
8551 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
8552 "ohci_parse_isoc_error: tw_pkt_idx %d", tw->tw_pkt_idx);
8553
8554 }
8555
8556
8557 /*
8558 * ohci_check_for_error:
8559 *
8560 * Check for any errors.
8561 */
8562 static usb_cr_t
ohci_check_for_error(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,ohci_td_t * td,uint_t ctrl)8563 ohci_check_for_error(
8564 ohci_state_t *ohcip,
8565 ohci_pipe_private_t *pp,
8566 ohci_trans_wrapper_t *tw,
8567 ohci_td_t *td,
8568 uint_t ctrl)
8569 {
8570 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
8571 uchar_t ep_attrs = ph->p_ep.bmAttributes;
8572 usb_cr_t error = USB_CR_OK;
8573 usb_req_attrs_t xfer_attrs;
8574
8575 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8576 "ohci_check_for_error: td = 0x%p ctrl = 0x%x",
8577 (void *)td, ctrl);
8578
8579 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8580
8581 switch (ctrl) {
8582 case HC_TD_CC_NO_E:
8583 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8584 "ohci_check_for_error: No Error");
8585 error = USB_CR_OK;
8586 break;
8587 case HC_TD_CC_CRC:
8588 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8589 "ohci_check_for_error: CRC error");
8590 error = USB_CR_CRC;
8591 break;
8592 case HC_TD_CC_BS:
8593 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8594 "ohci_check_for_error: Bit stuffing");
8595 error = USB_CR_BITSTUFFING;
8596 break;
8597 case HC_TD_CC_DTM:
8598 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8599 "ohci_check_for_error: Data Toggle Mismatch");
8600 error = USB_CR_DATA_TOGGLE_MM;
8601 break;
8602 case HC_TD_CC_STALL:
8603 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8604 "ohci_check_for_error: Stall");
8605 error = USB_CR_STALL;
8606 break;
8607 case HC_TD_CC_DNR:
8608 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8609 "ohci_check_for_error: Device not responding");
8610 error = USB_CR_DEV_NOT_RESP;
8611 break;
8612 case HC_TD_CC_PCF:
8613 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8614 "ohci_check_for_error: PID check failure");
8615 error = USB_CR_PID_CHECKFAILURE;
8616 break;
8617 case HC_TD_CC_UPID:
8618 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8619 "ohci_check_for_error: Unexpected PID");
8620 error = USB_CR_UNEXP_PID;
8621 break;
8622 case HC_TD_CC_DO:
8623 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8624 "ohci_check_for_error: Data overrrun");
8625 error = USB_CR_DATA_OVERRUN;
8626 break;
8627 case HC_TD_CC_DU:
8628 /*
8629 * Check whether short packets are acceptable.
8630 * If so don't report error to client drivers
8631 * and restart the endpoint. Otherwise report
8632 * data underrun error to client driver.
8633 */
8634 xfer_attrs = ohci_get_xfer_attrs(ohcip, pp, tw);
8635
8636 if (xfer_attrs & USB_ATTRS_SHORT_XFER_OK) {
8637 error = USB_CR_OK;
8638 if ((ep_attrs & USB_EP_ATTR_MASK) !=
8639 USB_EP_ATTR_ISOCH) {
8640 /*
8641 * Cleanup the remaining resources that may have
8642 * been allocated for this transfer.
8643 */
8644 if (ohci_cleanup_data_underrun(ohcip, pp, tw,
8645 td) == USB_SUCCESS) {
8646 /* Clear the halt bit */
8647 Set_ED(pp->pp_ept->hced_headp,
8648 (Get_ED(pp->pp_ept->hced_headp) &
8649 ~HC_EPT_Halt));
8650 } else {
8651 error = USB_CR_UNSPECIFIED_ERR;
8652 }
8653 }
8654 } else {
8655 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8656 "ohci_check_for_error: Data underrun");
8657
8658 error = USB_CR_DATA_UNDERRUN;
8659 }
8660
8661 break;
8662 case HC_TD_CC_BO:
8663 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8664 "ohci_check_for_error: Buffer overrun");
8665 error = USB_CR_BUFFER_OVERRUN;
8666 break;
8667 case HC_TD_CC_BU:
8668 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8669 "ohci_check_for_error: Buffer underrun");
8670 error = USB_CR_BUFFER_UNDERRUN;
8671 break;
8672 case HC_TD_CC_NA:
8673 default:
8674 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8675 "ohci_check_for_error: Not accessed");
8676 error = USB_CR_NOT_ACCESSED;
8677 break;
8678 }
8679
8680 if (error) {
8681 uint_t hced_ctrl = Get_ED(pp->pp_ept->hced_ctrl);
8682
8683 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8684 "ohci_check_for_error: Error %d Device address %d "
8685 "Endpoint number %d", error, (hced_ctrl & HC_EPT_FUNC),
8686 ((hced_ctrl & HC_EPT_EP) >> HC_EPT_EP_SHFT));
8687 }
8688
8689 return (error);
8690 }
8691
8692
8693 /*
8694 * ohci_handle_error:
8695 *
8696 * Inform USBA about occured transaction errors by calling the USBA callback
8697 * routine.
8698 */
8699 static void
ohci_handle_error(ohci_state_t * ohcip,ohci_td_t * td,usb_cr_t error)8700 ohci_handle_error(
8701 ohci_state_t *ohcip,
8702 ohci_td_t *td,
8703 usb_cr_t error)
8704 {
8705 ohci_trans_wrapper_t *tw;
8706 usba_pipe_handle_data_t *ph;
8707 ohci_pipe_private_t *pp;
8708 mblk_t *mp = NULL;
8709 size_t length = 0;
8710 uchar_t attributes;
8711 usb_intr_req_t *curr_intr_reqp;
8712
8713 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8714 "ohci_handle_error: error = 0x%x", error);
8715
8716 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8717
8718 ASSERT(td != NULL);
8719
8720 /* Print the values in the td */
8721 ohci_print_td(ohcip, td);
8722
8723 /* Obtain the transfer wrapper from the TD */
8724 tw = (ohci_trans_wrapper_t *)
8725 OHCI_LOOKUP_ID((uint32_t)Get_TD(td->hctd_trans_wrapper));
8726
8727 ASSERT(tw != NULL);
8728
8729 /* Obtain the pipe private structure */
8730 pp = tw->tw_pipe_private;
8731
8732 ph = tw->tw_pipe_private->pp_pipe_handle;
8733 attributes = ph->p_ep.bmAttributes & USB_EP_ATTR_MASK;
8734
8735 /*
8736 * Special error handling
8737 */
8738 if (tw->tw_direction == HC_TD_IN) {
8739
8740 switch (attributes) {
8741 case USB_EP_ATTR_CONTROL:
8742 if (((ph->p_ep.bmAttributes &
8743 USB_EP_ATTR_MASK) ==
8744 USB_EP_ATTR_CONTROL) &&
8745 (Get_TD(td->hctd_ctrl_phase) ==
8746 OHCI_CTRL_SETUP_PHASE)) {
8747
8748 break;
8749 }
8750 /* FALLTHROUGH */
8751 case USB_EP_ATTR_BULK:
8752 /*
8753 * Call ohci_sendup_td_message
8754 * to send message to upstream.
8755 */
8756 ohci_sendup_td_message(ohcip, pp, tw, td, error);
8757
8758 return;
8759 case USB_EP_ATTR_INTR:
8760 curr_intr_reqp =
8761 (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
8762
8763 if (curr_intr_reqp->intr_attributes &
8764 USB_ATTRS_ONE_XFER) {
8765
8766 ohci_handle_one_xfer_completion(ohcip, tw);
8767 }
8768
8769 /* Decrement periodic in request count */
8770 pp->pp_cur_periodic_req_cnt--;
8771 break;
8772 case USB_EP_ATTR_ISOCH:
8773 default:
8774 break;
8775 }
8776 } else {
8777 switch (attributes) {
8778 case USB_EP_ATTR_BULK:
8779 case USB_EP_ATTR_INTR:
8780 /*
8781 * If "CurrentBufferPointer" of Transfer
8782 * Descriptor (TD) is not equal to zero,
8783 * then we sent less data to the device
8784 * than requested by client. In that case,
8785 * return the mblk after updating the
8786 * data->r_ptr.
8787 */
8788 if (Get_TD(td->hctd_cbp)) {
8789 usb_opaque_t xfer_reqp = tw->tw_curr_xfer_reqp;
8790 size_t residue;
8791
8792 residue = ohci_get_td_residue(ohcip, td);
8793 length = Get_TD(td->hctd_xfer_offs) +
8794 Get_TD(td->hctd_xfer_len) - residue;
8795
8796 USB_DPRINTF_L2(PRINT_MASK_INTR,
8797 ohcip->ohci_log_hdl,
8798 "ohci_handle_error: requested data %lu "
8799 "sent data %lu", tw->tw_length, length);
8800
8801 if (attributes == USB_EP_ATTR_BULK) {
8802 mp = (mblk_t *)((usb_bulk_req_t *)
8803 (xfer_reqp))->bulk_data;
8804 } else {
8805 mp = (mblk_t *)((usb_intr_req_t *)
8806 (xfer_reqp))->intr_data;
8807 }
8808
8809 /* Increment the read pointer */
8810 mp->b_rptr = mp->b_rptr + length;
8811 }
8812 break;
8813 default:
8814 break;
8815 }
8816 }
8817
8818 /*
8819 * Callback the client with the
8820 * failure reason.
8821 */
8822 ohci_hcdi_callback(ph, tw, error);
8823
8824 /* Check anybody is waiting for transfers completion event */
8825 ohci_check_for_transfers_completion(ohcip, pp);
8826 }
8827
8828 /*
8829 * ohci_cleanup_data_underrun:
8830 *
8831 * Cleans up resources when a short xfer occurs
8832 */
8833 static int
ohci_cleanup_data_underrun(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,ohci_td_t * td)8834 ohci_cleanup_data_underrun(
8835 ohci_state_t *ohcip,
8836 ohci_pipe_private_t *pp,
8837 ohci_trans_wrapper_t *tw,
8838 ohci_td_t *td)
8839 {
8840 ohci_td_t *next_td;
8841 ohci_td_t *last_td;
8842 ohci_td_t *temp_td;
8843 uint32_t last_td_addr;
8844 uint_t hced_head;
8845
8846 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8847 "ohci_cleanup_data_underrun: td 0x%p, tw 0x%p",
8848 (void *)td, (void *)tw);
8849
8850 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8851 ASSERT(tw->tw_hctd_head == td);
8852
8853 /* Check if this TD is the last td in the tw */
8854 last_td = tw->tw_hctd_tail;
8855 if (td == last_td) {
8856 /* There is no need for cleanup */
8857 return (USB_SUCCESS);
8858 }
8859
8860 /*
8861 * Make sure the ED is halted before we change any td's.
8862 * If for some reason it is not halted, return error to client
8863 * driver so they can reset the port.
8864 */
8865 hced_head = Get_ED(pp->pp_ept->hced_headp);
8866 if (!(hced_head & HC_EPT_Halt)) {
8867 uint_t hced_ctrl = Get_ED(pp->pp_ept->hced_ctrl);
8868
8869 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8870 "ohci_cleanup_data_underrun: Unable to clean up a short "
8871 "xfer error. Client might send/receive irrelevant data."
8872 " Device address %d Endpoint number %d",
8873 (hced_ctrl & HC_EPT_FUNC),
8874 ((hced_ctrl & HC_EPT_EP) >> HC_EPT_EP_SHFT));
8875
8876 Set_ED(pp->pp_ept->hced_headp, hced_head | HC_EPT_Halt);
8877
8878 return (USB_FAILURE);
8879 }
8880
8881 /*
8882 * Get the address of the first td of the next transfer (tw).
8883 * This td, may currently be a dummy td, but when a new request
8884 * arrives, it will be transformed into a regular td.
8885 */
8886 last_td_addr = Get_TD(last_td->hctd_next_td);
8887 /* Set ED head to this last td */
8888 Set_ED(pp->pp_ept->hced_headp,
8889 (last_td_addr & HC_EPT_TD_HEAD) |
8890 (hced_head & ~HC_EPT_TD_HEAD));
8891
8892 /*
8893 * Start removing all the unused TD's from the TW,
8894 * but keep the first one.
8895 */
8896 tw->tw_hctd_tail = td;
8897
8898 /*
8899 * Get the last_td, the next td in the tw list.
8900 * Afterwards completely disassociate the current td from other tds
8901 */
8902 next_td = (ohci_td_t *)ohci_td_iommu_to_cpu(ohcip,
8903 Get_TD(td->hctd_tw_next_td));
8904 Set_TD(td->hctd_tw_next_td, NULL);
8905
8906 /*
8907 * Iterate down the tw list and deallocate them
8908 */
8909 while (next_td != NULL) {
8910 tw->tw_num_tds--;
8911 /* Disassociate this td from it's TW and set to RECLAIM */
8912 Set_TD(next_td->hctd_trans_wrapper, NULL);
8913 Set_TD(next_td->hctd_state, HC_TD_RECLAIM);
8914
8915 temp_td = next_td;
8916
8917 next_td = (ohci_td_t *)ohci_td_iommu_to_cpu(ohcip,
8918 Get_TD(next_td->hctd_tw_next_td));
8919
8920 ohci_deallocate_td(ohcip, temp_td);
8921 }
8922
8923 ASSERT(tw->tw_num_tds == 1);
8924
8925 return (USB_SUCCESS);
8926 }
8927
8928 /*
8929 * ohci_handle_normal_td:
8930 */
8931 static void
ohci_handle_normal_td(ohci_state_t * ohcip,ohci_td_t * td,ohci_trans_wrapper_t * tw)8932 ohci_handle_normal_td(
8933 ohci_state_t *ohcip,
8934 ohci_td_t *td,
8935 ohci_trans_wrapper_t *tw)
8936 {
8937 ohci_pipe_private_t *pp; /* Pipe private field */
8938
8939 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8940 "ohci_handle_normal_td:");
8941
8942 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8943 ASSERT(tw != NULL);
8944
8945 /* Obtain the pipe private structure */
8946 pp = tw->tw_pipe_private;
8947
8948 (*tw->tw_handle_td)(ohcip, pp, tw,
8949 td, tw->tw_handle_callback_value);
8950
8951 /* Check anybody is waiting for transfers completion event */
8952 ohci_check_for_transfers_completion(ohcip, pp);
8953 }
8954
8955
8956 /*
8957 * ohci_handle_ctrl_td:
8958 *
8959 * Handle a control Transfer Descriptor (TD).
8960 */
8961 /* ARGSUSED */
8962 static void
ohci_handle_ctrl_td(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,ohci_td_t * td,void * tw_handle_callback_value)8963 ohci_handle_ctrl_td(
8964 ohci_state_t *ohcip,
8965 ohci_pipe_private_t *pp,
8966 ohci_trans_wrapper_t *tw,
8967 ohci_td_t *td,
8968 void *tw_handle_callback_value)
8969 {
8970 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
8971
8972 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8973 "ohci_handle_ctrl_td: pp = 0x%p tw = 0x%p td = 0x%p state = 0x%x",
8974 (void *)pp, (void *)tw, (void *)td, Get_TD(td->hctd_ctrl_phase));
8975
8976 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8977
8978 /*
8979 * Check which control transfer phase got completed.
8980 */
8981 tw->tw_num_tds--;
8982 switch (Get_TD(td->hctd_ctrl_phase)) {
8983 case OHCI_CTRL_SETUP_PHASE:
8984 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8985 "Setup complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
8986
8987 break;
8988 case OHCI_CTRL_DATA_PHASE:
8989 /*
8990 * If "CurrentBufferPointer" of Transfer Descriptor (TD)
8991 * is not equal to zero, then we received less data from
8992 * the device than requested by us. In that case, get the
8993 * actual received data size.
8994 */
8995 if (Get_TD(td->hctd_cbp)) {
8996 size_t length, residue;
8997
8998 residue = ohci_get_td_residue(ohcip, td);
8999 length = Get_TD(td->hctd_xfer_offs) +
9000 Get_TD(td->hctd_xfer_len) - residue;
9001
9002 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9003 "ohci_handle_ctrl_qtd: requested data %lu "
9004 "received data %lu", tw->tw_length, length);
9005
9006 /* Save actual received data length */
9007 tw->tw_length = length;
9008 }
9009
9010 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9011 "Data complete: pp 0x%p td 0x%p",
9012 (void *)pp, (void *)td);
9013
9014 break;
9015 case OHCI_CTRL_STATUS_PHASE:
9016 if ((tw->tw_length != 0) &&
9017 (tw->tw_direction == HC_TD_IN)) {
9018
9019 /*
9020 * Call ohci_sendup_td_message
9021 * to send message to upstream.
9022 */
9023 ohci_sendup_td_message(ohcip,
9024 pp, tw, td, USB_CR_OK);
9025 } else {
9026 ohci_do_byte_stats(ohcip,
9027 tw->tw_length - OHCI_MAX_TD_BUF_SIZE,
9028 ph->p_ep.bmAttributes,
9029 ph->p_ep.bEndpointAddress);
9030
9031 ohci_hcdi_callback(ph, tw, USB_CR_OK);
9032 }
9033
9034 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9035 "Status complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
9036
9037 break;
9038 }
9039 }
9040
9041
9042 /*
9043 * ohci_handle_bulk_td:
9044 *
9045 * Handle a bulk Transfer Descriptor (TD).
9046 */
9047 /* ARGSUSED */
9048 static void
ohci_handle_bulk_td(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,ohci_td_t * td,void * tw_handle_callback_value)9049 ohci_handle_bulk_td(
9050 ohci_state_t *ohcip,
9051 ohci_pipe_private_t *pp,
9052 ohci_trans_wrapper_t *tw,
9053 ohci_td_t *td,
9054 void *tw_handle_callback_value)
9055 {
9056 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
9057 usb_ep_descr_t *eptd = &ph->p_ep;
9058
9059 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9060 "ohci_handle_bulk_td:");
9061
9062 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9063
9064 /*
9065 * Decrement the TDs counter and check whether all the bulk
9066 * data has been send or received. If TDs counter reaches
9067 * zero then inform client driver about completion current
9068 * bulk request. Other wise wait for completion of other bulk
9069 * TDs or transactions on this pipe.
9070 */
9071 if (--tw->tw_num_tds != 0) {
9072
9073 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9074 "ohci_handle_bulk_td: Number of TDs %d", tw->tw_num_tds);
9075
9076 return;
9077 }
9078
9079 /*
9080 * If this is a bulk in pipe, return the data to the client.
9081 * For a bulk out pipe, there is no need to do anything.
9082 */
9083 if ((eptd->bEndpointAddress &
9084 USB_EP_DIR_MASK) == USB_EP_DIR_OUT) {
9085
9086 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9087 "ohci_handle_bulk_td: Bulk out pipe");
9088
9089 ohci_do_byte_stats(ohcip, tw->tw_length,
9090 eptd->bmAttributes, eptd->bEndpointAddress);
9091
9092 /* Do the callback */
9093 ohci_hcdi_callback(ph, tw, USB_CR_OK);
9094
9095 return;
9096 }
9097
9098 /* Call ohci_sendup_td_message to send message to upstream */
9099 ohci_sendup_td_message(ohcip, pp, tw, td, USB_CR_OK);
9100 }
9101
9102
9103 /*
9104 * ohci_handle_intr_td:
9105 *
9106 * Handle a interrupt Transfer Descriptor (TD).
9107 */
9108 /* ARGSUSED */
9109 static void
ohci_handle_intr_td(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,ohci_td_t * td,void * tw_handle_callback_value)9110 ohci_handle_intr_td(
9111 ohci_state_t *ohcip,
9112 ohci_pipe_private_t *pp,
9113 ohci_trans_wrapper_t *tw,
9114 ohci_td_t *td,
9115 void *tw_handle_callback_value)
9116 {
9117 usb_intr_req_t *curr_intr_reqp =
9118 (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
9119 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
9120 usb_ep_descr_t *eptd = &ph->p_ep;
9121 usb_req_attrs_t attrs;
9122 int error = USB_SUCCESS;
9123
9124 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9125 "ohci_handle_intr_td: pp=0x%p tw=0x%p td=0x%p"
9126 "intr_reqp=0%p data=0x%p", (void *)pp, (void *)tw, (void *)td,
9127 (void *)curr_intr_reqp, (void *)curr_intr_reqp->intr_data);
9128
9129 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9130
9131 /* Get the interrupt xfer attributes */
9132 attrs = curr_intr_reqp->intr_attributes;
9133
9134 /*
9135 * For a Interrupt OUT pipe, we just callback and we are done
9136 */
9137 if ((eptd->bEndpointAddress & USB_EP_DIR_MASK) == USB_EP_DIR_OUT) {
9138
9139 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9140 "ohci_handle_intr_td: Intr out pipe, intr_reqp=0x%p,"
9141 "data=0x%p", (void *)curr_intr_reqp,
9142 (void *)curr_intr_reqp->intr_data);
9143
9144 ohci_do_byte_stats(ohcip, tw->tw_length,
9145 eptd->bmAttributes, eptd->bEndpointAddress);
9146
9147 /* Do the callback */
9148 ohci_hcdi_callback(ph, tw, USB_CR_OK);
9149
9150 return;
9151 }
9152
9153 /* Decrement number of interrupt request count */
9154 pp->pp_cur_periodic_req_cnt--;
9155
9156 /*
9157 * Check usb flag whether USB_FLAGS_ONE_XFER flag is set
9158 * and if so, free duplicate request.
9159 */
9160 if (attrs & USB_ATTRS_ONE_XFER) {
9161 ohci_handle_one_xfer_completion(ohcip, tw);
9162 }
9163
9164 /* Call ohci_sendup_td_message to callback into client */
9165 ohci_sendup_td_message(ohcip, pp, tw, td, USB_CR_OK);
9166
9167 /*
9168 * If interrupt pipe state is still active, insert next Interrupt
9169 * request into the Host Controller's Interrupt list. Otherwise
9170 * you are done.
9171 */
9172 if (pp->pp_state != OHCI_PIPE_STATE_ACTIVE) {
9173 return;
9174 }
9175
9176 if ((error = ohci_allocate_periodic_in_resource(ohcip, pp, tw, 0)) ==
9177 USB_SUCCESS) {
9178 curr_intr_reqp = (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
9179
9180 ASSERT(curr_intr_reqp != NULL);
9181
9182 tw->tw_num_tds = 1;
9183
9184 if (ohci_tw_rebind_cookie(ohcip, pp, tw) != USB_SUCCESS) {
9185 ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
9186 error = USB_FAILURE;
9187 } else if (ohci_allocate_tds_for_tw(ohcip, tw,
9188 tw->tw_num_tds) != USB_SUCCESS) {
9189 ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
9190 error = USB_FAILURE;
9191 }
9192 }
9193
9194 if (error != USB_SUCCESS) {
9195 /*
9196 * Set pipe state to stop polling and error to no
9197 * resource. Don't insert any more interrupt polling
9198 * requests.
9199 */
9200 pp->pp_state = OHCI_PIPE_STATE_STOP_POLLING;
9201 pp->pp_error = USB_CR_NO_RESOURCES;
9202 } else {
9203 ohci_insert_intr_req(ohcip, pp, tw, 0);
9204
9205 /* Increment number of interrupt request count */
9206 pp->pp_cur_periodic_req_cnt++;
9207
9208 ASSERT(pp->pp_cur_periodic_req_cnt ==
9209 pp->pp_max_periodic_req_cnt);
9210 }
9211 }
9212
9213
9214 /*
9215 * ohci_handle_one_xfer_completion:
9216 */
9217 static void
ohci_handle_one_xfer_completion(ohci_state_t * ohcip,ohci_trans_wrapper_t * tw)9218 ohci_handle_one_xfer_completion(
9219 ohci_state_t *ohcip,
9220 ohci_trans_wrapper_t *tw)
9221 {
9222 usba_pipe_handle_data_t *ph = tw->tw_pipe_private->pp_pipe_handle;
9223 ohci_pipe_private_t *pp = tw->tw_pipe_private;
9224 usb_intr_req_t *curr_intr_reqp =
9225 (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
9226
9227 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9228 "ohci_handle_one_xfer_completion: tw = 0x%p", (void *)tw);
9229
9230 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9231 ASSERT(curr_intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER);
9232
9233 pp->pp_state = OHCI_PIPE_STATE_IDLE;
9234
9235 /*
9236 * For one xfer, we need to copy back data ptr
9237 * and free current request
9238 */
9239 ((usb_intr_req_t *)(pp->pp_client_periodic_in_reqp))->
9240 intr_data = ((usb_intr_req_t *)
9241 (tw->tw_curr_xfer_reqp))->intr_data;
9242
9243 ((usb_intr_req_t *)tw->tw_curr_xfer_reqp)->intr_data = NULL;
9244
9245 /* Now free duplicate current request */
9246 usb_free_intr_req((usb_intr_req_t *)tw-> tw_curr_xfer_reqp);
9247
9248 mutex_enter(&ph->p_mutex);
9249 ph->p_req_count--;
9250 mutex_exit(&ph->p_mutex);
9251
9252 /* Make client's request the current request */
9253 tw->tw_curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
9254 pp->pp_client_periodic_in_reqp = NULL;
9255 }
9256
9257
9258 /*
9259 * ohci_handle_isoc_td:
9260 *
9261 * Handle an isochronous Transfer Descriptor (TD).
9262 */
9263 /* ARGSUSED */
9264 static void
ohci_handle_isoc_td(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,ohci_td_t * td,void * tw_handle_callback_value)9265 ohci_handle_isoc_td(
9266 ohci_state_t *ohcip,
9267 ohci_pipe_private_t *pp,
9268 ohci_trans_wrapper_t *tw,
9269 ohci_td_t *td,
9270 void *tw_handle_callback_value)
9271 {
9272 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
9273 usb_ep_descr_t *eptd = &ph->p_ep;
9274 usb_isoc_req_t *curr_isoc_reqp =
9275 (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
9276 int error = USB_SUCCESS;
9277
9278 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9279 "ohci_handle_isoc_td: pp=0x%p tw=0x%p td=0x%p"
9280 "isoc_reqp=0%p data=0x%p", (void *)pp, (void *)tw, (void *)td,
9281 (void *)curr_isoc_reqp, (void *)curr_isoc_reqp->isoc_data);
9282
9283 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9284
9285 /*
9286 * Decrement the TDs counter and check whether all the isoc
9287 * data has been send or received. If TDs counter reaches
9288 * zero then inform client driver about completion current
9289 * isoc request. Otherwise wait for completion of other isoc
9290 * TDs or transactions on this pipe.
9291 */
9292 if (--tw->tw_num_tds != 0) {
9293
9294 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9295 "ohci_handle_isoc_td: Number of TDs %d", tw->tw_num_tds);
9296
9297 return;
9298 }
9299
9300 /*
9301 * If this is a isoc in pipe, return the data to the client.
9302 * For a isoc out pipe, there is no need to do anything.
9303 */
9304 if ((eptd->bEndpointAddress & USB_EP_DIR_MASK) == USB_EP_DIR_OUT) {
9305 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9306 "ohci_handle_isoc_td: Isoc out pipe, isoc_reqp=0x%p,"
9307 "data=0x%p", (void *)curr_isoc_reqp,
9308 (void *)curr_isoc_reqp->isoc_data);
9309
9310 ohci_do_byte_stats(ohcip, tw->tw_length,
9311 eptd->bmAttributes, eptd->bEndpointAddress);
9312
9313 /* Do the callback */
9314 ohci_hcdi_callback(ph, tw, USB_CR_OK);
9315
9316 return;
9317 }
9318
9319 /* Decrement number of IN isochronous request count */
9320 pp->pp_cur_periodic_req_cnt--;
9321
9322 /* Call ohci_sendup_td_message to send message to upstream */
9323 ohci_sendup_td_message(ohcip, pp, tw, td, USB_CR_OK);
9324
9325 /*
9326 * If isochronous pipe state is still active, insert next isochronous
9327 * request into the Host Controller's isochronous list.
9328 */
9329 if (pp->pp_state != OHCI_PIPE_STATE_ACTIVE) {
9330 return;
9331 }
9332
9333 if ((error = ohci_allocate_periodic_in_resource(ohcip, pp, tw, 0)) ==
9334 USB_SUCCESS) {
9335 curr_isoc_reqp = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
9336
9337 ASSERT(curr_isoc_reqp != NULL);
9338
9339 tw->tw_num_tds =
9340 curr_isoc_reqp->isoc_pkts_count / OHCI_ISOC_PKTS_PER_TD;
9341 if (curr_isoc_reqp->isoc_pkts_count % OHCI_ISOC_PKTS_PER_TD) {
9342 tw->tw_num_tds++;
9343 }
9344
9345 if (ohci_tw_rebind_cookie(ohcip, pp, tw) != USB_SUCCESS) {
9346 ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
9347 error = USB_FAILURE;
9348 } else if (ohci_allocate_tds_for_tw(ohcip, tw,
9349 tw->tw_num_tds) != USB_SUCCESS) {
9350 ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
9351 error = USB_FAILURE;
9352 }
9353 }
9354
9355 if (error != USB_SUCCESS ||
9356 ohci_insert_isoc_req(ohcip, pp, tw, 0) != USB_SUCCESS) {
9357 /*
9358 * Set pipe state to stop polling and error to no
9359 * resource. Don't insert any more isoch polling
9360 * requests.
9361 */
9362 pp->pp_state = OHCI_PIPE_STATE_STOP_POLLING;
9363 pp->pp_error = USB_CR_NO_RESOURCES;
9364
9365 } else {
9366 /* Increment number of IN isochronous request count */
9367 pp->pp_cur_periodic_req_cnt++;
9368
9369 ASSERT(pp->pp_cur_periodic_req_cnt ==
9370 pp->pp_max_periodic_req_cnt);
9371 }
9372 }
9373
9374
9375 /*
9376 * ohci_tw_rebind_cookie:
9377 *
9378 * If the cookie associated with a DMA buffer has been walked, the cookie
9379 * is not usable any longer. To reuse the DMA buffer, the DMA handle needs
9380 * to rebind for cookies.
9381 */
9382 static int
ohci_tw_rebind_cookie(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw)9383 ohci_tw_rebind_cookie(
9384 ohci_state_t *ohcip,
9385 ohci_pipe_private_t *pp,
9386 ohci_trans_wrapper_t *tw)
9387 {
9388 usb_ep_descr_t *eptd = &pp->pp_pipe_handle->p_ep;
9389 int rval, i;
9390 uint_t ccount;
9391
9392 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9393 "ohci_tw_rebind_cookie:");
9394
9395 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9396
9397 if ((eptd->bmAttributes & USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH) {
9398 ASSERT(tw->tw_num_tds == tw->tw_ncookies);
9399
9400 for (i = 0; i < tw->tw_num_tds; i++) {
9401 if (tw->tw_isoc_bufs[i].ncookies == 1) {
9402
9403 /*
9404 * no need to rebind when there is
9405 * only one cookie in a buffer
9406 */
9407 continue;
9408 }
9409
9410 /* unbind the DMA handle before rebinding */
9411 rval = ddi_dma_unbind_handle(
9412 tw->tw_isoc_bufs[i].dma_handle);
9413 ASSERT(rval == USB_SUCCESS);
9414 tw->tw_isoc_bufs[i].ncookies = 0;
9415
9416 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9417 "rebind dma_handle %d", i);
9418
9419 /* rebind the handle to get cookies */
9420 rval = ddi_dma_addr_bind_handle(
9421 tw->tw_isoc_bufs[i].dma_handle, NULL,
9422 (caddr_t)tw->tw_isoc_bufs[i].buf_addr,
9423 tw->tw_isoc_bufs[i].length,
9424 DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
9425 DDI_DMA_DONTWAIT, NULL,
9426 &tw->tw_isoc_bufs[i].cookie, &ccount);
9427
9428 if ((rval == DDI_DMA_MAPPED) &&
9429 (ccount <= OHCI_DMA_ATTR_TD_SGLLEN)) {
9430 tw->tw_isoc_bufs[i].ncookies = ccount;
9431 } else {
9432
9433 return (USB_NO_RESOURCES);
9434 }
9435 }
9436 } else {
9437 if (tw->tw_cookie_idx != 0) {
9438 /* unbind the DMA handle before rebinding */
9439 rval = ddi_dma_unbind_handle(tw->tw_dmahandle);
9440 ASSERT(rval == DDI_SUCCESS);
9441 tw->tw_ncookies = 0;
9442
9443 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9444 "rebind dma_handle");
9445
9446 /* rebind the handle to get cookies */
9447 rval = ddi_dma_addr_bind_handle(
9448 tw->tw_dmahandle, NULL,
9449 (caddr_t)tw->tw_buf, tw->tw_length,
9450 DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
9451 DDI_DMA_DONTWAIT, NULL,
9452 &tw->tw_cookie, &ccount);
9453
9454 if (rval == DDI_DMA_MAPPED) {
9455 tw->tw_ncookies = ccount;
9456 tw->tw_dma_offs = 0;
9457 tw->tw_cookie_idx = 0;
9458 } else {
9459
9460 return (USB_NO_RESOURCES);
9461 }
9462 }
9463 }
9464
9465 return (USB_SUCCESS);
9466 }
9467
9468
9469 /*
9470 * ohci_sendup_td_message:
9471 * copy data, if necessary and do callback
9472 */
9473 static void
ohci_sendup_td_message(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,ohci_td_t * td,usb_cr_t error)9474 ohci_sendup_td_message(
9475 ohci_state_t *ohcip,
9476 ohci_pipe_private_t *pp,
9477 ohci_trans_wrapper_t *tw,
9478 ohci_td_t *td,
9479 usb_cr_t error)
9480 {
9481 usb_ep_descr_t *eptd = &pp->pp_pipe_handle->p_ep;
9482 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
9483 size_t length = 0, skip_len = 0, residue;
9484 mblk_t *mp;
9485 uchar_t *buf;
9486 usb_opaque_t curr_xfer_reqp = tw->tw_curr_xfer_reqp;
9487
9488 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9489
9490 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9491 "ohci_sendup_td_message:");
9492
9493 ASSERT(tw != NULL);
9494
9495 length = tw->tw_length;
9496
9497 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
9498 case USB_EP_ATTR_CONTROL:
9499 /*
9500 * Get the correct length, adjust it for the setup size
9501 * which is not part of the data length in control end
9502 * points. Update tw->tw_length for future references.
9503 */
9504 if (((usb_ctrl_req_t *)curr_xfer_reqp)->ctrl_wLength) {
9505 tw->tw_length = length = length - OHCI_MAX_TD_BUF_SIZE;
9506 } else {
9507 tw->tw_length = length = length - SETUP_SIZE;
9508 }
9509
9510 /* Set the length of the buffer to skip */
9511 skip_len = OHCI_MAX_TD_BUF_SIZE;
9512
9513 if (Get_TD(td->hctd_ctrl_phase) != OHCI_CTRL_DATA_PHASE) {
9514 break;
9515 }
9516 /* FALLTHRU */
9517 case USB_EP_ATTR_BULK:
9518 case USB_EP_ATTR_INTR:
9519 /*
9520 * If error is "data overrun", do not check for the
9521 * "CurrentBufferPointer" and return whatever data
9522 * received to the client driver.
9523 */
9524 if (error == USB_CR_DATA_OVERRUN) {
9525 break;
9526 }
9527
9528 /*
9529 * If "CurrentBufferPointer" of Transfer Descriptor
9530 * (TD) is not equal to zero, then we received less
9531 * data from the device than requested by us. In that
9532 * case, get the actual received data size.
9533 */
9534 if (Get_TD(td->hctd_cbp)) {
9535 residue = ohci_get_td_residue(ohcip, td);
9536 length = Get_TD(td->hctd_xfer_offs) +
9537 Get_TD(td->hctd_xfer_len) - residue - skip_len;
9538
9539 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9540 "ohci_sendup_qtd_message: requested data %lu "
9541 "received data %lu", tw->tw_length, length);
9542 }
9543
9544 break;
9545 case USB_EP_ATTR_ISOCH:
9546 default:
9547 break;
9548 }
9549
9550 /* Copy the data into the mblk_t */
9551 buf = (uchar_t *)tw->tw_buf + skip_len;
9552
9553 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9554 "ohci_sendup_qtd_message: length %lu error %d", length, error);
9555
9556 /* Get the message block */
9557 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
9558 case USB_EP_ATTR_CONTROL:
9559 mp = ((usb_ctrl_req_t *)curr_xfer_reqp)->ctrl_data;
9560 break;
9561 case USB_EP_ATTR_BULK:
9562 mp = ((usb_bulk_req_t *)curr_xfer_reqp)->bulk_data;
9563 break;
9564 case USB_EP_ATTR_INTR:
9565 mp = ((usb_intr_req_t *)curr_xfer_reqp)->intr_data;
9566 break;
9567 case USB_EP_ATTR_ISOCH:
9568 mp = ((usb_isoc_req_t *)curr_xfer_reqp)->isoc_data;
9569 break;
9570 }
9571
9572 ASSERT(mp != NULL);
9573
9574 if (length) {
9575 int i;
9576 uchar_t *p = mp->b_rptr;
9577
9578 /*
9579 * Update kstat byte counts
9580 * The control endpoints don't have direction bits so in
9581 * order for control stats to be counted correctly an in
9582 * bit must be faked on a control read.
9583 */
9584 if ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
9585 USB_EP_ATTR_CONTROL) {
9586 ohci_do_byte_stats(ohcip, length,
9587 eptd->bmAttributes, USB_EP_DIR_IN);
9588 } else {
9589 ohci_do_byte_stats(ohcip, length,
9590 eptd->bmAttributes, eptd->bEndpointAddress);
9591 }
9592
9593 if ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
9594 USB_EP_ATTR_ISOCH) {
9595 for (i = 0; i < tw->tw_ncookies; i++) {
9596 Sync_IO_Buffer(
9597 tw->tw_isoc_bufs[i].dma_handle,
9598 tw->tw_isoc_bufs[i].length);
9599
9600 ddi_rep_get8(tw->tw_isoc_bufs[i].mem_handle,
9601 p, (uint8_t *)tw->tw_isoc_bufs[i].buf_addr,
9602 tw->tw_isoc_bufs[i].length,
9603 DDI_DEV_AUTOINCR);
9604 p += tw->tw_isoc_bufs[i].length;
9605 }
9606 tw->tw_pkt_idx = 0;
9607 } else {
9608 /* Sync IO buffer */
9609 Sync_IO_Buffer(tw->tw_dmahandle, (skip_len + length));
9610
9611 /* Copy the data into the message */
9612 ddi_rep_get8(tw->tw_accesshandle,
9613 mp->b_rptr, buf, length, DDI_DEV_AUTOINCR);
9614 }
9615
9616 /* Increment the write pointer */
9617 mp->b_wptr = mp->b_wptr + length;
9618 } else {
9619 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9620 "ohci_sendup_td_message: Zero length packet");
9621 }
9622
9623 ohci_hcdi_callback(ph, tw, error);
9624 }
9625
9626
9627 /*
9628 * ohci_get_td_residue:
9629 *
9630 * Calculate the bytes not transfered by the TD
9631 */
9632 size_t
ohci_get_td_residue(ohci_state_t * ohcip,ohci_td_t * td)9633 ohci_get_td_residue(
9634 ohci_state_t *ohcip,
9635 ohci_td_t *td)
9636 {
9637 uint32_t buf_addr, end_addr;
9638 size_t residue;
9639
9640 buf_addr = Get_TD(td->hctd_cbp);
9641 end_addr = Get_TD(td->hctd_buf_end);
9642
9643 if ((buf_addr & 0xfffff000) ==
9644 (end_addr & 0xfffff000)) {
9645 residue = end_addr - buf_addr + 1;
9646 } else {
9647 residue = OHCI_MAX_TD_BUF_SIZE -
9648 (buf_addr & 0x00000fff) +
9649 (end_addr & 0x00000fff) + 1;
9650 }
9651
9652 return (residue);
9653 }
9654
9655
9656 /*
9657 * Miscellaneous functions
9658 */
9659
9660 /*
9661 * ohci_obtain_state:
9662 * NOTE: This function is also called from POLLED MODE.
9663 */
9664 ohci_state_t *
ohci_obtain_state(dev_info_t * dip)9665 ohci_obtain_state(dev_info_t *dip)
9666 {
9667 int instance = ddi_get_instance(dip);
9668 ohci_state_t *state = ddi_get_soft_state(
9669 ohci_statep, instance);
9670
9671 ASSERT(state != NULL);
9672
9673 return (state);
9674 }
9675
9676
9677 /*
9678 * ohci_state_is_operational:
9679 *
9680 * Check the Host controller state and return proper values.
9681 */
9682 int
ohci_state_is_operational(ohci_state_t * ohcip)9683 ohci_state_is_operational(ohci_state_t *ohcip)
9684 {
9685 int val;
9686
9687 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9688
9689 switch (ohcip->ohci_hc_soft_state) {
9690 case OHCI_CTLR_INIT_STATE:
9691 case OHCI_CTLR_SUSPEND_STATE:
9692 val = USB_FAILURE;
9693 break;
9694 case OHCI_CTLR_OPERATIONAL_STATE:
9695 val = USB_SUCCESS;
9696 break;
9697 case OHCI_CTLR_ERROR_STATE:
9698 val = USB_HC_HARDWARE_ERROR;
9699 break;
9700 default:
9701 val = USB_FAILURE;
9702 break;
9703 }
9704
9705 return (val);
9706 }
9707
9708
9709 /*
9710 * ohci_do_soft_reset
9711 *
9712 * Do soft reset of ohci host controller.
9713 */
9714 int
ohci_do_soft_reset(ohci_state_t * ohcip)9715 ohci_do_soft_reset(ohci_state_t *ohcip)
9716 {
9717 usb_frame_number_t before_frame_number, after_frame_number;
9718 timeout_id_t xfer_timer_id, rh_timer_id;
9719 ohci_regs_t *ohci_save_regs;
9720 ohci_td_t *done_head;
9721
9722 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9723
9724 /* Increment host controller error count */
9725 ohcip->ohci_hc_error++;
9726
9727 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9728 "ohci_do_soft_reset:"
9729 "Reset ohci host controller 0x%x", ohcip->ohci_hc_error);
9730
9731 /*
9732 * Allocate space for saving current Host Controller
9733 * registers. Don't do any recovery if allocation
9734 * fails.
9735 */
9736 ohci_save_regs = (ohci_regs_t *)
9737 kmem_zalloc(sizeof (ohci_regs_t), KM_NOSLEEP);
9738
9739 if (ohci_save_regs == NULL) {
9740 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9741 "ohci_do_soft_reset: kmem_zalloc failed");
9742
9743 return (USB_FAILURE);
9744 }
9745
9746 /* Save current ohci registers */
9747 ohci_save_regs->hcr_control = Get_OpReg(hcr_control);
9748 ohci_save_regs->hcr_cmd_status = Get_OpReg(hcr_cmd_status);
9749 ohci_save_regs->hcr_intr_enable = Get_OpReg(hcr_intr_enable);
9750 ohci_save_regs->hcr_periodic_strt = Get_OpReg(hcr_periodic_strt);
9751 ohci_save_regs->hcr_frame_interval = Get_OpReg(hcr_frame_interval);
9752 ohci_save_regs->hcr_HCCA = Get_OpReg(hcr_HCCA);
9753 ohci_save_regs->hcr_bulk_head = Get_OpReg(hcr_bulk_head);
9754 ohci_save_regs->hcr_ctrl_head = Get_OpReg(hcr_ctrl_head);
9755
9756 USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9757 "ohci_do_soft_reset: Save reg = 0x%p", (void *)ohci_save_regs);
9758
9759 /* Disable all list processing and interrupts */
9760 Set_OpReg(hcr_control, (Get_OpReg(hcr_control) & ~(HCR_CONTROL_CLE |
9761 HCR_CONTROL_BLE | HCR_CONTROL_PLE | HCR_CONTROL_IE)));
9762
9763 Set_OpReg(hcr_intr_disable, HCR_INTR_SO |
9764 HCR_INTR_WDH | HCR_INTR_RD | HCR_INTR_UE |
9765 HCR_INTR_FNO | HCR_INTR_SOF | HCR_INTR_MIE);
9766
9767 /* Wait for few milliseconds */
9768 drv_usecwait(OHCI_TIMEWAIT);
9769
9770 /* Root hub interrupt pipe timeout id */
9771 rh_timer_id = ohcip->ohci_root_hub.rh_intr_pipe_timer_id;
9772
9773 /* Stop the root hub interrupt timer */
9774 if (rh_timer_id) {
9775 ohcip->ohci_root_hub.rh_intr_pipe_timer_id = 0;
9776 ohcip->ohci_root_hub.rh_intr_pipe_state =
9777 OHCI_PIPE_STATE_IDLE;
9778
9779 mutex_exit(&ohcip->ohci_int_mutex);
9780 (void) untimeout(rh_timer_id);
9781 mutex_enter(&ohcip->ohci_int_mutex);
9782 }
9783
9784 /* Transfer timeout id */
9785 xfer_timer_id = ohcip->ohci_timer_id;
9786
9787 /* Stop the global transfer timer */
9788 if (xfer_timer_id) {
9789 ohcip->ohci_timer_id = 0;
9790 mutex_exit(&ohcip->ohci_int_mutex);
9791 (void) untimeout(xfer_timer_id);
9792 mutex_enter(&ohcip->ohci_int_mutex);
9793 }
9794
9795 /* Process any pending HCCA DoneHead */
9796 done_head = (ohci_td_t *)(uintptr_t)
9797 (Get_HCCA(ohcip->ohci_hccap->HccaDoneHead) & HCCA_DONE_HEAD_MASK);
9798
9799 if (ohci_check_done_head(ohcip, done_head) == USB_SUCCESS) {
9800 /* Reset the done head to NULL */
9801 Set_HCCA(ohcip->ohci_hccap->HccaDoneHead, 0);
9802
9803 ohci_traverse_done_list(ohcip, done_head);
9804 }
9805
9806 /* Process any pending hcr_done_head value */
9807 done_head = (ohci_td_t *)(uintptr_t)
9808 (Get_OpReg(hcr_done_head) & HCCA_DONE_HEAD_MASK);
9809 if (ohci_check_done_head(ohcip, done_head) == USB_SUCCESS) {
9810
9811 ohci_traverse_done_list(ohcip, done_head);
9812 }
9813
9814 /* Do soft reset of ohci host controller */
9815 Set_OpReg(hcr_cmd_status, HCR_STATUS_RESET);
9816
9817 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9818 "ohci_do_soft_reset: Reset in progress");
9819
9820 /* Wait for reset to complete */
9821 drv_usecwait(OHCI_RESET_TIMEWAIT);
9822
9823 /* Reset HCCA HcFrameNumber */
9824 Set_HCCA(ohcip->ohci_hccap->HccaFrameNo, 0x00000000);
9825
9826 /*
9827 * Restore previous saved HC register value
9828 * into the current HC registers.
9829 */
9830 Set_OpReg(hcr_periodic_strt, (uint32_t)
9831 ohci_save_regs->hcr_periodic_strt);
9832
9833 Set_OpReg(hcr_frame_interval, (uint32_t)
9834 ohci_save_regs->hcr_frame_interval);
9835
9836 Set_OpReg(hcr_done_head, 0x0);
9837
9838 Set_OpReg(hcr_bulk_curr, 0x0);
9839
9840 Set_OpReg(hcr_bulk_head, (uint32_t)
9841 ohci_save_regs->hcr_bulk_head);
9842
9843 Set_OpReg(hcr_ctrl_curr, 0x0);
9844
9845 Set_OpReg(hcr_ctrl_head, (uint32_t)
9846 ohci_save_regs->hcr_ctrl_head);
9847
9848 Set_OpReg(hcr_periodic_curr, 0x0);
9849
9850 Set_OpReg(hcr_HCCA, (uint32_t)
9851 ohci_save_regs->hcr_HCCA);
9852
9853 Set_OpReg(hcr_intr_status, 0x0);
9854
9855 /*
9856 * Set HcInterruptEnable to enable all interrupts except
9857 * Root Hub Status change interrupt.
9858 */
9859 Set_OpReg(hcr_intr_enable,
9860 HCR_INTR_SO | HCR_INTR_WDH | HCR_INTR_RD | HCR_INTR_UE |
9861 HCR_INTR_FNO | HCR_INTR_SOF | HCR_INTR_MIE);
9862
9863 /* Start Control and Bulk list processing */
9864 Set_OpReg(hcr_cmd_status, (HCR_STATUS_CLF | HCR_STATUS_BLF));
9865
9866 /*
9867 * Start up Control, Bulk, Periodic and Isochronous lists
9868 * processing.
9869 */
9870 Set_OpReg(hcr_control, (uint32_t)
9871 (ohci_save_regs->hcr_control & (~HCR_CONTROL_HCFS)));
9872
9873 /*
9874 * Deallocate the space that allocated for saving
9875 * HC registers.
9876 */
9877 kmem_free((void *) ohci_save_regs, sizeof (ohci_regs_t));
9878
9879 /* Resume the host controller */
9880 Set_OpReg(hcr_control, ((Get_OpReg(hcr_control) &
9881 (~HCR_CONTROL_HCFS)) | HCR_CONTROL_RESUME));
9882
9883 /* Wait for resume to complete */
9884 drv_usecwait(OHCI_RESUME_TIMEWAIT);
9885
9886 /* Set the Host Controller Functional State to Operational */
9887 Set_OpReg(hcr_control, ((Get_OpReg(hcr_control) &
9888 (~HCR_CONTROL_HCFS)) | HCR_CONTROL_OPERAT));
9889
9890 /* Wait 10ms for HC to start sending SOF */
9891 drv_usecwait(OHCI_TIMEWAIT);
9892
9893 /*
9894 * Get the current usb frame number before waiting for few
9895 * milliseconds.
9896 */
9897 before_frame_number = ohci_get_current_frame_number(ohcip);
9898
9899 /* Wait for few milliseconds */
9900 drv_usecwait(OHCI_TIMEWAIT);
9901
9902 /*
9903 * Get the current usb frame number after waiting for few
9904 * milliseconds.
9905 */
9906 after_frame_number = ohci_get_current_frame_number(ohcip);
9907
9908 USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9909 "ohci_do_soft_reset: Before Frm No 0x%llx After Frm No 0x%llx",
9910 (unsigned long long)before_frame_number,
9911 (unsigned long long)after_frame_number);
9912
9913 if (after_frame_number <= before_frame_number) {
9914
9915 USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9916 "ohci_do_soft_reset: Soft reset failed");
9917
9918 return (USB_FAILURE);
9919 }
9920
9921 /* Start the timer for the root hub interrupt pipe polling */
9922 if (rh_timer_id) {
9923 ohcip->ohci_root_hub.rh_intr_pipe_timer_id =
9924 timeout(ohci_handle_root_hub_status_change,
9925 (void *)ohcip, drv_usectohz(OHCI_RH_POLL_TIME));
9926
9927 ohcip->ohci_root_hub.
9928 rh_intr_pipe_state = OHCI_PIPE_STATE_ACTIVE;
9929 }
9930
9931 /* Start the global timer */
9932 if (xfer_timer_id) {
9933 ohcip->ohci_timer_id = timeout(ohci_xfer_timeout_handler,
9934 (void *)ohcip, drv_usectohz(1000000));
9935 }
9936
9937 return (USB_SUCCESS);
9938 }
9939
9940
9941 /*
9942 * ohci_get_current_frame_number:
9943 *
9944 * Get the current software based usb frame number.
9945 */
9946 usb_frame_number_t
ohci_get_current_frame_number(ohci_state_t * ohcip)9947 ohci_get_current_frame_number(ohci_state_t *ohcip)
9948 {
9949 usb_frame_number_t usb_frame_number;
9950 usb_frame_number_t ohci_fno, frame_number;
9951 ohci_save_intr_sts_t *ohci_intr_sts =
9952 &ohcip->ohci_save_intr_sts;
9953
9954 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9955
9956 /*
9957 * Sync HCCA area only if this function
9958 * is invoked in non interrupt context.
9959 */
9960 if (!(ohci_intr_sts->ohci_intr_flag &
9961 OHCI_INTR_HANDLING)) {
9962
9963 /* Sync HCCA area */
9964 Sync_HCCA(ohcip);
9965 }
9966
9967 ohci_fno = ohcip->ohci_fno;
9968 frame_number = Get_HCCA(ohcip->ohci_hccap->HccaFrameNo);
9969
9970 /*
9971 * Calculate current software based usb frame number.
9972 *
9973 * This code accounts for the fact that frame number is
9974 * updated by the Host Controller before the ohci driver
9975 * gets an FrameNumberOverflow (FNO) interrupt that will
9976 * adjust Frame higher part.
9977 *
9978 * Refer ohci specification 1.0a, section 5.4, page 86.
9979 */
9980 usb_frame_number = ((frame_number & 0x7FFF) | ohci_fno) +
9981 (((frame_number & 0xFFFF) ^ ohci_fno) & 0x8000);
9982
9983 return (usb_frame_number);
9984 }
9985
9986
9987 /*
9988 * ohci_cpr_cleanup:
9989 *
9990 * Cleanup ohci state and other ohci specific informations across
9991 * Check Point Resume (CPR).
9992 */
9993 static void
ohci_cpr_cleanup(ohci_state_t * ohcip)9994 ohci_cpr_cleanup(ohci_state_t *ohcip)
9995 {
9996 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9997
9998 /* Reset software part of usb frame number */
9999 ohcip->ohci_fno = 0;
10000
10001 /* Reset Schedule Overrrun Error Counter */
10002 ohcip->ohci_so_error = 0;
10003
10004 /* Reset HCCA HcFrameNumber */
10005 Set_HCCA(ohcip->ohci_hccap->HccaFrameNo, 0x00000000);
10006 }
10007
10008
10009 /*
10010 * ohci_get_xfer_attrs:
10011 *
10012 * Get the attributes of a particular xfer.
10013 */
10014 static usb_req_attrs_t
ohci_get_xfer_attrs(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw)10015 ohci_get_xfer_attrs(
10016 ohci_state_t *ohcip,
10017 ohci_pipe_private_t *pp,
10018 ohci_trans_wrapper_t *tw)
10019 {
10020 usb_ep_descr_t *eptd = &pp->pp_pipe_handle->p_ep;
10021 usb_req_attrs_t attrs = 0;
10022
10023 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10024 "ohci_get_xfer_attrs:");
10025
10026 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10027
10028 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
10029 case USB_EP_ATTR_CONTROL:
10030 attrs = ((usb_ctrl_req_t *)
10031 tw->tw_curr_xfer_reqp)->ctrl_attributes;
10032 break;
10033 case USB_EP_ATTR_BULK:
10034 attrs = ((usb_bulk_req_t *)
10035 tw->tw_curr_xfer_reqp)->bulk_attributes;
10036 break;
10037 case USB_EP_ATTR_INTR:
10038 attrs = ((usb_intr_req_t *)
10039 tw->tw_curr_xfer_reqp)->intr_attributes;
10040 break;
10041 case USB_EP_ATTR_ISOCH:
10042 attrs = ((usb_isoc_req_t *)
10043 tw->tw_curr_xfer_reqp)->isoc_attributes;
10044 break;
10045 }
10046
10047 return (attrs);
10048 }
10049
10050
10051 /*
10052 * ohci_allocate_periodic_in_resource
10053 *
10054 * Allocate interrupt/isochronous request structure for the
10055 * interrupt/isochronous IN transfer.
10056 */
10057 static int
ohci_allocate_periodic_in_resource(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw,usb_flags_t flags)10058 ohci_allocate_periodic_in_resource(
10059 ohci_state_t *ohcip,
10060 ohci_pipe_private_t *pp,
10061 ohci_trans_wrapper_t *tw,
10062 usb_flags_t flags)
10063 {
10064 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
10065 uchar_t ep_attr = ph->p_ep.bmAttributes;
10066 usb_intr_req_t *curr_intr_reqp;
10067 usb_isoc_req_t *curr_isoc_reqp;
10068 usb_opaque_t client_periodic_in_reqp;
10069 size_t length = 0;
10070
10071 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10072 "ohci_allocate_periodic_in_resource:"
10073 "pp = 0x%p tw = 0x%p flags = 0x%x", (void *)pp, (void *)tw, flags);
10074
10075 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10076 ASSERT(tw->tw_curr_xfer_reqp == NULL);
10077
10078 /* Get the client periodic in request pointer */
10079 client_periodic_in_reqp = pp->pp_client_periodic_in_reqp;
10080
10081 /*
10082 * If it a periodic IN request and periodic request is NULL,
10083 * allocate corresponding usb periodic IN request for the
10084 * current periodic polling request and copy the information
10085 * from the saved periodic request structure.
10086 */
10087 if ((ep_attr & USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR) {
10088
10089 if (client_periodic_in_reqp) {
10090
10091 /* Get the interrupt transfer length */
10092 length = ((usb_intr_req_t *)
10093 client_periodic_in_reqp)->intr_len;
10094
10095 curr_intr_reqp = usba_hcdi_dup_intr_req(
10096 ph->p_dip, (usb_intr_req_t *)
10097 client_periodic_in_reqp, length, flags);
10098 } else {
10099 curr_intr_reqp = usb_alloc_intr_req(
10100 ph->p_dip, length, flags);
10101 }
10102
10103 if (curr_intr_reqp == NULL) {
10104
10105 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10106 "ohci_allocate_periodic_in_resource: Interrupt "
10107 "request structure allocation failed");
10108
10109 return (USB_NO_RESOURCES);
10110 }
10111
10112 if (client_periodic_in_reqp == NULL) {
10113 /* For polled mode */
10114 curr_intr_reqp->
10115 intr_attributes = USB_ATTRS_SHORT_XFER_OK;
10116 curr_intr_reqp->
10117 intr_len = ph->p_ep.wMaxPacketSize;
10118 } else {
10119 /* Check and save the timeout value */
10120 tw->tw_timeout = (curr_intr_reqp->intr_attributes &
10121 USB_ATTRS_ONE_XFER) ?
10122 curr_intr_reqp->intr_timeout: 0;
10123 }
10124
10125 tw->tw_curr_xfer_reqp = (usb_opaque_t)curr_intr_reqp;
10126 tw->tw_length = curr_intr_reqp->intr_len;
10127 } else {
10128 ASSERT(client_periodic_in_reqp != NULL);
10129
10130 curr_isoc_reqp = usba_hcdi_dup_isoc_req(ph->p_dip,
10131 (usb_isoc_req_t *)client_periodic_in_reqp, flags);
10132
10133 if (curr_isoc_reqp == NULL) {
10134
10135 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10136 "ohci_allocate_periodic_in_resource: Isochronous"
10137 "request structure allocation failed");
10138
10139 return (USB_NO_RESOURCES);
10140 }
10141
10142 /*
10143 * Save the client's isochronous request pointer and
10144 * length of isochronous transfer in transfer wrapper.
10145 * The dup'ed request is saved in pp_client_periodic_in_reqp
10146 */
10147 tw->tw_curr_xfer_reqp =
10148 (usb_opaque_t)pp->pp_client_periodic_in_reqp;
10149 pp->pp_client_periodic_in_reqp = (usb_opaque_t)curr_isoc_reqp;
10150 }
10151
10152 mutex_enter(&ph->p_mutex);
10153 ph->p_req_count++;
10154 mutex_exit(&ph->p_mutex);
10155
10156 pp->pp_state = OHCI_PIPE_STATE_ACTIVE;
10157
10158 return (USB_SUCCESS);
10159 }
10160
10161
10162 /*
10163 * ohci_wait_for_sof:
10164 *
10165 * Wait for couple of SOF interrupts
10166 */
10167 static int
ohci_wait_for_sof(ohci_state_t * ohcip)10168 ohci_wait_for_sof(ohci_state_t *ohcip)
10169 {
10170 usb_frame_number_t before_frame_number, after_frame_number;
10171 clock_t sof_time_wait;
10172 int rval, sof_wait_count;
10173
10174 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10175 "ohci_wait_for_sof");
10176
10177 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10178
10179 rval = ohci_state_is_operational(ohcip);
10180
10181 if (rval != USB_SUCCESS) {
10182
10183 return (rval);
10184 }
10185
10186 /* Get the number of clock ticks to wait */
10187 sof_time_wait = drv_usectohz(OHCI_MAX_SOF_TIMEWAIT * 1000000);
10188
10189 sof_wait_count = 0;
10190
10191 /*
10192 * Get the current usb frame number before waiting for the
10193 * SOF interrupt event.
10194 */
10195 before_frame_number = ohci_get_current_frame_number(ohcip);
10196
10197 while (sof_wait_count < MAX_SOF_WAIT_COUNT) {
10198 /* Enable the SOF interrupt */
10199 Set_OpReg(hcr_intr_enable, HCR_INTR_SOF);
10200
10201 ASSERT(Get_OpReg(hcr_intr_enable) & HCR_INTR_SOF);
10202
10203 /* Wait for the SOF or timeout event */
10204 rval = cv_reltimedwait(&ohcip->ohci_SOF_cv,
10205 &ohcip->ohci_int_mutex, sof_time_wait, TR_CLOCK_TICK);
10206
10207 /*
10208 * Get the current usb frame number after woken up either
10209 * from SOF interrupt or timer expired event.
10210 */
10211 after_frame_number = ohci_get_current_frame_number(ohcip);
10212
10213 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10214 "ohci_wait_for_sof: before 0x%llx, after 0x%llx",
10215 (unsigned long long)before_frame_number,
10216 (unsigned long long)after_frame_number);
10217
10218 /*
10219 * Return failure, if we are woken up becuase of timer expired
10220 * event and if usb frame number has not been changed.
10221 */
10222 if ((rval == -1) &&
10223 (after_frame_number <= before_frame_number)) {
10224
10225 if ((ohci_do_soft_reset(ohcip)) != USB_SUCCESS) {
10226
10227 USB_DPRINTF_L0(PRINT_MASK_LISTS,
10228 ohcip->ohci_log_hdl, "No SOF interrupts");
10229
10230 /* Set host controller soft state to error */
10231 ohcip->ohci_hc_soft_state =
10232 OHCI_CTLR_ERROR_STATE;
10233
10234 return (USB_FAILURE);
10235 }
10236
10237 /* Get new usb frame number */
10238 after_frame_number = before_frame_number =
10239 ohci_get_current_frame_number(ohcip);
10240 }
10241
10242 ASSERT(after_frame_number >= before_frame_number);
10243
10244 before_frame_number = after_frame_number;
10245 sof_wait_count++;
10246 }
10247
10248 return (USB_SUCCESS);
10249 }
10250
10251
10252 /*
10253 * ohci_pipe_cleanup
10254 *
10255 * Cleanup ohci pipe.
10256 */
10257 static void
ohci_pipe_cleanup(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)10258 ohci_pipe_cleanup(
10259 ohci_state_t *ohcip,
10260 usba_pipe_handle_data_t *ph)
10261 {
10262 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
10263 usb_ep_descr_t *eptd = &ph->p_ep;
10264 usb_cr_t completion_reason;
10265 uint_t pipe_state = pp->pp_state;
10266 uint_t bit = 0;
10267
10268 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10269 "ohci_pipe_cleanup: ph = 0x%p", (void *)ph);
10270
10271 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10272
10273 switch (pipe_state) {
10274 case OHCI_PIPE_STATE_CLOSE:
10275 if (OHCI_NON_PERIODIC_ENDPOINT(eptd)) {
10276
10277 bit = ((eptd->bmAttributes &
10278 USB_EP_ATTR_MASK) == USB_EP_ATTR_CONTROL) ?
10279 HCR_CONTROL_CLE: HCR_CONTROL_BLE;
10280
10281 Set_OpReg(hcr_control,
10282 (Get_OpReg(hcr_control) & ~(bit)));
10283
10284 /* Wait for the next SOF */
10285 (void) ohci_wait_for_sof(ohcip);
10286
10287 break;
10288 }
10289 /* FALLTHROUGH */
10290 case OHCI_PIPE_STATE_RESET:
10291 case OHCI_PIPE_STATE_STOP_POLLING:
10292 /*
10293 * Set the sKip bit to stop all transactions on
10294 * this pipe
10295 */
10296 ohci_modify_sKip_bit(ohcip, pp, SET_sKip,
10297 OHCI_FLAGS_SLEEP | OHCI_FLAGS_DMA_SYNC);
10298
10299 break;
10300 default:
10301 return;
10302 }
10303
10304 /*
10305 * Wait for processing all completed transfers and
10306 * to send results to upstream.
10307 */
10308 ohci_wait_for_transfers_completion(ohcip, pp);
10309
10310 /* Save the data toggle information */
10311 ohci_save_data_toggle(ohcip, ph);
10312
10313 /*
10314 * Traverse the list of TD's on this endpoint and
10315 * these TD's have outstanding transfer requests.
10316 * Since the list processing is stopped, these tds
10317 * can be deallocated.
10318 */
10319 ohci_traverse_tds(ohcip, ph);
10320
10321 /*
10322 * If all of the endpoint's TD's have been deallocated,
10323 * then the DMA mappings can be torn down. If not there
10324 * are some TD's on the done list that have not been
10325 * processed. Tag these TD's so that they are thrown
10326 * away when the done list is processed.
10327 */
10328 ohci_done_list_tds(ohcip, ph);
10329
10330 /* Do callbacks for all unfinished requests */
10331 ohci_handle_outstanding_requests(ohcip, pp);
10332
10333 /* Free DMA resources */
10334 ohci_free_dma_resources(ohcip, ph);
10335
10336 switch (pipe_state) {
10337 case OHCI_PIPE_STATE_CLOSE:
10338 completion_reason = USB_CR_PIPE_CLOSING;
10339 break;
10340 case OHCI_PIPE_STATE_RESET:
10341 case OHCI_PIPE_STATE_STOP_POLLING:
10342 /* Set completion reason */
10343 completion_reason = (pipe_state ==
10344 OHCI_PIPE_STATE_RESET) ?
10345 USB_CR_PIPE_RESET: USB_CR_STOPPED_POLLING;
10346
10347 /* Restore the data toggle information */
10348 ohci_restore_data_toggle(ohcip, ph);
10349
10350 /*
10351 * Clear the sKip bit to restart all the
10352 * transactions on this pipe.
10353 */
10354 ohci_modify_sKip_bit(ohcip, pp,
10355 CLEAR_sKip, OHCI_FLAGS_NOSLEEP);
10356
10357 /* Set pipe state to idle */
10358 pp->pp_state = OHCI_PIPE_STATE_IDLE;
10359
10360 break;
10361 }
10362
10363 ASSERT((Get_ED(pp->pp_ept->hced_tailp) & HC_EPT_TD_TAIL) ==
10364 (Get_ED(pp->pp_ept->hced_headp) & HC_EPT_TD_HEAD));
10365
10366 ASSERT((pp->pp_tw_head == NULL) && (pp->pp_tw_tail == NULL));
10367
10368 /*
10369 * Do the callback for the original client
10370 * periodic IN request.
10371 */
10372 if ((OHCI_PERIODIC_ENDPOINT(eptd)) &&
10373 ((ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK) ==
10374 USB_EP_DIR_IN)) {
10375
10376 ohci_do_client_periodic_in_req_callback(
10377 ohcip, pp, completion_reason);
10378 }
10379 }
10380
10381
10382 /*
10383 * ohci_wait_for_transfers_completion:
10384 *
10385 * Wait for processing all completed transfers and to send results
10386 * to upstream.
10387 */
10388 static void
ohci_wait_for_transfers_completion(ohci_state_t * ohcip,ohci_pipe_private_t * pp)10389 ohci_wait_for_transfers_completion(
10390 ohci_state_t *ohcip,
10391 ohci_pipe_private_t *pp)
10392 {
10393 ohci_trans_wrapper_t *head_tw = pp->pp_tw_head;
10394 ohci_trans_wrapper_t *next_tw;
10395 ohci_td_t *tailp, *headp, *nextp;
10396 ohci_td_t *head_td, *next_td;
10397 ohci_ed_t *ept = pp->pp_ept;
10398 int rval;
10399
10400 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10401 "ohci_wait_for_transfers_completion: pp = 0x%p", (void *)pp);
10402
10403 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10404
10405 headp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
10406 Get_ED(ept->hced_headp) & (uint32_t)HC_EPT_TD_HEAD));
10407
10408 tailp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
10409 Get_ED(ept->hced_tailp) & (uint32_t)HC_EPT_TD_TAIL));
10410
10411 rval = ohci_state_is_operational(ohcip);
10412
10413 if (rval != USB_SUCCESS) {
10414
10415 return;
10416 }
10417
10418 pp->pp_count_done_tds = 0;
10419
10420 /* Process the transfer wrappers for this pipe */
10421 next_tw = head_tw;
10422 while (next_tw) {
10423 head_td = (ohci_td_t *)next_tw->tw_hctd_head;
10424 next_td = head_td;
10425
10426 if (head_td) {
10427 /*
10428 * Walk through each TD for this transfer
10429 * wrapper. If a TD still exists, then it
10430 * is currently on the done list.
10431 */
10432 while (next_td) {
10433
10434 nextp = headp;
10435
10436 while (nextp != tailp) {
10437
10438 /* TD is on the ED */
10439 if (nextp == next_td) {
10440 break;
10441 }
10442
10443 nextp = (ohci_td_t *)
10444 (ohci_td_iommu_to_cpu(ohcip,
10445 (Get_TD(nextp->hctd_next_td) &
10446 HC_EPT_TD_TAIL)));
10447 }
10448
10449 if (nextp == tailp) {
10450 pp->pp_count_done_tds++;
10451 }
10452
10453 next_td = ohci_td_iommu_to_cpu(ohcip,
10454 Get_TD(next_td->hctd_tw_next_td));
10455 }
10456 }
10457
10458 next_tw = next_tw->tw_next;
10459 }
10460
10461 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10462 "ohci_wait_for_transfers_completion: count_done_tds = 0x%x",
10463 pp->pp_count_done_tds);
10464
10465 if (!pp->pp_count_done_tds) {
10466
10467 return;
10468 }
10469
10470 (void) cv_reltimedwait(&pp->pp_xfer_cmpl_cv, &ohcip->ohci_int_mutex,
10471 drv_usectohz(OHCI_XFER_CMPL_TIMEWAIT * 1000000), TR_CLOCK_TICK);
10472
10473 if (pp->pp_count_done_tds) {
10474
10475 USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10476 "ohci_wait_for_transfers_completion: No transfers "
10477 "completion confirmation received for 0x%x requests",
10478 pp->pp_count_done_tds);
10479 }
10480 }
10481
10482
10483 /*
10484 * ohci_check_for_transfers_completion:
10485 *
10486 * Check whether anybody is waiting for transfers completion event. If so, send
10487 * this event and also stop initiating any new transfers on this pipe.
10488 */
10489 static void
ohci_check_for_transfers_completion(ohci_state_t * ohcip,ohci_pipe_private_t * pp)10490 ohci_check_for_transfers_completion(
10491 ohci_state_t *ohcip,
10492 ohci_pipe_private_t *pp)
10493 {
10494 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10495 "ohci_check_for_transfers_completion: pp = 0x%p", (void *)pp);
10496
10497 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10498
10499 if ((pp->pp_state == OHCI_PIPE_STATE_STOP_POLLING) &&
10500 (pp->pp_error == USB_CR_NO_RESOURCES) &&
10501 (pp->pp_cur_periodic_req_cnt == 0)) {
10502
10503 /* Reset pipe error to zero */
10504 pp->pp_error = 0;
10505
10506 /* Do callback for original request */
10507 ohci_do_client_periodic_in_req_callback(
10508 ohcip, pp, USB_CR_NO_RESOURCES);
10509 }
10510
10511 if (pp->pp_count_done_tds) {
10512
10513 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10514 "ohci_check_for_transfers_completion:"
10515 "count_done_tds = 0x%x", pp->pp_count_done_tds);
10516
10517 /* Decrement the done td count */
10518 pp->pp_count_done_tds--;
10519
10520 if (!pp->pp_count_done_tds) {
10521 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10522 "ohci_check_for_transfers_completion:"
10523 "Sent transfers completion event pp = 0x%p",
10524 (void *)pp);
10525
10526 /* Send the transfer completion signal */
10527 cv_signal(&pp->pp_xfer_cmpl_cv);
10528 }
10529 }
10530 }
10531
10532
10533 /*
10534 * ohci_save_data_toggle:
10535 *
10536 * Save the data toggle information.
10537 */
10538 static void
ohci_save_data_toggle(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)10539 ohci_save_data_toggle(
10540 ohci_state_t *ohcip,
10541 usba_pipe_handle_data_t *ph)
10542 {
10543 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
10544 usb_ep_descr_t *eptd = &ph->p_ep;
10545 uint_t data_toggle;
10546 usb_cr_t error = pp->pp_error;
10547 ohci_ed_t *ed = pp->pp_ept;
10548 ohci_td_t *headp, *tailp;
10549
10550 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10551 "ohci_save_data_toggle: ph = 0x%p", (void *)ph);
10552
10553 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10554
10555 /* Reset the pipe error value */
10556 pp->pp_error = USB_CR_OK;
10557
10558 /* Return immediately if it is a control or isoc pipe */
10559 if (((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
10560 USB_EP_ATTR_CONTROL) || ((eptd->bmAttributes &
10561 USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH)) {
10562
10563 return;
10564 }
10565
10566 headp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
10567 Get_ED(ed->hced_headp) & (uint32_t)HC_EPT_TD_HEAD));
10568
10569 tailp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
10570 Get_ED(ed->hced_tailp) & (uint32_t)HC_EPT_TD_TAIL));
10571
10572 /*
10573 * Retrieve the data toggle information either from the endpoint
10574 * (ED) or from the transfer descriptor (TD) depending on the
10575 * situation.
10576 */
10577 if ((Get_ED(ed->hced_headp) & HC_EPT_Halt) || (headp == tailp)) {
10578
10579 /* Get the data toggle information from the endpoint */
10580 data_toggle = (Get_ED(ed->hced_headp) &
10581 HC_EPT_Carry)? DATA1:DATA0;
10582 } else {
10583 /*
10584 * Retrieve the data toggle information depending on the
10585 * master data toggle information saved in the transfer
10586 * descriptor (TD) at the head of the endpoint (ED).
10587 *
10588 * Check for master data toggle information .
10589 */
10590 if (Get_TD(headp->hctd_ctrl) & HC_TD_MS_DT) {
10591 /* Get the data toggle information from td */
10592 data_toggle = (Get_TD(headp->hctd_ctrl) &
10593 HC_TD_DT_1) ? DATA1:DATA0;
10594 } else {
10595 /* Get the data toggle information from the endpoint */
10596 data_toggle = (Get_ED(ed->hced_headp) &
10597 HC_EPT_Carry)? DATA1:DATA0;
10598 }
10599 }
10600
10601 /*
10602 * If error is STALL, then, set
10603 * data toggle to zero.
10604 */
10605 if (error == USB_CR_STALL) {
10606 data_toggle = DATA0;
10607 }
10608
10609 /*
10610 * Save the data toggle information
10611 * in the usb device structure.
10612 */
10613 mutex_enter(&ph->p_mutex);
10614 usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
10615 data_toggle);
10616 mutex_exit(&ph->p_mutex);
10617 }
10618
10619
10620 /*
10621 * ohci_restore_data_toggle:
10622 *
10623 * Restore the data toggle information.
10624 */
10625 static void
ohci_restore_data_toggle(ohci_state_t * ohcip,usba_pipe_handle_data_t * ph)10626 ohci_restore_data_toggle(
10627 ohci_state_t *ohcip,
10628 usba_pipe_handle_data_t *ph)
10629 {
10630 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
10631 usb_ep_descr_t *eptd = &ph->p_ep;
10632 uint_t data_toggle = 0;
10633
10634 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10635 "ohci_restore_data_toggle: ph = 0x%p", (void *)ph);
10636
10637 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10638
10639 /*
10640 * Return immediately if it is a control or isoc pipe.
10641 */
10642 if (((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
10643 USB_EP_ATTR_CONTROL) || ((eptd->bmAttributes &
10644 USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH)) {
10645
10646 return;
10647 }
10648
10649 mutex_enter(&ph->p_mutex);
10650
10651 data_toggle = usba_hcdi_get_data_toggle(ph->p_usba_device,
10652 ph->p_ep.bEndpointAddress);
10653 usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
10654 0);
10655
10656 mutex_exit(&ph->p_mutex);
10657
10658 /*
10659 * Restore the data toggle bit depending on the
10660 * previous data toggle information.
10661 */
10662 if (data_toggle) {
10663 Set_ED(pp->pp_ept->hced_headp,
10664 Get_ED(pp->pp_ept->hced_headp) | HC_EPT_Carry);
10665 } else {
10666 Set_ED(pp->pp_ept->hced_headp,
10667 Get_ED(pp->pp_ept->hced_headp) & (~HC_EPT_Carry));
10668 }
10669 }
10670
10671
10672 /*
10673 * ohci_handle_outstanding_requests
10674 * NOTE: This function is also called from POLLED MODE.
10675 *
10676 * Deallocate interrupt/isochronous request structure for the
10677 * interrupt/isochronous IN transfer. Do the callbacks for all
10678 * unfinished requests.
10679 */
10680 void
ohci_handle_outstanding_requests(ohci_state_t * ohcip,ohci_pipe_private_t * pp)10681 ohci_handle_outstanding_requests(
10682 ohci_state_t *ohcip,
10683 ohci_pipe_private_t *pp)
10684 {
10685 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
10686 usb_ep_descr_t *eptd = &ph->p_ep;
10687 ohci_trans_wrapper_t *curr_tw;
10688 ohci_trans_wrapper_t *next_tw;
10689 usb_opaque_t curr_xfer_reqp;
10690
10691 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10692 "ohci_handle_outstanding_requests: pp = 0x%p", (void *)pp);
10693
10694 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10695
10696 /*
10697 * Deallocate all the pre-allocated interrupt requests
10698 */
10699 next_tw = pp->pp_tw_head;
10700
10701 while (next_tw) {
10702 curr_tw = next_tw;
10703 next_tw = curr_tw->tw_next;
10704
10705 curr_xfer_reqp = curr_tw->tw_curr_xfer_reqp;
10706
10707 /* Deallocate current interrupt request */
10708 if (curr_xfer_reqp) {
10709
10710 if ((OHCI_PERIODIC_ENDPOINT(eptd)) &&
10711 (curr_tw->tw_direction == HC_TD_IN)) {
10712
10713 /* Decrement periodic in request count */
10714 pp->pp_cur_periodic_req_cnt--;
10715
10716 ohci_deallocate_periodic_in_resource(
10717 ohcip, pp, curr_tw);
10718 } else {
10719 ohci_hcdi_callback(ph,
10720 curr_tw, USB_CR_FLUSHED);
10721 }
10722 }
10723 }
10724 }
10725
10726
10727 /*
10728 * ohci_deallocate_periodic_in_resource
10729 *
10730 * Deallocate interrupt/isochronous request structure for the
10731 * interrupt/isochronous IN transfer.
10732 */
10733 static void
ohci_deallocate_periodic_in_resource(ohci_state_t * ohcip,ohci_pipe_private_t * pp,ohci_trans_wrapper_t * tw)10734 ohci_deallocate_periodic_in_resource(
10735 ohci_state_t *ohcip,
10736 ohci_pipe_private_t *pp,
10737 ohci_trans_wrapper_t *tw)
10738 {
10739 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
10740 uchar_t ep_attr = ph->p_ep.bmAttributes;
10741 usb_opaque_t curr_xfer_reqp;
10742
10743 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10744 "ohci_deallocate_periodic_in_resource: "
10745 "pp = 0x%p tw = 0x%p", (void *)pp, (void *)tw);
10746
10747 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10748
10749 curr_xfer_reqp = tw->tw_curr_xfer_reqp;
10750
10751 /* Check the current periodic in request pointer */
10752 if (curr_xfer_reqp) {
10753 /*
10754 * Reset periodic in request usb isoch
10755 * packet request pointers to null.
10756 */
10757 tw->tw_curr_xfer_reqp = NULL;
10758 tw->tw_curr_isoc_pktp = NULL;
10759
10760 mutex_enter(&ph->p_mutex);
10761 ph->p_req_count--;
10762 mutex_exit(&ph->p_mutex);
10763
10764 /*
10765 * Free pre-allocated interrupt
10766 * or isochronous requests.
10767 */
10768 switch (ep_attr & USB_EP_ATTR_MASK) {
10769 case USB_EP_ATTR_INTR:
10770 usb_free_intr_req(
10771 (usb_intr_req_t *)curr_xfer_reqp);
10772 break;
10773 case USB_EP_ATTR_ISOCH:
10774 usb_free_isoc_req(
10775 (usb_isoc_req_t *)curr_xfer_reqp);
10776 break;
10777 }
10778 }
10779 }
10780
10781
10782 /*
10783 * ohci_do_client_periodic_in_req_callback
10784 *
10785 * Do callback for the original client periodic IN request.
10786 */
10787 static void
ohci_do_client_periodic_in_req_callback(ohci_state_t * ohcip,ohci_pipe_private_t * pp,usb_cr_t completion_reason)10788 ohci_do_client_periodic_in_req_callback(
10789 ohci_state_t *ohcip,
10790 ohci_pipe_private_t *pp,
10791 usb_cr_t completion_reason)
10792 {
10793 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
10794
10795 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10796 "ohci_do_client_periodic_in_req_callback: "
10797 "pp = 0x%p cc = 0x%x", (void *)pp, completion_reason);
10798
10799 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10800
10801 /*
10802 * Check for Interrupt/Isochronous IN, whether we need to do
10803 * callback for the original client's periodic IN request.
10804 */
10805 if (pp->pp_client_periodic_in_reqp) {
10806 ASSERT(pp->pp_cur_periodic_req_cnt == 0);
10807 ohci_hcdi_callback(ph, NULL, completion_reason);
10808 }
10809 }
10810
10811
10812 /*
10813 * ohci_hcdi_callback()
10814 *
10815 * Convenience wrapper around usba_hcdi_cb() other than root hub.
10816 */
10817 static void
ohci_hcdi_callback(usba_pipe_handle_data_t * ph,ohci_trans_wrapper_t * tw,usb_cr_t completion_reason)10818 ohci_hcdi_callback(
10819 usba_pipe_handle_data_t *ph,
10820 ohci_trans_wrapper_t *tw,
10821 usb_cr_t completion_reason)
10822 {
10823 ohci_state_t *ohcip = ohci_obtain_state(
10824 ph->p_usba_device->usb_root_hub_dip);
10825 uchar_t attributes = ph->p_ep.bmAttributes &
10826 USB_EP_ATTR_MASK;
10827 ohci_pipe_private_t *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
10828 usb_opaque_t curr_xfer_reqp;
10829 uint_t pipe_state = 0;
10830
10831 USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10832 "ohci_hcdi_callback: ph = 0x%p, tw = 0x%p, cr = 0x%x",
10833 (void *)ph, (void *)tw, completion_reason);
10834
10835 ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10836
10837 /* Set the pipe state as per completion reason */
10838 switch (completion_reason) {
10839 case USB_CR_OK:
10840 pipe_state = pp->pp_state;
10841 break;
10842 case USB_CR_NO_RESOURCES:
10843 case USB_CR_NOT_SUPPORTED:
10844 case USB_CR_STOPPED_POLLING:
10845 case USB_CR_PIPE_RESET:
10846 pipe_state = OHCI_PIPE_STATE_IDLE;
10847 break;
10848 case USB_CR_PIPE_CLOSING:
10849 break;
10850 default:
10851 /*
10852 * Set the pipe state to error
10853 * except for the isoc pipe.
10854 */
10855 if (attributes != USB_EP_ATTR_ISOCH) {
10856 pipe_state = OHCI_PIPE_STATE_ERROR;
10857 pp->pp_error = completion_reason;
10858 }
10859 break;
10860
10861 }
10862
10863 pp->pp_state = pipe_state;
10864
10865 if (tw && tw->tw_curr_xfer_reqp) {
10866 curr_xfer_reqp = tw->tw_curr_xfer_reqp;
10867 tw->tw_curr_xfer_reqp = NULL;
10868 tw->tw_curr_isoc_pktp = NULL;
10869 } else {
10870 ASSERT(pp->pp_client_periodic_in_reqp != NULL);
10871
10872 curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
10873 pp->pp_client_periodic_in_reqp = NULL;
10874 }
10875
10876 ASSERT(curr_xfer_reqp != NULL);
10877
10878 mutex_exit(&ohcip->ohci_int_mutex);
10879
10880 usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason);
10881
10882 mutex_enter(&ohcip->ohci_int_mutex);
10883 }
10884
10885
10886 /*
10887 * ohci kstat functions
10888 */
10889
10890 /*
10891 * ohci_create_stats:
10892 *
10893 * Allocate and initialize the ohci kstat structures
10894 */
10895 static void
ohci_create_stats(ohci_state_t * ohcip)10896 ohci_create_stats(ohci_state_t *ohcip)
10897 {
10898 char kstatname[KSTAT_STRLEN];
10899 const char *dname = ddi_driver_name(ohcip->ohci_dip);
10900 char *usbtypes[USB_N_COUNT_KSTATS] =
10901 {"ctrl", "isoch", "bulk", "intr"};
10902 uint_t instance = ohcip->ohci_instance;
10903 ohci_intrs_stats_t *isp;
10904 int i;
10905
10906 if (OHCI_INTRS_STATS(ohcip) == NULL) {
10907 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,intrs",
10908 dname, instance);
10909 OHCI_INTRS_STATS(ohcip) = kstat_create("usba", instance,
10910 kstatname, "usb_interrupts", KSTAT_TYPE_NAMED,
10911 sizeof (ohci_intrs_stats_t) / sizeof (kstat_named_t),
10912 KSTAT_FLAG_PERSISTENT);
10913
10914 if (OHCI_INTRS_STATS(ohcip)) {
10915 isp = OHCI_INTRS_STATS_DATA(ohcip);
10916 kstat_named_init(&isp->ohci_hcr_intr_total,
10917 "Interrupts Total", KSTAT_DATA_UINT64);
10918 kstat_named_init(&isp->ohci_hcr_intr_not_claimed,
10919 "Not Claimed", KSTAT_DATA_UINT64);
10920 kstat_named_init(&isp->ohci_hcr_intr_so,
10921 "Schedule Overruns", KSTAT_DATA_UINT64);
10922 kstat_named_init(&isp->ohci_hcr_intr_wdh,
10923 "Writeback Done Head", KSTAT_DATA_UINT64);
10924 kstat_named_init(&isp->ohci_hcr_intr_sof,
10925 "Start Of Frame", KSTAT_DATA_UINT64);
10926 kstat_named_init(&isp->ohci_hcr_intr_rd,
10927 "Resume Detected", KSTAT_DATA_UINT64);
10928 kstat_named_init(&isp->ohci_hcr_intr_ue,
10929 "Unrecoverable Error", KSTAT_DATA_UINT64);
10930 kstat_named_init(&isp->ohci_hcr_intr_fno,
10931 "Frame No. Overflow", KSTAT_DATA_UINT64);
10932 kstat_named_init(&isp->ohci_hcr_intr_rhsc,
10933 "Root Hub Status Change", KSTAT_DATA_UINT64);
10934 kstat_named_init(&isp->ohci_hcr_intr_oc,
10935 "Change In Ownership", KSTAT_DATA_UINT64);
10936
10937 OHCI_INTRS_STATS(ohcip)->ks_private = ohcip;
10938 OHCI_INTRS_STATS(ohcip)->ks_update = nulldev;
10939 kstat_install(OHCI_INTRS_STATS(ohcip));
10940 }
10941 }
10942
10943 if (OHCI_TOTAL_STATS(ohcip) == NULL) {
10944 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,total",
10945 dname, instance);
10946 OHCI_TOTAL_STATS(ohcip) = kstat_create("usba", instance,
10947 kstatname, "usb_byte_count", KSTAT_TYPE_IO, 1,
10948 KSTAT_FLAG_PERSISTENT);
10949
10950 if (OHCI_TOTAL_STATS(ohcip)) {
10951 kstat_install(OHCI_TOTAL_STATS(ohcip));
10952 }
10953 }
10954
10955 for (i = 0; i < USB_N_COUNT_KSTATS; i++) {
10956 if (ohcip->ohci_count_stats[i] == NULL) {
10957 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,%s",
10958 dname, instance, usbtypes[i]);
10959 ohcip->ohci_count_stats[i] = kstat_create("usba",
10960 instance, kstatname, "usb_byte_count",
10961 KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT);
10962
10963 if (ohcip->ohci_count_stats[i]) {
10964 kstat_install(ohcip->ohci_count_stats[i]);
10965 }
10966 }
10967 }
10968 }
10969
10970
10971 /*
10972 * ohci_destroy_stats:
10973 *
10974 * Clean up ohci kstat structures
10975 */
10976 static void
ohci_destroy_stats(ohci_state_t * ohcip)10977 ohci_destroy_stats(ohci_state_t *ohcip)
10978 {
10979 int i;
10980
10981 if (OHCI_INTRS_STATS(ohcip)) {
10982 kstat_delete(OHCI_INTRS_STATS(ohcip));
10983 OHCI_INTRS_STATS(ohcip) = NULL;
10984 }
10985
10986 if (OHCI_TOTAL_STATS(ohcip)) {
10987 kstat_delete(OHCI_TOTAL_STATS(ohcip));
10988 OHCI_TOTAL_STATS(ohcip) = NULL;
10989 }
10990
10991 for (i = 0; i < USB_N_COUNT_KSTATS; i++) {
10992 if (ohcip->ohci_count_stats[i]) {
10993 kstat_delete(ohcip->ohci_count_stats[i]);
10994 ohcip->ohci_count_stats[i] = NULL;
10995 }
10996 }
10997 }
10998
10999
11000 /*
11001 * ohci_do_intrs_stats:
11002 *
11003 * ohci status information
11004 */
11005 static void
ohci_do_intrs_stats(ohci_state_t * ohcip,int val)11006 ohci_do_intrs_stats(
11007 ohci_state_t *ohcip,
11008 int val)
11009 {
11010 if (OHCI_INTRS_STATS(ohcip)) {
11011 OHCI_INTRS_STATS_DATA(ohcip)->ohci_hcr_intr_total.value.ui64++;
11012 switch (val) {
11013 case HCR_INTR_SO:
11014 OHCI_INTRS_STATS_DATA(ohcip)->
11015 ohci_hcr_intr_so.value.ui64++;
11016 break;
11017 case HCR_INTR_WDH:
11018 OHCI_INTRS_STATS_DATA(ohcip)->
11019 ohci_hcr_intr_wdh.value.ui64++;
11020 break;
11021 case HCR_INTR_SOF:
11022 OHCI_INTRS_STATS_DATA(ohcip)->
11023 ohci_hcr_intr_sof.value.ui64++;
11024 break;
11025 case HCR_INTR_RD:
11026 OHCI_INTRS_STATS_DATA(ohcip)->
11027 ohci_hcr_intr_rd.value.ui64++;
11028 break;
11029 case HCR_INTR_UE:
11030 OHCI_INTRS_STATS_DATA(ohcip)->
11031 ohci_hcr_intr_ue.value.ui64++;
11032 break;
11033 case HCR_INTR_FNO:
11034 OHCI_INTRS_STATS_DATA(ohcip)->
11035 ohci_hcr_intr_fno.value.ui64++;
11036 break;
11037 case HCR_INTR_RHSC:
11038 OHCI_INTRS_STATS_DATA(ohcip)->
11039 ohci_hcr_intr_rhsc.value.ui64++;
11040 break;
11041 case HCR_INTR_OC:
11042 OHCI_INTRS_STATS_DATA(ohcip)->
11043 ohci_hcr_intr_oc.value.ui64++;
11044 break;
11045 default:
11046 OHCI_INTRS_STATS_DATA(ohcip)->
11047 ohci_hcr_intr_not_claimed.value.ui64++;
11048 break;
11049 }
11050 }
11051 }
11052
11053
11054 /*
11055 * ohci_do_byte_stats:
11056 *
11057 * ohci data xfer information
11058 */
11059 static void
ohci_do_byte_stats(ohci_state_t * ohcip,size_t len,uint8_t attr,uint8_t addr)11060 ohci_do_byte_stats(ohci_state_t *ohcip, size_t len, uint8_t attr, uint8_t addr)
11061 {
11062 uint8_t type = attr & USB_EP_ATTR_MASK;
11063 uint8_t dir = addr & USB_EP_DIR_MASK;
11064
11065 if (dir == USB_EP_DIR_IN) {
11066 OHCI_TOTAL_STATS_DATA(ohcip)->reads++;
11067 OHCI_TOTAL_STATS_DATA(ohcip)->nread += len;
11068 switch (type) {
11069 case USB_EP_ATTR_CONTROL:
11070 OHCI_CTRL_STATS(ohcip)->reads++;
11071 OHCI_CTRL_STATS(ohcip)->nread += len;
11072 break;
11073 case USB_EP_ATTR_BULK:
11074 OHCI_BULK_STATS(ohcip)->reads++;
11075 OHCI_BULK_STATS(ohcip)->nread += len;
11076 break;
11077 case USB_EP_ATTR_INTR:
11078 OHCI_INTR_STATS(ohcip)->reads++;
11079 OHCI_INTR_STATS(ohcip)->nread += len;
11080 break;
11081 case USB_EP_ATTR_ISOCH:
11082 OHCI_ISOC_STATS(ohcip)->reads++;
11083 OHCI_ISOC_STATS(ohcip)->nread += len;
11084 break;
11085 }
11086 } else if (dir == USB_EP_DIR_OUT) {
11087 OHCI_TOTAL_STATS_DATA(ohcip)->writes++;
11088 OHCI_TOTAL_STATS_DATA(ohcip)->nwritten += len;
11089 switch (type) {
11090 case USB_EP_ATTR_CONTROL:
11091 OHCI_CTRL_STATS(ohcip)->writes++;
11092 OHCI_CTRL_STATS(ohcip)->nwritten += len;
11093 break;
11094 case USB_EP_ATTR_BULK:
11095 OHCI_BULK_STATS(ohcip)->writes++;
11096 OHCI_BULK_STATS(ohcip)->nwritten += len;
11097 break;
11098 case USB_EP_ATTR_INTR:
11099 OHCI_INTR_STATS(ohcip)->writes++;
11100 OHCI_INTR_STATS(ohcip)->nwritten += len;
11101 break;
11102 case USB_EP_ATTR_ISOCH:
11103 OHCI_ISOC_STATS(ohcip)->writes++;
11104 OHCI_ISOC_STATS(ohcip)->nwritten += len;
11105 break;
11106 }
11107 }
11108 }
11109
11110
11111 /*
11112 * ohci_print_op_regs:
11113 *
11114 * Print Host Controller's (HC) Operational registers.
11115 */
11116 static void
ohci_print_op_regs(ohci_state_t * ohcip)11117 ohci_print_op_regs(ohci_state_t *ohcip)
11118 {
11119 uint_t i;
11120
11121 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11122 "\n\tOHCI%d Operational Registers\n",
11123 ddi_get_instance(ohcip->ohci_dip));
11124
11125 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11126 "\thcr_revision: 0x%x \t\thcr_control: 0x%x",
11127 Get_OpReg(hcr_revision), Get_OpReg(hcr_control));
11128 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11129 "\thcr_cmd_status: 0x%x \t\thcr_intr_enable: 0x%x",
11130 Get_OpReg(hcr_cmd_status), Get_OpReg(hcr_intr_enable));
11131 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11132 "\thcr_intr_disable: 0x%x \thcr_HCCA: 0x%x",
11133 Get_OpReg(hcr_intr_disable), Get_OpReg(hcr_HCCA));
11134 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11135 "\thcr_periodic_curr: 0x%x \t\thcr_ctrl_head: 0x%x",
11136 Get_OpReg(hcr_periodic_curr), Get_OpReg(hcr_ctrl_head));
11137 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11138 "\thcr_ctrl_curr: 0x%x \t\thcr_bulk_head: 0x%x",
11139 Get_OpReg(hcr_ctrl_curr), Get_OpReg(hcr_bulk_head));
11140 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11141 "\thcr_bulk_curr: 0x%x \t\thcr_done_head: 0x%x",
11142 Get_OpReg(hcr_bulk_curr), Get_OpReg(hcr_done_head));
11143 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11144 "\thcr_frame_interval: 0x%x "
11145 "\thcr_frame_remaining: 0x%x", Get_OpReg(hcr_frame_interval),
11146 Get_OpReg(hcr_frame_remaining));
11147 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11148 "\thcr_frame_number: 0x%x \thcr_periodic_strt: 0x%x",
11149 Get_OpReg(hcr_frame_number), Get_OpReg(hcr_periodic_strt));
11150 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11151 "\thcr_transfer_ls: 0x%x \t\thcr_rh_descriptorA: 0x%x",
11152 Get_OpReg(hcr_transfer_ls), Get_OpReg(hcr_rh_descriptorA));
11153 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11154 "\thcr_rh_descriptorB: 0x%x \thcr_rh_status: 0x%x",
11155 Get_OpReg(hcr_rh_descriptorB), Get_OpReg(hcr_rh_status));
11156
11157 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11158 "\tRoot hub port status");
11159
11160 for (i = 0; i < (Get_OpReg(hcr_rh_descriptorA) & HCR_RHA_NDP); i++) {
11161 USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11162 "\thcr_rh_portstatus 0x%x: 0x%x ", i,
11163 Get_OpReg(hcr_rh_portstatus[i]));
11164 }
11165 }
11166
11167
11168 /*
11169 * ohci_print_ed:
11170 */
11171 static void
ohci_print_ed(ohci_state_t * ohcip,ohci_ed_t * ed)11172 ohci_print_ed(
11173 ohci_state_t *ohcip,
11174 ohci_ed_t *ed)
11175 {
11176 uint_t ctrl = Get_ED(ed->hced_ctrl);
11177
11178 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11179 "ohci_print_ed: ed = 0x%p", (void *)ed);
11180
11181 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11182 "\thced_ctrl: 0x%x %s", ctrl,
11183 ((Get_ED(ed->hced_headp) & HC_EPT_Halt) ? "halted": ""));
11184 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11185 "\ttoggle carry: 0x%x", Get_ED(ed->hced_headp) & HC_EPT_Carry);
11186
11187 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11188 "\tctrl: 0x%x", Get_ED(ed->hced_ctrl));
11189 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11190 "\ttailp: 0x%x", Get_ED(ed->hced_tailp));
11191 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11192 "\theadp: 0x%x", Get_ED(ed->hced_headp));
11193 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11194 "\tnext: 0x%x", Get_ED(ed->hced_next));
11195 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11196 "\tprev: 0x%x", Get_ED(ed->hced_prev));
11197 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11198 "\tnode: 0x%x", Get_ED(ed->hced_node));
11199 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11200 "\treclaim_next: 0x%x", Get_ED(ed->hced_reclaim_next));
11201 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11202 "\treclaim_frame: 0x%x", Get_ED(ed->hced_reclaim_frame));
11203 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11204 "\tstate: 0x%x", Get_ED(ed->hced_state));
11205 }
11206
11207
11208 /*
11209 * ohci_print_td:
11210 */
11211 static void
ohci_print_td(ohci_state_t * ohcip,ohci_td_t * td)11212 ohci_print_td(
11213 ohci_state_t *ohcip,
11214 ohci_td_t *td)
11215 {
11216 uint_t i;
11217 uint_t ctrl = Get_TD(td->hctd_ctrl);
11218
11219 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11220 "ohci_print_td: td = 0x%p", (void *)td);
11221
11222 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11223 "\tPID: 0x%x ", ctrl & HC_TD_PID);
11224 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11225 "\tDelay Intr: 0x%x ", ctrl & HC_TD_DI);
11226 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11227 "\tData Toggle: 0x%x ", ctrl & HC_TD_DT);
11228 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11229 "\tError Count: 0x%x ", ctrl & HC_TD_EC);
11230
11231 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11232 "\tctrl: 0x%x ", Get_TD(td->hctd_ctrl));
11233 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11234 "\tcbp: 0x%x ", Get_TD(td->hctd_cbp));
11235 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11236 "\tnext_td: 0x%x ", Get_TD(td->hctd_next_td));
11237 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11238 "\tbuf_end: 0x%x ", Get_TD(td->hctd_buf_end));
11239
11240 for (i = 0; i < 4; i++) {
11241 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11242 "\toffset[%d]: 0x%x ", i, Get_TD(td->hctd_offsets[i]));
11243 }
11244
11245 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11246 "\ttrans_wrapper: 0x%x ", Get_TD(td->hctd_trans_wrapper));
11247 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11248 "\tstate: 0x%x ", Get_TD(td->hctd_state));
11249 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11250 "\ttw_next_td: 0x%x ", Get_TD(td->hctd_tw_next_td));
11251 USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11252 "\tctrl_phase: 0x%x ", Get_TD(td->hctd_ctrl_phase));
11253 }
11254
11255 /*
11256 * quiesce(9E) entry point.
11257 *
11258 * This function is called when the system is single-threaded at high
11259 * PIL with preemption disabled. Therefore, this function must not be
11260 * blocked.
11261 *
11262 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
11263 * DDI_FAILURE indicates an error condition and should almost never happen.
11264 *
11265 * define as a wrapper for sparc, or warlock will complain.
11266 */
11267 #ifdef __sparc
11268 int
ohci_quiesce(dev_info_t * dip)11269 ohci_quiesce(dev_info_t *dip)
11270 {
11271 return (ddi_quiesce_not_supported(dip));
11272 }
11273 #else
11274 int
ohci_quiesce(dev_info_t * dip)11275 ohci_quiesce(dev_info_t *dip)
11276 {
11277 ohci_state_t *ohcip = ohci_obtain_state(dip);
11278
11279 if (ohcip == NULL)
11280 return (DDI_FAILURE);
11281
11282 #ifndef lint
11283 _NOTE(NO_COMPETING_THREADS_NOW);
11284 #endif
11285
11286 if (ohcip->ohci_flags & OHCI_INTR) {
11287
11288 /* Disable all HC ED list processing */
11289 Set_OpReg(hcr_control,
11290 (Get_OpReg(hcr_control) & ~(HCR_CONTROL_CLE |
11291 HCR_CONTROL_BLE | HCR_CONTROL_PLE | HCR_CONTROL_IE)));
11292
11293 /* Disable all HC interrupts */
11294 Set_OpReg(hcr_intr_disable,
11295 (HCR_INTR_SO | HCR_INTR_WDH | HCR_INTR_RD | HCR_INTR_UE));
11296
11297 /* Disable Master and SOF interrupts */
11298 Set_OpReg(hcr_intr_disable, (HCR_INTR_MIE | HCR_INTR_SOF));
11299
11300 /* Set the Host Controller Functional State to Reset */
11301 Set_OpReg(hcr_control, ((Get_OpReg(hcr_control) &
11302 (~HCR_CONTROL_HCFS)) | HCR_CONTROL_RESET));
11303
11304 /*
11305 * Workaround for ULI1575 chipset. Following OHCI Operational
11306 * Memory Registers are not cleared to their default value
11307 * on reset. Explicitly set the registers to default value.
11308 */
11309 if (ohcip->ohci_vendor_id == PCI_ULI1575_VENID &&
11310 ohcip->ohci_device_id == PCI_ULI1575_DEVID) {
11311 Set_OpReg(hcr_control, HCR_CONTROL_DEFAULT);
11312 Set_OpReg(hcr_intr_enable, HCR_INT_ENABLE_DEFAULT);
11313 Set_OpReg(hcr_HCCA, HCR_HCCA_DEFAULT);
11314 Set_OpReg(hcr_ctrl_head, HCR_CONTROL_HEAD_ED_DEFAULT);
11315 Set_OpReg(hcr_bulk_head, HCR_BULK_HEAD_ED_DEFAULT);
11316 Set_OpReg(hcr_frame_interval,
11317 HCR_FRAME_INTERVAL_DEFAULT);
11318 Set_OpReg(hcr_periodic_strt,
11319 HCR_PERIODIC_START_DEFAULT);
11320 }
11321
11322 ohcip->ohci_hc_soft_state = OHCI_CTLR_SUSPEND_STATE;
11323 }
11324
11325 /* Unmap the OHCI registers */
11326 if (ohcip->ohci_regs_handle) {
11327 /* Reset the host controller */
11328 Set_OpReg(hcr_cmd_status, HCR_STATUS_RESET);
11329 }
11330
11331 #ifndef lint
11332 _NOTE(COMPETING_THREADS_NOW);
11333 #endif
11334 return (DDI_SUCCESS);
11335 }
11336 #endif /* __sparc */
11337