Index: uspace/drv/nic/virtio-net/virtio-net.c
===================================================================
--- uspace/drv/nic/virtio-net/virtio-net.c	(revision f175d221bec6983bcf290d98513c54aeef80b0a4)
+++ uspace/drv/nic/virtio-net/virtio-net.c	(revision 1c4035149053328f2f3e0e47a7a5bd837fe8b0eb)
@@ -27,4 +27,6 @@
  */
 
+#include "virtio-net.h"
+
 #include <stdio.h>
 #include <stdint.h>
@@ -41,4 +43,86 @@
 #define NAME	"virtio-net"
 
+static errno_t virtio_net_initialize(ddf_dev_t *dev)
+{
+	nic_t *nic_data = nic_create_and_bind(dev);
+	if (!nic_data)
+		return ENOMEM;
+
+	virtio_net_t *virtio_net = calloc(1, sizeof(virtio_net_t));
+	if (!virtio_net) {
+		nic_unbind_and_destroy(dev);
+		return ENOMEM;
+	}
+
+	nic_set_specific(nic_data, virtio_net);
+
+	errno_t rc = virtio_pci_dev_initialize(dev, &virtio_net->virtio_dev);
+	if (rc != EOK)
+		return rc;
+
+	virtio_pci_common_cfg_t *cfg = virtio_net->virtio_dev.common_cfg;
+	virtio_net_cfg_t *netcfg = virtio_net->virtio_dev.device_cfg;
+
+	/*
+	 * Perform device initialization as described in section 3.1.1 of the
+	 * specification.
+	 */
+
+	/* 1. Reset the device */
+	pio_write_8(&cfg->device_status, VIRTIO_DEV_STATUS_RESET);
+
+	/* 2. Acknowledge we found the device */
+	pio_write_8(&cfg->device_status, VIRTIO_DEV_STATUS_ACKNOWLEDGE);
+
+	/* 3. We know how to drive the device */
+	pio_write_8(&cfg->device_status, VIRTIO_DEV_STATUS_DRIVER);
+
+	/* 4. Read the offered feature flags */
+	pio_write_32(&cfg->device_feature_select, VIRTIO_NET_F_SELECT_PAGE_0);
+	uint32_t features = pio_read_32(&cfg->device_feature);
+
+	ddf_msg(LVL_NOTE, "offered features %x", features);
+	features &= (1U << VIRTIO_NET_F_MAC);
+
+	if (!features) {
+		pio_write_8(&cfg->device_status, VIRTIO_DEV_STATUS_FAILED);
+		return ENOTSUP;
+	}
+
+	/* 4. Write the accepted feature flags */
+	pio_write_32(&cfg->driver_feature_select, VIRTIO_NET_F_SELECT_PAGE_0);
+	pio_write_32(&cfg->driver_feature, features);
+
+	/* 5. Set FEATURES_OK */
+	pio_write_8(&cfg->device_status, VIRTIO_DEV_STATUS_FEATURES_OK);
+
+	/* 6. Test if the device supports our feature subset */ 
+	uint8_t status = pio_read_8(&cfg->device_status);
+	if (!(status & VIRTIO_DEV_STATUS_FEATURES_OK)) {
+		pio_write_8(&cfg->device_status, VIRTIO_DEV_STATUS_FAILED);
+		return ENOTSUP;
+	}
+
+	/* 7. Perform device-specific setup */
+	nic_address_t nic_addr;
+	for (unsigned i = 0; i < 6; i++)
+		nic_addr.address[i] = netcfg->mac[i];
+	rc = nic_report_address(nic_data, &nic_addr);
+	if (rc != EOK) {
+		pio_write_8(&cfg->device_status, VIRTIO_DEV_STATUS_FAILED);
+		return rc;
+	}
+
+	ddf_msg(LVL_NOTE, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x",
+	    nic_addr.address[0], nic_addr.address[1],
+	    nic_addr.address[2], nic_addr.address[3],
+	    nic_addr.address[4], nic_addr.address[5]);
+
+	/* 8. Go live */
+	pio_write_8(&cfg->device_status, VIRTIO_DEV_STATUS_DRIVER_OK);
+
+	return EOK;
+}
+
 static errno_t virtio_net_dev_add(ddf_dev_t *dev)
 {
@@ -46,7 +130,5 @@
 	    ddf_dev_get_name(dev), ddf_dev_get_handle(dev));
 
-	// XXX: this will be part of the nic data
-	virtio_dev_t virtio_dev;
-	errno_t rc = virtio_pci_dev_initialize(dev, &virtio_dev);
+	errno_t rc = virtio_net_initialize(dev);
 	if (rc != EOK)
 		return rc;
