blob: 92331018bccb9ca8315fea5bd7e3db86744ccfca [file] [log] [blame]
// Copyright 2017 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.
#pragma once
#include <ddk/protocol/block.h>
#include <ddktl/protocol/block-internal.h>
#include <fbl/type_support.h>
#include <fbl/unique_ptr.h>
#include <zircon/assert.h>
// DDK block protocol support
//
// :: Mixins ::
//
// ddk::BlockIfc and ddk::BlockProtocol are mixin classes that simplify writing DDK drivers that
// interact with the block protocol. They take care of implementing the function pointer tables
// and calling into the object that wraps them.
//
// :: Examples ::
//
// // A driver that implements a ZX_PROTOCOL_BLOCK_IMPL device
// class BlockDevice;
// using BlockDeviceType = ddk::Device<BlockDevice, /* ddk mixins */>;
//
// class BlockDevice : public BlockDeviceType,
// public ddk::BlockProtocol<BlockDevice> {
// public:
// BlockDevice(zx_device_t* parent)
// : BlockDeviceType("my-block-device", parent) {}
//
// zx_status_t Bind() {
// DdkAdd();
// }
//
// void DdkRelease() {
// // Clean up
// }
//
// ...
// private:
// ...
// };
namespace ddk {
template <typename D>
class BlockProtocol : public internal::base_protocol {
public:
BlockProtocol() {
internal::CheckBlockProtocolSubclass<D>();
ops_.query = Query;
ops_.queue = Queue;
// Can only inherit from one base_protocol implemenation
ZX_ASSERT(ddk_proto_id_ == 0);
ddk_proto_id_ = ZX_PROTOCOL_BLOCK_IMPL;
ddk_proto_ops_ = &ops_;
}
private:
static void Query(void* ctx, block_info_t* info_out, size_t* block_op_size_out) {
static_cast<D*>(ctx)->BlockQuery(info_out, block_op_size_out);
}
static void Queue(void* ctx, block_op_t* txn) {
static_cast<D*>(ctx)->BlockQueue(txn);
}
block_protocol_ops_t ops_ = {};
};
} // namespace ddk