iPXE
netvsc.h
Go to the documentation of this file.
00001 #ifndef _NETVSC_H
00002 #define _NETVSC_H
00003 
00004 /** @file
00005  *
00006  * Hyper-V network virtual service client
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 /** Maximum supported NetVSC message length */
00013 #define NETVSC_MTU 512
00014 
00015 /** Maximum time to wait for a transaction to complete
00016  *
00017  * This is a policy decision.
00018  */
00019 #define NETVSC_MAX_WAIT_MS 1000
00020 
00021 /** Number of transmit ring entries
00022  *
00023  * Must be a power of two.  This is a policy decision.  This value
00024  * must be sufficiently small to guarantee that we never run out of
00025  * space in the VMBus outbound ring buffer.
00026  */
00027 #define NETVSC_TX_NUM_DESC 32
00028 
00029 /** RX data buffer page set ID
00030  *
00031  * This is a policy decision.
00032  */
00033 #define NETVSC_RX_BUF_PAGESET 0xbead
00034 
00035 /** RX data buffer length
00036  *
00037  * This is a policy decision.
00038  */
00039 #define NETVSC_RX_BUF_LEN ( 16 * PAGE_SIZE )
00040 
00041 /** Base transaction ID
00042  *
00043  * This is a policy decision.
00044  */
00045 #define NETVSC_BASE_XID 0x18ae0000UL
00046 
00047 /** Relative transaction IDs */
00048 enum netvsc_xrid {
00049         /** Transmit descriptors (one per transmit buffer ID) */
00050         NETVSC_TX_BASE_XRID = 0,
00051         /** Initialisation */
00052         NETVSC_INIT_XRID = ( NETVSC_TX_BASE_XRID + NETVSC_TX_NUM_DESC ),
00053         /** NDIS version */
00054         NETVSC_NDIS_VERSION_XRID,
00055         /** Establish receive buffer */
00056         NETVSC_RX_ESTABLISH_XRID,
00057         /** Revoke receive buffer */
00058         NETVSC_RX_REVOKE_XRID,
00059 };
00060 
00061 /** NetVSC status codes */
00062 enum netvsc_status {
00063         NETVSC_NONE = 0,
00064         NETVSC_OK = 1,
00065         NETVSC_FAIL = 2,
00066         NETVSC_TOO_NEW = 3,
00067         NETVSC_TOO_OLD = 4,
00068         NETVSC_BAD_PACKET = 5,
00069         NETVSC_BUSY = 6,
00070         NETVSC_UNSUPPORTED = 7,
00071 };
00072 
00073 /** NetVSC message header */
00074 struct netvsc_header {
00075         /** Type */
00076         uint32_t type;
00077 } __attribute__ (( packed ));
00078 
00079 /** NetVSC initialisation message */
00080 #define NETVSC_INIT_MSG 1
00081 
00082 /** NetVSC initialisation message */
00083 struct netvsc_init_message {
00084         /** Message header */
00085         struct netvsc_header header;
00086         /** Minimum supported protocol version */
00087         uint32_t min;
00088         /** Maximum supported protocol version */
00089         uint32_t max;
00090         /** Reserved */
00091         uint8_t reserved[20];
00092 } __attribute__ (( packed ));
00093 
00094 /** Oldest known NetVSC protocol version */
00095 #define NETVSC_VERSION_1 2 /* sic */
00096 
00097 /** NetVSC initialisation completion */
00098 #define NETVSC_INIT_CMPLT 2
00099 
00100 /** NetVSC initialisation completion */
00101 struct netvsc_init_completion {
00102         /** Message header */
00103         struct netvsc_header header;
00104         /** Protocol version */
00105         uint32_t version;
00106         /** Maximum memory descriptor list length */
00107         uint32_t max_mdl_len;
00108         /** Status */
00109         uint32_t status;
00110         /** Reserved */
00111         uint8_t reserved[16];
00112 } __attribute__ (( packed ));
00113 
00114 /** NetVSC NDIS version message */
00115 #define NETVSC_NDIS_VERSION_MSG 100
00116 
00117 /** NetVSC NDIS version message */
00118 struct netvsc_ndis_version_message {
00119         /** Message header */
00120         struct netvsc_header header;
00121         /** Major version */
00122         uint32_t major;
00123         /** Minor version */
00124         uint32_t minor;
00125         /** Reserved */
00126         uint8_t reserved[20];
00127 } __attribute__ (( packed ));
00128 
00129 /** NetVSC NDIS major version */
00130 #define NETVSC_NDIS_MAJOR 6
00131 
00132 /** NetVSC NDIS minor version */
00133 #define NETVSC_NDIS_MINOR 1
00134 
00135 /** NetVSC establish receive data buffer message */
00136 #define NETVSC_RX_ESTABLISH_MSG 101
00137 
00138 /** NetVSC establish receive data buffer completion */
00139 #define NETVSC_RX_ESTABLISH_CMPLT 102
00140 
00141 /** NetVSC revoke receive data buffer message */
00142 #define NETVSC_RX_REVOKE_MSG 103
00143 
00144 /** NetVSC establish transmit data buffer message */
00145 #define NETVSC_TX_ESTABLISH_MSG 104
00146 
00147 /** NetVSC establish transmit data buffer completion */
00148 #define NETVSC_TX_ESTABLISH_CMPLT 105
00149 
00150 /** NetVSC revoke transmit data buffer message */
00151 #define NETVSC_TX_REVOKE_MSG 106
00152 
00153 /** NetVSC establish data buffer message */
00154 struct netvsc_establish_buffer_message {
00155         /** Message header */
00156         struct netvsc_header header;
00157         /** GPADL ID */
00158         uint32_t gpadl;
00159         /** Page set ID */
00160         uint16_t pageset;
00161         /** Reserved */
00162         uint8_t reserved[22];
00163 } __attribute__ (( packed ));
00164 
00165 /** NetVSC receive data buffer section */
00166 struct netvsc_rx_buffer_section {
00167         /** Starting offset */
00168         uint32_t start;
00169         /** Subsection length */
00170         uint32_t len;
00171         /** Number of subsections */
00172         uint32_t count;
00173         /** Ending offset */
00174         uint32_t end;
00175 } __attribute__ (( packed ));
00176 
00177 /** NetVSC establish receive data buffer completion */
00178 struct netvsc_rx_establish_buffer_completion {
00179         /** Message header */
00180         struct netvsc_header header;
00181         /** Status */
00182         uint32_t status;
00183         /** Number of sections (must be 1) */
00184         uint32_t count;
00185         /** Section descriptors */
00186         struct netvsc_rx_buffer_section section[1];
00187 } __attribute__ (( packed ));
00188 
00189 /** NetVSC establish transmit data buffer completion */
00190 struct netvsc_tx_establish_buffer_completion {
00191         /** Message header */
00192         struct netvsc_header header;
00193         /** Status */
00194         uint32_t status;
00195         /** Section length */
00196         uint32_t len;
00197 } __attribute__ (( packed ));
00198 
00199 /** NetVSC revoke data buffer message */
00200 struct netvsc_revoke_buffer_message {
00201         /** Message header */
00202         struct netvsc_header header;
00203         /** Page set ID */
00204         uint16_t pageset;
00205         /** Reserved */
00206         uint8_t reserved[26];
00207 } __attribute__ (( packed ));
00208 
00209 /** NetVSC RNDIS message */
00210 #define NETVSC_RNDIS_MSG 107
00211 
00212 /** NetVSC RNDIS message */
00213 struct netvsc_rndis_message {
00214         /** Message header */
00215         struct netvsc_header header;
00216         /** RNDIS channel */
00217         uint32_t channel;
00218         /** Buffer index (or NETVSC_RNDIS_NO_BUFFER) */
00219         uint32_t buffer;
00220         /** Buffer length */
00221         uint32_t len;
00222         /** Reserved */
00223         uint8_t reserved[16];
00224 } __attribute__ (( packed ));
00225 
00226 /** RNDIS data channel (for RNDIS_PACKET_MSG only) */
00227 #define NETVSC_RNDIS_DATA 0
00228 
00229 /** RNDIS control channel (for all other RNDIS messages) */
00230 #define NETVSC_RNDIS_CONTROL 1
00231 
00232 /** "No buffer used" index */
00233 #define NETVSC_RNDIS_NO_BUFFER 0xffffffffUL
00234 
00235 /** A NetVSC descriptor ring */
00236 struct netvsc_ring {
00237         /** Number of descriptors */
00238         unsigned int count;
00239         /** I/O buffers, indexed by buffer ID */
00240         struct io_buffer **iobufs;
00241         /** Buffer ID ring */
00242         uint8_t *ids;
00243         /** Buffer ID producer counter */
00244         unsigned int id_prod;
00245         /** Buffer ID consumer counter */
00246         unsigned int id_cons;
00247 };
00248 
00249 /**
00250  * Initialise descriptor ring
00251  *
00252  * @v ring              Descriptor ring
00253  * @v count             Maximum number of used descriptors
00254  * @v iobufs            I/O buffers
00255  * @v ids               Buffer IDs
00256  */
00257 static inline __attribute__ (( always_inline )) void
00258 netvsc_init_ring ( struct netvsc_ring *ring, unsigned int count,
00259                    struct io_buffer **iobufs, uint8_t *ids ) {
00260 
00261         ring->count = count;
00262         ring->iobufs = iobufs;
00263         ring->ids = ids;
00264 }
00265 
00266 /**
00267  * Check whether or not descriptor ring is full
00268  *
00269  * @v ring              Descriptor ring
00270  * @v is_full           Ring is full
00271  */
00272 static inline __attribute__ (( always_inline )) int
00273 netvsc_ring_is_full ( struct netvsc_ring *ring ) {
00274         unsigned int fill_level;
00275 
00276         fill_level = ( ring->id_prod - ring->id_cons );
00277         assert ( fill_level <= ring->count );
00278         return ( fill_level >= ring->count );
00279 }
00280 
00281 /**
00282  * Check whether or not descriptor ring is empty
00283  *
00284  * @v ring              Descriptor ring
00285  * @v is_empty          Ring is empty
00286  */
00287 static inline __attribute__ (( always_inline )) int
00288 netvsc_ring_is_empty ( struct netvsc_ring *ring ) {
00289 
00290         return ( ring->id_prod == ring->id_cons );
00291 }
00292 
00293 /** A NetVSC data buffer */
00294 struct netvsc_buffer {
00295         /** Transfer page set */
00296         struct vmbus_xfer_pages pages;
00297         /** Establish data buffer message type */
00298         uint8_t establish_type;
00299         /** Establish data buffer relative transaction ID */
00300         uint8_t establish_xrid;
00301         /** Revoke data buffer message type */
00302         uint8_t revoke_type;
00303         /** Revoke data buffer relative transaction ID */
00304         uint8_t revoke_xrid;
00305         /** Buffer length */
00306         size_t len;
00307         /** Buffer */
00308         userptr_t data;
00309         /** GPADL ID */
00310         unsigned int gpadl;
00311 };
00312 
00313 /**
00314  * Initialise data buffer
00315  *
00316  * @v buffer            Data buffer
00317  * @v pageset           Page set ID
00318  * @v op                Page set operations
00319  * @v establish_type    Establish data buffer message type
00320  * @v establish_xrid    Establish data buffer relative transaction ID
00321  * @v revoke_type       Revoke data buffer message type
00322  * @v revoke_type       Revoke data buffer relative transaction ID
00323  * @v len               Required length
00324  */
00325 static inline __attribute__ (( always_inline )) void
00326 netvsc_init_buffer ( struct netvsc_buffer *buffer, uint16_t pageset,
00327                      struct vmbus_xfer_pages_operations *op,
00328                      uint8_t establish_type, uint8_t establish_xrid,
00329                      uint8_t revoke_type, uint8_t revoke_xrid, size_t len ) {
00330 
00331         buffer->pages.pageset = cpu_to_le16 ( pageset );
00332         buffer->pages.op = op;
00333         buffer->establish_type = establish_type;
00334         buffer->establish_xrid = establish_xrid;
00335         buffer->revoke_type = revoke_type;
00336         buffer->revoke_xrid = revoke_xrid;
00337         buffer->len = len;
00338 }
00339 
00340 /** A NetVSC device */
00341 struct netvsc_device {
00342         /** VMBus device */
00343         struct vmbus_device *vmdev;
00344         /** RNDIS device */
00345         struct rndis_device *rndis;
00346         /** Name */
00347         const char *name;
00348 
00349         /** Transmit ring */
00350         struct netvsc_ring tx;
00351         /** Transmit buffer IDs */
00352         uint8_t tx_ids[NETVSC_TX_NUM_DESC];
00353         /** Transmit I/O buffers */
00354         struct io_buffer *tx_iobufs[NETVSC_TX_NUM_DESC];
00355 
00356         /** Receive buffer */
00357         struct netvsc_buffer rx;
00358 
00359         /** Relative transaction ID for current blocking transaction */
00360         unsigned int wait_xrid;
00361         /** Return status code for current blocking transaction */
00362         int wait_rc;
00363 };
00364 
00365 /**
00366  * Check if NetVSC device is obsolete
00367  *
00368  * @v netvsc            NetVSC device
00369  * @v is_obsolete       NetVSC device is obsolete
00370  *
00371  * Check if NetVSC device is obsolete (i.e. was opened before the most
00372  * recent Hyper-V reset).
00373  */
00374 static inline __attribute__ (( always_inline )) int
00375 netvsc_is_obsolete ( struct netvsc_device *netvsc ) {
00376 
00377         return vmbus_gpadl_is_obsolete ( netvsc->rx.gpadl );
00378 }
00379 
00380 #endif /* _NETVSC_H */