freebsd-dev/sys/dev/vmware/pvscsi/pvscsi.h
Josh Paetzel 052e12a508 Add the pvscsi driver to the tree.
This driver allows to usage of the paravirt SCSI controller
in VMware products like ESXi.  The pvscsi driver provides a
substantial performance improvement in block devices versus
the emulated mpt and mps SCSI/SAS controllers.

Error handling in this driver has not been extensively tested
yet.

Submitted by:	vbhakta@vmware.com
Relnotes:	yes
Sponsored by:	VMware, Panzura
Differential Revision:	D18613
2019-11-14 23:31:20 +00:00

216 lines
5.2 KiB
C

/*-
* Copyright (c) 2018 VMware, Inc.
*
* SPDX-License-Identifier: (BSD-2-Clause OR GPL-2.0)
*
* $FreeBSD$
*/
#ifndef _PVSCSI_H_
#define _PVSCSI_H_
#define MASK(v) ((1 << (v)) - 1)
#define PCI_VENDOR_ID_VMWARE 0x15ad
#define PCI_DEVICE_ID_VMWARE_PVSCSI 0x07c0
enum pvscsi_reg_offset {
PVSCSI_REG_OFFSET_COMMAND = 0x0000,
PVSCSI_REG_OFFSET_COMMAND_DATA = 0x0004,
PVSCSI_REG_OFFSET_COMMAND_STATUS = 0x0008,
PVSCSI_REG_OFFSET_LAST_STS_0 = 0x0100,
PVSCSI_REG_OFFSET_LAST_STS_1 = 0x0104,
PVSCSI_REG_OFFSET_LAST_STS_2 = 0x0108,
PVSCSI_REG_OFFSET_LAST_STS_3 = 0x010c,
PVSCSI_REG_OFFSET_INTR_STATUS = 0x100c,
PVSCSI_REG_OFFSET_INTR_MASK = 0x2010,
PVSCSI_REG_OFFSET_KICK_NON_RW_IO = 0x3014,
PVSCSI_REG_OFFSET_DEBUG = 0x3018,
PVSCSI_REG_OFFSET_KICK_RW_IO = 0x4018,
};
enum pvscsi_commands {
PVSCSI_CMD_FIRST = 0,
PVSCSI_CMD_ADAPTER_RESET = 1,
PVSCSI_CMD_ISSUE_SCSI = 2,
PVSCSI_CMD_SETUP_RINGS = 3,
PVSCSI_CMD_RESET_BUS = 4,
PVSCSI_CMD_RESET_DEVICE = 5,
PVSCSI_CMD_ABORT_CMD = 6,
PVSCSI_CMD_CONFIG = 7,
PVSCSI_CMD_SETUP_MSG_RING = 8,
PVSCSI_CMD_DEVICE_UNPLUG = 9,
PVSCSI_CMD_SETUP_REQCALLTHRESHOLD = 10,
PVSCSI_CMD_GET_MAX_TARGETS = 11,
PVSCSI_CMD_LAST = 12,
};
struct pvscsi_cmd_desc_reset_device {
uint32_t target;
uint8_t lun[8];
};
struct pvscsi_cmd_desc_abort_cmd {
uint64_t context;
uint32_t target;
uint32_t pad;
};
#define PVSCSI_SETUP_RINGS_MAX_NUM_PAGES 32
#define PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES 16
struct pvscsi_cmd_desc_setup_rings {
uint32_t req_ring_num_pages;
uint32_t cmp_ring_num_pages;
uint64_t rings_state_ppn;
uint64_t req_ring_ppns[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
uint64_t cmp_ring_ppns[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES];
};
struct pvscsi_cmd_desc_setup_msg_ring {
uint32_t num_pages;
uint32_t pad_;
uint64_t ring_ppns[PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES];
};
struct pvscsi_rings_state {
uint32_t req_prod_idx;
uint32_t req_cons_idx;
uint32_t req_num_entries_log2;
uint32_t cmp_prod_idx;
uint32_t cmp_cons_idx;
uint32_t cmp_num_entries_log2;
uint32_t req_call_threshold;
uint8_t _pad[100];
uint32_t msg_prod_idx;
uint32_t msg_cons_idx;
uint32_t msg_num_entries_log2;
};
#define PVSCSI_FLAG_CMD_WITH_SG_LIST (1 << 0)
#define PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB (1 << 1)
#define PVSCSI_FLAG_CMD_DIR_NONE (1 << 2)
#define PVSCSI_FLAG_CMD_DIR_TOHOST (1 << 3)
#define PVSCSI_FLAG_CMD_DIR_TODEVICE (1 << 4)
#define PVSCSI_FLAG_RESERVED_MASK (~MASK(5))
#define PVSCSI_INTR_CMPL_0 (1 << 0)
#define PVSCSI_INTR_CMPL_1 (1 << 1)
#define PVSCSI_INTR_CMPL_MASK MASK(2)
#define PVSCSI_INTR_MSG_0 (1 << 2)
#define PVSCSI_INTR_MSG_1 (1 << 3)
#define PVSCSI_INTR_MSG_MASK (MASK(2) << 2)
#define PVSCSI_INTR_ALL_SUPPORTED MASK(4)
struct pvscsi_ring_req_desc {
uint64_t context;
uint64_t data_addr;
uint64_t data_len;
uint64_t sense_addr;
uint32_t sense_len;
uint32_t flags;
uint8_t cdb[16];
uint8_t cdb_len;
uint8_t lun[8];
uint8_t tag;
uint8_t bus;
uint8_t target;
uint8_t vcpu_hint;
uint8_t unused[59];
};
struct pvscsi_ring_cmp_desc {
uint64_t context;
uint64_t data_len;
uint32_t sense_len;
uint16_t host_status;
uint16_t scsi_status;
uint32_t _pad[2];
};
#define PVSCSI_MAX_SG_ENTRIES_PER_SEGMENT 128
#define PVSCSI_MAX_NUM_SG_SEGMENTS 128
#define PVSCSI_SGE_FLAG_CHAIN_ELEMENT (1 << 0)
struct pvscsi_sg_element {
uint64_t addr;
uint32_t length;
uint32_t flags;
};
enum pvscsi_msg_type {
PVSCSI_MSG_DEV_ADDED = 0,
PVSCSI_MSG_DEV_REMOVED = 1,
PVSCSI_MSG_LAST = 2,
};
struct pvscsi_ring_msg_desc {
uint32_t type;
uint32_t args[31];
};
struct pvscsi_ring_msg_dev_status_changed {
uint32_t type;
uint32_t bus;
uint32_t target;
uint8_t lun[8];
uint32_t pad[27];
};
struct pvscsi_cmd_desc_setup_req_call {
uint32_t enable;
};
#define PVSCSI_MAX_NUM_PAGES_REQ_RING PVSCSI_SETUP_RINGS_MAX_NUM_PAGES
#define PVSCSI_MAX_NUM_PAGES_CMP_RING PVSCSI_SETUP_RINGS_MAX_NUM_PAGES
#define PVSCSI_MAX_NUM_PAGES_MSG_RING PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES
#define PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE \
(PAGE_SIZE / sizeof(struct pvscsi_ring_req_desc))
#define PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE \
(PAGE_SIZE / sizeof(struct pvscs_ring_cmp_desc))
#define PVSCSI_MAX_NUM_MSG_ENTRIES_PER_PAGE \
(PAGE_SIZE / sizeof(struct pvscsi_ring_msg_desc))
#define PVSCSI_MAX_REQ_QUEUE_DEPTH \
(PVSCSI_MAX_NUM_PAGES_REQ_RING * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE)
#define PVSCSI_MAX_CMP_QUEUE_DEPTH \
(PVSCSI_MAX_NUM_PAGES_CMP_RING * PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE)
#define PVSCSI_MAX_QUEUE_DEPTH \
MAX(PVSCSI_MAX_REQ_QUEUE_DEPTH, PVSCSI_MAX_CMP_QUEUE_DEPTH)
enum pvscsi_host_status {
BTSTAT_SUCCESS = 0x00,
BTSTAT_LINKED_COMMAND_COMPLETED = 0x0a,
BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG = 0x0b,
BTSTAT_DATA_UNDERRUN = 0x0c,
BTSTAT_SELTIMEO = 0x11,
BTSTAT_DATARUN = 0x12,
BTSTAT_BUSFREE = 0x13,
BTSTAT_INVPHASE = 0x14,
BTSTAT_INVCODE = 0x15,
BTSTAT_INVOPCODE = 0x16,
BTSTAT_LUNMISMATCH = 0x17,
BTSTAT_INVPARAM = 0x1a,
BTSTAT_SENSFAILED = 0x1b,
BTSTAT_TAGREJECT = 0x1c,
BTSTAT_BADMSG = 0x1d,
BTSTAT_HAHARDWARE = 0x20,
BTSTAT_NORESPONSE = 0x21,
BTSTAT_SENTRST = 0x22,
BTSTAT_RECVRST = 0x23,
BTSTAT_DISCONNECT = 0x24,
BTSTAT_BUSRESET = 0x25,
BTSTAT_ABORTQUEUE = 0x26,
BTSTAT_HASOFTWARE = 0x27,
BTSTAT_HATIMEOUT = 0x30,
BTSTAT_SCSIPARITY = 0x34,
};
#endif /* !_PVSCSI_H_ */