#ifndef _GPXE_NETDEVICE_H #define _GPXE_NETDEVICE_H /** @file * * Network device management * */ #include #include #include #include struct io_buffer; struct net_device; struct net_protocol; struct ll_protocol; struct device; /** Maximum length of a link-layer address */ #define MAX_LL_ADDR_LEN 6 /** Maximum length of a link-layer header */ #define MAX_LL_HEADER_LEN 16 /** Maximum length of a network-layer address */ #define MAX_NET_ADDR_LEN 4 /** * A network-layer protocol * */ struct net_protocol { /** Protocol name */ const char *name; /** * Process received packet * * @v iobuf I/O buffer * @v netdev Network device * @v ll_source Link-layer source address * * This method takes ownership of the I/O buffer. */ int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev, const void *ll_source ); /** * Transcribe network-layer address * * @v net_addr Network-layer address * @ret string Human-readable transcription of address * * This method should convert the network-layer address into a * human-readable format (e.g. dotted quad notation for IPv4). * * The buffer used to hold the transcription is statically * allocated. */ const char * ( *ntoa ) ( const void * net_addr ); /** Network-layer protocol * * This is an ETH_P_XXX constant, in network-byte order */ uint16_t net_proto; /** Network-layer address length */ uint8_t net_addr_len; }; /** * A link-layer protocol * */ struct ll_protocol { /** Protocol name */ const char *name; /** * Transmit network-layer packet via network device * * @v iobuf I/O buffer * @v netdev Network device * @v net_protocol Network-layer protocol * @v ll_dest Link-layer destination address * @ret rc Return status code * * This method should prepend in the link-layer header * (e.g. the Ethernet DIX header) and transmit the packet. * This method takes ownership of the I/O buffer. */ int ( * tx ) ( struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *ll_dest ); /** * Handle received packet * * @v iobuf I/O buffer * @v netdev Network device * * This method should strip off the link-layer header * (e.g. the Ethernet DIX header) and pass the packet to * net_rx(). This method takes ownership of the packet * buffer. */ int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev ); /** * Transcribe link-layer address * * @v ll_addr Link-layer address * @ret string Human-readable transcription of address * * This method should convert the link-layer address into a * human-readable format. * * The buffer used to hold the transcription is statically * allocated. */ const char * ( * ntoa ) ( const void * ll_addr ); /** Link-layer protocol * * This is an ARPHRD_XXX constant, in network byte order. */ uint16_t ll_proto; /** Link-layer address length */ uint8_t ll_addr_len; /** Link-layer broadcast address */ const uint8_t *ll_broadcast; }; /** * A network device * * This structure represents a piece of networking hardware. It has * properties such as a link-layer address and methods for * transmitting and receiving raw packets. * * Note that this structure must represent a generic network device, * not just an Ethernet device. */ struct net_device { /** List of network devices */ struct list_head list; /** Name of this network device */ char name[8]; /** Underlying hardware device */ struct device *dev; /** List of persistent reference holders */ struct list_head references; /** Open network device * * @v netdev Network device * @ret rc Return status code * * This method should allocate RX I/O buffers and enable * the hardware to start transmitting and receiving packets. */ int ( * open ) ( struct net_device *netdev ); /** Close network device * * @v netdev Network device * * This method should stop the flow of packets, and free up * any packets that are currently in the device's TX queue. */ void ( * close ) ( struct net_device *netdev ); /** Transmit packet * * @v netdev Network device * @v iobuf I/O buffer * @ret rc Return status code * * This method should cause the hardware to initiate * transmission of the I/O buffer. * * If this method returns success, the I/O buffer remains * owned by the net device's TX queue, and the net device must * eventually call netdev_tx_complete() to free the buffer. * If this method returns failure, the I/O buffer is * immediately released. * * This method is guaranteed to be called only when the device * is open. */ int ( * transmit ) ( struct net_device *netdev, struct io_buffer *iobuf ); /** Poll for received packet * * @v netdev Network device * @v rx_quota Maximum number of packets to receive * * This method should cause the hardware to check for received * packets. Any received packets should be delivered via * netdev_rx(), up to a maximum of @c rx_quota packets. * * This method is guaranteed to be called only when the device * is open. */ void ( * poll ) ( struct net_device *netdev, unsigned int rx_quota ); /** Link-layer protocol */ struct ll_protocol *ll_protocol; /** Link-layer address * * For Ethernet, this is the MAC address. */ uint8_t ll_addr[MAX_LL_ADDR_LEN]; /** Current device state * * This is the bitwise-OR of zero or more NETDEV_XXX constants. */ unsigned int state; /** TX packet queue */ struct list_head tx_queue; /** RX packet queue */ struct list_head rx_queue; /** Driver private data */ void *priv; }; /** Network device is open */ #define NETDEV_OPEN 0x0001 /** Declare a link-layer protocol */ #define __ll_protocol __table ( struct ll_protocol, ll_protocols, 01 ) /** Declare a network-layer protocol */ #define __net_protocol __table ( struct net_protocol, net_protocols, 01 ) extern struct list_head net_devices; /** * Get printable network device hardware address * * @v netdev Network device * @ret name Hardware address */ static inline const char * netdev_hwaddr ( struct net_device *netdev ) { return netdev->ll_protocol->ntoa ( netdev->ll_addr ); } /** Iterate over all network devices */ #define for_each_netdev( netdev ) \ list_for_each_entry ( (netdev), &net_devices, list ) /** There exist some network devices * * @ret existence Existence of network devices */ static inline int have_netdevs ( void ) { return ( ! list_empty ( &net_devices ) ); } extern int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ); void netdev_tx_complete ( struct net_device *netdev, struct io_buffer *iobuf ); void netdev_tx_complete_next ( struct net_device *netdev ); extern void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ); extern int netdev_poll ( struct net_device *netdev, unsigned int rx_quota ); extern struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ); extern struct net_device * alloc_netdev ( size_t priv_size ); extern int register_netdev ( struct net_device *netdev ); extern int netdev_open ( struct net_device *netdev ); extern void netdev_close ( struct net_device *netdev ); extern void unregister_netdev ( struct net_device *netdev ); extern void free_netdev ( struct net_device *netdev ); struct net_device * find_netdev ( const char *name ); struct net_device * find_pci_netdev ( unsigned int busdevfn ); extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *ll_dest ); extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev, uint16_t net_proto, const void *ll_source ); #endif /* _GPXE_NETDEVICE_H */