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