1565657caSYuri Pankov /* 2565657caSYuri Pankov * Copyright (C) 2008-2014, VMware, Inc. All Rights Reserved. 3565657caSYuri Pankov * 4565657caSYuri Pankov * Redistribution and use in source and binary forms, with or without 5565657caSYuri Pankov * modification, are permitted provided that the following conditions are met: 6565657caSYuri Pankov * 1. Redistributions of source code must retain the above copyright notice, 7565657caSYuri Pankov * this list of conditions and the following disclaimer. 8565657caSYuri Pankov * 2. Redistributions in binary form must reproduce the above copyright notice, 9565657caSYuri Pankov * this list of conditions and the following disclaimer in the documentation 10565657caSYuri Pankov * and/or other materials provided with the distribution. 11565657caSYuri Pankov * 12565657caSYuri Pankov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 13565657caSYuri Pankov * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 14565657caSYuri Pankov * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 15565657caSYuri Pankov * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY 16565657caSYuri Pankov * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 17565657caSYuri Pankov * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 18565657caSYuri Pankov * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 19565657caSYuri Pankov * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20565657caSYuri Pankov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21565657caSYuri Pankov * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22565657caSYuri Pankov */ 23565657caSYuri Pankov 24565657caSYuri Pankov #ifndef _PVSCSI_H_ 25565657caSYuri Pankov #define _PVSCSI_H_ 26565657caSYuri Pankov 27565657caSYuri Pankov #include <sys/types.h> 28565657caSYuri Pankov 29565657caSYuri Pankov #define PVSCSI_MAX_NUM_SG_ENTRIES_PER_SEGMENT 128 30565657caSYuri Pankov 31565657caSYuri Pankov #define MASK(n) ((1 << (n)) - 1) /* make an n-bit mask */ 32565657caSYuri Pankov 33565657caSYuri Pankov #define PCI_DEVICE_ID_VMWARE_PVSCSI 0x07C0 34565657caSYuri Pankov 35565657caSYuri Pankov /* 36565657caSYuri Pankov * host adapter status/error codes 37565657caSYuri Pankov */ 38565657caSYuri Pankov enum HostBusAdapterStatus { 39565657caSYuri Pankov BTSTAT_SUCCESS = 0x00, /* CCB complete normally with */ 40565657caSYuri Pankov /* no errors */ 41565657caSYuri Pankov BTSTAT_LINKED_COMMAND_COMPLETED = 0x0a, 42565657caSYuri Pankov BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG = 0x0b, 43565657caSYuri Pankov BTSTAT_DATA_UNDERRUN = 0x0c, 44565657caSYuri Pankov BTSTAT_SELTIMEO = 0x11, /* SCSI selection timeout */ 45565657caSYuri Pankov BTSTAT_DATARUN = 0x12, /* data overrun/underrun */ 46565657caSYuri Pankov BTSTAT_BUSFREE = 0x13, /* unexpected bus free */ 47565657caSYuri Pankov BTSTAT_INVPHASE = 0x14, /* invalid bus phase or sequence */ 48565657caSYuri Pankov /* requested by target */ 49565657caSYuri Pankov BTSTAT_LUNMISMATCH = 0x17, /* linked CCB has different LUN from */ 50565657caSYuri Pankov /* first CCB */ 51565657caSYuri Pankov BTSTAT_INVPARAM = 0x1a, /* invalid parameter in CCB */ 52565657caSYuri Pankov /* or segment list */ 53565657caSYuri Pankov BTSTAT_SENSFAILED = 0x1b, /* auto request sense failed */ 54565657caSYuri Pankov BTSTAT_TAGREJECT = 0x1c, /* SCSI II tagged queueing message */ 55565657caSYuri Pankov /* rejected by target */ 56565657caSYuri Pankov BTSTAT_BADMSG = 0x1d, /* unsupported message received by */ 57565657caSYuri Pankov /* the host adapter */ 58565657caSYuri Pankov BTSTAT_HAHARDWARE = 0x20, /* host adapter hardware failed */ 59565657caSYuri Pankov BTSTAT_NORESPONSE = 0x21, /* target did not respond to */ 60565657caSYuri Pankov /* SCSI ATN, sent a SCSI RST */ 61565657caSYuri Pankov BTSTAT_SENTRST = 0x22, /* host adapter asserted a SCSI RST */ 62565657caSYuri Pankov BTSTAT_RECVRST = 0x23, /* other SCSI devices asserted */ 63565657caSYuri Pankov /* a SCSI RST */ 64565657caSYuri Pankov BTSTAT_DISCONNECT = 0x24, /* target device reconnected */ 65565657caSYuri Pankov /* improperly (w/o tag) */ 66565657caSYuri Pankov BTSTAT_BUSRESET = 0x25, /* host adapter issued */ 67565657caSYuri Pankov /* BUS device reset */ 68565657caSYuri Pankov BTSTAT_ABORTQUEUE = 0x26, /* abort queue generated */ 69565657caSYuri Pankov BTSTAT_HASOFTWARE = 0x27, /* host adapter software error */ 70565657caSYuri Pankov BTSTAT_HATIMEOUT = 0x30, /* host adapter hardware */ 71565657caSYuri Pankov /* timeout error */ 72565657caSYuri Pankov BTSTAT_SCSIPARITY = 0x34, /* SCSI parity error detected */ 73565657caSYuri Pankov }; 74565657caSYuri Pankov 75565657caSYuri Pankov /* 76565657caSYuri Pankov * SCSI device status values. 77565657caSYuri Pankov */ 78565657caSYuri Pankov enum ScsiDeviceStatus { 79565657caSYuri Pankov SDSTAT_GOOD = 0x00, /* No errors. */ 80565657caSYuri Pankov SDSTAT_CHECK = 0x02, /* Check condition. */ 81565657caSYuri Pankov }; 82565657caSYuri Pankov 83565657caSYuri Pankov /* 84565657caSYuri Pankov * Register offsets. 85565657caSYuri Pankov * 86565657caSYuri Pankov * These registers are accessible both via i/o space and mm i/o. 87565657caSYuri Pankov */ 88565657caSYuri Pankov 89565657caSYuri Pankov enum PVSCSIRegOffset { 90565657caSYuri Pankov PVSCSI_REG_OFFSET_COMMAND = 0x0, 91565657caSYuri Pankov PVSCSI_REG_OFFSET_COMMAND_DATA = 0x4, 92565657caSYuri Pankov PVSCSI_REG_OFFSET_COMMAND_STATUS = 0x8, 93565657caSYuri Pankov PVSCSI_REG_OFFSET_LAST_STS_0 = 0x100, 94565657caSYuri Pankov PVSCSI_REG_OFFSET_LAST_STS_1 = 0x104, 95565657caSYuri Pankov PVSCSI_REG_OFFSET_LAST_STS_2 = 0x108, 96565657caSYuri Pankov PVSCSI_REG_OFFSET_LAST_STS_3 = 0x10c, 97565657caSYuri Pankov PVSCSI_REG_OFFSET_INTR_STATUS = 0x100c, 98565657caSYuri Pankov PVSCSI_REG_OFFSET_INTR_MASK = 0x2010, 99565657caSYuri Pankov PVSCSI_REG_OFFSET_KICK_NON_RW_IO = 0x3014, 100565657caSYuri Pankov PVSCSI_REG_OFFSET_DEBUG = 0x3018, 101565657caSYuri Pankov PVSCSI_REG_OFFSET_KICK_RW_IO = 0x4018, 102565657caSYuri Pankov }; 103565657caSYuri Pankov 104565657caSYuri Pankov /* 105565657caSYuri Pankov * Virtual h/w commands. 106565657caSYuri Pankov */ 107565657caSYuri Pankov 108565657caSYuri Pankov enum PVSCSICommands { 109565657caSYuri Pankov PVSCSI_CMD_FIRST = 0, /* has to be first */ 110565657caSYuri Pankov 111565657caSYuri Pankov PVSCSI_CMD_ADAPTER_RESET = 1, 112565657caSYuri Pankov PVSCSI_CMD_ISSUE_SCSI = 2, 113565657caSYuri Pankov PVSCSI_CMD_SETUP_RINGS = 3, 114565657caSYuri Pankov PVSCSI_CMD_RESET_BUS = 4, 115565657caSYuri Pankov PVSCSI_CMD_RESET_DEVICE = 5, 116565657caSYuri Pankov PVSCSI_CMD_ABORT_CMD = 6, 117565657caSYuri Pankov PVSCSI_CMD_CONFIG = 7, 118565657caSYuri Pankov PVSCSI_CMD_SETUP_MSG_RING = 8, 119565657caSYuri Pankov PVSCSI_CMD_DEVICE_UNPLUG = 9, 120565657caSYuri Pankov PVSCSI_CMD_SETUP_REQCALLTHRESHOLD = 10, 121565657caSYuri Pankov 122565657caSYuri Pankov PVSCSI_CMD_LAST = 11 /* has to be last */ 123565657caSYuri Pankov }; 124565657caSYuri Pankov 125565657caSYuri Pankov /* 126565657caSYuri Pankov * Command descriptor for PVSCSI_CMD_RESET_DEVICE -- 127565657caSYuri Pankov */ 128565657caSYuri Pankov #pragma pack(1) 129565657caSYuri Pankov struct PVSCSICmdDescResetDevice { 130565657caSYuri Pankov uint32_t target; 131565657caSYuri Pankov uint8_t lun[8]; 132565657caSYuri Pankov }; 133565657caSYuri Pankov #pragma pack() 134565657caSYuri Pankov 135565657caSYuri Pankov /* 136565657caSYuri Pankov * Command descriptor for PVSCSI_CMD_CONFIG -- 137565657caSYuri Pankov */ 138565657caSYuri Pankov #pragma pack(1) 139565657caSYuri Pankov struct PVSCSICmdDescConfigCmd { 140565657caSYuri Pankov uint64_t cmpAddr; 141565657caSYuri Pankov uint64_t configPageAddress; 142565657caSYuri Pankov uint32_t configPageNum; 143565657caSYuri Pankov uint32_t _pad; 144565657caSYuri Pankov }; 145565657caSYuri Pankov #pragma pack() 146565657caSYuri Pankov 147565657caSYuri Pankov /* 148565657caSYuri Pankov * Command descriptor for PVSCSI_CMD_SETUP_REQCALLTHRESHOLD -- 149565657caSYuri Pankov */ 150565657caSYuri Pankov #pragma pack(1) 151565657caSYuri Pankov struct PVSCSICmdDescSetupReqCall { 152565657caSYuri Pankov uint32_t enable; 153565657caSYuri Pankov }; 154565657caSYuri Pankov #pragma pack() 155565657caSYuri Pankov 156565657caSYuri Pankov enum PVSCSIConfigPageType { 157565657caSYuri Pankov PVSCSI_CONFIG_PAGE_CONTROLLER = 0x1958, 158565657caSYuri Pankov PVSCSI_CONFIG_PAGE_PHY = 0x1959, 159565657caSYuri Pankov PVSCSI_CONFIG_PAGE_DEVICE = 0x195a, 160565657caSYuri Pankov }; 161565657caSYuri Pankov 162565657caSYuri Pankov enum PVSCSIConfigPageAddressType { 163565657caSYuri Pankov PVSCSI_CONFIG_CONTROLLER_ADDRESS = 0x2120, 164565657caSYuri Pankov PVSCSI_CONFIG_BUSTARGET_ADDRESS = 0x2121, 165565657caSYuri Pankov PVSCSI_CONFIG_PHY_ADDRESS = 0x2122, 166565657caSYuri Pankov }; 167565657caSYuri Pankov 168565657caSYuri Pankov /* 169565657caSYuri Pankov * Command descriptor for PVSCSI_CMD_ABORT_CMD -- 170565657caSYuri Pankov * 171565657caSYuri Pankov * - currently does not support specifying the LUN. 172565657caSYuri Pankov * - _pad should be 0. 173565657caSYuri Pankov */ 174565657caSYuri Pankov 175565657caSYuri Pankov struct PVSCSICmdDescAbortCmd { 176565657caSYuri Pankov uint64_t context; 177565657caSYuri Pankov uint32_t target; 178565657caSYuri Pankov uint32_t _pad; 179565657caSYuri Pankov } __packed; 180565657caSYuri Pankov 181565657caSYuri Pankov /* 182565657caSYuri Pankov * Command descriptor for PVSCSI_CMD_SETUP_RINGS -- 183565657caSYuri Pankov * 184565657caSYuri Pankov * Notes: 185565657caSYuri Pankov * - reqRingNumPages and cmpRingNumPages need to be power of two. 186565657caSYuri Pankov * - reqRingNumPages and cmpRingNumPages need to be different from 0, 187565657caSYuri Pankov * - reqRingNumPages and cmpRingNumPages need to be inferior to 188565657caSYuri Pankov * PVSCSI_SETUP_RINGS_MAX_NUM_PAGES. 189565657caSYuri Pankov */ 190565657caSYuri Pankov #define PVSCSI_SETUP_RINGS_MAX_NUM_PAGES 32 191565657caSYuri Pankov 192565657caSYuri Pankov #pragma pack(1) 193565657caSYuri Pankov struct PVSCSICmdDescSetupRings { 194565657caSYuri Pankov uint32_t reqRingNumPages; 195565657caSYuri Pankov uint32_t cmpRingNumPages; 196565657caSYuri Pankov uint64_t ringsStatePPN; 197565657caSYuri Pankov uint64_t reqRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES]; 198565657caSYuri Pankov uint64_t cmpRingPPNs[PVSCSI_SETUP_RINGS_MAX_NUM_PAGES]; 199565657caSYuri Pankov }; 200565657caSYuri Pankov #pragma pack() 201565657caSYuri Pankov 202565657caSYuri Pankov /* 203565657caSYuri Pankov * Command descriptor for PVSCSI_CMD_SETUP_MSG_RING -- 204565657caSYuri Pankov * 205565657caSYuri Pankov * Notes: 206565657caSYuri Pankov * - this command was not supported in the initial revision of the h/w 207565657caSYuri Pankov * interface. Before using it, you need to check that it is supported by 208565657caSYuri Pankov * writing PVSCSI_CMD_SETUP_MSG_RING to the 'command' register, then 209565657caSYuri Pankov * immediately after read the 'command status' register: 210565657caSYuri Pankov * * a value of -1 means that the cmd is NOT supported, 211565657caSYuri Pankov * * a value != -1 means that the cmd IS supported. 212565657caSYuri Pankov * If it's supported the 'command status' register should return: 213565657caSYuri Pankov * sizeof(PVSCSICmdDescSetupMsgRing) / sizeof(uint32_t). 214565657caSYuri Pankov * - this command should be issued _after_ the usual SETUP_RINGS so that the 215565657caSYuri Pankov * RingsState page is already setup. If not, the command is a nop. 216565657caSYuri Pankov * - numPages needs to be a power of two, 217565657caSYuri Pankov * - numPages needs to be different from 0, 218565657caSYuri Pankov * - _pad should be zero. 219565657caSYuri Pankov */ 220565657caSYuri Pankov #define PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES 16 221565657caSYuri Pankov 222565657caSYuri Pankov #pragma pack(1) 223565657caSYuri Pankov struct PVSCSICmdDescSetupMsgRing { 224565657caSYuri Pankov uint32_t numPages; 225565657caSYuri Pankov uint32_t _pad; 226565657caSYuri Pankov uint64_t ringPPNs[PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES]; 227565657caSYuri Pankov }; 228565657caSYuri Pankov #pragma pack() 229565657caSYuri Pankov 230565657caSYuri Pankov enum PVSCSIMsgType { 231565657caSYuri Pankov PVSCSI_MSG_DEV_ADDED = 0, 232565657caSYuri Pankov PVSCSI_MSG_DEV_REMOVED = 1, 233565657caSYuri Pankov PVSCSI_MSG_LAST = 2, 234565657caSYuri Pankov }; 235565657caSYuri Pankov 236565657caSYuri Pankov /* 237565657caSYuri Pankov * Msg descriptor. 238565657caSYuri Pankov * 239565657caSYuri Pankov * sizeof(struct PVSCSIRingMsgDesc) == 128. 240565657caSYuri Pankov * 241565657caSYuri Pankov * - type is of type enum PVSCSIMsgType. 242565657caSYuri Pankov * - the content of args depend on the type of event being delivered. 243565657caSYuri Pankov */ 244565657caSYuri Pankov #pragma pack(1) 245565657caSYuri Pankov struct PVSCSIRingMsgDesc { 246565657caSYuri Pankov uint32_t type; 247565657caSYuri Pankov uint32_t args[31]; 248565657caSYuri Pankov }; 249565657caSYuri Pankov #pragma pack() 250565657caSYuri Pankov 251565657caSYuri Pankov #pragma pack(1) 252565657caSYuri Pankov struct PVSCSIMsgDescDevStatusChanged { 253565657caSYuri Pankov uint32_t type; /* PVSCSI_MSG_DEV _ADDED / _REMOVED */ 254565657caSYuri Pankov uint32_t bus; 255565657caSYuri Pankov uint32_t target; 256565657caSYuri Pankov uint8_t lun[8]; 257565657caSYuri Pankov uint32_t pad[27]; 258565657caSYuri Pankov }; 259565657caSYuri Pankov #pragma pack() 260565657caSYuri Pankov 261565657caSYuri Pankov /* 262565657caSYuri Pankov * Rings state. 263565657caSYuri Pankov * 264565657caSYuri Pankov * - the fields: 265565657caSYuri Pankov * . msgProdIdx, 266565657caSYuri Pankov * . msgConsIdx, 267565657caSYuri Pankov * . msgNumEntriesLog2, 268565657caSYuri Pankov * .. are only used once the SETUP_MSG_RING cmd has been issued. 269565657caSYuri Pankov * - '_pad' helps to ensure that the msg related fields are on their own 270565657caSYuri Pankov * cache-line. 271565657caSYuri Pankov */ 272565657caSYuri Pankov #pragma pack(1) 273565657caSYuri Pankov struct PVSCSIRingsState { 274565657caSYuri Pankov uint32_t reqProdIdx; 275565657caSYuri Pankov uint32_t reqConsIdx; 276565657caSYuri Pankov uint32_t reqNumEntriesLog2; 277565657caSYuri Pankov 278565657caSYuri Pankov uint32_t cmpProdIdx; 279565657caSYuri Pankov uint32_t cmpConsIdx; 280565657caSYuri Pankov uint32_t cmpNumEntriesLog2; 281565657caSYuri Pankov 282565657caSYuri Pankov uint32_t reqCallThreshold; 283565657caSYuri Pankov 284565657caSYuri Pankov uint8_t _pad[100]; 285565657caSYuri Pankov 286565657caSYuri Pankov uint32_t msgProdIdx; 287565657caSYuri Pankov uint32_t msgConsIdx; 288565657caSYuri Pankov uint32_t msgNumEntriesLog2; 289565657caSYuri Pankov }; 290565657caSYuri Pankov #pragma pack() 291565657caSYuri Pankov 292565657caSYuri Pankov /* 293565657caSYuri Pankov * Request descriptor. 294565657caSYuri Pankov * 295565657caSYuri Pankov * sizeof(RingReqDesc) = 128 296565657caSYuri Pankov * 297565657caSYuri Pankov * - context: is a unique identifier of a command. It could normally be any 298565657caSYuri Pankov * 64bit value, however we currently store it in the serialNumber variable 299565657caSYuri Pankov * of struct SCSI_Command, so we have the following restrictions due to the 300565657caSYuri Pankov * way this field is handled in the vmkernel storage stack: 301565657caSYuri Pankov * * this value can't be 0, 302565657caSYuri Pankov * * the upper 32bit need to be 0 since serialNumber is as a uint32_t. 303565657caSYuri Pankov * Currently tracked as PR 292060. 304565657caSYuri Pankov * - dataLen: contains the total number of bytes that need to be transferred. 305565657caSYuri Pankov * - dataAddr: 306565657caSYuri Pankov * * if PVSCSI_FLAG_CMD_WITH_SG_LIST is set: dataAddr is the PA of the first 307565657caSYuri Pankov * s/g table segment, each s/g segment is entirely contained on a single 308565657caSYuri Pankov * page of physical memory, 309565657caSYuri Pankov * * if PVSCSI_FLAG_CMD_WITH_SG_LIST is NOT set, then dataAddr is the PA of 310565657caSYuri Pankov * the buffer used for the DMA transfer, 311565657caSYuri Pankov * - flags: 312565657caSYuri Pankov * * PVSCSI_FLAG_CMD_WITH_SG_LIST: see dataAddr above, 313565657caSYuri Pankov * * PVSCSI_FLAG_CMD_DIR_NONE: no DMA involved, 314565657caSYuri Pankov * * PVSCSI_FLAG_CMD_DIR_TOHOST: transfer from device to main memory, 315565657caSYuri Pankov * * PVSCSI_FLAG_CMD_DIR_TODEVICE: transfer from main memory to device, 316565657caSYuri Pankov * * PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB: reserved to handle CDBs larger than 317565657caSYuri Pankov * 16bytes. To be specified. 318565657caSYuri Pankov * - vcpuHint: vcpuId of the processor that will be most likely waiting for the 319565657caSYuri Pankov * completion of the i/o. For guest OSes that use lowest priority message 320565657caSYuri Pankov * delivery mode (such as windows), we use this "hint" to deliver the 321565657caSYuri Pankov * completion action to the proper vcpu. For now, we can use the vcpuId of 322565657caSYuri Pankov * the processor that initiated the i/o as a likely candidate for the vcpu 323565657caSYuri Pankov * that will be waiting for the completion.. 324565657caSYuri Pankov * - bus should be 0: we currently only support bus 0 for now. 325565657caSYuri Pankov * - unused should be zero'd. 326565657caSYuri Pankov */ 327565657caSYuri Pankov #define PVSCSI_FLAG_CMD_WITH_SG_LIST (1 << 0) 328565657caSYuri Pankov #define PVSCSI_FLAG_CMD_OUT_OF_BAND_CDB (1 << 1) 329565657caSYuri Pankov #define PVSCSI_FLAG_CMD_DIR_NONE (1 << 2) 330565657caSYuri Pankov #define PVSCSI_FLAG_CMD_DIR_TOHOST (1 << 3) 331565657caSYuri Pankov #define PVSCSI_FLAG_CMD_DIR_TODEVICE (1 << 4) 332565657caSYuri Pankov 333565657caSYuri Pankov #pragma pack(1) 334565657caSYuri Pankov struct PVSCSIRingReqDesc { 335565657caSYuri Pankov uint64_t context; 336565657caSYuri Pankov uint64_t dataAddr; 337565657caSYuri Pankov uint64_t dataLen; 338565657caSYuri Pankov uint64_t senseAddr; 339565657caSYuri Pankov uint32_t senseLen; 340565657caSYuri Pankov uint32_t flags; 341565657caSYuri Pankov uint8_t cdb[16]; 342565657caSYuri Pankov uint8_t cdbLen; 343565657caSYuri Pankov uint8_t lun[8]; 344565657caSYuri Pankov uint8_t tag; 345565657caSYuri Pankov uint8_t bus; 346565657caSYuri Pankov uint8_t target; 347565657caSYuri Pankov uint8_t vcpuHint; 348565657caSYuri Pankov uint8_t unused[59]; 349565657caSYuri Pankov }; 350565657caSYuri Pankov #pragma pack() 351565657caSYuri Pankov 352565657caSYuri Pankov /* 353565657caSYuri Pankov * Scatter-gather list management. 354565657caSYuri Pankov * 355565657caSYuri Pankov * As described above, when PVSCSI_FLAG_CMD_WITH_SG_LIST is set in the 356565657caSYuri Pankov * RingReqDesc.flags, then RingReqDesc.dataAddr is the PA of the first s/g 357565657caSYuri Pankov * table segment. 358565657caSYuri Pankov * 359565657caSYuri Pankov * - each segment of the s/g table contain a succession of struct 360565657caSYuri Pankov * PVSCSISGElement. 361565657caSYuri Pankov * - each segment is entirely contained on a single physical page of memory. 362565657caSYuri Pankov * - a "chain" s/g element has the flag PVSCSI_SGE_FLAG_CHAIN_ELEMENT set in 363565657caSYuri Pankov * PVSCSISGElement.flags and in this case: 364565657caSYuri Pankov * * addr is the PA of the next s/g segment, 365565657caSYuri Pankov * * length is undefined, assumed to be 0. 366565657caSYuri Pankov */ 367565657caSYuri Pankov #pragma pack(1) 368565657caSYuri Pankov struct PVSCSISGElement { 369565657caSYuri Pankov uint64_t addr; 370565657caSYuri Pankov uint32_t length; 371565657caSYuri Pankov uint32_t flags; 372565657caSYuri Pankov }; 373565657caSYuri Pankov #pragma pack() 374565657caSYuri Pankov 375565657caSYuri Pankov /* 376565657caSYuri Pankov * Completion descriptor. 377565657caSYuri Pankov * 378565657caSYuri Pankov * sizeof(RingCmpDesc) = 32 379565657caSYuri Pankov * 380565657caSYuri Pankov * - context: identifier of the command. The same thing that was specified 381565657caSYuri Pankov * under "context" as part of struct RingReqDesc at initiation time, 382565657caSYuri Pankov * - dataLen: number of bytes transferred for the actual i/o operation, 383565657caSYuri Pankov * - senseLen: number of bytes written into the sense buffer, 384565657caSYuri Pankov * - hostStatus: adapter status, 385565657caSYuri Pankov * - scsiStatus: device status, 386565657caSYuri Pankov * - _pad should be zero. 387565657caSYuri Pankov */ 388565657caSYuri Pankov #pragma pack(1) 389565657caSYuri Pankov struct PVSCSIRingCmpDesc { 390565657caSYuri Pankov uint64_t context; 391565657caSYuri Pankov uint64_t dataLen; 392565657caSYuri Pankov uint32_t senseLen; 393565657caSYuri Pankov uint16_t hostStatus; 394565657caSYuri Pankov uint16_t scsiStatus; 395565657caSYuri Pankov uint32_t _pad[2]; 396565657caSYuri Pankov }; 397565657caSYuri Pankov #pragma pack() 398565657caSYuri Pankov 399565657caSYuri Pankov #pragma pack(1) 400565657caSYuri Pankov struct PVSCSIConfigPageHeader { 401565657caSYuri Pankov uint32_t pageNum; 402565657caSYuri Pankov uint16_t numDwords; 403565657caSYuri Pankov uint16_t hostStatus; 404565657caSYuri Pankov uint16_t scsiStatus; 405565657caSYuri Pankov uint16_t reserved[3]; 406565657caSYuri Pankov }; 407565657caSYuri Pankov #pragma pack() 408565657caSYuri Pankov 409565657caSYuri Pankov #pragma pack(1) 410565657caSYuri Pankov struct PVSCSIConfigPageController { 411565657caSYuri Pankov struct PVSCSIConfigPageHeader header; 412565657caSYuri Pankov uint64_t nodeWWN; /* Device name as defined in the SAS spec. */ 413565657caSYuri Pankov uint16_t manufacturer[64]; 414565657caSYuri Pankov uint16_t serialNumber[64]; 415565657caSYuri Pankov uint16_t opromVersion[32]; 416565657caSYuri Pankov uint16_t hwVersion[32]; 417565657caSYuri Pankov uint16_t firmwareVersion[32]; 418565657caSYuri Pankov uint32_t numPhys; 419565657caSYuri Pankov uint8_t useConsecutivePhyWWNs; 420565657caSYuri Pankov uint8_t reserved[3]; 421565657caSYuri Pankov }; 422565657caSYuri Pankov #pragma pack() 423565657caSYuri Pankov 424565657caSYuri Pankov /* 425565657caSYuri Pankov * Interrupt status / IRQ bits. 426565657caSYuri Pankov */ 427565657caSYuri Pankov 428565657caSYuri Pankov #define PVSCSI_INTR_CMPL_0 (1 << 0) 429565657caSYuri Pankov #define PVSCSI_INTR_CMPL_1 (1 << 1) 430565657caSYuri Pankov #define PVSCSI_INTR_CMPL_MASK MASK(2) 431565657caSYuri Pankov 432565657caSYuri Pankov #define PVSCSI_INTR_MSG_0 (1 << 2) 433565657caSYuri Pankov #define PVSCSI_INTR_MSG_1 (1 << 3) 434565657caSYuri Pankov #define PVSCSI_INTR_MSG_MASK (MASK(2) << 2) 435565657caSYuri Pankov 436565657caSYuri Pankov #define PVSCSI_INTR_ALL_SUPPORTED MASK(4) 437565657caSYuri Pankov 438565657caSYuri Pankov /* 439565657caSYuri Pankov * Number of MSI-X vectors supported. 440565657caSYuri Pankov */ 441565657caSYuri Pankov #define PVSCSI_MAX_INTRS 24 442565657caSYuri Pankov 443565657caSYuri Pankov /* 444565657caSYuri Pankov * Enumeration of supported MSI-X vectors 445565657caSYuri Pankov */ 446565657caSYuri Pankov #define PVSCSI_VECTOR_COMPLETION 0 447565657caSYuri Pankov 448565657caSYuri Pankov /* 449565657caSYuri Pankov * Misc constants for the rings. 450565657caSYuri Pankov */ 451565657caSYuri Pankov 452565657caSYuri Pankov #define PVSCSI_MAX_NUM_PAGES_REQ_RING PVSCSI_SETUP_RINGS_MAX_NUM_PAGES 453565657caSYuri Pankov #define PVSCSI_MAX_NUM_PAGES_CMP_RING PVSCSI_SETUP_RINGS_MAX_NUM_PAGES 454565657caSYuri Pankov #define PVSCSI_MAX_NUM_PAGES_MSG_RING PVSCSI_SETUP_MSG_RING_MAX_NUM_PAGES 455565657caSYuri Pankov 456565657caSYuri Pankov #define PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE \ 457565657caSYuri Pankov (PAGE_SIZE / sizeof (struct PVSCSIRingReqDesc)) 458565657caSYuri Pankov 459565657caSYuri Pankov #define PVSCSI_MAX_REQ_QUEUE_DEPTH \ 460565657caSYuri Pankov (PVSCSI_MAX_NUM_PAGES_REQ_RING * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE) 461565657caSYuri Pankov 462565657caSYuri Pankov #define PVSCSI_MEM_SPACE_COMMAND_NUM_PAGES 1 463565657caSYuri Pankov #define PVSCSI_MEM_SPACE_INTR_STATUS_NUM_PAGES 1 464565657caSYuri Pankov #define PVSCSI_MEM_SPACE_MISC_NUM_PAGES 2 465565657caSYuri Pankov #define PVSCSI_MEM_SPACE_KICK_IO_NUM_PAGES 2 466565657caSYuri Pankov #define PVSCSI_MEM_SPACE_MSIX_NUM_PAGES 2 467565657caSYuri Pankov 468565657caSYuri Pankov enum PVSCSIMemSpace { 469565657caSYuri Pankov PVSCSI_MEM_SPACE_COMMAND_PAGE = 0, 470565657caSYuri Pankov PVSCSI_MEM_SPACE_INTR_STATUS_PAGE = 1, 471565657caSYuri Pankov PVSCSI_MEM_SPACE_MISC_PAGE = 2, 472565657caSYuri Pankov PVSCSI_MEM_SPACE_KICK_IO_PAGE = 4, 473565657caSYuri Pankov PVSCSI_MEM_SPACE_MSIX_TABLE_PAGE = 6, 474565657caSYuri Pankov PVSCSI_MEM_SPACE_MSIX_PBA_PAGE = 7, 475565657caSYuri Pankov }; 476565657caSYuri Pankov 477565657caSYuri Pankov #define PVSCSI_MEM_SPACE_NUM_PAGES \ 478565657caSYuri Pankov (PVSCSI_MEM_SPACE_COMMAND_NUM_PAGES + \ 479565657caSYuri Pankov PVSCSI_MEM_SPACE_INTR_STATUS_NUM_PAGES +\ 480565657caSYuri Pankov PVSCSI_MEM_SPACE_MISC_NUM_PAGES + \ 481565657caSYuri Pankov PVSCSI_MEM_SPACE_KICK_IO_NUM_PAGES + \ 482565657caSYuri Pankov PVSCSI_MEM_SPACE_MSIX_NUM_PAGES) 483565657caSYuri Pankov 484565657caSYuri Pankov #define PVSCSI_MEM_SPACE_SIZE (PVSCSI_MEM_SPACE_NUM_PAGES * PAGE_SIZE) 485565657caSYuri Pankov 486565657caSYuri Pankov #endif /* _PVSCSI_H_ */ 487