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