117359Swosch/*-
217359Swosch * Copyright (c) 2012, Bryan Venteicher <bryanv@FreeBSD.org>
317359Swosch * All rights reserved.
417359Swosch *
517359Swosch * Redistribution and use in source and binary forms, with or without
617359Swosch * modification, are permitted provided that the following conditions
717359Swosch * are met:
817359Swosch * 1. Redistributions of source code must retain the above copyright
917359Swosch *    notice unmodified, this list of conditions, and the following
1017359Swosch *    disclaimer.
1117359Swosch * 2. Redistributions in binary form must reproduce the above copyright
1217359Swosch *    notice, this list of conditions and the following disclaimer in the
1317359Swosch *    documentation and/or other materials provided with the distribution.
1417359Swosch *
1517359Swosch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1617359Swosch * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1717359Swosch * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1817359Swosch * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1917359Swosch * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2017359Swosch * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2117359Swosch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2217359Swosch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2317359Swosch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2417359Swosch * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2517359Swosch *
2617359Swosch * $FreeBSD: releng/10.2/sys/dev/virtio/scsi/virtio_scsivar.h 252707 2013-07-04 17:57:26Z bryanv $
2717359Swosch */
2817359Swosch
2917359Swosch#ifndef _VIRTIO_SCSIVAR_H
3017359Swosch#define _VIRTIO_SCSIVAR_H
3117359Swosch
3217359Swoschstruct vtscsi_softc;
3317359Swoschstruct vtscsi_request;
3417359Swosch
3517359Swoschtypedef void vtscsi_request_cb_t(struct vtscsi_softc *,
3617359Swosch    struct vtscsi_request *);
3717359Swosch
3817359Swoschstruct vtscsi_statistics {
3917359Swosch	unsigned long		scsi_cmd_timeouts;
4017359Swosch	unsigned long		dequeue_no_requests;
4117359Swosch};
4217359Swosch
4317359Swoschstruct vtscsi_softc {
4417359Swosch	device_t		 vtscsi_dev;
4517359Swosch	struct mtx		 vtscsi_mtx;
4617359Swosch	uint64_t		 vtscsi_features;
4717359Swosch
4817359Swosch	uint16_t		 vtscsi_flags;
4917359Swosch#define VTSCSI_FLAG_INDIRECT		0x0001
5017359Swosch#define VTSCSI_FLAG_BIDIRECTIONAL	0x0002
5117359Swosch#define VTSCSI_FLAG_HOTPLUG		0x0004
5217359Swosch#define VTSCSI_FLAG_RESET		0x0008
5317359Swosch#define VTSCSI_FLAG_DETACH		0x0010
5417359Swosch
5517359Swosch	uint16_t		 vtscsi_frozen;
5617359Swosch#define VTSCSI_FROZEN_NO_REQUESTS	0x01
5717359Swosch#define VTSCSI_FROZEN_REQUEST_VQ_FULL	0x02
5817359Swosch
5917359Swosch	struct sglist		*vtscsi_sglist;
6017359Swosch
6117359Swosch	struct virtqueue	*vtscsi_control_vq;
6217359Swosch	struct virtqueue	*vtscsi_event_vq;
6317359Swosch	struct virtqueue	*vtscsi_request_vq;
6417359Swosch
6517359Swosch	struct cam_sim		*vtscsi_sim;
6617359Swosch	struct cam_path		*vtscsi_path;
6717359Swosch
6817359Swosch	int			 vtscsi_debug;
6917359Swosch	int			 vtscsi_nrequests;
7017359Swosch	int			 vtscsi_max_nsegs;
7117359Swosch	int			 vtscsi_event_buf_size;
7217359Swosch
7317359Swosch	TAILQ_HEAD(,vtscsi_request)
7417359Swosch				 vtscsi_req_free;
7517359Swosch
7617359Swosch	uint16_t		 vtscsi_max_channel;
7717359Swosch	uint16_t		 vtscsi_max_target;
7817359Swosch	uint32_t		 vtscsi_max_lun;
7917359Swosch
8017359Swosch#define VTSCSI_NUM_EVENT_BUFS	4
8117359Swosch	struct virtio_scsi_event
8217359Swosch				 vtscsi_event_bufs[VTSCSI_NUM_EVENT_BUFS];
8317359Swosch
8417359Swosch	struct vtscsi_statistics vtscsi_stats;
8517359Swosch};
8617359Swosch
8717359Swoschenum vtscsi_request_state {
8817359Swosch	VTSCSI_REQ_STATE_FREE,
8917359Swosch	VTSCSI_REQ_STATE_INUSE,
9017359Swosch	VTSCSI_REQ_STATE_ABORTED,
9117359Swosch	VTSCSI_REQ_STATE_TIMEDOUT
9217359Swosch};
9317359Swosch
9418194Ssosstruct vtscsi_request {
9517359Swosch	struct vtscsi_softc			*vsr_softc;
9617359Swosch	union ccb				*vsr_ccb;
9717359Swosch	vtscsi_request_cb_t			*vsr_complete;
9817359Swosch
9917359Swosch	void					*vsr_ptr0;
10017359Swosch/* Request when aborting a timedout command. */
10117359Swosch#define vsr_timedout_req	vsr_ptr0
10217359Swosch
10317359Swosch	enum vtscsi_request_state		 vsr_state;
10417359Swosch
10517359Swosch	uint16_t				 vsr_flags;
10617359Swosch#define VTSCSI_REQ_FLAG_POLLED		0x01
10717359Swosch#define VTSCSI_REQ_FLAG_COMPLETE	0x02
10817359Swosch#define VTSCSI_REQ_FLAG_TIMEOUT_SET	0x04
10917359Swosch
11017359Swosch	union {
11117359Swosch		struct virtio_scsi_cmd_req	 cmd;
11217359Swosch		struct virtio_scsi_ctrl_tmf_req	 tmf;
11317359Swosch		struct virtio_scsi_ctrl_an_req	 an;
11417359Swosch	} vsr_ureq;
11517359Swosch#define vsr_cmd_req 	vsr_ureq.cmd
11617359Swosch#define vsr_tmf_req 	vsr_ureq.tmf
11717359Swosch#define vsr_an_req	vsr_ureq.an
11817359Swosch
11917359Swosch	/* Make request and response non-contiguous. */
12017359Swosch	uint32_t				 vsr_pad;
12117359Swosch
12217359Swosch	union {
12318194Ssos		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) 	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))
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 */
217