1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * This module contains the specific uhci code used in POLLED mode.
29 */
30 #include <sys/usb/hcd/uhci/uhcid.h>
31 #include <sys/usb/hcd/uhci/uhcipolled.h>
32
33 #ifndef __sparc
34 extern void invalidate_cache();
35 #endif
36 /*
37 * Internal Function Prototypes
38 */
39 /* Polled initialization routine */
40 static int uhci_polled_init(usba_pipe_handle_data_t *, uhci_state_t *,
41 usb_console_info_impl_t *);
42
43 /* Polled fini routine */
44 static int uhci_polled_fini(uhci_polled_t *, uhci_state_t *);
45
46 /* Polled save state routine */
47 static void uhci_polled_save_state(uhci_polled_t *);
48
49 /* Polled restore state routine */
50 static void uhci_polled_restore_state(uhci_polled_t *);
51
52 /* Polled read routines */
53 static int uhci_polled_insert_td_on_qh(uhci_polled_t *,
54 usba_pipe_handle_data_t *);
55 static uhci_trans_wrapper_t
56 *uhci_polled_create_tw(uhci_state_t *);
57
58
59 /*
60 * POLLED entry points
61 *
62 * These functions are entry points into the POLLED code.
63 */
64
65 /*
66 * uhci_hcdi_polled_input_init:
67 * This is the initialization routine for handling the USB keyboard
68 * in POLLED mode. This routine is not called from POLLED mode, so
69 * it is OK to acquire mutexes.
70 */
71 int
uhci_hcdi_polled_input_init(usba_pipe_handle_data_t * ph,uchar_t ** polled_buf,usb_console_info_impl_t * console_input_info)72 uhci_hcdi_polled_input_init(usba_pipe_handle_data_t *ph,
73 uchar_t **polled_buf,
74 usb_console_info_impl_t *console_input_info)
75 {
76 int ret;
77 uhci_polled_t *uhci_polledp;
78 uhci_state_t *uhcip;
79
80 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
81
82 /*
83 * Grab the uhci_int_mutex so that things don't change on us
84 * if an interrupt comes in.
85 */
86 mutex_enter(&uhcip->uhci_int_mutex);
87 ret = uhci_polled_init(ph, uhcip, console_input_info);
88 if (ret != USB_SUCCESS) {
89 mutex_exit(&uhcip->uhci_int_mutex);
90
91 return (ret);
92 }
93
94 uhci_polledp = (uhci_polled_t *)console_input_info->uci_private;
95 /*
96 * Mark the structure so that if we are using it, we don't free
97 * the structures if one of them is unplugged.
98 */
99 uhci_polledp->uhci_polled_flags |= POLLED_INPUT_MODE;
100
101 /*
102 * This is the buffer we will copy characters into. It will be
103 * copied into at this layer, so we need to keep track of it.
104 */
105 uhci_polledp->uhci_polled_buf =
106 (uchar_t *)kmem_zalloc(POLLED_RAW_BUF_SIZE, KM_SLEEP);
107
108 *polled_buf = uhci_polledp->uhci_polled_buf;
109
110 mutex_exit(&uhcip->uhci_int_mutex);
111 return (USB_SUCCESS);
112 }
113
114
115 /*
116 * uhci_hcdi_polled_input_fini:
117 */
118 int
uhci_hcdi_polled_input_fini(usb_console_info_impl_t * info)119 uhci_hcdi_polled_input_fini(usb_console_info_impl_t *info)
120 {
121 int ret;
122 uhci_state_t *uhcip;
123 uhci_polled_t *uhci_polledp;
124
125 uhci_polledp = (uhci_polled_t *)info->uci_private;
126 uhcip = uhci_polledp->uhci_polled_uhcip;
127 mutex_enter(&uhcip->uhci_int_mutex);
128
129 /* Free the buffer that we copied data into */
130 kmem_free(uhci_polledp->uhci_polled_buf, POLLED_RAW_BUF_SIZE);
131 ret = uhci_polled_fini(uhci_polledp, uhcip);
132 info->uci_private = NULL;
133 mutex_exit(&uhcip->uhci_int_mutex);
134
135 return (ret);
136 }
137
138
139 /*
140 * uhci_hcdi_polled_input_enter:
141 * This is where we enter into POLLED mode. This routine sets up
142 * everything so that calls to uhci_hcdi_polled_read will return
143 * characters.
144 */
145 int
uhci_hcdi_polled_input_enter(usb_console_info_impl_t * info)146 uhci_hcdi_polled_input_enter(usb_console_info_impl_t *info)
147 {
148 uhci_polled_t *uhci_polledp;
149
150 uhci_polledp = (uhci_polled_t *)info->uci_private;
151 uhci_polledp->uhci_polled_entry++;
152
153 /*
154 * If the controller is already switched over, just return
155 */
156 if (uhci_polledp->uhci_polled_entry > 1) {
157
158 return (USB_SUCCESS);
159 }
160
161 uhci_polled_save_state(uhci_polledp);
162 uhci_polledp->uhci_polled_flags |= POLLED_INPUT_MODE_INUSE;
163
164 return (USB_SUCCESS);
165 }
166
167
168 /*
169 * uhci_hcdi_polled_input_exit:
170 * This is where we exit POLLED mode. This routine restores
171 * everything that is needed to continue operation.
172 */
173 int
uhci_hcdi_polled_input_exit(usb_console_info_impl_t * info)174 uhci_hcdi_polled_input_exit(usb_console_info_impl_t *info)
175 {
176 uhci_polled_t *uhci_polledp;
177
178 uhci_polledp = (uhci_polled_t *)info->uci_private;
179 uhci_polledp->uhci_polled_entry--;
180
181 /*
182 * If there are still outstanding "enters", just return
183 */
184 if (uhci_polledp->uhci_polled_entry > 0) {
185
186 return (USB_SUCCESS);
187 }
188
189 uhci_polledp->uhci_polled_flags &= ~POLLED_INPUT_MODE_INUSE;
190 uhci_polled_restore_state(uhci_polledp);
191
192 return (USB_SUCCESS);
193 }
194
195
196 /*
197 * uhci_hcdi_polled_read:
198 * Get a key character
199 */
200 int
uhci_hcdi_polled_read(usb_console_info_impl_t * info,uint_t * num_characters)201 uhci_hcdi_polled_read(usb_console_info_impl_t *info, uint_t *num_characters)
202 {
203 uhci_state_t *uhcip;
204 uhci_polled_t *uhci_polledp;
205 uhci_td_t *td;
206 uhci_trans_wrapper_t *tw;
207 ushort_t intr_status;
208
209 uhci_polledp = (uhci_polled_t *)info->uci_private;
210 uhcip = uhci_polledp->uhci_polled_uhcip;
211
212 /*
213 * This is a temporary work around for halt problem. The upper
214 * layer code does not call the right sequence of entry points
215 * points for reading a character in a polled mode. Once the
216 * upper layer code is fixed, the following code (two lines)
217 * must be removed.
218 */
219 if (uhci_polledp->uhci_polled_entry == 0) {
220 if (uhci_hcdi_polled_input_enter(info) != USB_SUCCESS) {
221 cmn_err(CE_WARN, "Entering Polled Mode failed");
222 }
223 }
224
225 #ifndef lint
226 _NOTE(NO_COMPETING_THREADS_NOW);
227 #endif
228 #ifndef __sparc
229 invalidate_cache();
230 #endif
231
232 td = uhci_polledp->uhci_polled_td;
233
234 /*
235 * Check to see if there are any TD's on the done head.
236 */
237 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) {
238 *num_characters = 0;
239 } else {
240
241 /*
242 * If the TD does not complete, retry.
243 */
244 if ((GetTD_status(uhcip, td) & TD_STATUS_MASK) ||
245 (GetTD_alen(uhcip, td) == ZERO_LENGTH)) {
246 *num_characters = 0;
247 SetTD_alen(uhcip, td, 0);
248 } else {
249 *num_characters = GetTD_alen(uhcip, td) + 1;
250
251 tw = td->tw;
252
253 /* Copy the data into the message */
254 ddi_rep_get8(tw->tw_accesshandle,
255 (uint8_t *)uhci_polledp->uhci_polled_buf,
256 (uint8_t *)td->tw->tw_buf,
257 *num_characters, DDI_DEV_AUTOINCR);
258 }
259
260 /*
261 * Insert the td again into the lattice.
262 */
263 SetTD_dtogg(uhcip, td, GetTD_dtogg(uhcip, td) == 0 ? 1 : 0);
264
265 SetTD_status(uhcip, td, UHCI_TD_ACTIVE);
266 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr,
267 TD_PADDR(td));
268
269 /* Clear the interrupt status register */
270 intr_status = Get_OpReg16(USBSTS);
271 Set_OpReg16(USBSTS, intr_status);
272 }
273
274 #ifndef lint
275 _NOTE(COMPETING_THREADS_NOW);
276 #endif
277
278 return (USB_SUCCESS);
279 }
280
281 /*
282 * uhci_hcdi_polled_output_init:
283 * This is the initialization routine for handling the USB serial
284 * output in POLLED mode. This routine is called after input_init
285 * succeeded.
286 */
287 int
uhci_hcdi_polled_output_init(usba_pipe_handle_data_t * ph,usb_console_info_impl_t * console_output_info)288 uhci_hcdi_polled_output_init(usba_pipe_handle_data_t *ph,
289 usb_console_info_impl_t *console_output_info)
290 {
291 int ret;
292 uhci_polled_t *uhci_polledp;
293 uhci_state_t *uhcip;
294
295 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
296
297 /*
298 * Grab the uhci_int_mutex so that things don't change on us
299 * if an interrupt comes in.
300 */
301 mutex_enter(&uhcip->uhci_int_mutex);
302 ret = uhci_polled_init(ph, uhcip, console_output_info);
303 if (ret != USB_SUCCESS) {
304 mutex_exit(&uhcip->uhci_int_mutex);
305
306 return (ret);
307 }
308
309 uhci_polledp = (uhci_polled_t *)console_output_info->uci_private;
310 /*
311 * Mark the structure so that if we are using it, we don't free
312 * the structures if one of them is unplugged.
313 */
314 uhci_polledp->uhci_polled_flags |= POLLED_OUTPUT_MODE;
315
316 mutex_exit(&uhcip->uhci_int_mutex);
317
318 return (USB_SUCCESS);
319 }
320
321
322 /*
323 * uhci_hcdi_polled_output_fini:
324 */
325 int
uhci_hcdi_polled_output_fini(usb_console_info_impl_t * info)326 uhci_hcdi_polled_output_fini(usb_console_info_impl_t *info)
327 {
328 int ret;
329 uhci_state_t *uhcip;
330 uhci_polled_t *uhci_polledp;
331
332 uhci_polledp = (uhci_polled_t *)info->uci_private;
333 uhcip = uhci_polledp->uhci_polled_uhcip;
334 mutex_enter(&uhcip->uhci_int_mutex);
335
336 ret = uhci_polled_fini(uhci_polledp, uhcip);
337 info->uci_private = NULL;
338 mutex_exit(&uhcip->uhci_int_mutex);
339
340 return (ret);
341 }
342
343
344 /*
345 * uhci_hcdi_polled_output_enter:
346 * everything is done in input enter
347 */
348 int
uhci_hcdi_polled_output_enter(usb_console_info_impl_t * info)349 uhci_hcdi_polled_output_enter(usb_console_info_impl_t *info)
350 {
351 uhci_state_t *uhcip;
352 uhci_polled_t *uhci_polledp;
353
354 uhci_polledp = (uhci_polled_t *)info->uci_private;
355 uhcip = uhci_polledp->uhci_polled_uhcip;
356
357 /*
358 * Check if the number of devices reaches the max number
359 * we can support in polled mode
360 */
361 if (uhcip->uhci_polled_count + 1 > MAX_NUM_FOR_KEYBORAD) {
362
363 return (USB_FAILURE);
364 }
365
366 return (USB_SUCCESS);
367 }
368
369
370 /*
371 * uhci_hcdi_polled_output_exit:
372 * everything is done in input exit
373 */
374 /*ARGSUSED*/
375 int
uhci_hcdi_polled_output_exit(usb_console_info_impl_t * info)376 uhci_hcdi_polled_output_exit(usb_console_info_impl_t *info)
377 {
378 return (USB_SUCCESS);
379 }
380
381 /*
382 * uhci_hcdi_polled_write:
383 * Put a key character -- rewrite this!
384 */
385 int
uhci_hcdi_polled_write(usb_console_info_impl_t * info,uchar_t * buf,uint_t num_characters,uint_t * num_characters_written)386 uhci_hcdi_polled_write(usb_console_info_impl_t *info, uchar_t *buf,
387 uint_t num_characters, uint_t *num_characters_written)
388 {
389 int i;
390 uhci_state_t *uhcip;
391 uhci_polled_t *uhci_polledp;
392 uhci_td_t *td;
393 uhci_trans_wrapper_t *tw;
394 uhci_pipe_private_t *pp;
395 usba_pipe_handle_data_t *ph;
396
397 #ifndef lint
398 _NOTE(NO_COMPETING_THREADS_NOW);
399 #endif
400
401 uhci_polledp = (uhci_polled_t *)info->uci_private;
402 uhcip = uhci_polledp->uhci_polled_uhcip;
403 ph = uhci_polledp->uhci_polled_ph;
404 pp = (uhci_pipe_private_t *)ph->p_hcd_private;
405
406 td = uhci_polledp->uhci_polled_td;
407 tw = td->tw;
408
409 /* copy transmit buffer */
410 if (num_characters > POLLED_RAW_BUF_SIZE) {
411 cmn_err(CE_NOTE, "polled write size %d bigger than %d",
412 num_characters, POLLED_RAW_BUF_SIZE);
413 num_characters = POLLED_RAW_BUF_SIZE;
414 }
415 tw->tw_length = num_characters;
416 ddi_put8(tw->tw_accesshandle, (uint8_t *)tw->tw_buf, *buf);
417 ddi_rep_put8(tw->tw_accesshandle, buf, (uint8_t *)tw->tw_buf,
418 num_characters, DDI_DEV_AUTOINCR);
419
420 bzero((char *)td, sizeof (uhci_td_t));
421
422 td->tw = tw;
423 SetTD_c_err(uhcip, td, UHCI_MAX_ERR_COUNT);
424 SetTD_status(uhcip, td, UHCI_TD_ACTIVE);
425 SetTD_ioc(uhcip, td, INTERRUPT_ON_COMPLETION);
426 SetTD_mlen(uhcip, td, num_characters - 1);
427 SetTD_dtogg(uhcip, td, pp->pp_data_toggle);
428 ADJ_DATA_TOGGLE(pp);
429 SetTD_devaddr(uhcip, td, ph->p_usba_device->usb_addr);
430 SetTD_endpt(uhcip, td, ph->p_ep.bEndpointAddress &
431 END_POINT_ADDRESS_MASK);
432 SetTD_PID(uhcip, td, PID_OUT);
433 SetTD32(uhcip, td->buffer_address, tw->tw_cookie.dmac_address);
434
435 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr,
436 TD_PADDR(td));
437
438 /*
439 * Now, add the endpoint to the lattice that we will hang our
440 * TD's off of.
441 */
442 for (i = uhcip->uhci_polled_count; i < NUM_FRAME_LST_ENTRIES;
443 i += MIN_LOW_SPEED_POLL_INTERVAL) {
444 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
445 QH_PADDR(uhci_polledp->uhci_polled_qh) | HC_QUEUE_HEAD);
446 }
447
448 /* wait for xfer to finish */
449 while (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE)
450 #ifndef __sparc
451 invalidate_cache();
452 #else
453 ;
454 #endif
455 *num_characters_written = GetTD_alen(uhcip, td) + 1;
456
457 /* Now, remove the endpoint from the lattice */
458 for (i = uhcip->uhci_polled_count; i < NUM_FRAME_LST_ENTRIES;
459 i += MIN_LOW_SPEED_POLL_INTERVAL) {
460 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
461 HC_END_OF_LIST);
462 }
463
464 #ifndef lint
465 _NOTE(COMPETING_THREADS_NOW);
466 #endif
467
468 return (USB_SUCCESS);
469 }
470
471
472 /*
473 * uhci_polled_init:
474 * Initialize generic information that is needed to provide USB/POLLED
475 * support.
476 */
477 static int
uhci_polled_init(usba_pipe_handle_data_t * ph,uhci_state_t * uhcip,usb_console_info_impl_t * console_info)478 uhci_polled_init(usba_pipe_handle_data_t *ph,
479 uhci_state_t *uhcip,
480 usb_console_info_impl_t *console_info)
481 {
482 uhci_polled_t *uhci_polledp;
483
484 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
485
486 /*
487 * If the structure has already been initialized, then we don't
488 * need to redo it.
489 */
490 if (console_info->uci_private != NULL) {
491
492 return (USB_SUCCESS);
493 }
494
495 /* Allocate and intitialize a polled mode state structure */
496 uhci_polledp = (uhci_polled_t *)kmem_zalloc(sizeof (uhci_polled_t),
497 KM_SLEEP);
498
499 /*
500 * Keep a copy of normal mode state structure and pipe handle.
501 */
502 uhci_polledp->uhci_polled_uhcip = uhcip;
503 uhci_polledp->uhci_polled_ph = ph;
504
505 /*
506 * Allocate a queue head for the device. This queue head wiil be
507 * put in action when we switch to polled mode in _enter point.
508 */
509 uhci_polledp->uhci_polled_qh = uhci_alloc_queue_head(uhcip);
510
511 if (uhci_polledp->uhci_polled_qh == NULL) {
512 kmem_free(uhci_polledp, sizeof (uhci_polled_t));
513
514 return (USB_NO_RESOURCES);
515 }
516
517 /*
518 * Insert a TD onto the queue head.
519 */
520 if ((uhci_polled_insert_td_on_qh(uhci_polledp,
521 uhci_polledp->uhci_polled_ph)) != USB_SUCCESS) {
522 uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
523 kmem_free(uhci_polledp, sizeof (uhci_polled_t));
524
525 return (USB_NO_RESOURCES);
526 }
527
528 console_info->uci_private = (usb_console_info_private_t)uhci_polledp;
529
530 return (USB_SUCCESS);
531 }
532
533
534 /*
535 * uhci_polled_fini:
536 */
537 static int
uhci_polled_fini(uhci_polled_t * uhci_polledp,uhci_state_t * uhcip)538 uhci_polled_fini(uhci_polled_t *uhci_polledp, uhci_state_t *uhcip)
539 {
540 uhci_td_t *td = uhci_polledp->uhci_polled_td;
541
542 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
543
544 /*
545 * Free the transfer wrapper
546 */
547 uhci_free_tw(uhcip, td->tw);
548
549 /*
550 * Free the queue head and transfer descriptor allocated.
551 */
552 uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
553 uhci_polledp->uhci_polled_td->flag = TD_FLAG_FREE;
554
555 /*
556 * Deallocate the memory for the polled mode state structure.
557 */
558 kmem_free(uhci_polledp, sizeof (uhci_polled_t));
559
560 return (USB_SUCCESS);
561 }
562
563
564 /*
565 * uhci_polled_save_state:
566 */
567 static void
uhci_polled_save_state(uhci_polled_t * uhci_polledp)568 uhci_polled_save_state(uhci_polled_t *uhci_polledp)
569 {
570 int i;
571 uhci_td_t *td, *polled_td;
572 uhci_state_t *uhcip;
573 usba_pipe_handle_data_t *ph;
574
575 #ifndef lint
576 _NOTE(NO_COMPETING_THREADS_NOW);
577 #endif
578
579 /*
580 * If either of these two flags are set, then we have already
581 * saved off the state information and setup the controller.
582 */
583 if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) {
584 #ifndef lint
585 _NOTE(COMPETING_THREADS_NOW);
586 #endif
587
588 return;
589 }
590
591 uhcip = uhci_polledp->uhci_polled_uhcip;
592
593 /*
594 * Check if the number of keyboard reaches the max number we can
595 * support in polled mode
596 */
597 if (++ uhcip->uhci_polled_count > MAX_NUM_FOR_KEYBORAD) {
598 #ifndef lint
599 _NOTE(COMPETING_THREADS_NOW);
600 #endif
601 return;
602 }
603
604 /*
605 * Get the normal mode usb pipe handle.
606 */
607 ph = (usba_pipe_handle_data_t *)uhci_polledp->uhci_polled_ph;
608 /*
609 * Only the first keyboard enter disable the interrutps, stop the
610 * host controller processing and initialize the interrupt table.
611 */
612 if (uhcip->uhci_polled_count == 1) {
613 /*
614 * Disable interrupts to prevent the interrupt handler getting
615 * called while we are switing to POLLed mode.
616 */
617
618 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
619
620 /*
621 * Stop the HC controller from processing TD's
622 */
623 Set_OpReg16(USBCMD, 0);
624
625 /*
626 * Save the current interrupt lattice and replace this lattice
627 * with an lattice used in POLLED mode. We will restore lattice
628 * back when we exit from the POLLED mode.
629 */
630 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) {
631 uhcip->uhci_polled_save_IntTble[i] =
632 uhcip->uhci_frame_lst_tablep[i];
633 }
634
635 /*
636 * Zero out the entire interrupt lattice tree.
637 */
638 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) {
639 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
640 HC_END_OF_LIST);
641 }
642 }
643
644 /*
645 * Now, add the endpoint to the lattice that we will hang our
646 * TD's off of. We (assume always) need to poll this device at
647 * every 8 ms.
648 */
649 for (i = uhcip->uhci_polled_count - 1; i < NUM_FRAME_LST_ENTRIES;
650 i += MIN_LOW_SPEED_POLL_INTERVAL) {
651 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
652 QH_PADDR(uhci_polledp->uhci_polled_qh) | HC_QUEUE_HEAD);
653 }
654
655 /*
656 * Adjust the data toggle
657 */
658 td = uhcip->uhci_outst_tds_head;
659 while (td != NULL) {
660 if (td->tw->tw_pipe_private->pp_pipe_handle == ph) {
661 polled_td = uhci_polledp->uhci_polled_td;
662 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) {
663 SetTD_dtogg(uhcip, polled_td,
664 GetTD_dtogg(uhcip, td));
665 } else {
666 SetTD_dtogg(uhcip, polled_td,
667 (GetTD_dtogg(uhcip, td) ^ 1));
668 uhcip->uhci_polled_flag =
669 UHCI_POLLED_FLAG_TD_COMPL;
670 }
671 break;
672 }
673 td = td->outst_td_next;
674 }
675 /*
676 * Only the first keyboard enter reset the frame number and start
677 * the host controler processing.
678 */
679 if (uhcip->uhci_polled_count == 1) {
680 /* Set the frame number to zero */
681 Set_OpReg16(FRNUM, 0);
682
683 /*
684 * Start the Host controller processing
685 */
686 Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
687 USBCMD_REG_CONFIG_FLAG));
688 }
689
690 #ifndef lint
691 _NOTE(COMPETING_THREADS_NOW);
692 #endif
693 }
694
695
696 /*
697 * uhci_polled_restore_state:
698 */
699 static void
uhci_polled_restore_state(uhci_polled_t * uhci_polledp)700 uhci_polled_restore_state(uhci_polled_t *uhci_polledp)
701 {
702 int i;
703 ushort_t real_data_toggle;
704 uhci_td_t *td, *polled_td;
705 uhci_state_t *uhcip;
706 uhci_pipe_private_t *pp;
707
708 #ifndef lint
709 _NOTE(NO_COMPETING_THREADS_NOW);
710 #endif
711 /*
712 * If this flags is set, then we are still using this structure,
713 * so don't restore any controller state information yet.
714 */
715 if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) {
716 #ifndef lint
717 _NOTE(COMPETING_THREADS_NOW);
718 #endif
719 return;
720 }
721
722 uhcip = uhci_polledp->uhci_polled_uhcip;
723 uhcip->uhci_polled_count --;
724
725 /* Just first leave keyboard entry turn off the controller */
726 if (Get_OpReg16(USBCMD)) {
727 Set_OpReg16(USBCMD, 0x0);
728 }
729 /* Only the last leave keyboard entry restore the interrupt table */
730 if (uhcip->uhci_polled_count == 0) {
731 /*
732 * Replace the lattice
733 */
734 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) {
735 uhcip->uhci_frame_lst_tablep[i] =
736 uhcip->uhci_polled_save_IntTble[i];
737 }
738 }
739
740 /*
741 * Adjust data toggle
742 */
743 pp = (uhci_pipe_private_t *)
744 uhci_polledp->uhci_polled_ph->p_hcd_private;
745
746 polled_td = uhci_polledp->uhci_polled_td;
747 real_data_toggle = (GetTD_status(uhcip, polled_td) & UHCI_TD_ACTIVE) ?
748 GetTD_dtogg(uhcip, polled_td) :
749 !GetTD_dtogg(uhcip, polled_td);
750
751 td = uhcip->uhci_outst_tds_head;
752 while (td != NULL) {
753 if (td->tw->tw_pipe_private->pp_pipe_handle ==
754 uhci_polledp->uhci_polled_ph) {
755 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) {
756 SetTD_dtogg(uhcip, td, real_data_toggle);
757 pp->pp_data_toggle =
758 (real_data_toggle == 0) ? 1 : 0;
759 } else {
760 pp->pp_data_toggle = (uchar_t)real_data_toggle;
761 }
762 }
763 td = td->outst_td_next;
764 }
765
766 /*
767 * Only the last leave keyboard entry enable the interrupts,
768 * start Host controller processing.
769 */
770 if (uhcip->uhci_polled_count == 0) {
771 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
772 Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
773 USBCMD_REG_CONFIG_FLAG));
774 if (uhcip->uhci_polled_flag == UHCI_POLLED_FLAG_TD_COMPL) {
775 uhcip->uhci_polled_flag = UHCI_POLLED_FLAG_TRUE;
776 }
777 }
778
779 #ifndef lint
780 _NOTE(COMPETING_THREADS_NOW);
781 #endif
782 }
783
784
785 /*
786 * uhci_polled_insert_td:
787 * Initializes the transfer descriptor for polling and inserts on the
788 * polled queue head. This will be put in action when entered in to
789 * polled mode.
790 */
791 static int
uhci_polled_insert_td_on_qh(uhci_polled_t * uhci_polledp,usba_pipe_handle_data_t * ph)792 uhci_polled_insert_td_on_qh(uhci_polled_t *uhci_polledp,
793 usba_pipe_handle_data_t *ph)
794 {
795 uhci_td_t *td;
796 uhci_state_t *uhcip = uhci_polledp->uhci_polled_uhcip;
797 usb_ep_descr_t *eptd;
798 uhci_trans_wrapper_t *tw;
799 uint_t direction;
800
801 /* Create the transfer wrapper */
802 if ((tw = uhci_polled_create_tw(uhci_polledp->uhci_polled_uhcip)) ==
803 NULL) {
804
805 return (USB_FAILURE);
806 }
807
808 /* Use the dummy TD allocated for the queue head */
809 td = uhci_polledp->uhci_polled_qh->td_tailp;
810 bzero((char *)td, sizeof (uhci_td_t));
811
812 uhci_polledp->uhci_polled_td = td;
813 td->tw = tw;
814 td->flag = TD_FLAG_BUSY;
815 SetTD32(uhcip, td->link_ptr, HC_END_OF_LIST);
816
817 mutex_enter(&ph->p_usba_device->usb_mutex);
818 if (ph->p_usba_device->usb_port_status == USBA_LOW_SPEED_DEV) {
819 SetTD_ls(uhcip, td, LOW_SPEED_DEVICE);
820 }
821
822 eptd = &ph->p_ep;
823 direction = (UHCI_XFER_DIR(eptd) == USB_EP_DIR_OUT) ? PID_OUT : PID_IN;
824 SetTD_c_err(uhcip, td, UHCI_MAX_ERR_COUNT);
825 SetTD_mlen(uhcip, td, POLLED_RAW_BUF_SIZE - 1);
826 SetTD_devaddr(uhcip, td, ph->p_usba_device->usb_addr);
827 SetTD_endpt(uhcip, td, eptd->bEndpointAddress & END_POINT_ADDRESS_MASK);
828 SetTD_PID(uhcip, td, direction);
829 SetTD32(uhcip, td->buffer_address, tw->tw_cookie.dmac_address);
830 SetTD_ioc(uhcip, td, INTERRUPT_ON_COMPLETION);
831 SetTD_status(uhcip, td, UHCI_TD_ACTIVE);
832 mutex_exit(&ph->p_usba_device->usb_mutex);
833
834 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr, TD_PADDR(td));
835
836 return (USB_SUCCESS);
837 }
838
839
840 /*
841 * uhci_polled_create_wrapper_t:
842 * Creates the transfer wrapper used in polled mode.
843 */
844 static uhci_trans_wrapper_t *
uhci_polled_create_tw(uhci_state_t * uhcip)845 uhci_polled_create_tw(uhci_state_t *uhcip)
846 {
847 uint_t result, ccount;
848 size_t real_length;
849 uhci_trans_wrapper_t *tw;
850 ddi_device_acc_attr_t dev_attr;
851
852 /* Allocate space for the transfer wrapper */
853 if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), KM_NOSLEEP)) ==
854 NULL) {
855
856 return (NULL);
857 }
858
859 tw->tw_length = POLLED_RAW_BUF_SIZE;
860
861 /* Allocate the DMA handle */
862 if ((result = ddi_dma_alloc_handle(uhcip->uhci_dip,
863 &uhcip->uhci_dma_attr, DDI_DMA_DONTWAIT, 0, &tw->tw_dmahandle)) !=
864 DDI_SUCCESS) {
865 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
866
867 return (NULL);
868 }
869
870 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
871 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
872 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
873
874 /* Allocate the memory */
875 if ((result = ddi_dma_mem_alloc(tw->tw_dmahandle, POLLED_RAW_BUF_SIZE,
876 &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
877 &tw->tw_buf, &real_length, &tw->tw_accesshandle)) !=
878 DDI_SUCCESS) {
879 ddi_dma_free_handle(&tw->tw_dmahandle);
880 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
881
882 return (NULL);
883 }
884
885 /* Bind the handle */
886 if ((result = ddi_dma_addr_bind_handle(tw->tw_dmahandle, NULL,
887 tw->tw_buf, real_length, DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
888 DDI_DMA_DONTWAIT, NULL, &tw->tw_cookie, &ccount)) !=
889 DDI_DMA_MAPPED) {
890 ddi_dma_mem_free(&tw->tw_accesshandle);
891 ddi_dma_free_handle(&tw->tw_dmahandle);
892 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
893
894 return (NULL);
895 }
896
897 /* The cookie count should be 1 */
898 if (ccount != 1) {
899 result = ddi_dma_unbind_handle(tw->tw_dmahandle);
900 ASSERT(result == DDI_SUCCESS);
901
902 ddi_dma_mem_free(&tw->tw_accesshandle);
903 ddi_dma_free_handle(&tw->tw_dmahandle);
904 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
905
906 return (NULL);
907 }
908
909 return (tw);
910 }
911