Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

virtio-net.c 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /* virtio-net.c - etherboot driver for virtio network interface
  2. *
  3. * (c) Copyright 2008 Bull S.A.S.
  4. *
  5. * Author: Laurent Vivier <Laurent.Vivier@bull.net>
  6. *
  7. * some parts from Linux Virtio PCI driver
  8. *
  9. * Copyright IBM Corp. 2007
  10. * Authors: Anthony Liguori <aliguori@us.ibm.com>
  11. *
  12. * some parts from Linux Virtio Ring
  13. *
  14. * Copyright Rusty Russell IBM Corporation 2007
  15. *
  16. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  17. * See the COPYING file in the top-level directory.
  18. *
  19. *
  20. */
  21. #include "etherboot.h"
  22. #include "nic.h"
  23. #include "gpxe/virtio-ring.h"
  24. #include "gpxe/virtio-pci.h"
  25. #include "virtio-net.h"
  26. #define BUG() do { \
  27. printf("BUG: failure at %s:%d/%s()!\n", \
  28. __FILE__, __LINE__, __FUNCTION__); \
  29. while(1); \
  30. } while (0)
  31. #define BUG_ON(condition) do { if (condition) BUG(); } while (0)
  32. /* Ethernet header */
  33. struct eth_hdr {
  34. unsigned char dst_addr[ETH_ALEN];
  35. unsigned char src_addr[ETH_ALEN];
  36. unsigned short type;
  37. };
  38. struct eth_frame {
  39. struct eth_hdr hdr;
  40. unsigned char data[ETH_FRAME_LEN];
  41. };
  42. /* TX: virtio header and eth buffer */
  43. static struct virtio_net_hdr tx_virtio_hdr;
  44. static struct eth_frame tx_eth_frame;
  45. /* RX: virtio headers and buffers */
  46. #define RX_BUF_NB 6
  47. static struct virtio_net_hdr rx_hdr[RX_BUF_NB];
  48. static unsigned char rx_buffer[RX_BUF_NB][ETH_FRAME_LEN];
  49. /* virtio queues and vrings */
  50. enum {
  51. RX_INDEX = 0,
  52. TX_INDEX,
  53. QUEUE_NB
  54. };
  55. static struct vring_virtqueue virtqueue[QUEUE_NB];
  56. /*
  57. * virtnet_disable
  58. *
  59. * Turn off ethernet interface
  60. *
  61. */
  62. static void virtnet_disable(struct nic *nic)
  63. {
  64. int i;
  65. for (i = 0; i < QUEUE_NB; i++) {
  66. vring_disable_cb(&virtqueue[i]);
  67. vp_del_vq(nic->ioaddr, i);
  68. }
  69. vp_reset(nic->ioaddr);
  70. }
  71. /*
  72. * virtnet_poll
  73. *
  74. * Wait for a frame
  75. *
  76. * return true if there is a packet ready to read
  77. *
  78. * nic->packet should contain data on return
  79. * nic->packetlen should contain length of data
  80. *
  81. */
  82. static int virtnet_poll(struct nic *nic, int retrieve)
  83. {
  84. unsigned int len;
  85. u16 token;
  86. struct virtio_net_hdr *hdr;
  87. struct vring_list list[2];
  88. if (!vring_more_used(&virtqueue[RX_INDEX]))
  89. return 0;
  90. if (!retrieve)
  91. return 1;
  92. token = vring_get_buf(&virtqueue[RX_INDEX], &len);
  93. BUG_ON(len > sizeof(struct virtio_net_hdr) + ETH_FRAME_LEN);
  94. hdr = &rx_hdr[token]; /* FIXME: check flags */
  95. len -= sizeof(struct virtio_net_hdr);
  96. nic->packetlen = len;
  97. memcpy(nic->packet, (char *)rx_buffer[token], nic->packetlen);
  98. /* add buffer to desc */
  99. list[0].addr = (char*)&rx_hdr[token];
  100. list[0].length = sizeof(struct virtio_net_hdr);
  101. list[1].addr = (char*)&rx_buffer[token];
  102. list[1].length = ETH_FRAME_LEN;
  103. vring_add_buf(&virtqueue[RX_INDEX], list, 0, 2, token, 0);
  104. vring_kick(nic->ioaddr, &virtqueue[RX_INDEX], 1);
  105. return 1;
  106. }
  107. /*
  108. *
  109. * virtnet_transmit
  110. *
  111. * Transmit a frame
  112. *
  113. */
  114. static void virtnet_transmit(struct nic *nic, const char *destaddr,
  115. unsigned int type, unsigned int len, const char *data)
  116. {
  117. struct vring_list list[2];
  118. /*
  119. * from http://www.etherboot.org/wiki/dev/devmanual :
  120. * "You do not need more than one transmit buffer."
  121. */
  122. /* FIXME: initialize header according to vp_get_features() */
  123. tx_virtio_hdr.flags = 0;
  124. tx_virtio_hdr.csum_offset = 0;
  125. tx_virtio_hdr.csum_start = 0;
  126. tx_virtio_hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE;
  127. tx_virtio_hdr.gso_size = 0;
  128. tx_virtio_hdr.hdr_len = 0;
  129. /* add ethernet frame into vring */
  130. BUG_ON(len > sizeof(tx_eth_frame.data));
  131. memcpy(tx_eth_frame.hdr.dst_addr, destaddr, ETH_ALEN);
  132. memcpy(tx_eth_frame.hdr.src_addr, nic->node_addr, ETH_ALEN);
  133. tx_eth_frame.hdr.type = htons(type);
  134. memcpy(tx_eth_frame.data, data, len);
  135. list[0].addr = (char*)&tx_virtio_hdr;
  136. list[0].length = sizeof(struct virtio_net_hdr);
  137. list[1].addr = (char*)&tx_eth_frame;
  138. list[1].length = ETH_FRAME_LEN;
  139. vring_add_buf(&virtqueue[TX_INDEX], list, 2, 0, 0, 0);
  140. vring_kick(nic->ioaddr, &virtqueue[TX_INDEX], 1);
  141. /*
  142. * http://www.etherboot.org/wiki/dev/devmanual
  143. *
  144. * "You should ensure the packet is fully transmitted
  145. * before returning from this routine"
  146. */
  147. while (!vring_more_used(&virtqueue[TX_INDEX])) {
  148. mb();
  149. udelay(10);
  150. }
  151. /* free desc */
  152. (void)vring_get_buf(&virtqueue[TX_INDEX], NULL);
  153. }
  154. static void virtnet_irq(struct nic *nic __unused, irq_action_t action)
  155. {
  156. switch ( action ) {
  157. case DISABLE :
  158. vring_disable_cb(&virtqueue[RX_INDEX]);
  159. vring_disable_cb(&virtqueue[TX_INDEX]);
  160. break;
  161. case ENABLE :
  162. vring_enable_cb(&virtqueue[RX_INDEX]);
  163. vring_enable_cb(&virtqueue[TX_INDEX]);
  164. break;
  165. case FORCE :
  166. break;
  167. }
  168. }
  169. static void provide_buffers(struct nic *nic)
  170. {
  171. int i;
  172. struct vring_list list[2];
  173. for (i = 0; i < RX_BUF_NB; i++) {
  174. list[0].addr = (char*)&rx_hdr[i];
  175. list[0].length = sizeof(struct virtio_net_hdr);
  176. list[1].addr = (char*)&rx_buffer[i];
  177. list[1].length = ETH_FRAME_LEN;
  178. vring_add_buf(&virtqueue[RX_INDEX], list, 0, 2, i, i);
  179. }
  180. /* nofify */
  181. vring_kick(nic->ioaddr, &virtqueue[RX_INDEX], i);
  182. }
  183. static struct nic_operations virtnet_operations = {
  184. .connect = dummy_connect,
  185. .poll = virtnet_poll,
  186. .transmit = virtnet_transmit,
  187. .irq = virtnet_irq,
  188. };
  189. /*
  190. * virtnet_probe
  191. *
  192. * Look for a virtio network adapter
  193. *
  194. */
  195. static int virtnet_probe(struct nic *nic, struct pci_device *pci)
  196. {
  197. u32 features;
  198. int i;
  199. /* Mask the bit that says "this is an io addr" */
  200. nic->ioaddr = pci->ioaddr & ~3;
  201. /* Copy IRQ from PCI information */
  202. nic->irqno = pci->irq;
  203. printf("I/O address 0x%08x, IRQ #%d\n", nic->ioaddr, nic->irqno);
  204. adjust_pci_device(pci);
  205. vp_reset(nic->ioaddr);
  206. features = vp_get_features(nic->ioaddr);
  207. if (features & (1 << VIRTIO_NET_F_MAC)) {
  208. vp_get(nic->ioaddr, offsetof(struct virtio_net_config, mac),
  209. nic->node_addr, ETH_ALEN);
  210. printf("MAC address ");
  211. for (i = 0; i < ETH_ALEN; i++) {
  212. printf("%02x%c", nic->node_addr[i],
  213. (i == ETH_ALEN - 1) ? '\n' : ':');
  214. }
  215. }
  216. /* initialize emit/receive queue */
  217. for (i = 0; i < QUEUE_NB; i++) {
  218. virtqueue[i].free_head = 0;
  219. virtqueue[i].last_used_idx = 0;
  220. memset((char*)&virtqueue[i].queue, 0, sizeof(virtqueue[i].queue));
  221. if (vp_find_vq(nic->ioaddr, i, &virtqueue[i]) == -1)
  222. printf("Cannot register queue #%d\n", i);
  223. }
  224. /* provide some receive buffers */
  225. provide_buffers(nic);
  226. /* define NIC interface */
  227. nic->nic_op = &virtnet_operations;
  228. /* driver is ready */
  229. vp_set_features(nic->ioaddr, features & (1 << VIRTIO_NET_F_MAC));
  230. vp_set_status(nic->ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK);
  231. return 1;
  232. }
  233. static struct pci_device_id virtnet_nics[] = {
  234. PCI_ROM(0x1af4, 0x1000, "virtio-net", "Virtio Network Interface", 0),
  235. };
  236. PCI_DRIVER ( virtnet_driver, virtnet_nics, PCI_NO_CLASS );
  237. DRIVER ( "VIRTIO-NET", nic_driver, pci_driver, virtnet_driver,
  238. virtnet_probe, virtnet_disable );