uhcipolled.c revision 2326:38ebe9e094d9
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
35extern void invalidate_cache();
36#endif
37/*
38 * Internal Function Prototypes
39 */
40/* Polled initialization routine */
41static int	uhci_polled_init(usba_pipe_handle_data_t *, uhci_state_t *,
42		    usb_console_info_impl_t *);
43
44/* Polled fini routine */
45static int	uhci_polled_fini(uhci_polled_t *, uhci_state_t *);
46
47/* Polled save state routine */
48static void	uhci_polled_save_state(uhci_polled_t *);
49
50/* Polled restore state routine */
51static void	uhci_polled_restore_state(uhci_polled_t *);
52
53/* Polled read routines */
54static int	uhci_polled_insert_td_on_qh(uhci_polled_t *,
55		    usba_pipe_handle_data_t *);
56static 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 */
72int
73uhci_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 */
119int
120uhci_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 */
146int
147uhci_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 */
174int
175uhci_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 */
201int
202uhci_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 */
289int
290uhci_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 */
327int
328uhci_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 */
350int
351uhci_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*/
377int
378uhci_hcdi_polled_output_exit(usb_console_info_impl_t *info)
379{
380	return (USB_SUCCESS);
381}
382
383static int uhci_polled_status;
384
385/*
386 * uhci_hcdi_polled_write:
387 *	Put a key character -- rewrite this!
388 */
389int
390uhci_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 */
481static int
482uhci_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 */
541static int
542uhci_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 */
571static void
572uhci_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 */
703static void
704uhci_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 */
795static int
796uhci_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 */
848static uhci_trans_wrapper_t *
849uhci_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