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