blob: bf9f37aa3252bdf7f24766cad04f659619778227 [file] [log] [blame]
// Copyright 2018 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.
#include "nand_operation.h"
#include <lib/ddk/debug.h>
#include <lib/ddk/driver.h>
#include <zircon/errors.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include "lib/zx/status.h"
namespace ftl {
zx_status_t NandOperation::SetDataVmo(size_t num_bytes) {
nand_operation_t* operation = GetOperation();
if (!operation) {
return ZX_ERR_NO_MEMORY;
}
zx_status_t status = GetVmo(num_bytes);
if (status != ZX_OK) {
return status;
}
operation->rw.data_vmo = mapper_.vmo().get();
return ZX_OK;
}
zx_status_t NandOperation::SetOobVmo(size_t num_bytes) {
nand_operation_t* operation = GetOperation();
if (!operation) {
return ZX_ERR_NO_MEMORY;
}
zx_status_t status = GetVmo(num_bytes);
if (status != ZX_OK) {
return status;
}
operation->rw.oob_vmo = mapper_.vmo().get();
return ZX_OK;
}
nand_operation_t* NandOperation::GetOperation() {
if (!raw_buffer_) {
CreateOperation();
}
return reinterpret_cast<nand_operation_t*>(raw_buffer_.get());
}
zx_status_t NandOperation::Execute(OobDoubler* parent) {
parent->Queue(GetOperation(), OnCompletion, this);
zx_status_t status = sync_completion_wait(&event_, ZX_SEC(60));
sync_completion_reset(&event_);
if (status != ZX_OK) {
return status;
}
return status_;
}
// Static.
void NandOperation::OnCompletion(void* cookie, zx_status_t status, nand_operation_t* op) {
NandOperation* operation = reinterpret_cast<NandOperation*>(cookie);
operation->status_ = status;
sync_completion_signal(&operation->event_);
}
zx_status_t NandOperation::GetVmo(size_t num_bytes) {
if (mapper_.start()) {
return ZX_OK;
}
return mapper_.CreateAndMap(num_bytes, "");
}
std::vector<zx::status<>> NandOperation::ExecuteBatch(
OobDoubler* parent, fbl::Span<std::unique_ptr<NandOperation>> operations) {
std::vector<zx::status<>> results(operations.size(), zx::ok());
for (auto& operation : operations) {
parent->Queue(operation->GetOperation(), &OnCompletion, static_cast<void*>(operation.get()));
}
for (size_t i = 0; i < operations.size(); ++i) {
zx_status_t status = sync_completion_wait(&operations[i]->event_, zx::sec(60).get());
results[i] = status == ZX_OK ? zx::status<>(zx::ok()) : zx::status<>(zx::error(status));
if (results[i].is_ok()) {
results[i] = operations[i]->status_ == ZX_OK
? zx::status<>(zx::ok())
: zx::status<>(zx::error(operations[i]->status_));
}
}
return results;
}
void NandOperation::CreateOperation() {
ZX_DEBUG_ASSERT(op_size_ >= sizeof(nand_operation_t));
raw_buffer_.reset(new char[op_size_]);
memset(raw_buffer_.get(), 0, op_size_);
}
} // namespace ftl.