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; }
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; }
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(); }
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; }
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; } } }
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; }
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; }
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; }