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         ddi_taskq_t             *s_taskq;       /* common taskq for all luns */
 189         boolean_t               s_symbios;      /* need Symbios workaround? */
 190         boolean_t               s_disconnect_warned; /* disconnect warning */
 191         size_t                  s_totalsec;     /* total sectors */
 192         size_t                  s_secsz;        /* sector size */
 193         scsa1394_inst_stat_t    s_stat;         /* statistics */
 194 } scsa1394_state_t;
 195 
 196 _NOTE(MUTEX_PROTECTS_DATA(scsa1394_state::s_mutex, scsa1394_state))
 197 _NOTE(SCHEME_PROTECTS_DATA("stable data", scsa1394_state::{
 198     s_dip s_instance s_t1394_hdl s_attachinfo s_reset_cb_id s_remove_cb_id
 199     s_insert_cb_id s_buf_dma_attr s_pt_dma_attr s_tran s_tgt s_cfgrom
 200     s_nluns s_lun s_cmd_cache s_taskq s_symbios s_targetinfo
 201     s_totalsec s_secsz}))
 202 _NOTE(SCHEME_PROTECTS_DATA("statistics", scsa1394_state::s_stat))
 203 
 204 _NOTE(LOCK_ORDER(scsa1394_state::s_mutex scsa1394_lun::l_mutex))
 205 
 206 /* for sbp2_bus_buf.bb_hdl */
 207 typedef struct scsa1394_bus_buf {
 208         scsa1394_state_t        *sbb_state;     /* soft state */
 209         t1394_addr_handle_t     sbb_addr_hdl;   /* 1394 address handle */
 210         ddi_dma_handle_t        sbb_dma_hdl;    /* DMA handle */
 211         ddi_acc_handle_t        sbb_acc_hdl;    /* access handle */
 212 } scsa1394_bus_buf_t;
 213 
 214 _NOTE(SCHEME_PROTECTS_DATA("unique per task", scsa1394_bus_buf))
 215 _NOTE(SCHEME_PROTECTS_DATA("dev_info::devi_lock", dev_info::devi_state))
 216 
 217 /* various translation macros */
 218 #define ADDR2TRAN(ap)   ((ap)->a_hba_tran)
 219 #define TRAN2STATE(hba) ((scsa1394_state_t *)(hba)->tran_hba_private)
 220 #define ADDR2STATE(ap)  (TRAN2STATE(ADDR2TRAN(ap)))
 221 
 222 #define SCSA1394_NODEID(sp)     ((sp)->s_attachinfo.localinfo.local_nodeID)
 223 #define SCSA1394_BUSGEN(sp)     ((sp)->s_attachinfo.localinfo.bus_generation)
 224 
 225 #define SCSA1394_ORB_SIZE_ROUNDUP(sp, sz) SBP2_ORB_SIZE_ROUNDUP(sp->s_tgt, sz)
 226 #define SCSA1394_ADDR_SET(sp, var, addr) \
 227     SBP2_ADDR_SET(var, addr, SCSA1394_NODEID(sp))
 228 
 229 /* macros to calculate LBA for 6/10/12-byte commands */
 230 #define SCSA1394_LBA_6BYTE(pkt)                                         \
 231         (((pkt)->pkt_cdbp[1] & 0x1f) << 16) +                              \
 232         ((pkt)->pkt_cdbp[2] << 8) + (pkt)->pkt_cdbp[3]
 233 #define SCSA1394_LEN_6BYTE(pkt)                                         \
 234         (pkt)->pkt_cdbp[4]
 235 
 236 #define SCSA1394_LEN_10BYTE(pkt)                                        \
 237         ((pkt)->pkt_cdbp[7] << 8) + (pkt)->pkt_cdbp[8]
 238 #define SCSA1394_LBA_10BYTE(pkt)                                        \
 239         ((pkt)->pkt_cdbp[2] << 24) + ((pkt)->pkt_cdbp[3] << 16) +     \
 240         ((pkt)->pkt_cdbp[4] << 8) +  (pkt)->pkt_cdbp[5]
 241 
 242 #define SCSA1394_LEN_12BYTE(pkt)                                        \
 243         ((pkt)->pkt_cdbp[6] << 24) + ((pkt)->pkt_cdbp[7] << 16) +     \
 244         ((pkt)->pkt_cdbp[8] << 8) +  (pkt)->pkt_cdbp[9]
 245 #define SCSA1394_LBA_12BYTE(pkt)                                        \
 246         ((pkt)->pkt_cdbp[2] << 24) + ((pkt)->pkt_cdbp[3] << 16) +     \
 247         ((pkt)->pkt_cdbp[4] << 8) +  (pkt)->pkt_cdbp[5]
 248 
 249 /* macro to calculate LEN for SCMD_READ_CD command */
 250 #define SCSA1394_LEN_READ_CD(pkt)                                       \
 251         (((pkt)->pkt_cdbp[6] << 16) + ((pkt)->pkt_cdbp[7] << 8) +     \
 252         (pkt)->pkt_cdbp[8])
 253 
 254 /* calculate block size for CD-RW writes */
 255 #define SCSA1394_CDRW_BLKSZ(bcount, len)        ((bcount) / (len))
 256 #define SCSA1394_VALID_CDRW_BLKSZ(blksz)                                \
 257         (((blksz) == CDROM_BLK_2048) || ((blksz) == CDROM_BLK_2352) ||  \
 258         ((blksz) == CDROM_BLK_2336) || ((blksz) == CDROM_BLK_2324))
 259 
 260 /* black/white list */
 261 typedef struct scsa1394_bw_list {
 262         int     vid_match;
 263         int     vid;
 264 } scsa1394_bw_list_t;
 265 
 266 /* match type */
 267 enum {
 268         SCSA1394_BW_ONE,
 269         SCSA1394_BW_ALL
 270 };
 271 
 272 #define NELEM(a)        (sizeof (a) / sizeof (*(a)))
 273 
 274 /* misc constants */
 275 enum {
 276         SCSA1394_COMPAT_MAX             = 1,    /* max @ of compatible names */
 277         SCSA1394_CLEANUP_LEVEL_MAX      = 256,
 278         SCSA1394_START_STOP_FAIL_MAX    = 3,    /* max start/stop failures */
 279         SCSA1394_MODE_SENSE_FAIL_MAX    = 3,    /* max mode sense failures */
 280         SCSA1394_START_STOP_TIMEOUT_MAX = 30,
 281         SCSA1394_MAPIN_SIZE_MAX         = 512,
 282         SCSA1394_PROBE_TIMEOUT          = 15,   /* in seconds */
 283 
 284         SCSA1394_DTYPE_RBC              = 0x0E
 285 };
 286 
 287 
 288 /* SBP-2 routines */
 289 int     scsa1394_sbp2_attach(scsa1394_state_t *);
 290 void    scsa1394_sbp2_detach(scsa1394_state_t *);
 291 void    scsa1394_sbp2_fake_inquiry(scsa1394_state_t *, struct scsi_inquiry *);
 292 int     scsa1394_sbp2_threads_init(scsa1394_state_t *);
 293 void    scsa1394_sbp2_threads_fini(scsa1394_state_t *);
 294 int     scsa1394_sbp2_get_lun_type(scsa1394_lun_t *);
 295 int     scsa1394_sbp2_login(scsa1394_state_t *, int);
 296 void    scsa1394_sbp2_logout(scsa1394_state_t *, int, boolean_t);
 297 void    scsa1394_sbp2_req(scsa1394_state_t *, int, int);
 298 void    scsa1394_sbp2_disconnect(scsa1394_state_t *);
 299 void    scsa1394_sbp2_seg2pt(scsa1394_lun_t *, scsa1394_cmd_t *);
 300 void    scsa1394_sbp2_cmd2orb(scsa1394_lun_t *, scsa1394_cmd_t *);
 301 int     scsa1394_sbp2_start(scsa1394_lun_t *, scsa1394_cmd_t *);
 302 void    scsa1394_sbp2_nudge(scsa1394_lun_t *);
 303 int     scsa1394_sbp2_reset(scsa1394_lun_t *, int, scsa1394_cmd_t *);
 304 void    scsa1394_sbp2_flush_cmds(scsa1394_lun_t *, int, int, int);
 305 
 306 
 307 /* HBA public routines */
 308 int     scsa1394_thr_dispatch(scsa1394_thread_t *);
 309 void    scsa1394_thr_cancel(scsa1394_thread_t *);
 310 void    scsa1394_thr_wake(scsa1394_thread_t *, int);
 311 void    scsa1394_thr_clear_req(scsa1394_thread_t *, int);
 312 void    scsa1394_cmd_status_proc(scsa1394_lun_t *, scsa1394_cmd_t *);
 313 boolean_t scsa1394_dev_is_online(scsa1394_state_t *);
 314 void    scsa1394_sbp2_req_bus_reset(scsa1394_lun_t *);
 315 void    scsa1394_sbp2_req_reconnect(scsa1394_lun_t *);
 316 
 317 
 318 #ifdef  __cplusplus
 319 }
 320 #endif
 321 
 322 #endif  /* _SYS_1394_TARGETS_SCSA1394_IMPL_H */