| /* SPDX-License-Identifier: BSD-3-Clause */ | |
| #ifndef _VMBUS_BUF_H_ | |
| #define _VMBUS_BUF_H_ | |
| #include <stdbool.h> | |
| #include <stdint.h> | |
| #define __packed __attribute__((__packed__)) | |
| #define unlikely(x) __builtin_expect(!!(x), 0) | |
| #define ICMSGHDRFLAG_TRANSACTION 1 | |
| #define ICMSGHDRFLAG_REQUEST 2 | |
| #define ICMSGHDRFLAG_RESPONSE 4 | |
| #define IC_VERSION_NEGOTIATION_MAX_VER_COUNT 100 | |
| #define ICMSG_HDR (sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr)) | |
| #define ICMSG_NEGOTIATE_PKT_SIZE(icframe_vercnt, icmsg_vercnt) \ | |
| (ICMSG_HDR + sizeof(struct icmsg_negotiate) + \ | |
| (((icframe_vercnt) + (icmsg_vercnt)) * sizeof(struct ic_version))) | |
| /* | |
| * Channel packets | |
| */ | |
| /* Channel packet flags */ | |
| #define VMBUS_CHANPKT_TYPE_INBAND 0x0006 | |
| #define VMBUS_CHANPKT_TYPE_RXBUF 0x0007 | |
| #define VMBUS_CHANPKT_TYPE_GPA 0x0009 | |
| #define VMBUS_CHANPKT_TYPE_COMP 0x000b | |
| #define VMBUS_CHANPKT_FLAG_NONE 0 | |
| #define VMBUS_CHANPKT_FLAG_RC 0x0001 /* report completion */ | |
| #define VMBUS_CHANPKT_SIZE_SHIFT 3 | |
| #define VMBUS_CHANPKT_SIZE_ALIGN BIT(VMBUS_CHANPKT_SIZE_SHIFT) | |
| #define VMBUS_CHANPKT_HLEN_MIN \ | |
| (sizeof(struct vmbus_chanpkt_hdr) >> VMBUS_CHANPKT_SIZE_SHIFT) | |
| /* | |
| * Buffer ring | |
| */ | |
| struct vmbus_bufring { | |
| volatile uint32_t windex; | |
| volatile uint32_t rindex; | |
| /* | |
| * Interrupt mask {0,1} | |
| * | |
| * For TX bufring, host set this to 1, when it is processing | |
| * the TX bufring, so that we can safely skip the TX event | |
| * notification to host. | |
| * | |
| * For RX bufring, once this is set to 1 by us, host will not | |
| * further dispatch interrupts to us, even if there are data | |
| * pending on the RX bufring. This effectively disables the | |
| * interrupt of the channel to which this RX bufring is attached. | |
| */ | |
| volatile uint32_t imask; | |
| /* | |
| * Win8 uses some of the reserved bits to implement | |
| * interrupt driven flow management. On the send side | |
| * we can request that the receiver interrupt the sender | |
| * when the ring transitions from being full to being able | |
| * to handle a message of size "pending_send_sz". | |
| * | |
| * Add necessary state for this enhancement. | |
| */ | |
| volatile uint32_t pending_send; | |
| uint32_t reserved1[12]; | |
| union { | |
| struct { | |
| uint32_t feat_pending_send_sz:1; | |
| }; | |
| uint32_t value; | |
| } feature_bits; | |
| /* Pad it to rte_mem_page_size() so that data starts on page boundary */ | |
| uint8_t reserved2[4028]; | |
| /* | |
| * Ring data starts here + RingDataStartOffset | |
| * !!! DO NOT place any fields below this !!! | |
| */ | |
| uint8_t data[]; | |
| } __packed; | |
| struct vmbus_br { | |
| struct vmbus_bufring *vbr; | |
| uint32_t dsize; | |
| uint32_t windex; /* next available location */ | |
| }; | |
| struct vmbus_chanpkt_hdr { | |
| uint16_t type; /* VMBUS_CHANPKT_TYPE_ */ | |
| uint16_t hlen; /* header len, in 8 bytes */ | |
| uint16_t tlen; /* total len, in 8 bytes */ | |
| uint16_t flags; /* VMBUS_CHANPKT_FLAG_ */ | |
| uint64_t xactid; | |
| } __packed; | |
| struct vmbus_chanpkt { | |
| struct vmbus_chanpkt_hdr hdr; | |
| } __packed; | |
| struct vmbuspipe_hdr { | |
| unsigned int flags; | |
| unsigned int msgsize; | |
| } __packed; | |
| struct ic_version { | |
| unsigned short major; | |
| unsigned short minor; | |
| } __packed; | |
| struct icmsg_negotiate { | |
| unsigned short icframe_vercnt; | |
| unsigned short icmsg_vercnt; | |
| unsigned int reserved; | |
| struct ic_version icversion_data[]; /* any size array */ | |
| } __packed; | |
| struct icmsg_hdr { | |
| struct ic_version icverframe; | |
| unsigned short icmsgtype; | |
| struct ic_version icvermsg; | |
| unsigned short icmsgsize; | |
| unsigned int status; | |
| unsigned char ictransaction_id; | |
| unsigned char icflags; | |
| unsigned char reserved[2]; | |
| } __packed; | |
| int rte_vmbus_chan_recv_raw(struct vmbus_br *rxbr, void *data, uint32_t *len); | |
| int rte_vmbus_chan_send(struct vmbus_br *txbr, uint16_t type, void *data, | |
| uint32_t dlen, uint32_t flags); | |
| void vmbus_br_setup(struct vmbus_br *br, void *buf, unsigned int blen); | |
| void *vmbus_uio_map(int *fd, int size); | |
| /* Amount of space available for write */ | |
| static inline uint32_t vmbus_br_availwrite(const struct vmbus_br *br, uint32_t windex) | |
| { | |
| uint32_t rindex = br->vbr->rindex; | |
| if (windex >= rindex) | |
| return br->dsize - (windex - rindex); | |
| else | |
| return rindex - windex; | |
| } | |
| static inline uint32_t vmbus_br_availread(const struct vmbus_br *br) | |
| { | |
| return br->dsize - vmbus_br_availwrite(br, br->vbr->windex); | |
| } | |
| #endif /* !_VMBUS_BUF_H_ */ |