1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <inttypes.h>
8 
9 #include <fbl/array.h>
10 #include <lib/ftl/ndm-driver.h>
11 #include <zircon/types.h>
12 
13 // How often to inject errors.
14 constexpr int kEccErrorInterval = 900;
15 constexpr int kBadBlockInterval = 50;
16 
17 // Ram-backed driver for testing purposes.
18 class NdmRamDriver : public ftl::NdmBaseDriver {
19   public:
NdmRamDriver(const ftl::VolumeOptions & options)20     NdmRamDriver(const ftl::VolumeOptions& options) : options_(options) {}
~NdmRamDriver()21     ~NdmRamDriver() final {}
22 
23     // NdmDriver interface:
24     const char* Init() final;
25     const char* Attach(const ftl::Volume* ftl_volume) final;
26     bool Detach() final;
27     int NandRead(uint32_t start_page, uint32_t page_count, void* page_buffer, void* oob_buffer) final;
28     int NandWrite(uint32_t start_page, uint32_t page_count, const void* page_buffer,
29                   const void* oob_buffer) final;
30     int NandErase(uint32_t page_num) final;
31     int IsBadBlock(uint32_t page_num) final;
32     bool IsEmptyPage(uint32_t page_num, const uint8_t* data, const uint8_t* spare) final;
33 
34   private:
35     // Reads or Writes a single page.
36     int ReadPage(uint32_t page_num, uint8_t* data, uint8_t* spare);
37     int WritePage(uint32_t page_num, const uint8_t* data, const uint8_t* spare);
38 
39     // Returns true for a freshly minted bad block.
40     bool SimulateBadBlock(uint32_t page_num);
41 
42     // Access the main data and spare area for a given page.
43     uint8_t* MainData(uint32_t page_num);
44     uint8_t* SpareData(uint32_t page_num);
45 
46     // Access flags for a given page.
47     bool Written(uint32_t page_num);
48     bool FailEcc(uint32_t page_num);
49     bool BadBlock(uint32_t page_num);
50     void SetWritten(uint32_t page_num, bool value);
51     void SetFailEcc(uint32_t page_num, bool value);
52     void SetBadBlock(uint32_t page_num, bool value);
53 
54     uint32_t PagesPerBlock() const;
55 
56     fbl::Array<uint8_t> volume_;
57     fbl::Array<uint8_t> flags_;
58     ftl::VolumeOptions options_;
59     int ecc_error_interval_ = 0;  // Controls simulation of ECC errors.
60     int bad_block_interval_ = 0;  // Controls simulation of bad blocks.
61     uint32_t num_bad_blocks_ = 0;
62 };
63