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