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