diff options
Diffstat (limited to 'qemu/roms/ipxe/src/drivers/net/netvsc.h')
-rw-r--r-- | qemu/roms/ipxe/src/drivers/net/netvsc.h | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/qemu/roms/ipxe/src/drivers/net/netvsc.h b/qemu/roms/ipxe/src/drivers/net/netvsc.h new file mode 100644 index 000000000..39eeb891c --- /dev/null +++ b/qemu/roms/ipxe/src/drivers/net/netvsc.h @@ -0,0 +1,365 @@ +#ifndef _NETVSC_H +#define _NETVSC_H + +/** @file + * + * Hyper-V network virtual service client + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** Maximum supported NetVSC message length */ +#define NETVSC_MTU 512 + +/** Maximum time to wait for a transaction to complete + * + * This is a policy decision. + */ +#define NETVSC_MAX_WAIT_MS 1000 + +/** Number of transmit ring entries + * + * Must be a power of two. This is a policy decision. This value + * must be sufficiently small to guarantee that we never run out of + * space in the VMBus outbound ring buffer. + */ +#define NETVSC_TX_NUM_DESC 32 + +/** RX data buffer page set ID + * + * This is a policy decision. + */ +#define NETVSC_RX_BUF_PAGESET 0xbead + +/** RX data buffer length + * + * This is a policy decision. + */ +#define NETVSC_RX_BUF_LEN ( 16 * PAGE_SIZE ) + +/** Base transaction ID + * + * This is a policy decision. + */ +#define NETVSC_BASE_XID 0x18ae0000UL + +/** Relative transaction IDs */ +enum netvsc_xrid { + /** Transmit descriptors (one per transmit buffer ID) */ + NETVSC_TX_BASE_XRID = 0, + /** Initialisation */ + NETVSC_INIT_XRID = ( NETVSC_TX_BASE_XRID + NETVSC_TX_NUM_DESC ), + /** NDIS version */ + NETVSC_NDIS_VERSION_XRID, + /** Establish receive buffer */ + NETVSC_RX_ESTABLISH_XRID, + /** Revoke receive buffer */ + NETVSC_RX_REVOKE_XRID, +}; + +/** NetVSC status codes */ +enum netvsc_status { + NETVSC_NONE = 0, + NETVSC_OK = 1, + NETVSC_FAIL = 2, + NETVSC_TOO_NEW = 3, + NETVSC_TOO_OLD = 4, + NETVSC_BAD_PACKET = 5, + NETVSC_BUSY = 6, + NETVSC_UNSUPPORTED = 7, +}; + +/** NetVSC message header */ +struct netvsc_header { + /** Type */ + uint32_t type; +} __attribute__ (( packed )); + +/** NetVSC initialisation message */ +#define NETVSC_INIT_MSG 1 + +/** NetVSC initialisation message */ +struct netvsc_init_message { + /** Message header */ + struct netvsc_header header; + /** Minimum supported protocol version */ + uint32_t min; + /** Maximum supported protocol version */ + uint32_t max; + /** Reserved */ + uint8_t reserved[20]; +} __attribute__ (( packed )); + +/** Oldest known NetVSC protocol version */ +#define NETVSC_VERSION_1 2 /* sic */ + +/** NetVSC initialisation completion */ +#define NETVSC_INIT_CMPLT 2 + +/** NetVSC initialisation completion */ +struct netvsc_init_completion { + /** Message header */ + struct netvsc_header header; + /** Protocol version */ + uint32_t version; + /** Maximum memory descriptor list length */ + uint32_t max_mdl_len; + /** Status */ + uint32_t status; + /** Reserved */ + uint8_t reserved[16]; +} __attribute__ (( packed )); + +/** NetVSC NDIS version message */ +#define NETVSC_NDIS_VERSION_MSG 100 + +/** NetVSC NDIS version message */ +struct netvsc_ndis_version_message { + /** Message header */ + struct netvsc_header header; + /** Major version */ + uint32_t major; + /** Minor version */ + uint32_t minor; + /** Reserved */ + uint8_t reserved[20]; +} __attribute__ (( packed )); + +/** NetVSC NDIS major version */ +#define NETVSC_NDIS_MAJOR 6 + +/** NetVSC NDIS minor version */ +#define NETVSC_NDIS_MINOR 1 + +/** NetVSC establish receive data buffer message */ +#define NETVSC_RX_ESTABLISH_MSG 101 + +/** NetVSC establish receive data buffer completion */ +#define NETVSC_RX_ESTABLISH_CMPLT 102 + +/** NetVSC revoke receive data buffer message */ +#define NETVSC_RX_REVOKE_MSG 103 + +/** NetVSC establish transmit data buffer message */ +#define NETVSC_TX_ESTABLISH_MSG 104 + +/** NetVSC establish transmit data buffer completion */ +#define NETVSC_TX_ESTABLISH_CMPLT 105 + +/** NetVSC revoke transmit data buffer message */ +#define NETVSC_TX_REVOKE_MSG 106 + +/** NetVSC establish data buffer message */ +struct netvsc_establish_buffer_message { + /** Message header */ + struct netvsc_header header; + /** GPADL ID */ + uint32_t gpadl; + /** Page set ID */ + uint16_t pageset; + /** Reserved */ + uint8_t reserved[22]; +} __attribute__ (( packed )); + +/** NetVSC receive data buffer section */ +struct netvsc_rx_buffer_section { + /** Starting offset */ + uint32_t start; + /** Subsection length */ + uint32_t len; + /** Number of subsections */ + uint32_t count; + /** Ending offset */ + uint32_t end; +} __attribute__ (( packed )); + +/** NetVSC establish receive data buffer completion */ +struct netvsc_rx_establish_buffer_completion { + /** Message header */ + struct netvsc_header header; + /** Status */ + uint32_t status; + /** Number of sections (must be 1) */ + uint32_t count; + /** Section descriptors */ + struct netvsc_rx_buffer_section section[1]; +} __attribute__ (( packed )); + +/** NetVSC establish transmit data buffer completion */ +struct netvsc_tx_establish_buffer_completion { + /** Message header */ + struct netvsc_header header; + /** Status */ + uint32_t status; + /** Section length */ + uint32_t len; +} __attribute__ (( packed )); + +/** NetVSC revoke data buffer message */ +struct netvsc_revoke_buffer_message { + /** Message header */ + struct netvsc_header header; + /** Page set ID */ + uint16_t pageset; + /** Reserved */ + uint8_t reserved[26]; +} __attribute__ (( packed )); + +/** NetVSC RNDIS message */ +#define NETVSC_RNDIS_MSG 107 + +/** NetVSC RNDIS message */ +struct netvsc_rndis_message { + /** Message header */ + struct netvsc_header header; + /** RNDIS channel */ + uint32_t channel; + /** Buffer index (or NETVSC_RNDIS_NO_BUFFER) */ + uint32_t buffer; + /** Buffer length */ + uint32_t len; + /** Reserved */ + uint8_t reserved[16]; +} __attribute__ (( packed )); + +/** RNDIS data channel (for RNDIS_PACKET_MSG only) */ +#define NETVSC_RNDIS_DATA 0 + +/** RNDIS control channel (for all other RNDIS messages) */ +#define NETVSC_RNDIS_CONTROL 1 + +/** "No buffer used" index */ +#define NETVSC_RNDIS_NO_BUFFER 0xffffffffUL + +/** A NetVSC descriptor ring */ +struct netvsc_ring { + /** Number of descriptors */ + unsigned int count; + /** I/O buffers, indexed by buffer ID */ + struct io_buffer **iobufs; + /** Buffer ID ring */ + uint8_t *ids; + /** Buffer ID producer counter */ + unsigned int id_prod; + /** Buffer ID consumer counter */ + unsigned int id_cons; +}; + +/** + * Initialise descriptor ring + * + * @v ring Descriptor ring + * @v count Maximum number of used descriptors + * @v iobufs I/O buffers + * @v ids Buffer IDs + */ +static inline __attribute__ (( always_inline )) void +netvsc_init_ring ( struct netvsc_ring *ring, unsigned int count, + struct io_buffer **iobufs, uint8_t *ids ) { + + ring->count = count; + ring->iobufs = iobufs; + ring->ids = ids; +} + +/** + * Check whether or not descriptor ring is full + * + * @v ring Descriptor ring + * @v is_full Ring is full + */ +static inline __attribute__ (( always_inline )) int +netvsc_ring_is_full ( struct netvsc_ring *ring ) { + unsigned int fill_level; + + fill_level = ( ring->id_prod - ring->id_cons ); + assert ( fill_level <= ring->count ); + return ( fill_level >= ring->count ); +} + +/** + * Check whether or not descriptor ring is empty + * + * @v ring Descriptor ring + * @v is_empty Ring is empty + */ +static inline __attribute__ (( always_inline )) int +netvsc_ring_is_empty ( struct netvsc_ring *ring ) { + + return ( ring->id_prod == ring->id_cons ); +} + +/** A NetVSC data buffer */ +struct netvsc_buffer { + /** Transfer page set */ + struct vmbus_xfer_pages pages; + /** Establish data buffer message type */ + uint8_t establish_type; + /** Establish data buffer relative transaction ID */ + uint8_t establish_xrid; + /** Revoke data buffer message type */ + uint8_t revoke_type; + /** Revoke data buffer relative transaction ID */ + uint8_t revoke_xrid; + /** Buffer length */ + size_t len; + /** Buffer */ + userptr_t data; + /** GPADL ID */ + unsigned int gpadl; +}; + +/** + * Initialise data buffer + * + * @v buffer Data buffer + * @v pageset Page set ID + * @v op Page set operations + * @v establish_type Establish data buffer message type + * @v establish_xrid Establish data buffer relative transaction ID + * @v revoke_type Revoke data buffer message type + * @v revoke_type Revoke data buffer relative transaction ID + * @v len Required length + */ +static inline __attribute__ (( always_inline )) void +netvsc_init_buffer ( struct netvsc_buffer *buffer, uint16_t pageset, + struct vmbus_xfer_pages_operations *op, + uint8_t establish_type, uint8_t establish_xrid, + uint8_t revoke_type, uint8_t revoke_xrid, size_t len ) { + + buffer->pages.pageset = cpu_to_le16 ( pageset ); + buffer->pages.op = op; + buffer->establish_type = establish_type; + buffer->establish_xrid = establish_xrid; + buffer->revoke_type = revoke_type; + buffer->revoke_xrid = revoke_xrid; + buffer->len = len; +} + +/** A NetVSC device */ +struct netvsc_device { + /** VMBus device */ + struct vmbus_device *vmdev; + /** RNDIS device */ + struct rndis_device *rndis; + /** Name */ + const char *name; + + /** Transmit ring */ + struct netvsc_ring tx; + /** Transmit buffer IDs */ + uint8_t tx_ids[NETVSC_TX_NUM_DESC]; + /** Transmit I/O buffers */ + struct io_buffer *tx_iobufs[NETVSC_TX_NUM_DESC]; + + /** Receive buffer */ + struct netvsc_buffer rx; + + /** Relative transaction ID for current blocking transaction */ + unsigned int wait_xrid; + /** Return status code for current blocking transaction */ + int wait_rc; +}; + +#endif /* _NETVSC_H */ |