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 <ddktl/device.h>
8#include <ddktl/protocol/platform-bus.h>
9#include <ddktl/protocol/platform-device.h>
10#include <fbl/unique_ptr.h>
11#include <fbl/vector.h>
12
13#include "device-resources.h"
14#include "proxy-protocol.h"
15
16namespace platform_bus {
17
18class PlatformBus;
19
20// This class is used for binding protocol implementation drivers.
21// It implements the platform device protocol, and also provides access to the
22// a subset of the platform bus protocol, and also the other protocols that are
23// available to platform devices.
24// Unlike platform device drivers, proto implementation drivers run in the same
25// devhost as the platform bus driver.
26
27class ProtocolDevice;
28using ProtocolDeviceType = ddk::Device<ProtocolDevice, ddk::GetProtocolable>;
29
30// This class represents a platform device attached to the platform bus.
31// Instances of this class are created by PlatformBus at boot time when the board driver
32// calls the platform bus protocol method pbus_device_add().
33
34class ProtocolDevice : public ProtocolDeviceType, public ddk::PlatformDevProtocol<ProtocolDevice> {
35public:
36    // Creates a new ProtocolDevice instance.
37    // *flags* contains zero or more PDEV_ADD_* flags from the platform bus protocol.
38    static zx_status_t Create(const pbus_dev_t* pdev, zx_device_t* parent, PlatformBus* bus,
39                              fbl::unique_ptr<platform_bus::ProtocolDevice>* out);
40
41    inline uint32_t vid() const { return vid_; }
42    inline uint32_t pid() const { return pid_; }
43    inline uint32_t did() const { return did_; }
44
45    // Device protocol implementation.
46    zx_status_t DdkGetProtocol(uint32_t proto_id, void* out);
47    void DdkRelease();
48
49    // Platform device protocol implementation.
50    zx_status_t GetMmio(uint32_t index, pdev_mmio_t* out_mmio);
51    zx_status_t MapMmio(uint32_t index, uint32_t cache_policy, void** out_vaddr, size_t* out_size,
52                        zx_paddr_t* out_paddr, zx_handle_t* out_handle);
53    zx_status_t MapInterrupt(uint32_t index, uint32_t flags, zx_handle_t* out_handle);
54    zx_status_t GetBti(uint32_t index, zx_handle_t* out_handle);
55    zx_status_t GetDeviceInfo(pdev_device_info_t* out_info);
56    zx_status_t GetBoardInfo(pdev_board_info_t* out_info);
57    zx_status_t DeviceAdd(uint32_t index, device_add_args_t* args, zx_device_t** out);
58    zx_status_t GetProtocol(uint32_t proto_id, uint32_t index, void* out_protocol);
59
60    // Starts the underlying devmgr device.
61    zx_status_t Start();
62
63private:
64    explicit ProtocolDevice(zx_device_t* parent, PlatformBus* bus, const pbus_dev_t* pdev);
65    zx_status_t Init(const pbus_dev_t* pdev);
66
67    PlatformBus* bus_;
68    char name_[ZX_DEVICE_NAME_MAX + 1];
69    const uint32_t vid_;
70    const uint32_t pid_;
71    const uint32_t did_;
72
73    // Platform bus resources for this device.
74    DeviceResources resources_;
75
76    // Restricted subset of the platform bus protocol.
77    // We do not allow protocol devices call pbus_device_add() or pbus_protocol_device_add()
78    platform_bus_protocol_ops_t pbus_ops_;
79    void* pbus_ctx_;
80};
81
82} // namespace platform_bus
83