From 1c4035149053328f2f3e0e47a7a5bd837fe8b0eb Mon Sep 17 00:00:00 2001 From: Jakub Jermar Date: Mon, 23 Apr 2018 23:00:57 +0200 Subject: [PATCH] Start initializing the virtio-net device --- uspace/drv/nic/virtio-net/virtio-net.c | 88 ++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/uspace/drv/nic/virtio-net/virtio-net.c b/uspace/drv/nic/virtio-net/virtio-net.c index 04519acae..7dc9b6766 100644 --- a/uspace/drv/nic/virtio-net/virtio-net.c +++ b/uspace/drv/nic/virtio-net/virtio-net.c @@ -26,6 +26,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "virtio-net.h" + #include #include @@ -40,14 +42,94 @@ #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) { ddf_msg(LVL_NOTE, "%s %s (handle = %zu)", __func__, 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; -- 2.11.4.GIT