devmap(9E)




NAME

     devmap - validate and translate virtual mapping  for  memory
     mapped device


SYNOPSIS

     #include <sys/ddi.h>
     #include <sys/sunddi.h>

     int prefixdevmap(dev_t dev,  devmap_cookie_t  dhp,  offset_t
     off, size_t len, size_t *maplen, uint_t model);


INTERFACE LEVEL

     Solaris DDI specific (Solaris DDI).


PARAMETERS

      dev  Device whose memory is to be mapped.

     dhp   An opaque mapping  handle  that  the  system  uses  to
           describe the mapping.

     off   User offset within the logical device memory at  which
           the mapping begins.

     len   Length (in bytes) of the mapping to be mapped.

     maplen
           Pointer to length (in bytes) of mapping that has  been
           validated. maplen is less than or equal to  len.

     model The data model type of the current thread.


DESCRIPTION

     devmap() is a required entry  point  for  character  drivers
     supporting memory-mapped devices if the drivers use the dev-
     map framework to set up the mapping. A memory mapped  device
     has  memory   that  can  be  mapped into a process's address
     space. The mmap(2) system call, when applied to a  character
     special  file,  allows  this device memory to be mapped into
     user space for direct access by the user applications.

     As a result of a mmap(2) system call, the system  calls  the
     devmap()  entry point during the mapping setup when D_DEVMAP
     is set in the cb_flag field of the cb_ops(9S) structure, and
     any of the following conditions apply:

        o  ddi_devmap_segmap(9F) is used as the segmap(9E)  entry
           point.

        o  segmap(9E) entry point is set to NULL.

        o  mmap(9E) entry point is set to NULL.

     Otherwise EINVAL will be returned to mmap(2).

     Device drivers should use devmap() to validate the user map-
     pings  to the device, to translate the logical offset,  off,
     to the  corresponding  physical  offset  within  the  device
     address  space,  and  to pass the mapping information to the
     system for setting up the mapping.

     dhp is a device mapping  handle  that  the  system  uses  to
     describe  a mapping to a memory that is either contiguous in
     physical address space or in kernel virtual  address  space.
     The  system  may  create  multiple  mapping   handles in one
     mmap(2) system call (for example, if  the  mapping  contains
     multiple physically discontiguous memory regions).

     model returns the C Language Type Model  which  the  current
     thread expects.  It is set to DDI_MODEL_ILP32 if the current
     thread expects 32-bit ( ILP32) semantics, or  DDI_MODEL_LP64
     if  the  current  thread  expects  64-bit ( LP64) semantics.
     model is used in combination with ddi_model_convert_from(9F)
     to  determine whether there is a data model mismatch between
     the current thread and the device driver. The device  driver
     might  have  to  adjust  the shape of data structures before
     exporting them to a user thread which supports  a  different
     data model.

     devmap() should return EINVAL if the logical offset, off, is
     out  of  the  range of memory exported by the device to user
     space. If off + len exceeds  the  range  of  the  contiguous
     memory,  devmap()  should return the length from  off to the
     end of the contiguous memory region. The system will repeat-
     edly  call  devmap()  until  the  original mapping length is
     satisfied. The driver sets *maplen to the  validated  length
     which must be either less than or equal to len.

     The devmap() entry point must initialize the mapping parame-
     ters  before  passing  them  to  the  system  through either
     devmap_devmem_setup(9F) (if the memory being mapped is  dev-
     ice  memory)  or  devmap_umem_setup(9F) (if the memory being
     mapped is kernel memory). The devmap() entry point  initial-
     izes  the mapping parameters by mapping the control callback
     structure (see devmap_callback_ctl(9S)), the  device  access
     attributes,  mapping length, maximum protection possible for
     the   mapping,   and   optional    mapping    flags.     See
     devmap_devmem_setup(9F)    and   devmap_umem_setup(9F)   for
     further information on initializing the mapping parameters.

     The system will copy  the  driver's  devmap_callback_ctl(9S)
     data  into  its private memory so the drivers do not need to
     keep  the  data  structure  after  the  return  from  either
     devmap_devmem_setup(9F) or devmap_umem_setup(9F).

     For device mappings, the system establishes the  mapping  to
     the  physical address that corresponds to off by passing the
     register number and the offset within the  register  address
     space to  devmap_devmem_setup(9F).

     For kernel memory mapping, the system selects a user virtual
     address that is aligned with the kernel address being mapped
     for cache coherence.


RETURN VALUES

      0    Successful completion.

     Non-zero
           An error occurred.


EXAMPLES

     Example 1: Implementing the devmap() Entry Point

     The following is an example of the  implementation  for  the
     devmap()  entry  point.  For mapping device memory, devmap()
     calls  devmap_devmem_setup(9F)  with  the  register  number,
     rnumber,  and the offset within the register, roff. For map-
     ping kernel memory, the driver must first allocate the  ker-
     nel   memory   using   ddi_umem_alloc(9F).    For   example,
     ddi_umem_alloc(9F) can be called in the attach(9E)  routine.
     The  resulting  kernel memory cookie is stored in the driver
     soft state structure, which is accessible from the  devmap()
     entry  point.  See  ddi_soft_state(9F).  devmap() passes the
     cookie  obtained  from  ddi_umem_alloc(9F)  and  the  offset
     within the allocated kernel memory to devmap_umem_setup(9F).
     The corresponding  ddi_umem_free(9F)  can  be  made  in  the
     detach(9E) routine to free up the kernel memory.

     ...
     #define MAPPING_SIZE 0x2000        /* size of the mapping */
     #define MAPPING_START 0x70000000   /* logical offset at beginning
                                           of the mapping */
     static
     struct devmap_callback_ctl xxmap_ops = {
             DEVMAP_OPS_REV,                /* devmap_ops version number */
             xxmap_map,                     /* devmap_ops map routine */
             xxmap_access,                  /* devmap_ops access routine */
             xxmap_dup,                     /* devmap_ops dup routine */
             xxmap_unmap,                   /* devmap_ops unmap routine  */
     };

     static int
     xxdevmap(dev_t dev, devmap_cookie_t dhp, offset_t off, size_t len,
        size_t *maplen, uint_t model)
     {
        int    instance;
        struct xxstate *xsp;
        struct ddi_device_acc_attr *endian_attr;
        struct devmap_callback_ctl *callbackops = NULL;
        ddi_umem_cookie_t cookie;
        dev_info_t *dip;
        offset_t   roff;
        offset_t   koff;
        uint_t rnumber;
        uint_t maxprot;
        uint_t flags = 0;
        size_t length;
        int    err;

        /* get device soft state */
        instance = getminor(dev);
        xsp = ddi_get_soft_state(statep, instance);
        if (xsp == NULL)
           return (-1);

        dip = xsp->dip;
        /* check for a valid offset */
        if ( off is invalid )
           return (-1);
        /* check if len is within the range of contiguous memory */
        if ( (off + len) is contiguous.)
            length = len;
        else
            length = MAPPING_START + MAPPING_SIZE - off;

        /* device access attributes */
        endian_attr = xsp->endian_attr;

        if (  off is referring to a device memory.  ) {
                                      /* assign register related parameters */
           rnumber = XXX;             /* index to register set at off */
           roff = XXX;                /* offset of rnumber at local bus */
           callbackops = &xxmap_ops;  /* do all callbacks for this mapping */
           maxprot = PROT_ALL;        /* allowing all access */
           if ((err = devmap_devmem_setup(dhp, dip, callbackops, rnumber, roff,
                    length, maxprot, flags, endian_attr)) < 0)

               return (err);

        } else if ( off is referring to a kernel memory.) {
           cookie = xsp->cookie;      /* cookie is obtained from
                                         ddi_umem_alloc(9F) */
           koff = XXX;                /* offset within the kernel memory. */
           callbackops = NULL;        /* don't do callback for this mapping */
           maxprot = PROT_ALL;        /* allowing all access */
           if ((err = devmap_umem_setup(dhp, dip, callbackops, cookie, koff,
                    length, maxprot, flags, endian_attr)) < 0)

              return (err);
       }

              *maplen = length;
         return (0);
     }


SEE ALSO

     mmap(2),  attach(9E),  detach(9E),   mmap(9E),   segmap(9E),
     ddi_devmap_segmap(9F),           ddi_model_convert_from(9F),
     ddi_soft_state(9F),  ddi_umem_alloc(9F),  ddi_umem_free(9F),
     devmap_devmem_setup(9F),                   devmap_setup(9F),
     devmap_umem_setup(9F), cb_ops(9S), devmap_callback_ctl(9S)

     Writing Device Drivers


Man(1) output converted with man2html