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 
16 namespace platform_bus {
17 
18 class 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 
27 class ProtocolDevice;
28 using 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 
34 class ProtocolDevice : public ProtocolDeviceType,
35                        public ddk::PDevProtocol<ProtocolDevice, ddk::base_protocol> {
36 public:
37     // Creates a new ProtocolDevice instance.
38     // *flags* contains zero or more PDEV_ADD_* flags from the platform bus protocol.
39     static zx_status_t Create(const pbus_dev_t* pdev, zx_device_t* parent, PlatformBus* bus,
40                               fbl::unique_ptr<platform_bus::ProtocolDevice>* out);
41 
vid()42     inline uint32_t vid() const { return vid_; }
pid()43     inline uint32_t pid() const { return pid_; }
did()44     inline uint32_t did() const { return did_; }
45 
46     // Device protocol implementation.
47     zx_status_t DdkGetProtocol(uint32_t proto_id, void* out);
48     void DdkRelease();
49 
50     // Platform device protocol implementation.
51     zx_status_t PDevGetMmio(uint32_t index, pdev_mmio_t* out_mmio);
52     zx_status_t PDevMapMmio(uint32_t index, uint32_t cache_policy, void** out_vaddr,
53                             size_t* out_size, zx_paddr_t* out_paddr, zx::vmo* out_vmo);
54     zx_status_t PDevGetInterrupt(uint32_t index, uint32_t flags, zx::interrupt* out_irq);
55     zx_status_t PDevGetBti(uint32_t index, zx::bti* out_handle);
56     zx_status_t PDevGetSmc(uint32_t index, zx::resource* out_resource);
57     zx_status_t PDevGetDeviceInfo(pdev_device_info_t* out_info);
58     zx_status_t PDevGetBoardInfo(pdev_board_info_t* out_info);
59     zx_status_t PDevDeviceAdd(uint32_t index, const device_add_args_t* args, zx_device_t** device);
60     zx_status_t PDevGetProtocol(uint32_t proto_id, uint32_t index, void* out_protocol,
61                                 size_t protocol_size, size_t* protocol_actual);
62 
63     // Starts the underlying devmgr device.
64     zx_status_t Start();
65 
66 private:
67     explicit ProtocolDevice(zx_device_t* parent, PlatformBus* bus, const pbus_dev_t* pdev);
68     zx_status_t Init(const pbus_dev_t* pdev);
69 
70     PlatformBus* bus_;
71     char name_[ZX_DEVICE_NAME_MAX + 1];
72     const uint32_t vid_;
73     const uint32_t pid_;
74     const uint32_t did_;
75 
76     // Platform bus resources for this device.
77     DeviceResources resources_;
78 
79     // Restricted subset of the platform bus protocol.
80     // We do not allow protocol devices call pbus_device_add() or pbus_protocol_device_add()
81     pbus_protocol_ops_t pbus_ops_;
82     void* pbus_ctx_;
83 };
84 
85 } // namespace platform_bus
86