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.Dd August 7, 2015 27.Dt PROTO 4 28.Os 29.\" 30.Sh NAME 31.Nm proto 32.Nd Generic prototyping and diagnostics driver 33.\" 34.Sh SYNOPSIS 35To compile this driver into the kernel, 36place the following line in your 37kernel configuration file: 38.Bd -ragged -offset indent 39.Cd "device proto" 40.Ed 41.Pp 42Alternatively, to load the driver as a 43module at boot time, place the following line in 44.Xr loader.conf 5 : 45.Bd -literal -offset indent 46proto_load="YES" 47.Ed 48.Pp 49To have the driver attach to a device instead of its regular driver, 50mention it in the list of devices assigned to the following loader variable: 51.Bd -ragged -offset indent 52hw.proto.attach="desc[,desc]" 53.Ed 54.\" 55.Sh DESCRIPTION 56The 57.Nm 58device driver attaches to PCI or ISA devices when no other device drivers 59are present for those devices and it creates device special files for all 60resources associated with the device. 61The driver itself has no knowledge of the device it attaches to. 62Programs can open these device special files and perform register-level 63reads and writes. 64As such, the 65.Nm 66device driver is nothing but a conduit or gateway between user space 67programs and the hardware device. 68.Pp 69Examples for why this is useful include hardware diagnostics and prototyping. 70In both these use cases, it is far more convenient to develop and run the 71logic in user space. 72Especially hardware diagnostics requires a somewhat user-friendly interface 73and adequate reporting. 74Neither is done easily as kernel code. 75.Ss I/O port resources 76Device special files created for I/O port resources allow 77.Xr lseek 2 , 78.Xr read 2 , 79.Xr write 2 80and 81.Xr ioctl 2 82operations to be performed on them. 83The 84.Xr read 2 85and 86.Xr write 2 87system calls are used to perform input and output (resp.) on the port. 88The amount of data that can be read or written at any single time is either 891, 2 or 4 bytes. 90While the 91.Nm 92driver does not prevent reading or writing 8 bytes at a time for some 93architectures, it should not be assumed that such actually produces 94correct results. 95The 96.Xr lseek 2 97system call is used to select the port number, relative to the I/O port 98region being represented by the device special file. 99If, for example, the device special file corresponds to an I/O port region 100from 0x3f8 to 0x3ff inclusive, then an offset of 4 given to lseek with a 101whence value of SEEK_SET will target port 0x3fc on the next read or write 102operation. 103The 104.Xr ioctl 2 105system call can be used for the 106.Dv PROTO_IOC_REGION 107request. 108This ioctl request returns the extend of the resource covered by this 109device special file. 110The extend is returned in the following structure: 111.Bd -literal 112struct proto_ioc_region { 113 unsigned long address; 114 unsigned long size; 115}; 116.Ed 117.Ss Memory mapped I/O resources 118The device special files created for memory mapped I/O resources behave 119in the same way as those created for I/O port resources. 120Additionally, device special files for memory mapped I/O resources allow 121the memory to be mapped into the process' address space using 122.Xr mmap 2 . 123Reads and writes to the memory address returned by 124.Xr mmap 2 125go directly to the hardware. 126As such the use of 127.Xr read 2 128and 129.Xr write 2 130can be avoided, reducing the access overhead significantly. 131Alignment and access width constraints put forth by the underlying device 132apply. 133Also, make sure the compiler does not optimize memory accesses away or has 134them coalesced into bigger accesses. 135.Ss DMA pseudo resource 136A device special file named 137.Pa busdma 138is created for the purpose of doing DMA. 139It only supports 140.Xr ioctl 2 141and only for the 142.Dv PROTO_IOC_BUSDMA 143request. 144This device special file does not support 145.Xr read 2 146nor 147.Xr write 2 . 148The 149.Dv PROTO_IOC_BUSDMA 150request has an argument that is both in and out and is defined as 151follows: 152.Bd -literal 153struct proto_ioc_busdma { 154 unsigned int request; 155 unsigned long key; 156 union { 157 struct { 158 unsigned long align; 159 unsigned long bndry; 160 unsigned long maxaddr; 161 unsigned long maxsz; 162 unsigned long maxsegsz; 163 unsigned int nsegs; 164 unsigned int datarate; 165 unsigned int flags; 166 } tag; 167 struct { 168 unsigned long tag; 169 unsigned int flags; 170 unsigned long virt_addr; 171 unsigned long virt_size; 172 unsigned int phys_nsegs; 173 unsigned long phys_addr; 174 unsigned long bus_addr; 175 unsigned int bus_nsegs; 176 } md; 177 struct { 178 unsigned int op; 179 unsigned long base; 180 unsigned long size; 181 } sync; 182 } u; 183 unsigned long result; 184}; 185.Ed 186The 187.Va request 188field is used to specify which DMA operation is to be performed. 189The 190.Va key 191field is used to specify which object the operation applies to. 192An object is either a tag or a memory descriptor (md). 193The following DMA operations are defined: 194.Bl -tag -width XXXX 195.It PROTO_IOC_BUSDMA_TAG_CREATE 196Create a root tag. 197The 198.Va result 199field is set on output with the key of the DMA tag. 200The tag is created with the constraints given by the 201.Va tag 202sub-structure. 203These constraints correspond roughly to those that can be given to the 204.Xr bus_dma_tag_create 9 205function. 206.It PROTO_IOC_BUSDMA_TAG_DERIVE 207Create a derived tag. 208The 209.Va key 210field is used to identify the parent tag from which to derive the new tag. 211The key of the derived tag is returned in the 212.Va result 213field. 214The derived tag combines the constraints of the parent tag with those 215given by the 216.Va tag 217sub-structure. 218The combined constraints are written back to the 219.Va tag 220sub-structure on return. 221.It PROTO_IOC_BUSDMA_TAG_DESTROY 222Destroy a root or derived tag previously created. 223The 224.Va key 225field specifies the tag to destroy. 226A tag can only be destroyed when not referenced anymore. 227This means that derived tags that have this tag as a parent and memory 228descriptors created from this tag must be destroyed first. 229.It PROTO_IOC_BUSDMA_MEM_ALLOC 230Allocate memory that satisfies the constraints put forth by the tag 231given in the 232.Va tag 233field of the 234.Va md 235sub-structure. 236The key of the memory descriptor for this memory is returned in the 237.Va result 238field. 239The 240.Va md 241sub-structure is filled on return with details of the allocation. 242The kernel virtual address and the size of the allocated memory are returned 243in the 244.Va virt_addr 245and 246.Va virt_size 247fields. 248The number of contigous physical memory segments and the address of the first 249segment are returned in the 250.Va phys_nsegs 251and 252.Va phys_addr 253fields. 254Allocated memory is automatically loaded and thus mapped into bus space. 255The number of bus segments and the address of the first segment are returned 256in the 257.Va bus_nsegs 258and 259.Va bus_addr 260fields. 261The behaviour of this operation banks heavily on how 262.Xr bus_dmamem_alloc 9 263is implemented, which means that memory is currently always allocated as a 264single contigous region of physical memory. 265In practice this also tends to give a single contigous region in bus space. 266This may change over time. 267.It PROTO_IOC_BUSDMA_MEM_FREE 268Free previously allocated memory and destroy the memory descriptor. 269The 270.Nm 271driver is not in a position to track whether the memory has been mapped in 272the process' address space, so the application is responsible for unmapping 273the memory before it is freed. 274The 275.Nm 276driver also cannot protect against the hardware writing to or reading from 277the memory, even after it has been freed. 278When the memory is reused for other purposes it can be corrupted or cause 279the hardware to behave in unpredictable ways when DMA has not stopped 280completely before freeing. 281.It PROTO_IOC_BUSDMA_MD_CREATE 282Create an empty memory descriptor with the tag specified in the 283.Va tag 284field of the 285.Va md 286sub-structure. 287The key of the memory descriptor is returned in the 288.Va result 289field. 290.It PROTO_IOC_BUSDMA_MD_DESTROY 291Destroy the previously created memory descriptor specified by the 292.Va key 293field. 294When the memory descriptor is still loaded, it is unloaded first. 295.It PROTO_IOC_BUSDMA_MD_LOAD 296Load a contigous region of memory in the memory descriptor specified by the 297.Va key 298field. 299The size and address in the process' virtual address space are specified 300by the 301.Va virt_size 302and 303.Va virt_addr 304fields. 305On return, the 306.Va md 307sub-structure contains the result of the operation. 308The number of physical segments and the address of the first segment is 309returned in the 310.Va phys_nsegs 311and 312.Va phys_addr 313fields. 314The number of bus space segments and the address of the first segment in 315bus space is returned in the 316.Va bus_nsegs 317and 318.Va bus_addr 319fields. 320.It PROTO_IOC_BUSDMA_MD_UNLOAD 321Unload the memory descriptor specified by the 322.Va key 323field. 324.It PROTO_IOC_BUSDMA_SYNC 325Guarantee that all hardware components have a coherent view of the memory 326tracked by the memory descriptor, specified by the 327.Va key 328field. 329A sub-section of the memory can be targeted by specifying the relative 330offset and size of the memory to make coherent. 331The offset and size are given by the 332.Va base 333and 334.Va size 335fields of the 336.Va sync 337sub-structure. 338The 339.Va op 340field holds the sync operation to be performed. 341This is similar to the 342.Xr bus_dmamap_sync 9 343function. 344.El 345.Ss PCI configuration space 346Access to PCI configuration space is possible through the 347.Pa pcicfg 348device special file. 349The device special file supports 350.Xr lseek 2 , 351.Xr read 2 352and 353.Xr write 2 . 354Usage is the asme as for I/O port resources. 355.Sh FILES 356All device special files corresponding to a PCI device are located under 357.Pa /dev/proto/pci<d>:<b>:<s>:<f> 358with 359.Pa pci<d>:<b>:<s>:<f> 360representing the location of the PCI device in the PCI hierarchy. 361A PCI location includes: 362.Pp 363.Bl -tag -width XXXXXX -compact -offset indent 364.It <d> 365The PCI domain number 366.It <b> 367The PCI bus number 368.It <s> 369The PCI slot or device number 370.It <f> 371The PCI function number 372.El 373.Pp 374Every PCI device has a device special file called 375.Pa pcicfg . 376This device special file gives access to the PCI configuration space. 377A device special file called 378.Pa busdma 379is also created. 380This device special file provides the interfaces needed for doing DMA. 381For each valid base address register (BAR), a device special file is created 382that contains the BAR offset and the resource type. 383A resource type can be either 384.Pa io 385or 386.Pa mem 387representing I/O port or memory mapped I/O space (resp.) 388.Pp 389ISA devices do not have a location. 390Instead, 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