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