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