1# Zircon Driver Development
2
3Zircon drivers are shared libraries that are dynamically loaded in Device Host
4processes in user space. The process of loading a driver is controlled by the
5Device Coordinator. See [Device Model](device-model.md) for more information on
6Device Hosts, Device Coordinator and the driver and device lifecycles.
7
8## Directory structure
9
10Zircon drivers are found under [system/dev](../../system/dev).
11They are grouped based on the protocols they implement.
12The driver protocols are defined in
13[ddk/include/ddk/protodefs.h](../../system/ulib/ddk/include/ddk/protodefs.h).
14For example, a USB ethernet driver goes in [system/dev/ethernet](../../system/dev/ethernet)
15rather than [system/dev/usb](../../system/dev/usb) because it implements an ethernet protocol.
16However, drivers that implement the USB stack are in [system/dev/usb](../../system/dev/usb)
17because they implement USB protocols.
18
19In the driver's `rules.mk`, the `MODULE_TYPE` should
20be `driver`. This will install the driver shared lib in `/boot/driver/`.
21
22If your driver is built outside Zircon, install them in `/system/driver/`
23. The Device Coordinator looks in those directories for loadable
24drivers.
25
26## Declaring a driver
27
28At a minimum, a driver should contain the driver declaration and implement the
29`bind()` driver op.
30
31Drivers are loaded and bound to a device when the Device Coordinator
32successfully finds a matching driver for a device. A driver declares the
33devices it is compatible with via bindings.
34The following bind program
35declares the [AHCI driver](../../system/dev/block/ahci/ahci.c):
36
37```
38ZIRCON_DRIVER_BEGIN(ahci, ahci_driver_ops, "zircon", "0.1", 4)
39    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PCI),
40    BI_ABORT_IF(NE, BIND_PCI_CLASS, 0x01),
41    BI_ABORT_IF(NE, BIND_PCI_SUBCLASS, 0x06),
42    BI_MATCH_IF(EQ, BIND_PCI_INTERFACE, 0x01),
43ZIRCON_DRIVER_END(ahci)
44```
45
46The AHCI driver has 4 directives in the bind program. `"zircon"` is the vendor
47id and `"0.1"` is the driver version. It binds with `ZX_PROTOCOL_PCI` devices
48with PCI class 1, subclass 6, interface 1.
49
50The [PCI driver](../../system/dev/bus/pci/kpci.c) publishes the matching
51device with the following properties:
52
53```
54zx_device_prop_t device_props[] = {
55    {BIND_PROTOCOL, 0, ZX_PROTOCOL_PCI},
56    {BIND_PCI_VID, 0, info.vendor_id},
57    {BIND_PCI_DID, 0, info.device_id},
58    {BIND_PCI_CLASS, 0, info.base_class},
59    {BIND_PCI_SUBCLASS, 0, info.sub_class},
60    {BIND_PCI_INTERFACE, 0, info.program_interface},
61    {BIND_PCI_REVISION, 0, info.revision_id},
62    {BIND_PCI_BDF_ADDR, 0, BIND_PCI_BDF_PACK(info.bus_id, info.dev_id,
63                                             info.func_id)},
64};
65```
66
67Binding variables and macros are defined in
68[zircon/driver/binding.h](../../system/public/zircon/driver/binding.h).
69If you are introducing a new device class, you may need to introduce new
70binding variables in that file.
71Binding variables are 32-bit values. If your
72variable value requires greater than a 32-bit value,
73split them into multiple 32-bit variables. An
74example is ACPI HID values, which are 8 characters (64-bits) long.
75It is split into `BIND_ACPI_HID_0_3` and `BIND_ACPI_HID_4_7`.
76
77Binding directives are evaluated sequentially. The branching directives
78`BI_GOTO()` and `BI_GOTO_IF()` allow you to jump forward to the matching
79label, defined by `BI_LABEL()`.
80
81`BI_ABORT_IF_AUTOBIND` may be used (usually as the first instruction)
82to prevent the default automatic binding behaviour.
83In that case, a driver can be bound to a device using
84`ioctl_device_bind()` call
85
86
87## Driver binding
88
89A driver’s `bind()` function is called when it is matched to a device.
90Generally a driver will initialize any data structures needed for the device
91and initialize hardware in this function. It should not perform any
92time-consuming tasks or block in this function, because it is invoked from the
93devhost's RPC thread and it will not be able to service other requests in the
94meantime. Instead, it should spawn a new thread to perform lengthy tasks.
95
96The driver should make no assumptions about the state of the hardware in
97`bind()`, resetting the hardware or otherwise ensuring it is in a known state.
98Because the system recovers from a
99driver crash by re-spawning the devhost, the hardware may be in an unknown
100state when `bind()` is invoked.
101
102A driver is required to publish a `zx_device_t` in `bind()` by calling
103`device_add()`. This is necessary for the Device Coordinator to keep
104track of the
105device lifecycle. If the driver is not able to publish a functional device in
106`bind()`, for example if it is initializing the full device in a thread, it
107should publish an invisible device, and make this device visible when
108initialization is completed. See `DEVICE_ADD_INVISIBLE` and
109`device_make_visible()` in
110[zircon/ddk/driver.h](../../system/ulib/ddk/include/ddk/driver.h).
111
112There are generally four outcomes from `bind()`:
113
1141. The driver determines the device is supported and does not need to do any
115heavy lifting, so publishes a new device via `device_add()` and returns
116`ZX_OK`.
117
1182. The driver determines that even though the bind program matched, the device
119cannot be supported (maybe due to checking hw version bits or whatnot) and
120returns an error.
121
1223. The driver needs to do further initialization before the device is ready or
123it’s sure it can support it, so it publishes an invisible device and kicks off
124a thread to keep working, while returning `ZX_OK`. That thread will eventually
125make the device visible or, if it cannot successfully initialize it, remove it.
126
1274. The driver represents a bus or controller with 0..n children which may
128dynamically appear or disappear. In this case it should publish a device
129immediately representing the bus or controller, and then dynamically publish
130children (that downstream drivers will bind to) representing hardware on that
131bus. Examples: AHCI/SATA, USB, etc.
132
133After a device is added and made visible by the system, it is made available
134to client processes and for binding by compatible drivers.
135
136## Device protocols
137
138A driver provides a set of device ops and optional protocol ops to a device.
139Device ops implement the device lifecycle methods and the external interface
140to the device that are called by other user space applications and services.
141Protocol ops implement the ddk-internal protocols of the device that are
142called by other drivers.
143
144You can pass one set of protocol ops for the device in `device_add_args_t`. If
145a device supports multiple protocols, implement the `get_protocol()` device
146op. A device can only have one protocol id. The protocol id corresponds to the
147class the device is published under in devfs.
148
149Device protocol headers are found in
150[ddk/protocol/](../../system/ulib/ddk/include/ddk/protocol). Ops and any data
151structures passed between drivers should be defined in this header.
152
153## Driver operation
154
155A driver generally operates by servicing client requests from children drivers
156or other processes. It fulfills those requests either by communicating
157directly with hardware (for example, via MMIO) or by communicating with its
158parent device (for example, queuing a USB transaction).
159
160External client requests from processes outside the devhost are fulfilled by
161the device ops `read()`, `write()`, and `ioctl()`. Requests from children
162drivers, generally in the same process, are fulfilled by device
163protocols corresponding to the device class. Driver-to-driver requests should
164use device protocols instead of device ops.
165
166A device can get a protocol supported by its parent by calling
167`device_get_protocol()` on its parent device.
168
169## Device interrupts
170
171Device interrupts are implemented by interrupt objects, which are a type of
172kernel objects. A driver requests a handle to the device interrupt from its
173parent device in a device protocol method. The handle returned will be bound
174to the appropriate interrupt for the device, as defined by a parent driver.
175For example, the PCI protocol implements `map_interrupt()` for PCI children. A
176driver should spawn a thread to wait on the interrupt handle.
177
178The kernel will automatically handle masking and unmasking the
179interrupt as appropriate, depending on whether the interrupt is edge-triggered
180or level-triggered. For level-triggered hardware interrupts,
181[zx_interrupt_wait()](../syscalls/interrupt_wait.md) will mask the interrupt
182before returning and unmask the interrupt when it is called again the next
183time. For edge-triggered interrupts, the interrupt remains unmasked.
184
185The interrupt thread should not perform any long-running tasks. For drivers
186that perform lengthy tasks, use a worker thread.
187
188You can signal an interrupt handle with
189[zx_interrupt_signal()](../syscalls/interrupt_signal.md) on slot
190**ZX_INTERRUPT_SLOT_USER** to return from `zx_interrupt_wait()`. This is
191necessary to shut down the interrupt thread during driver clean up.
192
193## Ioctl
194
195Ioctls for each device class are defined in
196[zircon/device/](../../system/public/zircon/device). Ioctls may accept or
197return handles. The `IOCTL_KIND_*` defines in
198[zircon/device/ioctl.h](../../system/public/zircon/device/ioctl.h), used in
199the ioctl declaration, defines whether the ioctl accepts or returns handles
200and how many. The driver owns the handles passed in and should close the
201handles when they’re no longer needed, unless it returns
202`ZX_ERR_NOT_SUPPORTED` in which case the devhost RPC layer will close the
203handles.
204
205## Protocol ops vs. ioctls
206
207Protocol ops define the DDK-internal API for a device. Ioctls define the
208external API. Define a protocol op if the function is primarily meant to be
209called by other drivers, and generally a driver should call a protocol op on
210its parent instead of an ioctl.
211
212## Isolate devices
213
214Devices that are added with `DEVICE_ADD_MUST_ISOLATE` spawn a new proxy devhost.
215The device exists in both the parent devhost and as the root of the new devhost.
216Devmgr attempts to load <driver>.proxy.so into this proxy devhost. For example,
217PCI is supplied by libpci.so so devmgr would look to load libpci.proxy.so. The
218driver is provided a channel in `create()` when it creates the proxy device
219(the “bottom half” that runs in the new devhost). The proxy device should cache
220this channel for when it needs to communicate with the top half (e.g. if
221it needs to call API on the parent device).
222
223`rxrpc()` is invoked on the top half when this channel is written to by the
224bottom half. There is no common wire protocol for this channel. For an
225example, refer to the [PCI driver](../../system/dev/bus/pci).
226
227NOTE: This is a mechanism used by various bus devices and not something
228general drivers should have to worry about. (please ping swetland if you think
229you need to use this)
230
231## Logging
232
233[ddk/debug.h](../../system/ulib/ddk/include/ddk/debug.h) defines the
234`zxlogf(<log_level>,...)` macro. The log messages are printed to the system
235debuglog over the network and on the serial port if available for the device.
236By default, `ERROR` and `INFO` are always printed. You can control the log
237level for a driver by passing the boot cmdline
238`driver.<driver_name>.log=+<level>,-<level>`. For example,
239`driver.sdhci.log=-info,+trace,+spew` enables the `TRACE` and `SPEW` logs and
240disable the `INFO` logs for the sdhci driver.
241
242The log levels prefixed by "L" (`LERROR`, `LINFO`, etc.) do not get sent over
243the network and is useful for network logging.
244
245## Driver testing
246
247`ZX_PROTOCOL_TEST` provides a mechanism to test drivers by running the driver
248under test in an emulated environment. Write a driver that binds to a
249`ZX_PROTOCOL_TEST` device. This driver should publish a device that the driver
250under test can bind to, and it should implement the protocol functions the
251driver under test invokes in normal operation. This helper driver should be
252declared with `BI_ABORT_IF_AUTOBIND` in the bindings.
253
254The test harness calls `fuchsia.device.test.RootDevice.CreateDevice()` on
255`/dev/test/test`, which will create a `ZX_PROTOCOL_TEST` device and return
256its path. Then it calls `ioctl_device_bind()` with the helper driver on the
257newly created device.  This approach generally works better for mid-layer
258protocol drivers. It's possible to emulate real hardware with the same
259approach but it may not be as useful.
260
261The functions defined in
262[ddk/protocol/test.h](../../system/ulib/ddk/include/ddk/protocol/test.h) are
263for testing libraries that run as part of a driver. For an example, refer to
264[system/ulib/ddk/test](../../system/ulib/ddk/test). The test harness for these
265tests is
266[system/utest/driver-tests/main.c](../../system/utest/driver-tests/main.c)
267
268## Driver rights
269
270Although drivers run in user space processes, they have a more restricted set
271of rights than normal processes. Drivers are not allowed to access the
272filesystem, including devfs. That means a driver cannot interact with
273arbitrary devices. If your driver needs to do this, consider writing a service
274instead. For example, the virtual console is implemented by the
275[virtcon](../../system/core/virtcon) service.
276
277Privileged operations such as `zx_vmo_create_contiguous()` and
278[zx_interrupt_create](../syscalls/interrupt_create.md) require a root resource
279handle. This handle is not available to drivers other than the system driver
280([ACPI](../../system/dev/bus/acpi) on x86 systems and
281[platform](../../system/dev/bus/platform) on ARM systems). A device should
282request its parent to perform such operations for it. Contact the author
283of the parent driver if its protocol does not address this use case.
284
285Similarly, a driver is not allowed to request arbitrary MMIO ranges,
286interrupts or GPIOs. Bus drivers such as PCI and platform only return the
287resources associated to the child device.
288