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_1394_TARGETS_SCSA1394_IMPL_H
27 #define	_SYS_1394_TARGETS_SCSA1394_IMPL_H
28 
29 /*
30  * scsa1394 definitions
31  */
32 
33 #include <sys/1394/t1394.h>
34 #include <sys/sbp2/driver.h>
35 #include <sys/scsi/scsi.h>
36 #include <sys/cdio.h>
37 #include <sys/1394/targets/scsa1394/cmd.h>
38 
39 #ifdef	__cplusplus
40 extern "C" {
41 #endif
42 
43 /*
44  * each lun uses a worker thread for various deferred processing
45  */
46 typedef enum {
47 	SCSA1394_THR_INIT,			/* initial state */
48 	SCSA1394_THR_RUN,			/* thread is running */
49 	SCSA1394_THR_EXIT			/* thread exited */
50 } scsa1394_thr_state_t;
51 
52 /* thread requests */
53 enum {
54 	SCSA1394_THREQ_EXIT		= 0x1,	/* thread has to exit */
55 	SCSA1394_THREQ_TASK_STATUS	= 0x2,	/* task status received */
56 	SCSA1394_THREQ_NUDGE		= 0x4,	/* nudge SBP-2 layer */
57 	SCSA1394_THREQ_BUS_RESET	= 0x8,
58 	SCSA1394_THREQ_DISCONNECT	= 0x10,
59 	SCSA1394_THREQ_RECONNECT	= 0x20
60 };
61 
62 typedef struct scsa1394_thread {
63 	void			(*thr_func)(void *);	/* function to be run */
64 	void			*thr_arg;	/* function argument */
65 	struct scsa1394_lun	*thr_lun;	/* lun we belong to */
66 	scsa1394_thr_state_t	thr_state;	/* state */
67 	kcondvar_t		thr_cv;		/* cv for request wait */
68 	int			thr_req;	/* request mask */
69 } scsa1394_thread_t;
70 
71 
72 /* 1394 device state */
73 typedef enum {
74 	SCSA1394_DEV_INIT		= 0,
75 	SCSA1394_DEV_ONLINE,
76 	SCSA1394_DEV_BUS_RESET,
77 	SCSA1394_DEV_DISCONNECTED,
78 	SCSA1394_DEV_PWRED_DOWN,
79 	SCSA1394_DEV_SUSPENDED
80 } scsa1394_dev_state_t;
81 
82 enum { SCSA1394_STAT_NCMD_LAST = 8 };
83 
84 /* per-lun statistics */
85 typedef struct scsa1394_lun_stat {
86 	/*
87 	 * ring buffer of the last N failed commands. stat_cmd_fail_last_idx
88 	 * is an index into stat_cmd_fail_last the array and points to the
89 	 * entry to be written next. The first 16 bytes are CDB bytes,
90 	 * the last 8 bytes are a timestamp (lbolt).
91 	 */
92 	uint64_t		stat_cmd_last_fail[SCSA1394_STAT_NCMD_LAST][3];
93 	int			stat_cmd_last_fail_idx;
94 
95 	uint_t			stat_cmd_cnt;	/* # of commands submitted */
96 	uint_t			stat_cmd_buf_max_nsegs;
97 	uint_t			stat_cmd_buf_dma_partial;
98 
99 	/*
100 	 * errors
101 	 */
102 	uint_t			stat_err_pkt_kmem_alloc;
103 	uint_t			stat_err_cmd_cdb_dmem_alloc;
104 	uint_t			stat_err_cmd_cdb_dbind;
105 	uint_t			stat_err_cmd_cdb_addr_alloc;
106 	uint_t			stat_err_cmd_buf_dbind;
107 	uint_t			stat_err_cmd_buf_addr_alloc;
108 	uint_t			stat_err_cmd_pt_kmem_alloc;
109 	uint_t			stat_err_cmd_pt_dmem_alloc;
110 	uint_t			stat_err_cmd_pt_addr_alloc;
111 	uint_t			stat_err_status_tran_err;
112 	uint_t			stat_err_status_conv;
113 	uint_t			stat_err_status_resp;
114 } scsa1394_lun_stat_t;
115 
116 /* logical unit */
117 typedef struct scsa1394_lun {
118 	kmutex_t		l_mutex;	/* structure lock */
119 	struct scsa1394_state	*l_sp;		/* soft state */
120 	sbp2_lun_t		*l_lun;		/* SBP2 lun */
121 	sbp2_ses_t		*l_ses;		/* login session */
122 	dev_info_t		*l_cdip;	/* child devinfo */
123 	scsa1394_thread_t	l_worker_thread; /* worker thread */
124 	ddi_softintr_t		l_softintr_id;	/* soft interrupt */
125 	boolean_t		l_softintr_triggered; /* trigger indicator */
126 	int			l_softintr_req;	/* soft intr request mask */
127 
128 	/* workarounds */
129 	int			l_lba_size;	/* LBA size */
130 	int			l_dtype_orig;	/* original DTYPE value */
131 	int			l_rmb_orig;	/* original RMB value */
132 	int			l_start_stop_fail_cnt; /* start/stop failures */
133 	boolean_t		l_start_stop_fake; /* fake start/stop unit */
134 	int			l_mode_sense_fail_cnt; /* mode sense failures */
135 	boolean_t		l_mode_sense_fake; /* fake mode sense command */
136 	boolean_t		l_nosup_tur;
137 	boolean_t		l_nosup_start_stop;
138 	boolean_t		l_nosup_inquiry;
139 
140 	struct scsi_inquiry	l_fake_inq;
141 
142 	scsa1394_lun_stat_t	l_stat;		/* statistics */
143 } scsa1394_lun_t;
144 
145 _NOTE(MUTEX_PROTECTS_DATA(scsa1394_lun::l_mutex, scsa1394_lun))
146 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsa1394_lun::{
147     l_sp l_lun l_ses l_cdip l_worker_thread l_softintr_id
148     l_nosup_tur l_nosup_start_stop l_nosup_inquiry }))
149 _NOTE(SCHEME_PROTECTS_DATA("statistics", scsa1394_lun::l_stat))
150 
151 /* l_softintr_req */
152 enum {
153 	SCSA1394_SOFTINTR_STATUS_RCVD	= 0x1,	/* task status received */
154 	SCSA1394_SOFTINTR_RECONNECT	= 0x2	/* perform reconnect */
155 };
156 
157 /* per-instance statistics */
158 typedef struct scsa1394_inst_stat {
159 	uint_t			stat_bus_reset_cnt;
160 	uint_t			stat_disconnect_cnt;
161 	uint_t			stat_reconnect_cnt;
162 	/*
163 	 * errors
164 	 */
165 } scsa1394_inst_stat_t;
166 
167 /* per-instance soft state structure */
168 typedef struct scsa1394_state {
169 	kmutex_t		s_mutex;	/* structure mutex */
170 	dev_info_t		*s_dip;		/* device information */
171 	int			s_instance;	/* instance number */
172 	scsa1394_dev_state_t	s_dev_state;	/* device state */
173 	t1394_handle_t		s_t1394_hdl;	/* 1394 handle */
174 	t1394_attachinfo_t	s_attachinfo;	/* 1394 attach info */
175 	t1394_targetinfo_t	s_targetinfo;	/* 1394 target info */
176 	ddi_callback_id_t	s_reset_cb_id;	/* reset event cb id */
177 	ddi_callback_id_t	s_remove_cb_id;	/* remove event cb id */
178 	ddi_callback_id_t	s_insert_cb_id;	/* insert event cb id */
179 	boolean_t		s_event_entered; /* event serialization */
180 	kcondvar_t		s_event_cv;	/* event serialization cv */
181 	ddi_dma_attr_t		s_buf_dma_attr;	/* data buffer DMA attrs */
182 	ddi_dma_attr_t		s_pt_dma_attr;	/* page table DMA attrs */
183 	scsi_hba_tran_t		*s_tran;	/* SCSA HBA tran structure */
184 	sbp2_tgt_t		*s_tgt;		/* SBP-2 target */
185 	sbp2_cfgrom_t		*s_cfgrom;	/* Config ROM */
186 	int			s_nluns;	/* # of logical units */
187 	scsa1394_lun_t		*s_lun;		/* logical units */
188 	kmem_cache_t		*s_cmd_cache;	/* command kmem cache */
189 	ddi_taskq_t		*s_taskq;	/* common taskq for all luns */
190 	boolean_t		s_symbios;	/* need Symbios workaround? */
191 	boolean_t		s_disconnect_warned; /* disconnect warning */
192 	size_t			s_totalsec;	/* total sectors */
193 	size_t			s_secsz;	/* sector size */
194 	scsa1394_inst_stat_t	s_stat;		/* statistics */
195 } scsa1394_state_t;
196 
197 _NOTE(MUTEX_PROTECTS_DATA(scsa1394_state::s_mutex, scsa1394_state))
198 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsa1394_state::{
199     s_dip s_instance s_t1394_hdl s_attachinfo s_reset_cb_id s_remove_cb_id
200     s_insert_cb_id s_buf_dma_attr s_pt_dma_attr s_tran s_tgt s_cfgrom
201     s_nluns s_lun s_cmd_cache s_taskq s_symbios s_targetinfo
202     s_totalsec s_secsz}))
203 _NOTE(SCHEME_PROTECTS_DATA("statistics", scsa1394_state::s_stat))
204 
205 _NOTE(LOCK_ORDER(scsa1394_state::s_mutex scsa1394_lun::l_mutex))
206 
207 /* for sbp2_bus_buf.bb_hdl */
208 typedef struct scsa1394_bus_buf {
209 	scsa1394_state_t	*sbb_state;	/* soft state */
210 	t1394_addr_handle_t	sbb_addr_hdl;	/* 1394 address handle */
211 	ddi_dma_handle_t	sbb_dma_hdl;	/* DMA handle */
212 	ddi_acc_handle_t	sbb_acc_hdl;	/* access handle */
213 } scsa1394_bus_buf_t;
214 
215 _NOTE(SCHEME_PROTECTS_DATA("unique per task", scsa1394_bus_buf))
216 _NOTE(SCHEME_PROTECTS_DATA("dev_info::devi_lock", dev_info::devi_state))
217 
218 /* various translation macros */
219 #define	ADDR2TRAN(ap)	((ap)->a_hba_tran)
220 #define	TRAN2STATE(hba)	((scsa1394_state_t *)(hba)->tran_hba_private)
221 #define	ADDR2STATE(ap)	(TRAN2STATE(ADDR2TRAN(ap)))
222 
223 #define	SCSA1394_NODEID(sp)	((sp)->s_attachinfo.localinfo.local_nodeID)
224 #define	SCSA1394_BUSGEN(sp)	((sp)->s_attachinfo.localinfo.bus_generation)
225 
226 #define	SCSA1394_ORB_SIZE_ROUNDUP(sp, sz) SBP2_ORB_SIZE_ROUNDUP(sp->s_tgt, sz)
227 #define	SCSA1394_ADDR_SET(sp, var, addr) \
228     SBP2_ADDR_SET(var, addr, SCSA1394_NODEID(sp))
229 
230 /* macros to calculate LBA for 6/10/12-byte commands */
231 #define	SCSA1394_LBA_6BYTE(pkt)						\
232 	(((pkt)->pkt_cdbp[1] & 0x1f) << 16) +				\
233 	((pkt)->pkt_cdbp[2] << 8) + (pkt)->pkt_cdbp[3]
234 #define	SCSA1394_LEN_6BYTE(pkt)						\
235 	(pkt)->pkt_cdbp[4]
236 
237 #define	SCSA1394_LEN_10BYTE(pkt)					\
238 	((pkt)->pkt_cdbp[7] << 8) + (pkt)->pkt_cdbp[8]
239 #define	SCSA1394_LBA_10BYTE(pkt)					\
240 	((pkt)->pkt_cdbp[2] << 24) + ((pkt)->pkt_cdbp[3] << 16) + 	\
241 	((pkt)->pkt_cdbp[4] << 8) +  (pkt)->pkt_cdbp[5]
242 
243 #define	SCSA1394_LEN_12BYTE(pkt)					\
244 	((pkt)->pkt_cdbp[6] << 24) + ((pkt)->pkt_cdbp[7] << 16) +	\
245 	((pkt)->pkt_cdbp[8] << 8) +  (pkt)->pkt_cdbp[9]
246 #define	SCSA1394_LBA_12BYTE(pkt)					\
247 	((pkt)->pkt_cdbp[2] << 24) + ((pkt)->pkt_cdbp[3] << 16) +	\
248 	((pkt)->pkt_cdbp[4] << 8) +  (pkt)->pkt_cdbp[5]
249 
250 /* macro to calculate LEN for SCMD_READ_CD command */
251 #define	SCSA1394_LEN_READ_CD(pkt)					\
252 	(((pkt)->pkt_cdbp[6] << 16) + ((pkt)->pkt_cdbp[7] << 8) +	\
253 	(pkt)->pkt_cdbp[8])
254 
255 /* calculate block size for CD-RW writes */
256 #define	SCSA1394_CDRW_BLKSZ(bcount, len)	((bcount) / (len))
257 #define	SCSA1394_VALID_CDRW_BLKSZ(blksz)				\
258 	(((blksz) == CDROM_BLK_2048) || ((blksz) == CDROM_BLK_2352) ||	\
259 	((blksz) == CDROM_BLK_2336) || ((blksz) == CDROM_BLK_2324))
260 
261 /* black/white list */
262 typedef struct scsa1394_bw_list {
263 	int	vid_match;
264 	int	vid;
265 } scsa1394_bw_list_t;
266 
267 /* match type */
268 enum {
269 	SCSA1394_BW_ONE,
270 	SCSA1394_BW_ALL
271 };
272 
273 #define	NELEM(a)	(sizeof (a) / sizeof (*(a)))
274 
275 /* misc constants */
276 enum {
277 	SCSA1394_COMPAT_MAX		= 1,	/* max @ of compatible names */
278 	SCSA1394_CLEANUP_LEVEL_MAX	= 256,
279 	SCSA1394_START_STOP_FAIL_MAX	= 3,	/* max start/stop failures */
280 	SCSA1394_MODE_SENSE_FAIL_MAX	= 3,	/* max mode sense failures */
281 	SCSA1394_START_STOP_TIMEOUT_MAX	= 30,
282 	SCSA1394_MAPIN_SIZE_MAX		= 512,
283 	SCSA1394_PROBE_TIMEOUT		= 15,	/* in seconds */
284 
285 	SCSA1394_DTYPE_RBC		= 0x0E
286 };
287 
288 
289 /* SBP-2 routines */
290 int	scsa1394_sbp2_attach(scsa1394_state_t *);
291 void	scsa1394_sbp2_detach(scsa1394_state_t *);
292 void	scsa1394_sbp2_fake_inquiry(scsa1394_state_t *, struct scsi_inquiry *);
293 int	scsa1394_sbp2_threads_init(scsa1394_state_t *);
294 void	scsa1394_sbp2_threads_fini(scsa1394_state_t *);
295 int	scsa1394_sbp2_get_lun_type(scsa1394_lun_t *);
296 int	scsa1394_sbp2_login(scsa1394_state_t *, int);
297 void	scsa1394_sbp2_logout(scsa1394_state_t *, int, boolean_t);
298 void	scsa1394_sbp2_req(scsa1394_state_t *, int, int);
299 void	scsa1394_sbp2_disconnect(scsa1394_state_t *);
300 void	scsa1394_sbp2_seg2pt(scsa1394_lun_t *, scsa1394_cmd_t *);
301 void	scsa1394_sbp2_cmd2orb(scsa1394_lun_t *, scsa1394_cmd_t *);
302 int	scsa1394_sbp2_start(scsa1394_lun_t *, scsa1394_cmd_t *);
303 void	scsa1394_sbp2_nudge(scsa1394_lun_t *);
304 int	scsa1394_sbp2_reset(scsa1394_lun_t *, int, scsa1394_cmd_t *);
305 void	scsa1394_sbp2_flush_cmds(scsa1394_lun_t *, int, int, int);
306 
307 
308 /* HBA public routines */
309 int	scsa1394_thr_dispatch(scsa1394_thread_t *);
310 void	scsa1394_thr_cancel(scsa1394_thread_t *);
311 void	scsa1394_thr_wake(scsa1394_thread_t *, int);
312 void	scsa1394_thr_clear_req(scsa1394_thread_t *, int);
313 void	scsa1394_cmd_status_proc(scsa1394_lun_t *, scsa1394_cmd_t *);
314 boolean_t scsa1394_dev_is_online(scsa1394_state_t *);
315 void	scsa1394_sbp2_req_bus_reset(scsa1394_lun_t *);
316 void	scsa1394_sbp2_req_reconnect(scsa1394_lun_t *);
317 
318 
319 #ifdef	__cplusplus
320 }
321 #endif
322 
323 #endif	/* _SYS_1394_TARGETS_SCSA1394_IMPL_H */
324