xref: /freebsd/sys/dev/virtio/scsi/virtio_scsivar.h (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
12f001371SPeter Grehan /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
4abd6790cSBryan Venteicher  * Copyright (c) 2012, Bryan Venteicher <bryanv@FreeBSD.org>
52f001371SPeter Grehan  * All rights reserved.
62f001371SPeter Grehan  *
72f001371SPeter Grehan  * Redistribution and use in source and binary forms, with or without
82f001371SPeter Grehan  * modification, are permitted provided that the following conditions
92f001371SPeter Grehan  * are met:
102f001371SPeter Grehan  * 1. Redistributions of source code must retain the above copyright
112f001371SPeter Grehan  *    notice unmodified, this list of conditions, and the following
122f001371SPeter Grehan  *    disclaimer.
132f001371SPeter Grehan  * 2. Redistributions in binary form must reproduce the above copyright
142f001371SPeter Grehan  *    notice, this list of conditions and the following disclaimer in the
152f001371SPeter Grehan  *    documentation and/or other materials provided with the distribution.
162f001371SPeter Grehan  *
172f001371SPeter Grehan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
182f001371SPeter Grehan  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
192f001371SPeter Grehan  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
202f001371SPeter Grehan  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
212f001371SPeter Grehan  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
222f001371SPeter Grehan  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232f001371SPeter Grehan  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242f001371SPeter Grehan  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252f001371SPeter Grehan  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
262f001371SPeter Grehan  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272f001371SPeter Grehan  */
282f001371SPeter Grehan 
292f001371SPeter Grehan #ifndef _VIRTIO_SCSIVAR_H
302f001371SPeter Grehan #define _VIRTIO_SCSIVAR_H
312f001371SPeter Grehan 
322f001371SPeter Grehan struct vtscsi_softc;
332f001371SPeter Grehan struct vtscsi_request;
342f001371SPeter Grehan 
352f001371SPeter Grehan typedef void vtscsi_request_cb_t(struct vtscsi_softc *,
362f001371SPeter Grehan     struct vtscsi_request *);
372f001371SPeter Grehan 
382f001371SPeter Grehan struct vtscsi_statistics {
392f001371SPeter Grehan 	unsigned long		scsi_cmd_timeouts;
402f001371SPeter Grehan 	unsigned long		dequeue_no_requests;
412f001371SPeter Grehan };
422f001371SPeter Grehan 
432f001371SPeter Grehan struct vtscsi_softc {
442f001371SPeter Grehan 	device_t		 vtscsi_dev;
452f001371SPeter Grehan 	struct mtx		 vtscsi_mtx;
462f001371SPeter Grehan 	uint64_t		 vtscsi_features;
472f001371SPeter Grehan 
482f001371SPeter Grehan 	uint16_t		 vtscsi_flags;
492f001371SPeter Grehan #define VTSCSI_FLAG_INDIRECT		0x0001
502f001371SPeter Grehan #define VTSCSI_FLAG_BIDIRECTIONAL	0x0002
512f001371SPeter Grehan #define VTSCSI_FLAG_HOTPLUG		0x0004
522f001371SPeter Grehan #define VTSCSI_FLAG_RESET		0x0008
532f001371SPeter Grehan #define VTSCSI_FLAG_DETACH		0x0010
542f001371SPeter Grehan 
552f001371SPeter Grehan 	uint16_t		 vtscsi_frozen;
562f001371SPeter Grehan #define VTSCSI_FROZEN_NO_REQUESTS	0x01
572f001371SPeter Grehan #define VTSCSI_FROZEN_REQUEST_VQ_FULL	0x02
582f001371SPeter Grehan 
592f001371SPeter Grehan 	struct sglist		*vtscsi_sglist;
602f001371SPeter Grehan 
612f001371SPeter Grehan 	struct virtqueue	*vtscsi_control_vq;
622f001371SPeter Grehan 	struct virtqueue	*vtscsi_event_vq;
632f001371SPeter Grehan 	struct virtqueue	*vtscsi_request_vq;
642f001371SPeter Grehan 
652f001371SPeter Grehan 	struct cam_sim		*vtscsi_sim;
662f001371SPeter Grehan 	struct cam_path		*vtscsi_path;
672f001371SPeter Grehan 
682f001371SPeter Grehan 	int			 vtscsi_debug;
692f001371SPeter Grehan 	int			 vtscsi_nrequests;
702f001371SPeter Grehan 	int			 vtscsi_max_nsegs;
712f001371SPeter Grehan 	int			 vtscsi_event_buf_size;
722f001371SPeter Grehan 
732f001371SPeter Grehan 	TAILQ_HEAD(,vtscsi_request)
742f001371SPeter Grehan 				 vtscsi_req_free;
752f001371SPeter Grehan 
762f001371SPeter Grehan 	uint16_t		 vtscsi_max_channel;
772f001371SPeter Grehan 	uint16_t		 vtscsi_max_target;
782f001371SPeter Grehan 	uint32_t		 vtscsi_max_lun;
792f001371SPeter Grehan 
802f001371SPeter Grehan #define VTSCSI_NUM_EVENT_BUFS	4
812f001371SPeter Grehan 	struct virtio_scsi_event
822f001371SPeter Grehan 				 vtscsi_event_bufs[VTSCSI_NUM_EVENT_BUFS];
832f001371SPeter Grehan 
842f001371SPeter Grehan 	struct vtscsi_statistics vtscsi_stats;
852f001371SPeter Grehan };
862f001371SPeter Grehan 
872f001371SPeter Grehan enum vtscsi_request_state {
882f001371SPeter Grehan 	VTSCSI_REQ_STATE_FREE,
892f001371SPeter Grehan 	VTSCSI_REQ_STATE_INUSE,
902f001371SPeter Grehan 	VTSCSI_REQ_STATE_ABORTED,
912f001371SPeter Grehan 	VTSCSI_REQ_STATE_TIMEDOUT
922f001371SPeter Grehan };
932f001371SPeter Grehan 
942f001371SPeter Grehan struct vtscsi_request {
952f001371SPeter Grehan 	struct vtscsi_softc			*vsr_softc;
962f001371SPeter Grehan 	union ccb				*vsr_ccb;
972f001371SPeter Grehan 	vtscsi_request_cb_t			*vsr_complete;
982f001371SPeter Grehan 
992f001371SPeter Grehan 	void					*vsr_ptr0;
1002f001371SPeter Grehan /* Request when aborting a timedout command. */
1012f001371SPeter Grehan #define vsr_timedout_req	vsr_ptr0
1022f001371SPeter Grehan 
1032f001371SPeter Grehan 	enum vtscsi_request_state		 vsr_state;
1042f001371SPeter Grehan 
1052f001371SPeter Grehan 	uint16_t				 vsr_flags;
1062f001371SPeter Grehan #define VTSCSI_REQ_FLAG_POLLED		0x01
1072f001371SPeter Grehan #define VTSCSI_REQ_FLAG_COMPLETE	0x02
1082f001371SPeter Grehan #define VTSCSI_REQ_FLAG_TIMEOUT_SET	0x04
1092f001371SPeter Grehan 
1102f001371SPeter Grehan 	union {
1112f001371SPeter Grehan 		struct virtio_scsi_cmd_req	 cmd;
1122f001371SPeter Grehan 		struct virtio_scsi_ctrl_tmf_req	 tmf;
1132f001371SPeter Grehan 		struct virtio_scsi_ctrl_an_req	 an;
1142f001371SPeter Grehan 	} vsr_ureq;
1152f001371SPeter Grehan #define vsr_cmd_req 	vsr_ureq.cmd
1162f001371SPeter Grehan #define vsr_tmf_req 	vsr_ureq.tmf
1172f001371SPeter Grehan #define vsr_an_req	vsr_ureq.an
1182f001371SPeter Grehan 
1192f001371SPeter Grehan 	/* Make request and response non-contiguous. */
1202f001371SPeter Grehan 	uint32_t				 vsr_pad;
1212f001371SPeter Grehan 
1222f001371SPeter Grehan 	union {
1232f001371SPeter Grehan 		struct virtio_scsi_cmd_resp	 cmd;
1242f001371SPeter Grehan 		struct virtio_scsi_ctrl_tmf_resp tmf;
1252f001371SPeter Grehan 		struct virtio_scsi_ctrl_an_resp	 an;
1262f001371SPeter Grehan 	} vsr_uresp;
1272f001371SPeter Grehan #define vsr_cmd_resp	vsr_uresp.cmd
1282f001371SPeter Grehan #define vsr_tmf_resp	vsr_uresp.tmf
1292f001371SPeter Grehan #define vsr_an_resp	vsr_uresp.an
1302f001371SPeter Grehan 
1312f001371SPeter Grehan 	struct callout				 vsr_callout;
1322f001371SPeter Grehan 
1332f001371SPeter Grehan 	TAILQ_ENTRY(vtscsi_request)		 vsr_link;
1342f001371SPeter Grehan };
1352f001371SPeter Grehan 
1362f001371SPeter Grehan /* Private field in the CCB header that points to our request. */
1372f001371SPeter Grehan #define ccbh_vtscsi_req	spriv_ptr0
1382f001371SPeter Grehan 
1392f001371SPeter Grehan /* Features desired/implemented by this driver. */
1402f001371SPeter Grehan #define VTSCSI_FEATURES \
1412f001371SPeter Grehan     (VIRTIO_SCSI_F_HOTPLUG		| \
1422f001371SPeter Grehan      VIRTIO_RING_F_INDIRECT_DESC)
1432f001371SPeter Grehan 
1442f001371SPeter Grehan #define VTSCSI_MTX(_sc)			&(_sc)->vtscsi_mtx
1452f001371SPeter Grehan #define VTSCSI_LOCK_INIT(_sc, _name) 	mtx_init(VTSCSI_MTX(_sc), _name, \
1462f001371SPeter Grehan 					    "VTSCSI Lock", MTX_DEF)
1472f001371SPeter Grehan #define VTSCSI_LOCK(_sc)		mtx_lock(VTSCSI_MTX(_sc))
1482f001371SPeter Grehan #define VTSCSI_UNLOCK(_sc)		mtx_unlock(VTSCSI_MTX(_sc))
1492f001371SPeter Grehan #define VTSCSI_LOCK_OWNED(_sc)		mtx_assert(VTSCSI_MTX(_sc), MA_OWNED)
1502f001371SPeter Grehan #define VTSCSI_LOCK_NOTOWNED(_sc) 	mtx_assert(VTSCSI_MTX(_sc), MA_NOTOWNED)
1512f001371SPeter Grehan #define VTSCSI_LOCK_DESTROY(_sc)	mtx_destroy(VTSCSI_MTX(_sc))
1522f001371SPeter Grehan 
1532f001371SPeter Grehan /*
1542f001371SPeter Grehan  * Reasons for either freezing or thawing the SIMQ.
1552f001371SPeter Grehan  *
1562f001371SPeter Grehan  * VirtIO SCSI is a bit unique in the sense that SCSI and TMF
1572f001371SPeter Grehan  * commands go over different queues. Both queues are fed by
1582f001371SPeter Grehan  * the same SIMQ, but we only freeze the SIMQ when the request
1592f001371SPeter Grehan  * (SCSI) virtqueue is full, not caring if the control (TMF)
1602f001371SPeter Grehan  * virtqueue unlikely gets full. However, both queues share the
1612f001371SPeter Grehan  * same pool of requests, so the completion of a TMF command
1622f001371SPeter Grehan  * could cause the SIMQ to be unfrozen.
1632f001371SPeter Grehan  */
1642f001371SPeter Grehan #define VTSCSI_REQUEST		0x01
1652f001371SPeter Grehan #define VTSCSI_REQUEST_VQ	0x02
1662f001371SPeter Grehan 
1672f001371SPeter Grehan /* Debug trace levels. */
1682f001371SPeter Grehan #define VTSCSI_INFO	0x01
1692f001371SPeter Grehan #define VTSCSI_ERROR	0x02
1702f001371SPeter Grehan #define VTSCSI_TRACE	0x04
1712f001371SPeter Grehan 
1722f001371SPeter Grehan #define vtscsi_dprintf(_sc, _level, _msg, _args ...) do { 		\
1732f001371SPeter Grehan 	if ((_sc)->vtscsi_debug & (_level))				\
1742f001371SPeter Grehan 		device_printf((_sc)->vtscsi_dev, "%s: "_msg,		\
1752f001371SPeter Grehan 		    __FUNCTION__, ##_args);				\
1762f001371SPeter Grehan } while (0)
1772f001371SPeter Grehan 
1782f001371SPeter Grehan #define vtscsi_dprintf_req(_req, _level, _msg, _args ...) do {		\
1792f001371SPeter Grehan 	struct vtscsi_softc *__sc = (_req)->vsr_softc;			\
1802f001371SPeter Grehan 	if ((__sc)->vtscsi_debug & (_level))				\
1812f001371SPeter Grehan 		vtscsi_printf_req(_req, __FUNCTION__, _msg, ##_args);	\
1822f001371SPeter Grehan } while (0)
1832f001371SPeter Grehan 
1842f001371SPeter Grehan /*
1852f001371SPeter Grehan  * Set the status field in a CCB, optionally clearing non CCB_STATUS_* flags.
1862f001371SPeter Grehan  */
1872f001371SPeter Grehan #define vtscsi_set_ccb_status(_ccbh, _status, _mask) do {		\
1882f001371SPeter Grehan 	KASSERT(((_mask) & CAM_STATUS_MASK) == 0,			\
1892f001371SPeter Grehan 	    ("%s:%d bad mask: 0x%x", __FUNCTION__, __LINE__, (_mask)));	\
1902f001371SPeter Grehan 	(_ccbh)->status &= ~(CAM_STATUS_MASK | (_mask));		\
1912f001371SPeter Grehan 	(_ccbh)->status |= (_status);					\
1922f001371SPeter Grehan } while (0)
1932f001371SPeter Grehan 
1942f001371SPeter Grehan /*
1952f001371SPeter Grehan  * One segment each for the request and the response.
1962f001371SPeter Grehan  */
1972f001371SPeter Grehan #define VTSCSI_MIN_SEGMENTS	2
1982f001371SPeter Grehan 
1992f001371SPeter Grehan /*
2002f001371SPeter Grehan  * Allocate additional requests for internal use such
2012f001371SPeter Grehan  * as TM commands (e.g. aborting timedout commands).
2022f001371SPeter Grehan  */
2032f001371SPeter Grehan #define VTSCSI_RESERVED_REQUESTS	10
2042f001371SPeter Grehan 
2052f001371SPeter Grehan /*
2062f001371SPeter Grehan  * How to wait (or not) for request completion.
2072f001371SPeter Grehan  */
2082f001371SPeter Grehan #define VTSCSI_EXECUTE_ASYNC	0
2092f001371SPeter Grehan #define VTSCSI_EXECUTE_POLL	1
2102f001371SPeter Grehan 
2112f001371SPeter Grehan #endif /* _VIRTIO_SCSIVAR_H */
212