• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2010 - 2013 UNISYS CORPORATION */
2 /* All rights reserved. */
3 #ifndef __IOCHANNEL_H__
4 #define __IOCHANNEL_H__
5 
6 /*
7  * Everything needed for IOPart-GuestPart communication is define in
8  * this file.  Note: Everything is OS-independent because this file is
9  * used by Windows, Linux and possible EFI drivers.  */
10 
11 /*
12  * Communication flow between the IOPart and GuestPart uses the channel headers
13  * channel state.  The following states are currently being used:
14  *       UNINIT(All Zeroes), CHANNEL_ATTACHING, CHANNEL_ATTACHED, CHANNEL_OPENED
15  *
16  * additional states will be used later.  No locking is needed to switch between
17  * states due to the following rules:
18  *
19  *      1.  IOPart is only the only partition allowed to change from UNIT
20  *      2.  IOPart is only the only partition allowed to change from
21  *		CHANNEL_ATTACHING
22  *      3.  GuestPart is only the only partition allowed to change from
23  *		CHANNEL_ATTACHED
24  *
25  * The state changes are the following: IOPart sees the channel is in UNINIT,
26  *        UNINIT -> CHANNEL_ATTACHING (performed only by IOPart)
27  *        CHANNEL_ATTACHING -> CHANNEL_ATTACHED (performed only by IOPart)
28  *        CHANNEL_ATTACHED -> CHANNEL_OPENED (performed only by GuestPart)
29  */
30 
31 #include <linux/uuid.h>
32 
33 #include <linux/dma-direction.h>
34 #include "channel.h"
35 #include "channel_guid.h"
36 
37 #define ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
38 #define ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE ULTRA_CHANNEL_PROTOCOL_SIGNATURE
39 #define ULTRA_VSWITCH_CHANNEL_PROTOCOL_SIGNATURE \
40 	ULTRA_CHANNEL_PROTOCOL_SIGNATURE
41 
42 /* Must increment these whenever you insert or delete fields within this channel
43  * struct.  Also increment whenever you change the meaning of fields within this
44  * channel struct so as to break pre-existing software.  Note that you can
45  * usually add fields to the END of the channel struct withOUT needing to
46  * increment this.
47  */
48 #define ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID 2
49 #define ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID 2
50 #define ULTRA_VSWITCH_CHANNEL_PROTOCOL_VERSIONID 1
51 
52 #define SPAR_VHBA_CHANNEL_OK_CLIENT(ch)			\
53 	(spar_check_channel_client(ch, spar_vhba_channel_protocol_uuid, \
54 				   "vhba", MIN_IO_CHANNEL_SIZE,	\
55 				   ULTRA_VHBA_CHANNEL_PROTOCOL_VERSIONID, \
56 				   ULTRA_VHBA_CHANNEL_PROTOCOL_SIGNATURE))
57 
58 #define SPAR_VNIC_CHANNEL_OK_CLIENT(ch)			\
59 	(spar_check_channel_client(ch, spar_vnic_channel_protocol_uuid, \
60 				   "vnic", MIN_IO_CHANNEL_SIZE,	\
61 				   ULTRA_VNIC_CHANNEL_PROTOCOL_VERSIONID, \
62 				   ULTRA_VNIC_CHANNEL_PROTOCOL_SIGNATURE))
63 
64 /*
65  * Everything necessary to handle SCSI & NIC traffic between Guest Partition and
66  * IO Partition is defined below.
67  */
68 
69 /*
70  * Defines and enums.
71  */
72 
73 #define MINNUM(a, b) (((a) < (b)) ? (a) : (b))
74 #define MAXNUM(a, b) (((a) > (b)) ? (a) : (b))
75 
76 /* these define the two queues per data channel between iopart and
77  * ioguestparts
78  */
79 #define IOCHAN_TO_IOPART 0 /* used by ioguestpart to 'insert' signals to
80 			    * iopart */
81 
82 #define IOCHAN_FROM_IOPART 1 /* used by ioguestpart to 'remove' signals from
83 			      * iopart - same queue as previous queue */
84 
85 /* size of cdb - i.e., scsi cmnd */
86 #define MAX_CMND_SIZE 16
87 
88 #define MAX_SENSE_SIZE 64
89 
90 #define MAX_PHYS_INFO 64
91 
92 /* various types of network packets that can be sent in cmdrsp */
93 enum net_types {
94 	NET_RCV_POST = 0,	/* submit buffer to hold receiving
95 				 * incoming packet */
96 	/* virtnic -> uisnic */
97 	NET_RCV,		/* incoming packet received */
98 	/* uisnic -> virtpci */
99 	NET_XMIT,		/* for outgoing net packets      */
100 	/* virtnic -> uisnic */
101 	NET_XMIT_DONE,		/* outgoing packet xmitted */
102 	/* uisnic -> virtpci */
103 	NET_RCV_ENBDIS,		/* enable/disable packet reception */
104 	/* virtnic -> uisnic */
105 	NET_RCV_ENBDIS_ACK,	/* acknowledge enable/disable packet
106 				 * reception */
107 	/* uisnic -> virtnic */
108 	NET_RCV_PROMISC,	/* enable/disable promiscuous mode */
109 	/* virtnic -> uisnic */
110 	NET_CONNECT_STATUS,	/* indicate the loss or restoration of a network
111 				 * connection */
112 	/* uisnic -> virtnic */
113 	NET_MACADDR,		/* indicates the client has requested to update
114 				 * its MAC addr */
115 	NET_MACADDR_ACK,	/* MAC address */
116 
117 };
118 
119 #define		ETH_HEADER_SIZE 14	/* size of ethernet header */
120 
121 #define		ETH_MIN_DATA_SIZE 46	/* minimum eth data size */
122 #define		ETH_MIN_PACKET_SIZE (ETH_HEADER_SIZE + ETH_MIN_DATA_SIZE)
123 
124 #define		ETH_MAX_MTU 16384	/* maximum data size */
125 
126 #ifndef MAX_MACADDR_LEN
127 #define MAX_MACADDR_LEN 6	/* number of bytes in MAC address */
128 #endif				/* MAX_MACADDR_LEN */
129 
130 /* various types of scsi task mgmt commands  */
131 enum task_mgmt_types {
132 	TASK_MGMT_ABORT_TASK = 1,
133 	TASK_MGMT_BUS_RESET,
134 	TASK_MGMT_LUN_RESET,
135 	TASK_MGMT_TARGET_RESET,
136 };
137 
138 /* various types of vdisk mgmt commands  */
139 enum vdisk_mgmt_types {
140 	VDISK_MGMT_ACQUIRE = 1,
141 	VDISK_MGMT_RELEASE,
142 };
143 
144 struct phys_info {
145 	u64 pi_pfn;
146 	u16 pi_off;
147 	u16 pi_len;
148 } __packed;
149 
150 #define MIN_NUMSIGNALS 64
151 
152 /* structs with pragma pack  */
153 
154 struct guest_phys_info {
155 	u64 address;
156 	u64 length;
157 } __packed;
158 
159 #define GPI_ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(struct guest_phys_info))
160 
161 struct uisscsi_dest {
162 	u32 channel;		/* channel == bus number */
163 	u32 id;			/* id == target number */
164 	u32 lun;		/* lun == logical unit number */
165 } __packed;
166 
167 struct vhba_wwnn {
168 	u32 wwnn1;
169 	u32 wwnn2;
170 } __packed;
171 
172 /* WARNING: Values stired in this structure must contain maximum counts (not
173  * maximum values). */
174 struct vhba_config_max {	/* 20 bytes */
175 	u32 max_channel;	/* maximum channel for devices attached to this
176 				 * bus */
177 	u32 max_id;		/* maximum SCSI ID for devices attached to this
178 				 * bus */
179 	u32 max_lun;		/* maximum SCSI LUN for devices attached to this
180 				 * bus */
181 	u32 cmd_per_lun;	/* maximum number of outstanding commands per
182 				 * lun that are allowed at one time */
183 	u32 max_io_size;	/* maximum io size for devices attached to this
184 				 * bus */
185 	/* max io size is often determined by the resource of the hba. e.g */
186 	/* max scatter gather list length * page size / sector size */
187 } __packed;
188 
189 struct uiscmdrsp_scsi {
190 	u64 handle;		/* the handle to the cmd that was received -
191 				 * send it back as is in the rsp packet.  */
192 	u8 cmnd[MAX_CMND_SIZE];	/* the cdb for the command */
193 	u32 bufflen;		/* length of data to be transferred out or in */
194 	u16 guest_phys_entries;	/* Number of entries in scatter-gather (sg)
195 				 * list */
196 	struct guest_phys_info gpi_list[MAX_PHYS_INFO];	/* physical address
197 							 * information for each
198 							 * fragment */
199 	enum dma_data_direction  data_dir; /* direction of the data, if any */
200 	struct uisscsi_dest vdest;	/* identifies the virtual hba, id,
201 					 * channel, lun to which cmd was sent */
202 
203 	    /* the following fields are needed to queue the rsp back to cmd
204 	     * originator */
205 	int linuxstat;		/* the original Linux status - for use by linux
206 				 * vdisk code */
207 	u8 scsistat;		/* the scsi status */
208 	u8 addlstat;		/* non-scsi status - covers cases like timeout
209 				 * needed by windows guests */
210 #define ADDL_SEL_TIMEOUT	4
211 
212 	/* the following fields are need to determine the result of command */
213 	 u8 sensebuf[MAX_SENSE_SIZE];	/* sense info in case cmd failed; */
214 	/* it holds the sense_data struct; */
215 	/* see that struct for details. */
216 	void *vdisk; /* contains pointer to the vdisk so that we can clean up
217 		      * when the IO completes. */
218 	int no_disk_result;
219 	/* used to return no disk inquiry result
220 	 * when no_disk_result is set to 1,
221 	 * scsi.scsistat is SAM_STAT_GOOD
222 	 * scsi.addlstat is 0
223 	 * scsi.linuxstat is SAM_STAT_GOOD
224 	 * That is, there is NO error.
225 	 */
226 } __packed;
227 
228 /* Defines to support sending correct inquiry result when no disk is
229  * configured.
230  */
231 
232 /* From SCSI SPC2 -
233  *
234  * If the target is not capable of supporting a device on this logical unit, the
235  * device server shall set this field to 7Fh (PERIPHERAL QUALIFIER set to 011b
236  * and PERIPHERAL DEVICE TYPE set to 1Fh).
237  *
238  *The device server is capable of supporting the specified peripheral device
239  *type on this logical unit. However, the physical device is not currently
240  *connected to this logical unit.
241  */
242 
243 #define DEV_NOT_CAPABLE 0x7f	/* peripheral qualifier of 0x3  */
244 				/* peripheral type of 0x1f */
245 				/* specifies no device but target present */
246 
247 #define DEV_DISK_CAPABLE_NOT_PRESENT 0x20 /* peripheral qualifier of 0x1 */
248     /* peripheral type of 0 - disk */
249     /* specifies device capable, but not present */
250 
251 #define DEV_HISUPPORT 0x10	/* HiSup = 1; shows support for report luns */
252 				/* must be returned for lun 0. */
253 
254 /* NOTE: Linux code assumes inquiry contains 36 bytes. Without checking length
255  * in buf[4] some linux code accesses bytes beyond 5 to retrieve vendor, product
256  * & revision.  Yikes! So let us always send back 36 bytes, the minimum for
257  * inquiry result.
258  */
259 #define NO_DISK_INQUIRY_RESULT_LEN 36
260 
261 #define MIN_INQUIRY_RESULT_LEN 5 /* we need at least 5 bytes minimum for inquiry
262 				  * result */
263 
264 /* SCSI device version for no disk inquiry result */
265 #define SCSI_SPC2_VER 4		/* indicates SCSI SPC2 (SPC3 is 5) */
266 
267 /* Windows and Linux want different things for a non-existent lun. So, we'll let
268  * caller pass in the peripheral qualifier and type.
269  * NOTE:[4] SCSI returns (n-4); so we return length-1-4 or length-5. */
270 
271 #define SET_NO_DISK_INQUIRY_RESULT(buf, len, lun, lun0notpresent, notpresent) \
272 	do {								\
273 		memset(buf, 0,						\
274 		       MINNUM(len,					\
275 			      (unsigned int)NO_DISK_INQUIRY_RESULT_LEN)); \
276 		buf[2] = (u8)SCSI_SPC2_VER;				\
277 		if (lun == 0) {						\
278 			buf[0] = (u8)lun0notpresent;			\
279 			buf[3] = (u8)DEV_HISUPPORT;			\
280 		} else							\
281 			buf[0] = (u8)notpresent;			\
282 		buf[4] = (u8)(						\
283 			MINNUM(len,					\
284 			       (unsigned int)NO_DISK_INQUIRY_RESULT_LEN) - 5);\
285 		if (len >= NO_DISK_INQUIRY_RESULT_LEN) {		\
286 			buf[8] = 'D';					\
287 			buf[9] = 'E';					\
288 			buf[10] = 'L';					\
289 			buf[11] = 'L';					\
290 			buf[16] = 'P';					\
291 			buf[17] = 'S';					\
292 			buf[18] = 'E';					\
293 			buf[19] = 'U';					\
294 			buf[20] = 'D';					\
295 			buf[21] = 'O';					\
296 			buf[22] = ' ';					\
297 			buf[23] = 'D';					\
298 			buf[24] = 'E';					\
299 			buf[25] = 'V';					\
300 			buf[26] = 'I';					\
301 			buf[27] = 'C';					\
302 			buf[28] = 'E';					\
303 			buf[30] = ' ';					\
304 			buf[31] = '.';					\
305 		}							\
306 	} while (0)
307 
308 /*
309  * Struct & Defines to support sense information.
310  */
311 
312 /* The following struct is returned in sensebuf field in uiscmdrsp_scsi.  It is
313  * initialized in exactly the manner that is recommended in Windows (hence the
314  * odd values).
315  * When set, these fields will have the following values:
316  * ErrorCode = 0x70		indicates current error
317  * Valid = 1			indicates sense info is valid
318  * SenseKey			contains sense key as defined by SCSI specs.
319  * AdditionalSenseCode		contains sense key as defined by SCSI specs.
320  * AdditionalSenseCodeQualifier	contains qualifier to sense code as defined by
321  *				scsi docs.
322  * AdditionalSenseLength	contains will be sizeof(sense_data)-8=10.
323  */
324 struct sense_data {
325 	u8 errorcode:7;
326 	u8 valid:1;
327 	u8 segment_number;
328 	u8 sense_key:4;
329 	u8 reserved:1;
330 	u8 incorrect_length:1;
331 	u8 end_of_media:1;
332 	u8 file_mark:1;
333 	u8 information[4];
334 	u8 additional_sense_length;
335 	u8 command_specific_information[4];
336 	u8 additional_sense_code;
337 	u8 additional_sense_code_qualifier;
338 	u8 fru_code;
339 	u8 sense_key_specific[3];
340 } __packed;
341 
342 struct net_pkt_xmt {
343 	int len;	/* full length of data in the packet */
344 	int num_frags;	/* number of fragments in frags containing data */
345 	struct phys_info frags[MAX_PHYS_INFO];	/* physical page information for
346 						 * each fragment */
347 	char ethhdr[ETH_HEADER_SIZE];	/* the ethernet header  */
348 	struct {
349 		    /* these are needed for csum at uisnic end */
350 		u8 valid;	/* 1 = rest of this struct is valid - else
351 				 * ignore */
352 		u8 hrawoffv;	/* 1 = hwrafoff is valid */
353 		u8 nhrawoffv;	/* 1 = nhwrafoff is valid */
354 		u16 protocol;	/* specifies packet protocol */
355 		u32 csum;	/* value used to set skb->csum at IOPart */
356 		u32 hrawoff;	/* value used to set skb->h.raw at IOPart */
357 		/* hrawoff points to the start of the TRANSPORT LAYER HEADER */
358 		u32 nhrawoff;	/* value used to set skb->nh.raw at IOPart */
359 		/* nhrawoff points to the start of the NETWORK LAYER HEADER */
360 	} lincsum;
361 
362 	    /* **** NOTE ****
363 	     * The full packet is described in frags but the ethernet header is
364 	     * separately kept in ethhdr so that uisnic doesn't have "MAP" the
365 	     * guest memory to get to the header. uisnic needs ethhdr to
366 	     * determine how to route the packet.
367 	     */
368 } __packed;
369 
370 struct net_pkt_xmtdone {
371 	u32 xmt_done_result;	/* result of NET_XMIT */
372 } __packed;
373 
374 /* RCVPOST_BUF_SIZe must be at most page_size(4096) - cache_line_size (64) The
375  * reason is because dev_skb_alloc which is used to generate RCV_POST skbs in
376  * virtnic requires that there is "overhead" in the buffer, and pads 16 bytes. I
377  * prefer to use 1 full cache line size for "overhead" so that transfers are
378  * better.  IOVM requires that a buffer be represented by 1 phys_info structure
379  * which can only cover page_size.
380  */
381 #define RCVPOST_BUF_SIZE 4032
382 #define MAX_NET_RCV_CHAIN \
383 	((ETH_MAX_MTU+ETH_HEADER_SIZE + RCVPOST_BUF_SIZE-1) / RCVPOST_BUF_SIZE)
384 
385 struct net_pkt_rcvpost {
386 	    /* rcv buf size must be large enough to include ethernet data len +
387 	     * ethernet header len - we are choosing 2K because it is guaranteed
388 	     * to be describable */
389 	    struct phys_info frag;	/* physical page information for the
390 					 * single fragment 2K rcv buf */
391 	    u64 unique_num;		/* This is used to make sure that
392 					 * receive posts are returned to  */
393 	    /* the Adapter which we sent them originally. */
394 } __packed;
395 
396 struct net_pkt_rcv {
397 	/* the number of receive buffers that can be chained  */
398 	/* is based on max mtu and size of each rcv buf */
399 	u32 rcv_done_len;	/* length of received data */
400 	u8 numrcvbufs;		/* number of receive buffers that contain the */
401 	/* incoming data; guest end MUST chain these together. */
402 	void *rcvbuf[MAX_NET_RCV_CHAIN];	/* the list of receive buffers
403 						 * that must be chained; */
404 	/* each entry is a receive buffer provided by NET_RCV_POST. */
405 	/* NOTE: first rcvbuf in the chain will also be provided in net.buf. */
406 	u64 unique_num;
407 	u32 rcvs_dropped_delta;
408 } __packed;
409 
410 struct net_pkt_enbdis {
411 	void *context;
412 	u16 enable;		/* 1 = enable, 0 = disable */
413 } __packed;
414 
415 struct net_pkt_macaddr {
416 	void *context;
417 	u8 macaddr[MAX_MACADDR_LEN];	/* 6 bytes */
418 } __packed;
419 
420 /* cmd rsp packet used for VNIC network traffic  */
421 struct uiscmdrsp_net {
422 	enum net_types type;
423 	void *buf;
424 	union {
425 		struct net_pkt_xmt xmt;		/* used for NET_XMIT */
426 		struct net_pkt_xmtdone xmtdone;	/* used for NET_XMIT_DONE */
427 		struct net_pkt_rcvpost rcvpost;	/* used for NET_RCV_POST */
428 		struct net_pkt_rcv rcv;		/* used for NET_RCV */
429 		struct net_pkt_enbdis enbdis;	/* used for NET_RCV_ENBDIS, */
430 						/* NET_RCV_ENBDIS_ACK,  */
431 						/* NET_RCV_PROMSIC, */
432 						/* and NET_CONNECT_STATUS */
433 		struct net_pkt_macaddr macaddr;
434 	};
435 } __packed;
436 
437 struct uiscmdrsp_scsitaskmgmt {
438 	enum task_mgmt_types tasktype;
439 
440 	    /* the type of task */
441 	struct uisscsi_dest vdest;
442 
443 	    /* the vdisk for which this task mgmt is generated */
444 	u64 handle;
445 
446 	    /* This is a handle that the guest has saved off for its own use.
447 	     * Its value is preserved by iopart & returned as is in the task
448 	     * mgmt rsp.
449 	     */
450 	u64 notify_handle;
451 
452 	   /* For linux guests, this is a pointer to wait_queue_head that a
453 	    * thread is waiting on to see if the taskmgmt command has completed.
454 	    * When the rsp is received by guest, the thread receiving the
455 	    * response uses this to notify the thread waiting for taskmgmt
456 	    * command completion.  Its value is preserved by iopart & returned
457 	    * as is in the task mgmt rsp.
458 	    */
459 	u64 notifyresult_handle;
460 
461 	    /* this is a handle to location in guest where the result of the
462 	     * taskmgmt command (result field) is to saved off when the response
463 	     * is handled.  Its value is preserved by iopart & returned as is in
464 	     * the task mgmt rsp.
465 	     */
466 	char result;
467 
468 	    /* result of taskmgmt command - set by IOPart - values are: */
469 #define TASK_MGMT_FAILED  0
470 } __packed;
471 
472 /* The following is used by uissd to send disk add/remove notifications to
473  * Guest */
474 /* Note that the vHba pointer is not used by the Client/Guest side. */
475 struct uiscmdrsp_disknotify {
476 	u8 add;			/* 0-remove, 1-add */
477 	void *v_hba;		/* Pointer to vhba_info for channel info to
478 				 * route msg */
479 	u32 channel, id, lun;	/* SCSI Path of Disk to added or removed */
480 } __packed;
481 
482 /* The following is used by virthba/vSCSI to send the Acquire/Release commands
483  * to the IOVM. */
484 struct uiscmdrsp_vdiskmgmt {
485 	enum vdisk_mgmt_types vdisktype;
486 
487 	    /* the type of task */
488 	struct uisscsi_dest vdest;
489 
490 	    /* the vdisk for which this task mgmt is generated */
491 	u64 handle;
492 
493 	    /* This is a handle that the guest has saved off for its own use.
494 	     * Its value is preserved by iopart & returned as is in the task
495 	     * mgmt rsp.
496 	     */
497 	u64 notify_handle;
498 
499 	    /* For linux guests, this is a pointer to wait_queue_head that a
500 	     * thread is waiting on to see if the tskmgmt command has completed.
501 	     * When the rsp is received by guest, the thread receiving the
502 	     * response uses this to notify the thread waiting for taskmgmt
503 	     * command completion.  Its value is preserved by iopart & returned
504 	     * as is in the task mgmt rsp.
505 	     */
506 	u64 notifyresult_handle;
507 
508 	    /* this is a handle to location in guest where the result of the
509 	     * taskmgmt command (result field) is to saved off when the response
510 	     * is handled.  Its value is preserved by iopart & returned as is in
511 	     * the task mgmt rsp.
512 	     */
513 	char result;
514 
515 	    /* result of taskmgmt command - set by IOPart - values are: */
516 #define VDISK_MGMT_FAILED  0
517 } __packed;
518 
519 /* keeping cmd & rsp info in one structure for now cmd rsp packet for scsi */
520 struct uiscmdrsp {
521 	char cmdtype;
522 
523 /* describes what type of information is in the struct */
524 #define CMD_SCSI_TYPE		1
525 #define CMD_NET_TYPE		2
526 #define CMD_SCSITASKMGMT_TYPE	3
527 #define CMD_NOTIFYGUEST_TYPE	4
528 #define CMD_VDISKMGMT_TYPE	5
529 	union {
530 		struct uiscmdrsp_scsi scsi;
531 		struct uiscmdrsp_net net;
532 		struct uiscmdrsp_scsitaskmgmt scsitaskmgmt;
533 		struct uiscmdrsp_disknotify disknotify;
534 		struct uiscmdrsp_vdiskmgmt vdiskmgmt;
535 	};
536 	void *private_data;	/* used to send the response when the cmd is
537 				 * done (scsi & scsittaskmgmt). */
538 	struct uiscmdrsp *next;	/* General Purpose Queue Link */
539 	struct uiscmdrsp *activeQ_next;	/* Used to track active commands */
540 	struct uiscmdrsp *activeQ_prev;	/* Used to track active commands */
541 } __packed;
542 
543 struct iochannel_vhba {
544 	struct vhba_wwnn wwnn;		/* 8 bytes */
545 	struct vhba_config_max max;	/* 20 bytes */
546 } __packed;				/* total = 28 bytes */
547 struct iochannel_vnic {
548 	u8 macaddr[6];			/* 6 bytes */
549 	u32 num_rcv_bufs;		/* 4 bytes */
550 	u32 mtu;			/* 4 bytes */
551 	uuid_le zone_uuid;		/* 16 bytes */
552 } __packed;
553 /* This is just the header of the IO channel.  It is assumed that directly after
554  * this header there is a large region of memory which contains the command and
555  * response queues as specified in cmd_q and rsp_q SIGNAL_QUEUE_HEADERS.
556  */
557 struct spar_io_channel_protocol {
558 	struct channel_header channel_header;
559 	struct signal_queue_header cmd_q;
560 	struct signal_queue_header rsp_q;
561 	union {
562 		struct iochannel_vhba vhba;
563 		struct iochannel_vnic vnic;
564 	} __packed;
565 
566 #define MAX_CLIENTSTRING_LEN 1024
567 	 u8 client_string[MAX_CLIENTSTRING_LEN];/* NULL terminated - so holds
568 						 * max - 1 bytes */
569 } __packed;
570 
571 
572 /*
573  * INLINE functions for initializing and accessing I/O data channels
574  */
575 
576 #define SIZEOF_PROTOCOL (COVER(sizeof(struct spar_io_channel_protocol), 64))
577 #define SIZEOF_CMDRSP (COVER(sizeof(struct uiscmdrsp), 64))
578 
579 #define MIN_IO_CHANNEL_SIZE COVER(SIZEOF_PROTOCOL + \
580 				  2 * MIN_NUMSIGNALS * SIZEOF_CMDRSP, 4096)
581 
582 /*
583  * INLINE function for expanding a guest's pfn-off-size into multiple 4K page
584  * pfn-off-size entires.
585  */
586 
587 /* we deal with 4K page sizes when we it comes to passing page information
588  * between */
589 /* Guest and IOPartition. */
590 #define PI_PAGE_SIZE  0x1000
591 #define PI_PAGE_MASK  0x0FFF
592 
593 /* returns next non-zero index on success or zero on failure (i.e. out of
594  * room)
595  */
596 static inline  u16
add_physinfo_entries(u32 inp_pfn,u16 inp_off,u32 inp_len,u16 index,u16 max_pi_arr_entries,struct phys_info pi_arr[])597 add_physinfo_entries(u32 inp_pfn,	/* input - specifies the pfn to be used
598 					 * to add entries */
599 		     u16 inp_off,	/* input - specifies the off to be used
600 					 * to add entries */
601 		     u32 inp_len,	/* input - specifies the len to be used
602 					 * to add entries */
603 		     u16 index,		/* input - index in array at which new
604 					 * entries are added */
605 		     u16 max_pi_arr_entries,	/* input - specifies the maximum
606 						 * entries pi_arr can hold */
607 		     struct phys_info pi_arr[]) /* input & output - array to
608 						  * which entries are added */
609 {
610 	u32 len;
611 	u16 i, firstlen;
612 
613 	firstlen = PI_PAGE_SIZE - inp_off;
614 	if (inp_len <= firstlen) {
615 		/* the input entry spans only one page - add as is */
616 		if (index >= max_pi_arr_entries)
617 			return 0;
618 		pi_arr[index].pi_pfn = inp_pfn;
619 		pi_arr[index].pi_off = (u16)inp_off;
620 		pi_arr[index].pi_len = (u16)inp_len;
621 		    return index + 1;
622 	}
623 
624 	    /* this entry spans multiple pages */
625 	    for (len = inp_len, i = 0; len;
626 		 len -= pi_arr[index + i].pi_len, i++) {
627 		if (index + i >= max_pi_arr_entries)
628 			return 0;
629 		pi_arr[index + i].pi_pfn = inp_pfn + i;
630 		if (i == 0) {
631 			pi_arr[index].pi_off = inp_off;
632 			pi_arr[index].pi_len = firstlen;
633 		}
634 
635 		else {
636 			pi_arr[index + i].pi_off = 0;
637 			pi_arr[index + i].pi_len =
638 			    (u16)MINNUM(len, (u32)PI_PAGE_SIZE);
639 		}
640 	}
641 	return index + i;
642 }
643 
644 #endif				/* __IOCHANNEL_H__ */
645