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