summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/vioscsi/vioscsi.h
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/vioscsi/vioscsi.h')
-rw-r--r--usr/src/uts/common/io/vioscsi/vioscsi.h313
1 files changed, 313 insertions, 0 deletions
diff --git a/usr/src/uts/common/io/vioscsi/vioscsi.h b/usr/src/uts/common/io/vioscsi/vioscsi.h
new file mode 100644
index 0000000000..b032ef28c8
--- /dev/null
+++ b/usr/src/uts/common/io/vioscsi/vioscsi.h
@@ -0,0 +1,313 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
+ * Copyright 2022 RackTop Systems, Inc.
+ */
+
+#ifndef _VIOSCSI_H_
+#define _VIOSCSI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/atomic.h>
+#include <sys/kmem.h>
+#include <sys/conf.h>
+#include <sys/devops.h>
+#include <sys/ksynch.h>
+#include <sys/modctl.h>
+#include <sys/debug.h>
+#include <sys/list.h>
+#include <sys/stddef.h>
+
+#include <sys/scsi/scsi.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+
+#include <virtio.h>
+
+#define VIRTIO_SCSI_CDB_SIZE 32
+#define VIRTIO_SCSI_SENSE_SIZE 96
+
+/*
+ * Feature bits:
+ */
+#define VIRTIO_SCSI_F_INOUT (0x1 << 0)
+#define VIRTIO_SCSI_F_HOTPLUG (0x1 << 1)
+#define VIRTIO_SCSI_F_CHANGE (0x1 << 2)
+#define VIRTIO_SCSI_F_T10_PI (0x1 << 3)
+
+/*
+ * Register offset in bytes:
+ */
+#define VIRTIO_SCSI_CFG_NUM_QUEUES 0
+#define VIRTIO_SCSI_CFG_SEG_MAX 4
+#define VIRTIO_SCSI_CFG_MAX_SECTORS 8
+#define VIRTIO_SCSI_CFG_CMD_PER_LUN 12
+#define VIRTIO_SCSI_CFG_EVI_SIZE 16
+#define VIRTIO_SCSI_CFG_SENSE_SIZE 20
+#define VIRTIO_SCSI_CFG_CDB_SIZE 24
+#define VIRTIO_SCSI_CFG_MAX_CHANNEL 28
+#define VIRTIO_SCSI_CFG_MAX_TARGET 30
+#define VIRTIO_SCSI_CFG_MAX_LUN 32
+
+/*
+ * Response codes:
+ */
+#define VIRTIO_SCSI_S_OK 0
+#define VIRTIO_SCSI_S_FUNCTION_COMPLETED 0
+#define VIRTIO_SCSI_S_OVERRUN 1
+#define VIRTIO_SCSI_S_ABORTED 2
+#define VIRTIO_SCSI_S_BAD_TARGET 3
+#define VIRTIO_SCSI_S_RESET 4
+#define VIRTIO_SCSI_S_BUSY 5
+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6
+#define VIRTIO_SCSI_S_TARGET_FAILURE 7
+#define VIRTIO_SCSI_S_NEXUS_FAILURE 8
+#define VIRTIO_SCSI_S_FAILURE 9
+#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED 10
+#define VIRTIO_SCSI_S_FUNCTION_REJECTED 11
+#define VIRTIO_SCSI_S_INCORRECT_LUN 12
+
+/*
+ * Control queue type codes:
+ */
+#define VIRTIO_SCSI_T_TMF 0
+#define VIRTIO_SCSI_T_AN_QUERY 1
+#define VIRTIO_SCSI_T_AN_SUBSCRIBE 2
+
+/*
+ * Task management codes:
+ */
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK 0
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET 1
+#define VIRTIO_SCSI_T_TMF_CLEAR_ACA 2
+#define VIRTIO_SCSI_T_TMF_CLEAR_ACA_TASK_SET 3
+#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET 4
+#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET 5
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK 6
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET 7
+
+/*
+ * Events:
+ */
+#define VIRTIO_SCSI_T_EVENTS_MISSED 0x80000000
+#define VIRTIO_SCSI_T_NO_EVENT 0
+#define VIRTIO_SCSI_T_TRANSPORT_RESET 1
+#define VIRTIO_SCSI_T_ASYNC_NOTIFY 2
+
+/*
+ * Task attributes:
+ */
+#define VIRTIO_SCSI_S_SIMPLE 0
+#define VIRTIO_SCSI_S_ORDERED 1
+#define VIRTIO_SCSI_S_HEAD 2
+#define VIRTIO_SCSI_S_ACA 3
+
+/*
+ * Reasons of reset event:
+ */
+#define VIRTIO_SCSI_EVT_RESET_HARD 0
+#define VIRTIO_SCSI_EVT_RESET_RESCAN 1
+#define VIRTIO_SCSI_EVT_RESET_REMOVED 2
+
+/*
+ * We need to support INOUT, and we want hotplug notifications:
+ */
+#define VIOSCSI_WANTED_FEATURES (VIRTIO_SCSI_F_INOUT | VIRTIO_SCSI_F_HOTPLUG)
+
+#define VIOSCSI_MAX_TARGET 256
+#define VIOSCSI_MIN_SEGS 3
+#define VIOSCSI_NUM_EVENTS 16
+
+/*
+ * Data structures:
+ */
+
+#pragma pack(1)
+
+/*
+ * virtio SCSI command request:
+ */
+struct virtio_scsi_cmd_req {
+ uint8_t lun[8];
+ uint64_t tag;
+ uint8_t task_attr;
+ uint8_t prio;
+ uint8_t crn;
+ uint8_t cdb[VIRTIO_SCSI_CDB_SIZE];
+};
+
+/*
+ * Virtio SCSI response:
+ */
+struct virtio_scsi_cmd_resp {
+ uint32_t sense_len;
+ uint32_t res_id;
+ uint16_t status_qualifier;
+ uint8_t status;
+ uint8_t response;
+ uint8_t sense[VIRTIO_SCSI_SENSE_SIZE];
+};
+
+/*
+ * Task management request:
+ */
+struct virtio_scsi_ctrl_tmf_req {
+ uint32_t type;
+ uint32_t subtype;
+ uint8_t lun[8];
+ uint64_t tag;
+};
+
+/*
+ * Task management response:
+ */
+struct virtio_scsi_ctrl_tmf_resp {
+ uint8_t response;
+};
+
+/*
+ * Asynchronous notification request:
+ */
+struct virtio_scsi_ctrl_an_req {
+ uint32_t type;
+ uint8_t lun[8];
+ uint32_t event_requested;
+};
+
+/*
+ * Asynchronous notification response:
+ */
+struct virtio_scsi_ctrl_an_resp {
+ uint32_t event_actual;
+ uint8_t response;
+};
+
+/*
+ * Events delivered on the event queue:
+ */
+struct virtio_scsi_event {
+ uint32_t event;
+ uint8_t lun[8];
+ uint32_t reason;
+};
+
+#pragma pack()
+
+typedef union {
+ struct virtio_scsi_cmd_req cmd;
+ struct virtio_scsi_ctrl_tmf_req tmf;
+ struct virtio_scsi_ctrl_an_req anr;
+} vioscsi_req_t;
+
+typedef union {
+ struct virtio_scsi_cmd_resp cmd;
+ struct virtio_scsi_ctrl_tmf_resp tmf;
+ struct virtio_scsi_ctrl_an_resp anr;
+} vioscsi_res_t;
+
+struct virtio_scsi_op {
+ vioscsi_req_t req;
+ vioscsi_res_t res;
+};
+
+#define VIOSCSI_REQ_OFFSET offsetof(struct virtio_scsi_op, req)
+#define VIOSCSI_RES_OFFSET offsetof(struct virtio_scsi_op, res)
+
+typedef struct vioscsi_request vioscsi_request_t;
+typedef struct vioscsi_event vioscsi_event_t;
+typedef struct vioscsi_softc vioscsi_softc_t;
+typedef struct vioscsi_dev vioscsi_dev_t;
+typedef struct virtio_scsi_event vioscsi_evt_t;
+typedef struct virtio_scsi_ctrl_tmf_req vioscsi_tmf_req_t;
+typedef struct virtio_scsi_ctrl_tmf_resp vioscsi_tmf_res_t;
+typedef struct virtio_scsi_cmd_req vioscsi_cmd_req_t;
+typedef struct virtio_scsi_cmd_resp vioscsi_cmd_res_t;
+typedef struct virtio_scsi_op vioscsi_op_t;
+
+struct vioscsi_request {
+ list_node_t vr_node;
+ struct scsi_pkt *vr_pkt;
+ virtio_queue_t *vr_vq;
+ virtio_dma_t *vr_dma;
+ virtio_chain_t *vr_vic;
+ vioscsi_dev_t *vr_dev;
+ vioscsi_req_t *vr_req;
+ vioscsi_res_t *vr_res;
+ uint64_t vr_req_pa;
+ uint64_t vr_res_pa;
+ boolean_t vr_poll;
+ uint8_t vr_expired; /* access using atomics */
+ uint8_t vr_done; /* access using atomics */
+ uint8_t vr_task_attr;
+ uint8_t vr_target;
+ uint16_t vr_lun;
+ clock_t vr_time; /* seconds */
+ clock_t vr_start; /* ticks */
+ clock_t vr_expire; /* ticks */
+};
+
+struct vioscsi_dev {
+ list_node_t vd_node;
+ uint8_t vd_target;
+ uint16_t vd_lun;
+ struct scsi_device *vd_sd;
+ vioscsi_softc_t *vd_sc;
+ int vd_num_cmd;
+ int vd_max_cmd;
+ boolean_t vd_rescan;
+ list_t vd_reqs;
+ timeout_id_t vd_timeout;
+ kmutex_t vd_lock;
+};
+
+struct vioscsi_event {
+ virtio_chain_t *ve_vic;
+ virtio_dma_t *ve_dma;
+ vioscsi_evt_t *ve_evt;
+};
+
+struct vioscsi_softc {
+ dev_info_t *vs_dip;
+ virtio_t *vs_virtio;
+ uint64_t vs_features;
+
+ virtio_queue_t *vs_ctl_vq;
+ virtio_queue_t *vs_evt_vq;
+ virtio_queue_t *vs_cmd_vq;
+
+ scsi_hba_tran_t *vs_tran;
+ scsi_hba_tgtmap_t *vs_tgtmap;
+ ddi_taskq_t *vs_tq;
+
+ uint32_t vs_max_target;
+ uint32_t vs_max_lun;
+ uint32_t vs_cdb_size;
+ uint32_t vs_max_seg;
+ uint32_t vs_cmd_per_lun;
+
+ vioscsi_event_t vs_events[VIOSCSI_NUM_EVENTS];
+
+ void *vs_intr_pri;
+ kmutex_t vs_lock;
+ list_t vs_devs;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VIOSCSI_H_ */