/** * The structure define the virtio driver. * 主要是关于函数绑定 */ structvirtio_driver { /** Next entry of the driver list */ UK_TAILQ_ENTRY(struct virtio_driver) next; /** The id map for the virtio device */ conststructvirtio_dev_id *dev_ids; /** The init function for the driver */ virtio_driver_init_func_t init; /** Adding the virtio device */ virtio_driver_add_func_t add_dev; };
/** * The structure defines the virtio device. * 定义device相关操作以及virtqueue */ structvirtio_dev { /* Feature bit describing the virtio device */ __u64 features; /* List of the virtqueue for the device */ UK_TAILQ_HEAD(virtqueue_head, struct virtqueue) vqs; /* Private data of the driver */ void *priv; /* Virtio device identifier */ structvirtio_dev_idid; /* List of the config operations */ structvirtio_config_ops *cops; /* Reference to the virtio driver for the device */ structvirtio_driver *vdrv; /* Status of the device */ enumvirtio_dev_statusstatus; };
后面涉及的都是driver和dev相关的setter和getter函数,不展开了
virtio_bus.c
在这里需要先补充virtio_config对driver定义的相关宏
1 2 3 4 5 6
#define VIRTIO_CONFIG_STATUS_RESET 0x0 /* Reset the device */ #define VIRTIO_CONFIG_STATUS_ACK 0x1 /* recognize device as virtio */ #define VIRTIO_CONFIG_STATUS_DRIVER 0x2 /* driver for the device found*/ #define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x4 /* initialization is complete */ #define VIRTIO_CONFIG_STATUS_NEEDS_RESET 0x40 /* device needs reset */ #define VIRTIO_CONFIG_STATUS_FAIL 0x80 /* device something's wrong*/
/** * Find a match driver * @param vdev * Reference to the virtio device. */ staticstruct virtio_driver *find_match_drv(struct virtio_dev *vdev) { int i = 0; structvirtio_driver *drv =NULL;
UK_TAILQ_FOREACH(drv, &virtio_drvs, next) { i = 0; while (drv->dev_ids[i].virtio_device_id != VIRTIO_ID_INVALID) { if (virtio_device_id_match(&drv->dev_ids[i], &vdev->id)) { // id一致 就是dev要的driver return drv; } i++; } } returnNULL; }
UK_ASSERT(vdev); /* Check for the dev with the driver list */ drv = find_match_drv(vdev); if (!drv) { uk_pr_err("Failed to find the driver for the virtio device %p (id:%"__PRIu16")\n", vdev, vdev->id.virtio_device_id); return -EFAULT; } vdev->vdrv = drv;
/* Initialize the device */ rc = virtio_device_reinit(vdev); if (rc != 0) { uk_pr_err("Failed to initialize the virtio device %p (id:%"__PRIu16": %d\n", vdev, vdev->id.virtio_device_id, rc); return rc; }
/* Initialize the virtqueue list */ UK_TAILQ_INIT(&vdev->vqs);
/* Calling the driver add device */ rc = drv->add_dev(vdev); if (rc != 0) { uk_pr_err("Failed to add the virtio device %p: %d\n", vdev, rc); goto virtio_dev_fail_set; } exit: return rc;
virtio_dev_fail_set: /** * We set the status to fail. We can ignore the exit status from the * status update. */ virtio_dev_status_update(vdev, VIRTIO_CONFIG_STATUS_FAIL); gotoexit; }
/** * Reinitialize the virtio device * @param vdev * Reference to the virtio device. */ staticintvirtio_device_reinit(struct virtio_dev *vdev) { int rc = 0;
/** * Resetting the virtio device * This may not be necessary while initializing the device for the first * time. */ if (vdev->cops->device_reset) { vdev->cops->device_reset(vdev); /* Set the device status */ vdev->status = VIRTIO_DEV_RESET; } /* Acknowledge the virtio device */ rc = virtio_dev_status_update(vdev, VIRTIO_CONFIG_STATUS_ACK); if (rc != 0) { uk_pr_err("Failed to acknowledge the virtio device %p: %d\n", vdev, rc); return rc; }
/* Acknowledge the virtio driver */ rc = virtio_dev_status_update(vdev, VIRTIO_CONFIG_STATUS_DRIVER); if (rc != 0) { uk_pr_err("Failed to acknowledge the virtio driver %p: %d\n", vdev, rc); return rc; } vdev->status = VIRTIO_DEV_INITIALIZED; uk_pr_info("Virtio device %p initialized\n", vdev); return rc; }
/** * Probe for the virtio device. */ staticintvirtio_bus_probe(void) { return0; }
/** * Initialize the virtio bus driver(s). * @param mem_alloc * Reference to the mem_allocator. * @return * (int) On successful initialization return the count of device * initialized. * On error return -1. */ /** * Initialize the virtio bus driver(s). * @param mem_alloc * Reference to the mem_allocator. * @return * (int) On successful initialization return the count of device * initialized. * On error return -1. */ staticintvirtio_bus_init(struct uk_alloc *mem_alloc) { structvirtio_driver *drv =NULL, *ndrv = NULL; int ret = 0, dev_count = 0;
a = mem_alloc; UK_TAILQ_FOREACH_SAFE(drv, &virtio_drvs, next, ndrv) { if (drv->init) { ret = drv->init(a); if (unlikely(ret)) { uk_pr_err("Failed to initialize virtio driver %p: %d\n", drv, ret); UK_TAILQ_REMOVE(&virtio_drvs, drv, next); } else dev_count++; } } return (dev_count > 0) ? dev_count : 0; }
/** * Register the virtio driver(s). * @param vdrv * Reference to the virtio_driver */ void _virtio_bus_register_driver(struct virtio_driver *vdrv) { UK_TAILQ_INSERT_TAIL(&virtio_drvs, vdrv, next); }