17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53304303fSsl  * Common Development and Distribution License (the "License").
63304303fSsl  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
229b58c2adSzhigang lu - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * EHCI Host Controller Driver (EHCI)
287c478bd9Sstevel@tonic-gate  *
297c478bd9Sstevel@tonic-gate  * The EHCI driver is a software driver which interfaces to the Universal
307c478bd9Sstevel@tonic-gate  * Serial Bus layer (USBA) and the Host Controller (HC). The interface to
317c478bd9Sstevel@tonic-gate  * the Host Controller is defined by the EHCI Host Controller Interface.
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * This module contains the specific EHCI code used in POLLED mode. This
347c478bd9Sstevel@tonic-gate  * code is in a separate file since it will never become part of the EHCI
357c478bd9Sstevel@tonic-gate  * driver.
367c478bd9Sstevel@tonic-gate  */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include <sys/usb/usba/usbai_version.h>
397c478bd9Sstevel@tonic-gate #include <sys/usb/hcd/ehci/ehcid.h>
407c478bd9Sstevel@tonic-gate #include <sys/usb/hcd/ehci/ehci_xfer.h>
417c478bd9Sstevel@tonic-gate #include <sys/usb/hcd/ehci/ehci_intr.h>
427c478bd9Sstevel@tonic-gate #include <sys/usb/hcd/ehci/ehci_util.h>
437c478bd9Sstevel@tonic-gate #include <sys/usb/hcd/ehci/ehci_polled.h>
447c478bd9Sstevel@tonic-gate 
459b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef __sparc
469b58c2adSzhigang lu - Sun Microsystems - Beijing China extern void invalidate_cache();
479b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
489b58c2adSzhigang lu - Sun Microsystems - Beijing China 
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate  * Internal Function Prototypes
517c478bd9Sstevel@tonic-gate  */
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /* Polled initialization routines */
547c478bd9Sstevel@tonic-gate static int	ehci_polled_init(
557c478bd9Sstevel@tonic-gate 				usba_pipe_handle_data_t	*ph,
567c478bd9Sstevel@tonic-gate 				ehci_state_t		*ehcip,
577c478bd9Sstevel@tonic-gate 				usb_console_info_impl_t	*console_input_info);
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate /* Polled deinitialization routines */
607c478bd9Sstevel@tonic-gate static int	ehci_polled_fini(ehci_polled_t		*ehci_polledp);
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /* Polled save state routines */
637c478bd9Sstevel@tonic-gate static void	ehci_polled_save_state(ehci_polled_t	*ehci_polledp);
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /* Polled restore state routines */
667c478bd9Sstevel@tonic-gate static void	ehci_polled_restore_state(ehci_polled_t	*ehci_polledp);
677c478bd9Sstevel@tonic-gate static void	ehci_polled_stop_processing(
687c478bd9Sstevel@tonic-gate 				ehci_polled_t		*ehci_polledp);
697c478bd9Sstevel@tonic-gate static void	ehci_polled_start_processing(
707c478bd9Sstevel@tonic-gate 				ehci_polled_t		*ehci_polledp);
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate /* Polled read routines */
737c478bd9Sstevel@tonic-gate static int	ehci_polled_process_active_intr_qtd_list(
747c478bd9Sstevel@tonic-gate 				ehci_polled_t		*ehci_polledp);
757c478bd9Sstevel@tonic-gate static int	ehci_polled_handle_normal_qtd(
767c478bd9Sstevel@tonic-gate 				ehci_polled_t		*ehci_polledp,
777c478bd9Sstevel@tonic-gate 				ehci_qtd_t		*qtd);
789b58c2adSzhigang lu - Sun Microsystems - Beijing China static void	ehci_polled_insert_intr_qtd(
797c478bd9Sstevel@tonic-gate 				ehci_polled_t		*ehci_polledp,
807c478bd9Sstevel@tonic-gate 				ehci_qtd_t		*qtd);
819b58c2adSzhigang lu - Sun Microsystems - Beijing China static void	ehci_polled_insert_bulk_qtd(
829b58c2adSzhigang lu - Sun Microsystems - Beijing China 				ehci_polled_t		*ehci_polledp);
837c478bd9Sstevel@tonic-gate static void	ehci_polled_fill_in_qtd(
847c478bd9Sstevel@tonic-gate 				ehci_state_t		*ehcip,
857c478bd9Sstevel@tonic-gate 				ehci_qtd_t		*qtd,
867c478bd9Sstevel@tonic-gate 				uint_t			qtd_ctrl,
873304303fSsl 				size_t			qtd_dma_offs,
887c478bd9Sstevel@tonic-gate 				size_t			qtd_length,
897c478bd9Sstevel@tonic-gate 				ehci_trans_wrapper_t	*tw);
907c478bd9Sstevel@tonic-gate static void	ehci_polled_insert_qtd_on_tw(
917c478bd9Sstevel@tonic-gate 				ehci_state_t		*ehcip,
927c478bd9Sstevel@tonic-gate 				ehci_trans_wrapper_t	*tw,
937c478bd9Sstevel@tonic-gate 				ehci_qtd_t		*qtd);
947c478bd9Sstevel@tonic-gate static ehci_qtd_t *ehci_polled_create_done_qtd_list(
957c478bd9Sstevel@tonic-gate 				ehci_polled_t		*ehci_polledp);
967c478bd9Sstevel@tonic-gate static void	ehci_polled_insert_qtd_into_active_intr_qtd_list(
977c478bd9Sstevel@tonic-gate 				ehci_polled_t		*ehci_polledp,
987c478bd9Sstevel@tonic-gate 				ehci_qtd_t		*curr_qtd);
997c478bd9Sstevel@tonic-gate static void	ehci_polled_remove_qtd_from_active_intr_qtd_list(
1007c478bd9Sstevel@tonic-gate 				ehci_polled_t		*ehci_polledp,
1017c478bd9Sstevel@tonic-gate 				ehci_qtd_t		*curr_qtd);
1027c478bd9Sstevel@tonic-gate static void	ehci_polled_traverse_qtds(
1037c478bd9Sstevel@tonic-gate 				ehci_polled_t		*ehci_polledp,
1047c478bd9Sstevel@tonic-gate 				usba_pipe_handle_data_t	*ph);
1057c478bd9Sstevel@tonic-gate static void	ehci_polled_finish_interrupt(
1067c478bd9Sstevel@tonic-gate 				ehci_state_t		*ehcip,
1077c478bd9Sstevel@tonic-gate 				uint_t			intr);
1089b58c2adSzhigang lu - Sun Microsystems - Beijing China static int	ehci_polled_create_tw(
1099b58c2adSzhigang lu - Sun Microsystems - Beijing China 				ehci_polled_t		*ehci_polledp,
1109b58c2adSzhigang lu - Sun Microsystems - Beijing China 				usba_pipe_handle_data_t	*ph,
1119b58c2adSzhigang lu - Sun Microsystems - Beijing China 				usb_flags_t		usb_flags);
1129b58c2adSzhigang lu - Sun Microsystems - Beijing China static void	ehci_polled_insert_async_qh(
1139b58c2adSzhigang lu - Sun Microsystems - Beijing China 				ehci_state_t		*ehcip,
1149b58c2adSzhigang lu - Sun Microsystems - Beijing China 				ehci_pipe_private_t	*pp);
1159b58c2adSzhigang lu - Sun Microsystems - Beijing China static void	ehci_polled_remove_async_qh(
1169b58c2adSzhigang lu - Sun Microsystems - Beijing China 				ehci_state_t		*ehcip,
1179b58c2adSzhigang lu - Sun Microsystems - Beijing China 				ehci_pipe_private_t	*pp);
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate  * POLLED entry points
1217c478bd9Sstevel@tonic-gate  *
1227c478bd9Sstevel@tonic-gate  * These functions are entry points into the POLLED code.
1237c478bd9Sstevel@tonic-gate  */
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate  * ehci_hcdi_polled_input_init:
1277c478bd9Sstevel@tonic-gate  *
1289b58c2adSzhigang lu - Sun Microsystems - Beijing China  * This is the initialization routine for handling the USB input device
1297c478bd9Sstevel@tonic-gate  * in POLLED mode.  This routine is not called from POLLED mode, so
1307c478bd9Sstevel@tonic-gate  * it is OK to acquire mutexes.
1317c478bd9Sstevel@tonic-gate  */
1327c478bd9Sstevel@tonic-gate int
ehci_hcdi_polled_input_init(usba_pipe_handle_data_t * ph,uchar_t ** polled_buf,usb_console_info_impl_t * console_input_info)1337c478bd9Sstevel@tonic-gate ehci_hcdi_polled_input_init(
1347c478bd9Sstevel@tonic-gate 	usba_pipe_handle_data_t	*ph,
1357c478bd9Sstevel@tonic-gate 	uchar_t			**polled_buf,
1367c478bd9Sstevel@tonic-gate 	usb_console_info_impl_t	*console_input_info)
1377c478bd9Sstevel@tonic-gate {
1387c478bd9Sstevel@tonic-gate 	ehci_polled_t		*ehci_polledp;
1397c478bd9Sstevel@tonic-gate 	ehci_state_t		*ehcip;
1407c478bd9Sstevel@tonic-gate 	int			ret;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	ehcip = ehci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	/*
1457c478bd9Sstevel@tonic-gate 	 * Grab the ehci_int_mutex so that things don't change on us
1467c478bd9Sstevel@tonic-gate 	 * if an interrupt comes in.
1477c478bd9Sstevel@tonic-gate 	 */
1487c478bd9Sstevel@tonic-gate 	mutex_enter(&ehcip->ehci_int_mutex);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	ret = ehci_polled_init(ph, ehcip, console_input_info);
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	if (ret != USB_SUCCESS) {
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 		/* Allow interrupts to continue */
1557c478bd9Sstevel@tonic-gate 		mutex_exit(&ehcip->ehci_int_mutex);
1567c478bd9Sstevel@tonic-gate 		return (ret);
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	ehci_polledp = (ehci_polled_t *)console_input_info->uci_private;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	/*
1627c478bd9Sstevel@tonic-gate 	 * Mark the structure so that if we are using it, we don't free
1637c478bd9Sstevel@tonic-gate 	 * the structures if one of them is unplugged.
1647c478bd9Sstevel@tonic-gate 	 */
1657c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_flags |= POLLED_INPUT_MODE;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	/* increase the counter for keyboard connected */
1687c478bd9Sstevel@tonic-gate 	ehcip->ehci_polled_kbd_count ++;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	/*
1717c478bd9Sstevel@tonic-gate 	 * This is the buffer we will copy characters into. It will be
1727c478bd9Sstevel@tonic-gate 	 * copied into at this layer, so we need to keep track of it.
1737c478bd9Sstevel@tonic-gate 	 */
1747c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_buf =
1757c478bd9Sstevel@tonic-gate 	    (uchar_t *)kmem_zalloc(POLLED_RAW_BUF_SIZE, KM_SLEEP);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	*polled_buf = ehci_polledp->ehci_polled_buf;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	/*
1807c478bd9Sstevel@tonic-gate 	 * This is a software workaround to fix schizo hardware bug.
1817c478bd9Sstevel@tonic-gate 	 * Existence of "no-prom-cdma-sync"  property means consistent
1827c478bd9Sstevel@tonic-gate 	 * dma sync should not be done while in prom or polled mode.
1837c478bd9Sstevel@tonic-gate 	 */
1847c478bd9Sstevel@tonic-gate 	if (ddi_prop_exists(DDI_DEV_T_ANY, ehcip->ehci_dip,
1857c478bd9Sstevel@tonic-gate 	    DDI_PROP_NOTPROM, "no-prom-cdma-sync")) {
1867c478bd9Sstevel@tonic-gate 		ehci_polledp->ehci_polled_no_sync_flag = B_TRUE;
1877c478bd9Sstevel@tonic-gate 	}
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	/* Allow interrupts to continue */
1907c478bd9Sstevel@tonic-gate 	mutex_exit(&ehcip->ehci_int_mutex);
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	return (USB_SUCCESS);
1937c478bd9Sstevel@tonic-gate }
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate /*
1977c478bd9Sstevel@tonic-gate  * ehci_hcdi_polled_input_fini:
1987c478bd9Sstevel@tonic-gate  */
1997c478bd9Sstevel@tonic-gate int
ehci_hcdi_polled_input_fini(usb_console_info_impl_t * info)2007c478bd9Sstevel@tonic-gate ehci_hcdi_polled_input_fini(usb_console_info_impl_t *info)
2017c478bd9Sstevel@tonic-gate {
2027c478bd9Sstevel@tonic-gate 	ehci_polled_t		*ehci_polledp;
2037c478bd9Sstevel@tonic-gate 	ehci_state_t		*ehcip;
2047c478bd9Sstevel@tonic-gate 	int			ret;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	ehci_polledp = (ehci_polled_t *)info->uci_private;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	ehcip = ehci_polledp->ehci_polled_ehcip;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	mutex_enter(&ehcip->ehci_int_mutex);
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	/*
2137c478bd9Sstevel@tonic-gate 	 * Reset the POLLED_INPUT_MODE flag so that we can tell if
2147c478bd9Sstevel@tonic-gate 	 * this structure is in use in the ehci_polled_fini routine.
2157c478bd9Sstevel@tonic-gate 	 */
2167c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_flags &= ~POLLED_INPUT_MODE;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	/* decrease the counter for keyboard disconnected */
2197c478bd9Sstevel@tonic-gate 	ehcip->ehci_polled_kbd_count --;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	/* Free the buffer that we copied data into */
2227c478bd9Sstevel@tonic-gate 	kmem_free(ehci_polledp->ehci_polled_buf, POLLED_RAW_BUF_SIZE);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	ret = ehci_polled_fini(ehci_polledp);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	mutex_exit(&ehcip->ehci_int_mutex);
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	return (ret);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate /*
2337c478bd9Sstevel@tonic-gate  * ehci_hcdi_polled_input_enter:
2347c478bd9Sstevel@tonic-gate  *
2357c478bd9Sstevel@tonic-gate  * This is where we enter into POLLED mode.  This routine sets up
2367c478bd9Sstevel@tonic-gate  * everything so that calls to	ehci_hcdi_polled_read will return
2377c478bd9Sstevel@tonic-gate  * characters.
2387c478bd9Sstevel@tonic-gate  */
2397c478bd9Sstevel@tonic-gate int
ehci_hcdi_polled_input_enter(usb_console_info_impl_t * info)2407c478bd9Sstevel@tonic-gate ehci_hcdi_polled_input_enter(usb_console_info_impl_t *info)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate 	ehci_polled_t		*ehci_polledp;
2439b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_state_t		*ehcip;
2449b58c2adSzhigang lu - Sun Microsystems - Beijing China 	usba_pipe_handle_data_t	*ph;
2459b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_pipe_private_t	*pp;
2469b58c2adSzhigang lu - Sun Microsystems - Beijing China 	int			pipe_attr;
2477c478bd9Sstevel@tonic-gate 
2489b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
2499b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(NO_COMPETING_THREADS_NOW);
2509b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
2517c478bd9Sstevel@tonic-gate 	ehci_polledp = (ehci_polled_t *)info->uci_private;
2529b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehcip = ehci_polledp->ehci_polled_ehcip;
2539b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ph = ehci_polledp->ehci_polled_input_pipe_handle;
2549b58c2adSzhigang lu - Sun Microsystems - Beijing China 	pp = (ehci_pipe_private_t *)ph->p_hcd_private;
2557c478bd9Sstevel@tonic-gate 
2569b58c2adSzhigang lu - Sun Microsystems - Beijing China 	pipe_attr = ph->p_ep.bmAttributes & USB_EP_ATTR_MASK;
2579b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
2589b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(COMPETING_THREADS_NOW);
2599b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
2607c478bd9Sstevel@tonic-gate 
2619b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polledp->ehci_polled_entry++;
2627c478bd9Sstevel@tonic-gate 	/*
2637c478bd9Sstevel@tonic-gate 	 * If the controller is already switched over, just return
2647c478bd9Sstevel@tonic-gate 	 */
2657c478bd9Sstevel@tonic-gate 	if (ehci_polledp->ehci_polled_entry > 1) {
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		return (USB_SUCCESS);
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 
2709b58c2adSzhigang lu - Sun Microsystems - Beijing China 	switch (pipe_attr) {
2719b58c2adSzhigang lu - Sun Microsystems - Beijing China 	case USB_EP_ATTR_INTR:
2729b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_polled_save_state(ehci_polledp);
2739b58c2adSzhigang lu - Sun Microsystems - Beijing China 		break;
2749b58c2adSzhigang lu - Sun Microsystems - Beijing China 	case USB_EP_ATTR_BULK:
2759b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
2769b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(NO_COMPETING_THREADS_NOW);
2779b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
2789b58c2adSzhigang lu - Sun Microsystems - Beijing China 		Set_OpReg(ehci_command, (Get_OpReg(ehci_command) &
2799b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    ~(EHCI_CMD_PERIODIC_SCHED_ENABLE |
2809b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    EHCI_CMD_ASYNC_SCHED_ENABLE)));
2819b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/* Wait for few milliseconds */
2829b58c2adSzhigang lu - Sun Microsystems - Beijing China 		drv_usecwait(EHCI_POLLED_TIMEWAIT);
2839b58c2adSzhigang lu - Sun Microsystems - Beijing China 
2849b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_polled_insert_async_qh(ehcip, pp);
2859b58c2adSzhigang lu - Sun Microsystems - Beijing China 
2869b58c2adSzhigang lu - Sun Microsystems - Beijing China 		Set_OpReg(ehci_command,
2879b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    (Get_OpReg(ehci_command) | EHCI_CMD_ASYNC_SCHED_ENABLE));
2889b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
2899b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(COMPETING_THREADS_NOW);
2909b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
2919b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/* Wait for few milliseconds */
2929b58c2adSzhigang lu - Sun Microsystems - Beijing China 		drv_usecwait(EHCI_POLLED_TIMEWAIT);
2939b58c2adSzhigang lu - Sun Microsystems - Beijing China 		break;
2949b58c2adSzhigang lu - Sun Microsystems - Beijing China 	default:
2959b58c2adSzhigang lu - Sun Microsystems - Beijing China 		return (USB_FAILURE);
2969b58c2adSzhigang lu - Sun Microsystems - Beijing China 	}
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_flags |= POLLED_INPUT_MODE_INUSE;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	return (USB_SUCCESS);
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate /*
3057c478bd9Sstevel@tonic-gate  * ehci_hcdi_polled_input_exit:
3067c478bd9Sstevel@tonic-gate  *
3077c478bd9Sstevel@tonic-gate  * This is where we exit POLLED mode. This routine restores
3087c478bd9Sstevel@tonic-gate  * everything that is needed to continue operation.
3097c478bd9Sstevel@tonic-gate  */
3107c478bd9Sstevel@tonic-gate int
ehci_hcdi_polled_input_exit(usb_console_info_impl_t * info)3117c478bd9Sstevel@tonic-gate ehci_hcdi_polled_input_exit(usb_console_info_impl_t *info)
3127c478bd9Sstevel@tonic-gate {
3137c478bd9Sstevel@tonic-gate 	ehci_polled_t		*ehci_polledp;
3149b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_state_t		*ehcip;
3159b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_pipe_private_t	*pp;
3169b58c2adSzhigang lu - Sun Microsystems - Beijing China 	int			pipe_attr;
3177c478bd9Sstevel@tonic-gate 
3189b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
3199b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(NO_COMPETING_THREADS_NOW);
3209b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
3217c478bd9Sstevel@tonic-gate 	ehci_polledp = (ehci_polled_t *)info->uci_private;
3229b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehcip = ehci_polledp->ehci_polled_ehcip;
3239b58c2adSzhigang lu - Sun Microsystems - Beijing China 	pp = (ehci_pipe_private_t *)ehci_polledp->
3249b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    ehci_polled_input_pipe_handle->p_hcd_private;
3259b58c2adSzhigang lu - Sun Microsystems - Beijing China 
3269b58c2adSzhigang lu - Sun Microsystems - Beijing China 	pipe_attr = ehci_polledp->ehci_polled_input_pipe_handle->
3279b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    p_ep.bmAttributes & USB_EP_ATTR_MASK;
3289b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
3299b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(COMPETING_THREADS_NOW);
3309b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_entry--;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	/*
3357c478bd9Sstevel@tonic-gate 	 * If there are still outstanding "enters", just return
3367c478bd9Sstevel@tonic-gate 	 */
3377c478bd9Sstevel@tonic-gate 	if (ehci_polledp->ehci_polled_entry > 0) {
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 		return (USB_SUCCESS);
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_flags &= ~POLLED_INPUT_MODE_INUSE;
3437c478bd9Sstevel@tonic-gate 
3449b58c2adSzhigang lu - Sun Microsystems - Beijing China 	switch (pipe_attr & USB_EP_ATTR_MASK) {
3459b58c2adSzhigang lu - Sun Microsystems - Beijing China 	case USB_EP_ATTR_INTR:
3469b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_polled_restore_state(ehci_polledp);
3479b58c2adSzhigang lu - Sun Microsystems - Beijing China 		break;
3489b58c2adSzhigang lu - Sun Microsystems - Beijing China 	case USB_EP_ATTR_BULK:
3499b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
3509b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(NO_COMPETING_THREADS_NOW);
3519b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
3529b58c2adSzhigang lu - Sun Microsystems - Beijing China 		Set_OpReg(ehci_command, (Get_OpReg(ehci_command) &
3539b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    ~(EHCI_CMD_PERIODIC_SCHED_ENABLE |
3549b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    EHCI_CMD_ASYNC_SCHED_ENABLE)));
3559b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/* Wait for few milliseconds */
3569b58c2adSzhigang lu - Sun Microsystems - Beijing China 		drv_usecwait(EHCI_POLLED_TIMEWAIT);
3579b58c2adSzhigang lu - Sun Microsystems - Beijing China 
3589b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_polled_remove_async_qh(ehcip, pp);
3599b58c2adSzhigang lu - Sun Microsystems - Beijing China 
3609b58c2adSzhigang lu - Sun Microsystems - Beijing China 		Set_OpReg(ehci_command,
3619b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    (Get_OpReg(ehci_command) | EHCI_CMD_ASYNC_SCHED_ENABLE |
3629b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    EHCI_CMD_ASYNC_SCHED_ENABLE));
3639b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
3649b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(COMPETING_THREADS_NOW);
3659b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
3669b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/* Wait for few milliseconds */
3679b58c2adSzhigang lu - Sun Microsystems - Beijing China 		drv_usecwait(EHCI_POLLED_TIMEWAIT);
3689b58c2adSzhigang lu - Sun Microsystems - Beijing China 		break;
3699b58c2adSzhigang lu - Sun Microsystems - Beijing China 	default:
3709b58c2adSzhigang lu - Sun Microsystems - Beijing China 		return (USB_FAILURE);
3719b58c2adSzhigang lu - Sun Microsystems - Beijing China 
3729b58c2adSzhigang lu - Sun Microsystems - Beijing China 	}
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	return (USB_SUCCESS);
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate /*
3797c478bd9Sstevel@tonic-gate  * ehci_hcdi_polled_read:
3807c478bd9Sstevel@tonic-gate  *
3817c478bd9Sstevel@tonic-gate  * Get a key character
3827c478bd9Sstevel@tonic-gate  */
3837c478bd9Sstevel@tonic-gate int
ehci_hcdi_polled_read(usb_console_info_impl_t * info,uint_t * num_characters)3847c478bd9Sstevel@tonic-gate ehci_hcdi_polled_read(
3857c478bd9Sstevel@tonic-gate 	usb_console_info_impl_t	*info,
3867c478bd9Sstevel@tonic-gate 	uint_t			*num_characters)
3877c478bd9Sstevel@tonic-gate {
3887c478bd9Sstevel@tonic-gate 	ehci_state_t		*ehcip;
3897c478bd9Sstevel@tonic-gate 	ehci_polled_t		*ehci_polledp;
3907c478bd9Sstevel@tonic-gate 	uint_t			intr;
3919b58c2adSzhigang lu - Sun Microsystems - Beijing China 	int			pipe_attr;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	ehci_polledp = (ehci_polled_t *)info->uci_private;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	ehcip = ehci_polledp->ehci_polled_ehcip;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate #ifndef lint
3987c478bd9Sstevel@tonic-gate 	_NOTE(NO_COMPETING_THREADS_NOW);
3997c478bd9Sstevel@tonic-gate #endif
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	*num_characters = 0;
4027c478bd9Sstevel@tonic-gate 
4039b58c2adSzhigang lu - Sun Microsystems - Beijing China 	pipe_attr = ehci_polledp->ehci_polled_input_pipe_handle->
4049b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    p_ep.bmAttributes & USB_EP_ATTR_MASK;
4059b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4069b58c2adSzhigang lu - Sun Microsystems - Beijing China 	if (pipe_attr == USB_EP_ATTR_BULK) {
4079b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_polled_insert_bulk_qtd(ehci_polledp);
4089b58c2adSzhigang lu - Sun Microsystems - Beijing China 	}
4099b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4107c478bd9Sstevel@tonic-gate 	intr = ((Get_OpReg(ehci_status) & Get_OpReg(ehci_interrupt)) &
4117c478bd9Sstevel@tonic-gate 	    (EHCI_INTR_FRAME_LIST_ROLLOVER |
4127c478bd9Sstevel@tonic-gate 	    EHCI_INTR_USB | EHCI_INTR_USB_ERROR));
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	/*
4157c478bd9Sstevel@tonic-gate 	 * Check whether any frame list rollover interrupt is pending
4167c478bd9Sstevel@tonic-gate 	 * and if it is pending, process this interrupt.
4177c478bd9Sstevel@tonic-gate 	 */
4187c478bd9Sstevel@tonic-gate 	if (intr & EHCI_INTR_FRAME_LIST_ROLLOVER) {
4197c478bd9Sstevel@tonic-gate 		/* Check any frame list rollover interrupt is pending */
4207c478bd9Sstevel@tonic-gate 		ehci_handle_frame_list_rollover(ehcip);
4217c478bd9Sstevel@tonic-gate 		ehci_polled_finish_interrupt(ehcip,
4227c478bd9Sstevel@tonic-gate 		    EHCI_INTR_FRAME_LIST_ROLLOVER);
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate 
4259b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/* Process any QTD's on the active interrupt qtd list */
4269b58c2adSzhigang lu - Sun Microsystems - Beijing China 	*num_characters =
4279b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    ehci_polled_process_active_intr_qtd_list(ehci_polledp);
4289b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4299b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
4309b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(COMPETING_THREADS_NOW);
4319b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
4329b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4339b58c2adSzhigang lu - Sun Microsystems - Beijing China 	return (USB_SUCCESS);
4349b58c2adSzhigang lu - Sun Microsystems - Beijing China }
4359b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4369b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4379b58c2adSzhigang lu - Sun Microsystems - Beijing China /*
4389b58c2adSzhigang lu - Sun Microsystems - Beijing China  * ehci_hcdi_polled_output_init:
4399b58c2adSzhigang lu - Sun Microsystems - Beijing China  *
4409b58c2adSzhigang lu - Sun Microsystems - Beijing China  * This is the initialization routine for handling the USB serial output
4419b58c2adSzhigang lu - Sun Microsystems - Beijing China  * in POLLED mode.  This routine is not called from POLLED mode, so
4429b58c2adSzhigang lu - Sun Microsystems - Beijing China  * it is OK to acquire mutexes.
4439b58c2adSzhigang lu - Sun Microsystems - Beijing China  */
4449b58c2adSzhigang lu - Sun Microsystems - Beijing China int
ehci_hcdi_polled_output_init(usba_pipe_handle_data_t * ph,usb_console_info_impl_t * console_output_info)4459b58c2adSzhigang lu - Sun Microsystems - Beijing China ehci_hcdi_polled_output_init(
4469b58c2adSzhigang lu - Sun Microsystems - Beijing China 	usba_pipe_handle_data_t	*ph,
4479b58c2adSzhigang lu - Sun Microsystems - Beijing China 	usb_console_info_impl_t	*console_output_info)
4489b58c2adSzhigang lu - Sun Microsystems - Beijing China {
4499b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polled_t		*ehci_polledp;
4509b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_state_t		*ehcip;
4519b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_pipe_private_t	*pp;
4529b58c2adSzhigang lu - Sun Microsystems - Beijing China 	int			ret;
4539b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4549b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehcip = ehci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
4559b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4569b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/*
4579b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * Grab the ehci_int_mutex so that things don't change on us
4589b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * if an interrupt comes in.
4599b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 */
4609b58c2adSzhigang lu - Sun Microsystems - Beijing China 	mutex_enter(&ehcip->ehci_int_mutex);
4619b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4629b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ret = ehci_polled_init(ph, ehcip, console_output_info);
4639b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4649b58c2adSzhigang lu - Sun Microsystems - Beijing China 	if (ret != USB_SUCCESS) {
4659b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4669b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/* Allow interrupts to continue */
4679b58c2adSzhigang lu - Sun Microsystems - Beijing China 		mutex_exit(&ehcip->ehci_int_mutex);
4689b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4699b58c2adSzhigang lu - Sun Microsystems - Beijing China 		return (ret);
4709b58c2adSzhigang lu - Sun Microsystems - Beijing China 	}
4719b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4729b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polledp = (ehci_polled_t *)console_output_info->uci_private;
4739b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/*
4749b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * Mark the structure so that if we are using it, we don't free
4759b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * the structures if one of them is unplugged.
4769b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 */
4779b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polledp->ehci_polled_flags |= POLLED_OUTPUT_MODE;
4789b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4799b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/*
4809b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * Insert the Endpoint Descriptor to appropriate endpoint list.
4819b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 */
4829b58c2adSzhigang lu - Sun Microsystems - Beijing China 	pp = (ehci_pipe_private_t *)ehci_polledp->
4839b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    ehci_polled_input_pipe_handle->p_hcd_private;
4849b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polled_insert_async_qh(ehcip, pp);
4859b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4869b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/*
4879b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * This is a software workaround to fix schizo hardware bug.
4889b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * Existence of "no-prom-cdma-sync"  property means consistent
4899b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * dma sync should not be done while in prom or polled mode.
4909b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 */
4919b58c2adSzhigang lu - Sun Microsystems - Beijing China 	if (ddi_prop_exists(DDI_DEV_T_ANY, ehcip->ehci_dip,
4929b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    DDI_PROP_NOTPROM, "no-prom-cdma-sync")) {
4939b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_polledp->ehci_polled_no_sync_flag = B_TRUE;
4949b58c2adSzhigang lu - Sun Microsystems - Beijing China 	}
4959b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4969b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/* Allow interrupts to continue */
4979b58c2adSzhigang lu - Sun Microsystems - Beijing China 	mutex_exit(&ehcip->ehci_int_mutex);
4989b58c2adSzhigang lu - Sun Microsystems - Beijing China 
4999b58c2adSzhigang lu - Sun Microsystems - Beijing China 	return (USB_SUCCESS);
5009b58c2adSzhigang lu - Sun Microsystems - Beijing China }
5019b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5029b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5039b58c2adSzhigang lu - Sun Microsystems - Beijing China /*
5049b58c2adSzhigang lu - Sun Microsystems - Beijing China  * ehci_hcdi_polled_output_fini:
5059b58c2adSzhigang lu - Sun Microsystems - Beijing China  */
5069b58c2adSzhigang lu - Sun Microsystems - Beijing China int
ehci_hcdi_polled_output_fini(usb_console_info_impl_t * info)5079b58c2adSzhigang lu - Sun Microsystems - Beijing China ehci_hcdi_polled_output_fini(usb_console_info_impl_t *info)
5089b58c2adSzhigang lu - Sun Microsystems - Beijing China {
5099b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polled_t		*ehci_polledp;
5109b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_state_t		*ehcip;
5119b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_pipe_private_t	*pp;
5129b58c2adSzhigang lu - Sun Microsystems - Beijing China 	int			ret;
5139b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5149b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polledp = (ehci_polled_t *)info->uci_private;
5159b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5169b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehcip = ehci_polledp->ehci_polled_ehcip;
5179b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5189b58c2adSzhigang lu - Sun Microsystems - Beijing China 	mutex_enter(&ehcip->ehci_int_mutex);
5199b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5209b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/* Remove the Endpoint Descriptor. */
5219b58c2adSzhigang lu - Sun Microsystems - Beijing China 	pp = (ehci_pipe_private_t *)ehci_polledp->
5229b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    ehci_polled_input_pipe_handle->p_hcd_private;
5239b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polled_remove_async_qh(ehcip, pp);
5249b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5259b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/*
5269b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * Reset the POLLED_INPUT_MODE flag so that we can tell if
5279b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * this structure is in use in the ehci_polled_fini routine.
5289b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 */
5299b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polledp->ehci_polled_flags &= ~POLLED_OUTPUT_MODE;
5309b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5319b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ret = ehci_polled_fini(ehci_polledp);
5329b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5339b58c2adSzhigang lu - Sun Microsystems - Beijing China 	info->uci_private = NULL;
5349b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5359b58c2adSzhigang lu - Sun Microsystems - Beijing China 	mutex_exit(&ehcip->ehci_int_mutex);
5369b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5379b58c2adSzhigang lu - Sun Microsystems - Beijing China 	return (ret);
5389b58c2adSzhigang lu - Sun Microsystems - Beijing China }
5399b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5409b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5419b58c2adSzhigang lu - Sun Microsystems - Beijing China /*
5429b58c2adSzhigang lu - Sun Microsystems - Beijing China  * ehci_hcdi_polled_output_enter:
5439b58c2adSzhigang lu - Sun Microsystems - Beijing China  *
5449b58c2adSzhigang lu - Sun Microsystems - Beijing China  * everything is done in input enter
5459b58c2adSzhigang lu - Sun Microsystems - Beijing China  */
5469b58c2adSzhigang lu - Sun Microsystems - Beijing China /*ARGSUSED*/
5479b58c2adSzhigang lu - Sun Microsystems - Beijing China int
ehci_hcdi_polled_output_enter(usb_console_info_impl_t * info)5489b58c2adSzhigang lu - Sun Microsystems - Beijing China ehci_hcdi_polled_output_enter(usb_console_info_impl_t *info)
5499b58c2adSzhigang lu - Sun Microsystems - Beijing China {
5509b58c2adSzhigang lu - Sun Microsystems - Beijing China 	return (USB_SUCCESS);
5519b58c2adSzhigang lu - Sun Microsystems - Beijing China }
5529b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5539b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5549b58c2adSzhigang lu - Sun Microsystems - Beijing China /*
5559b58c2adSzhigang lu - Sun Microsystems - Beijing China  * ehci_hcdi_polled_output_exit:
5569b58c2adSzhigang lu - Sun Microsystems - Beijing China  *
5579b58c2adSzhigang lu - Sun Microsystems - Beijing China  * everything is done in input exit
5589b58c2adSzhigang lu - Sun Microsystems - Beijing China  */
5599b58c2adSzhigang lu - Sun Microsystems - Beijing China /*ARGSUSED*/
5609b58c2adSzhigang lu - Sun Microsystems - Beijing China int
ehci_hcdi_polled_output_exit(usb_console_info_impl_t * info)5619b58c2adSzhigang lu - Sun Microsystems - Beijing China ehci_hcdi_polled_output_exit(usb_console_info_impl_t *info)
5629b58c2adSzhigang lu - Sun Microsystems - Beijing China {
5639b58c2adSzhigang lu - Sun Microsystems - Beijing China 	return (USB_SUCCESS);
5649b58c2adSzhigang lu - Sun Microsystems - Beijing China }
5659b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5669b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5679b58c2adSzhigang lu - Sun Microsystems - Beijing China /*
5689b58c2adSzhigang lu - Sun Microsystems - Beijing China  * ehci_hcdi_polled_write:
5699b58c2adSzhigang lu - Sun Microsystems - Beijing China  *	Put a key character.
5709b58c2adSzhigang lu - Sun Microsystems - Beijing China  */
5719b58c2adSzhigang lu - Sun Microsystems - Beijing China int
ehci_hcdi_polled_write(usb_console_info_impl_t * info,uchar_t * buf,uint_t num_characters,uint_t * num_characters_written)5729b58c2adSzhigang lu - Sun Microsystems - Beijing China ehci_hcdi_polled_write(usb_console_info_impl_t *info, uchar_t *buf,
5739b58c2adSzhigang lu - Sun Microsystems - Beijing China     uint_t num_characters, uint_t *num_characters_written)
5749b58c2adSzhigang lu - Sun Microsystems - Beijing China {
5759b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_state_t		*ehcip;
5769b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polled_t		*ehci_polledp;
5779b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_trans_wrapper_t	*tw;
5789b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_pipe_private_t	*pp;
5799b58c2adSzhigang lu - Sun Microsystems - Beijing China 	usba_pipe_handle_data_t	*ph;
5809b58c2adSzhigang lu - Sun Microsystems - Beijing China 	int			intr;
5819b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5829b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef lint
5839b58c2adSzhigang lu - Sun Microsystems - Beijing China 	_NOTE(NO_COMPETING_THREADS_NOW);
5849b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
5859b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polledp = (ehci_polled_t *)info->uci_private;
5869b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehcip = ehci_polledp->ehci_polled_ehcip;
5879b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ph = ehci_polledp->ehci_polled_input_pipe_handle;
5889b58c2adSzhigang lu - Sun Microsystems - Beijing China 	pp = (ehci_pipe_private_t *)ph->p_hcd_private;
5899b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5909b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/* Disable all list processing */
5919b58c2adSzhigang lu - Sun Microsystems - Beijing China 	Set_OpReg(ehci_command, Get_OpReg(ehci_command) &
5929b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    ~(EHCI_CMD_ASYNC_SCHED_ENABLE |
5939b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    EHCI_CMD_PERIODIC_SCHED_ENABLE));
5949b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5959b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/* Wait for few milliseconds */
5969b58c2adSzhigang lu - Sun Microsystems - Beijing China 	drv_usecwait(EHCI_POLLED_TIMEWAIT);
5979b58c2adSzhigang lu - Sun Microsystems - Beijing China 
5989b58c2adSzhigang lu - Sun Microsystems - Beijing China 	tw = pp->pp_tw_head;
5999b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ASSERT(tw != NULL);
6009b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6019b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/* copy transmit buffer */
6029b58c2adSzhigang lu - Sun Microsystems - Beijing China 	if (num_characters > POLLED_RAW_BUF_SIZE) {
6039b58c2adSzhigang lu - Sun Microsystems - Beijing China 		cmn_err(CE_NOTE, "polled write size %d bigger than %d",
6049b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    num_characters, POLLED_RAW_BUF_SIZE);
6059b58c2adSzhigang lu - Sun Microsystems - Beijing China 		num_characters = POLLED_RAW_BUF_SIZE;
6069b58c2adSzhigang lu - Sun Microsystems - Beijing China 	}
6079b58c2adSzhigang lu - Sun Microsystems - Beijing China 	tw->tw_length = num_characters;
6089b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ddi_rep_put8(tw->tw_accesshandle,
6099b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    buf, (uint8_t *)tw->tw_buf,
6109b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    tw->tw_length, DDI_DEV_AUTOINCR);
6119b58c2adSzhigang lu - Sun Microsystems - Beijing China 	Sync_IO_Buffer_for_device(tw->tw_dmahandle, tw->tw_length);
6129b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6139b58c2adSzhigang lu - Sun Microsystems - Beijing China 	ehci_polled_insert_bulk_qtd(ehci_polledp);
6149b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6159b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/* Enable async list processing */
6169b58c2adSzhigang lu - Sun Microsystems - Beijing China 	Set_OpReg(ehci_command, (Get_OpReg(ehci_command) |
6179b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    EHCI_CMD_ASYNC_SCHED_ENABLE));
6189b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6199b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/* Wait for few milliseconds */
6209b58c2adSzhigang lu - Sun Microsystems - Beijing China 	drv_usecwait(EHCI_POLLED_TIMEWAIT);
6219b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6229b58c2adSzhigang lu - Sun Microsystems - Beijing China 	while (!((Get_OpReg(ehci_status)) & (EHCI_INTR_USB
6239b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    |EHCI_INTR_FRAME_LIST_ROLLOVER | EHCI_INTR_USB_ERROR))) {
6249b58c2adSzhigang lu - Sun Microsystems - Beijing China #ifndef __sparc
6259b58c2adSzhigang lu - Sun Microsystems - Beijing China 		invalidate_cache();
6269b58c2adSzhigang lu - Sun Microsystems - Beijing China #else
6279b58c2adSzhigang lu - Sun Microsystems - Beijing China 		;
6289b58c2adSzhigang lu - Sun Microsystems - Beijing China #endif
6299b58c2adSzhigang lu - Sun Microsystems - Beijing China 	}
6309b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6319b58c2adSzhigang lu - Sun Microsystems - Beijing China 	intr = (Get_OpReg(ehci_status)) &
6329b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    (EHCI_INTR_FRAME_LIST_ROLLOVER |
6339b58c2adSzhigang lu - Sun Microsystems - Beijing China 	    EHCI_INTR_USB | EHCI_INTR_USB_ERROR);
6349b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6359b58c2adSzhigang lu - Sun Microsystems - Beijing China 	/*
6369b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * Check whether any frame list rollover interrupt is pending
6379b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * and if it is pending, process this interrupt.
6389b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 */
6399b58c2adSzhigang lu - Sun Microsystems - Beijing China 	if (intr & EHCI_INTR_FRAME_LIST_ROLLOVER) {
6409b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6419b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_handle_frame_list_rollover(ehcip);
6429b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_polled_finish_interrupt(ehcip,
6439b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    EHCI_INTR_FRAME_LIST_ROLLOVER);
6449b58c2adSzhigang lu - Sun Microsystems - Beijing China 	}
6459b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6467c478bd9Sstevel@tonic-gate 	/* Check for any USB transaction completion notification */
6477c478bd9Sstevel@tonic-gate 	if (intr & (EHCI_INTR_USB | EHCI_INTR_USB_ERROR)) {
6489b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6499b58c2adSzhigang lu - Sun Microsystems - Beijing China 		(void) ehci_polled_process_active_intr_qtd_list(ehci_polledp);
6509b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6519b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/* Acknowledge the USB and USB error interrupt */
6529b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_polled_finish_interrupt(ehcip,
6539b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    intr & (EHCI_INTR_USB | EHCI_INTR_USB_ERROR));
6549b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 
6579b58c2adSzhigang lu - Sun Microsystems - Beijing China 	*num_characters_written = num_characters;
6589b58c2adSzhigang lu - Sun Microsystems - Beijing China 
6597c478bd9Sstevel@tonic-gate #ifndef lint
6607c478bd9Sstevel@tonic-gate 	_NOTE(COMPETING_THREADS_NOW);
6617c478bd9Sstevel@tonic-gate #endif
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	return (USB_SUCCESS);
6647c478bd9Sstevel@tonic-gate }
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate /*
6687c478bd9Sstevel@tonic-gate  * Internal Functions
6697c478bd9Sstevel@tonic-gate  */
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate /*
6727c478bd9Sstevel@tonic-gate  * Polled initialization routines
6737c478bd9Sstevel@tonic-gate  */
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate /*
6777c478bd9Sstevel@tonic-gate  * ehci_polled_init:
6787c478bd9Sstevel@tonic-gate  *
6797c478bd9Sstevel@tonic-gate  * Initialize generic information Uthat is needed to provide USB/POLLED
6807c478bd9Sstevel@tonic-gate  * support.
6817c478bd9Sstevel@tonic-gate  */
6827c478bd9Sstevel@tonic-gate static int
ehci_polled_init(usba_pipe_handle_data_t * ph,ehci_state_t * ehcip,usb_console_info_impl_t * console_info)6837c478bd9Sstevel@tonic-gate ehci_polled_init(
6847c478bd9Sstevel@tonic-gate 	usba_pipe_handle_data_t	*ph,
6857c478bd9Sstevel@tonic-gate 	ehci_state_t		*ehcip,
6867c478bd9Sstevel@tonic-gate 	usb_console_info_impl_t	*console_info)
6877c478bd9Sstevel@tonic-gate {
6887c478bd9Sstevel@tonic-gate 	ehci_polled_t		*ehci_polledp;
6897c478bd9Sstevel@tonic-gate 	ehci_pipe_private_t	*pp;
6907c478bd9Sstevel@tonic-gate 	ehci_qtd_t		*qtd;
6919b58c2adSzhigang lu - Sun Microsystems - Beijing China 	int			pipe_attr;
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
6947c478bd9Sstevel@tonic-gate 
6957c478bd9Sstevel@tonic-gate 	/*
6967c478bd9Sstevel@tonic-gate 	 * We have already initialized this structure. If the structure
6977c478bd9Sstevel@tonic-gate 	 * has already been initialized, then we don't need to redo it.
6987c478bd9Sstevel@tonic-gate 	 */
6997c478bd9Sstevel@tonic-gate 	if (console_info->uci_private) {
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 		return (USB_SUCCESS);
7027c478bd9Sstevel@tonic-gate 	}
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	/* Allocate and intitialize a state structure */
7057c478bd9Sstevel@tonic-gate 	ehci_polledp = (ehci_polled_t *)
7067c478bd9Sstevel@tonic-gate 	    kmem_zalloc(sizeof (ehci_polled_t), KM_SLEEP);
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	console_info->uci_private = (usb_console_info_private_t)ehci_polledp;
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 	/*
7117c478bd9Sstevel@tonic-gate 	 * Store away the ehcip so that we can get to it when we are in
7127c478bd9Sstevel@tonic-gate 	 * POLLED mode. We don't want to have to call ehci_obtain_state
7137c478bd9Sstevel@tonic-gate 	 * every time we want to access this structure.
7147c478bd9Sstevel@tonic-gate 	 */
7157c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_ehcip = ehcip;
7167c478bd9Sstevel@tonic-gate 	/*
7177c478bd9Sstevel@tonic-gate 	 * Save usb device and endpoint number information from the usb
7187c478bd9Sstevel@tonic-gate 	 * pipe handle.
7197c478bd9Sstevel@tonic-gate 	 */
7207c478bd9Sstevel@tonic-gate 	mutex_enter(&ph->p_mutex);
7217c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_usb_dev = ph->p_usba_device;
7227c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_ep_addr = ph->p_ep.bEndpointAddress;
7237c478bd9Sstevel@tonic-gate 	mutex_exit(&ph->p_mutex);
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	/*
7267c478bd9Sstevel@tonic-gate 	 * Allocate memory to make duplicate of original usb pipe handle.
7277c478bd9Sstevel@tonic-gate 	 */
7287c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_input_pipe_handle =
7297c478bd9Sstevel@tonic-gate 	    kmem_zalloc(sizeof (usba_pipe_handle_data_t), KM_SLEEP);
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	/*
7327c478bd9Sstevel@tonic-gate 	 * Copy the USB handle into the new pipe handle. Also
7337c478bd9Sstevel@tonic-gate 	 * create new lock for the new pipe handle.
7347c478bd9Sstevel@tonic-gate 	 */
7357c478bd9Sstevel@tonic-gate 	bcopy((void *)ph,
7367c478bd9Sstevel@tonic-gate 	    (void *)ehci_polledp->ehci_polled_input_pipe_handle,
7377c478bd9Sstevel@tonic-gate 	    sizeof (usba_pipe_handle_data_t));
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 	/*
7407c478bd9Sstevel@tonic-gate 	 * uint64_t typecast to make sure amd64 can compile
7417c478bd9Sstevel@tonic-gate 	 */
7427c478bd9Sstevel@tonic-gate 	mutex_init(&ehci_polledp->ehci_polled_input_pipe_handle->p_mutex,
743a195726fSgovinda 	    NULL, MUTEX_DRIVER, DDI_INTR_PRI(ehcip->ehci_intr_pri));
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 	/*
7467c478bd9Sstevel@tonic-gate 	 * Create a new ehci pipe private structure
7477c478bd9Sstevel@tonic-gate 	 */
7487c478bd9Sstevel@tonic-gate 	pp = (ehci_pipe_private_t *)
7497c478bd9Sstevel@tonic-gate 	    kmem_zalloc(sizeof (ehci_pipe_private_t), KM_SLEEP);
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	/*
7527c478bd9Sstevel@tonic-gate 	 * Store the pointer in the pipe handle. This structure was also
7537c478bd9Sstevel@tonic-gate 	 * just allocated.
7547c478bd9Sstevel@tonic-gate 	 */
7557c478bd9Sstevel@tonic-gate 	mutex_enter(&ehci_polledp->ehci_polled_input_pipe_handle->p_mutex);
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_input_pipe_handle->
7587c478bd9Sstevel@tonic-gate 	    p_hcd_private = (usb_opaque_t)pp;
7597c478bd9Sstevel@tonic-gate 
7607c478bd9Sstevel@tonic-gate 	mutex_exit(&ehci_polledp->ehci_polled_input_pipe_handle->p_mutex);
7617c478bd9Sstevel@tonic-gate 
7627c478bd9Sstevel@tonic-gate 	/*
7637c478bd9Sstevel@tonic-gate 	 * Store a pointer to the pipe handle. This structure was  just
7647c478bd9Sstevel@tonic-gate 	 * allocated and it is not in use yet.	The locking is there to
7657c478bd9Sstevel@tonic-gate 	 * satisfy warlock.
7667c478bd9Sstevel@tonic-gate 	 */
7677c478bd9Sstevel@tonic-gate 	mutex_enter(&ph->p_mutex);
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 	bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t));
7707c478bd9Sstevel@tonic-gate 
7717c478bd9Sstevel@tonic-gate 	mutex_exit(&ph->p_mutex);
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate 	pp->pp_pipe_handle = ehci_polledp->ehci_polled_input_pipe_handle;
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	/*
7767c478bd9Sstevel@tonic-gate 	 * Allocate a dummy for the interrupt table. This dummy will be
7777c478bd9Sstevel@tonic-gate 	 * put into the action when we	switch interrupt  tables during
7787c478bd9Sstevel@tonic-gate 	 * ehci_hcdi_polled_enter. Dummy is placed on the unused lattice
7797c478bd9Sstevel@tonic-gate 	 * entries. When the QH is allocated we will replace dummy QH by
7807c478bd9Sstevel@tonic-gate 	 * valid interrupt QH in one or more locations in the interrupt
7817c478bd9Sstevel@tonic-gate 	 * lattice depending on the requested polling interval. Also we
7827c478bd9Sstevel@tonic-gate 	 * will hang a dummy QTD to the QH & dummy QTD is used to indicate
7837c478bd9Sstevel@tonic-gate 	 * the end of the QTD chain.
7847c478bd9Sstevel@tonic-gate 	 */
7857c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_dummy_qh =
7867c478bd9Sstevel@tonic-gate 	    ehci_alloc_qh(ehcip, NULL, EHCI_POLLED_MODE_FLAG);
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 	if (ehci_polledp->ehci_polled_dummy_qh == NULL) {
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 		return (USB_NO_RESOURCES);
7917c478bd9Sstevel@tonic-gate 	}
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	/*
7949b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * Allocate the endpoint. This QH will be inserted in
7959b58c2adSzhigang lu - Sun Microsystems - Beijing China 	 * to the lattice chain for the device. This endpoint
7967c478bd9Sstevel@tonic-gate 	 * will have the QTDs hanging off of it for the processing.
7977c478bd9Sstevel@tonic-gate 	 */
7987c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_qh = ehci_alloc_qh(
7997c478bd9Sstevel@tonic-gate 	    ehcip, ph, EHCI_POLLED_MODE_FLAG);
8007c478bd9Sstevel@tonic-gate 
8017c478bd9Sstevel@tonic-gate 	if (ehci_polledp->ehci_polled_qh == NULL) {
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 		return (USB_NO_RESOURCES);
8047c478bd9Sstevel@tonic-gate 	}
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	/* Set the state of pipe as idle */
8077c478bd9Sstevel@tonic-gate 	pp->pp_state = EHCI_PIPE_STATE_IDLE;
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	/* Set polled mode flag */
8107c478bd9Sstevel@tonic-gate 	pp->pp_flag = EHCI_POLLED_MODE_FLAG;
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	/* Insert the endpoint onto the pipe handle */
8137c478bd9Sstevel@tonic-gate 	pp->pp_qh = ehci_polledp->ehci_polled_qh;
8147c478bd9Sstevel@tonic-gate 
8159b58c2adSzhigang lu - Sun Microsystems - Beijing China 	pipe_attr = ph->p_ep.bmAttributes & USB_EP_ATTR_MASK;
8167c478bd9Sstevel@tonic-gate 
8179b58c2adSzhigang lu - Sun Microsystems - Beijing China 	switch (pipe_attr) {
8189b58c2adSzhigang lu - Sun Microsystems - Beijing China 	case USB_EP_ATTR_INTR:
8199b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/*
8209b58c2adSzhigang lu - Sun Microsystems - Beijing China 		 * Set soft interrupt handler flag in the normal mode usb
8219b58c2adSzhigang lu - Sun Microsystems - Beijing China 		 * pipe handle.
8229b58c2adSzhigang lu - Sun Microsystems - Beijing China 		 */
8239b58c2adSzhigang lu - Sun Microsystems - Beijing China 		mutex_enter(&ph->p_mutex);
8249b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ph->p_spec_flag |= USBA_PH_FLAG_USE_SOFT_INTR;
8259b58c2adSzhigang lu - Sun Microsystems - Beijing China 		mutex_exit(&ph->p_mutex);
8267c478bd9Sstevel@tonic-gate 
8279b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/*
8289b58c2adSzhigang lu - Sun Microsystems - Beijing China 		 * Insert a Interrupt polling request onto the endpoint.
8299b58c2adSzhigang lu - Sun Microsystems - Beijing China 		 *
8309b58c2adSzhigang lu - Sun Microsystems - Beijing China 		 * There will now be two QTDs on the QH, one is the dummy QTD
8319b58c2adSzhigang lu - Sun Microsystems - Beijing China 		 * that was allocated above in the  ehci_alloc_qh and this
8329b58c2adSzhigang lu - Sun Microsystems - Beijing China 		 * new one.
8339b58c2adSzhigang lu - Sun Microsystems - Beijing China 		 */
8349b58c2adSzhigang lu - Sun Microsystems - Beijing China 		if ((ehci_start_periodic_pipe_polling(ehcip,
8359b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    ehci_polledp->ehci_polled_input_pipe_handle,
8369b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    NULL, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
8377c478bd9Sstevel@tonic-gate 
8389b58c2adSzhigang lu - Sun Microsystems - Beijing China 			return (USB_NO_RESOURCES);
8399b58c2adSzhigang lu - Sun Microsystems - Beijing China 		}
8409b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/* Get the given new interrupt qtd */
8419b58c2adSzhigang lu - Sun Microsystems - Beijing China 		qtd = (ehci_qtd_t *)(ehci_qtd_iommu_to_cpu(ehcip,
8429b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    (Get_QH(pp->pp_qh->qh_next_qtd) & EHCI_QH_NEXT_QTD_PTR)));
8439b58c2adSzhigang lu - Sun Microsystems - Beijing China 
8449b58c2adSzhigang lu - Sun Microsystems - Beijing China 		/* Insert this qtd into active interrupt QTD list */
8459b58c2adSzhigang lu - Sun Microsystems - Beijing China 		ehci_polled_insert_qtd_into_active_intr_qtd_list(ehci_polledp,
8469b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    qtd);
8479b58c2adSzhigang lu - Sun Microsystems - Beijing China 		break;
8489b58c2adSzhigang lu - Sun Microsystems - Beijing China 	case USB_EP_ATTR_BULK:
8499b58c2adSzhigang lu - Sun Microsystems - Beijing China 		if ((ehci_polled_create_tw(ehci_polledp,
8509b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    ehci_polledp->ehci_polled_input_pipe_handle,
8519b58c2adSzhigang lu - Sun Microsystems - Beijing China 		    USB_FLAGS_SLEEP)) != USB_SUCCESS) {
8529b58c2adSzhigang lu - Sun Microsystems - Beijing China 
8539b58c2adSzhigang lu - Sun Microsystems - Beijing China 			return (USB_NO_RESOURCES);
8549b58c2adSzhigang lu - Sun Microsystems - Beijing China 		}
8559b58c2adSzhigang lu - Sun Microsystems - Beijing China 		break;
8569b58c2adSzhigang lu - Sun Microsystems - Beijing China 	default:
8579b58c2adSzhigang lu - Sun Microsystems - Beijing China 		return (USB_FAILURE);
8589b58c2adSzhigang lu - Sun Microsystems - Beijing China 	}
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 	return (USB_SUCCESS);
8617c478bd9Sstevel@tonic-gate }
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate /*
8657c478bd9Sstevel@tonic-gate  * Polled deinitialization routines
8667c478bd9Sstevel@tonic-gate  */
8677c478bd9Sstevel@tonic-gate 
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate /*
8707c478bd9Sstevel@tonic-gate  * ehci_polled_fini:
8717c478bd9Sstevel@tonic-gate  */
8727c478bd9Sstevel@tonic-gate static int
ehci_polled_fini(ehci_polled_t * ehci_polledp)8737c478bd9Sstevel@tonic-gate ehci_polled_fini(ehci_polled_t	*ehci_polledp)
8747c478bd9Sstevel@tonic-gate {
8757c478bd9Sstevel@tonic-gate 	ehci_state_t		*ehcip = ehci_polledp->ehci_polled_ehcip;
8767c478bd9Sstevel@tonic-gate 	ehci_pipe_private_t	*pp;
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 	/* If the structure is already in use, then don't free it */
8817c478bd9Sstevel@tonic-gate 	if (ehci_polledp->ehci_polled_flags & POLLED_INPUT_MODE) {
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 		return (USB_SUCCESS);
8847c478bd9Sstevel@tonic-gate 	}
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 	pp = (ehci_pipe_private_t *)
8877c478bd9Sstevel@tonic-gate 	    ehci_polledp->ehci_polled_input_pipe_handle->p_hcd_private;
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 	/* Deallocate all the pre-allocated interrupt requests */
8907c478bd9Sstevel@tonic-gate 	ehci_handle_outstanding_requests(ehcip, pp);
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 	/*
8937c478bd9Sstevel@tonic-gate 	 * Traverse the list of QTD's on this endpoint and these QTD's
8947c478bd9Sstevel@tonic-gate 	 * have outstanding transfer requests. Since list processing
8957c478bd9Sstevel@tonic-gate 	 * is stopped, these QTDs can be deallocated.
8967c478bd9Sstevel@tonic-gate 	 */
8977c478bd9Sstevel@tonic-gate 	ehci_polled_traverse_qtds(ehci_polledp, pp->pp_pipe_handle);
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	/* Free DMA resources */
9007c478bd9Sstevel@tonic-gate 	ehci_free_dma_resources(ehcip, pp->pp_pipe_handle);
9017c478bd9Sstevel@tonic-gate 
9027c478bd9Sstevel@tonic-gate 	/*
9037c478bd9Sstevel@tonic-gate 	 * Deallocate the endpoint descriptors that we allocated
9047c478bd9Sstevel@tonic-gate 	 * with ehci_alloc_qh.
9057c478bd9Sstevel@tonic-gate 	 */
9067c478bd9Sstevel@tonic-gate 	if (ehci_polledp->ehci_polled_dummy_qh) {
9077c478bd9Sstevel@tonic-gate 		ehci_deallocate_qh(ehcip, ehci_polledp->ehci_polled_dummy_qh);
9087c478bd9Sstevel@tonic-gate 	}
9097c478bd9Sstevel@tonic-gate 
9107c478bd9Sstevel@tonic-gate 	if (ehci_polledp->ehci_polled_qh) {
9117c478bd9Sstevel@tonic-gate 		ehci_deallocate_qh(ehcip, ehci_polledp->ehci_polled_qh);
9127c478bd9Sstevel@tonic-gate 	}
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	mutex_destroy(&ehci_polledp->ehci_polled_input_pipe_handle->p_mutex);
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	/*
9177c478bd9Sstevel@tonic-gate 	 * Destroy everything about the pipe that we allocated in
9187c478bd9Sstevel@tonic-gate 	 * ehci_polled_duplicate_pipe_handle
9197c478bd9Sstevel@tonic-gate 	 */
9207c478bd9Sstevel@tonic-gate 	kmem_free(pp, sizeof (ehci_pipe_private_t));
9217c478bd9Sstevel@tonic-gate 
9227c478bd9Sstevel@tonic-gate 	kmem_free(ehci_polledp->ehci_polled_input_pipe_handle,
9237c478bd9Sstevel@tonic-gate 	    sizeof (usba_pipe_handle_data_t));
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	/*
9267c478bd9Sstevel@tonic-gate 	 * We use this field to determine if a QTD is for input or not,
9277c478bd9Sstevel@tonic-gate 	 * so NULL the pointer so we don't check deallocated data.
9287c478bd9Sstevel@tonic-gate 	 */
9297c478bd9Sstevel@tonic-gate 	ehci_polledp->ehci_polled_input_pipe_handle = NULL;
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	/*
9327c478bd9Sstevel@tonic-gate 	 * Finally, free off the structure that we use to keep track
9337c478bd9Sstevel@tonic-gate 	 * of all this.
9347c478bd9Sstevel@tonic-gate 	 */
9357c478bd9Sstevel@tonic-gate 	kmem_free(ehci_polledp, sizeof (ehci_polled_t));
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 	return (USB_SUCCESS);
9387c478bd9Sstevel@tonic-gate }
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate /*
9427c478bd9Sstevel@tonic-gate  * Polled save state routines
9437c478bd9Sstevel@tonic-gate  */
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate /*
9477c478bd9Sstevel@tonic-gate  * ehci_polled_save_state:
9487c478bd9Sstevel@tonic-gate  */
9497c478bd9Sstevel@tonic-gate static void
ehci_polled_save_state(ehci_polled_t * ehci_polledp)9507c478bd9Sstevel@tonic-gate ehci_polled_save_state(ehci_polled_t	*ehci_polledp)
9517c478bd9Sstevel@tonic-gate {
9527c478bd9Sstevel@tonic-gate 	int				i;
9537c478bd9Sstevel@tonic-gate 	ehci_state_t			*ehcip;
9547c478bd9Sstevel@tonic-gate 	uint_t				polled_toggle;
9557c478bd9Sstevel@tonic-gate 	uint_t				real_toggle;
9567c478bd9Sstevel@tonic-gate 	ehci_pipe_private_t		*pp = NULL; /* Normal mode Pipe */
9577c478bd9Sstevel@tonic-gate 	ehci_pipe_private_t		*polled_pp; /* Polled mode Pipe */
9587c478bd9Sstevel@tonic-gate 	usba_pipe_handle_data_t		*ph;
9597c478bd9Sstevel@tonic-gate 	uint8_t				ep_addr;
9607c478bd9Sstevel@tonic-gate 	ehci_regs_t			*ehci_polled_regsp;
9617c478bd9Sstevel@tonic-gate 	ehci_qh_t			*qh;
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate #ifndef lint
9647c478bd9Sstevel@tonic-gate 	_NOTE(NO_COMPETING_THREADS_NOW);
9657c478bd9Sstevel@tonic-gate #endif
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 	/*
9687c478bd9Sstevel@tonic-gate 	 * If either of these two flags are set, then we have already
9697c478bd9Sstevel@tonic-gate 	 * saved off the state information and setup the controller.
9707c478bd9Sstevel@tonic-gate 	 */
9717c478bd9Sstevel@tonic-gate 	if (ehci_polledp->ehci_polled_flags & POLLED_INPUT_MODE_INUSE) {
9727c478bd9Sstevel@tonic-gate #ifndef lint
9737c478bd9Sstevel@tonic-gate 		_NOTE(COMPETING_THREADS_NOW);
9747c478bd9Sstevel@tonic-gate #endif
9757c478bd9Sstevel@tonic-gate 		return;
9767c478bd9Sstevel@tonic-gate 	}
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate 	ehcip = ehci_polledp->ehci_polled_ehcip;
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 	/*
9817c478bd9Sstevel@tonic-gate 	 * Check if the number of keyboard reach the max number we can
9827c478bd9Sstevel@tonic-gate 	 * support in polled mode
9837c478bd9Sstevel@tonic-gate 	 */
9847c478bd9Sstevel@tonic-gate 	if (++ ehcip->ehci_polled_enter_count > MAX_NUM_FOR_KEYBOARD) {
9857c478bd9Sstevel@tonic-gate #ifndef lint
9867c478bd9Sstevel@tonic-gate 		_NOTE(COMPETING_THREADS_NOW);
9877c478bd9Sstevel@tonic-gate #endif
9887c478bd9Sstevel@tonic-gate 		return;
9897c478bd9Sstevel@tonic-gate 	}
9907c478bd9Sstevel@tonic-gate 	ehci_polled_regsp = &ehcip->ehci_polled_save_regs;
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 	/* Get the endpoint addr. */
9937c478bd9Sstevel@tonic-gate 	ep_addr = ehci_polledp->ehci_polled_ep_addr;
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 	/* Get the normal mode usb pipe handle */
9967c478bd9Sstevel@tonic-gate 	ph = usba_hcdi_get_ph_data(ehci_polledp->ehci_polled_usb_dev, ep_addr);
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate 	/*
9997c478bd9Sstevel@tonic-gate 	 * The first enter keyboard entry should save info of the normal mode,
10007c478bd9Sstevel@tonic-gate 	 * disable all list processing and interrupt, initialize the
10017c478bd9Sstevel@tonic-gate 	 * frame list table with dummy QHs.
10027c478bd9Sstevel@tonic-gate 	 */
10037c478bd9Sstevel@tonic-gate 	if (ehcip->ehci_polled_enter_count == 1) {
10047c478bd9Sstevel@tonic-gate 		/*
10057c478bd9Sstevel@tonic-gate 		 * Save the current normal mode ehci registers	and later this
10067c478bd9Sstevel@tonic-gate 		 * saved register copy is used to replace some of required ehci
10077c478bd9Sstevel@tonic-gate 		 * registers before switching from polled mode to normal mode.
10087c478bd9Sstevel@tonic-gate 		 */
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 		bzero((void *)ehci_polled_regsp, sizeof (ehci_regs_t));
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 		/* Save current ehci registers */
10137c478bd9Sstevel@tonic-gate 		ehci_polled_regsp->ehci_command = Get_OpReg(ehci_command);
10147c478bd9Sstevel@tonic-gate 		ehci_polled_regsp->ehci_interrupt = Get_OpReg(ehci_interrupt);
10157c478bd9Sstevel@tonic-gate 		ehci_polled_regsp->ehci_ctrl_segment =
10167c478bd9Sstevel@tonic-gate 		    Get_OpReg(ehci_ctrl_segment);
10177c478bd9Sstevel@tonic-gate 		ehci_polled_regsp->
10187c478bd9Sstevel@tonic-gate 		    ehci_async_list_addr = Get_OpReg(ehci_async_list_addr);
10197c478bd9Sstevel@tonic-gate 		ehci_polled_regsp->ehci_config_flag =
10207c478bd9Sstevel@tonic-gate 		    Get_OpReg(ehci_config_flag);
10217c478bd9Sstevel@tonic-gate 		ehci_polled_regsp->ehci_periodic_list_base =
10227c478bd9Sstevel@tonic-gate 		    Get_OpReg(ehci_periodic_list_base);
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate 		/* Disable all list processing and interrupts */
10257c478bd9Sstevel@tonic-gate 		Set_OpReg(ehci_command, Get_OpReg(ehci_command) &
10267c478bd9Sstevel@tonic-gate 		    ~(EHCI_CMD_ASYNC_SCHED_ENABLE |
10277c478bd9Sstevel@tonic-gate 		    EHCI_CMD_PERIODIC_SCHED_ENABLE));
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate 		/* Wait for few milliseconds */
10307c478bd9Sstevel@tonic-gate 		drv_usecwait(EHCI_POLLED_TIMEWAIT);
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 		/* Save any unprocessed normal mode ehci interrupts */
10337c478bd9Sstevel@tonic-gate 		ehcip->ehci_missed_intr_sts = EHCI_INTR_USB;
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 		/*
10367c478bd9Sstevel@tonic-gate 		 * Save the current interrupt lattice and  replace this lattice
10377c478bd9Sstevel@tonic-gate 		 * with an lattice used in POLLED mode. We will restore lattice
10387c478bd9Sstevel@tonic-gate 		 * back when we exit from the POLLED mode.
10397c478bd9Sstevel@tonic-gate 		 */
10407c478bd9Sstevel@tonic-gate 		for (i = 0; i < EHCI_NUM_PERIODIC_FRAME_LISTS; i++) {
10417c478bd9Sstevel@tonic-gate 			ehcip->ehci_polled_frame_list_table[i] =
10427c478bd9Sstevel@tonic-gate 			    (ehci_qh_t *)(uintptr_t)Get_PFLT(ehcip->
10437c478bd9Sstevel@tonic-gate 			    ehci_periodic_frame_list_tablep->
10447c478bd9Sstevel@tonic-gate 			    ehci_periodic_frame_list_table[i]);
10457c478bd9Sstevel@tonic-gate 		}
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 		/*
10487c478bd9Sstevel@tonic-gate 		 * Fill in the lattice with dummy QHs. These QHs are used so the
10497c478bd9Sstevel@tonic-gate 		 * controller can tell that it is at the end of the QH list.
10507c478bd9Sstevel@tonic-gate 		 */
10517c478bd9Sstevel@tonic-gate 		for (i = 0; i < EHCI_NUM_PERIODIC_FRAME_LISTS; i++) {
10527c478bd9Sstevel@tonic-gate 			Set_PFLT(ehcip->ehci_periodic_frame_list_tablep->
10537c478bd9Sstevel@tonic-gate 			    ehci_periodic_frame_list_table[i],
10547c478bd9Sstevel@tonic-gate 			    ehci_qh_cpu_to_iommu(ehcip,
10557c478bd9Sstevel@tonic-gate 			    ehci_polledp->ehci_polled_dummy_qh) |
10567c478bd9Sstevel@tonic-gate 			    (EHCI_QH_LINK_REF_QH | EHCI_QH_LINK_PTR_VALID));
10577c478bd9Sstevel@tonic-gate 		}
10587c478bd9Sstevel@tonic-gate 
10597c478bd9Sstevel@tonic-gate 	}
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 	/* Get the polled mode ehci pipe private structure */
10627c478bd9Sstevel@tonic-gate 	polled_pp = (ehci_pipe_private_t *)
10637c478bd9Sstevel@tonic-gate 	    ehci_polledp->ehci_polled_input_pipe_handle->p_hcd_private;
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate 	/*
10667c478bd9Sstevel@tonic-gate 	 * Before replacing the lattice, adjust the data togggle on the
10677c478bd9Sstevel@tonic-gate 	 * on the ehci's interrupt ed
10687c478bd9Sstevel@tonic-gate 	 */
10697c478bd9Sstevel@tonic-gate 	polled_toggle = (Get_QH(polled_pp->pp_qh->qh_status) &
10707c478bd9Sstevel@tonic-gate 	    EHCI_QH_STS_DATA_TOGGLE) ? DATA1:DATA0;
10717c478bd9Sstevel@tonic-gate 
10727c478bd9Sstevel@tonic-gate 	/*
10737c478bd9Sstevel@tonic-gate 	 * If normal mode interrupt pipe endpoint is active, get the data
10747c478bd9Sstevel@tonic-gate 	 * toggle from the this interrupt endpoint through the corresponding
10757c478bd9Sstevel@tonic-gate 	 * interrupt pipe handle. Else get the data toggle information from
10767c478bd9Sstevel@tonic-gate 	 * the usb device structure and this information is saved during the
10777c478bd9Sstevel@tonic-gate 	 * normal mode interrupt pipe close. Use this data toggle information
10787c478bd9Sstevel@tonic-gate 	 * to fix the data toggle of polled mode interrupt endpoint.
10797c478bd9Sstevel@tonic-gate 	 */
10807c478bd9Sstevel@tonic-gate 	if (ph) {
10817c478bd9Sstevel@tonic-gate 		/* Get the normal mode ehci pipe private structure */
10827c478bd9Sstevel@tonic-gate 		pp = (ehci_pipe_private_t *)ph->p_hcd_private;
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 		real_toggle = (Get_QH(pp->pp_qh->qh_status) &
10857c478bd9Sstevel@tonic-gate 		    EHCI_QH_STS_DATA_TOGGLE) ? DATA1:DATA0;
10867c478bd9Sstevel@tonic-gate 	} else {
10877c478bd9Sstevel@tonic-gate 		real_toggle = usba_hcdi_get_data_toggle(
10887c478bd9Sstevel@tonic-gate 		    ehci_polledp->ehci_polled_usb_dev, ep_addr);
10897c478bd9Sstevel@tonic-gate 	}
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 	if (polled_toggle != real_toggle) {
10927c478bd9Sstevel@tonic-gate 		if (real_toggle == DATA0) {
10937c478bd9Sstevel@tonic-gate 			Set_QH(polled_pp->pp_qh->qh_status,
10947c478bd9Sstevel@tonic-gate 			    Get_QH(polled_pp->pp_qh->qh_status) &
10957c478bd9Sstevel@tonic-gate 			    ~EHCI_QH_STS_DATA_TOGGLE);
10967c478bd9Sstevel@tonic-gate 		} else {
10977c478bd9Sstevel@tonic-gate 			Set_QH(polled_pp->pp_qh->qh_status,
10987c478bd9Sstevel@tonic-gate 			    Get_QH(polled_pp->pp_qh->qh_status) |
10997c478bd9Sstevel@tonic-gate 			    EHCI_QH_STS_DATA_TOGGLE);
11007c478bd9Sstevel@tonic-gate 		}
11017c478bd9Sstevel@tonic-gate 	}
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 	/*
11047c478bd9Sstevel@tonic-gate 	 * Check whether Halt bit is set in the QH and if so  clear the
11057c478bd9Sstevel@tonic-gate 	 * halt bit.
11067c478bd9Sstevel@tonic-gate 	 */
11077c478bd9Sstevel@tonic-gate 	if (polled_pp->pp_qh->qh_status & EHCI_QH_STS_HALTED) {
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 		/* Clear the halt bit */
11107c478bd9Sstevel@tonic-gate 		Set_QH(polled_pp->pp_qh->qh_status,
11117c478bd9Sstevel@tonic-gate 		    (Get_QH(polled_pp->pp_qh->qh_status) &
11127c478bd9Sstevel@tonic-gate 		    ~EHCI_QH_STS_HALTED));
11137c478bd9Sstevel@tonic-gate 	}
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 	/*
11167c478bd9Sstevel@tonic-gate 	 * Initialize the qh overlay area
11177c478bd9Sstevel@tonic-gate 	 */
11187c478bd9Sstevel@tonic-gate 	qh = ehci_polledp->ehci_polled_qh;
11197c478bd9Sstevel@tonic-gate 	for (i = 0; i < 5; i++) {
11206aef9e11SToomas Soome 		Set_QH(qh->qh_buf[i], 0);
11216aef9e11SToomas Soome 		Set_QH(qh->qh_buf_high[i], 0);
11227c478bd9Sstevel@tonic-gate 	}
11237c478bd9Sstevel@tonic-gate 	Set_QH(qh->qh_next_qtd, ehci_qtd_cpu_to_iommu(ehcip,
11247c478bd9Sstevel@tonic-gate 	    ehci_polledp->ehci_polled_active_intr_qtd_list));
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 	/*
11277c478bd9Sstevel@tonic-gate 	 * Now, add the endpoint to the lattice that we will  hang  our
11287c478bd9Sstevel@tonic-gate 	 * QTD's off of.  We need to poll this device at  every 8 ms and
11297c478bd9Sstevel@tonic-gate 	 * hence add this QH needs 4 entries in interrupt lattice.
11307c478bd9Sstevel@tonic-gate 	 */
11317c478bd9Sstevel@tonic-gate 	for (i = ehcip->ehci_polled_enter_count - 1;
11327c478bd9Sstevel@tonic-gate 	    i < EHCI_NUM_PERIODIC_FRAME_LISTS;
11337c478bd9Sstevel@tonic-gate 	    i = i + LS_MIN_POLL_INTERVAL) {
11347c478bd9Sstevel@tonic-gate 		Set_PFLT(ehcip->ehci_periodic_frame_list_tablep->
11357c478bd9Sstevel@tonic-gate 		    ehci_periodic_frame_list_table[i],
11367c478bd9Sstevel@tonic-gate 		    ehci_qh_cpu_to_iommu(ehcip,
11377c478bd9Sstevel@tonic-gate 		    ehci_polledp->ehci_polled_qh) | EHCI_QH_LINK_REF_QH);
11387c478bd9Sstevel@tonic-gate 	}
11397c478bd9Sstevel@tonic-gate 	/* The first enter keyboard entry enable interrupts and periodic list */
11407c478bd9Sstevel@tonic-gate 	if (ehcip->ehci_polled_enter_count == 1) {
11417c478bd9Sstevel@tonic-gate 		/* Enable USB and Frame list rollover interrupts */
11427c478bd9Sstevel@tonic-gate 		Set_OpReg(ehci_interrupt, (EHCI_INTR_USB |
11437c478bd9Sstevel@tonic-gate 		    EHCI_INTR_USB_ERROR | EHCI_INTR_FRAME_LIST_ROLLOVER));
1144