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