blob: 9a6f1fa89edd5f28a46b582b85ec644d45602ee1 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVICES_BLOCK_DRIVERS_NVME_QUEUE_H_
#define SRC_DEVICES_BLOCK_DRIVERS_NVME_QUEUE_H_
#include <lib/dma-buffer/buffer.h>
#include <lib/zx/bti.h>
#include <lib/zx/result.h>
#include <memory>
#include <hwreg/bitfields.h>
namespace nvme {
// Represents a single NVME queue in memory.
// The queue will always fit in one page.
class Queue {
public:
static zx::result<Queue> Create(zx::unowned_bti bti, uint16_t queue_id, uint32_t max_entries,
size_t entry_size) {
Queue ret(entry_size, queue_id);
auto status = ret.Init(std::move(bti), max_entries);
if (status.is_error()) {
return status.take_error();
}
return zx::ok(std::move(ret));
}
// Get the physical address of this queue, suitable for passing to the controller.
zx_paddr_t GetDeviceAddress() const { return io_->phys(); }
// Return the number of entries in the queue.
uint32_t entry_count() const { return entry_count_; }
// Get the next item in the queue, and move the queue pointer forward.
void* Next() {
void* value = static_cast<uint8_t*>(io_->virt()) + (next_index_ * entry_size_);
next_index_++;
if (next_index_ == entry_count_) {
next_index_ = 0;
}
return value;
}
// Return the next item in the queue without affecting the queue.
void* Peek() { return static_cast<uint8_t*>(io_->virt()) + (next_index_ * entry_size_); }
// Return the index of the next item in the queue.
size_t NextIndex() const { return next_index_; }
uint16_t id() const { return queue_id_; }
// For unit tests only.
void* head() const { return io_->virt(); }
private:
explicit Queue(size_t entry_size, uint16_t queue_id)
: entry_size_(entry_size), queue_id_(queue_id) {}
zx::result<> Init(zx::unowned_bti bti, uint32_t max_entries);
std::unique_ptr<dma_buffer::ContiguousBuffer> io_;
size_t entry_size_;
uint32_t entry_count_;
uint16_t queue_id_;
size_t next_index_ = 0;
};
} // namespace nvme
#endif // SRC_DEVICES_BLOCK_DRIVERS_NVME_QUEUE_H_