preprocessor cleanup: __sparc
[unleashed/tickless.git] / usr / src / uts / common / io / usb / hcd / uhci / uhcipolled.c
blob5c93b560501909ecc978e88c14346b44591647c0
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 * This module contains the specific uhci code used in POLLED mode.
30 #include <sys/usb/hcd/uhci/uhcid.h>
31 #include <sys/usb/hcd/uhci/uhcipolled.h>
33 extern void invalidate_cache();
35 * Internal Function Prototypes
37 /* Polled initialization routine */
38 static int uhci_polled_init(usba_pipe_handle_data_t *, uhci_state_t *,
39 usb_console_info_impl_t *);
41 /* Polled fini routine */
42 static int uhci_polled_fini(uhci_polled_t *, uhci_state_t *);
44 /* Polled save state routine */
45 static void uhci_polled_save_state(uhci_polled_t *);
47 /* Polled restore state routine */
48 static void uhci_polled_restore_state(uhci_polled_t *);
50 /* Polled read routines */
51 static int uhci_polled_insert_td_on_qh(uhci_polled_t *,
52 usba_pipe_handle_data_t *);
53 static uhci_trans_wrapper_t
54 *uhci_polled_create_tw(uhci_state_t *);
58 * POLLED entry points
60 * These functions are entry points into the POLLED code.
64 * uhci_hcdi_polled_input_init:
65 * This is the initialization routine for handling the USB keyboard
66 * in POLLED mode. This routine is not called from POLLED mode, so
67 * it is OK to acquire mutexes.
69 int
70 uhci_hcdi_polled_input_init(usba_pipe_handle_data_t *ph,
71 uchar_t **polled_buf,
72 usb_console_info_impl_t *console_input_info)
74 int ret;
75 uhci_polled_t *uhci_polledp;
76 uhci_state_t *uhcip;
78 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
81 * Grab the uhci_int_mutex so that things don't change on us
82 * if an interrupt comes in.
84 mutex_enter(&uhcip->uhci_int_mutex);
85 ret = uhci_polled_init(ph, uhcip, console_input_info);
86 if (ret != USB_SUCCESS) {
87 mutex_exit(&uhcip->uhci_int_mutex);
89 return (ret);
92 uhci_polledp = (uhci_polled_t *)console_input_info->uci_private;
94 * Mark the structure so that if we are using it, we don't free
95 * the structures if one of them is unplugged.
97 uhci_polledp->uhci_polled_flags |= POLLED_INPUT_MODE;
100 * This is the buffer we will copy characters into. It will be
101 * copied into at this layer, so we need to keep track of it.
103 uhci_polledp->uhci_polled_buf =
104 (uchar_t *)kmem_zalloc(POLLED_RAW_BUF_SIZE, KM_SLEEP);
106 *polled_buf = uhci_polledp->uhci_polled_buf;
108 mutex_exit(&uhcip->uhci_int_mutex);
109 return (USB_SUCCESS);
114 * uhci_hcdi_polled_input_fini:
117 uhci_hcdi_polled_input_fini(usb_console_info_impl_t *info)
119 int ret;
120 uhci_state_t *uhcip;
121 uhci_polled_t *uhci_polledp;
123 uhci_polledp = (uhci_polled_t *)info->uci_private;
124 uhcip = uhci_polledp->uhci_polled_uhcip;
125 mutex_enter(&uhcip->uhci_int_mutex);
127 /* Free the buffer that we copied data into */
128 kmem_free(uhci_polledp->uhci_polled_buf, POLLED_RAW_BUF_SIZE);
129 ret = uhci_polled_fini(uhci_polledp, uhcip);
130 info->uci_private = NULL;
131 mutex_exit(&uhcip->uhci_int_mutex);
133 return (ret);
138 * uhci_hcdi_polled_input_enter:
139 * This is where we enter into POLLED mode. This routine sets up
140 * everything so that calls to uhci_hcdi_polled_read will return
141 * characters.
144 uhci_hcdi_polled_input_enter(usb_console_info_impl_t *info)
146 uhci_polled_t *uhci_polledp;
148 uhci_polledp = (uhci_polled_t *)info->uci_private;
149 uhci_polledp->uhci_polled_entry++;
152 * If the controller is already switched over, just return
154 if (uhci_polledp->uhci_polled_entry > 1) {
156 return (USB_SUCCESS);
159 uhci_polled_save_state(uhci_polledp);
160 uhci_polledp->uhci_polled_flags |= POLLED_INPUT_MODE_INUSE;
162 return (USB_SUCCESS);
167 * uhci_hcdi_polled_input_exit:
168 * This is where we exit POLLED mode. This routine restores
169 * everything that is needed to continue operation.
172 uhci_hcdi_polled_input_exit(usb_console_info_impl_t *info)
174 uhci_polled_t *uhci_polledp;
176 uhci_polledp = (uhci_polled_t *)info->uci_private;
177 uhci_polledp->uhci_polled_entry--;
180 * If there are still outstanding "enters", just return
182 if (uhci_polledp->uhci_polled_entry > 0) {
184 return (USB_SUCCESS);
187 uhci_polledp->uhci_polled_flags &= ~POLLED_INPUT_MODE_INUSE;
188 uhci_polled_restore_state(uhci_polledp);
190 return (USB_SUCCESS);
195 * uhci_hcdi_polled_read:
196 * Get a key character
199 uhci_hcdi_polled_read(usb_console_info_impl_t *info, uint_t *num_characters)
201 uhci_state_t *uhcip;
202 uhci_polled_t *uhci_polledp;
203 uhci_td_t *td;
204 uhci_trans_wrapper_t *tw;
205 ushort_t intr_status;
207 uhci_polledp = (uhci_polled_t *)info->uci_private;
208 uhcip = uhci_polledp->uhci_polled_uhcip;
211 * This is a temporary work around for halt problem. The upper
212 * layer code does not call the right sequence of entry points
213 * points for reading a character in a polled mode. Once the
214 * upper layer code is fixed, the following code (two lines)
215 * must be removed.
217 if (uhci_polledp->uhci_polled_entry == 0) {
218 if (uhci_hcdi_polled_input_enter(info) != USB_SUCCESS) {
219 cmn_err(CE_WARN, "Entering Polled Mode failed");
223 _NOTE(NO_COMPETING_THREADS_NOW);
224 invalidate_cache();
226 td = uhci_polledp->uhci_polled_td;
229 * Check to see if there are any TD's on the done head.
231 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) {
232 *num_characters = 0;
233 } else {
236 * If the TD does not complete, retry.
238 if ((GetTD_status(uhcip, td) & TD_STATUS_MASK) ||
239 (GetTD_alen(uhcip, td) == ZERO_LENGTH)) {
240 *num_characters = 0;
241 SetTD_alen(uhcip, td, 0);
242 } else {
243 *num_characters = GetTD_alen(uhcip, td) + 1;
245 tw = td->tw;
247 /* Copy the data into the message */
248 ddi_rep_get8(tw->tw_accesshandle,
249 (uint8_t *)uhci_polledp->uhci_polled_buf,
250 (uint8_t *)td->tw->tw_buf,
251 *num_characters, DDI_DEV_AUTOINCR);
255 * Insert the td again into the lattice.
257 SetTD_dtogg(uhcip, td, GetTD_dtogg(uhcip, td) == 0 ? 1 : 0);
259 SetTD_status(uhcip, td, UHCI_TD_ACTIVE);
260 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr,
261 TD_PADDR(td));
263 /* Clear the interrupt status register */
264 intr_status = Get_OpReg16(USBSTS);
265 Set_OpReg16(USBSTS, intr_status);
268 _NOTE(COMPETING_THREADS_NOW);
270 return (USB_SUCCESS);
274 * uhci_hcdi_polled_output_init:
275 * This is the initialization routine for handling the USB serial
276 * output in POLLED mode. This routine is called after input_init
277 * succeeded.
280 uhci_hcdi_polled_output_init(usba_pipe_handle_data_t *ph,
281 usb_console_info_impl_t *console_output_info)
283 int ret;
284 uhci_polled_t *uhci_polledp;
285 uhci_state_t *uhcip;
287 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
290 * Grab the uhci_int_mutex so that things don't change on us
291 * if an interrupt comes in.
293 mutex_enter(&uhcip->uhci_int_mutex);
294 ret = uhci_polled_init(ph, uhcip, console_output_info);
295 if (ret != USB_SUCCESS) {
296 mutex_exit(&uhcip->uhci_int_mutex);
298 return (ret);
301 uhci_polledp = (uhci_polled_t *)console_output_info->uci_private;
303 * Mark the structure so that if we are using it, we don't free
304 * the structures if one of them is unplugged.
306 uhci_polledp->uhci_polled_flags |= POLLED_OUTPUT_MODE;
308 mutex_exit(&uhcip->uhci_int_mutex);
310 return (USB_SUCCESS);
315 * uhci_hcdi_polled_output_fini:
318 uhci_hcdi_polled_output_fini(usb_console_info_impl_t *info)
320 int ret;
321 uhci_state_t *uhcip;
322 uhci_polled_t *uhci_polledp;
324 uhci_polledp = (uhci_polled_t *)info->uci_private;
325 uhcip = uhci_polledp->uhci_polled_uhcip;
326 mutex_enter(&uhcip->uhci_int_mutex);
328 ret = uhci_polled_fini(uhci_polledp, uhcip);
329 info->uci_private = NULL;
330 mutex_exit(&uhcip->uhci_int_mutex);
332 return (ret);
337 * uhci_hcdi_polled_output_enter:
338 * everything is done in input enter
341 uhci_hcdi_polled_output_enter(usb_console_info_impl_t *info)
343 uhci_state_t *uhcip;
344 uhci_polled_t *uhci_polledp;
346 uhci_polledp = (uhci_polled_t *)info->uci_private;
347 uhcip = uhci_polledp->uhci_polled_uhcip;
350 * Check if the number of devices reaches the max number
351 * we can support in polled mode
353 if (uhcip->uhci_polled_count + 1 > MAX_NUM_FOR_KEYBORAD) {
355 return (USB_FAILURE);
358 return (USB_SUCCESS);
363 * uhci_hcdi_polled_output_exit:
364 * everything is done in input exit
366 /*ARGSUSED*/
368 uhci_hcdi_polled_output_exit(usb_console_info_impl_t *info)
370 return (USB_SUCCESS);
374 * uhci_hcdi_polled_write:
375 * Put a key character -- rewrite this!
378 uhci_hcdi_polled_write(usb_console_info_impl_t *info, uchar_t *buf,
379 uint_t num_characters, uint_t *num_characters_written)
381 int i;
382 uhci_state_t *uhcip;
383 uhci_polled_t *uhci_polledp;
384 uhci_td_t *td;
385 uhci_trans_wrapper_t *tw;
386 uhci_pipe_private_t *pp;
387 usba_pipe_handle_data_t *ph;
389 _NOTE(NO_COMPETING_THREADS_NOW);
391 uhci_polledp = (uhci_polled_t *)info->uci_private;
392 uhcip = uhci_polledp->uhci_polled_uhcip;
393 ph = uhci_polledp->uhci_polled_ph;
394 pp = (uhci_pipe_private_t *)ph->p_hcd_private;
396 td = uhci_polledp->uhci_polled_td;
397 tw = td->tw;
399 /* copy transmit buffer */
400 if (num_characters > POLLED_RAW_BUF_SIZE) {
401 cmn_err(CE_NOTE, "polled write size %d bigger than %d",
402 num_characters, POLLED_RAW_BUF_SIZE);
403 num_characters = POLLED_RAW_BUF_SIZE;
405 tw->tw_length = num_characters;
406 ddi_put8(tw->tw_accesshandle, (uint8_t *)tw->tw_buf, *buf);
407 ddi_rep_put8(tw->tw_accesshandle, buf, (uint8_t *)tw->tw_buf,
408 num_characters, DDI_DEV_AUTOINCR);
410 bzero((char *)td, sizeof (uhci_td_t));
412 td->tw = tw;
413 SetTD_c_err(uhcip, td, UHCI_MAX_ERR_COUNT);
414 SetTD_status(uhcip, td, UHCI_TD_ACTIVE);
415 SetTD_ioc(uhcip, td, INTERRUPT_ON_COMPLETION);
416 SetTD_mlen(uhcip, td, num_characters - 1);
417 SetTD_dtogg(uhcip, td, pp->pp_data_toggle);
418 ADJ_DATA_TOGGLE(pp);
419 SetTD_devaddr(uhcip, td, ph->p_usba_device->usb_addr);
420 SetTD_endpt(uhcip, td, ph->p_ep.bEndpointAddress &
421 END_POINT_ADDRESS_MASK);
422 SetTD_PID(uhcip, td, PID_OUT);
423 SetTD32(uhcip, td->buffer_address, tw->tw_cookie.dmac_address);
425 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr,
426 TD_PADDR(td));
429 * Now, add the endpoint to the lattice that we will hang our
430 * TD's off of.
432 for (i = uhcip->uhci_polled_count; i < NUM_FRAME_LST_ENTRIES;
433 i += MIN_LOW_SPEED_POLL_INTERVAL) {
434 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
435 QH_PADDR(uhci_polledp->uhci_polled_qh) | HC_QUEUE_HEAD);
438 /* wait for xfer to finish */
439 while (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE)
440 invalidate_cache();
441 *num_characters_written = GetTD_alen(uhcip, td) + 1;
443 /* Now, remove the endpoint from the lattice */
444 for (i = uhcip->uhci_polled_count; i < NUM_FRAME_LST_ENTRIES;
445 i += MIN_LOW_SPEED_POLL_INTERVAL) {
446 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
447 HC_END_OF_LIST);
450 _NOTE(COMPETING_THREADS_NOW);
452 return (USB_SUCCESS);
457 * uhci_polled_init:
458 * Initialize generic information that is needed to provide USB/POLLED
459 * support.
461 static int
462 uhci_polled_init(usba_pipe_handle_data_t *ph,
463 uhci_state_t *uhcip,
464 usb_console_info_impl_t *console_info)
466 uhci_polled_t *uhci_polledp;
468 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
471 * If the structure has already been initialized, then we don't
472 * need to redo it.
474 if (console_info->uci_private != NULL) {
476 return (USB_SUCCESS);
479 /* Allocate and intitialize a polled mode state structure */
480 uhci_polledp = (uhci_polled_t *)kmem_zalloc(sizeof (uhci_polled_t),
481 KM_SLEEP);
484 * Keep a copy of normal mode state structure and pipe handle.
486 uhci_polledp->uhci_polled_uhcip = uhcip;
487 uhci_polledp->uhci_polled_ph = ph;
490 * Allocate a queue head for the device. This queue head wiil be
491 * put in action when we switch to polled mode in _enter point.
493 uhci_polledp->uhci_polled_qh = uhci_alloc_queue_head(uhcip);
495 if (uhci_polledp->uhci_polled_qh == NULL) {
496 kmem_free(uhci_polledp, sizeof (uhci_polled_t));
498 return (USB_NO_RESOURCES);
502 * Insert a TD onto the queue head.
504 if ((uhci_polled_insert_td_on_qh(uhci_polledp,
505 uhci_polledp->uhci_polled_ph)) != USB_SUCCESS) {
506 uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
507 kmem_free(uhci_polledp, sizeof (uhci_polled_t));
509 return (USB_NO_RESOURCES);
512 console_info->uci_private = (usb_console_info_private_t)uhci_polledp;
514 return (USB_SUCCESS);
519 * uhci_polled_fini:
521 static int
522 uhci_polled_fini(uhci_polled_t *uhci_polledp, uhci_state_t *uhcip)
524 uhci_td_t *td = uhci_polledp->uhci_polled_td;
526 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
529 * Free the transfer wrapper
531 uhci_free_tw(uhcip, td->tw);
534 * Free the queue head and transfer descriptor allocated.
536 uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
537 uhci_polledp->uhci_polled_td->flag = TD_FLAG_FREE;
540 * Deallocate the memory for the polled mode state structure.
542 kmem_free(uhci_polledp, sizeof (uhci_polled_t));
544 return (USB_SUCCESS);
549 * uhci_polled_save_state:
551 static void
552 uhci_polled_save_state(uhci_polled_t *uhci_polledp)
554 int i;
555 uhci_td_t *td, *polled_td;
556 uhci_state_t *uhcip;
557 usba_pipe_handle_data_t *ph;
559 _NOTE(NO_COMPETING_THREADS_NOW);
562 * If either of these two flags are set, then we have already
563 * saved off the state information and setup the controller.
565 if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) {
566 _NOTE(COMPETING_THREADS_NOW);
568 return;
571 uhcip = uhci_polledp->uhci_polled_uhcip;
574 * Check if the number of keyboard reaches the max number we can
575 * support in polled mode
577 if (++ uhcip->uhci_polled_count > MAX_NUM_FOR_KEYBORAD) {
578 _NOTE(COMPETING_THREADS_NOW);
579 return;
583 * Get the normal mode usb pipe handle.
585 ph = (usba_pipe_handle_data_t *)uhci_polledp->uhci_polled_ph;
587 * Only the first keyboard enter disable the interrutps, stop the
588 * host controller processing and initialize the interrupt table.
590 if (uhcip->uhci_polled_count == 1) {
592 * Disable interrupts to prevent the interrupt handler getting
593 * called while we are switing to POLLed mode.
596 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
599 * Stop the HC controller from processing TD's
601 Set_OpReg16(USBCMD, 0);
604 * Save the current interrupt lattice and replace this lattice
605 * with an lattice used in POLLED mode. We will restore lattice
606 * back when we exit from the POLLED mode.
608 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) {
609 uhcip->uhci_polled_save_IntTble[i] =
610 uhcip->uhci_frame_lst_tablep[i];
614 * Zero out the entire interrupt lattice tree.
616 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) {
617 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
618 HC_END_OF_LIST);
623 * Now, add the endpoint to the lattice that we will hang our
624 * TD's off of. We (assume always) need to poll this device at
625 * every 8 ms.
627 for (i = uhcip->uhci_polled_count - 1; i < NUM_FRAME_LST_ENTRIES;
628 i += MIN_LOW_SPEED_POLL_INTERVAL) {
629 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
630 QH_PADDR(uhci_polledp->uhci_polled_qh) | HC_QUEUE_HEAD);
634 * Adjust the data toggle
636 td = uhcip->uhci_outst_tds_head;
637 while (td != NULL) {
638 if (td->tw->tw_pipe_private->pp_pipe_handle == ph) {
639 polled_td = uhci_polledp->uhci_polled_td;
640 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) {
641 SetTD_dtogg(uhcip, polled_td,
642 GetTD_dtogg(uhcip, td));
643 } else {
644 SetTD_dtogg(uhcip, polled_td,
645 (GetTD_dtogg(uhcip, td) ^ 1));
646 uhcip->uhci_polled_flag =
647 UHCI_POLLED_FLAG_TD_COMPL;
649 break;
651 td = td->outst_td_next;
654 * Only the first keyboard enter reset the frame number and start
655 * the host controler processing.
657 if (uhcip->uhci_polled_count == 1) {
658 /* Set the frame number to zero */
659 Set_OpReg16(FRNUM, 0);
662 * Start the Host controller processing
664 Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
665 USBCMD_REG_CONFIG_FLAG));
668 _NOTE(COMPETING_THREADS_NOW);
673 * uhci_polled_restore_state:
675 static void
676 uhci_polled_restore_state(uhci_polled_t *uhci_polledp)
678 int i;
679 ushort_t real_data_toggle;
680 uhci_td_t *td, *polled_td;
681 uhci_state_t *uhcip;
682 uhci_pipe_private_t *pp;
684 _NOTE(NO_COMPETING_THREADS_NOW);
686 * If this flags is set, then we are still using this structure,
687 * so don't restore any controller state information yet.
689 if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) {
690 _NOTE(COMPETING_THREADS_NOW);
691 return;
694 uhcip = uhci_polledp->uhci_polled_uhcip;
695 uhcip->uhci_polled_count --;
697 /* Just first leave keyboard entry turn off the controller */
698 if (Get_OpReg16(USBCMD)) {
699 Set_OpReg16(USBCMD, 0x0);
701 /* Only the last leave keyboard entry restore the interrupt table */
702 if (uhcip->uhci_polled_count == 0) {
704 * Replace the lattice
706 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) {
707 uhcip->uhci_frame_lst_tablep[i] =
708 uhcip->uhci_polled_save_IntTble[i];
713 * Adjust data toggle
715 pp = (uhci_pipe_private_t *)
716 uhci_polledp->uhci_polled_ph->p_hcd_private;
718 polled_td = uhci_polledp->uhci_polled_td;
719 real_data_toggle = (GetTD_status(uhcip, polled_td) & UHCI_TD_ACTIVE) ?
720 GetTD_dtogg(uhcip, polled_td) :
721 !GetTD_dtogg(uhcip, polled_td);
723 td = uhcip->uhci_outst_tds_head;
724 while (td != NULL) {
725 if (td->tw->tw_pipe_private->pp_pipe_handle ==
726 uhci_polledp->uhci_polled_ph) {
727 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) {
728 SetTD_dtogg(uhcip, td, real_data_toggle);
729 pp->pp_data_toggle =
730 (real_data_toggle == 0) ? 1 : 0;
731 } else {
732 pp->pp_data_toggle = (uchar_t)real_data_toggle;
735 td = td->outst_td_next;
739 * Only the last leave keyboard entry enable the interrupts,
740 * start Host controller processing.
742 if (uhcip->uhci_polled_count == 0) {
743 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
744 Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
745 USBCMD_REG_CONFIG_FLAG));
746 if (uhcip->uhci_polled_flag == UHCI_POLLED_FLAG_TD_COMPL) {
747 uhcip->uhci_polled_flag = UHCI_POLLED_FLAG_TRUE;
751 _NOTE(COMPETING_THREADS_NOW);
756 * uhci_polled_insert_td:
757 * Initializes the transfer descriptor for polling and inserts on the
758 * polled queue head. This will be put in action when entered in to
759 * polled mode.
761 static int
762 uhci_polled_insert_td_on_qh(uhci_polled_t *uhci_polledp,
763 usba_pipe_handle_data_t *ph)
765 uhci_td_t *td;
766 uhci_state_t *uhcip = uhci_polledp->uhci_polled_uhcip;
767 usb_ep_descr_t *eptd;
768 uhci_trans_wrapper_t *tw;
769 uint_t direction;
771 /* Create the transfer wrapper */
772 if ((tw = uhci_polled_create_tw(uhci_polledp->uhci_polled_uhcip)) ==
773 NULL) {
775 return (USB_FAILURE);
778 /* Use the dummy TD allocated for the queue head */
779 td = uhci_polledp->uhci_polled_qh->td_tailp;
780 bzero((char *)td, sizeof (uhci_td_t));
782 uhci_polledp->uhci_polled_td = td;
783 td->tw = tw;
784 td->flag = TD_FLAG_BUSY;
785 SetTD32(uhcip, td->link_ptr, HC_END_OF_LIST);
787 mutex_enter(&ph->p_usba_device->usb_mutex);
788 if (ph->p_usba_device->usb_port_status == USBA_LOW_SPEED_DEV) {
789 SetTD_ls(uhcip, td, LOW_SPEED_DEVICE);
792 eptd = &ph->p_ep;
793 direction = (UHCI_XFER_DIR(eptd) == USB_EP_DIR_OUT) ? PID_OUT : PID_IN;
794 SetTD_c_err(uhcip, td, UHCI_MAX_ERR_COUNT);
795 SetTD_mlen(uhcip, td, POLLED_RAW_BUF_SIZE - 1);
796 SetTD_devaddr(uhcip, td, ph->p_usba_device->usb_addr);
797 SetTD_endpt(uhcip, td, eptd->bEndpointAddress & END_POINT_ADDRESS_MASK);
798 SetTD_PID(uhcip, td, direction);
799 SetTD32(uhcip, td->buffer_address, tw->tw_cookie.dmac_address);
800 SetTD_ioc(uhcip, td, INTERRUPT_ON_COMPLETION);
801 SetTD_status(uhcip, td, UHCI_TD_ACTIVE);
802 mutex_exit(&ph->p_usba_device->usb_mutex);
804 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr, TD_PADDR(td));
806 return (USB_SUCCESS);
811 * uhci_polled_create_wrapper_t:
812 * Creates the transfer wrapper used in polled mode.
814 static uhci_trans_wrapper_t *
815 uhci_polled_create_tw(uhci_state_t *uhcip)
817 uint_t result, ccount;
818 size_t real_length;
819 uhci_trans_wrapper_t *tw;
820 ddi_device_acc_attr_t dev_attr;
822 /* Allocate space for the transfer wrapper */
823 if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), KM_NOSLEEP)) ==
824 NULL) {
826 return (NULL);
829 tw->tw_length = POLLED_RAW_BUF_SIZE;
831 /* Allocate the DMA handle */
832 if ((result = ddi_dma_alloc_handle(uhcip->uhci_dip,
833 &uhcip->uhci_dma_attr, DDI_DMA_DONTWAIT, 0, &tw->tw_dmahandle)) !=
834 DDI_SUCCESS) {
835 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
837 return (NULL);
840 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
841 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
842 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
844 /* Allocate the memory */
845 if ((result = ddi_dma_mem_alloc(tw->tw_dmahandle, POLLED_RAW_BUF_SIZE,
846 &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
847 &tw->tw_buf, &real_length, &tw->tw_accesshandle)) !=
848 DDI_SUCCESS) {
849 ddi_dma_free_handle(&tw->tw_dmahandle);
850 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
852 return (NULL);
855 /* Bind the handle */
856 if ((result = ddi_dma_addr_bind_handle(tw->tw_dmahandle, NULL,
857 tw->tw_buf, real_length, DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
858 DDI_DMA_DONTWAIT, NULL, &tw->tw_cookie, &ccount)) !=
859 DDI_DMA_MAPPED) {
860 ddi_dma_mem_free(&tw->tw_accesshandle);
861 ddi_dma_free_handle(&tw->tw_dmahandle);
862 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
864 return (NULL);
867 /* The cookie count should be 1 */
868 if (ccount != 1) {
869 result = ddi_dma_unbind_handle(tw->tw_dmahandle);
870 ASSERT(result == DDI_SUCCESS);
872 ddi_dma_mem_free(&tw->tw_accesshandle);
873 ddi_dma_free_handle(&tw->tw_dmahandle);
874 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
876 return (NULL);
879 return (tw);