| /* 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_ */ |