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