1 // Copyright 2016 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 <zircon/types.h>
8 #include <zircon/listnode.h>
9 #include <zircon/compiler.h>
10 #include <stdint.h>
11 
12 __BEGIN_CDECLS;
13 
14 typedef struct zx_device zx_device_t;
15 typedef struct zx_driver zx_driver_t;
16 typedef struct zx_protocol_device zx_protocol_device_t;
17 typedef struct zx_device_prop zx_device_prop_t;
18 typedef struct zx_driver_rec zx_driver_rec_t;
19 
20 typedef struct zx_bind_inst zx_bind_inst_t;
21 typedef struct zx_driver_binding zx_driver_binding_t;
22 
23 // echo -n "zx_driver_ops_v0.5" | sha256sum | cut -c1-16
24 #define DRIVER_OPS_VERSION 0x2b3490fa40d9f452
25 
26 typedef struct zx_driver_ops {
27     uint64_t version;   // DRIVER_OPS_VERSION
28 
29     // Opportunity to do on-load work.
30     // Called ony once, before any other ops are called.
31     // The driver may optionally return a context pointer to be passed
32     // to the other driver ops.
33     zx_status_t (*init)(void** out_ctx);
34 
35     // Requests that the driver bind to the provided device,
36     // initialize it, and publish any children.
37     zx_status_t (*bind)(void* ctx, zx_device_t* device);
38 
39     // Only provided by bus manager drivers, create() is invoked to
40     // instantiate a bus device instance in a new device host process
41     zx_status_t (*create)(void* ctx, zx_device_t* parent,
42                           const char* name, const char* args,
43                           zx_handle_t rpc_channel);
44 
45     // Last call before driver is unloaded.
46     void (*release)(void* ctx);
47 } zx_driver_ops_t;
48 
49 // echo -n "device_add_args_v0.5" | sha256sum | cut -c1-16
50 #define DEVICE_ADD_ARGS_VERSION 0x96a64134d56e88e3
51 
52 enum {
53     // Do not attempt to bind drivers to this device automatically
54     DEVICE_ADD_NON_BINDABLE = (1 << 0),
55 
56     // This is a device instance (not visible in devfs or eligible for binding)
57     DEVICE_ADD_INSTANCE     = (1 << 1),
58 
59     // Children of this device will be loaded in their own devhost process,
60     // behind a proxy of this device
61     DEVICE_ADD_MUST_ISOLATE = (1 << 2),
62 
63     // This device will not be visible in devfs or available for binding
64     // until device_make_visible() is called on it.
65     DEVICE_ADD_INVISIBLE    = (1 << 3),
66 };
67 
68 // Device Manager API
69 typedef struct device_add_args {
70     // DEVICE_ADD_ARGS_VERSION
71     uint64_t version;
72 
73     // Driver name is copied to internal structure
74     // max length is ZX_DEVICE_NAME_MAX
75     const char* name;
76 
77     // Context pointer for use by the driver
78     // and passed to driver in all zx_protocol_device_t callbacks
79     void* ctx;
80 
81     // Pointer to device's device protocol operations
82     zx_protocol_device_t* ops;
83 
84     // Optional list of device properties
85     zx_device_prop_t* props;
86 
87     // Number of device properties
88     uint32_t prop_count;
89 
90     // Optional custom protocol for this device
91     uint32_t proto_id;
92 
93     // Optional custom protocol operations for this device
94     void* proto_ops;
95 
96     // Arguments used with DEVICE_ADD_MUST_ISOLATE
97     // these will be passed to the create() driver op of
98     // the proxy device in the new devhost
99     const char* proxy_args;
100 
101     // One or more of DEVICE_ADD_*
102     uint32_t flags;
103 } device_add_args_t;
104 
105 struct zx_driver_rec {
106     const zx_driver_ops_t* ops;
107     zx_driver_t* driver;
108     uint32_t log_flags;
109 };
110 
111 // This global symbol is initialized by the driver loader in devhost
112 extern zx_driver_rec_t __zircon_driver_rec__;
113 
114 zx_status_t device_add_from_driver(zx_driver_t* drv, zx_device_t* parent,
115                               device_add_args_t* args, zx_device_t** out);
116 
117 // Creates a device and adds it to the devmgr.
118 // device_add_args_t contains all "in" arguments.
119 // All device_add_args_t values are copied, so device_add_args_t can be stack allocated.
120 // The device_add_args_t.name string value is copied.
121 // All other pointer fields are copied as pointers.
122 // The newly added device will be active before this call returns, so be sure to have
123 // the "out" pointer point to your device-local structure so callbacks can access
124 // it immediately.
125 //
126 // If this call is successful, but the device needs to be torn down, device_remove() should be
127 // called.  If |args->ctx| is backed by memory, it is the programmer's responsibility to not free
128 // that memory until the device's |release| hook is called.
device_add(zx_device_t * parent,device_add_args_t * args,zx_device_t ** out)129 static inline zx_status_t device_add(zx_device_t* parent, device_add_args_t* args, zx_device_t** out) {
130     return device_add_from_driver(__zircon_driver_rec__.driver, parent, args, out);
131 }
132 
133 zx_status_t device_remove(zx_device_t* device);
134 zx_status_t device_rebind(zx_device_t* device);
135 void device_make_visible(zx_device_t* device);
136 
137 #define ROUNDUP(a, b)   (((a) + ((b)-1)) & ~((b)-1))
138 #define ROUNDDOWN(a, b) ((a) & ~((b)-1))
139 #define ALIGN(a, b) ROUNDUP(a, b)
140 
141 // temporary accessor for root resource handle
142 zx_handle_t get_root_resource(void);
143 
144 // Drivers may need to load firmware for a device, typically during the call to
145 // bind the device. The devmgr will look for the firmware at the given path
146 // relative to system-defined locations for device firmware. The file will be
147 // loaded into a vmo pointed to by fw. The actual size of the firmware will be
148 // returned in size.
149 zx_status_t load_firmware(zx_device_t* device, const char* path,
150                           zx_handle_t* fw, size_t* size);
151 
152 // panic is for handling non-recoverable, non-reportable fatal
153 // errors in a way that will get logged.  Right now this just
154 // does a bogus write to unmapped memory.
panic(void)155 static inline void panic(void) {
156     for (;;) {
157         *((int*) 0xdead) = 1;
158     }
159 }
160 
161 // Protocol Identifiers
162 #define DDK_PROTOCOL_DEF(tag, val, name, flags) ZX_PROTOCOL_##tag = val,
163 enum {
164 #include <ddk/protodefs.h>
165 };
166 
167 __END_CDECLS;
168