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. 112The extend is returned in the following structure: 113.Bd -literal 114struct proto_ioc_region { 115 unsigned long address; 116 unsigned long size; 117}; 118.Ed 119.Ss Memory mapped I/O resources 120The device special files created for memory mapped I/O resources behave 121in the same way as those created for I/O port resources. 122Additionally, device special files for memory mapped I/O resources allow 123the memory to be mapped into the process' address space using 124.Xr mmap 2 . 125Reads and writes to the memory address returned by 126.Xr mmap 2 127go directly to the hardware. 128As such the use of 129.Xr read 2 130and 131.Xr write 2 132can be avoided, reducing the access overhead significantly. 133Alignment and access width constraints put forth by the underlying device 134apply. 135Also, make sure the compiler does not optimize memory accesses away or has 136them coalesced into bigger accesses. 137.Ss DMA pseudo resource 138A device special file named 139.Pa busdma 140is created for the purpose of doing DMA. 141It only supports 142.Xr ioctl 2 143and only for the 144.Dv PROTO_IOC_BUSDMA 145request. 146This device special file does not support 147.Xr read 2 148nor 149.Xr write 2 . 150The 151.Dv PROTO_IOC_BUSDMA 152request has an argument that is both in and out and is defined as 153follows: 154.Bd -literal 155struct proto_ioc_busdma { 156 unsigned int request; 157 unsigned long key; 158 union { 159 struct { 160 unsigned long align; 161 unsigned long bndry; 162 unsigned long maxaddr; 163 unsigned long maxsz; 164 unsigned long maxsegsz; 165 unsigned int nsegs; 166 unsigned int datarate; 167 unsigned int flags; 168 } tag; 169 struct { 170 unsigned long tag; 171 unsigned int flags; 172 unsigned long virt_addr; 173 unsigned long virt_size; 174 unsigned int phys_nsegs; 175 unsigned long phys_addr; 176 unsigned long bus_addr; 177 unsigned int bus_nsegs; 178 } md; 179 struct { 180 unsigned int op; 181 unsigned long base; 182 unsigned long size; 183 } sync; 184 } u; 185 unsigned long result; 186}; 187.Ed 188The 189.Va request 190field is used to specify which DMA operation is to be performed. 191The 192.Va key 193field is used to specify which object the operation applies to. 194An object is either a tag or a memory descriptor (md). 195The following DMA operations are defined: 196.Bl -tag -width XXXX 197.It PROTO_IOC_BUSDMA_TAG_CREATE 198Create a root tag. 199The 200.Va result 201field is set on output with the key of the DMA tag. 202The tag is created with the constraints given by the 203.Va tag 204sub-structure. 205These constraints correspond roughly to those that can be given to the 206.Xr bus_dma_tag_create 9 207function. 208.It PROTO_IOC_BUSDMA_TAG_DERIVE 209Create a derived tag. 210The 211.Va key 212field is used to identify the parent tag from which to derive the new tag. 213The key of the derived tag is returned in the 214.Va result 215field. 216The derived tag combines the constraints of the parent tag with those 217given by the 218.Va tag 219sub-structure. 220The combined constraints are written back to the 221.Va tag 222sub-structure on return. 223.It PROTO_IOC_BUSDMA_TAG_DESTROY 224Destroy a root or derived tag previously created. 225The 226.Va key 227field specifies the tag to destroy. 228A tag can only be destroyed when not referenced anymore. 229This means that derived tags that have this tag as a parent and memory 230descriptors created from this tag must be destroyed first. 231.It PROTO_IOC_BUSDMA_MEM_ALLOC 232Allocate memory that satisfies the constraints put forth by the tag 233given in the 234.Va tag 235field of the 236.Va md 237sub-structure. 238The key of the memory descriptor for this memory is returned in the 239.Va result 240field. 241The 242.Va md 243sub-structure is filled on return with details of the allocation. 244The kernel virtual address and the size of the allocated memory are returned 245in the 246.Va virt_addr 247and 248.Va virt_size 249fields. 250The number of contigous physical memory segments and the address of the first 251segment are returned in the 252.Va phys_nsegs 253and 254.Va phys_addr 255fields. 256Allocated memory is automatically loaded and thus mapped into bus space. 257The number of bus segments and the address of the first segment are returned 258in the 259.Va bus_nsegs 260and 261.Va bus_addr 262fields. 263The behaviour of this operation banks heavily on how 264.Xr bus_dmamem_alloc 9 265is implemented, which means that memory is currently always allocated as a 266single contigous region of physical memory. 267In practice this also tends to give a single contigous region in bus space. 268This may change over time. 269.It PROTO_IOC_BUSDMA_MEM_FREE 270Free previously allocated memory and destroy the memory descriptor. 271The 272.Nm 273driver is not in a position to track whether the memory has been mapped in 274the process' address space, so the application is responsible for unmapping 275the memory before it is freed. 276The 277.Nm 278driver also cannot protect against the hardware writing to or reading from 279the memory, even after it has been freed. 280When the memory is reused for other purposes it can be corrupted or cause 281the hardware to behave in unpredictable ways when DMA has not stopped 282completely before freeing. 283.It PROTO_IOC_BUSDMA_MD_CREATE 284Create an empty memory descriptor with the tag specified in the 285.Va tag 286field of the 287.Va md 288sub-structure. 289The key of the memory descriptor is returned in the 290.Va result 291field. 292.It PROTO_IOC_BUSDMA_MD_DESTROY 293Destroy the previously created memory descriptor specified by the 294.Va key 295field. 296When the memory descriptor is still loaded, it is unloaded first. 297.It PROTO_IOC_BUSDMA_MD_LOAD 298Load a contigous region of memory in the memory descriptor specified by the 299.Va key 300field. 301The size and address in the process' virtual address space are specified 302by the 303.Va virt_size 304and 305.Va virt_addr 306fields. 307On return, the 308.Va md 309sub-structure contains the result of the operation. 310The number of physical segments and the address of the first segment is 311returned in the 312.Va phys_nsegs 313and 314.Va phys_addr 315fields. 316The number of bus space segments and the address of the first segment in 317bus space is returned in the 318.Va bus_nsegs 319and 320.Va bus_addr 321fields. 322.It PROTO_IOC_BUSDMA_MD_UNLOAD 323Unload the memory descriptor specified by the 324.Va key 325field. 326.It PROTO_IOC_BUSDMA_SYNC 327Guarantee that all hardware components have a coherent view of the memory 328tracked by the memory descriptor, specified by the 329.Va key 330field. 331A sub-section of the memory can be targeted by specifying the relative 332offset and size of the memory to make coherent. 333The offset and size are given by the 334.Va base 335and 336.Va size 337fields of the 338.Va sync 339sub-structure. 340The 341.Va op 342field holds the sync operation to be performed. 343This is similar to the 344.Xr bus_dmamap_sync 9 345function. 346.El 347.Ss PCI configuration space 348Access to PCI configuration space is possible through the 349.Pa pcicfg 350device special file. 351The device special file supports 352.Xr lseek 2 , 353.Xr read 2 354and 355.Xr write 2 . 356Usage is the asme as for I/O port resources. 357.Sh FILES 358All device special files corresponding to a PCI device are located under 359.Pa /dev/proto/pci<d>:<b>:<s>:<f> 360with 361.Pa pci<d>:<b>:<s>:<f> 362representing the location of the PCI device in the PCI hierarchy. 363A PCI location includes: 364.Pp 365.Bl -tag -width XXXXXX -compact -offset indent 366.It <d> 367The PCI domain number 368.It <b> 369The PCI bus number 370.It <s> 371The PCI slot or device number 372.It <f> 373The PCI function number 374.El 375.Pp 376Every PCI device has a device special file called 377.Pa pcicfg . 378This device special file gives access to the PCI configuration space. 379A device special file called 380.Pa busdma 381is also created. 382This device special file provides the interfaces needed for doing DMA. 383For each valid base address register (BAR), a device special file is created 384that contains the BAR offset and the resource type. 385A resource type can be either 386.Pa io 387or 388.Pa mem 389representing I/O port or memory mapped I/O space (resp.) 390.Pp 391ISA devices do not have a location. 392Instead, they are identified by the 393first I/O port address or first memory mapped I/O address. 394Consequently, all device special files corresponding to an ISA device are 395located under 396.Pa /dev/proto/isa:<addr> 397with 398.Pa addr 399the address in hexadecimal notation. 400For each I/O port or memory mapped I/O address, a device special file is 401created that contains the resource identification used by the kernel and 402the resource type. 403The resource type can be either 404.Pa io 405or 406.Pa mem 407representing I/O port or memory mapped I/O space (resp.) 408When the device has a DMA channel assigned to it, a device special file 409with the name 410.Pa busdma 411is created as well. 412This device special file provides the interfaces needed for doing DMA. 413.Pp 414If the ISA device is not a Plug-and-Play device nor present in the ACPI 415device tree, it must have the appropriate hints so that the kernel can 416reserve the resources for it. 417.\" 418.Sh EXAMPLES 419A single function PCI device in domain 0, on bus 1, in slot 2 and having a 420single memory mapped I/O region will have the following device special files: 421.Pp 422.Bl -tag -width XXXXXX -compact -offset indent 423.It Pa /dev/proto/pci0:1:2:0/10.mem 424.It Pa /dev/proto/pci0:1:2:0/pcicfg 425.El 426.Pp 427A legacy floppy controller will have the following device files: 428.Pp 429.Bl -tag -width XXXXXX -compact -offset indent 430.It Pa /dev/proto/isa:0x3f0/00.io 431.It Pa /dev/proto/isa:0x3f0/01.io 432.It Pa /dev/proto/isa:0x3f0/busdma 433.El 434.\" 435.Sh SEE ALSO 436.Xr ioctl 2 , 437.Xr lseek 2 , 438.Xr mmap 2 , 439.Xr read 2 , 440.Xr write 2 , 441.Xr bus_dma_tag_create 9 , 442.Xr bus_dmamap_sync 9 , 443.Xr bus_dmamem_alloc 9 444.\" 445.Sh AUTHORS 446The 447.Nm 448device driver and this manual page were written by 449.An Marcel Moolenaar Aq Mt marcel@xcllnt.net . 450.Sh SECURITY CONSIDERATIONS 451Because programs have direct access to the hardware, the 452.Nm 453driver is inherently insecure. 454It is not advisable to use this driver on a production machine. 455.\" 456.Sh MISSING FUNCTIONALITY 457The 458.Nm 459driver does not fully support memory descriptors that need multiple 460physical memory segments or multiple bus space segments. 461At the very least, an operation is needed on the DMA pseudo resource 462for the application to obtain all segments. 463.Pp 464The 465.Nm 466driver does not yet support interrupts. 467Since interrupts cannot be handled by the driver itself, they must be 468converted into signals and delivered to the program that has registered 469for interrupts. 470A satisfactory mechanism for keeping the interrupt masked during the 471signal handling is still being worked out. 472.Pp 473DMA support for devices other than busmaster devices is not present yet. 474The details of how a program is to interact with the DMA controller still 475need to be fleshed out. 476