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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
26 
27 /*
28  * USBA: Solaris USB Architecture support
29  *
30  * ISSUES:
31  */
32 #define	USBA_FRAMEWORK
33 #include <sys/usb/usba.h>
34 #include <sys/usb/usba/hcdi.h>
35 #include <sys/usb/usba/genconsole.h>
36 #include <sys/usb/usba/usba_types.h>
37 #include <sys/usb/usba/usba_impl.h>
38 
39 /*
40  * Initialize USB polled support. This routine calls down to the lower
41  * layers to initialize any state information.
42  */
43 int
44 usb_console_input_init(dev_info_t		*dip,
45 			usb_pipe_handle_t	pipe_handle,
46 			uchar_t			**state_buf,
47 			usb_console_info_t	*console_input_info)
48 {
49 	int			ret;
50 	usba_device_t		*usba_device;
51 	usb_console_info_impl_t	*usb_console_input = kmem_zalloc(
52 			sizeof (struct usb_console_info_impl), KM_SLEEP);
53 
54 	/*
55 	 * Save the dip
56 	 */
57 	usb_console_input->uci_dip = dip;
58 
59 	/*
60 	 * Translate the dip into a device.
61 	 */
62 	usba_device = usba_get_usba_device(dip);
63 
64 	/*
65 	 * Call the lower layer to initialize any state information
66 	 */
67 	ret = usba_device->usb_hcdi_ops->usba_hcdi_console_input_init(
68 		usba_get_ph_data(pipe_handle), state_buf, usb_console_input);
69 
70 	if (ret != USB_SUCCESS) {
71 		kmem_free(usb_console_input,
72 			sizeof (struct usb_console_info_impl));
73 	} else {
74 		*console_input_info = (usb_console_info_t)usb_console_input;
75 	}
76 
77 	return (ret);
78 }
79 
80 
81 /*
82  * Free up any resources that we allocated in the above initialization
83  * routine.
84  */
85 int
86 usb_console_input_fini(usb_console_info_t console_input_info)
87 {
88 	usb_console_info_impl_t		*usb_console_input;
89 	usba_device_t			*usba_device;
90 	int				ret;
91 
92 	usb_console_input = (usb_console_info_impl_t *)console_input_info;
93 
94 	/*
95 	 * Translate the dip into a device.
96 	 */
97 	usba_device = usba_get_usba_device(usb_console_input->uci_dip);
98 
99 	/*
100 	 * Call the lower layer to free any state information.
101 	 */
102 	ret = usba_device->usb_hcdi_ops->usba_hcdi_console_input_fini(
103 		usb_console_input);
104 
105 	if (ret == USB_FAILURE) {
106 
107 		return (ret);
108 	}
109 
110 	/*
111 	 * We won't be needing this information anymore.
112 	 */
113 	kmem_free(usb_console_input, sizeof (struct usb_console_info_impl));
114 
115 	return (USB_SUCCESS);
116 }
117 
118 
119 /*
120  * This is the routine that OBP calls to save the USB state information
121  * before using the USB keyboard as an input device.  This routine,
122  * and all of the routines that it calls, are responsible for saving
123  * any state information so that it can be restored when OBP mode is
124  * over.  At this layer, this code is mainly just a pass through.
125  *
126  * Warning:  this code runs in polled mode.
127  */
128 int
129 usb_console_input_enter(usb_console_info_t console_input_info)
130 {
131 	usba_device_t				*usba_device;
132 	usb_console_info_impl_t			*usb_console_input;
133 
134 	usb_console_input = (usb_console_info_impl_t *)console_input_info;
135 
136 	/*
137 	 * Translate the dip into a device.
138 	 * Do this by directly looking at the dip, do not call
139 	 * usba_get_usba_device() because this function calls into the DDI.
140 	 * The ddi then tries to acquire a mutex and the machine hard hangs.
141 	 */
142 	usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip);
143 
144 	/*
145 	 * Call the lower layer to save state information.
146 	 */
147 	usba_device->usb_hcdi_ops->usba_hcdi_console_input_enter(
148 		usb_console_input);
149 
150 	return (USB_SUCCESS);
151 }
152 
153 
154 /*
155  * This is the routine that OBP calls when it wants to read a character.
156  * We will call to the lower layers to see if there is any input data
157  * available.  At this layer, this code is mainly just a pass through.
158  *
159  * Warning: This code runs in polled mode.
160  */
161 int
162 usb_console_read(usb_console_info_t console_input_info, uint_t *num_characters)
163 {
164 	usba_device_t				*usba_device;
165 	usb_console_info_impl_t			*usb_console_input;
166 
167 	usb_console_input = (usb_console_info_impl_t *)console_input_info;
168 
169 	/*
170 	 * Translate the dip into a device.
171 	 * Do this by directly looking at the dip, do not call
172 	 * usba_get_usba_device() because this function calls into the DDI.
173 	 * The ddi then tries to acquire a mutex and the machine hard hangs.
174 	 */
175 	usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip);
176 
177 	/*
178 	 * Call the lower layer to get a a character.  Return the number
179 	 * of characters read into the buffer.
180 	 */
181 	return (usba_device->usb_hcdi_ops->usba_hcdi_console_read(
182 		usb_console_input, num_characters));
183 }
184 
185 
186 /*
187  * This is the routine that OBP calls when it is giving up control of the
188  * USB keyboard.  This routine, and the lower layer routines that it calls,
189  * are responsible for restoring the controller state to the state it was
190  * in before OBP took control. At this layer, this code is mainly just a
191  * pass through.
192  *
193  * Warning: This code runs in polled mode.
194  */
195 int
196 usb_console_input_exit(usb_console_info_t console_input_info)
197 {
198 	usba_device_t				*usba_device;
199 	usb_console_info_impl_t			*usb_console_input;
200 
201 	usb_console_input = (usb_console_info_impl_t *)console_input_info;
202 
203 	/*
204 	 * Translate the dip into a device.
205 	 * Do this by directly looking at the dip, do not call
206 	 * usba_get_usba_device() because this function calls into the DDI.
207 	 * The ddi then tries to acquire a mutex and the machine hard hangs.
208 	 */
209 	usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip);
210 
211 	/*
212 	 * Restore the state information.
213 	 */
214 	usba_device->usb_hcdi_ops->usba_hcdi_console_input_exit(
215 		usb_console_input);
216 
217 	return (USB_SUCCESS);
218 }
219 
220 /*
221  * Initialize USB OBP support.  This routine calls down to the lower
222  * layers to initialize any state information.
223  */
224 int
225 usb_console_output_init(
226 	dev_info_t		*dip,
227 	usb_pipe_handle_t	pipe_handle,
228 	usb_console_info_t	*console_output_info)
229 {
230 	usba_device_t		*usb_device;
231 	usb_console_info_impl_t	*usb_console_output;
232 	int			ret;
233 
234 	/* Translate the dip into a device and check hcdi ops  */
235 	usb_device = usba_get_usba_device(dip);
236 	if (usb_device->usb_hcdi_ops->usba_hcdi_ops_version <
237 	    HCDI_OPS_VERSION_1 ||
238 	    usb_device->usb_hcdi_ops->usba_hcdi_console_output_init == NULL)
239 
240 		return (USB_FAILURE);
241 
242 	usb_console_output = kmem_zalloc(sizeof (struct usb_console_info_impl),
243 		KM_SLEEP);
244 	usb_console_output->uci_dip = dip;
245 
246 	/*
247 	 * Call the lower layer to initialize any state information
248 	 */
249 	ret = usb_device->usb_hcdi_ops->usba_hcdi_console_output_init(
250 		usba_get_ph_data(pipe_handle), usb_console_output);
251 
252 	if (ret == USB_FAILURE) {
253 		kmem_free(usb_console_output,
254 			sizeof (struct usb_console_info_impl));
255 
256 		return (ret);
257 	}
258 
259 	*console_output_info = (usb_console_info_t)usb_console_output;
260 
261 	return (USB_SUCCESS);
262 }
263 
264 /*
265  * Free up any resources that we allocated in the above initialization
266  * routine.
267  */
268 int
269 usb_console_output_fini(usb_console_info_t console_output_info)
270 {
271 	usb_console_info_impl_t	*usb_console_output;
272 	usba_device_t		*usb_device;
273 	int			ret;
274 
275 	usb_console_output = (usb_console_info_impl_t *)console_output_info;
276 
277 	/*
278 	 * Translate the dip into a device.
279 	 */
280 	usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip);
281 
282 	/*
283 	 * Call the lower layer to free any state information.
284 	 */
285 	ret = usb_device->usb_hcdi_ops->usba_hcdi_console_output_fini(
286 		usb_console_output);
287 
288 	if (ret == USB_FAILURE) {
289 
290 		return (ret);
291 	}
292 
293 	/*
294 	 * We won't be needing this information anymore.
295 	 */
296 	kmem_free(usb_console_output, sizeof (struct usb_console_info_impl));
297 
298 	return (USB_SUCCESS);
299 }
300 
301 /*
302  * This is the routine that OBP calls to save the USB state information
303  * before using the USB device as an output device.  This routine,
304  * and all of the routines that it calls, are responsible for saving
305  * any state information so that it can be restored when OBP mode is
306  * over.  At this layer, this code is mainly just a pass through.
307  */
308 int
309 usb_console_output_enter(usb_console_info_t console_output_info)
310 {
311 	usba_device_t			    *usb_device;
312 	usb_console_info_impl_t		 *usb_console_output;
313 
314 	usb_console_output = (usb_console_info_impl_t *)console_output_info;
315 
316 	/*
317 	 * Translate the dip into a device.
318 	 */
319 	usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip);
320 
321 	/*
322 	 * Call the lower layer to save state information.
323 	 */
324 	usb_device->usb_hcdi_ops->usba_hcdi_console_output_enter(
325 		usb_console_output);
326 
327 	return (USB_SUCCESS);
328 }
329 
330 /*
331  * This is the routine that OBP calls when it wants to write a character.
332  * We will call to the lower layers to write any data
333  * At this layer, this code is mainly just a pass through.
334  */
335 int
336 usb_console_write(usb_console_info_t console_output_info,
337 	uchar_t *buf, uint_t num_characters, uint_t *num_characters_written)
338 {
339 	usba_device_t		*usb_device;
340 	usb_console_info_impl_t	*usb_console_output;
341 
342 	usb_console_output = (usb_console_info_impl_t *)console_output_info;
343 
344 	/*
345 	 * Translate the dip into a device.
346 	 */
347 	usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip);
348 
349 	/*
350 	 * Call the lower layer to get a a character.  Return the number
351 	 * of characters read into the buffer.
352 	 */
353 	return (usb_device->usb_hcdi_ops->usba_hcdi_console_write(
354 		usb_console_output, buf, num_characters,
355 		num_characters_written));
356 }
357 
358 /*
359  * This is the routine that OBP calls when it is giving up control of the
360  * USB output device.  This routine, and the lower layer routines that it
361  * calls, are responsible for restoring the controller state to the state
362  * it was in before OBP took control. At this layer, this code is mainly
363  * just a pass through.
364  */
365 int
366 usb_console_output_exit(usb_console_info_t console_output_info)
367 {
368 	usba_device_t			 *usb_device;
369 	usb_console_info_impl_t		 *usb_console_output;
370 
371 	usb_console_output = (usb_console_info_impl_t *)console_output_info;
372 
373 	/*
374 	 * Translate the dip into a device.
375 	 */
376 	usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip);
377 
378 	/*
379 	 * Restore the state information.
380 	 */
381 	usb_device->usb_hcdi_ops->usba_hcdi_console_output_exit(
382 		usb_console_output);
383 
384 	return (USB_SUCCESS);
385 }
386