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 #include "block_device.h"
6 
7 #include <ddk/debug.h>
8 #include <zircon/assert.h>
9 
10 #include "nand_driver.h"
11 
12 namespace ftl {
13 
~BlockDevice()14 BlockDevice::~BlockDevice() {
15     bool volume_created = (DdkGetSize() != 0);
16     if (volume_created) {
17         if (volume_->Unmount() != ZX_OK) {
18             zxlogf(ERROR, "FTL: FtlUmmount() failed");
19         }
20     }
21 }
22 
Bind()23 zx_status_t BlockDevice::Bind() {
24     zxlogf(INFO, "FTL: parent: '%s'\n", device_get_name(parent()));
25 
26     if (device_get_protocol(parent(), ZX_PROTOCOL_NAND, &parent_) != ZX_OK) {
27         zxlogf(ERROR, "FTL: device '%s' does not support nand protocol\n",
28                device_get_name(parent()));
29         return ZX_ERR_NOT_SUPPORTED;
30     }
31 
32     // Get the optional bad block protocol.
33     if (device_get_protocol(parent(), ZX_PROTOCOL_BAD_BLOCK, &bad_block_) != ZX_OK) {
34         zxlogf(WARN, "FTL: Parent device '%s': does not support bad_block protocol\n",
35                device_get_name(parent()));
36     }
37 
38     zx_status_t status = Init();
39     if (status != ZX_OK) {
40         return status;
41     }
42     return DdkAdd("ftl");
43 }
44 
DdkUnbind()45 void BlockDevice::DdkUnbind() {
46     DdkRemove();
47 }
48 
Init()49 zx_status_t BlockDevice::Init() {
50     if (!InitFtl()) {
51         return ZX_ERR_NO_RESOURCES;
52     }
53 
54     return ZX_OK;
55 }
56 
OnVolumeAdded(uint32_t page_size,uint32_t num_pages)57 bool BlockDevice::OnVolumeAdded(uint32_t page_size, uint32_t num_pages) {
58     params_ = {page_size, num_pages};
59     zxlogf(INFO, "FTL: %d pages of %d bytes\n", num_pages, page_size);
60     return true;
61 }
62 
InitFtl()63 bool BlockDevice::InitFtl() {
64     std::unique_ptr<NandDriver> driver = NandDriver::Create(&parent_, &bad_block_);
65     memcpy(guid_, driver->info().partition_guid, ZBI_PARTITION_GUID_LEN);
66 
67     if (!volume_) {
68         volume_ = std::make_unique<ftl::VolumeImpl>(this);
69     }
70 
71     const char* error = volume_->Init(std::move(driver));
72     if (error) {
73         zxlogf(ERROR, "FTL: %s\n", error);
74         return false;
75     }
76 
77     zxlogf(INFO, "FTL: InitFtl ok\n");
78     return true;
79 }
80 
81 }  // namespace ftl.
82