kernel: Add FreeBSD's virtio_scsi(4) driver.
[dragonfly.git] / sys / dev / virtual / virtio / scsi / virtio_scsivar.h
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
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
92 };
93
94 struct vtscsi_request {
95         struct vtscsi_softc                     *vsr_softc;
96         union ccb                               *vsr_ccb;
97         vtscsi_request_cb_t                     *vsr_complete;
98
99         void                                    *vsr_ptr0;
100 /* Request when aborting a timedout command. */
101 #define vsr_timedout_req        vsr_ptr0
102
103         enum vtscsi_request_state                vsr_state;
104
105         uint16_t                                 vsr_flags;
106 #define VTSCSI_REQ_FLAG_POLLED          0x01
107 #define VTSCSI_REQ_FLAG_COMPLETE        0x02
108 #define VTSCSI_REQ_FLAG_TIMEOUT_SET     0x04
109
110         union {
111                 struct virtio_scsi_cmd_req       cmd;
112                 struct virtio_scsi_ctrl_tmf_req  tmf;
113                 struct virtio_scsi_ctrl_an_req   an;
114         } vsr_ureq;
115 #define vsr_cmd_req     vsr_ureq.cmd
116 #define vsr_tmf_req     vsr_ureq.tmf
117 #define vsr_an_req      vsr_ureq.an
118
119         /* Make request and response non-contiguous. */
120         uint32_t                                 vsr_pad;
121
122         union {
123                 struct virtio_scsi_cmd_resp      cmd;
124                 struct virtio_scsi_ctrl_tmf_resp tmf;
125                 struct virtio_scsi_ctrl_an_resp  an;
126         } vsr_uresp;
127 #define vsr_cmd_resp    vsr_uresp.cmd
128 #define vsr_tmf_resp    vsr_uresp.tmf
129 #define vsr_an_resp     vsr_uresp.an
130
131         struct callout                           vsr_callout;
132
133         TAILQ_ENTRY(vtscsi_request)              vsr_link;
134 };
135
136 /* Private field in the CCB header that points to our request. */
137 #define ccbh_vtscsi_req spriv_ptr0
138
139 /* Features desired/implemented by this driver. */
140 #define VTSCSI_FEATURES \
141     (VIRTIO_SCSI_F_HOTPLUG              | \
142      VIRTIO_RING_F_INDIRECT_DESC)
143
144 #define VTSCSI_MTX(_sc)                 &(_sc)->vtscsi_mtx
145 #define VTSCSI_LOCK_INIT(_sc, _name)    lockinit(VTSCSI_MTX(_sc), \
146                                             "VTSCSI Lock", 0, LK_CANRECURSE)
147 #define VTSCSI_LOCK(_sc)                lockmgr(VTSCSI_MTX(_sc), LK_EXCLUSIVE)
148 #define VTSCSI_UNLOCK(_sc)              lockmgr(VTSCSI_MTX(_sc), LK_RELEASE)
149 #define VTSCSI_LOCK_OWNED(_sc)          KKASSERT(lockowned(VTSCSI_MTX(_sc)) != 0)
150 #define VTSCSI_LOCK_NOTOWNED(_sc)       KKASSERT(lockowned(VTSCSI_MTX(_sc)) == 0)
151 #define VTSCSI_LOCK_DESTROY(_sc)        lockuninit(VTSCSI_MTX(_sc))
152
153 /*
154  * Reasons for either freezing or thawing the SIMQ.
155  *
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.
163  */
164 #define VTSCSI_REQUEST          0x01
165 #define VTSCSI_REQUEST_VQ       0x02
166
167 /* Debug trace levels. */
168 #define VTSCSI_INFO     0x01
169 #define VTSCSI_ERROR    0x02
170 #define VTSCSI_TRACE    0x04
171
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);                             \
176 } while (0)
177
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);   \
182 } while (0)
183
184 /*
185  * Set the status field in a CCB, optionally clearing non CCB_STATUS_* flags.
186  */
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);                                   \
192 } while (0)
193
194 /*
195  * One segment each for the request and the response.
196  */
197 #define VTSCSI_MIN_SEGMENTS     2
198
199 /*
200  * Allocate additional requests for internal use such
201  * as TM commands (e.g. aborting timedout commands).
202  */
203 #define VTSCSI_RESERVED_REQUESTS        10
204
205 /*
206  * Specification doesn't say, use traditional SCSI default.
207  */
208 #define VTSCSI_INITIATOR_ID     7
209
210 /*
211  * How to wait (or not) for request completion.
212  */
213 #define VTSCSI_EXECUTE_ASYNC    0
214 #define VTSCSI_EXECUTE_POLL     1
215
216 #endif /* _VIRTIO_SCSIVAR_H */