iPXE
virtio-net.c
Go to the documentation of this file.
00001 /*
00002  * (c) Copyright 2010 Stefan Hajnoczi <stefanha@gmail.com>
00003  *
00004  * based on the Etherboot virtio-net driver
00005  *
00006  *  (c) Copyright 2008 Bull S.A.S.
00007  *
00008  *  Author: Laurent Vivier <Laurent.Vivier@bull.net>
00009  *
00010  * some parts from Linux Virtio PCI driver
00011  *
00012  *  Copyright IBM Corp. 2007
00013  *  Authors: Anthony Liguori  <aliguori@us.ibm.com>
00014  *
00015  *  some parts from Linux Virtio Ring
00016  *
00017  *  Copyright Rusty Russell IBM Corporation 2007
00018  *
00019  * This work is licensed under the terms of the GNU GPL, version 2 or later.
00020  * See the COPYING file in the top-level directory.
00021  */
00022 
00023 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00024 
00025 #include <errno.h>
00026 #include <stdlib.h>
00027 #include <unistd.h>
00028 #include <ipxe/list.h>
00029 #include <ipxe/iobuf.h>
00030 #include <ipxe/netdevice.h>
00031 #include <ipxe/pci.h>
00032 #include <ipxe/if_ether.h>
00033 #include <ipxe/ethernet.h>
00034 #include <ipxe/virtio-pci.h>
00035 #include <ipxe/virtio-ring.h>
00036 #include "virtio-net.h"
00037 
00038 /*
00039  * Virtio network device driver
00040  *
00041  * Specification:
00042  * http://ozlabs.org/~rusty/virtio-spec/
00043  *
00044  * The virtio network device is supported by Linux virtualization software
00045  * including QEMU/KVM and lguest.  This driver supports the virtio over PCI
00046  * transport; virtual machines have one virtio-net PCI adapter per NIC.
00047  *
00048  * Virtio-net is different from hardware NICs because virtio devices
00049  * communicate with the hypervisor via virtqueues, not traditional descriptor
00050  * rings.  Virtqueues are unordered queues, they support add_buf() and
00051  * get_buf() operations.  To transmit a packet, the driver has to add the
00052  * packet buffer onto the virtqueue.  To receive a packet, the driver must
00053  * first add an empty buffer to the virtqueue and then get the filled packet
00054  * buffer on completion.
00055  *
00056  * Virtqueues are an abstraction that is commonly implemented using the vring
00057  * descriptor ring layout.  The vring is the actual shared memory structure
00058  * that allows the virtual machine to communicate buffers with the hypervisor.
00059  * Because the vring layout is optimized for flexibility and performance rather
00060  * than space, it is heavy-weight and allocated like traditional descriptor
00061  * rings in the open() function of the driver and not in probe().
00062  *
00063  * There is no true interrupt enable/disable.  Virtqueues have callback
00064  * enable/disable flags but these are only hints.  The hypervisor may still
00065  * raise an interrupt.  Nevertheless, this driver disables callbacks in the
00066  * hopes of avoiding interrupts.
00067  */
00068 
00069 /* Driver types are declared here so virtio-net.h can be easily synced with its
00070  * Linux source.
00071  */
00072 
00073 /* Virtqueue indices */
00074 enum {
00075         RX_INDEX = 0,
00076         TX_INDEX,
00077         QUEUE_NB
00078 };
00079 
00080 /** Max number of pending rx packets */
00081 #define NUM_RX_BUF 8
00082 
00083 struct virtnet_nic {
00084         /** Base pio register address */
00085         unsigned long ioaddr;
00086 
00087         /** 0 for legacy, 1 for virtio 1.0 */
00088         int virtio_version;
00089 
00090         /** Virtio 1.0 device data */
00091         struct virtio_pci_modern_device vdev;
00092 
00093         /** RX/TX virtqueues */
00094         struct vring_virtqueue *virtqueue;
00095 
00096         /** RX packets handed to the NIC waiting to be filled in */
00097         struct list_head rx_iobufs;
00098 
00099         /** Pending rx packet count */
00100         unsigned int rx_num_iobufs;
00101 
00102         /** Virtio net dummy packet headers */
00103         struct virtio_net_hdr_modern empty_header[QUEUE_NB];
00104 };
00105 
00106 /** Add an iobuf to a virtqueue
00107  *
00108  * @v netdev            Network device
00109  * @v vq_idx            Virtqueue index (RX_INDEX or TX_INDEX)
00110  * @v iobuf             I/O buffer
00111  *
00112  * The virtqueue is kicked after the iobuf has been added.
00113  */
00114 static void virtnet_enqueue_iob ( struct net_device *netdev,
00115                                   int vq_idx, struct io_buffer *iobuf ) {
00116         struct virtnet_nic *virtnet = netdev->priv;
00117         struct vring_virtqueue *vq = &virtnet->virtqueue[vq_idx];
00118         struct virtio_net_hdr_modern *header = &virtnet->empty_header[vq_idx];
00119         unsigned int out = ( vq_idx == TX_INDEX ) ? 2 : 0;
00120         unsigned int in = ( vq_idx == TX_INDEX ) ? 0 : 2;
00121         size_t header_len = ( virtnet->virtio_version ?
00122                               sizeof ( *header ) : sizeof ( header->legacy ) );
00123         struct vring_list list[] = {
00124                 {
00125                         /* Share a single zeroed virtio net header between all
00126                          * packets in a ring.  This works because this driver
00127                          * does not use any advanced features so none of the
00128                          * header fields get used.
00129                          *
00130                          * Some host implementations (notably Google Compute
00131                          * Platform) are known to unconditionally write back
00132                          * to header->flags for received packets.  Work around
00133                          * this by using separate RX and TX headers.
00134                          */
00135                         .addr = ( char* ) header,
00136                         .length = header_len,
00137                 },
00138                 {
00139                         .addr = ( char* ) iobuf->data,
00140                         .length = iob_len ( iobuf ),
00141                 },
00142         };
00143 
00144         DBGC2 ( virtnet, "VIRTIO-NET %p enqueuing iobuf %p on vq %d\n",
00145                 virtnet, iobuf, vq_idx );
00146 
00147         vring_add_buf ( vq, list, out, in, iobuf, 0 );
00148         vring_kick ( virtnet->virtio_version ? &virtnet->vdev : NULL,
00149                      virtnet->ioaddr, vq, 1 );
00150 }
00151 
00152 /** Try to keep rx virtqueue filled with iobufs
00153  *
00154  * @v netdev            Network device
00155  */
00156 static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
00157         struct virtnet_nic *virtnet = netdev->priv;
00158         size_t len = ( netdev->max_pkt_len + 4 /* VLAN */ );
00159 
00160         while ( virtnet->rx_num_iobufs < NUM_RX_BUF ) {
00161                 struct io_buffer *iobuf;
00162 
00163                 /* Try to allocate a buffer, stop for now if out of memory */
00164                 iobuf = alloc_iob ( len );
00165                 if ( ! iobuf )
00166                         break;
00167 
00168                 /* Keep track of iobuf so close() can free it */
00169                 list_add ( &iobuf->list, &virtnet->rx_iobufs );
00170 
00171                 /* Mark packet length until we know the actual size */
00172                 iob_put ( iobuf, len );
00173 
00174                 virtnet_enqueue_iob ( netdev, RX_INDEX, iobuf );
00175                 virtnet->rx_num_iobufs++;
00176         }
00177 }
00178 
00179 /** Helper to free all virtqueue memory
00180  *
00181  * @v netdev            Network device
00182  */
00183 static void virtnet_free_virtqueues ( struct net_device *netdev ) {
00184         struct virtnet_nic *virtnet = netdev->priv;
00185         int i;
00186 
00187         for ( i = 0; i < QUEUE_NB; i++ ) {
00188                 virtio_pci_unmap_capability ( &virtnet->virtqueue[i].notification );
00189                 vp_free_vq ( &virtnet->virtqueue[i] );
00190         }
00191 
00192         free ( virtnet->virtqueue );
00193         virtnet->virtqueue = NULL;
00194 }
00195 
00196 /** Open network device, legacy virtio 0.9.5
00197  *
00198  * @v netdev    Network device
00199  * @ret rc      Return status code
00200  */
00201 static int virtnet_open_legacy ( struct net_device *netdev ) {
00202         struct virtnet_nic *virtnet = netdev->priv;
00203         unsigned long ioaddr = virtnet->ioaddr;
00204         u32 features;
00205         int i;
00206 
00207         /* Reset for sanity */
00208         vp_reset ( ioaddr );
00209 
00210         /* Allocate virtqueues */
00211         virtnet->virtqueue = zalloc ( QUEUE_NB *
00212                                       sizeof ( *virtnet->virtqueue ) );
00213         if ( ! virtnet->virtqueue )
00214                 return -ENOMEM;
00215 
00216         /* Initialize rx/tx virtqueues */
00217         for ( i = 0; i < QUEUE_NB; i++ ) {
00218                 if ( vp_find_vq ( ioaddr, i, &virtnet->virtqueue[i] ) == -1 ) {
00219                         DBGC ( virtnet, "VIRTIO-NET %p cannot register queue %d\n",
00220                                virtnet, i );
00221                         virtnet_free_virtqueues ( netdev );
00222                         return -ENOENT;
00223                 }
00224         }
00225 
00226         /* Initialize rx packets */
00227         INIT_LIST_HEAD ( &virtnet->rx_iobufs );
00228         virtnet->rx_num_iobufs = 0;
00229         virtnet_refill_rx_virtqueue ( netdev );
00230 
00231         /* Disable interrupts before starting */
00232         netdev_irq ( netdev, 0 );
00233 
00234         /* Driver is ready */
00235         features = vp_get_features ( ioaddr );
00236         vp_set_features ( ioaddr, features & ( ( 1 << VIRTIO_NET_F_MAC ) |
00237                                                ( 1 << VIRTIO_NET_F_MTU ) ) );
00238         vp_set_status ( ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK );
00239         return 0;
00240 }
00241 
00242 /** Open network device, modern virtio 1.0
00243  *
00244  * @v netdev    Network device
00245  * @ret rc      Return status code
00246  */
00247 static int virtnet_open_modern ( struct net_device *netdev ) {
00248         struct virtnet_nic *virtnet = netdev->priv;
00249         u64 features;
00250         u8 status;
00251 
00252         /* Negotiate features */
00253         features = vpm_get_features ( &virtnet->vdev );
00254         if ( ! ( features & VIRTIO_F_VERSION_1 ) ) {
00255                 vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED );
00256                 return -EINVAL;
00257         }
00258         vpm_set_features ( &virtnet->vdev, features & (
00259                 ( 1ULL << VIRTIO_NET_F_MAC ) |
00260                 ( 1ULL << VIRTIO_NET_F_MTU ) |
00261                 ( 1ULL << VIRTIO_F_VERSION_1 ) |
00262                 ( 1ULL << VIRTIO_F_ANY_LAYOUT ) |
00263                 ( 1ULL << VIRTIO_F_IOMMU_PLATFORM ) ) );
00264         vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FEATURES_OK );
00265 
00266         status = vpm_get_status ( &virtnet->vdev );
00267         if ( ! ( status & VIRTIO_CONFIG_S_FEATURES_OK ) ) {
00268                 DBGC ( virtnet, "VIRTIO-NET %p device didn't accept features\n",
00269                        virtnet );
00270                 vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED );
00271                 return -EINVAL;
00272         }
00273 
00274         /* Allocate virtqueues */
00275         virtnet->virtqueue = zalloc ( QUEUE_NB *
00276                                       sizeof ( *virtnet->virtqueue ) );
00277         if ( ! virtnet->virtqueue ) {
00278                 vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED );
00279                 return -ENOMEM;
00280         }
00281 
00282         /* Initialize rx/tx virtqueues */
00283         if ( vpm_find_vqs ( &virtnet->vdev, QUEUE_NB, virtnet->virtqueue ) ) {
00284                 DBGC ( virtnet, "VIRTIO-NET %p cannot register queues\n",
00285                        virtnet );
00286                 virtnet_free_virtqueues ( netdev );
00287                 vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED );
00288                 return -ENOENT;
00289         }
00290 
00291         /* Disable interrupts before starting */
00292         netdev_irq ( netdev, 0 );
00293 
00294         vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER_OK );
00295 
00296         /* Initialize rx packets */
00297         INIT_LIST_HEAD ( &virtnet->rx_iobufs );
00298         virtnet->rx_num_iobufs = 0;
00299         virtnet_refill_rx_virtqueue ( netdev );
00300         return 0;
00301 }
00302 
00303 /** Open network device
00304  *
00305  * @v netdev    Network device
00306  * @ret rc      Return status code
00307  */
00308 static int virtnet_open ( struct net_device *netdev ) {
00309         struct virtnet_nic *virtnet = netdev->priv;
00310 
00311         if ( virtnet->virtio_version ) {
00312                 return virtnet_open_modern ( netdev );
00313         } else {
00314                 return virtnet_open_legacy ( netdev );
00315         }
00316 }
00317 
00318 /** Close network device
00319  *
00320  * @v netdev    Network device
00321  */
00322 static void virtnet_close ( struct net_device *netdev ) {
00323         struct virtnet_nic *virtnet = netdev->priv;
00324         struct io_buffer *iobuf;
00325         struct io_buffer *next_iobuf;
00326 
00327         if ( virtnet->virtio_version ) {
00328                 vpm_reset ( &virtnet->vdev );
00329         } else {
00330                 vp_reset ( virtnet->ioaddr );
00331         }
00332 
00333         /* Virtqueues can be freed now that NIC is reset */
00334         virtnet_free_virtqueues ( netdev );
00335 
00336         /* Free rx iobufs */
00337         list_for_each_entry_safe ( iobuf, next_iobuf, &virtnet->rx_iobufs, list ) {
00338                 free_iob ( iobuf );
00339         }
00340         INIT_LIST_HEAD ( &virtnet->rx_iobufs );
00341         virtnet->rx_num_iobufs = 0;
00342 }
00343 
00344 /** Transmit packet
00345  *
00346  * @v netdev    Network device
00347  * @v iobuf     I/O buffer
00348  * @ret rc      Return status code
00349  */
00350 static int virtnet_transmit ( struct net_device *netdev,
00351                               struct io_buffer *iobuf ) {
00352         virtnet_enqueue_iob ( netdev, TX_INDEX, iobuf );
00353         return 0;
00354 }
00355 
00356 /** Complete packet transmission
00357  *
00358  * @v netdev    Network device
00359  */
00360 static void virtnet_process_tx_packets ( struct net_device *netdev ) {
00361         struct virtnet_nic *virtnet = netdev->priv;
00362         struct vring_virtqueue *tx_vq = &virtnet->virtqueue[TX_INDEX];
00363 
00364         while ( vring_more_used ( tx_vq ) ) {
00365                 struct io_buffer *iobuf = vring_get_buf ( tx_vq, NULL );
00366 
00367                 DBGC2 ( virtnet, "VIRTIO-NET %p tx complete iobuf %p\n",
00368                         virtnet, iobuf );
00369 
00370                 netdev_tx_complete ( netdev, iobuf );
00371         }
00372 }
00373 
00374 /** Complete packet reception
00375  *
00376  * @v netdev    Network device
00377  */
00378 static void virtnet_process_rx_packets ( struct net_device *netdev ) {
00379         struct virtnet_nic *virtnet = netdev->priv;
00380         struct vring_virtqueue *rx_vq = &virtnet->virtqueue[RX_INDEX];
00381 
00382         while ( vring_more_used ( rx_vq ) ) {
00383                 unsigned int len;
00384                 struct io_buffer *iobuf = vring_get_buf ( rx_vq, &len );
00385 
00386                 /* Release ownership of iobuf */
00387                 list_del ( &iobuf->list );
00388                 virtnet->rx_num_iobufs--;
00389 
00390                 /* Update iobuf length */
00391                 iob_unput ( iobuf, iob_len ( iobuf ) );
00392                 iob_put ( iobuf, len - sizeof ( struct virtio_net_hdr ) );
00393 
00394                 DBGC2 ( virtnet, "VIRTIO-NET %p rx complete iobuf %p len %zd\n",
00395                         virtnet, iobuf, iob_len ( iobuf ) );
00396 
00397                 /* Pass completed packet to the network stack */
00398                 netdev_rx ( netdev, iobuf );
00399         }
00400 
00401         virtnet_refill_rx_virtqueue ( netdev );
00402 }
00403 
00404 /** Poll for completed and received packets
00405  *
00406  * @v netdev    Network device
00407  */
00408 static void virtnet_poll ( struct net_device *netdev ) {
00409         struct virtnet_nic *virtnet = netdev->priv;
00410 
00411         /* Acknowledge interrupt.  This is necessary for UNDI operation and
00412          * interrupts that are raised despite VRING_AVAIL_F_NO_INTERRUPT being
00413          * set (that flag is just a hint and the hypervisor does not have to
00414          * honor it).
00415          */
00416         if ( virtnet->virtio_version ) {
00417                 vpm_get_isr ( &virtnet->vdev );
00418         } else {
00419                 vp_get_isr ( virtnet->ioaddr );
00420         }
00421 
00422         virtnet_process_tx_packets ( netdev );
00423         virtnet_process_rx_packets ( netdev );
00424 }
00425 
00426 /** Enable or disable interrupts
00427  *
00428  * @v netdev    Network device
00429  * @v enable    Interrupts should be enabled
00430  */
00431 static void virtnet_irq ( struct net_device *netdev, int enable ) {
00432         struct virtnet_nic *virtnet = netdev->priv;
00433         int i;
00434 
00435         for ( i = 0; i < QUEUE_NB; i++ ) {
00436                 if ( enable )
00437                         vring_enable_cb ( &virtnet->virtqueue[i] );
00438                 else
00439                         vring_disable_cb ( &virtnet->virtqueue[i] );
00440         }
00441 }
00442 
00443 /** virtio-net device operations */
00444 static struct net_device_operations virtnet_operations = {
00445         .open = virtnet_open,
00446         .close = virtnet_close,
00447         .transmit = virtnet_transmit,
00448         .poll = virtnet_poll,
00449         .irq = virtnet_irq,
00450 };
00451 
00452 /**
00453  * Probe PCI device, legacy virtio 0.9.5
00454  *
00455  * @v pci       PCI device
00456  * @ret rc      Return status code
00457  */
00458 static int virtnet_probe_legacy ( struct pci_device *pci ) {
00459         unsigned long ioaddr = pci->ioaddr;
00460         struct net_device *netdev;
00461         struct virtnet_nic *virtnet;
00462         u32 features;
00463         u16 mtu;
00464         int rc;
00465 
00466         /* Allocate and hook up net device */
00467         netdev = alloc_etherdev ( sizeof ( *virtnet ) );
00468         if ( ! netdev )
00469                 return -ENOMEM;
00470         netdev_init ( netdev, &virtnet_operations );
00471         virtnet = netdev->priv;
00472         virtnet->ioaddr = ioaddr;
00473         pci_set_drvdata ( pci, netdev );
00474         netdev->dev = &pci->dev;
00475 
00476         DBGC ( virtnet, "VIRTIO-NET %p busaddr=%s ioaddr=%#lx irq=%d\n",
00477                virtnet, pci->dev.name, ioaddr, pci->irq );
00478 
00479         /* Enable PCI bus master and reset NIC */
00480         adjust_pci_device ( pci );
00481         vp_reset ( ioaddr );
00482 
00483         /* Load MAC address and MTU */
00484         features = vp_get_features ( ioaddr );
00485         if ( features & ( 1 << VIRTIO_NET_F_MAC ) ) {
00486                 vp_get ( ioaddr, offsetof ( struct virtio_net_config, mac ),
00487                          netdev->hw_addr, ETH_ALEN );
00488                 DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
00489                        eth_ntoa ( netdev->hw_addr ) );
00490         }
00491         if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
00492                 vp_get ( ioaddr, offsetof ( struct virtio_net_config, mtu ),
00493                          &mtu, sizeof ( mtu ) );
00494                 DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet, mtu );
00495                 netdev->max_pkt_len = ( mtu + ETH_HLEN );
00496         }
00497 
00498         /* Register network device */
00499         if ( ( rc = register_netdev ( netdev ) ) != 0 )
00500                 goto err_register_netdev;
00501 
00502         /* Mark link as up, control virtqueue is not used */
00503         netdev_link_up ( netdev );
00504 
00505         return 0;
00506 
00507         unregister_netdev ( netdev );
00508  err_register_netdev:
00509         vp_reset ( ioaddr );
00510         netdev_nullify ( netdev );
00511         netdev_put ( netdev );
00512         return rc;
00513 }
00514 
00515 /**
00516  * Probe PCI device, modern virtio 1.0
00517  *
00518  * @v pci       PCI device
00519  * @v found_dev Set to non-zero if modern device was found (probe may still fail)
00520  * @ret rc      Return status code
00521  */
00522 static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) {
00523         struct net_device *netdev;
00524         struct virtnet_nic *virtnet;
00525         u64 features;
00526         u16 mtu;
00527         int rc, common, isr, notify, config, device;
00528 
00529         common = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_COMMON_CFG );
00530         if ( ! common ) {
00531                 DBG ( "Common virtio capability not found!\n" );
00532                 return -ENODEV;
00533         }
00534         *found_dev = 1;
00535 
00536         isr = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_ISR_CFG );
00537         notify = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_NOTIFY_CFG );
00538         config = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_PCI_CFG );
00539         if ( ! isr || ! notify || ! config ) {
00540                 DBG ( "Missing virtio capabilities %i/%i/%i/%i\n",
00541                       common, isr, notify, config );
00542                 return -EINVAL;
00543         }
00544         device = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_DEVICE_CFG );
00545 
00546         /* Allocate and hook up net device */
00547         netdev = alloc_etherdev ( sizeof ( *virtnet ) );
00548         if ( ! netdev )
00549                 return -ENOMEM;
00550         netdev_init ( netdev, &virtnet_operations );
00551         virtnet = netdev->priv;
00552 
00553         pci_set_drvdata ( pci, netdev );
00554         netdev->dev = &pci->dev;
00555 
00556         DBGC ( virtnet, "VIRTIO-NET modern %p busaddr=%s irq=%d\n",
00557                virtnet, pci->dev.name, pci->irq );
00558 
00559         virtnet->vdev.pci = pci;
00560         rc = virtio_pci_map_capability ( pci, common,
00561                 sizeof ( struct virtio_pci_common_cfg ), 4,
00562                 0, sizeof ( struct virtio_pci_common_cfg ),
00563                 &virtnet->vdev.common );
00564         if ( rc )
00565                 goto err_map_common;
00566 
00567         rc = virtio_pci_map_capability ( pci, isr, sizeof ( u8 ), 1,
00568                 0, 1,
00569                 &virtnet->vdev.isr );
00570         if ( rc )
00571                 goto err_map_isr;
00572 
00573         virtnet->vdev.notify_cap_pos = notify;
00574         virtnet->vdev.cfg_cap_pos = config;
00575 
00576         /* Map the device capability */
00577         if ( device ) {
00578                 rc = virtio_pci_map_capability ( pci, device,
00579                         0, 4, 0, sizeof ( struct virtio_net_config ),
00580                         &virtnet->vdev.device );
00581                 if ( rc )
00582                         goto err_map_device;
00583         }
00584 
00585         /* Enable the PCI device */
00586         adjust_pci_device ( pci );
00587 
00588         /* Reset the device and set initial status bits */
00589         vpm_reset ( &virtnet->vdev );
00590         vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE );
00591         vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER );
00592 
00593         /* Load MAC address and MTU */
00594         if ( device ) {
00595                 features = vpm_get_features ( &virtnet->vdev );
00596                 if ( features & ( 1ULL << VIRTIO_NET_F_MAC ) ) {
00597                         vpm_get ( &virtnet->vdev,
00598                                   offsetof ( struct virtio_net_config, mac ),
00599                                   netdev->hw_addr, ETH_ALEN );
00600                         DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
00601                                eth_ntoa ( netdev->hw_addr ) );
00602                 }
00603                 if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
00604                         vpm_get ( &virtnet->vdev,
00605                                   offsetof ( struct virtio_net_config, mtu ),
00606                                   &mtu, sizeof ( mtu ) );
00607                         DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet,
00608                                mtu );
00609                         netdev->max_pkt_len = ( mtu + ETH_HLEN );
00610                 }
00611         }
00612 
00613         /* We need a valid MAC address */
00614         if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) {
00615                 rc = -EADDRNOTAVAIL;
00616                 goto err_mac_address;
00617         }
00618 
00619         /* Register network device */
00620         if ( ( rc = register_netdev ( netdev ) ) != 0 )
00621                 goto err_register_netdev;
00622 
00623         /* Mark link as up, control virtqueue is not used */
00624         netdev_link_up ( netdev );
00625 
00626         virtnet->virtio_version = 1;
00627         return 0;
00628 
00629         unregister_netdev ( netdev );
00630 err_register_netdev:
00631 err_mac_address:
00632         vpm_reset ( &virtnet->vdev );
00633         netdev_nullify ( netdev );
00634         netdev_put ( netdev );
00635 
00636         virtio_pci_unmap_capability ( &virtnet->vdev.device );
00637 err_map_device:
00638         virtio_pci_unmap_capability ( &virtnet->vdev.isr );
00639 err_map_isr:
00640         virtio_pci_unmap_capability ( &virtnet->vdev.common );
00641 err_map_common:
00642         return rc;
00643 }
00644 
00645 /**
00646  * Probe PCI device
00647  *
00648  * @v pci       PCI device
00649  * @ret rc      Return status code
00650  */
00651 static int virtnet_probe ( struct pci_device *pci ) {
00652         int found_modern = 0;
00653         int rc = virtnet_probe_modern ( pci, &found_modern );
00654         if ( ! found_modern && pci->device < 0x1040 ) {
00655                 /* fall back to the legacy probe */
00656                 rc = virtnet_probe_legacy ( pci );
00657         }
00658         return rc;
00659 }
00660 
00661 /**
00662  * Remove device
00663  *
00664  * @v pci       PCI device
00665  */
00666 static void virtnet_remove ( struct pci_device *pci ) {
00667         struct net_device *netdev = pci_get_drvdata ( pci );
00668         struct virtnet_nic *virtnet = netdev->priv;
00669 
00670         virtio_pci_unmap_capability ( &virtnet->vdev.device );
00671         virtio_pci_unmap_capability ( &virtnet->vdev.isr );
00672         virtio_pci_unmap_capability ( &virtnet->vdev.common );
00673 
00674         unregister_netdev ( netdev );
00675         netdev_nullify ( netdev );
00676         netdev_put ( netdev );
00677 }
00678 
00679 static struct pci_device_id virtnet_nics[] = {
00680 PCI_ROM(0x1af4, 0x1000, "virtio-net", "Virtio Network Interface", 0),
00681 PCI_ROM(0x1af4, 0x1041, "virtio-net", "Virtio Network Interface 1.0", 0),
00682 };
00683 
00684 struct pci_driver virtnet_driver __pci_driver = {
00685         .ids = virtnet_nics,
00686         .id_count = ( sizeof ( virtnet_nics ) / sizeof ( virtnet_nics[0] ) ),
00687         .probe = virtnet_probe,
00688         .remove = virtnet_remove,
00689 };