status_t virtio_gpu_init(struct virtio_device *dev, uint32_t host_features) { LTRACEF("dev %p, host_features 0x%x\n", dev, host_features); /* allocate a new gpu device */ struct virtio_gpu_dev *gdev = malloc(sizeof(struct virtio_gpu_dev)); if (!gdev) return ERR_NO_MEMORY; mutex_init(&gdev->lock); event_init(&gdev->io_event, false, EVENT_FLAG_AUTOUNSIGNAL); event_init(&gdev->flush_event, false, EVENT_FLAG_AUTOUNSIGNAL); gdev->dev = dev; dev->priv = gdev; gdev->pmode_id = -1; gdev->next_resource_id = 1; /* allocate memory for a gpu request */ #if WITH_KERNEL_VM gdev->gpu_request = pmm_alloc_kpage(); gdev->gpu_request_phys = vaddr_to_paddr(gdev->gpu_request); #else gdev->gpu_request = malloc(sizeof(struct virtio_gpu_resp_display_info)); // XXX get size better gdev->gpu_request_phys = (paddr_t)gdev->gpu_request; #endif /* make sure the device is reset */ virtio_reset_device(dev); volatile struct virtio_gpu_config *config = (struct virtio_gpu_config *)dev->config_ptr; dump_gpu_config(config); /* ack and set the driver status bit */ virtio_status_acknowledge_driver(dev); // XXX check features bits and ack/nak them /* allocate a virtio ring */ virtio_alloc_ring(dev, 0, 16); /* set our irq handler */ dev->irq_driver_callback = &virtio_gpu_irq_driver_callback; dev->config_change_callback = &virtio_gpu_config_change_callback; /* set DRIVER_OK */ virtio_status_driver_ok(dev); /* save the main device we've found */ the_gdev = gdev; printf("found virtio gpu device\n"); return NO_ERROR; }
status_t virtio_block_init(struct virtio_device *dev, uint32_t host_features) { LTRACEF("dev %p, host_features 0x%x\n", dev, host_features); /* allocate a new block device */ struct virtio_block_dev *bdev = malloc(sizeof(struct virtio_block_dev)); if (!bdev) return ERR_NO_MEMORY; mutex_init(&bdev->lock); event_init(&bdev->io_event, false, EVENT_FLAG_AUTOUNSIGNAL); bdev->dev = dev; dev->priv = bdev; bdev->blk_req = memalign(sizeof(struct virtio_blk_req), sizeof(struct virtio_blk_req)); #if WITH_KERNEL_VM arch_mmu_query((vaddr_t)bdev->blk_req, &bdev->blk_req_phys, NULL); #else bdev->blk_freq_phys = (uint64_t)(uintptr_t)bdev->blk_req; #endif LTRACEF("blk_req structure at %p (0x%lx phys)\n", bdev->blk_req, bdev->blk_req_phys); #if WITH_KERNEL_VM arch_mmu_query((vaddr_t)&bdev->blk_response, &bdev->blk_response_phys, NULL); #else bdev->blk_response_phys = (uint64_t)(uintptr_t)&bdev->blk_response; #endif /* make sure the device is reset */ virtio_reset_device(dev); volatile struct virtio_blk_config *config = (struct virtio_blk_config *)dev->config_ptr; LTRACEF("capacity 0x%llx\n", config->capacity); LTRACEF("size_max 0x%x\n", config->size_max); LTRACEF("seg_max 0x%x\n", config->seg_max); LTRACEF("blk_size 0x%x\n", config->blk_size); /* ack and set the driver status bit */ virtio_status_acknowledge_driver(dev); // XXX check features bits and ack/nak them /* allocate a virtio ring */ virtio_alloc_ring(dev, 0, 256); /* set our irq handler */ dev->irq_driver_callback = &virtio_block_irq_driver_callback; /* set DRIVER_OK */ virtio_status_driver_ok(dev); /* construct the block device */ static uint8_t found_index = 0; char buf[16]; snprintf(buf, sizeof(buf), "virtio%u", found_index++); bio_initialize_bdev(&bdev->bdev, buf, config->blk_size, config->capacity, 0, NULL); /* override our block device hooks */ bdev->bdev.read_block = &virtio_bdev_read_block; bdev->bdev.write_block = &virtio_bdev_write_block; bio_register_device(&bdev->bdev); printf("found virtio block device of size %lld\n", config->capacity * config->blk_size); return NO_ERROR; }