2 * Copyright (c) 2012, Bryan Venteicher <bryanv@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
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.
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.
29 #ifndef _VIRTIO_SCSIVAR_H
30 #define _VIRTIO_SCSIVAR_H
33 struct vtscsi_request;
35 typedef void vtscsi_request_cb_t(struct vtscsi_softc *,
36 struct vtscsi_request *);
38 struct vtscsi_statistics {
39 unsigned long scsi_cmd_timeouts;
40 unsigned long dequeue_no_requests;
45 struct mtx vtscsi_mtx;
46 uint64_t vtscsi_features;
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
55 uint16_t vtscsi_frozen;
56 #define VTSCSI_FROZEN_NO_REQUESTS 0x01
57 #define VTSCSI_FROZEN_REQUEST_VQ_FULL 0x02
59 struct sglist *vtscsi_sglist;
61 struct virtqueue *vtscsi_control_vq;
62 struct virtqueue *vtscsi_event_vq;
63 struct virtqueue *vtscsi_request_vq;
65 struct cam_sim *vtscsi_sim;
66 struct cam_path *vtscsi_path;
71 int vtscsi_event_buf_size;
73 TAILQ_HEAD(,vtscsi_request)
76 uint16_t vtscsi_max_channel;
77 uint16_t vtscsi_max_target;
78 uint32_t vtscsi_max_lun;
80 #define VTSCSI_NUM_EVENT_BUFS 4
81 struct virtio_scsi_event
82 vtscsi_event_bufs[VTSCSI_NUM_EVENT_BUFS];
84 struct vtscsi_statistics vtscsi_stats;
87 enum vtscsi_request_state {
88 VTSCSI_REQ_STATE_FREE,
89 VTSCSI_REQ_STATE_INUSE,
90 VTSCSI_REQ_STATE_ABORTED,
91 VTSCSI_REQ_STATE_TIMEDOUT
94 struct vtscsi_request {
95 struct vtscsi_softc *vsr_softc;
97 vtscsi_request_cb_t *vsr_complete;
100 /* Request when aborting a timedout command. */
101 #define vsr_timedout_req vsr_ptr0
103 enum vtscsi_request_state vsr_state;
106 #define VTSCSI_REQ_FLAG_POLLED 0x01
107 #define VTSCSI_REQ_FLAG_COMPLETE 0x02
108 #define VTSCSI_REQ_FLAG_TIMEOUT_SET 0x04
111 struct virtio_scsi_cmd_req cmd;
112 struct virtio_scsi_ctrl_tmf_req tmf;
113 struct virtio_scsi_ctrl_an_req an;
115 #define vsr_cmd_req vsr_ureq.cmd
116 #define vsr_tmf_req vsr_ureq.tmf
117 #define vsr_an_req vsr_ureq.an
119 /* Make request and response non-contiguous. */
123 struct virtio_scsi_cmd_resp cmd;
124 struct virtio_scsi_ctrl_tmf_resp tmf;
125 struct virtio_scsi_ctrl_an_resp an;
127 #define vsr_cmd_resp vsr_uresp.cmd
128 #define vsr_tmf_resp vsr_uresp.tmf
129 #define vsr_an_resp vsr_uresp.an
131 struct callout vsr_callout;
133 TAILQ_ENTRY(vtscsi_request) vsr_link;
136 /* Private field in the CCB header that points to our request. */
137 #define ccbh_vtscsi_req spriv_ptr0
139 /* Features desired/implemented by this driver. */
140 #define VTSCSI_FEATURES \
141 (VIRTIO_SCSI_F_HOTPLUG | \
142 VIRTIO_RING_F_INDIRECT_DESC)
144 #define VTSCSI_MTX(_sc) &(_sc)->vtscsi_mtx
145 #define VTSCSI_LOCK_INIT(_sc, _name) mtx_init(VTSCSI_MTX(_sc), _name, \
146 "VTSCSI Lock", MTX_DEF)
147 #define VTSCSI_LOCK(_sc) mtx_lock(VTSCSI_MTX(_sc))
148 #define VTSCSI_UNLOCK(_sc) mtx_unlock(VTSCSI_MTX(_sc))
149 #define VTSCSI_LOCK_OWNED(_sc) mtx_assert(VTSCSI_MTX(_sc), MA_OWNED)
150 #define VTSCSI_LOCK_NOTOWNED(_sc) mtx_assert(VTSCSI_MTX(_sc), MA_NOTOWNED)
151 #define VTSCSI_LOCK_DESTROY(_sc) mtx_destroy(VTSCSI_MTX(_sc))
154 * Reasons for either freezing or thawing the SIMQ.
156 * VirtIO SCSI is a bit unique in the sense that SCSI and TMF
157 * commands go over different queues. Both queues are fed by
158 * the same SIMQ, but we only freeze the SIMQ when the request
159 * (SCSI) virtqueue is full, not caring if the control (TMF)
160 * virtqueue unlikely gets full. However, both queues share the
161 * same pool of requests, so the completion of a TMF command
162 * could cause the SIMQ to be unfrozen.
164 #define VTSCSI_REQUEST 0x01
165 #define VTSCSI_REQUEST_VQ 0x02
167 /* Debug trace levels. */
168 #define VTSCSI_INFO 0x01
169 #define VTSCSI_ERROR 0x02
170 #define VTSCSI_TRACE 0x04
172 #define vtscsi_dprintf(_sc, _level, _msg, _args ...) do { \
173 if ((_sc)->vtscsi_debug & (_level)) \
174 device_printf((_sc)->vtscsi_dev, "%s: "_msg, \
175 __FUNCTION__, ##_args); \
178 #define vtscsi_dprintf_req(_req, _level, _msg, _args ...) do { \
179 struct vtscsi_softc *__sc = (_req)->vsr_softc; \
180 if ((__sc)->vtscsi_debug & (_level)) \
181 vtscsi_printf_req(_req, __FUNCTION__, _msg, ##_args); \
185 * Set the status field in a CCB, optionally clearing non CCB_STATUS_* flags.
187 #define vtscsi_set_ccb_status(_ccbh, _status, _mask) do { \
188 KASSERT(((_mask) & CAM_STATUS_MASK) == 0, \
189 ("%s:%d bad mask: 0x%x", __FUNCTION__, __LINE__, (_mask))); \
190 (_ccbh)->status &= ~(CAM_STATUS_MASK | (_mask)); \
191 (_ccbh)->status |= (_status); \
195 * One segment each for the request and the response.
197 #define VTSCSI_MIN_SEGMENTS 2
200 * Allocate additional requests for internal use such
201 * as TM commands (e.g. aborting timedout commands).
203 #define VTSCSI_RESERVED_REQUESTS 10
206 * Specification doesn't say, use traditional SCSI default.
208 #define VTSCSI_INITIATOR_ID 7
211 * How to wait (or not) for request completion.
213 #define VTSCSI_EXECUTE_ASYNC 0
214 #define VTSCSI_EXECUTE_POLL 1
216 #endif /* _VIRTIO_SCSIVAR_H */