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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _SYS_USB_USBSER_KEYSPAN_VAR_H
27 #define	_SYS_USB_USBSER_KEYSPAN_VAR_H
28 
29 
30 /*
31  * keyspan implementation definitions
32  */
33 
34 #include <sys/types.h>
35 #include <sys/dditypes.h>
36 #include <sys/note.h>
37 
38 #include <sys/usb/clients/usbser/usbser_dsdi.h>
39 
40 #include <sys/usb/clients/usbser/usbser_keyspan/usa90msg.h>
41 #include <sys/usb/clients/usbser/usbser_keyspan/usa49msg.h>
42 
43 #ifdef	__cplusplus
44 extern "C" {
45 #endif
46 
47 /* product id */
48 #define	KEYSPAN_USA19HS_PID		0x121
49 #define	KEYSPAN_USA49WLC_PID		0x12a
50 #define	KEYSPAN_USA49WG_PID		0x131
51 
52 #define	KEYSPAN_MAX_PORT_NUM		4
53 
54 /*
55  * forward typedefs needed to resolve recursive header dependencies
56  */
57 typedef struct keyspan_pre_state keyspan_pre_state_t;
58 typedef struct keyspan_state keyspan_state_t;
59 typedef struct keyspan_port keyspan_port_t;
60 
61 #include <sys/usb/clients/usbser/usbser_keyspan/keyspan_pipe.h>
62 
63 /*
64  * temporary soft state for pre_attach
65  */
66 struct keyspan_pre_state {
67 	dev_info_t		*kb_dip;	/* device info */
68 	int			kb_instance;	/* instance */
69 	usb_client_dev_data_t	*kb_dev_data;	/* registration data */
70 	usb_log_handle_t	kb_lh;		/* USBA log handle */
71 	keyspan_pipe_t		kb_def_pipe;	/* default pipe */
72 };
73 
74 /* Firmware structure */
75 typedef struct usbser_keyspan_fw_record {
76 	uint16_t address;
77 	uint8_t data_len;
78 	uint8_t data[64];
79 } usbser_keyspan_fw_record_t;
80 
81 #define	ezusb_hex_record usbser_keyspan_fw_record
82 
83 /*
84  * PM support
85  */
86 typedef struct keyspan_power {
87 	uint8_t		pm_wakeup_enabled;	/* remote wakeup enabled */
88 	uint8_t		pm_pwr_states;	/* bit mask of power states */
89 	boolean_t	pm_raise_power;	/* driver is about to raise power */
90 	uint8_t		pm_cur_power;	/* current power level */
91 	uint_t		pm_busy_cnt;	/* number of set_busy requests */
92 } keyspan_pm_t;
93 
94 /*
95  * device specific info structure
96  */
97 typedef struct keyspan_dev_spec {
98 
99 	uint16_t	id_product;	/* product ID value */
100 	uint8_t		port_cnt;	/* How many ports on the device */
101 	uint8_t	ctrl_ep_addr;	/* Endpoint used to control the device */
102 	uint8_t	stat_ep_addr;	/* Endpoint used to get device status */
103 	uint8_t	dataout_ep_addr[4];	/* Endpoint used to send data */
104 
105 	/* Endpoint used to get data from device */
106 	uint8_t	datain_ep_addr[4];
107 } keyspan_dev_spec_t;
108 
109 /*
110  * To support different keyspan adapters, use union type
111  * for different cmd msg format.
112  */
113 typedef union keyspan_port_ctrl_msg {
114 	keyspan_usa19hs_port_ctrl_msg_t	usa19hs;
115 	keyspan_usa49_port_ctrl_msg_t usa49;
116 } keyspan_port_ctrl_msg_t;
117 
118 /*
119  * To support different keyspan adapters, use union type
120  * for different status msg format.
121  */
122 typedef union keyspan_port_status_msg {
123 	keyspan_usa19hs_port_status_msg_t	usa19hs;
124 	keyspan_usa49_port_status_msg_t usa49;
125 } keyspan_port_status_msg_t;
126 
127 /*
128  * per device state structure
129  */
130 struct keyspan_state {
131 	kmutex_t		ks_mutex;	/* structure lock */
132 	dev_info_t		*ks_dip;	/* device info */
133 	keyspan_port_t		*ks_ports;	/* per port structs */
134 	keyspan_dev_spec_t	ks_dev_spec;	/* device specific info */
135 
136 	/*
137 	 * we use semaphore to serialize pipe open/close by different ports.
138 	 * mutex could be used too, but it causes trouble when warlocking
139 	 * with USBA: some functions inside usb_pipe_close() wait on cv
140 	 *
141 	 * since semaphore is only used for serialization during
142 	 * open/close and suspend/resume, there is no deadlock hazard
143 	 */
144 	ksema_t			ks_pipes_sema;
145 
146 	/*
147 	 * USBA related
148 	 */
149 	usb_client_dev_data_t	*ks_dev_data;	/* registration data */
150 	usb_event_t		*ks_usb_events;	/* usb events */
151 
152 	keyspan_pipe_t		ks_def_pipe;	/* default pipe */
153 
154 	/* bulk in pipe for getting device status */
155 	keyspan_pipe_t		ks_statin_pipe;
156 
157 	/* bulk out pipe for sending control cmd to device */
158 	keyspan_pipe_t		ks_ctrlout_pipe;
159 
160 	usb_log_handle_t	ks_lh;		/* USBA log handle */
161 	int			ks_dev_state;	/* USB device state */
162 	keyspan_pm_t		*ks_pm;		/* PM support */
163 
164 	/*
165 	 * The following only used on USA_49WG
166 	 */
167 	/* Shared bulk in pipe handle */
168 	usb_pipe_handle_t	ks_datain_pipe_handle;
169 
170 	/* counter for opened bulk in pipe */
171 	uint8_t			ks_datain_open_cnt;
172 
173 	/* Flag for device reconnect */
174 	uint8_t			ks_reconnect_flag;
175 
176 };
177 
178 _NOTE(MUTEX_PROTECTS_DATA(keyspan_state::ks_mutex, keyspan_state))
179 _NOTE(DATA_READABLE_WITHOUT_LOCK(keyspan_state::{
180 	ks_dip
181 	ks_dev_data
182 	ks_usb_events
183 	ks_dev_spec
184 	ks_ports
185 	ks_def_pipe
186 	ks_ctrlout_pipe.pipe_handle
187 	ks_statin_pipe.pipe_handle
188 	ks_lh
189 	ks_pm
190 }))
191 
192 /*
193  * per port structure
194  */
195 struct keyspan_port {
196 	kmutex_t	kp_mutex;	/* structure lock */
197 	keyspan_state_t	*kp_ksp;	/* back pointer to the state */
198 	char		kp_lh_name[16];	/* log handle name */
199 	usb_log_handle_t kp_lh;		/* log handle */
200 	uint_t		kp_port_num;	/* port number */
201 	int		kp_state;	/* port state */
202 	int		kp_flags;	/* port flags */
203 	ds_cb_t		kp_cb;		/* DSD callbacks */
204 	kcondvar_t	kp_tx_cv;	/* cv to wait for tx completion */
205 	/*
206 	 * data receipt and transmit
207 	 */
208 	mblk_t		*kp_rx_mp;	/* received data */
209 	mblk_t		*kp_tx_mp;	/* data to transmit */
210 	boolean_t	kp_no_more_reads; /* disable reads */
211 
212 	/* The control cmd sent to the port */
213 	keyspan_port_ctrl_msg_t	kp_ctrl_msg;
214 
215 	/* status msg of the port */
216 	keyspan_port_status_msg_t	kp_status_msg;
217 
218 	uint_t kp_baud;	/* the current baud speed code */
219 	uint8_t	kp_lcr;	/* the current lcr value */
220 	/*
221 	 * the current port status, including: rts, dtr,
222 	 * break, loopback, enable.
223 	 */
224 	uint8_t	kp_status_flag;
225 
226 	keyspan_pipe_t		kp_datain_pipe;	/* bulk in data pipe */
227 	keyspan_pipe_t		kp_dataout_pipe; /* bulk out data pipe */
228 
229 	uint_t		kp_read_len;	/* max length of bulkin request */
230 	uint_t		kp_write_len;	/* max length of bulkout request */
231 };
232 
233 _NOTE(MUTEX_PROTECTS_DATA(keyspan_port::kp_mutex, keyspan_port))
234 _NOTE(DATA_READABLE_WITHOUT_LOCK(keyspan_port::{
235 	kp_ksp
236 	kp_lh
237 	kp_port_num
238 	kp_read_len
239 	kp_write_len
240 	kp_cb
241 	kp_datain_pipe.pipe_handle
242 	kp_datain_pipe.pipe_ep_descr
243 }))
244 
245 /* lock relationships */
246 _NOTE(LOCK_ORDER(keyspan_state::ks_mutex keyspan_port::kp_mutex))
247 _NOTE(LOCK_ORDER(keyspan_port::kp_mutex keyspan_pipe::pipe_mutex))
248 
249 /* port status flags */
250 enum {
251 	KEYSPAN_PORT_ENABLE = 0x0001,		/* port is enabled */
252 	KEYSPAN_PORT_RTS = 0x0002,		/* port's rts is set */
253 	KEYSPAN_PORT_DTR = 0x0004,		/* port's dtr is set */
254 	KEYSPAN_PORT_TXBREAK = 0x0008,		/* port is in TX break mod */
255 	KEYSPAN_PORT_LOOPBACK = 0x0010,		/* port is in loopback mod */
256 
257 	/* the ctrl cmd sent to this port is responded */
258 	KEYSPAN_PORT_CTRLRESP = 0x0020,
259 	KEYSPAN_PORT_RXBREAK = 0x0040		/* port is in RX break mod */
260 };
261 
262 /* port state */
263 enum {
264 	KEYSPAN_PORT_NOT_INIT = 0,	/* port is not initialized */
265 	KEYSPAN_PORT_CLOSED,		/* port is closed */
266 	KEYSPAN_PORT_OPENING,		/* port is being opened */
267 	KEYSPAN_PORT_OPEN		/* port is open */
268 };
269 
270 /* port flags */
271 enum {
272 	KEYSPAN_PORT_TX_STOPPED	= 0x0001	/* transmit not allowed */
273 };
274 
275 /* various tunables */
276 enum {
277 	KEYSPAN_BULK_TIMEOUT		= 3,	/* transfer timeout */
278 	KEYSPAN_BULKIN_MAX_LEN		= 64,	/* bulk in max length */
279 	KEYSPAN_BULKIN_MAX_LEN_49WG	= 512,	/* bulk in max length */
280 	/*
281 	 * From keyspan spec, USA49WLC max packet length for bulk out transfer
282 	 * is 64, the format is [status byte][up to 63 data bytes], so the
283 	 * max data length per transfer is 63 bytes, USA19HS doesn't need
284 	 * extra status byte. USA49WG max packet length for bulk out transfer
285 	 * is 512, the format is [status byte][63 data bytes]...[status byte]
286 	 * [up to 63 data bytes], so the max data length per transfer is 504
287 	 * bytes, while the port0 use intr out pipe send data, the packet
288 	 * format is the same as USA49WLC, so the max data length for USA49WG
289 	 * port0 is 63 bytes.
290 	 */
291 	KEYSPAN_BULKOUT_MAX_LEN_19HS	= 64,	/* for 19HS only */
292 	KEYSPAN_BULKOUT_MAX_LEN_49WLC	= 63,	/* for 49WLC and 49WG port0 */
293 	KEYSPAN_BULKOUT_MAX_LEN_49WG	= 504,	/* for 49WG other ports */
294 	KEYSPAN_STATIN_MAX_LEN		= 16	/* status in max length */
295 };
296 
297 /* This flag indicates if the firmware already downloaded to the device */
298 #define	KEYSPAN_FW_FLAG 0x8000
299 
300 /* Vendor specific ctrl req, used to set/download bytes in the device memory */
301 #define	KEYSPAN_REQ_SET 0xa0
302 /* Vendor specific ctrl req, used to send ctrl command for USA_49WG model */
303 #define	KEYSPAN_SET_CONTROL_REQUEST	0xB0
304 
305 /*
306  * debug printing masks
307  */
308 #define	DPRINT_ATTACH		0x00000001
309 #define	DPRINT_OPEN		0x00000002
310 #define	DPRINT_CLOSE		0x00000004
311 #define	DPRINT_DEF_PIPE		0x00000010
312 #define	DPRINT_IN_PIPE		0x00000020
313 #define	DPRINT_OUT_PIPE		0x00000040
314 #define	DPRINT_INTR_PIPE	0x00000080
315 #define	DPRINT_PIPE_RESET	0x00000100
316 #define	DPRINT_IN_DATA		0x00000200
317 #define	DPRINT_OUT_DATA		0x00000400
318 #define	DPRINT_CTLOP		0x00000800
319 #define	DPRINT_HOTPLUG		0x00001000
320 #define	DPRINT_PM		0x00002000
321 #define	DPRINT_MASK_ALL		0xFFFFFFFF
322 
323 /*
324  * misc macros
325  */
326 #define	NELEM(a)	(sizeof (a) / sizeof (*(a)))
327 
328 /* common DSD functions */
329 int	keyspan_tx_copy_data(keyspan_port_t *, mblk_t *, int);
330 void	keyspan_tx_start(keyspan_port_t *, int *);
331 void	keyspan_put_tail(mblk_t **, mblk_t *);
332 void	keyspan_put_head(mblk_t **, mblk_t *, keyspan_port_t *);
333 
334 void	keyspan_bulkin_cb(usb_pipe_handle_t, usb_bulk_req_t *);
335 void	keyspan_bulkout_cb(usb_pipe_handle_t, usb_bulk_req_t *);
336 
337 int	keyspan_restore_device(keyspan_state_t *);
338 int	keyspan_send_cmd(keyspan_port_t *);
339 
340 int	keyspan_dev_is_online(keyspan_state_t *);
341 
342 
343 #ifdef	__cplusplus
344 }
345 #endif
346 
347 #endif	/* _SYS_USB_USBSER_KEYSPAN_VAR_H */
348