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 <ddk/device.h> 8#include <ddk/protocol/nand.h> 9#include <ddktl/device.h> 10#include <ddktl/protocol/bad-block.h> 11#include <ddktl/protocol/nand.h> 12 13#include <fbl/array.h> 14#include <fbl/macros.h> 15#include <fbl/ref_ptr.h> 16#include <zircon/types.h> 17 18#include "bad-block.h" 19 20namespace nand { 21 22class NandPartDevice; 23using DeviceType = ddk::Device<NandPartDevice, ddk::GetSizable, ddk::GetProtocolable, 24 ddk::Unbindable>; 25 26class NandPartDevice : public DeviceType, 27 public ddk::NandProtocol<NandPartDevice>, 28 public ddk::BadBlockable<NandPartDevice> { 29public: 30 // Spawns device nodes based on parent node. 31 static zx_status_t Create(zx_device_t* parent); 32 33 zx_status_t Bind(const char* name, uint32_t copy_count); 34 35 // Device protocol implementation. 36 zx_off_t DdkGetSize() { 37 //TODO: use query() results, *but* fvm returns different query and getsize 38 // results, and the latter are dynamic... 39 return device_get_size(parent()); 40 } 41 zx_status_t DdkGetProtocol(uint32_t proto_id, void* protocol); 42 void DdkUnbind() { DdkRemove(); } 43 void DdkRelease() { delete this; } 44 45 // nand protocol implementation. 46 void Query(nand_info_t* info_out, size_t* nand_op_size_out); 47 void Queue(nand_op_t* op); 48 zx_status_t GetFactoryBadBlockList(uint32_t* bad_blocks, uint32_t bad_block_len, 49 uint32_t* num_bad_blocks); 50 51 // Bad block protocol implementation. 52 zx_status_t GetBadBlockList(uint32_t* bad_block_list, uint32_t bad_block_list_len, 53 uint32_t* bad_block_count); 54 zx_status_t MarkBlockBad(uint32_t block); 55 56private: 57 explicit NandPartDevice(zx_device_t* parent, const nand_protocol_t& nand_proto, 58 fbl::RefPtr<BadBlock> bad_block, size_t parent_op_size, 59 const nand_info_t& nand_info, uint32_t erase_block_start) 60 : DeviceType(parent), nand_proto_(nand_proto), nand_(&nand_proto_), 61 parent_op_size_(parent_op_size), nand_info_(nand_info), 62 erase_block_start_(erase_block_start), bad_block_(fbl::move(bad_block)) {} 63 64 DISALLOW_COPY_ASSIGN_AND_MOVE(NandPartDevice); 65 66 nand_protocol_t nand_proto_; 67 ddk::NandProtocolProxy nand_; 68 69 // op_size for parent device. 70 size_t parent_op_size_; 71 // info about nand. 72 nand_info_t nand_info_; 73 // First erase block for the partition. 74 uint32_t erase_block_start_; 75 // Device specific bad block info. Shared between all devices for a given 76 // parent device. 77 fbl::RefPtr<BadBlock> bad_block_; 78 // Cached list of bad blocks for this partition. Lazily instantiated. 79 fbl::Array<uint32_t> bad_block_list_; 80}; 81 82} // namespace nand 83