xref: /onnv-gate/usr/src/uts/common/io/usb/hcd/uhci/uhcipolled.c (revision 7425:e4dbffd35ebc)
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
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
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
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
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
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
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
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
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
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
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
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 = kmem_zalloc(sizeof (uhci_polled_t), KM_SLEEP);
497 
498 	/*
499 	 * Keep a copy of normal mode state structure and pipe handle.
500 	 */
501 	uhci_polledp->uhci_polled_uhcip	= uhcip;
502 	uhci_polledp->uhci_polled_ph	= ph;
503 
504 	/*
505 	 * Allocate a queue head for the device. This queue head wiil be
506 	 * put in action when we switch to polled mode in _enter point.
507 	 */
508 	uhci_polledp->uhci_polled_qh = uhci_alloc_queue_head(uhcip);
509 
510 	if (uhci_polledp->uhci_polled_qh == NULL) {
511 		kmem_free(uhci_polledp, sizeof (uhci_polled_t));
512 
513 		return (USB_NO_RESOURCES);
514 	}
515 
516 	/*
517 	 * Insert a TD onto the queue head.
518 	 */
519 	if ((uhci_polled_insert_td_on_qh(uhci_polledp,
520 	    uhci_polledp->uhci_polled_ph)) != USB_SUCCESS) {
521 		uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
522 		kmem_free(uhci_polledp, sizeof (uhci_polled_t));
523 
524 		return (USB_NO_RESOURCES);
525 	}
526 
527 	console_info->uci_private = (usb_console_info_private_t)uhci_polledp;
528 
529 	return (USB_SUCCESS);
530 }
531 
532 
533 /*
534  * uhci_polled_fini:
535  */
536 static int
537 uhci_polled_fini(uhci_polled_t *uhci_polledp, uhci_state_t *uhcip)
538 {
539 	uhci_td_t	*td = uhci_polledp->uhci_polled_td;
540 
541 	ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
542 
543 	/*
544 	 * Free the transfer wrapper
545 	 */
546 	uhci_free_tw(uhcip, td->tw);
547 
548 	/*
549 	 * Free the queue head and transfer descriptor allocated.
550 	 */
551 	uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
552 	uhci_polledp->uhci_polled_td->flag = TD_FLAG_FREE;
553 
554 	/*
555 	 * Deallocate the memory for the polled mode state structure.
556 	 */
557 	kmem_free(uhci_polledp, sizeof (uhci_polled_t));
558 
559 	return (USB_SUCCESS);
560 }
561 
562 
563 /*
564  * uhci_polled_save_state:
565  */
566 static void
567 uhci_polled_save_state(uhci_polled_t	*uhci_polledp)
568 {
569 	int			i;
570 	uhci_td_t		*td, *polled_td;
571 	uhci_state_t		*uhcip;
572 	usba_pipe_handle_data_t	*ph;
573 
574 #ifndef lint
575 	_NOTE(NO_COMPETING_THREADS_NOW);
576 #endif
577 
578 	/*
579 	 * If either of these two flags are set, then we have already
580 	 * saved off the state information and setup the controller.
581 	 */
582 	if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) {
583 #ifndef lint
584 		_NOTE(COMPETING_THREADS_NOW);
585 #endif
586 
587 		return;
588 	}
589 
590 	uhcip = uhci_polledp->uhci_polled_uhcip;
591 
592 	/*
593 	 * Check if the number of keyboard reaches the max number we can
594 	 * support in polled mode
595 	 */
596 	if (++ uhcip->uhci_polled_count > MAX_NUM_FOR_KEYBORAD) {
597 #ifndef lint
598 		_NOTE(COMPETING_THREADS_NOW);
599 #endif
600 		return;
601 	}
602 
603 	/*
604 	 * Get the normal mode usb pipe handle.
605 	 */
606 	ph = (usba_pipe_handle_data_t *)uhci_polledp->uhci_polled_ph;
607 	/*
608 	 * Only the first keyboard enter disable the interrutps, stop the
609 	 * host controller processing and initialize the interrupt table.
610 	 */
611 	if (uhcip->uhci_polled_count == 1) {
612 		/*
613 		 * Disable interrupts to prevent the interrupt handler getting
614 		 * called while we are switing to POLLed mode.
615 		 */
616 
617 		Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
618 
619 		/*
620 		 * Stop the HC controller from processing TD's
621 		 */
622 		Set_OpReg16(USBCMD, 0);
623 
624 		/*
625 		 * Save the current interrupt lattice and  replace this lattice
626 		 * with an lattice used in POLLED mode. We will restore lattice
627 		 * back when we exit from the POLLED mode.
628 		 */
629 		for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) {
630 			uhcip->uhci_polled_save_IntTble[i] =
631 			    uhcip->uhci_frame_lst_tablep[i];
632 		}
633 
634 		/*
635 		 * Zero out the entire interrupt lattice tree.
636 		 */
637 		for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) {
638 			SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
639 			    HC_END_OF_LIST);
640 		}
641 	}
642 
643 	/*
644 	 * Now, add the endpoint to the lattice that we will hang  our
645 	 * TD's off of.  We (assume always) need to poll this device at
646 	 * every 8 ms.
647 	 */
648 	for (i = uhcip->uhci_polled_count - 1; i < NUM_FRAME_LST_ENTRIES;
649 	    i += MIN_LOW_SPEED_POLL_INTERVAL) {
650 		SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i],
651 		    QH_PADDR(uhci_polledp->uhci_polled_qh) | HC_QUEUE_HEAD);
652 	}
653 
654 	/*
655 	 * Adjust the data toggle
656 	 */
657 	td = uhcip->uhci_outst_tds_head;
658 	while (td != NULL) {
659 		if (td->tw->tw_pipe_private->pp_pipe_handle == ph) {
660 			polled_td = uhci_polledp->uhci_polled_td;
661 			if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) {
662 				SetTD_dtogg(uhcip, polled_td,
663 				    GetTD_dtogg(uhcip, td));
664 			} else {
665 				SetTD_dtogg(uhcip, polled_td,
666 				    (GetTD_dtogg(uhcip, td) ^ 1));
667 				uhcip->uhci_polled_flag =
668 				    UHCI_POLLED_FLAG_TD_COMPL;
669 			}
670 			break;
671 		}
672 		td = td->outst_td_next;
673 	}
674 	/*
675 	 * Only the first keyboard enter reset the frame number and start
676 	 * the host controler processing.
677 	 */
678 	if (uhcip->uhci_polled_count == 1) {
679 		/* Set the frame number to zero */
680 		Set_OpReg16(FRNUM, 0);
681 
682 		/*
683 		 * Start the Host controller processing
684 		 */
685 		Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
686 		    USBCMD_REG_CONFIG_FLAG));
687 	}
688 
689 #ifndef lint
690 	_NOTE(COMPETING_THREADS_NOW);
691 #endif
692 }
693 
694 
695 /*
696  * uhci_polled_restore_state:
697  */
698 static void
699 uhci_polled_restore_state(uhci_polled_t	*uhci_polledp)
700 {
701 	int			i;
702 	ushort_t		real_data_toggle;
703 	uhci_td_t		*td, *polled_td;
704 	uhci_state_t		*uhcip;
705 	uhci_pipe_private_t	*pp;
706 
707 #ifndef lint
708 	_NOTE(NO_COMPETING_THREADS_NOW);
709 #endif
710 	/*
711 	 * If this flags is set, then we are still using this structure,
712 	 * so don't restore any controller state information yet.
713 	 */
714 	if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) {
715 #ifndef lint
716 		_NOTE(COMPETING_THREADS_NOW);
717 #endif
718 		return;
719 	}
720 
721 	uhcip = uhci_polledp->uhci_polled_uhcip;
722 	uhcip->uhci_polled_count --;
723 
724 	/* Just first leave keyboard entry turn off the controller */
725 	if (Get_OpReg16(USBCMD)) {
726 		Set_OpReg16(USBCMD, 0x0);
727 	}
728 	/* Only the last leave keyboard entry restore the interrupt table */
729 	if (uhcip->uhci_polled_count == 0) {
730 		/*
731 		 * Replace the lattice
732 		 */
733 		for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) {
734 			uhcip->uhci_frame_lst_tablep[i] =
735 			    uhcip->uhci_polled_save_IntTble[i];
736 		}
737 	}
738 
739 	/*
740 	 * Adjust data toggle
741 	 */
742 	pp = (uhci_pipe_private_t *)
743 	    uhci_polledp->uhci_polled_ph->p_hcd_private;
744 
745 	polled_td = uhci_polledp->uhci_polled_td;
746 	real_data_toggle = (GetTD_status(uhcip, polled_td) & UHCI_TD_ACTIVE) ?
747 	    GetTD_dtogg(uhcip, polled_td) :
748 	    !GetTD_dtogg(uhcip, polled_td);
749 
750 	td = uhcip->uhci_outst_tds_head;
751 	while (td != NULL) {
752 		if (td->tw->tw_pipe_private->pp_pipe_handle ==
753 		    uhci_polledp->uhci_polled_ph) {
754 			if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) {
755 				SetTD_dtogg(uhcip, td, real_data_toggle);
756 				pp->pp_data_toggle =
757 				    (real_data_toggle == 0) ? 1 : 0;
758 			} else {
759 				pp->pp_data_toggle = real_data_toggle;
760 			}
761 		}
762 		td = td->outst_td_next;
763 	}
764 
765 	/*
766 	 * Only the last leave keyboard entry enable the interrupts,
767 	 * start Host controller processing.
768 	 */
769 	if (uhcip->uhci_polled_count == 0) {
770 		Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
771 		Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
772 		    USBCMD_REG_CONFIG_FLAG));
773 		if (uhcip->uhci_polled_flag == UHCI_POLLED_FLAG_TD_COMPL) {
774 			uhcip->uhci_polled_flag = UHCI_POLLED_FLAG_TRUE;
775 		}
776 	}
777 
778 #ifndef lint
779 	_NOTE(COMPETING_THREADS_NOW);
780 #endif
781 }
782 
783 
784 /*
785  * uhci_polled_insert_td:
786  *	Initializes the transfer descriptor for polling and inserts on the
787  *	polled queue head. This will be put in action when entered in to
788  *	polled mode.
789  */
790 static int
791 uhci_polled_insert_td_on_qh(uhci_polled_t *uhci_polledp,
792 	usba_pipe_handle_data_t *ph)
793 {
794 	uhci_td_t		*td;
795 	uhci_state_t		*uhcip = uhci_polledp->uhci_polled_uhcip;
796 	usb_ep_descr_t		*eptd;
797 	uhci_trans_wrapper_t	*tw;
798 	uint_t			direction;
799 
800 	/* Create the transfer wrapper */
801 	if ((tw = uhci_polled_create_tw(uhci_polledp->uhci_polled_uhcip)) ==
802 	    NULL) {
803 
804 		return (USB_FAILURE);
805 	}
806 
807 	/* Use the dummy TD allocated for the queue head */
808 	td = uhci_polledp->uhci_polled_qh->td_tailp;
809 	bzero((char *)td, sizeof (uhci_td_t));
810 
811 	uhci_polledp->uhci_polled_td = td;
812 	td->tw = tw;
813 	td->flag = TD_FLAG_BUSY;
814 	SetTD32(uhcip, td->link_ptr, HC_END_OF_LIST);
815 
816 	mutex_enter(&ph->p_usba_device->usb_mutex);
817 	if (ph->p_usba_device->usb_port_status == USBA_LOW_SPEED_DEV) {
818 		SetTD_ls(uhcip, td, LOW_SPEED_DEVICE);
819 	}
820 
821 	eptd = &ph->p_ep;
822 	direction = (UHCI_XFER_DIR(eptd) == USB_EP_DIR_OUT) ? PID_OUT : PID_IN;
823 	SetTD_c_err(uhcip, td, UHCI_MAX_ERR_COUNT);
824 	SetTD_mlen(uhcip, td, POLLED_RAW_BUF_SIZE - 1);
825 	SetTD_devaddr(uhcip, td, ph->p_usba_device->usb_addr);
826 	SetTD_endpt(uhcip, td, eptd->bEndpointAddress & END_POINT_ADDRESS_MASK);
827 	SetTD_PID(uhcip, td, direction);
828 	SetTD32(uhcip, td->buffer_address, tw->tw_cookie.dmac_address);
829 	SetTD_ioc(uhcip, td, INTERRUPT_ON_COMPLETION);
830 	SetTD_status(uhcip, td, UHCI_TD_ACTIVE);
831 	mutex_exit(&ph->p_usba_device->usb_mutex);
832 
833 	SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr, TD_PADDR(td));
834 
835 	return (USB_SUCCESS);
836 }
837 
838 
839 /*
840  * uhci_polled_create_wrapper_t:
841  *	Creates the transfer wrapper used in polled mode.
842  */
843 static uhci_trans_wrapper_t *
844 uhci_polled_create_tw(uhci_state_t *uhcip)
845 {
846 	uint_t			result, ccount;
847 	size_t			real_length;
848 	uhci_trans_wrapper_t	*tw;
849 	ddi_device_acc_attr_t	dev_attr;
850 
851 	/* Allocate space for the transfer wrapper */
852 	if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), KM_NOSLEEP)) ==
853 	    NULL) {
854 
855 		return (NULL);
856 	}
857 
858 	tw->tw_length = POLLED_RAW_BUF_SIZE;
859 
860 	/* Allocate the DMA handle */
861 	if ((result = ddi_dma_alloc_handle(uhcip->uhci_dip,
862 	    &uhcip->uhci_dma_attr, DDI_DMA_DONTWAIT, 0, &tw->tw_dmahandle)) !=
863 	    DDI_SUCCESS) {
864 		kmem_free(tw, sizeof (uhci_trans_wrapper_t));
865 
866 		return (NULL);
867 	}
868 
869 	dev_attr.devacc_attr_version		= DDI_DEVICE_ATTR_V0;
870 	dev_attr.devacc_attr_endian_flags	= DDI_STRUCTURE_LE_ACC;
871 	dev_attr.devacc_attr_dataorder		= DDI_STRICTORDER_ACC;
872 
873 	/* Allocate the memory */
874 	if ((result = ddi_dma_mem_alloc(tw->tw_dmahandle, POLLED_RAW_BUF_SIZE,
875 	    &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
876 	    &tw->tw_buf, &real_length, &tw->tw_accesshandle)) !=
877 	    DDI_SUCCESS) {
878 		ddi_dma_free_handle(&tw->tw_dmahandle);
879 		kmem_free(tw, sizeof (uhci_trans_wrapper_t));
880 
881 		return (NULL);
882 	}
883 
884 	/* Bind the handle */
885 	if ((result = ddi_dma_addr_bind_handle(tw->tw_dmahandle, NULL,
886 	    tw->tw_buf, real_length, DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
887 	    DDI_DMA_DONTWAIT, NULL, &tw->tw_cookie, &ccount)) !=
888 	    DDI_DMA_MAPPED) {
889 		ddi_dma_mem_free(&tw->tw_accesshandle);
890 		ddi_dma_free_handle(&tw->tw_dmahandle);
891 		kmem_free(tw, sizeof (uhci_trans_wrapper_t));
892 
893 		return (NULL);
894 	}
895 
896 	/* The cookie count should be 1 */
897 	if (ccount != 1) {
898 		result = ddi_dma_unbind_handle(tw->tw_dmahandle);
899 		ASSERT(result == DDI_SUCCESS);
900 
901 		ddi_dma_mem_free(&tw->tw_accesshandle);
902 		ddi_dma_free_handle(&tw->tw_dmahandle);
903 		kmem_free(tw, sizeof (uhci_trans_wrapper_t));
904 
905 		return (NULL);
906 	}
907 
908 	return (tw);
909 }
910