Provided by: freebsd-manpages_12.2-1_all bug

NAME

       proto — Generic prototyping and diagnostics driver

SYNOPSIS

       To compile this driver into the kernel, place the following line in your kernel configuration file:

             device proto

       Alternatively, to load the driver as a module at boot time, place the following line in loader.conf(5):

             proto_load="YES"

       To  have  the  driver attach to a device instead of its regular driver, mention it in the list of devices
       assigned to the following loader variable:

             hw.proto.attach="desc[,desc]"

DESCRIPTION

       The proto device driver attaches to PCI or ISA devices when no other device drivers are present for those
       devices and it creates device special files for all resources associated with  the  device.   The  driver
       itself  has  no knowledge of the device it attaches to.  Programs can open these device special files and
       perform register-level reads and writes.  As such, the proto device driver is nothing but  a  conduit  or
       gateway between user space programs and the hardware device.

       Examples  for  why this is useful include hardware diagnostics and prototyping.  In both these use cases,
       it is far more convenient to develop and run the logic in user space.   Especially  hardware  diagnostics
       requires  a  somewhat  user-friendly  interface and adequate reporting.  Neither is done easily as kernel
       code.

   I/O port resources
       Device special files created for I/O port  resources  allow  lseek(2),  read(2),  write(2)  and  ioctl(2)
       operations  to be performed on them.  The read(2) and write(2) system calls are used to perform input and
       output (resp.) on the port.  The amount of data that can be read or written at any single time is  either
       1,  2  or 4 bytes.  While the proto driver does not prevent reading or writing 8 bytes at a time for some
       architectures, it should not be assumed that such actually produces correct results.  The lseek(2) system
       call is used to select the port number, relative to the I/O port region being represented by  the  device
       special  file.   If, for example, the device special file corresponds to an I/O port region from 0x3f8 to
       0x3ff inclusive, then an offset of 4 given to lseek with a whence value  of  SEEK_SET  will  target  port
       0x3fc on the next read or write operation.  The ioctl(2) system call can be used for the PROTO_IOC_REGION
       request.  This ioctl request returns the extend of the resource covered by this device special file.  The
       extend is returned in the following structure:

       struct proto_ioc_region {
               unsigned long   address;
               unsigned long   size;
       };

   Memory mapped I/O resources
       The  device special files created for memory mapped I/O resources behave in the same way as those created
       for I/O port resources.  Additionally, device special files for memory mapped  I/O  resources  allow  the
       memory  to  be  mapped  into  the  process'  address space using mmap(2).  Reads and writes to the memory
       address returned by mmap(2) go directly to the hardware.  As such the use of read(2) and write(2) can  be
       avoided, reducing the access overhead significantly.  Alignment and access width constraints put forth by
       the  underlying device apply.  Also, make sure the compiler does not optimize memory accesses away or has
       them coalesced into bigger accesses.

   DMA pseudo resource
       A device special file named busdma is created for the purpose of doing DMA.  It  only  supports  ioctl(2)
       and  only  for  the  PROTO_IOC_BUSDMA  request.   This  device  special file does not support read(2) nor
       write(2).  The PROTO_IOC_BUSDMA request has an argument that is  both  in  and  out  and  is  defined  as
       follows:

       struct proto_ioc_busdma {
               unsigned int    request;
               unsigned long   key;
               union {
                       struct {
                               unsigned long   align;
                               unsigned long   bndry;
                               unsigned long   maxaddr;
                               unsigned long   maxsz;
                               unsigned long   maxsegsz;
                               unsigned int    nsegs;
                               unsigned int    datarate;
                               unsigned int    flags;
                       } tag;
                       struct {
                               unsigned long   tag;
                               unsigned int    flags;
                               unsigned long   virt_addr;
                               unsigned long   virt_size;
                               unsigned int    phys_nsegs;
                               unsigned long   phys_addr;
                               unsigned long   bus_addr;
                               unsigned int    bus_nsegs;
                       } md;
                       struct {
                               unsigned int    op;
                               unsigned long   base;
                               unsigned long   size;
                       } sync;
               } u;
               unsigned long   result;
       };
       The  request  field  is used to specify which DMA operation is to be performed.  The key field is used to
       specify which object the operation applies to.  An object is either a tag or a  memory  descriptor  (md).
       The following DMA operations are defined:

       PROTO_IOC_BUSDMA_TAG_CREATE
             Create  a  root  tag.   The  result field is set on output with the key of the DMA tag.  The tag is
             created with the constraints given by the tag sub-structure.  These constraints correspond  roughly
             to those that can be given to the bus_dma_tag_create(9) function.

       PROTO_IOC_BUSDMA_TAG_DERIVE
             Create  a  derived  tag.  The key field is used to identify the parent tag from which to derive the
             new tag.  The key of the derived tag is returned in the result field.  The derived tag combines the
             constraints of the parent tag with those given by the tag sub-structure.  The combined  constraints
             are written back to the tag sub-structure on return.

       PROTO_IOC_BUSDMA_TAG_DESTROY
             Destroy  a  root or derived tag previously created.  The key field specifies the tag to destroy.  A
             tag can only be destroyed when not referenced anymore.  This means that derived tags that have this
             tag as a parent and memory descriptors created from this tag must be destroyed first.

       PROTO_IOC_BUSDMA_MEM_ALLOC
             Allocate memory that satisfies the constraints put forth by the tag given in the tag field  of  the
             md  sub-structure.   The  key  of  the  memory descriptor for this memory is returned in the result
             field.  The md sub-structure is filled on return  with  details  of  the  allocation.   The  kernel
             virtual  address  and  the size of the allocated memory are returned in the virt_addr and virt_size
             fields.  The number of contigous physical memory segments and the address of the first segment  are
             returned in the phys_nsegs and phys_addr fields.  Allocated memory is automatically loaded and thus
             mapped  into  bus  space.   The  number  of  bus  segments and the address of the first segment are
             returned in the bus_nsegs and bus_addr fields.  The behaviour of this operation  banks  heavily  on
             how  bus_dmamem_alloc(9) is implemented, which means that memory is currently always allocated as a
             single contigous region of physical memory.  In practice this also tends to give a single contigous
             region in bus space.  This may change over time.

       PROTO_IOC_BUSDMA_MEM_FREE
             Free previously allocated memory and destroy the memory desciptor.  The proto driver is  not  in  a
             position  to  track  whether  the  memory  has  been  mapped  in the process' address space, so the
             application is responsible for unmapping the memory before it is  freed.   The  proto  driver  also
             cannot  protect  against the hardware writing to or reading from the memory, even after it has been
             freed.  When the memory is reused for other purposes it can be corrupted or cause the  hardware  to
             behave in unpredictable ways when DMA has not stopped completely before freeing.

       PROTO_IOC_BUSDMA_MD_CREATE
             Create  an empty memory descriptor with the tag specified in the tag field of the md sub-structure.
             The key of the memory descriptor is returned in the result field.

       PROTO_IOC_BUSDMA_MD_DESTROY
             Destroy the previously created memory descriptor specified by  the  key  field.   When  the  memory
             descriptor is still loaded, it is unloaded first.

       PROTO_IOC_BUSDMA_MD_LOAD
             Load  a  contigous  region of memory in the memory descriptor specified by the key field.  The size
             and address in the process' virtual address space are specified  by  the  virt_size  and  virt_addr
             fields.   On  return,  the  md  sub-structure  contains the result of the operation.  The number of
             physical segments and the address of the first segment is returned in the phys_nsegs and  phys_addr
             fields.   The  number  of  bus  space segments and the address of the first segment in bus space is
             returned in the bus_nsegs and bus_addr fields.

       PROTO_IOC_BUSDMA_MD_UNLOAD
             Unload the memory descriptor specified by the key field.

       PROTO_IOC_BUSDMA_SYNC
             Guarantee that all hardware components have a coherent view of the memory  tracked  by  the  memory
             descriptor,  specified by the key field.  A sub-section of the memory can be targeted by specifying
             the relative offset and size of the memory to make coherent.  The offset and size are given by  the
             base  and  size  fields  of  the  sync  sub-structure.  The op field holds the sync operation to be
             performed.  This is similar to the bus_dmamap_sync(9) function.

   PCI configuration space
       Access to PCI configuration space is possible through the pcicfg device special file.  The device special
       file supports lseek(2), read(2) and write(2).  Usage is the asme as for I/O port resources.

FILES

       All device special files corresponding to a PCI device are  located  under  /dev/proto/pci<d>:<b>:<s>:<f>
       with pci<d>:<b>:<s>:<f> representing the location of the PCI device in the PCI hierarchy.  A PCI location
       includes:

             <d>     The PCI domain number
             <b>     The PCI bus number
             <s>     The PCI slot or device number
             <f>     The PCI function number

       Every  PCI  device has a device special file called pcicfg.  This device special file gives access to the
       PCI configuration space.  A device special file called busdma is also created.  This device special  file
       provides  the  interfaces  needed  for  doing  DMA.  For each valid base address register (BAR), a device
       special file is created that contains the BAR offset and the resource  type.   A  resource  type  can  be
       either io or mem representing I/O port or memory mapped I/O space (resp.)

       ISA  devices do not have a location.  Instead, they are identified by the first I/O port address or first
       memory mapped I/O address.  Consequently, all device special files corresponding to  an  ISA  device  are
       located  under /dev/proto/isa:<addr> with addr the address in hexadecimal notation.  For each I/O port or
       memory mapped I/O address, a device special file is created that  contains  the  resource  identification
       used  by  the  kernel  and the resource type.  The resource type can be either io or mem representing I/O
       port or memory mapped I/O space (resp.)  When the device has a DMA  channel  assigned  to  it,  a  device
       special  file  with the name busdma is created as well.  This device special file provides the interfaces
       needed for doing DMA.

       If the ISA device is not a Plug-and-Play device nor present in the ACPI device tree,  it  must  have  the
       appropriate hints so that the kernel can reserve the resources for it.

EXAMPLES

       A  single  function  PCI  device  in  domain 0, on bus 1, in slot 2 and having a single memory mapped I/O
       region will have the following device special files:

             /dev/proto/pci0:1:2:0/10.mem
             /dev/proto/pci0:1:2:0/pcicfg

       A legacy floppy controller will have the following device files:

             /dev/proto/isa:0x3f0/00.io
             /dev/proto/isa:0x3f0/01.io
             /dev/proto/isa:0x3f0/busdma

SEE ALSO

       ioctl(2),   lseek(2),   mmap(2),   read(2),    write(2),    bus_dma_tag_create(9),    bus_dmamap_sync(9),
       bus_dmamem_alloc(9)

AUTHORS

       The proto device driver and this manual page were written by Marcel Moolenaar <marcel@xcllnt.net>.

SECURITY CONSIDERATIONS

       Because  programs have direct access to the hardware, the proto driver is inherently insecure.  It is not
       advisable to use this driver on a production machine.

MISSING FUNCTIONALITY

       The proto driver does not fully support memory descriptors that need multiple physical memory segments or
       multiple bus space segments.  At the very least, an operation is needed on the DMA  pseudo  resource  for
       the application to obtain all segments.

       The  proto  driver  does  not  yet  support interrupts.  Since interrupts cannot be handled by the driver
       itself, they must be converted into signals  and  delivered  to  the  program  that  has  registered  for
       interrupts.   A  satisfactory  mechanism  for  keeping the interrupt masked during the signal handling is
       still being worked out.

       DMA support for devices other than busmaster devices is not present yet.  The details of how a program is
       to interact with the DMA controller still need to be fleshed out.

Debian                                           August 7, 2015                                         PROTO(4)