1.\" 2.\" Copyright (c) 2014, 2015 Marcel Moolenaar 3.\" All rights reserved. 4.\" 5.\" Redistribution and use in source and binary forms, with or without 6.\" modification, are permitted provided that the following conditions 7.\" are met: 8.\" 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 15.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25.\" 26.\" $FreeBSD$ 27.\" 28.Dd August 7, 2015 29.Dt PROTO 4 30.Os 31.\" 32.Sh NAME 33.Nm proto 34.Nd Generic prototyping and diagnostics driver 35.\" 36.Sh SYNOPSIS 37To compile this driver into the kernel, 38place the following line in your 39kernel configuration file: 40.Bd -ragged -offset indent 41.Cd "device proto" 42.Ed 43.Pp 44Alternatively, to load the driver as a 45module at boot time, place the following line in 46.Xr loader.conf 5 : 47.Bd -literal -offset indent 48proto_load="YES" 49.Ed 50.Pp 51To have the driver attach to a device instead of its regular driver, 52mention it in the list of devices assigned to the following loader variable: 53.Bd -ragged -offset indent 54hw.proto.attach="desc[,desc]" 55.Ed 56.\" 57.Sh DESCRIPTION 58The 59.Nm 60device driver attaches to PCI or ISA devices when no other device drivers 61are present for those devices and it creates device special files for all 62resources associated with the device. 63The driver itself has no knowledge of the device it attaches to. 64Programs can open these device special files and perform register-level 65reads and writes. 66As such, the 67.Nm 68device driver is nothing but a conduit or gateway between user space 69programs and the hardware device. 70.Pp 71Examples for why this is useful include hardware diagnostics and prototyping. 72In both these use cases, it is far more convenient to develop and run the 73logic in user space. 74Especially hardware diagnostics requires a somewhat user-friendly interface 75and adequate reporting. 76Neither is done easily as kernel code. 77.Ss I/O port resources 78Device special files created for I/O port resources allow 79.Xr lseek 2 , 80.Xr read 2 , 81.Xr write 2 82and 83.Xr ioctl 2 84operations to be performed on them. 85The 86.Xr read 2 87and 88.Xr write 2 89system calls are used to perform input and output (resp.) on the port. 90The amount of data that can be read or written at any single time is either 911, 2 or 4 bytes. 92While the 93.Nm 94driver does not prevent reading or writing 8 bytes at a time for some 95architectures, it should not be assumed that such actually produces 96correct results. 97The 98.Xr lseek 2 99system call is used to select the port number, relative to the I/O port 100region being represented by the device special file. 101If, for example, the device special file corresponds to an I/O port region 102from 0x3f8 to 0x3ff inclusive, then an offset of 4 given to lseek with a 103whence value of SEEK_SET will target port 0x3fc on the next read or write 104operation. 105The 106.Xr ioctl 2 107system call can be used for the 108.Dv PROTO_IOC_REGION 109request. 110This ioctl request returns the extend of the resource covered by this 111device special file. The extend is returned in the following structure: 112.Bd -literal 113struct proto_ioc_region { 114 unsigned long address; 115 unsigned long size; 116}; 117.Ed 118.Ss Memory mapped I/O resources 119The device special files created for memory mapped I/O resources behave 120in the same way as those created for I/O port resources. 121Additionally, device special files for memory mapped I/O resources allow 122the memory to be mapped into the process' address space using 123.Xr mmap 2 . 124Reads and writes to the memory address returned by 125.Xr mmap 2 126go directly to the hardware. 127As such the use of 128.Xr read 2 129and 130.Xr write 2 131can be avoided, reducing the access overhead significantly. 132Alignment and access width constraints put forth by the underlying device 133apply. 134Also, make sure the compiler does not optimize memory accesses away or has 135them coalesced into bigger accesses. 136.Ss DMA pseudo resource 137A device special file named 138.Pa busdma 139is created for the purpose of doing DMA. 140It only supports 141.Xr ioctl 2 142and only for the 143.Dv PROTO_IOC_BUSDMA 144request. 145This device special file does not support 146.Xr read 2 147nor 148.Xr write 2 . 149The 150.Dv PROTO_IOC_BUSDMA 151request has an argument that is both in and out and is defined as 152follows: 153.Bd -literal 154struct proto_ioc_busdma { 155 unsigned int request; 156 unsigned long key; 157 union { 158 struct { 159 unsigned long align; 160 unsigned long bndry; 161 unsigned long maxaddr; 162 unsigned long maxsz; 163 unsigned long maxsegsz; 164 unsigned int nsegs; 165 unsigned int datarate; 166 unsigned int flags; 167 } tag; 168 struct { 169 unsigned long tag; 170 unsigned int flags; 171 unsigned long virt_addr; 172 unsigned long virt_size; 173 unsigned int phys_nsegs; 174 unsigned long phys_addr; 175 unsigned long bus_addr; 176 unsigned int bus_nsegs; 177 } md; 178 struct { 179 unsigned int op; 180 unsigned long base; 181 unsigned long size; 182 } sync; 183 } u; 184 unsigned long result; 185}; 186.Ed 187The 188.Va request 189field is used to specify which DMA operation is to be performed. 190The 191.Va key 192field is used to specify which object the operation applies to. 193An object is either a tag or a memory descriptor (md). 194The following DMA operations are defined: 195.Bl -tag -width XXXX 196.It PROTO_IOC_BUSDMA_TAG_CREATE 197Create a root tag. 198The 199.Va result 200field is set on output with the key of the DMA tag. 201The tag is created with the constraints given by the 202.Va tag 203sub-structure. These constraints correspond roughly to those that can be 204given to the 205.Xr bus_dma_tag_create 9 206function. 207.It PROTO_IOC_BUSDMA_TAG_DERIVE 208Create a derived tag. 209The 210.Va key 211field is used to identify the parent tag from which to derive the new tag. 212The key of the derived tag is returned in the 213.Va result 214field. 215The derived tag combines the constraints of the parent tag with those 216given by the 217.Va tag 218sub-structure. 219The combined constraints are written back to the 220.Va tag 221sub-structure on return. 222.It PROTO_IOC_BUSDMA_TAG_DESTROY 223Destroy a root or derived tag previously created. 224The 225.Va key 226field specifies the tag to destroy. 227A tag can only be destroyed when not referenced anymore. 228This means that derived tags that have this tag as a parent and memory 229descriptors created from this tag must be destroyed first. 230.It PROTO_IOC_BUSDMA_MEM_ALLOC 231Allocate memory that satisfies the constraints put forth by the tag 232given in the 233.Va tag 234field of the 235.Va md 236sub-structure. 237The key of the memory descriptor for this memory is returned in the 238.Va result 239field. 240The 241.Va md 242sub-structure is filled on return with details of the allocation. 243The kernel virtual address and the size of the allocated memory are returned 244in the 245.Va virt_addr 246and 247.Va virt_size 248fields. 249The number of contigous physical memory segments and the address of the first 250segment are returned in the 251.Va phys_nsegs 252and 253.Va phys_addr 254fields. 255Allocated memory is automatically loaded and thus mapped into bus space. 256The number of bus segments and the address of the first segment are returned 257in the 258.Va bus_nsegs 259and 260.Va bus_addr 261fields. 262The behaviour of this operation banks heavily on how 263.Xr bus_dmamem_alloc 9 264is implemented, which means that memory is currently always allocated as a 265single contigous region of physical memory. 266In practice this also tends to give a single contigous region in bus space. 267This may change over time. 268.It PROTO_IOC_BUSDMA_MEM_FREE 269Free previously allocated memory and destroy the memory desciptor. 270The 271.Nm 272driver is not in a position to track whether the memory has been mapped in 273the process' address space, so the application is responsible for unmapping 274the memory before it is freed. 275The 276.Nm 277driver also cannot protect against the hardware writing to or reading from 278the memory, even after it has been freed. 279When the memory is reused for other purposes it can be corrupted or cause 280the hardware to behave in unpredictable ways when DMA has not stopped 281completely before freeing. 282.It PROTO_IOC_BUSDMA_MD_CREATE 283Create an empty memory descriptor with the tag specified in the 284.Va tag 285field of the 286.Va md 287sub-structure. 288The key of the memory descriptor is returned in the 289.Va result 290field. 291.It PROTO_IOC_BUSDMA_MD_DESTROY 292Destroy the previously created memory descriptor specified by the 293.Va key 294field. 295When the memory descriptor is still loaded, it is unloaded first. 296.It PROTO_IOC_BUSDMA_MD_LOAD 297Load a contigous region of memory in the memory descriptor specified by the 298.Va key 299field. 300The size and address in the process' virtual address space are specified 301by the 302.Va virt_size 303and 304.Va virt_addr 305fields. 306On return, the 307.Va md 308sub-structure contains the result of the operation. 309The number of physical segments and the address of the first segment is 310returned in the 311.Va phys_nsegs 312and 313.Va phys_addr 314fields. 315The number of bus space segments and the address of the first segment in 316bus space is returned in the 317.Va bus_nsegs 318and 319.Va bus_addr 320fields. 321.It PROTO_IOC_BUSDMA_MD_UNLOAD 322Unload the memory descriptor specified by the 323.Va key 324field. 325.It PROTO_IOC_BUSDMA_SYNC 326Guarantee that all hardware components have a coherent view of the memory 327tracked by the memory descriptor, specified by the 328.Va key 329field. 330A sub-section of the memory can be targeted by specifying the relative 331offset and size of the memory to make coherent. 332The offset and size are given by the 333.Va base 334and 335.Va size 336fields of the 337.Va sync 338sub-structure. 339The 340.Va op 341field holds the sync operation to be performed. 342This is similar to the 343.Xr bus_dmamap_sync 9 344function. 345.El 346.Ss PCI configuration space 347Access to PCI configuration space is possible through the 348.Pa pcicfg 349device special file. 350The device special file supports 351.Xr lseek 2 , 352.Xr read 2 353and 354.Xr write 2 . 355Usage is the asme as for I/O port resources. 356.Sh FILES 357All device special files corresponding to a PCI device are located under 358.Pa /dev/proto/pci<d>:<b>:<s>:<f> 359with 360.Pa pci<d>:<b>:<s>:<f> 361representing the location of the PCI device in the PCI hierarchy. 362A PCI location includes: 363.Pp 364.Bl -tag -width XXXXXX -compact -offset indent 365.It <d> 366The PCI domain number 367.It <b> 368The PCI bus number 369.It <s> 370The PCI slot or device number 371.It <f> 372The PCI function number 373.El 374.Pp 375Every PCI device has a device special file called 376.Pa pcicfg . 377This device special file gives access to the PCI configuration space. 378A device special file called 379.Pa busdma 380is also created. 381This device special file provides the interfaces needed for doing DMA. 382For each valid base address register (BAR), a device special file is created 383that contains the BAR offset and the resource type. 384A resource type can be either 385.Pa io 386or 387.Pa mem 388representing I/O port or memory mapped I/O space (resp.) 389.Pp 390ISA devices do not have a location. Instead, they are identified by the 391first I/O port address or first memory mapped I/O address. 392Consequently, all device special files corresponding to an ISA device are 393located under 394.Pa /dev/proto/isa:<addr> 395with 396.Pa addr 397the address in hexadecimal notation. 398For each I/O port or memory mapped I/O address, a device special file is 399created that contains the resource identification used by the kernel and 400the resource type. 401The resource type can be either 402.Pa io 403or 404.Pa mem 405representing I/O port or memory mapped I/O space (resp.) 406When the device has a DMA channel assigned to it, a device special file 407with the name 408.Pa busdma 409is created as well. 410This device special file provides the interfaces needed for doing DMA. 411.Pp 412If the ISA device is not a Plug-and-Play device nor present in the ACPI 413device tree, it must have the appropriate hints so that the kernel can 414reserve the resources for it. 415.\" 416.Sh EXAMPLES 417A single function PCI device in domain 0, on bus 1, in slot 2 and having a 418single memory mapped I/O region will have the following device special files: 419.Pp 420.Bl -tag -width XXXXXX -compact -offset indent 421.It Pa /dev/proto/pci0:1:2:0/10.mem 422.It Pa /dev/proto/pci0:1:2:0/pcicfg 423.El 424.Pp 425A legacy floppy controller will have the following device files: 426.Pp 427.Bl -tag -width XXXXXX -compact -offset indent 428.It Pa /dev/proto/isa:0x3f0/00.io 429.It Pa /dev/proto/isa:0x3f0/01.io 430.It Pa /dev/proto/isa:0x3f0/busdma 431.El 432.\" 433.Sh SEE ALSO 434.Xr ioctl 2 , 435.Xr lseek 2 , 436.Xr mmap 2 , 437.Xr read 2 , 438.Xr write 2 , 439.Xr bus_dma_tag_create 9 , 440.Xr bus_dmamap_sync 9 , 441.Xr bus_dmamem_alloc 9 442.\" 443.Sh AUTHORS 444The 445.Nm 446device driver and this manual page were written by 447.An Marcel Moolenaar Aq Mt marcel@xcllnt.net . 448.Sh SECURITY CONSIDERATIONS 449Because programs have direct access to the hardware, the 450.Nm 451driver is inherently insecure. 452It is not advisable to use this driver on a production machine. 453.\" 454.Sh MISSING FUNCTIONALITY 455The 456.Nm 457driver does not fully support memory descriptors that need multiple 458physical memory segments or multiple bus space segments. 459At the very least, an operation is needed on the DMA pseudo resource 460for the application to obtain all segments. 461.Pp 462The 463.Nm 464driver does not yet support interrupts. 465Since interrupts cannot be handled by the driver itself, they must be 466converted into signals and delivered to the program that has registered 467for interrupts. 468A satisfactory mechanism for keeping the interrupt masked during the 469signal handling is still being worked out. 470.Pp 471DMA support for devices other than busmaster devices is not present yet. 472The details of how a program is to interact with the DMA controller still 473need to be fleshed out. 474