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