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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * USBA: Solaris USB Architecture support
30  *
31  * ISSUES:
32  */
33 #define	USBA_FRAMEWORK
34 #include <sys/usb/usba.h>
35 #include <sys/usb/usba/hcdi.h>
36 #include <sys/usb/usba/genconsole.h>
37 #include <sys/usb/usba/usba_types.h>
38 #include <sys/usb/usba/usba_impl.h>
39 
40 /*
41  * Initialize USB OBP support.	This routine calls down to the lower
42  * layers to initialize any state information.
43  */
44 int
45 usb_console_input_init(dev_info_t		*dip,
46 			usb_pipe_handle_t	pipe_handle,
47 			uchar_t			**obp_buf,
48 			usb_console_info_t	*console_input_info)
49 {
50 	int			ret;
51 	usba_device_t		*usba_device;
52 	usb_console_info_impl_t	*usb_console_input = kmem_zalloc(
53 			sizeof (struct usb_console_info_impl), KM_SLEEP);
54 
55 	/*
56 	 * Save the dip
57 	 */
58 	usb_console_input->uci_dip = dip;
59 
60 	/*
61 	 * Translate the dip into a device.
62 	 */
63 	usba_device = usba_get_usba_device(dip);
64 
65 	/*
66 	 * Call the lower layer to initialize any state information
67 	 */
68 	ret = usba_device->usb_hcdi_ops->usba_hcdi_console_input_init(
69 		usba_get_ph_data(pipe_handle), obp_buf, usb_console_input);
70 
71 	if (ret != USB_SUCCESS) {
72 		kmem_free(usb_console_input,
73 			sizeof (struct usb_console_info_impl));
74 	} else {
75 		*console_input_info = (usb_console_info_t)usb_console_input;
76 	}
77 
78 	return (ret);
79 }
80 
81 
82 /*
83  * Free up any resources that we allocated in the above initialization
84  * routine.
85  */
86 int
87 usb_console_input_fini(usb_console_info_t console_input_info)
88 {
89 	usb_console_info_impl_t		*usb_console_input;
90 	usba_device_t			*usba_device;
91 	int				ret;
92 
93 	usb_console_input = (usb_console_info_impl_t *)console_input_info;
94 
95 	/*
96 	 * Translate the dip into a device.
97 	 */
98 	usba_device = usba_get_usba_device(usb_console_input->uci_dip);
99 
100 	/*
101 	 * Call the lower layer to free any state information.
102 	 */
103 	ret = usba_device->usb_hcdi_ops->usba_hcdi_console_input_fini(
104 		usb_console_input);
105 
106 	if (ret == USB_FAILURE) {
107 
108 		return (ret);
109 	}
110 
111 	/*
112 	 * We won't be needing this information anymore.
113 	 */
114 	kmem_free(usb_console_input, sizeof (struct usb_console_info_impl));
115 
116 	return (USB_SUCCESS);
117 }
118 
119 
120 /*
121  * This is the routine that OBP calls to save the USB state information
122  * before using the USB keyboard as an input device.  This routine,
123  * and all of the routines that it calls, are responsible for saving
124  * any state information so that it can be restored when OBP mode is
125  * over.  At this layer, this code is mainly just a pass through.
126  *
127  * Warning:  this code runs in polled mode.
128  */
129 int
130 usb_console_input_enter(usb_console_info_t console_input_info)
131 {
132 	usba_device_t				*usba_device;
133 	usb_console_info_impl_t			*usb_console_input;
134 
135 	usb_console_input = (usb_console_info_impl_t *)console_input_info;
136 
137 	/*
138 	 * Translate the dip into a device.
139 	 * Do this by directly looking at the dip, do not call
140 	 * usba_get_usba_device() because this function calls into the DDI.
141 	 * The ddi then tries to acquire a mutex and the machine hard hangs.
142 	 */
143 	usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip);
144 
145 	/*
146 	 * Call the lower layer to save state information.
147 	 */
148 	usba_device->usb_hcdi_ops->usba_hcdi_console_input_enter(
149 		usb_console_input);
150 
151 	return (USB_SUCCESS);
152 }
153 
154 
155 /*
156  * This is the routine that OBP calls when it wants to read a character.
157  * We will call to the lower layers to see if there is any input data
158  * available.  At this layer, this code is mainly just a pass through.
159  *
160  * Warning: This code runs in polled mode.
161  */
162 int
163 usb_console_read(usb_console_info_t console_input_info, uint_t *num_characters)
164 {
165 	usba_device_t				*usba_device;
166 	usb_console_info_impl_t			*usb_console_input;
167 
168 	usb_console_input = (usb_console_info_impl_t *)console_input_info;
169 
170 	/*
171 	 * Translate the dip into a device.
172 	 * Do this by directly looking at the dip, do not call
173 	 * usba_get_usba_device() because this function calls into the DDI.
174 	 * The ddi then tries to acquire a mutex and the machine hard hangs.
175 	 */
176 	usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip);
177 
178 	/*
179 	 * Call the lower layer to get a a character.  Return the number
180 	 * of characters read into the buffer.
181 	 */
182 	return (usba_device->usb_hcdi_ops->usba_hcdi_console_read(
183 		usb_console_input, num_characters));
184 }
185 
186 
187 /*
188  * This is the routine that OBP calls when it is giving up control of the
189  * USB keyboard.  This routine, and the lower layer routines that it calls,
190  * are responsible for restoring the controller state to the state it was
191  * in before OBP took control. At this layer, this code is mainly just a
192  * pass through.
193  *
194  * Warning: This code runs in polled mode.
195  */
196 int
197 usb_console_input_exit(usb_console_info_t console_input_info)
198 {
199 	usba_device_t				*usba_device;
200 	usb_console_info_impl_t			*usb_console_input;
201 
202 	usb_console_input = (usb_console_info_impl_t *)console_input_info;
203 
204 	/*
205 	 * Translate the dip into a device.
206 	 * Do this by directly looking at the dip, do not call
207 	 * usba_get_usba_device() because this function calls into the DDI.
208 	 * The ddi then tries to acquire a mutex and the machine hard hangs.
209 	 */
210 	usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip);
211 
212 	/*
213 	 * Restore the state information.
214 	 */
215 	usba_device->usb_hcdi_ops->usba_hcdi_console_input_exit(
216 		usb_console_input);
217 
218 	return (USB_SUCCESS);
219 }
220