#include "etherboot.h"#include "nic.h"#include "gpxe/virtio-ring.h"#include "gpxe/virtio-pci.h"#include "virtio-net.h"Go to the source code of this file.
Data Structures | |
| struct | eth_hdr |
| struct | eth_frame |
Defines | |
| #define | BUG() |
| #define | BUG_ON(condition) do { if (condition) BUG(); } while (0) |
| #define | RX_BUF_NB 6 |
Enumerations | |
| enum | { RX_INDEX = 0, TX_INDEX, QUEUE_NB } |
Functions | |
| static void | virtnet_disable (struct nic *nic) |
| static int | virtnet_poll (struct nic *nic, int retrieve) |
| static void | virtnet_transmit (struct nic *nic, const char *destaddr, unsigned int type, unsigned int len, const char *data) |
| static void | virtnet_irq (struct nic *nic __unused, irq_action_t action) |
| static void | provide_buffers (struct nic *nic) |
| static int | virtnet_probe (struct nic *nic, struct pci_device *pci) |
| PCI_DRIVER (virtnet_driver, virtnet_nics, PCI_NO_CLASS) | |
| DRIVER ("VIRTIO-NET", nic_driver, pci_driver, virtnet_driver, virtnet_probe, virtnet_disable) | |
Variables | |
| static struct virtio_net_hdr | tx_virtio_hdr |
| static struct eth_frame | tx_eth_frame |
| static struct virtio_net_hdr | rx_hdr [RX_BUF_NB] |
| static unsigned char | rx_buffer [RX_BUF_NB][ETH_FRAME_LEN] |
| static struct vring_virtqueue | virtqueue [QUEUE_NB] |
| static struct nic_operations | virtnet_operations |
| static struct pci_device_id | virtnet_nics [] |
| #define BUG | ( | ) |
Value:
do { \ printf("BUG: failure at %s:%d/%s()!\n", \ __FILE__, __LINE__, __FUNCTION__); \ while(1); \ } while (0)
Definition at line 28 of file virtio-net.c.
| #define BUG_ON | ( | condition | ) | do { if (condition) BUG(); } while (0) |
Definition at line 33 of file virtio-net.c.
| #define RX_BUF_NB 6 |
| anonymous enum |
| static void virtnet_disable | ( | struct nic * | nic | ) | [static] |
Definition at line 76 of file virtio-net.c.
References nic::ioaddr, QUEUE_NB, virtqueue, vp_del_vq(), vp_reset(), and vring_disable_cb().
00077 { 00078 int i; 00079 00080 for (i = 0; i < QUEUE_NB; i++) { 00081 vring_disable_cb(&virtqueue[i]); 00082 vp_del_vq(nic->ioaddr, i); 00083 } 00084 vp_reset(nic->ioaddr); 00085 }
| static int virtnet_poll | ( | struct nic * | nic, | |
| int | retrieve | |||
| ) | [static] |
Definition at line 98 of file virtio-net.c.
References vring_list::addr, BUG_ON, ETH_FRAME_LEN, nic::ioaddr, vring_list::length, memcpy, nic::packet, nic::packetlen, rx_buffer, rx_hdr, RX_INDEX, u16, virtqueue, vring_add_buf(), vring_get_buf(), vring_kick(), and vring_more_used().
00099 { 00100 unsigned int len; 00101 u16 token; 00102 struct virtio_net_hdr *hdr; 00103 struct vring_list list[2]; 00104 00105 if (!vring_more_used(&virtqueue[RX_INDEX])) 00106 return 0; 00107 00108 if (!retrieve) 00109 return 1; 00110 00111 token = vring_get_buf(&virtqueue[RX_INDEX], &len); 00112 00113 BUG_ON(len > sizeof(struct virtio_net_hdr) + ETH_FRAME_LEN); 00114 00115 hdr = &rx_hdr[token]; /* FIXME: check flags */ 00116 len -= sizeof(struct virtio_net_hdr); 00117 00118 nic->packetlen = len; 00119 memcpy(nic->packet, (char *)rx_buffer[token], nic->packetlen); 00120 00121 /* add buffer to desc */ 00122 00123 list[0].addr = (char*)&rx_hdr[token]; 00124 list[0].length = sizeof(struct virtio_net_hdr); 00125 list[1].addr = (char*)&rx_buffer[token]; 00126 list[1].length = ETH_FRAME_LEN; 00127 00128 vring_add_buf(&virtqueue[RX_INDEX], list, 0, 2, token, 0); 00129 vring_kick(nic->ioaddr, &virtqueue[RX_INDEX], 1); 00130 00131 return 1; 00132 }
| static void virtnet_transmit | ( | struct nic * | nic, | |
| const char * | destaddr, | |||
| unsigned int | type, | |||
| unsigned int | len, | |||
| const char * | data | |||
| ) | [static] |
Definition at line 142 of file virtio-net.c.
References vring_list::addr, BUG_ON, virtio_net_hdr::csum_offset, virtio_net_hdr::csum_start, eth_frame::data, eth_hdr::dst_addr, ETH_ALEN, ETH_FRAME_LEN, virtio_net_hdr::flags, virtio_net_hdr::gso_size, virtio_net_hdr::gso_type, eth_frame::hdr, virtio_net_hdr::hdr_len, htons, nic::ioaddr, vring_list::length, mb(), memcpy, nic::node_addr, NULL, eth_hdr::src_addr, tx_eth_frame, TX_INDEX, tx_virtio_hdr, eth_hdr::type, udelay(), VIRTIO_NET_HDR_GSO_NONE, virtqueue, vring_add_buf(), vring_get_buf(), vring_kick(), and vring_more_used().
00144 { 00145 struct vring_list list[2]; 00146 00147 /* 00148 * from http://www.etherboot.org/wiki/dev/devmanual : 00149 * "You do not need more than one transmit buffer." 00150 */ 00151 00152 /* FIXME: initialize header according to vp_get_features() */ 00153 00154 tx_virtio_hdr.flags = 0; 00155 tx_virtio_hdr.csum_offset = 0; 00156 tx_virtio_hdr.csum_start = 0; 00157 tx_virtio_hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE; 00158 tx_virtio_hdr.gso_size = 0; 00159 tx_virtio_hdr.hdr_len = 0; 00160 00161 /* add ethernet frame into vring */ 00162 00163 BUG_ON(len > sizeof(tx_eth_frame.data)); 00164 00165 memcpy(tx_eth_frame.hdr.dst_addr, destaddr, ETH_ALEN); 00166 memcpy(tx_eth_frame.hdr.src_addr, nic->node_addr, ETH_ALEN); 00167 tx_eth_frame.hdr.type = htons(type); 00168 memcpy(tx_eth_frame.data, data, len); 00169 00170 list[0].addr = (char*)&tx_virtio_hdr; 00171 list[0].length = sizeof(struct virtio_net_hdr); 00172 list[1].addr = (char*)&tx_eth_frame; 00173 list[1].length = ETH_FRAME_LEN; 00174 00175 vring_add_buf(&virtqueue[TX_INDEX], list, 2, 0, 0, 0); 00176 00177 vring_kick(nic->ioaddr, &virtqueue[TX_INDEX], 1); 00178 00179 /* 00180 * http://www.etherboot.org/wiki/dev/devmanual 00181 * 00182 * "You should ensure the packet is fully transmitted 00183 * before returning from this routine" 00184 */ 00185 00186 while (!vring_more_used(&virtqueue[TX_INDEX])) { 00187 mb(); 00188 udelay(10); 00189 } 00190 00191 /* free desc */ 00192 00193 (void)vring_get_buf(&virtqueue[TX_INDEX], NULL); 00194 }
| static void virtnet_irq | ( | struct nic *nic | __unused, | |
| irq_action_t | action | |||
| ) | [static] |
Definition at line 196 of file virtio-net.c.
References DISABLE, ENABLE, FORCE, RX_INDEX, TX_INDEX, virtqueue, vring_disable_cb(), and vring_enable_cb().
00197 { 00198 switch ( action ) { 00199 case DISABLE : 00200 vring_disable_cb(&virtqueue[RX_INDEX]); 00201 vring_disable_cb(&virtqueue[TX_INDEX]); 00202 break; 00203 case ENABLE : 00204 vring_enable_cb(&virtqueue[RX_INDEX]); 00205 vring_enable_cb(&virtqueue[TX_INDEX]); 00206 break; 00207 case FORCE : 00208 break; 00209 } 00210 }
| static void provide_buffers | ( | struct nic * | nic | ) | [static] |
Definition at line 212 of file virtio-net.c.
References vring_list::addr, ETH_FRAME_LEN, nic::ioaddr, vring_list::length, RX_BUF_NB, rx_buffer, rx_hdr, RX_INDEX, virtqueue, vring_add_buf(), and vring_kick().
Referenced by virtnet_probe().
00213 { 00214 int i; 00215 struct vring_list list[2]; 00216 00217 for (i = 0; i < RX_BUF_NB; i++) { 00218 list[0].addr = (char*)&rx_hdr[i]; 00219 list[0].length = sizeof(struct virtio_net_hdr); 00220 list[1].addr = (char*)&rx_buffer[i]; 00221 list[1].length = ETH_FRAME_LEN; 00222 vring_add_buf(&virtqueue[RX_INDEX], list, 0, 2, i, i); 00223 } 00224 00225 /* nofify */ 00226 00227 vring_kick(nic->ioaddr, &virtqueue[RX_INDEX], i); 00228 }
| static int virtnet_probe | ( | struct nic * | nic, | |
| struct pci_device * | pci | |||
| ) | [static] |
Definition at line 244 of file virtio-net.c.
References adjust_pci_device(), ETH_ALEN, vring_virtqueue::free_head, pci_device::ioaddr, nic::ioaddr, pci_device::irq, nic::irqno, vring_virtqueue::last_used_idx, memset(), nic::nic_op, nic::node_addr, offsetof, printf(), provide_buffers(), QUEUE_NB, u32, VIRTIO_CONFIG_S_DRIVER, VIRTIO_CONFIG_S_DRIVER_OK, VIRTIO_NET_F_MAC, virtqueue, vp_find_vq(), vp_get(), vp_get_features(), vp_reset(), vp_set_features(), and vp_set_status().
00245 { 00246 u32 features; 00247 int i; 00248 00249 /* Mask the bit that says "this is an io addr" */ 00250 00251 nic->ioaddr = pci->ioaddr & ~3; 00252 00253 /* Copy IRQ from PCI information */ 00254 00255 nic->irqno = pci->irq; 00256 00257 printf("I/O address 0x%08x, IRQ #%d\n", nic->ioaddr, nic->irqno); 00258 00259 adjust_pci_device(pci); 00260 00261 vp_reset(nic->ioaddr); 00262 00263 features = vp_get_features(nic->ioaddr); 00264 if (features & (1 << VIRTIO_NET_F_MAC)) { 00265 vp_get(nic->ioaddr, offsetof(struct virtio_net_config, mac), 00266 nic->node_addr, ETH_ALEN); 00267 printf("MAC address "); 00268 for (i = 0; i < ETH_ALEN; i++) { 00269 printf("%02x%c", nic->node_addr[i], 00270 (i == ETH_ALEN - 1) ? '\n' : ':'); 00271 } 00272 } 00273 00274 /* initialize emit/receive queue */ 00275 00276 for (i = 0; i < QUEUE_NB; i++) { 00277 virtqueue[i].free_head = 0; 00278 virtqueue[i].last_used_idx = 0; 00279 memset((char*)&virtqueue[i].queue, 0, sizeof(virtqueue[i].queue)); 00280 if (vp_find_vq(nic->ioaddr, i, &virtqueue[i]) == -1) 00281 printf("Cannot register queue #%d\n", i); 00282 } 00283 00284 /* provide some receive buffers */ 00285 00286 provide_buffers(nic); 00287 00288 /* define NIC interface */ 00289 00290 nic->nic_op = &virtnet_operations; 00291 00292 /* driver is ready */ 00293 00294 vp_set_features(nic->ioaddr, features & (1 << VIRTIO_NET_F_MAC)); 00295 vp_set_status(nic->ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK); 00296 00297 return 1; 00298 }
| PCI_DRIVER | ( | virtnet_driver | , | |
| virtnet_nics | , | |||
| PCI_NO_CLASS | ||||
| ) |
| DRIVER | ( | "VIRTIO-NET" | , | |
| nic_driver | , | |||
| pci_driver | , | |||
| virtnet_driver | , | |||
| virtnet_probe | , | |||
| virtnet_disable | ||||
| ) |
struct virtio_net_hdr tx_virtio_hdr [static] |
struct eth_frame tx_eth_frame [static] |
struct virtio_net_hdr rx_hdr[RX_BUF_NB] [static] |
Definition at line 56 of file virtio-net.c.
Referenced by bnx2_poll(), provide_buffers(), and virtnet_poll().
unsigned char rx_buffer[RX_BUF_NB][ETH_FRAME_LEN] [static] |
struct vring_virtqueue virtqueue[QUEUE_NB] [static] |
Definition at line 67 of file virtio-net.c.
Referenced by provide_buffers(), virtnet_disable(), virtnet_irq(), virtnet_poll(), virtnet_probe(), and virtnet_transmit().
struct nic_operations virtnet_operations [static] |
Initial value:
{
.connect = dummy_connect,
.poll = virtnet_poll,
.transmit = virtnet_transmit,
.irq = virtnet_irq,
}
Definition at line 230 of file virtio-net.c.
struct pci_device_id virtnet_nics[] [static] |
Initial value:
{
PCI_ROM(0x1af4, 0x1000, "virtio-net", "Virtio Network Interface", 0),
}
Definition at line 300 of file virtio-net.c.
1.5.7.1