1 /*- 2 * Copyright (c) 2012, Bryan Venteicher <bryanv@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/dev/virtio/scsi/virtio_scsivar.h 252707 2013-07-04 17:57:26Z bryanv $ 27 */ 28 29 #ifndef _VIRTIO_SCSIVAR_H 30 #define _VIRTIO_SCSIVAR_H 31 32 struct vtscsi_softc; 33 struct vtscsi_request; 34 35 typedef void vtscsi_request_cb_t(struct vtscsi_softc *, 36 struct vtscsi_request *); 37 38 struct vtscsi_statistics { 39 unsigned long scsi_cmd_timeouts; 40 unsigned long dequeue_no_requests; 41 }; 42 43 struct vtscsi_softc { 44 device_t vtscsi_dev; 45 struct lock vtscsi_mtx; 46 uint64_t vtscsi_features; 47 48 uint16_t vtscsi_flags; 49 #define VTSCSI_FLAG_INDIRECT 0x0001 50 #define VTSCSI_FLAG_BIDIRECTIONAL 0x0002 51 #define VTSCSI_FLAG_HOTPLUG 0x0004 52 #define VTSCSI_FLAG_RESET 0x0008 53 #define VTSCSI_FLAG_DETACH 0x0010 54 55 uint16_t vtscsi_frozen; 56 #define VTSCSI_FROZEN_NO_REQUESTS 0x01 57 #define VTSCSI_FROZEN_REQUEST_VQ_FULL 0x02 58 59 struct sglist *vtscsi_sglist; 60 61 struct virtqueue *vtscsi_control_vq; 62 struct virtqueue *vtscsi_event_vq; 63 struct virtqueue *vtscsi_request_vq; 64 65 struct cam_sim *vtscsi_sim; 66 struct cam_path *vtscsi_path; 67 68 int vtscsi_debug; 69 int vtscsi_nrequests; 70 int vtscsi_max_nsegs; 71 int vtscsi_event_buf_size; 72 73 TAILQ_HEAD(,vtscsi_request) 74 vtscsi_req_free; 75 76 uint16_t vtscsi_max_channel; 77 uint16_t vtscsi_max_target; 78 uint32_t vtscsi_max_lun; 79 80 #define VTSCSI_NUM_EVENT_BUFS 4 81 struct virtio_scsi_event 82 vtscsi_event_bufs[VTSCSI_NUM_EVENT_BUFS]; 83 84 struct vtscsi_statistics vtscsi_stats; 85 86 int vtscsi_cpus[4]; 87 int vtscsi_nintr; 88 }; 89 90 enum vtscsi_request_state { 91 VTSCSI_REQ_STATE_FREE, 92 VTSCSI_REQ_STATE_INUSE, 93 VTSCSI_REQ_STATE_ABORTED, 94 VTSCSI_REQ_STATE_TIMEDOUT 95 }; 96 97 struct vtscsi_request { 98 struct vtscsi_softc *vsr_softc; 99 union ccb *vsr_ccb; 100 vtscsi_request_cb_t *vsr_complete; 101 102 void *vsr_ptr0; 103 /* Request when aborting a timedout command. */ 104 #define vsr_timedout_req vsr_ptr0 105 106 enum vtscsi_request_state vsr_state; 107 108 uint16_t vsr_flags; 109 #define VTSCSI_REQ_FLAG_POLLED 0x01 110 #define VTSCSI_REQ_FLAG_COMPLETE 0x02 111 #define VTSCSI_REQ_FLAG_TIMEOUT_SET 0x04 112 113 union { 114 struct virtio_scsi_cmd_req cmd; 115 struct virtio_scsi_ctrl_tmf_req tmf; 116 struct virtio_scsi_ctrl_an_req an; 117 } vsr_ureq; 118 #define vsr_cmd_req vsr_ureq.cmd 119 #define vsr_tmf_req vsr_ureq.tmf 120 #define vsr_an_req vsr_ureq.an 121 122 /* Make request and response non-contiguous. */ 123 uint32_t vsr_pad; 124 125 union { 126 struct virtio_scsi_cmd_resp cmd; 127 struct virtio_scsi_ctrl_tmf_resp tmf; 128 struct virtio_scsi_ctrl_an_resp an; 129 } vsr_uresp; 130 #define vsr_cmd_resp vsr_uresp.cmd 131 #define vsr_tmf_resp vsr_uresp.tmf 132 #define vsr_an_resp vsr_uresp.an 133 134 struct callout vsr_callout; 135 136 TAILQ_ENTRY(vtscsi_request) vsr_link; 137 }; 138 139 /* Private field in the CCB header that points to our request. */ 140 #define ccbh_vtscsi_req spriv_ptr0 141 142 /* Features desired/implemented by this driver. */ 143 #define VTSCSI_FEATURES \ 144 (VIRTIO_SCSI_F_HOTPLUG | \ 145 VIRTIO_RING_F_INDIRECT_DESC) 146 147 #define VTSCSI_MTX(_sc) &(_sc)->vtscsi_mtx 148 #define VTSCSI_LOCK_INIT(_sc, _name) lockinit(VTSCSI_MTX(_sc), \ 149 "VTSCSI Lock", 0, LK_CANRECURSE) 150 #define VTSCSI_LOCK(_sc) lockmgr(VTSCSI_MTX(_sc), LK_EXCLUSIVE) 151 #define VTSCSI_UNLOCK(_sc) lockmgr(VTSCSI_MTX(_sc), LK_RELEASE) 152 #define VTSCSI_LOCK_OWNED(_sc) KKASSERT(lockowned(VTSCSI_MTX(_sc)) != 0) 153 #define VTSCSI_LOCK_NOTOWNED(_sc) KKASSERT(lockowned(VTSCSI_MTX(_sc)) == 0) 154 #define VTSCSI_LOCK_DESTROY(_sc) lockuninit(VTSCSI_MTX(_sc)) 155 156 /* 157 * Reasons for either freezing or thawing the SIMQ. 158 * 159 * VirtIO SCSI is a bit unique in the sense that SCSI and TMF 160 * commands go over different queues. Both queues are fed by 161 * the same SIMQ, but we only freeze the SIMQ when the request 162 * (SCSI) virtqueue is full, not caring if the control (TMF) 163 * virtqueue unlikely gets full. However, both queues share the 164 * same pool of requests, so the completion of a TMF command 165 * could cause the SIMQ to be unfrozen. 166 */ 167 #define VTSCSI_REQUEST 0x01 168 #define VTSCSI_REQUEST_VQ 0x02 169 170 /* Debug trace levels. */ 171 #define VTSCSI_INFO 0x01 172 #define VTSCSI_ERROR 0x02 173 #define VTSCSI_TRACE 0x04 174 175 #define vtscsi_dprintf(_sc, _level, _msg, _args ...) do { \ 176 if ((_sc)->vtscsi_debug & (_level)) \ 177 device_printf((_sc)->vtscsi_dev, "%s: "_msg, \ 178 __FUNCTION__, ##_args); \ 179 } while (0) 180 181 #define vtscsi_dprintf_req(_req, _level, _msg, _args ...) do { \ 182 struct vtscsi_softc *__sc = (_req)->vsr_softc; \ 183 if ((__sc)->vtscsi_debug & (_level)) \ 184 vtscsi_printf_req(_req, __FUNCTION__, _msg, ##_args); \ 185 } while (0) 186 187 /* 188 * Set the status field in a CCB, optionally clearing non CCB_STATUS_* flags. 189 */ 190 #define vtscsi_set_ccb_status(_ccbh, _status, _mask) do { \ 191 KASSERT(((_mask) & CAM_STATUS_MASK) == 0, \ 192 ("%s:%d bad mask: 0x%x", __FUNCTION__, __LINE__, (_mask))); \ 193 (_ccbh)->status &= ~(CAM_STATUS_MASK | (_mask)); \ 194 (_ccbh)->status |= (_status); \ 195 } while (0) 196 197 /* 198 * One segment each for the request and the response. 199 */ 200 #define VTSCSI_MIN_SEGMENTS 2 201 202 /* 203 * Allocate additional requests for internal use such 204 * as TM commands (e.g. aborting timedout commands). 205 */ 206 #define VTSCSI_RESERVED_REQUESTS 10 207 208 /* 209 * Specification doesn't say, use traditional SCSI default. 210 */ 211 #define VTSCSI_INITIATOR_ID 7 212 213 /* 214 * How to wait (or not) for request completion. 215 */ 216 #define VTSCSI_EXECUTE_ASYNC 0 217 #define VTSCSI_EXECUTE_POLL 1 218 219 #endif /* _VIRTIO_SCSIVAR_H */ 220