Пример #1
0
status_t bio_publish_subdevice(const char *parent_dev, const char *subdev, bnum_t startblock, size_t len)
{
	LTRACEF("parent %s, sub %s, startblock %u, len %zd\n", parent_dev, subdev, startblock, len);

	bdev_t *parent = bio_open(parent_dev);
	if (!parent)
		return -1;

	/* make sure we're able to do this */
	if (startblock + len > parent->block_count)
		return -1;

	subdev_t *sub = malloc(sizeof(subdev_t));
	bio_initialize_bdev(&sub->dev, subdev, parent->block_size, len);

	sub->parent = parent;
	sub->offset = startblock;

	sub->dev.read = &subdev_read;
	sub->dev.read_block = &subdev_read_block;
	sub->dev.write = &subdev_write;
	sub->dev.write_block = &subdev_write_block;
	sub->dev.erase = &subdev_erase;
	sub->dev.close = &subdev_close;

	bio_register_device(&sub->dev);

	return 0;
}
Пример #2
0
Файл: flash.c Проект: cpizano/lk
void stm32_flash_init(void)
{
    // XXX detect here
    flash.size = 1024*1024;

    flash.geometry[0].start = ERASE_RANGE0_START;
    flash.geometry[0].size = ERASE_RANGE0_END - ERASE_RANGE0_START;
    flash.geometry[0].erase_size = _32K;
    flash.geometry[0].erase_size = log2_uint(_32K);

    flash.geometry[1].start = ERASE_RANGE1_START;
    flash.geometry[1].size = ERASE_RANGE1_END - ERASE_RANGE1_START;
    flash.geometry[1].erase_size = _128K;
    flash.geometry[1].erase_size = log2_uint(_128K);

    flash.geometry[2].start = ERASE_RANGE2_START;
    flash.geometry[2].size = ERASE_RANGE2_END - ERASE_RANGE2_START;
    flash.geometry[2].erase_size = _256K;
    flash.geometry[2].erase_size = log2_uint(_256K);

    /* construct the block device */
    bio_initialize_bdev(&flash.bdev, "flash0",
                        PROGRAM_SIZE, flash.size / PROGRAM_SIZE,
                        3, flash.geometry);

    /* override our block device hooks */
    flash.bdev.read = &stm32_flash_bdev_read;
    flash.bdev.read_block = &stm32_flash_bdev_read_block;
    //flash.bdev.write = &stm32_flash_bdev_write;
    flash.bdev.write_block = &stm32_flash_bdev_write_block;
    flash.bdev.erase = &stm32_flash_bdev_erase;
    flash.bdev.ioctl = &stm32_flash_ioctl;

    bio_register_device(&flash.bdev);
}
Пример #3
0
bdev_t* create_membdev(const char *name, void *ptr, size_t len, bool publish)
{
	mem_bdev_t *mem = malloc(sizeof(mem_bdev_t));

	/* set up the base device */
	bio_initialize_bdev(&mem->dev, name, BLOCKSIZE, len / BLOCKSIZE);

	/* our bits */
	mem->ptr = ptr;
	mem->dev.read = mem_bdev_read;
	mem->dev.read_block = mem_bdev_read_block;
	mem->dev.write = mem_bdev_write;
	mem->dev.write_block = mem_bdev_write_block;

	/* register it */
	if(publish)
		bio_register_device(&mem->dev);
	else mem->dev.ref = 1;

	return &mem->dev;
}
Пример #4
0
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;
}
Пример #5
0
status_t bio_publish_subdevice(const char *parent_dev,
							   const char *subdev,
							   bnum_t startblock,
							   bnum_t block_count)
{
	status_t err = NO_ERROR;
	bdev_t *parent = NULL;
	subdev_t *sub = NULL;
	size_t geometry_count;
	bio_erase_geometry_info_t* geometry;

	LTRACEF("parent \"%s\", sub \"%s\", startblock %u, count %u\n", parent_dev, subdev, startblock, block_count);

	// Make sure our parent exists
	parent = bio_open(parent_dev);
	if (!parent) {
		LTRACEF("Failed to find parent \"%s\"\n", parent_dev);
		BAIL(ERR_NOT_FOUND);
	}

	// Allocate our sub-device.
	sub = malloc(sizeof(subdev_t));
	if (!sub) {
		LTRACEF("Failed to allocate subdevice\n");
		BAIL(ERR_NO_MEMORY);
	}

	/* Make sure we're able to do this.  If the device has a specified erase
	 * geometry, the specified sub-region must exist entirely with one of our
	 * parent's erase regions, and be aligned to an erase unit boundary.
	 * Otherwise, the specified region must simply exist within the block range
	 * of the device.
	 */
	if (parent->geometry_count && parent->geometry) {
		uint64_t byte_start = ((uint64_t)startblock  << parent->block_shift);
		uint64_t byte_size  = ((uint64_t)block_count << parent->block_shift);
		const bio_erase_geometry_info_t* geo = NULL;

		LTRACEF("Searching geometry for region which contains @[0x%llx, 0x%llx)\n",
				byte_start, byte_start + byte_size);

		// Start by finding the erase region which completely contains the requested range.
		for (size_t i = 0; i < parent->geometry_count; ++i) {
			geo = parent->geometry + i;

			LTRACEF("Checking geometry @[0x%llx, 0x%llx) erase size 0x%zx\n",
					geo->start,
					geo->start + geo->size,
					geo->erase_size);

			if (bio_contains_range(geo->start, geo->size, byte_start, byte_size))
				break;
		}

		if (!geo) {
			LTRACEF("No suitable erase region found\n");
			BAIL(ERR_INVALID_ARGS);
		}

		// Now check out alignment.
		uint64_t erase_mask = ((uint64_t)0x1 << geo->erase_shift) - 1;
		if ((byte_start & erase_mask) || (byte_size & erase_mask)) {
			LTRACEF("Requested region has improper alignment/length\n");
			BAIL(ERR_INVALID_ARGS);
		}

		geometry_count = 1;
		geometry = &sub->geometry;

		geometry->start       = 0;
		geometry->size        = byte_size;
		geometry->erase_size  = geo->erase_size;
		geometry->erase_shift = geo->erase_shift;
	} else {
		bnum_t endblock = startblock + block_count;

		if ((endblock < startblock) || (endblock > parent->block_count))
			BAIL(ERR_INVALID_ARGS);

		geometry_count = 0;
		geometry = NULL;
	}

	bio_initialize_bdev(&sub->dev, subdev,
						parent->block_size, block_count,
						geometry_count, geometry);

	sub->parent = parent;
	sub->offset = startblock;

	sub->dev.read = &subdev_read;
	sub->dev.read_block = &subdev_read_block;
	sub->dev.write = &subdev_write;
	sub->dev.write_block = &subdev_write_block;
	sub->dev.erase = &subdev_erase;
	sub->dev.close = &subdev_close;

	bio_register_device(&sub->dev);

bailout:
	if (err < 0) {
		if (NULL != parent)
			bio_close(parent);
		free(sub);
	}

	return err;
}