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