xref: /illumos-gate/usr/src/uts/common/sys/usb/usba/usba_impl.h (revision 4de2612967d06c4fdbf524a62556a1e8118a006f)
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 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_SYS_USB_USBA_USBA_IMPL_H
28 #define	_SYS_USB_USBA_USBA_IMPL_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <sys/usb/usba.h>
33 #include <sys/usb/usba/hcdi.h>
34 #include <sys/usb/usba/hubdi.h>
35 #include <sys/usb/usba/usba_private.h>
36 #include <sys/usb/usba/usba_types.h>
37 #include <sys/taskq.h>
38 #include <sys/disp.h>
39 
40 #ifdef	__cplusplus
41 extern "C" {
42 #endif
43 
44 
45 /*
46  * UGEN binding values specified in <hcd>.conf files
47  */
48 #define	USBA_UGEN_DEVICE_BINDING	1
49 #define	USBA_UGEN_INTERFACE_BINDING	2
50 
51 /*
52  * Allocating a USB address
53  */
54 #define	USBA_MAX_ADDRESS		127
55 #define	USBA_ADDRESS_ARRAY_SIZE	((USBA_MAX_ADDRESS+8)/8)
56 
57 /*
58  * async execution of usb_pipe_* functions which have a
59  * completion callback parameter (eg. usb_pipe_close(),
60  * usb_pipe_reset(), usb_pipe_stop_*_polling()
61  */
62 typedef struct usba_pipe_async_req {
63 	dev_info_t		*dip;
64 	struct usba_ph_impl	*ph_impl;
65 	usb_opaque_t		arg;
66 	usb_flags_t		usb_flags;
67 	void			(*callback)(
68 					usb_pipe_handle_t	ph,
69 					usb_opaque_t		callback_arg,
70 					int			rval,
71 					usb_cb_flags_t		error_code);
72 	usb_opaque_t		callback_arg;
73 	int			(*sync_func)(dev_info_t *,
74 					usba_ph_impl_t *,
75 					struct usba_pipe_async_req *,
76 					usb_flags_t);
77 } usba_pipe_async_req_t;
78 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usba_pipe_async_req_t))
79 
80 /* per-pipe taskq */
81 int	usba_async_ph_req(usba_pipe_handle_data_t *, void (*func)(void *),
82 							void *, usb_flags_t);
83 
84 /*
85  * usb wrapper around pm_request_power_change to allow for
86  * non blocking behavior
87  */
88 typedef struct usba_pm_req {
89 	dev_info_t	*dip;
90 	int		comp;
91 	int		old_level;
92 	int		level;
93 	void		(*cb)(void *, int);
94 	void		*arg;
95 	uint_t		flags;
96 } usba_pm_req_t;
97 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usba_pm_req_t))
98 
99 
100 /*
101  * Request wrappers for control/bulk/interrupt and isoch pipes
102  * These are hidden from client driver. They serve as place-holders
103  * for doing callbacks
104  *
105  * Request allocation: wrapper + usb_*_req_t alloc'ed together:
106  *
107  *		+-----------------------+
108  *		|	wr_queue	|		for callbacks
109  *		+-----------------------+
110  *		|	wr_req	|-------+	wr_req points to
111  *		+-----------------------+	|	the req below.
112  *		|			|	|
113  *		|	....		|	|
114  *		|	req_wrapper_t	|	|
115  *		|			|	|
116  *		+-----------------------+<------+
117  *		|			|
118  *		|	....		|
119  *		| ctrl/bulk/intr/isoch	|
120  *		|	req_t	|
121  *		|			|
122  *		|			|
123  *		+-----------------------+
124  */
125 typedef struct usba_req_wrapper {
126 	/* queueing in either a request or callback queue */
127 	usba_list_entry_t	wr_queue;
128 
129 	/*
130 	 * The request could be control/bulk/intr/isoc
131 	 * See usbai.h usb_ctrl_req_t/usb_bulk_req_t
132 	 * usb_intr_req_t/usb_isoc_req_t
133 	 */
134 	usb_opaque_t		wr_req;
135 
136 	/* for allocation tracking in usba_device_t */
137 	usba_list_entry_t	wr_allocated_list;
138 
139 	/*
140 	 * All reqs that are synchronous sleep on this cv
141 	 * for completion notification.
142 	 * In hcdi soft interrupt handler we call cv_signal()
143 	 */
144 	kcondvar_t		wr_cv;
145 
146 	/*
147 	 * This goes hand-in-hand with wr_cv. It is set by the soft intr hdlr
148 	 * before doing a cv_signal
149 	 */
150 	boolean_t		wr_done;
151 	dev_info_t		*wr_dip;	/* owner */
152 
153 	usb_opaque_t		wr_hcd_private;	/* for HCD's use */
154 
155 	usba_pipe_handle_data_t	*wr_ph_data;	/* ptr to pipe handle */
156 
157 	usb_cr_t		wr_cr;		/* save cr from HCDI */
158 	usb_cb_flags_t		wr_cb_flags;	/* save cb_flags */
159 	usb_flags_t		wr_usb_flags;	/* save usb flags from HCDI */
160 	usb_req_attrs_t		wr_attrs;	/* save attrs from HCDI */
161 
162 	/* total lenght of wrapper and request */
163 	size_t			wr_length;
164 } usba_req_wrapper_t;
165 
166 _NOTE(SCHEME_PROTECTS_DATA("method", usba_req_wrapper))
167 _NOTE(SCHEME_PROTECTS_DATA("method", usb_ctrl_req))
168 _NOTE(SCHEME_PROTECTS_DATA("method", usb_bulk_req))
169 _NOTE(SCHEME_PROTECTS_DATA("method", usb_intr_req))
170 _NOTE(SCHEME_PROTECTS_DATA("method", usb_isoc_req))
171 
172 /* additional flag for wr_usb_flags */
173 #define	USBA_WRP_FLAGS_WAIT	0x01
174 
175 /* additional usb flags, not exposed to clients */
176 #define	USBA_FLAGS_PRIVILEGED	0x02	/* for default pipe operations */
177 
178 /* Macros to convert wrapper to different request and vice-versa */
179 
180 /* to get the wr->wr_req field */
181 #define	USBA_WRP2REQ(wrp)	((wrp)->wr_req)
182 
183 /* to get the wrapper form the wr_req field */
184 #define	USBA_REQ2WRP(req)		(usba_req_wrapper_t *)\
185 				((uintptr_t)(req) - sizeof (usba_req_wrapper_t))
186 
187 /* to set the the address in the wr_req field */
188 #define	USBA_SETREQ_ADDR(wrp)	((uintptr_t)(wrp) + sizeof (*(wrp)))
189 
190 /* to get the 4 xfer type requests */
191 #define	USBA_WRP2CTRL_REQ(wrp)	((usb_ctrl_req_t *)USBA_WRP2REQ((wrp)))
192 #define	USBA_WRP2INTR_REQ(wrp)	((usb_intr_req_t *)USBA_WRP2REQ((wrp)))
193 #define	USBA_WRP2BULK_REQ(wrp)	((usb_bulk_req_t *)USBA_WRP2REQ((wrp)))
194 #define	USBA_WRP2ISOC_REQ(wrp)	((usb_isoc_req_t *)USBA_WRP2REQ((wrp)))
195 
196 /* to get pipe_handle from the wrapper */
197 #define	USBA_WRP2PH_DATA(wrp) \
198 	(usba_pipe_handle_data_t *)((wrp)->wr_ph_data)
199 
200 /* to get to the wr_queue from the wrapper */
201 #define	USBA_WRQUEUE2WRP(queue)	(usba_req_wrapper_t *)(queue)
202 
203 /* to get to the wr_allocated queue from the wrapper */
204 #define	USBA_ALLOCQ2WRP(queue)	(usba_req_wrapper_t *)((uintptr_t) \
205 	(queue)  - sizeof (usba_list_entry_t) - sizeof (usb_opaque_t))
206 
207 
208 /* alias for pipe handle member p_usba_private */
209 #define	p_active_cntrl_req_wrp	p_usba_private
210 
211 /*
212  * This function is used to get the HCD private field maintained by USBA.
213  * HCD calls this function.
214  */
215 usb_opaque_t usba_hcdi_get_ctrl_req_hcd_private(usb_ctrl_req_t *);
216 
217 /*
218  * This function is used to set the HCD private field maintained by USBA.
219  * HCD calls this function.
220  */
221 void	usba_hcdi_set_ctrl_req_hcd_private(usb_ctrl_req_t *, usb_opaque_t);
222 
223 int	usba_set_usb_address(usba_device_t *);
224 void	usba_unset_usb_address(usba_device_t *);
225 
226 /*
227  * Per Hub Data Structures
228  */
229 typedef  struct usba_hubdi {
230 	usba_list_entry_t hubdi_list;	 /* linking in hubdi list */
231 
232 	dev_info_t	*hubdi_dip;	 /* ptr to devinfo struct */
233 
234 	int		hubdi_flags;	/* flag options */
235 
236 } usba_hubdi_t;
237 
238 
239 /*
240  * usba_get_mfg_prod_sn_str:
241  *	Return a string containing mfg, product, serial number strings.
242  *	Remove duplicates if some strings are the same.
243  */
244 char	*usba_get_mfg_prod_sn_str(dev_info_t *, char *, int);
245 
246 /* return value when user doesn't specify configuration index */
247 #define	USBA_DEV_CONFIG_INDEX_UNDEFINED	-1
248 
249 /*
250  * prototypes
251  */
252 void	usba_usba_initialization();
253 void	usba_usba_destroy();
254 
255 void	usba_usbai_register_initialization();
256 void	usba_usbai_register_destroy();
257 
258 void	usba_usbai_initialization();
259 void	usba_usbai_destroy();
260 
261 void	usba_hubdi_initialization();
262 void	usba_hubdi_destroy();
263 
264 void	usba_devdb_initialization();
265 void	usba_devdb_destroy();
266 
267 int	usba_is_root_hub(dev_info_t *dip);
268 
269 usba_device_t *usba_alloc_usba_device(dev_info_t *);
270 void	usba_free_usba_device(usba_device_t *usba_device_t);
271 void	usba_clear_data_toggle(usba_device_t *usba_device);
272 
273 void	usba_start_next_req(usba_pipe_handle_data_t *ph);
274 
275 int	usba_pipe_check_handle(usba_pipe_handle_data_t *);
276 int	usba_drain_cbs(usba_pipe_handle_data_t *, usb_cb_flags_t,
277 			usb_cr_t);
278 int	usba_pipe_setup_func_call(dev_info_t *,
279 			int (*sync_func)(dev_info_t *,
280 				usba_ph_impl_t *, usba_pipe_async_req_t *,
281 				usb_flags_t),
282 			usba_ph_impl_t *,
283 			usb_opaque_t,
284 			usb_flags_t,
285 			void (*cb)(usb_pipe_handle_t, usb_opaque_t,
286 			    int, usb_cb_flags_t),
287 			usb_opaque_t);
288 
289 
290 void	usba_pipe_new_state(usba_pipe_handle_data_t *, usb_pipe_state_t);
291 
292 
293 /*
294  * retrieve string descriptors for manufacturer, vendor and serial
295  * number
296  */
297 void usba_get_dev_string_descrs(dev_info_t *, usba_device_t *);
298 
299 /*
300  * Check if we are not in interrupt context and have
301  * USB_FLAGS_SLEEP flags set.
302  */
303 #define	USBA_CHECK_CONTEXT()	ASSERT(!(servicing_interrupt()))
304 
305 /*
306  * USBA module Masks
307  */
308 #define	DPRINT_MASK_USBA		0x00000001
309 #define	DPRINT_MASK_USBAI		0x00000002
310 #define	DPRINT_MASK_HUBDI		0x00000004
311 #define	DPRINT_MASK_HCDI		0x00000008
312 #define	DPRINT_MASK_HCDI_DUMPING	0x00000010
313 #define	DPRINT_MASK_HUBDI_DUMPING	0x00000020
314 #define	DPRINT_MASK_REGISTER		0x00000040
315 #define	DPRINT_MASK_DEVDB		0x00000080
316 #define	DPRINT_MASK_ALL 		0xFFFFFFFF
317 
318 typedef struct usba_log_handle_impl {
319 	dev_info_t	*lh_dip;
320 	char		*lh_name;
321 	uint_t		*lh_errlevel;
322 	uint_t		*lh_mask;
323 	uint_t		*lh_instance_filter;
324 	uint_t		lh_flags;
325 } usba_log_handle_impl_t;
326 
327 _NOTE(SCHEME_PROTECTS_DATA("USBA managed data", usba_log_handle_impl))
328 
329 /*
330  * Miscellaneous definitions.
331  */
332 
333 /* possible strlen of a USB driver's name */
334 #define	USBA_DRVNAME_LEN	40
335 
336 /* strings passed to usb_dprintfN() are this long */
337 #define	USBA_PRINT_BUF_LEN	256
338 
339 /*
340  * usba_set_node_name() sets a device info node name
341  * according to class, subclass, and protocol.
342  * a subclass == -1 or protocol == -1 is considered a "don't care".
343  */
344 #define	DONTCARE		((int16_t)-1)
345 #define	FLAG_INTERFACE_NODE	0
346 #define	FLAG_DEVICE_NODE	1
347 #define	FLAG_COMBINED_NODE	2
348 
349 typedef struct node_name_entry {
350 	int16_t class;
351 	int16_t subclass;
352 	int16_t protocol;
353 	char	*name;
354 } node_name_entry_t;
355 
356 
357 /*
358  * USB enumeration statistics support
359  */
360 
361 /* Flags telling which stats usba_update_hotplug_stats should update */
362 #define	USBA_TOTAL_HOTPLUG_SUCCESS	0x01
363 #define	USBA_HOTPLUG_SUCCESS		0x02
364 #define	USBA_TOTAL_HOTPLUG_FAILURE	0x04
365 #define	USBA_HOTPLUG_FAILURE		0x08
366 
367 /*
368  * Increment enumeration stats indicated by the flags
369  */
370 void	usba_update_hotplug_stats(dev_info_t *, usb_flags_t);
371 
372 /* Retrieve the current enumeration hotplug statistics */
373 void	usba_get_hotplug_stats(dev_info_t *,
374 		ulong_t	*, ulong_t *, ulong_t *,
375 		ulong_t	*, uchar_t *);
376 
377 /* Reset the resetable hotplug stats */
378 void	usba_reset_hotplug_stats(dev_info_t *);
379 
380 
381 extern usb_log_handle_t usbai_log_handle;
382 extern	kmutex_t usbai_mutex;
383 
384 void	usba_req_normal_cb(usba_req_wrapper_t *);
385 void	usba_req_exc_cb(usba_req_wrapper_t *, usb_cr_t, usb_cb_flags_t);
386 void	usba_do_req_exc_cb(usba_req_wrapper_t *, usb_cr_t,
387 						usb_cb_flags_t);
388 void	usba_req_set_cb_flags(usba_req_wrapper_t *, usb_cb_flags_t);
389 
390 /*
391  * Creating/Destroying children (root hub, and hub children)
392  */
393 int	usba_create_child_devi(dev_info_t *, char *, usba_hcdi_ops_t *,
394 		dev_info_t *, usb_port_status_t,
395 		usba_device_t *, dev_info_t **);
396 
397 int	usba_destroy_child_devi(dev_info_t *, uint_t);
398 
399 /* utility function to map rval to a meaningful cr */
400 usb_cr_t usba_rval2cr(int);
401 
402 /* various conversion functions */
403 usb_pipe_handle_t	usba_get_dflt_pipe_handle(dev_info_t *);
404 dev_info_t		*usba_get_dip(usb_pipe_handle_t);
405 usb_pipe_handle_t	usba_usbdev_to_dflt_pipe_handle(usba_device_t *);
406 usb_pipe_handle_t	usba_get_pipe_handle(usba_pipe_handle_data_t *);
407 usba_pipe_handle_data_t *usba_get_ph_data(usb_pipe_handle_t);
408 usb_pipe_state_t	usba_get_ph_state(usba_pipe_handle_data_t *);
409 int			usba_get_ph_ref_count(usba_pipe_handle_data_t *);
410 
411 /* increment and decrement ref_count */
412 usba_pipe_handle_data_t *usba_hold_ph_data(usb_pipe_handle_t);
413 void			usba_release_ph_data(usba_ph_impl_t *);
414 
415 /* close all pipe and mark them persistent */
416 void			usba_persistent_pipe_close(usba_device_t *);
417 
418 /* reopen pipes that are marked persistent */
419 int			usba_persistent_pipe_open(usba_device_t *);
420 
421 /* check for leaks in hubd and usb_mid */
422 void	usba_check_for_leaks(usba_device_t *);
423 
424 /* free request wrappers */
425 void	usba_req_wrapper_free(usba_req_wrapper_t *);
426 
427 #ifdef __cplusplus
428 }
429 #endif
430 
431 #endif /* _SYS_USB_USBA_USBA_IMPL_H */
432