1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2019 Nexenta by DDN, Inc. All rights reserved. 14 * Copyright 2022 RackTop Systems, Inc. 15 */ 16 17 #ifndef _VIOSCSI_H_ 18 #define _VIOSCSI_H_ 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 #include <sys/types.h> 25 #include <sys/atomic.h> 26 #include <sys/kmem.h> 27 #include <sys/conf.h> 28 #include <sys/devops.h> 29 #include <sys/ksynch.h> 30 #include <sys/modctl.h> 31 #include <sys/debug.h> 32 #include <sys/list.h> 33 #include <sys/stddef.h> 34 35 #include <sys/scsi/scsi.h> 36 #include <sys/ddi.h> 37 #include <sys/sunddi.h> 38 39 #include <virtio.h> 40 41 #define VIRTIO_SCSI_CDB_SIZE 32 42 #define VIRTIO_SCSI_SENSE_SIZE 96 43 44 /* 45 * Feature bits: 46 */ 47 #define VIRTIO_SCSI_F_INOUT (0x1 << 0) 48 #define VIRTIO_SCSI_F_HOTPLUG (0x1 << 1) 49 #define VIRTIO_SCSI_F_CHANGE (0x1 << 2) 50 #define VIRTIO_SCSI_F_T10_PI (0x1 << 3) 51 52 /* 53 * Register offset in bytes: 54 */ 55 #define VIRTIO_SCSI_CFG_NUM_QUEUES 0 56 #define VIRTIO_SCSI_CFG_SEG_MAX 4 57 #define VIRTIO_SCSI_CFG_MAX_SECTORS 8 58 #define VIRTIO_SCSI_CFG_CMD_PER_LUN 12 59 #define VIRTIO_SCSI_CFG_EVI_SIZE 16 60 #define VIRTIO_SCSI_CFG_SENSE_SIZE 20 61 #define VIRTIO_SCSI_CFG_CDB_SIZE 24 62 #define VIRTIO_SCSI_CFG_MAX_CHANNEL 28 63 #define VIRTIO_SCSI_CFG_MAX_TARGET 30 64 #define VIRTIO_SCSI_CFG_MAX_LUN 32 65 66 /* 67 * Response codes: 68 */ 69 #define VIRTIO_SCSI_S_OK 0 70 #define VIRTIO_SCSI_S_FUNCTION_COMPLETED 0 71 #define VIRTIO_SCSI_S_OVERRUN 1 72 #define VIRTIO_SCSI_S_ABORTED 2 73 #define VIRTIO_SCSI_S_BAD_TARGET 3 74 #define VIRTIO_SCSI_S_RESET 4 75 #define VIRTIO_SCSI_S_BUSY 5 76 #define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6 77 #define VIRTIO_SCSI_S_TARGET_FAILURE 7 78 #define VIRTIO_SCSI_S_NEXUS_FAILURE 8 79 #define VIRTIO_SCSI_S_FAILURE 9 80 #define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10 81 #define VIRTIO_SCSI_S_FUNCTION_REJECTED 11 82 #define VIRTIO_SCSI_S_INCORRECT_LUN 12 83 84 /* 85 * Control queue type codes: 86 */ 87 #define VIRTIO_SCSI_T_TMF 0 88 #define VIRTIO_SCSI_T_AN_QUERY 1 89 #define VIRTIO_SCSI_T_AN_SUBSCRIBE 2 90 91 /* 92 * Task management codes: 93 */ 94 #define VIRTIO_SCSI_T_TMF_ABORT_TASK 0 95 #define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1 96 #define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2 97 #define VIRTIO_SCSI_T_TMF_CLEAR_ACA_TASK_SET 3 98 #define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4 99 #define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5 100 #define VIRTIO_SCSI_T_TMF_QUERY_TASK 6 101 #define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7 102 103 /* 104 * Events: 105 */ 106 #define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000 107 #define VIRTIO_SCSI_T_NO_EVENT 0 108 #define VIRTIO_SCSI_T_TRANSPORT_RESET 1 109 #define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 110 111 /* 112 * Task attributes: 113 */ 114 #define VIRTIO_SCSI_S_SIMPLE 0 115 #define VIRTIO_SCSI_S_ORDERED 1 116 #define VIRTIO_SCSI_S_HEAD 2 117 #define VIRTIO_SCSI_S_ACA 3 118 119 /* 120 * Reasons of reset event: 121 */ 122 #define VIRTIO_SCSI_EVT_RESET_HARD 0 123 #define VIRTIO_SCSI_EVT_RESET_RESCAN 1 124 #define VIRTIO_SCSI_EVT_RESET_REMOVED 2 125 126 /* 127 * We need to support INOUT, and we want hotplug notifications: 128 */ 129 #define VIOSCSI_WANTED_FEATURES (VIRTIO_SCSI_F_INOUT | VIRTIO_SCSI_F_HOTPLUG) 130 131 #define VIOSCSI_MAX_TARGET 256 132 #define VIOSCSI_MIN_SEGS 3 133 #define VIOSCSI_NUM_EVENTS 16 134 135 /* 136 * Data structures: 137 */ 138 139 #pragma pack(1) 140 141 /* 142 * virtio SCSI command request: 143 */ 144 struct virtio_scsi_cmd_req { 145 uint8_t lun[8]; 146 uint64_t tag; 147 uint8_t task_attr; 148 uint8_t prio; 149 uint8_t crn; 150 uint8_t cdb[VIRTIO_SCSI_CDB_SIZE]; 151 }; 152 153 /* 154 * Virtio SCSI response: 155 */ 156 struct virtio_scsi_cmd_resp { 157 uint32_t sense_len; 158 uint32_t res_id; 159 uint16_t status_qualifier; 160 uint8_t status; 161 uint8_t response; 162 uint8_t sense[VIRTIO_SCSI_SENSE_SIZE]; 163 }; 164 165 /* 166 * Task management request: 167 */ 168 struct virtio_scsi_ctrl_tmf_req { 169 uint32_t type; 170 uint32_t subtype; 171 uint8_t lun[8]; 172 uint64_t tag; 173 }; 174 175 /* 176 * Task management response: 177 */ 178 struct virtio_scsi_ctrl_tmf_resp { 179 uint8_t response; 180 }; 181 182 /* 183 * Asynchronous notification request: 184 */ 185 struct virtio_scsi_ctrl_an_req { 186 uint32_t type; 187 uint8_t lun[8]; 188 uint32_t event_requested; 189 }; 190 191 /* 192 * Asynchronous notification response: 193 */ 194 struct virtio_scsi_ctrl_an_resp { 195 uint32_t event_actual; 196 uint8_t response; 197 }; 198 199 /* 200 * Events delivered on the event queue: 201 */ 202 struct virtio_scsi_event { 203 uint32_t event; 204 uint8_t lun[8]; 205 uint32_t reason; 206 }; 207 208 #pragma pack() 209 210 typedef union { 211 struct virtio_scsi_cmd_req cmd; 212 struct virtio_scsi_ctrl_tmf_req tmf; 213 struct virtio_scsi_ctrl_an_req anr; 214 } vioscsi_req_t; 215 216 typedef union { 217 struct virtio_scsi_cmd_resp cmd; 218 struct virtio_scsi_ctrl_tmf_resp tmf; 219 struct virtio_scsi_ctrl_an_resp anr; 220 } vioscsi_res_t; 221 222 struct virtio_scsi_op { 223 vioscsi_req_t req; 224 vioscsi_res_t res; 225 }; 226 227 #define VIOSCSI_REQ_OFFSET offsetof(struct virtio_scsi_op, req) 228 #define VIOSCSI_RES_OFFSET offsetof(struct virtio_scsi_op, res) 229 230 typedef struct vioscsi_request vioscsi_request_t; 231 typedef struct vioscsi_event vioscsi_event_t; 232 typedef struct vioscsi_softc vioscsi_softc_t; 233 typedef struct vioscsi_dev vioscsi_dev_t; 234 typedef struct virtio_scsi_event vioscsi_evt_t; 235 typedef struct virtio_scsi_ctrl_tmf_req vioscsi_tmf_req_t; 236 typedef struct virtio_scsi_ctrl_tmf_resp vioscsi_tmf_res_t; 237 typedef struct virtio_scsi_cmd_req vioscsi_cmd_req_t; 238 typedef struct virtio_scsi_cmd_resp vioscsi_cmd_res_t; 239 typedef struct virtio_scsi_op vioscsi_op_t; 240 241 struct vioscsi_request { 242 list_node_t vr_node; 243 struct scsi_pkt *vr_pkt; 244 virtio_queue_t *vr_vq; 245 virtio_dma_t *vr_dma; 246 virtio_chain_t *vr_vic; 247 vioscsi_dev_t *vr_dev; 248 vioscsi_req_t *vr_req; 249 vioscsi_res_t *vr_res; 250 uint64_t vr_req_pa; 251 uint64_t vr_res_pa; 252 boolean_t vr_poll; 253 uint8_t vr_expired; /* access using atomics */ 254 uint8_t vr_done; /* access using atomics */ 255 uint8_t vr_task_attr; 256 uint8_t vr_target; 257 uint16_t vr_lun; 258 clock_t vr_time; /* seconds */ 259 clock_t vr_start; /* ticks */ 260 clock_t vr_expire; /* ticks */ 261 }; 262 263 struct vioscsi_dev { 264 list_node_t vd_node; 265 uint8_t vd_target; 266 uint16_t vd_lun; 267 struct scsi_device *vd_sd; 268 vioscsi_softc_t *vd_sc; 269 int vd_num_cmd; 270 int vd_max_cmd; 271 boolean_t vd_rescan; 272 list_t vd_reqs; 273 timeout_id_t vd_timeout; 274 kmutex_t vd_lock; 275 }; 276 277 struct vioscsi_event { 278 virtio_chain_t *ve_vic; 279 virtio_dma_t *ve_dma; 280 vioscsi_evt_t *ve_evt; 281 }; 282 283 struct vioscsi_softc { 284 dev_info_t *vs_dip; 285 virtio_t *vs_virtio; 286 uint64_t vs_features; 287 288 virtio_queue_t *vs_ctl_vq; 289 virtio_queue_t *vs_evt_vq; 290 virtio_queue_t *vs_cmd_vq; 291 292 scsi_hba_tran_t *vs_tran; 293 scsi_hba_tgtmap_t *vs_tgtmap; 294 ddi_taskq_t *vs_tq; 295 296 uint32_t vs_max_target; 297 uint32_t vs_max_lun; 298 uint32_t vs_cdb_size; 299 uint32_t vs_max_seg; 300 uint32_t vs_cmd_per_lun; 301 302 vioscsi_event_t vs_events[VIOSCSI_NUM_EVENTS]; 303 304 void *vs_intr_pri; 305 kmutex_t vs_lock; 306 list_t vs_devs; 307 }; 308 309 #ifdef __cplusplus 310 } 311 #endif 312 313 #endif /* _VIOSCSI_H_ */ 314