| #ifndef _IPXE_RNDIS_H |
| #define _IPXE_RNDIS_H |
| |
| /** @file |
| * |
| * Remote Network Driver Interface Specification |
| * |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); |
| |
| #include <stdint.h> |
| #include <ipxe/netdevice.h> |
| #include <ipxe/iobuf.h> |
| |
| /** Maximum time to wait for a transaction to complete |
| * |
| * This is a policy decision. |
| */ |
| #define RNDIS_MAX_WAIT_MS 1000 |
| |
| /** RNDIS message header */ |
| struct rndis_header { |
| /** Message type */ |
| uint32_t type; |
| /** Message length */ |
| uint32_t len; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS initialise message */ |
| #define RNDIS_INITIALISE_MSG 0x00000002UL |
| |
| /** RNDIS initialise message */ |
| struct rndis_initialise_message { |
| /** Request ID */ |
| uint32_t id; |
| /** Major version */ |
| uint32_t major; |
| /** Minor version */ |
| uint32_t minor; |
| /** Maximum transfer size */ |
| uint32_t mtu; |
| } __attribute__ (( packed )); |
| |
| /** Request ID used for initialisation |
| * |
| * This is a policy decision. |
| */ |
| #define RNDIS_INIT_ID 0xe110e110UL |
| |
| /** RNDIS major version */ |
| #define RNDIS_VERSION_MAJOR 1 |
| |
| /** RNDIS minor version */ |
| #define RNDIS_VERSION_MINOR 0 |
| |
| /** RNDIS maximum transfer size |
| * |
| * This is a policy decision. |
| */ |
| #define RNDIS_MTU 2048 |
| |
| /** RNDIS initialise completion */ |
| #define RNDIS_INITIALISE_CMPLT 0x80000002UL |
| |
| /** RNDIS initialise completion */ |
| struct rndis_initialise_completion { |
| /** Request ID */ |
| uint32_t id; |
| /** Status */ |
| uint32_t status; |
| /** Major version */ |
| uint32_t major; |
| /** Minor version */ |
| uint32_t minor; |
| /** Device flags */ |
| uint32_t flags; |
| /** Medium */ |
| uint32_t medium; |
| /** Maximum packets per transfer */ |
| uint32_t max_pkts; |
| /** Maximum transfer size */ |
| uint32_t mtu; |
| /** Packet alignment factor */ |
| uint32_t align; |
| /** Reserved */ |
| uint32_t reserved[2]; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS halt message */ |
| #define RNDIS_HALT_MSG 0x00000003UL |
| |
| /** RNDIS halt message */ |
| struct rndis_halt_message { |
| /** Request ID */ |
| uint32_t id; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS query OID message */ |
| #define RNDIS_QUERY_MSG 0x00000004UL |
| |
| /** RNDIS set OID message */ |
| #define RNDIS_SET_MSG 0x00000005UL |
| |
| /** RNDIS query or set OID message */ |
| struct rndis_oid_message { |
| /** Request ID */ |
| uint32_t id; |
| /** Object ID */ |
| uint32_t oid; |
| /** Information buffer length */ |
| uint32_t len; |
| /** Information buffer offset */ |
| uint32_t offset; |
| /** Reserved */ |
| uint32_t reserved; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS query OID completion */ |
| #define RNDIS_QUERY_CMPLT 0x80000004UL |
| |
| /** RNDIS query OID completion */ |
| struct rndis_query_completion { |
| /** Request ID */ |
| uint32_t id; |
| /** Status */ |
| uint32_t status; |
| /** Information buffer length */ |
| uint32_t len; |
| /** Information buffer offset */ |
| uint32_t offset; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS set OID completion */ |
| #define RNDIS_SET_CMPLT 0x80000005UL |
| |
| /** RNDIS set OID completion */ |
| struct rndis_set_completion { |
| /** Request ID */ |
| uint32_t id; |
| /** Status */ |
| uint32_t status; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS reset message */ |
| #define RNDIS_RESET_MSG 0x00000006UL |
| |
| /** RNDIS reset message */ |
| struct rndis_reset_message { |
| /** Reserved */ |
| uint32_t reserved; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS reset completion */ |
| #define RNDIS_RESET_CMPLT 0x80000006UL |
| |
| /** RNDIS reset completion */ |
| struct rndis_reset_completion { |
| /** Status */ |
| uint32_t status; |
| /** Addressing reset */ |
| uint32_t addr; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS indicate status message */ |
| #define RNDIS_INDICATE_STATUS_MSG 0x00000007UL |
| |
| /** RNDIS diagnostic information */ |
| struct rndis_diagnostic_info { |
| /** Status */ |
| uint32_t status; |
| /** Error offset */ |
| uint32_t offset; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS indicate status message */ |
| struct rndis_indicate_status_message { |
| /** Status */ |
| uint32_t status; |
| /** Status buffer length */ |
| uint32_t len; |
| /** Status buffer offset */ |
| uint32_t offset; |
| /** Diagnostic information (optional) */ |
| struct rndis_diagnostic_info diag[0]; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS status codes */ |
| enum rndis_status { |
| /** Device is connected to a network medium */ |
| RNDIS_STATUS_MEDIA_CONNECT = 0x4001000bUL, |
| /** Device is disconnected from the medium */ |
| RNDIS_STATUS_MEDIA_DISCONNECT = 0x4001000cUL, |
| /** Unknown start-of-day status code */ |
| RNDIS_STATUS_WTF_WORLD = 0x40020006UL, |
| }; |
| |
| /** RNDIS keepalive message */ |
| #define RNDIS_KEEPALIVE_MSG 0x00000008UL |
| |
| /** RNDIS keepalive message */ |
| struct rndis_keepalive_message { |
| /** Request ID */ |
| uint32_t id; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS keepalive completion */ |
| #define RNDIS_KEEPALIVE_CMPLT 0x80000008UL |
| |
| /** RNDIS keepalive completion */ |
| struct rndis_keepalive_completion { |
| /** Request ID */ |
| uint32_t id; |
| /** Status */ |
| uint32_t status; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS packet message */ |
| #define RNDIS_PACKET_MSG 0x00000001UL |
| |
| /** RNDIS packet field */ |
| struct rndis_packet_field { |
| /** Offset */ |
| uint32_t offset; |
| /** Length */ |
| uint32_t len; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS packet message */ |
| struct rndis_packet_message { |
| /** Data */ |
| struct rndis_packet_field data; |
| /** Out-of-band data records */ |
| struct rndis_packet_field oob; |
| /** Number of out-of-band data records */ |
| uint32_t oob_count; |
| /** Per-packet information record */ |
| struct rndis_packet_field ppi; |
| /** Reserved */ |
| uint32_t reserved[2]; |
| } __attribute__ (( packed )); |
| |
| /** RNDIS packet record */ |
| struct rndis_packet_record { |
| /** Length */ |
| uint32_t len; |
| /** Type */ |
| uint32_t type; |
| /** Offset */ |
| uint32_t offset; |
| } __attribute__ (( packed )); |
| |
| /** OID for packet filter */ |
| #define RNDIS_OID_GEN_CURRENT_PACKET_FILTER 0x0001010eUL |
| |
| /** Packet filter bits */ |
| enum rndis_packet_filter { |
| /** Unicast packets */ |
| RNDIS_FILTER_UNICAST = 0x00000001UL, |
| /** Multicast packets */ |
| RNDIS_FILTER_MULTICAST = 0x00000002UL, |
| /** All multicast packets */ |
| RNDIS_FILTER_ALL_MULTICAST = 0x00000004UL, |
| /** Broadcast packets */ |
| RNDIS_FILTER_BROADCAST = 0x00000008UL, |
| /** All packets */ |
| RNDIS_FILTER_PROMISCUOUS = 0x00000020UL |
| }; |
| |
| /** OID for media status */ |
| #define RNDIS_OID_GEN_MEDIA_CONNECT_STATUS 0x00010114UL |
| |
| /** OID for permanent MAC address */ |
| #define RNDIS_OID_802_3_PERMANENT_ADDRESS 0x01010101UL |
| |
| /** OID for current MAC address */ |
| #define RNDIS_OID_802_3_CURRENT_ADDRESS 0x01010102UL |
| |
| struct rndis_device; |
| |
| /** RNDIS device operations */ |
| struct rndis_operations { |
| /** |
| * Open RNDIS device |
| * |
| * @v rndis RNDIS device |
| * @ret rc Return status code |
| */ |
| int ( * open ) ( struct rndis_device *rndis ); |
| /** |
| * Close RNDIS device |
| * |
| * @v rndis RNDIS device |
| */ |
| void ( * close ) ( struct rndis_device *rndis ); |
| /** |
| * Transmit packet |
| * |
| * @v rndis RNDIS device |
| * @v iobuf I/O buffer |
| * @ret rc Return status code |
| * |
| * If this method returns success then the RNDIS device must |
| * eventually report completion via rndis_tx_complete(). |
| */ |
| int ( * transmit ) ( struct rndis_device *rndis, |
| struct io_buffer *iobuf ); |
| /** |
| * Poll for completed and received packets |
| * |
| * @v rndis RNDIS device |
| */ |
| void ( * poll ) ( struct rndis_device *rndis ); |
| }; |
| |
| /** An RNDIS device */ |
| struct rndis_device { |
| /** Network device */ |
| struct net_device *netdev; |
| /** Device name */ |
| const char *name; |
| /** RNDIS operations */ |
| struct rndis_operations *op; |
| /** Driver private data */ |
| void *priv; |
| |
| /** Request ID for current blocking request */ |
| unsigned int wait_id; |
| /** Return status code for current blocking request */ |
| int wait_rc; |
| }; |
| |
| /** |
| * Initialise an RNDIS device |
| * |
| * @v rndis RNDIS device |
| * @v op RNDIS device operations |
| */ |
| static inline void rndis_init ( struct rndis_device *rndis, |
| struct rndis_operations *op ) { |
| |
| rndis->op = op; |
| } |
| |
| extern void rndis_tx_complete_err ( struct rndis_device *rndis, |
| struct io_buffer *iobuf, int rc ); |
| extern int rndis_tx_defer ( struct rndis_device *rndis, |
| struct io_buffer *iobuf ); |
| extern void rndis_rx ( struct rndis_device *rndis, struct io_buffer *iobuf ); |
| extern void rndis_rx_err ( struct rndis_device *rndis, struct io_buffer *iobuf, |
| int rc ); |
| |
| extern struct rndis_device * alloc_rndis ( size_t priv_len ); |
| extern int register_rndis ( struct rndis_device *rndis ); |
| extern void unregister_rndis ( struct rndis_device *rndis ); |
| extern void free_rndis ( struct rndis_device *rndis ); |
| |
| /** |
| * Complete message transmission |
| * |
| * @v rndis RNDIS device |
| * @v iobuf I/O buffer |
| */ |
| static inline void rndis_tx_complete ( struct rndis_device *rndis, |
| struct io_buffer *iobuf ) { |
| |
| rndis_tx_complete_err ( rndis, iobuf, 0 ); |
| } |
| |
| #endif /* _IPXE_RNDIS_H */ |