Beispiel #1
0
int blocklevel_get_info(struct blocklevel_device *bl, const char **name, uint64_t *total_size,
		uint32_t *erase_granule)
{
	int rc;

	if (!bl || !bl->get_info) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	rc = reacquire(bl);
	if (rc)
		return rc;

	rc = bl->get_info(bl, name, total_size, erase_granule);

	/* Check the validity of what we are being told */
	if (erase_granule && *erase_granule != bl->erase_mask + 1)
		FL_ERR("blocklevel_get_info: WARNING: erase_granule (0x%08x) and erase_mask"
				" (0x%08x) don't match\n", *erase_granule, bl->erase_mask + 1);

	release(bl);

	return rc;
}
Beispiel #2
0
int blocklevel_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
{
	int rc;
	if (!bl || !bl->erase) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	FL_DBG("%s: 0x%" PRIx64 "\t0x%" PRIx64 "\n", __func__, pos, len);

	/* Programmer may be making a horrible mistake without knowing it */
	if (pos & bl->erase_mask) {
		FL_ERR("blocklevel_erase: pos (0x%"PRIx64") is not erase block (0x%08x) aligned\n",
				pos, bl->erase_mask + 1);
		return FLASH_ERR_ERASE_BOUNDARY;
	}

	if (len & bl->erase_mask) {
		FL_ERR("blocklevel_erase: len (0x%"PRIx64") is not erase block (0x%08x) aligned\n",
				len, bl->erase_mask + 1);
		return FLASH_ERR_ERASE_BOUNDARY;
	}

	rc = reacquire(bl);
	if (rc)
		return rc;

	rc = bl->erase(bl, pos, len);

	release(bl);

	return rc;
}
Beispiel #3
0
Renderer::Renderer(IDirect3DDevice9 *device, std::size_t max_vertices) :
	device(device), vertex_buffer(nullptr), max_vertices(max_vertices), render_list(std::make_shared<RenderList>(max_vertices)),
	prev_state_block(nullptr), render_state_block(nullptr)
{
	if (!device)
		throw std::exception("Renderer::ctor: Device was nullptr!");

	reacquire();
}
Beispiel #4
0
int blocklevel_raw_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len)
{
	int rc;

	if (!bl || !bl->read || !buf) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	rc = reacquire(bl);
	if (rc)
		return rc;

	rc = bl->read(bl, pos, buf, len);

	release(bl);

	return rc;
}
Beispiel #5
0
void Renderer::draw(const RenderListPtr &render_list)
{
	std::size_t num_vertices = std::size(render_list->vertices);
	if (num_vertices > 0)
	{
		void *data;

		if (num_vertices > max_vertices)
		{
			max_vertices = num_vertices;
			release();
			reacquire();
		}

		throw_if_failed(vertex_buffer->Lock(0, 0, &data, D3DLOCK_DISCARD));
		{
			std::memcpy(data, std::data(render_list->vertices), sizeof(Vertex) * num_vertices);
		}
		vertex_buffer->Unlock();
	}

	std::size_t pos = 0;

	Batch &prev_batch = render_list->batches.front();

	for (const auto &batch : render_list->batches)
	{
		int order = topology_order(batch.topology);
		if (batch.count && order > 0)
		{
			std::uint32_t primitive_count = batch.count;

			if (is_toplogy_list(batch.topology))
				primitive_count /= order;
			else
				primitive_count -= (order - 1);

			device->SetTexture(0, batch.texture);
			device->DrawPrimitive(batch.topology, pos, primitive_count);
			pos += batch.count;
		}
	}
}
Beispiel #6
0
int blocklevel_raw_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len)
{
	int rc;

	FL_DBG("%s: 0x%" PRIx64 "\t%p\t0x%" PRIx64 "\n", __func__, pos, buf, len);
	if (!bl || !bl->read || !buf) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	rc = reacquire(bl);
	if (rc)
		return rc;

	rc = bl->read(bl, pos, buf, len);

	release(bl);

	return rc;
}
Beispiel #7
0
int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len)
{
	uint32_t erase_size;
	const void *write_buf = buf;
	void *write_buf_start = NULL;
	uint64_t ecc_start;
	void *erase_buf;
	int rc = 0;

	if (!write_buf || !bl) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	FL_DBG("%s: 0x%" PRIx64 "\t0x%" PRIx64 "\n", __func__, pos, len);

	if (!(bl->flags & WRITE_NEED_ERASE)) {
		FL_DBG("%s: backend doesn't need erase\n", __func__);
		return blocklevel_write(bl, pos, buf, len);
	}

	rc = blocklevel_get_info(bl, NULL, NULL, &erase_size);
	if (rc)
		return rc;

	if (ecc_protected(bl, pos, len, &ecc_start)) {
		FL_DBG("%s: region has ECC\n", __func__);

		len = ecc_buffer_size(len);

		write_buf_start = malloc(len);
		if (!write_buf_start) {
			errno = ENOMEM;
			return FLASH_ERR_MALLOC_FAILED;
		}

		if (memcpy_to_ecc(write_buf_start, buf, ecc_buffer_size_minus_ecc(len))) {
			free(write_buf_start);
			errno = EBADF;
			return FLASH_ERR_ECC_INVALID;
		}
		write_buf = write_buf_start;
	}

	erase_buf = malloc(erase_size);
	if (!erase_buf) {
		errno = ENOMEM;
		rc = FLASH_ERR_MALLOC_FAILED;
		goto out_free;
	}

	rc = reacquire(bl);
	if (rc)
		goto out_free;

	while (len > 0) {
		uint32_t erase_block = pos & ~(erase_size - 1);
		uint32_t block_offset = pos & (erase_size - 1);
		uint32_t size = erase_size > len ? len : erase_size;
		int cmp;

		/* Write crosses an erase boundary, shrink the write to the boundary */
		if (erase_size < block_offset + size) {
			size = erase_size - block_offset;
		}

		rc = bl->read(bl, erase_block, erase_buf, erase_size);
		if (rc)
			goto out;

		cmp = blocklevel_flashcmp(erase_buf + block_offset, write_buf, size);
		FL_DBG("%s: region 0x%08x..0x%08x ", __func__,
				erase_block, erase_size);
		if (cmp != 0) {
			FL_DBG("needs ");
			if (cmp == -1) {
				FL_DBG("erase and ");
				bl->erase(bl, erase_block, erase_size);
			}
			FL_DBG("write\n");
			memcpy(erase_buf + block_offset, write_buf, size);
			rc = bl->write(bl, erase_block, erase_buf, erase_size);
			if (rc)
				goto out;
		}
		len -= size;
		pos += size;
		write_buf += size;
	}

out:
	release(bl);
out_free:
	free(write_buf_start);
	free(erase_buf);
	return rc;
}
Beispiel #8
0
int blocklevel_smart_erase(struct blocklevel_device *bl, uint64_t pos, uint64_t len)
{
	uint64_t block_size;
	void *erase_buf;
	int rc;

	if (!bl) {
		errno = EINVAL;
		return FLASH_ERR_PARM_ERROR;
	}

	FL_DBG("%s: 0x%" PRIx64 "\t0x%" PRIx64 "\n", __func__, pos, len);

	/* Nothing smart needs to be done, pos and len are aligned */
	if ((pos & bl->erase_mask) == 0 && (len & bl->erase_mask) == 0) {
		FL_DBG("%s: Skipping smarts everything is aligned 0x%" PRIx64 " 0x%" PRIx64
				"to 0x%08x\n", __func__, pos, len, bl->erase_mask);
		return blocklevel_erase(bl, pos, len);
	}
	block_size = bl->erase_mask + 1;
	erase_buf = malloc(block_size);
	if (!erase_buf) {
		errno = ENOMEM;
		return FLASH_ERR_MALLOC_FAILED;
	}

	rc = reacquire(bl);
	if (rc) {
		free(erase_buf);
		return rc;
	}

	if (pos & bl->erase_mask) {
		/*
		 * base_pos and base_len are the values in the first erase
		 * block that we need to preserve: the region up to pos.
		 */
		uint64_t base_pos = pos & ~(bl->erase_mask);
		uint64_t base_len = pos - base_pos;

		FL_DBG("%s: preserving 0x%" PRIx64 "..0x%" PRIx64 "\n",
				__func__, base_pos, base_pos + base_len);

		/*
		 * Read the entire block in case this is the ONLY block we're
		 * modifying, we may need the end chunk of it later
		 */
		rc = bl->read(bl, base_pos, erase_buf, block_size);
		if (rc)
			goto out;

		rc = bl->erase(bl, base_pos, block_size);
		if (rc)
			goto out;

		rc = bl->write(bl, base_pos, erase_buf, base_len);
		if (rc)
			goto out;

		/*
		 * The requested erase fits entirely into this erase block and
		 * so we need to write back the chunk at the end of the block
		 */
		if (base_pos + base_len + len < base_pos + block_size) {
			rc = bl->write(bl, pos + len, erase_buf + base_len + len,
					block_size - base_len - len);
			FL_DBG("%s: Early exit, everything was in one erase block\n",
					__func__);
			goto out;
		}

		pos += block_size - base_len;
		len -= block_size - base_len;
	}

	/* Now we should be aligned, best to double check */
	if (pos & bl->erase_mask) {
		FL_DBG("%s:pos 0x%" PRIx64 " isn't erase_mask 0x%08x aligned\n",
			   	__func__, pos, bl->erase_mask);
		rc = FLASH_ERR_PARM_ERROR;
		goto out;
	}

	if (len & ~(bl->erase_mask)) {
		rc = bl->erase(bl, pos, len & ~(bl->erase_mask));
		if (rc)
			goto out;

		pos += len & ~(bl->erase_mask);
		len -= len & ~(bl->erase_mask);
	}

	/* Length should be less than a block now */
	if (len > block_size) {
		FL_DBG("%s: len 0x%" PRIx64 " is still exceeds block_size 0x%" PRIx64 "\n",
				__func__, len, block_size);
		rc = FLASH_ERR_PARM_ERROR;
		goto out;
	}

	if (len & bl->erase_mask) {
		/*
		 * top_pos is the first byte that must be preserved and
		 * top_len is the length from top_pos to the end of the erase
		 * block: the region that must be preserved
		 */
		uint64_t top_pos = pos + len;
		uint64_t top_len = block_size - len;

		FL_DBG("%s: preserving 0x%" PRIx64 "..0x%" PRIx64 "\n",
				__func__, top_pos, top_pos + top_len);

		rc = bl->read(bl, top_pos, erase_buf, top_len);
		if (rc)
			goto out;

		rc = bl->erase(bl, pos, block_size);
		if (rc)
			goto out;

		rc = bl->write(bl, top_pos, erase_buf, top_len);
		if (rc)
			goto out;
	}

out:
	free(erase_buf);
	release(bl);
	return rc;
}