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