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 Joyent, Inc. 14 */ 15 16 /* 17 * VIRTIO BLOCK DRIVER 18 */ 19 20 #ifndef _VIOBLK_H 21 #define _VIOBLK_H 22 23 #include "virtio.h" 24 25 #ifdef __cplusplus 26 extern "C" { 27 #endif 28 29 /* 30 * VIRTIO BLOCK CONFIGURATION REGISTERS 31 * 32 * These are offsets into the device-specific configuration space available 33 * through the virtio_dev_*() family of functions. 34 */ 35 #define VIRTIO_BLK_CONFIG_CAPACITY 0x00 /* 64 R */ 36 #define VIRTIO_BLK_CONFIG_SIZE_MAX 0x08 /* 32 R */ 37 #define VIRTIO_BLK_CONFIG_SEG_MAX 0x0C /* 32 R */ 38 #define VIRTIO_BLK_CONFIG_GEOMETRY_C 0x10 /* 16 R */ 39 #define VIRTIO_BLK_CONFIG_GEOMETRY_H 0x12 /* 8 R */ 40 #define VIRTIO_BLK_CONFIG_GEOMETRY_S 0x13 /* 8 R */ 41 #define VIRTIO_BLK_CONFIG_BLK_SIZE 0x14 /* 32 R */ 42 #define VIRTIO_BLK_CONFIG_TOPO_PBEXP 0x18 /* 8 R */ 43 #define VIRTIO_BLK_CONFIG_TOPO_ALIGN 0x19 /* 8 R */ 44 #define VIRTIO_BLK_CONFIG_TOPO_MIN_SZ 0x1A /* 16 R */ 45 #define VIRTIO_BLK_CONFIG_TOPO_OPT_SZ 0x1C /* 32 R */ 46 47 /* 48 * VIRTIO BLOCK VIRTQUEUES 49 * 50 * Virtio block devices have just one queue which is used to make the various 51 * supported I/O requests. 52 */ 53 #define VIRTIO_BLK_VIRTQ_IO 0 54 55 /* 56 * VIRTIO BLOCK FEATURE BITS 57 */ 58 #define VIRTIO_BLK_F_BARRIER (1ULL << 0) 59 #define VIRTIO_BLK_F_SIZE_MAX (1ULL << 1) 60 #define VIRTIO_BLK_F_SEG_MAX (1ULL << 2) 61 #define VIRTIO_BLK_F_GEOMETRY (1ULL << 4) 62 #define VIRTIO_BLK_F_RO (1ULL << 5) 63 #define VIRTIO_BLK_F_BLK_SIZE (1ULL << 6) 64 #define VIRTIO_BLK_F_SCSI (1ULL << 7) 65 #define VIRTIO_BLK_F_FLUSH (1ULL << 9) 66 #define VIRTIO_BLK_F_TOPOLOGY (1ULL << 10) 67 68 /* 69 * These features are supported by the driver and we will request them from the 70 * device. 71 */ 72 #define VIRTIO_BLK_WANTED_FEATURES (VIRTIO_BLK_F_RO | \ 73 VIRTIO_BLK_F_BLK_SIZE | \ 74 VIRTIO_BLK_F_FLUSH | \ 75 VIRTIO_BLK_F_TOPOLOGY | \ 76 VIRTIO_BLK_F_SEG_MAX | \ 77 VIRTIO_BLK_F_SIZE_MAX) 78 79 /* 80 * VIRTIO BLOCK REQUEST HEADER 81 * 82 * This structure appears at the start of each I/O request buffer. Note that 83 * neither the data payload nor the status byte appear in this structure as 84 * both are handled in separate descriptor entries. 85 */ 86 struct vioblk_req_hdr { 87 uint32_t vbh_type; 88 uint32_t vbh_ioprio; 89 uint64_t vbh_sector; 90 } __packed; 91 92 /* 93 * VIRTIO BLOCK REQUEST HEADER: COMMANDS (vbh_type) 94 * 95 * Each of these is a command type, except for BARRIER which is logically 96 * OR-ed with one of the other types. 97 */ 98 #define VIRTIO_BLK_T_IN 0 99 #define VIRTIO_BLK_T_OUT 1 100 #define VIRTIO_BLK_T_SCSI_CMD 2 101 #define VIRTIO_BLK_T_SCSI_CMD_OUT 3 102 #define VIRTIO_BLK_T_FLUSH 4 103 #define VIRTIO_BLK_T_FLUSH_OUT 5 104 #define VIRTIO_BLK_T_GET_ID 8 105 #define VIRTIO_BLK_T_BARRIER 0x80000000 106 107 /* 108 * The GET_ID command type does not appear in the specification, but 109 * implementations in the wild use a 20 byte buffer into which the device will 110 * write an ASCII string. The string should not be assumed to be 111 * NUL-terminated. 112 */ 113 #define VIRTIO_BLK_ID_BYTES 20 114 115 /* 116 * VIRTIO BLOCK REQUEST HEADER: STATUS CODES 117 * 118 * These are returned in the writeable status byte descriptor included at the 119 * end of each request passed to the device. 120 */ 121 #define VIRTIO_BLK_S_OK 0 122 #define VIRTIO_BLK_S_IOERR 1 123 #define VIRTIO_BLK_S_UNSUPP 2 124 125 /* 126 * DRIVER PARAMETERS 127 */ 128 129 /* 130 * In the event that the device does not negotiate DMA parameters, we have to 131 * make a best guess. 132 */ 133 #define VIRTIO_BLK_DEFAULT_MAX_SEG 128 134 #define VIRTIO_BLK_DEFAULT_MAX_SIZE 4096 135 136 /* 137 * We allocate a fixed number of request buffers in advance and place them in a 138 * per-instance free list. 139 */ 140 #define VIRTIO_BLK_REQ_BUFS 256 141 142 /* 143 * TYPE DEFINITIONS 144 */ 145 146 typedef enum vioblk_req_status { 147 VIOBLK_REQSTAT_ALLOCATED = (0x1 << 0), 148 VIOBLK_REQSTAT_INFLIGHT = (0x1 << 1), 149 VIOBLK_REQSTAT_COMPLETE = (0x1 << 2), 150 VIOBLK_REQSTAT_POLLED = (0x1 << 3), 151 VIOBLK_REQSTAT_POLL_COMPLETE = (0x1 << 4), 152 } vioblk_req_status_t; 153 154 typedef struct vioblk_req { 155 vioblk_req_status_t vbr_status; 156 uint64_t vbr_seqno; 157 int vbr_type; 158 int vbr_error; 159 virtio_dma_t *vbr_dma; 160 bd_xfer_t *vbr_xfer; 161 list_node_t vbr_link; 162 } vioblk_req_t; 163 164 typedef struct vioblk_stats { 165 struct kstat_named vbs_rw_outofmemory; 166 struct kstat_named vbs_rw_badoffset; 167 struct kstat_named vbs_rw_queuemax; 168 struct kstat_named vbs_rw_cookiesmax; 169 struct kstat_named vbs_rw_cacheflush; 170 struct kstat_named vbs_intr_queuemax; 171 struct kstat_named vbs_intr_total; 172 struct kstat_named vbs_io_errors; 173 struct kstat_named vbs_unsupp_errors; 174 struct kstat_named vbs_nxio_errors; 175 } vioblk_stats_t; 176 177 typedef struct vioblk { 178 dev_info_t *vib_dip; 179 virtio_t *vib_virtio; 180 virtio_queue_t *vib_vq; 181 182 kmutex_t vib_mutex; 183 kcondvar_t vib_cv; 184 185 bd_handle_t vib_bd_h; 186 ddi_dma_attr_t vib_bd_dma_attr; 187 188 list_t vib_reqs; 189 uint_t vib_nreqs_alloc; 190 uint_t vib_reqs_capacity; 191 vioblk_req_t *vib_reqs_mem; 192 193 kstat_t *vib_kstat; 194 vioblk_stats_t *vib_stats; 195 196 uint64_t vib_nblks; 197 boolean_t vib_readonly; 198 uint_t vib_blk_size; 199 uint_t vib_pblk_size; 200 uint_t vib_seg_max; 201 uint_t vib_seg_size_max; 202 203 boolean_t vib_devid_fetched; 204 char vib_devid[VIRTIO_BLK_ID_BYTES + 1]; 205 uint8_t vib_rawid[VIRTIO_BLK_ID_BYTES]; 206 } vioblk_t; 207 208 #ifdef __cplusplus 209 } 210 #endif 211 212 #endif /* _VIOBLK_H */ 213