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