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