// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2010 - 2016 UNISYS CORPORATION * All rights reserved. */ #ifndef __IOCHANNEL_H__ #define __IOCHANNEL_H__ /* * Everything needed for IOPart-GuestPart communication is define in * this file. Note: Everything is OS-independent because this file is * used by Windows, Linux and possible EFI drivers. * * Communication flow between the IOPart and GuestPart uses the channel headers * channel state. The following states are currently being used: * UNINIT(All Zeroes), CHANNEL_ATTACHING, CHANNEL_ATTACHED, CHANNEL_OPENED * * Additional states will be used later. No locking is needed to switch between * states due to the following rules: * * 1. IOPart is only the only partition allowed to change from UNIT * 2. IOPart is only the only partition allowed to change from * CHANNEL_ATTACHING * 3. GuestPart is only the only partition allowed to change from * CHANNEL_ATTACHED * * The state changes are the following: IOPart sees the channel is in UNINIT, * UNINIT -> CHANNEL_ATTACHING (performed only by IOPart) * CHANNEL_ATTACHING -> CHANNEL_ATTACHED (performed only by IOPart) * CHANNEL_ATTACHED -> CHANNEL_OPENED (performed only by GuestPart) */ #include #include #include /* * Must increment these whenever you insert or delete fields within this channel * struct. Also increment whenever you change the meaning of fields within this * channel struct so as to break pre-existing software. Note that you can * usually add fields to the END of the channel struct without needing to * increment this. */ #define VISOR_VHBA_CHANNEL_VERSIONID 2 #define VISOR_VNIC_CHANNEL_VERSIONID 2 /* * Everything necessary to handle SCSI & NIC traffic between Guest Partition and * IO Partition is defined below. */ /* * Define the two queues per data channel between iopart and ioguestparts. * IOCHAN_TO_IOPART -- used by guest to 'insert' signals to iopart. * IOCHAN_FROM_IOPART -- used by guest to 'remove' signals from IO part. */ #define IOCHAN_TO_IOPART 0 #define IOCHAN_FROM_IOPART 1 /* Size of cdb - i.e., SCSI cmnd */ #define MAX_CMND_SIZE 16 /* Unisys-specific DMA direction values */ enum uis_dma_data_direction { UIS_DMA_BIDIRECTIONAL = 0, UIS_DMA_TO_DEVICE = 1, UIS_DMA_FROM_DEVICE = 2, UIS_DMA_NONE = 3 }; #define MAX_SENSE_SIZE 64 #define MAX_PHYS_INFO 64 /* * enum net_types - Various types of network packets that can be sent in cmdrsp. * @NET_RCV_POST: Submit buffer to hold receiving incoming packet. * @NET_RCV: visornic -> uisnic. Incoming packet received. * @NET_XMIT: uisnic -> visornic. For outgoing packet. * @NET_XMIT_DONE: visornic -> uisnic. Outgoing packet xmitted. * @NET_RCV_ENBDIS: uisnic -> visornic. Enable/Disable packet reception. * @NET_RCV_ENBDIS_ACK: visornic -> uisnic. Acknowledge enable/disable packet. * @NET_RCV_PROMISC: uisnic -> visornic. Enable/Disable promiscuous mode. * @NET_CONNECT_STATUS: visornic -> uisnic. Indicate the loss or restoration of * a network connection. * @NET_MACADDR: uisnic -> visornic. Indicates the client has requested * to update it's MAC address. * @NET_MACADDR_ACK: MAC address acknowledge. */ enum net_types { NET_RCV_POST = 0, NET_RCV, NET_XMIT, NET_XMIT_DONE, NET_RCV_ENBDIS, NET_RCV_ENBDIS_ACK, /* Reception */ NET_RCV_PROMISC, NET_CONNECT_STATUS, NET_MACADDR, NET_MACADDR_ACK, }; /* Minimum eth data size */ #define ETH_MIN_DATA_SIZE 46 #define ETH_MIN_PACKET_SIZE (ETH_HLEN + ETH_MIN_DATA_SIZE) /* Maximum data size */ #define VISOR_ETH_MAX_MTU 16384 #ifndef MAX_MACADDR_LEN /* Number of bytes in MAC address */ #define MAX_MACADDR_LEN 6 #endif /* Various types of scsi task mgmt commands. */ enum task_mgmt_types { TASK_MGMT_ABORT_TASK = 1, TASK_MGMT_BUS_RESET, TASK_MGMT_LUN_RESET, TASK_MGMT_TARGET_RESET, }; /* Various types of vdisk mgmt commands. */ enum vdisk_mgmt_types { VDISK_MGMT_ACQUIRE = 1, VDISK_MGMT_RELEASE, }; struct phys_info { u64 pi_pfn; u16 pi_off; u16 pi_len; } __packed; #define MIN_NUMSIGNALS 64 /* Structs with pragma pack. */ struct guest_phys_info { u64 address; u64 length; } __packed; /* * struct uisscsi_dest * @channel: Bus number. * @id: Target number. * @lun: Logical unit number. */ struct uisscsi_dest { u32 channel; u32 id; u32 lun; } __packed; struct vhba_wwnn { u32 wwnn1; u32 wwnn2; } __packed; /* * struct vhba_config_max * @max_channel: Maximum channel for devices attached to this bus. * @max_id: Maximum SCSI ID for devices attached to bus. * @max_lun: Maximum SCSI LUN for devices attached to bus. * @cmd_per_lun: Maximum number of outstanding commands per LUN. * @max_io_size: Maximum io size for devices attached to this bus. Max io size * is often determined by the resource of the hba. * e.g Max scatter gather list length * page size / sector size. * * WARNING: Values stored in this structure must contain maximum counts (not * maximum values). * * 20 bytes */ struct vhba_config_max { u32 max_channel; u32 max_id; u32 max_lun; u32 cmd_per_lun; u32 max_io_size; } __packed; /* * struct uiscmdrsp_scsi * * @handle: The handle to the cmd that was received. Send it back as * is in the rsp packet. * @cmnd: The cdb for the command. * @bufflen: Length of data to be transferred out or in. * @guest_phys_entries: Number of entries in scatter-gather list. * @struct gpi_list: Physical address information for each fragment. * @data_dir: Direction of the data, if any. * @struct vdest: Identifies the virtual hba, id, channel, lun to which * cmd was sent. * @linuxstat: Original Linux status used by Linux vdisk. * @scsistat: The scsi status. * @addlstat: Non-scsi status. * @sensebuf: Sense info in case cmd failed. sensebuf holds the * sense_data struct. See sense_data struct for more * details. * @*vdisk: Pointer to the vdisk to clean up when IO completes. * @no_disk_result: Used to return no disk inquiry result when * no_disk_result is set to 1 * scsi.scsistat is SAM_STAT_GOOD * scsi.addlstat is 0 * scsi.linuxstat is SAM_STAT_GOOD * That is, there is NO error. */ struct uiscmdrsp_scsi { u64 handle; u8 cmnd[MAX_CMND_SIZE]; u32 bufflen; u16 guest_phys_entries; struct guest_phys_info gpi_list[MAX_PHYS_INFO]; u32 data_dir; struct uisscsi_dest vdest; /* Needed to queue the rsp back to cmd originator. */ int linuxstat; u8 scsistat; u8 addlstat; #define ADDL_SEL_TIMEOUT 4 /* The following fields are need to determine the result of command. */ u8 sensebuf[MAX_SENSE_SIZE]; void *vdisk; int no_disk_result; } __packed; /* * Defines to support sending correct inquiry result when no disk is * configured. * * From SCSI SPC2 - * * If the target is not capable of supporting a device on this logical unit, the * device server shall set this field to 7Fh (PERIPHERAL QUALIFIER set to 011b * and PERIPHERAL DEVICE TYPE set to 1Fh). * * The device server is capable of supporting the specified peripheral device * type on this logical unit. However, the physical device is not currently * connected to this logical unit. */ /* * Peripheral qualifier of 0x3 * Peripheral type of 0x1f * Specifies no device but target present */ #define DEV_NOT_CAPABLE 0x7f /* * Peripheral qualifier of 0x1 * Peripheral type of 0 - disk * Specifies device capable, but not present */ #define DEV_DISK_CAPABLE_NOT_PRESENT 0x20 /* HiSup = 1; shows support for report luns must be returned for lun 0. */ #define DEV_HISUPPORT 0x10 /* * Peripheral qualifier of 0x3 * Peripheral type of 0x1f * Specifies no device but target present */ #define DEV_NOT_CAPABLE 0x7f /* * Peripheral qualifier of 0x1 * Peripheral type of 0 - disk * Specifies device capable, but not present */ #define DEV_DISK_CAPABLE_NOT_PRESENT 0x20 /* HiSup = 1; shows support for report luns must be returned for lun 0. */ #define DEV_HISUPPORT 0x10 /* * NOTE: Linux code assumes inquiry contains 36 bytes. Without checking length * in buf[4] some Linux code accesses bytes beyond 5 to retrieve vendor, product * and revision. Yikes! So let us always send back 36 bytes, the minimum for * inquiry result. */ #define NO_DISK_INQUIRY_RESULT_LEN 36 /* 5 bytes minimum for inquiry result */ #define MIN_INQUIRY_RESULT_LEN 5 /* SCSI device version for no disk inquiry result */ /* indicates SCSI SPC2 (SPC3 is 5) */ #define SCSI_SPC2_VER 4 /* Struct and Defines to support sense information. */ /* * The following struct is returned in sensebuf field in uiscmdrsp_scsi. It is * initialized in exactly the manner that is recommended in Windows (hence the * odd values). * When set, these fields will have the following values: * ErrorCode = 0x70 indicates current error * Valid = 1 indicates sense info is valid * SenseKey contains sense key as defined by SCSI specs. * AdditionalSenseCode contains sense key as defined by SCSI specs. * AdditionalSenseCodeQualifier contains qualifier to sense code as defined by * scsi docs. * AdditionalSenseLength contains will be sizeof(sense_data)-8=10. */ struct sense_data { u8 errorcode:7; u8 valid:1; u8 segment_number; u8 sense_key:4; u8 reserved:1; u8 incorrect_length:1; u8 end_of_media:1; u8 file_mark:1; u8 information[4]; u8 additional_sense_length; u8 command_specific_information[4]; u8 additional_sense_code; u8 additional_sense_code_qualifier; u8 fru_code; u8 sense_key_specific[3]; } __packed; /* * struct net_pkt_xmt * @len: Full length of data in the packet. * @num_frags: Number of fragments in frags containing data. * @struct phys_info frags: Physical page information. * @ethhdr: The ethernet header. * @struct lincsum: These are needed for csum at uisnic end. * @valid: 1 = struct is valid - else ignore. * @hrawoffv: 1 = hwrafoff is valid. * @nhrawoffv: 1 = nhwrafoff is valid. * @protocol: Specifies packet protocol. * @csum: Value used to set skb->csum at IOPart. * @hrawoff: Value used to set skb->h.raw at IOPart. hrawoff points to * the start of the TRANSPORT LAYER HEADER. * @nhrawoff: Value used to set skb->nh.raw at IOPart. nhrawoff points to * the start of the NETWORK LAYER HEADER. * * NOTE: * The full packet is described in frags but the ethernet header is separately * kept in ethhdr so that uisnic doesn't have "MAP" the guest memory to get to * the header. uisnic needs ethhdr to determine how to route the packet. */ struct net_pkt_xmt { int len; int num_frags; struct phys_info frags[MAX_PHYS_INFO]; char ethhdr[ETH_HLEN]; struct { u8 valid; u8 hrawoffv; u8 nhrawoffv; __be16 protocol; __wsum csum; u32 hrawoff; u32 nhrawoff; } lincsum; } __packed; struct net_pkt_xmtdone { /* Result of NET_XMIT */ u32 xmt_done_result; } __packed; /* * RCVPOST_BUF_SIZE must be at most page_size(4096) - cache_line_size (64) The * reason is because dev_skb_alloc which is used to generate RCV_POST skbs in * visornic requires that there is "overhead" in the buffer, and pads 16 bytes. * Use 1 full cache line size for "overhead" so that transfers are optimized. * IOVM requires that a buffer be represented by 1 phys_info structure * which can only cover page_size. */ #define RCVPOST_BUF_SIZE 4032 #define MAX_NET_RCV_CHAIN \ ((VISOR_ETH_MAX_MTU + ETH_HLEN + RCVPOST_BUF_SIZE - 1) \ / RCVPOST_BUF_SIZE) /* rcv buf size must be large enough to include ethernet data len + ethernet * header len - we are choosing 2K because it is guaranteed to be describable. */ struct net_pkt_rcvpost { /* Physical page information for the single fragment 2K rcv buf */ struct phys_info frag; /* * Ensures that receive posts are returned to the adapter which we sent * them from originally. */ u64 unique_num; } __packed; /* * struct net_pkt_rcv * @rcv_done_len: Length of the received data. * @numrcvbufs: Contains the incoming data. Guest side MUST chain these * together. * @*rcvbuf: List of chained rcvbufa. Each entry is a receive buffer * provided by NET_RCV_POST. NOTE: First rcvbuf in the * chain will also be provided in net.buf. * @unique_num: * @rcvs_dropped_delta: * * The number of rcvbuf that can be chained is based on max mtu and size of each * rcvbuf. */ struct net_pkt_rcv { u32 rcv_done_len; u8 numrcvbufs; void *rcvbuf[MAX_NET_RCV_CHAIN]; u64 unique_num; u32 rcvs_dropped_delta; } __packed; struct net_pkt_enbdis { void *context; /* 1 = enable, 0 = disable */ u16 enable; } __packed; struct net_pkt_macaddr { void *context; /* 6 bytes */ u8 macaddr[MAX_MACADDR_LEN]; } __packed; /* * struct uiscmdrsp_net - cmd rsp packet used for VNIC network traffic. * @enum type: * @*buf: * @union: * @struct xmt: Used for NET_XMIT. * @struct xmtdone: Used for NET_XMIT_DONE. * @struct rcvpost: Used for NET_RCV_POST. * @struct rcv: Used for NET_RCV. * @struct enbdis: Used for NET_RCV_ENBDIS, NET_RCV_ENBDIS_ACK, * NET_RCV_PROMSIC, and NET_CONNECT_STATUS. * @struct macaddr: */ struct uiscmdrsp_net { enum net_types type; void *buf; union { struct net_pkt_xmt xmt; struct net_pkt_xmtdone xmtdone; struct net_pkt_rcvpost rcvpost; struct net_pkt_rcv rcv; struct net_pkt_enbdis enbdis; struct net_pkt_macaddr macaddr; }; } __packed; /* * struct uiscmdrsp_scsitaskmgmt * @enum tasktype: The type of task. * @struct vdest: The vdisk for which this task mgmt is generated. * @handle: This is a handle that the guest has saved off for its * own use. The handle value is preserved by iopart and * returned as in task mgmt rsp. * @notify_handle: For Linux guests, this is a pointer to wait_queue_head * that a thread is waiting on to see if the taskmgmt * command has completed. When the rsp is received by * guest, the thread receiving the response uses this to * notify the thread waiting for taskmgmt command * completion. It's value is preserved by iopart and * returned as in the task mgmt rsp. * @notifyresult_handle: This is a handle to the location in the guest where * the result of the taskmgmt command (result field) is * saved to when the response is handled. It's value is * preserved by iopart and returned as is in the task mgmt * rsp. * @result: Result of taskmgmt command - set by IOPart. */ struct uiscmdrsp_scsitaskmgmt { enum task_mgmt_types tasktype; struct uisscsi_dest vdest; u64 handle; u64 notify_handle; u64 notifyresult_handle; char result; #define TASK_MGMT_FAILED 0 } __packed; /* * struct uiscmdrsp_disknotify - Used by uissd to send disk add/remove * notifications to Guest. * @add: 0-remove, 1-add. * @*v_hba: Channel info to route msg. * @channel: SCSI Path of Disk to added or removed. * @id: SCSI Path of Disk to added or removed. * @lun: SCSI Path of Disk to added or removed. * * Note that the vHba pointer is not used by the Client/Guest side. */ struct uiscmdrsp_disknotify { u8 add; void *v_hba; u32 channel, id, lun; } __packed; /* Keeping cmd and rsp info in one structure for now cmd rsp packet for SCSI */ struct uiscmdrsp { char cmdtype; /* Describes what type of information is in the struct */ #define CMD_SCSI_TYPE 1 #define CMD_NET_TYPE 2 #define CMD_SCSITASKMGMT_TYPE 3 #define CMD_NOTIFYGUEST_TYPE 4 union { struct uiscmdrsp_scsi scsi; struct uiscmdrsp_net net; struct uiscmdrsp_scsitaskmgmt scsitaskmgmt; struct uiscmdrsp_disknotify disknotify; }; /* Send the response when the cmd is done (scsi and scsittaskmgmt). */ void *private_data; /* General Purpose Queue Link */ struct uiscmdrsp *next; /* Pointer to the nextactive commands */ struct uiscmdrsp *activeQ_next; /* Pointer to the prevactive commands */ struct uiscmdrsp *activeQ_prev; } __packed; /* total = 28 bytes */ struct iochannel_vhba { /* 8 bytes */ struct vhba_wwnn wwnn; /* 20 bytes */ struct vhba_config_max max; } __packed; struct iochannel_vnic { /* 6 bytes */ u8 macaddr[6]; /* 4 bytes */ u32 num_rcv_bufs; /* 4 bytes */ u32 mtu; /* 16 bytes */ guid_t zone_guid; } __packed; /* * This is just the header of the IO channel. It is assumed that directly after * this header there is a large region of memory which contains the command and * response queues as specified in cmd_q and rsp_q SIGNAL_QUEUE_HEADERS. */ struct visor_io_channel { struct channel_header channel_header; struct signal_queue_header cmd_q; struct signal_queue_header rsp_q; union { struct iochannel_vhba vhba; struct iochannel_vnic vnic; } __packed; #define MAX_CLIENTSTRING_LEN 1024 /* client_string is NULL termimated so holds max-1 bytes */ u8 client_string[MAX_CLIENTSTRING_LEN]; } __packed; /* INLINE functions for initializing and accessing I/O data channels. */ #define SIZEOF_CMDRSP (64 * DIV_ROUND_UP(sizeof(struct uiscmdrsp), 64)) /* Use 4K page sizes when passing page info between Guest and IOPartition. */ #define PI_PAGE_SIZE 0x1000 #define PI_PAGE_MASK 0x0FFF /* __IOCHANNEL_H__ */ #endif