1// Copyright 2017 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/driver.h>
8#include <ddk/protocol/block.h>
9#include <ddktl/protocol/block-internal.h>
10#include <fbl/type_support.h>
11#include <fbl/unique_ptr.h>
12#include <zircon/assert.h>
13
14// DDK block protocol support
15//
16// :: Mixins ::
17//
18// ddk::BlockIfc and ddk::BlockProtocol are mixin classes that simplify writing DDK drivers that
19// interact with the block protocol. They take care of implementing the function pointer tables
20// and calling into the object that wraps them.
21//
22// :: Examples ::
23//
24// // A driver that implements a ZX_PROTOCOL_BLOCK_IMPL device
25// class BlockDevice;
26// using BlockDeviceType = ddk::Device<BlockDevice, /* ddk mixins */>;
27//
28// class BlockDevice : public BlockDeviceType,
29//                      public ddk::BlockProtocol<BlockDevice> {
30//   public:
31//     BlockDevice(zx_device_t* parent)
32//       : BlockDeviceType("my-block-device", parent) {}
33//
34//     zx_status_t Bind() {
35//         DdkAdd();
36//     }
37//
38//     void DdkRelease() {
39//         // Clean up
40//     }
41//
42//     ...
43//   private:
44//     ...
45// };
46
47namespace ddk {
48
49template <typename D>
50class BlockProtocol : public internal::base_protocol {
51public:
52    BlockProtocol() {
53        internal::CheckBlockProtocolSubclass<D>();
54        ops_.query = Query;
55        ops_.queue = Queue;
56
57        // Can only inherit from one base_protocol implemenation
58        ZX_ASSERT(ddk_proto_id_ == 0);
59        ddk_proto_id_ = ZX_PROTOCOL_BLOCK_IMPL;
60        ddk_proto_ops_ = &ops_;
61    }
62
63private:
64    static void Query(void* ctx, block_info_t* info_out, size_t* block_op_size_out) {
65        static_cast<D*>(ctx)->BlockQuery(info_out, block_op_size_out);
66    }
67
68    static void Queue(void* ctx, block_op_t* txn) {
69        static_cast<D*>(ctx)->BlockQueue(txn);
70    }
71
72    block_protocol_ops_t ops_ = {};
73};
74
75} // namespace ddk
76