NAME

ddi_fm_init, ddi_fm_fini, ddi_fm_capable - initialize and get the FM
capabilities for a device instance

SYNOPSIS

#include <sys/ddifm.h>

void ddi_fm_init(dev_info_t *dip, int *fm_capability,
	ddi_iblock_cookie_t *ibcp);

void ddi_fm_fini(dev_info_t *dip);

int ddi_fm_capable(dev_info_t *dip, int *fm_capability);

PARAMETERS

dip		Pointer to dev_info structure
fm_capability	Fault Management capability bit mask
ibcp		Pointer to where interrupt block cookie should be returned

DESCRIPTION

A device driver may declare its fault management capabilities to the IO
Fault Management framework by calling ddi_fm_init(9F). ddi_fm_init()
allocates and initializes resources according to the bitwise-inclusive-OR
of the fault management capabilities described as follows and supported by
the driver's immediate nexus parent.

DDI_FM_NOT_CAPABLE	driver does not support any FMA features. This is the
			default value assigned to device drivers.

DDI_FM_EREPORT_CAPABLE	driver is responsible for and capable of generating
			FMA protocol error (ereports) events upon detection of
			an error condition.

DDI_FM_ACCCHK_CAPABLE	driver is responsible for and capable of checking for
			errors upon completion of one or more access IO
			transactions.

DDI_FM_DMACHK_CAPABLE	driver is responsible for and capable of checking for
			errors upon completion of one or more DMA IO
			transaction.

DDI_FM_ERRCB_CAPABLE	driver is capable of error handler callback
			registration.

If the parent nexus is not capable of supporting any one of the requested
capabilities, the associated bit will not be set and returned as such to the
driver. Before returning from ddi_fm_init(), the IO Fault Management framework
will create a set of fault management capability properties, fm-ereport-capable,
fm-errcb-capable, fm-accchk-capable and fm-dmachk-capable. The current
supported fault management capability levels are observable via prtconf(1M).

A driver that wishes to support administrative selection of fault management
capabilities may do so by exporting and setting a fault management capability
level properties to the values describe above in its driver.conf(4) file. The
fm-capable properties must be set and read prior to calling ddi_fm_init() with
the desired capability list.

fm-capable int The device driver is capable of performing the following fault
    management tasks.

ddi_fm_fini() cleans up resources allocated to support fault management for dip.

ddi_fm_capable() returns the capability bit mask currently set for dip.

CONTEXT

These functions may be called from kernel context in a driver attach(9F) or
detach(9F) entry point.




NAME

ddi_fm_handler_register, ddi_fm_handler_unregister - register or unregister an
error handling callback

SYNOPSIS

#include <sys/ddifm.h>

void ddi_fm_handler_register(dev_info_t *dip, ddi_err_func_t error_handler,
	void *impl_data);

void ddi_fm_handler_unregister(dev_info_t *dip);

PARAMETERS

dip		Pointer to dev_info structure
error_handler	Pointer to an error handler callback function
impl_data	Pointer to private data for use by the caller

DESCRIPTION

The ddi_fm_handler_register() routine registers an error handler callback
routine with the IO Fault Management framework. The error handler callback,
error_handler, is called to process error conditions detected by the system.
In addition to its device instance, dip, the error handler is called with a
pointer to a fault management error status structure, ddi_fm_error_t.

int (*ddi_err_func_t)(dev_info_t *dip, ddi_fm_error_t *error_status);

Driver error handling callbacks are passed a pointer to the device instance
registered for this callback and a data structure, containing common fault
management data and status for error handling.

The primary responsibilities of a device driver error handler include: check for
outstanding hardware or software errors, where possible isolate the device
that may have caused the errors and report errors that were detected. During the
invocation of an error handler, a device driver may need to quiesce or suspend
all IO activities to check for error conditions or status in hardware control
and status registers, outstanding IO transactions and access or DMA handles.
For each error detected, the driver must formulate an error report and post via
ddi_fm_ereport_post() for problem analysis by the Solaris Fault Manager fmd(1M).

For a PCI, PCI/X or PCI Express leaf device, the pci_ereport_post() function
is provided which carries out these responsibilities on behalf of the driver.
In many cases an error handler callback function of the following simple form 
will suffice:

        xxx_err_cb(dev_info_t *dip, ddi_fm_error_t *errp) {
                pci_ereport_post(dip, errp, NULL);
		return (errp->fme_status);
        }

In addition the driver may be able to carry out further device specific checks
within the error handler.

Error handlers may be called from kernel, interrupt or high-level interrupt
context. The interrupt block cookie returned from ddi_fm_init() should be used
to allocate and initialize any synchronization variables and locks which may be
used within the error handler callback function. Note that any such locks may
not be held by the driver when accessing device registers using functions
such as ddi_get8(9F), ddi_put8(9F), etc.

The data structure, ddi_fm_error_t, contains an FMA protocol
(format 1) ENA for the current error propagation chain, the status of the error
handler callback, an error expectation flag and any potential access or DMA
handles associated with an error detected by the parent nexus.

ddi_fm_handler_unregister() removes a previously registered error handling
callback for the device instance specified by the dip.

CONTEXT

ddi_fm_handler_register and ddi_fm_handler_unregister() must be called from
kernel context in a driver attach(9F) or detach(9F) entry point. The registered
error handler, error_handler, callback may called from kernel, interrupt or high
level interrupt context.

SEE ALSO

	ddi_fm_init(9F), ddi_fm_ereport_post(9F), pci_ereport_post(9F),
	ddi_fm_error(9S)



NAME

ddi_fm_error - IO error status structure

SYNOPSIS

#include <sys/ddifm.h>

DESCRIPTION

A ddi_fm_error_t structure contains common data necessary to IO error handling.
A pointer to a ddi_fm_error_t structure is passed to error handling callbacks
where it may then be used in a call to pci_ereport_post(). The same structure
is also returned to callers of ddi_fm_acc_err_get() and ddi_fm_dma_err_get().

STRUCTURE MEMBERS
	int			fme_version;
	uint64_t		fme_ena;
	int			fme_status;
	int			fme_flag;
	ddi_acc_handle_t	fme_acc_handle;
	ddi_dma_handle_t	fme_dma_handle;

fme_version -	Current version of ddi_fm_error_t. Valid values for version are:
		DDI_FME_VER0 and DDI_FME_VER1.

fme_ena -	The FMA event protocol Format 1 Error Numeric Association (ENA)
		for this error condition. 

fme_flag -	This field is set to DDI_FM_ERR_EXPECTED if the error was the
		result of a DDI_ACC_CAUTIOUS protected operation. In this case,
		fme_acc_handle will be valid and the driver should check for
		and report only errors not associated with the DDI_ACC_CAUTIOUS
		protected access operation. This field could also be set to 
		DDI_FM_ERR_POKE or DDI_FM_ERR_PEEK if the error was the result
		of a ddi_poke(9F) or ddi_peek(9F) operation. The driver should
		handle these in a similar way to DDI_FM_ERR_EXPECTED. Otherwise
		ddi_flag is set to DDI_FM_ERR_UNEXPECTED and the driver must
		perform the full range of error handling tasks.

fme_status -	The current status of a error handler callback or resource
		handle:

		DDI_FM_OK	no errors were detected.

		DDI_FM_FATAL	an error which is considered fatal to the
				operational state of the system was detected.

		DDI_FM_NONFATAL	an error which is not considered fatal to
				the operational state of the system was
				detected.

		DDI_FM_UNKNOWN	an error was detected, but the driver was
				unable to determine the impact of the error on
				the operational state of the system.

fme_acc_handle - Valid access handle associated with this error. May be returned
		 from pci_ereport_post()

fme_dma_handle - Valid DMA handle associated with this error. May be returned
		 from pci_ereport_post()

SEE ALSO
	ddi_fm_acc_err_get(9F), ddi_fm_dma_err_get(9F), pci_ereport_post(9F)
	ddi_fm_handler_register(9F)



NAME

ddi_fm_acc_err_get, ddi_fm_dma_err_get - get the error status for an access or
DMA handle

SYNOPSIS

#include <sys/ndifma.h>

void ddi_fm_acc_err_get(ddi_acc_handle_t acc_handle,
	ddi_fm_error_t *error_status, int version);

void ddi_fm_dma_err_get(ddi_dma_handle_t dma_handle,
	ddi_fm_error_t *error_status, int version);

PARAMETERS

acc_handle -	Data access handle obtained from a previous call to
		ddi_regs_map_setup(9F), ddi_dma_mem_alloc(9F), or
		similar function.

dma_handle -	DMA handle obtained from a previous call to
		ddi_dma_alloc_handle(9F) or one of its derivatives.

error_status -	Pointer to where error status for the access or DMA handle
		should be returned.

version -	Version number of ddi_fm_error_t. The driver should always
		set this to DDI_FME_VERSION.

DESCRIPTION

ddi_fm_dma_err_get() and ddi_fm_acc_err_get() return the error status for a DMA
or access handle respectively. If a fault has occurred which affects the
resource mapped by the supplied handle, the supplied error_status structure is
updated to reflect error information captured during error handling by a bus or
other device driver in IO data path.

If an error is indicated for an access handle, the driver may no longer be able
to access the mapped registers or memory using programmed I/O through that
handle. Typically, this might occur after the device has failed to respond to
an I/O access (for example, has incurred a bus error or timed out). The effect
of programmed I/O accesses made at the time of a fault is undefined. For
example, read accesses via ddi_get8(9F) may return random values, and write
accesses via ddi_put8(9F) may or may not have any effect. However it is
possible that the error may be transient, and the driver can therefore attempt
to recover by calling ddi_fm_acc_err_clear(), resetting the device to get it
back into a known state and then retrying any potentially failed transactions.

If a error is indicated for a DMA handle, it implies that an error has been
detected that has (or will) affect DMA transactions between the device and the
memory currently bound to the handle (or most recently bound, if the handle is
currently unbound). Possible causes include the failure of a component in the
DMA data path, or an attempt by the device to make an invalid DMA access. The
contents of any memory currently (or previously) bound to the handle should be
considered indeterminate. The driver may be able to continue by freeing back to
the system memory bound to the handle, resetting the device to get it back into
a known state and then retrying any potentially failed transactions.

If the driver is unable to recover it should change its operating state by
calling ddi_fm_service_impact() specifying DDI_SERVICE_LOST for the impacted
device instance. If the recovery and retry succeeded it should still call
ddi_fm_service_impact() but specifying DDI_SERVICE_UNAFFECTED.

CONTEXT

The ddi_fm_acc_err_get() and ddi_fm_dma_err_get) functions may be called from
user, kernel, or high-level interrupt context.

SEE ALSO
	ddi_fm_service_impact(9F), ddi_fm_acc_err_clear(9F),
	ddi_fm_error(9S)



NAME

ddi_fm_acc_err_clear, ddi_fm_dma_err_clear - clear the error status for an
access or DMA handle

SYNOPSIS

#include <sys/ndifma.h>

void ddi_fm_acc_err_clear(ddi_acc_handle_t acc_handle, int version);
void ddi_fm_dma_err_clear(ddi_dma_handle_t dma_handle, int version);

PARAMETERS

acc_handle      Data access handle obtained from a previous call to
                ddi_regs_map_setup(9F), ddi_dma_mem_alloc(9F), or
                similar function.

dma_handle      DMA handle obtained from a previous call to
                ddi_dma_alloc_handle(9F) or one of its derivatives.

version         Version number of ddi_fm_error_t

DESCRIPTION

ddi_fm_dma_err_clear() and ddi_fm_acc_err_clear()
clear the error status of a DMA or access handle respectively.

Once cleared, the driver is again able to access the
mapped registers or memory using programmed I/O through that
handle.


SEE ALSO
	ddi_fm_dma_err_get(9F), ddi_fm_acc_err_get(9F)



NAME

ddi_fm_ereport_post - post an FMA Protocol Error Report Event

SYNOPSIS

#include <sys/ddifm.h>

void ddi_fm_ereport_post(dev_info_t *dip, char *ereport_class, uint64_t ena,
int sflag, ... /* name-value pair args */)

PARAMETERS

dip		Pointer to dev_info structure

ereport_class	FMA Event Protocol error class

ena		Error Numeric Association

sflag		Determines whether caller can sleep for memory or
		other event resources.

DESCRIPTION

ddi_fm_ereport_post() causes an encoded fault management error report
name-value pair list to be queued for delivery to the Fault Manager daemon,
fmd(1M). sflag indicates whether or not the caller is willing to wait for
system memory and event channel resources to become available.

The following ereport_class strings are available for use by any leaf device
driver:

"device.inval_state" - A leaf driver discovers that the device is in an
	invalid/inconsistent state. For example, this may be because it detects
	that receive or send ring descriptor indices are corrupted, finds an
	invalid value in a register or detects a driver-to-device protocol
	violation.
 
"device.no_response" - A leaf driver times out waiting for a response from the
	device. For example when no confirmation is seen after
	resetting/enabling/disabling part of the device.

"device.stall" - A leaf driver determines that data transmission has stalled
	indefinitely.

"device.badint_limit" - A leaf device sends too many consecutive interrupts
	with no work to do.

"device.intern_corr"- A leaf device reports to the driver that it has itself
	detected an internal correctable error.

"device.intern_uncorr" - A leaf device reports to the driver that it has itself
	detected an internal uncorrectable error.

The ena indicates the Format 1 Error Numeric Association for this
error report. It may have already been initialized by another error detecting
software module (for example if ddi_fm_ereport_post() is called from
an error handler callback function, then the fme_ena field from the passed-in
ddi_fm_error argument should be used). Otherwise it should be set to 0 and will
be initialized by ddi_fm_ereport_post().

The name-value pair args variable argument list contains one or more
name, type, value pointer nvpair tuples for non-array data_type_t types or
one or more name, type, number of element, value pointer tuples
for data_type_t array types. There is one mandarory tuple to describe the
ereport version. This should contain the following values

name - FM_VERSION
type - DATA_TYPE_UINT8
value - FM_EREPORT_VERS0

Additonal nvpair tuples may describe error conditions for logging purposes,
but are not interpreted by the IO framework or fault manager. The end of the
argument list is specified by NULL.

CONTEXT

ddi_fm_ereport_post() may be called from user, kernel or high-level interrupt
context.


SEE ALSO

	ddi_fm_service_impact(9F)


NAME

ddi_fm_service_impact - report the impact of an error

SYNOPSIS

#include <sys/ddifm.h>

void ddi_fm_service_impact(dev_info_t *dip, int impact);

PARAMETERS

dip	Pointer to dev_info structure
impact	Impact of error

DESCRIPTION

The following service impact values are accepted by ddi_fm_service_impact():

DDI_SERVICE_LOST 	the service provided by the device is unavailable due
			to an error. The operational state of the device will
			transition to DEVI_DEVICE_DOWN.

DDI_SERVICE_DEGRADED 	the driver is unable to provide normal service, but can
			provide a partial or degraded level of service. The
			driver may have to make repeated attempts to perform an
			operation before it succeeds, or it may be running at
			less than its configured speed. A driver may use this
			value to indicate that an alternative device should be
			used if available, but that it can continue operation
			if no alternative exists. The operational state of the
			device will transition to DEVI_DEVICE_DEGRADED.

DDI_SERVICE_RESTORE 	the service provided by the device has been restored.
			The operational state of the device will transition to
			its pre-error condition state (i.e. DEVI_DEVICE_DOWN or
			DEVI_DEVICE_DEGRADED is removed).

DDI_SERVICE_UNAFFECTED  the service provided by the device was unaffected by
			the error.

CONTEXT

ddi_fm_service_impact() may be called from user, kernel or interrupt context.

SEE ALSO

	ddi_fm_ereport_post(9F), pci_ereport_post(9F)



NAME

pci_ereport_setup, pci_ereport_teardown, pci_ereport_post - Post error
reports for the generic PCI errors logged in the PCI Configuration Status
register.

SYNOPSIS

#include <sys/sunddi.h>

void pci_ereport_setup(dev_info_t *dip);

void pci_ereport_teardown(dev_info_t *dip);

void pci_ereport_post(dev_info_t *dip, ddi_fm_error_t *dep, uin16_t *status);

PARAMETERS

dip	Pointer to the device's dev_info structure.

dep	Pointer to DDI error status.

status	Pointer to status bit storage location.

DESCRIPTION
pci_ereport_setup() initializes support for error report generation and
sets up the resources for subsequent accesses to PCI, PCI/X or PCI Express
Configuration space.  The caller must have established a fault management
capability level of at least DDI_FM_EREPORT_CAPABLE with a previous call
to ddi_fm_init() for dip.

pci_ereport_teardown() releases any resources allocated and setup
by pci_ereport_setup() and associated with dip. 

pci_ereport_post() is called to scan for and post any PCI, PCI/X or PCI Express
Bus errors. For example on a PCI bus, the errors detected include:
        o Detected Parity Error
        o Master Data Parity Error
        o Target Abort
        o Master Abort
        o System Error
        o Discard Timeout

pci_ereport_post() must only be called from a driver's error handler callback
function (see ddi_fm_handler_register(9F)). The error_status argument to the
error handler callback function should be passed through as the dep argument
to pci_ereport_post() as it may contain bus specific information that might
be useful for handling any errors that are discovered.

The fme_flag in the error_status argument to the error handler callback
function will contain one of:

	DDI_FM_ERR_UNEXPECTED -	any errors discovered are unexpected.

	DDI_FM_ERR_EXPECTED -	errors discovered were the result of
				a DDI_ACC_CAUTIOUS operation.

	DDI_FM_ERR_POKE -	errors discovered are the result of a
				ddi_poke(9F) operation.

	DDI_FM_ERR_PEEK -	errors discovered are the result of a
				ddi_peek(9F) operation.

Error report events will be generated automatically if fme_flag is set to
DDI_FM_ERR_UNEXPECTED and the corresponding error bits are set in the various
PCI, PCI/X or PCI Express Bus error registers of the device associated with dip.
The generated error report events are posted to the Solaris Fault Manager
fmd(1M) for diagnosis.

If the status argument is non-null, then pci_ereport_post() will save the
contents of the the PCI Configuration Status Register to *status. If
it is not possible to read the PCI Configuration Status Register the -1 will
be returned in *status instead.

On return from the call to pci_ereport_post() the ddi_fm_error_t structure
pointed at by dep will have been updated, and the fme_status field will contain
one of the following values:

       DDI_FM_OK	No errors were detected which might affect this
			device instance.

       DDI_FM_FATAL	An error which is considered fatal to the
                        operational state of the system was detected.

       DDI_FM_NONFATAL	An error which is not considered fatal to
                        the operational state of the system was detected. 
			The fme_acc_handle or fme_dma_handle fields in the
			returned ddi_fm_error_t structure will typically
			reference a handle belonging to this device instance
			that has been affected.

       DDI_FM_UNKNOWN	An error was detected, but the call was unable to
		 	determine the impact of the error on the operational
			state of the system. This will be treated the same
			as DDI_FM_FATAL unless some other device is able to
			evaluate the fault to be DDI_FM_NONFATAL.

The value returned in fme_status can be used as the return value from the
error handler callback function as in the example below.

CONTEXT

pci_ereport_setup(), pci_ereport_teardown() must be called from
user or kernel context.

pci_ereport_post() can be called in any context.

EXAMPLE

        int xxx_fmcap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE;

        xxx_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) {

                ddi_fm_init(dip, &xxx_fmcap, &xxx_ibc);
                if (xxx_fmcap & DDI_FM_ERRCB_CAPABLE)
			ddi_fm_handler_register(dip, xxx_err_cb);
                if (xxx_fmcap & DDI_FM_EREPORT_CAPABLE)
                        pci_ereport_setup(dip);

        }

        xxx_err_cb(dev_info_t *dip, ddi_fm_error_t *errp) {
		uint16_t status;

                pci_ereport_post(dip, errp, &status);
		return (errp->fme_status);
        }

        xxx_detach(dev_info_t *dip, ddi_attach_cmd_t cmd) {

                if (xxx_fmcap & DDI_FM_EREPORT_CAPABLE)
                        pci_ereport_teardown(dip);
                if (xxx_fmcap & DDI_FM_ERRCB_CAPABLE)
			ddi_fm_handler_unregister(dip);
		ddi_fm_fini(dip);

        }

SEE ALSO
	ddi_fm_handler_register(9F), ddi_fm_init(9F), ddi_fm_error(9S)



NAME
     ddi_dma_attr - DMA attributes structure

SYNOPSIS
     #include <sys/ddidmareq.h>

INTERFACE LEVEL
     Solaris DDI specific (Solaris DDI).

DESCRIPTION
     A   ddi_dma_attr_t  structure  describes  device-  and   DMA
     engine-specific   attributes   necessary  to  allocate   DMA
     resources for a device. The driver might have to extend  the
     attributes  with  bus-specific information, depending on the
     bus to which the device is connected.

STRUCTURE MEMBERS
     uint_t      dma_attr_version;      /* version number */
     uint64_t    dma_attr_addr_lo;      /* low DMA address range */
     uint64_t    dma_attr_addr_hi;      /* high DMA address range */
     uint64_t    dma_attr_count_max;    /* DMA counter register */
     uint64_t    dma_attr_align;        /* DMA address alignment */
     uint_t      dma_attr_burstsizes;   /* DMA burstsizes */
     uint32_t    dma_attr_minxfer;      /* min effective DMA size */
     uint64_t    dma_attr_maxxfer;      /* max DMA xfer size */
     uint64_t    dma_attr_seg;          /* segment boundary */
     int         dma_attr_sgllen;       /* s/g list length */
     uint32_t    dma_attr_granular;     /* granularity of device */
     uint_t      dma_attr_flags;        /* DMA transfer flags */

     dma_attr_version stores  the  version  number  of  this  DMA
     attribute structure. It should be set to DMA_ATTR_V0.

     The dma_attr_addr_lo and dma_attr_addr_hi fields specify the
     address  range  the  device's  DMA  engine  can  access. The
     dma_attr_addr_lo field describes the inclusive lower  64-bit
     boundary.   The  dma_attr_addr_hi  describes  the  inclusive
     upper 64-bit boundary. The system ensures that allocated DMA
     resources    are    within    the   range   specified.   See
     ddi_dma_cookie(9S).

     The  dma_attr_count_max describes an inclusive  upper  bound
     for   the  device's   DMA  counter  register.  For  example,
     0xFFFFFF would describe a DMA engine with a  24-bit  counter
     register. DMA resource allocation functions have to break up
     a  DMA object into multiple  DMA cookies if the size of  the
     object exceeds the size of the  DMA counter register.

     The  dma_attr_align  specifies  alignment  requirements  for
     allocated  DMA  resources.  This  field can be used to force
     more    restrictive    alignment     than     imposed     by
     dma_attr_burstsizes  or  dma_attr_minxfer, such as alignment
     at a page boundary. Most drivers set this field to 1,  indi-
     cating byte alignment.

     Note that dma_attr_align only specifies  alignment  require-
     ments  for  allocated  DMA  resources.  The buffer passed to
     ddi_dma_addr_bind_handle(9F) or  ddi_dma_buf_bind_handle(9F)
     must    have   an   equally   restrictive   alignment   (see
     ddi_dma_mem_alloc(9F)).

     The  dma_attr_burstsizes field describes the possible  burst
     sizes the device's  DMA engine can accept. The format of the
     data sizes is binary encoded in terms of powers of two. When
     DMA  resources  are  allocated,  the  system  can modify the
     burstsizes value to reflect the system  limits.  The  driver
     must use the allowable burstsizes to program the DMA engine.
     See ddi_dma_burstsizes(9F).

     The  dma_attr_minxfer field describes the minimum  effective
     DMA  access  size  in  units  of bytes. DMA resources can be
     modified, depending on the presence and use  of  I/O  caches
     and  write  buffers  between  the  DMA engine and the memory
     object. This field is used to determine alignment  and  pad-
     ding requirements for ddi_dma_mem_alloc(9F).

     The  dma_attr_maxxfer field describes the maximum  effective
     DMA access size in units of bytes.

     The  dma_attr_seg field specifies segment boundary  restric-
     tions  for allocated DMA resources. The system allocates DMA
     resources for the device so that the object  does  not  span
     the segment boundary specified by dma_attr_seg. For example,
     a value of 0xFFFF means DMA resources must not  cross  a  64
     Kbyte  boundary.   DMA  resource  allocation functions might
     have to break up a DMA object into multiple DMA  cookies  to
     enforce  segment  boundary  restrictions.  In this case, the
     transfer must be performed using scatter-gather I/O or  mul-
     tiple DMA windows.

     The  dma_attr_sgllen  field  describes  the  length  of  the
     device's  DMA  scatter/gather  list.  Possible values are as
     follows:

     < 0      Device  DMA engine is not constrained by the  size,
              for example, withDMA chaining.

     = 0      Reserved.

     = 1      Device  DMA engine does not support  scatter/gather
              such as third party DMA.

     > 1      Device     DMA    engine    uses    scatter/gather.
              dma_attr_sgllen is the maximum number of entries in
              the list.

     The dma_attr_granular field describes the granularity of the
     device  transfer  size,  in  units of bytes. When the system
     allocates DMA resources, a single segment's size is a multi-
     ple  of  the  device granularity. Or if   dma_attr_sgllen is
     larger than 1 within a window, the sum of the  sizes  for  a
     subgroup  of  segments is a multiple of the device granular-
     ity.

     Note that all driver requests for DMA resources  must  be  a
     multiple of the granularity of the device transfer size.

+    The dma_attr_flags field can be set to a combination of:

     DDI_DMA_FORCE_PHYSICAL

         Some platforms, such as SPARC systems, support  what  is
         called  Direct  Virtual  Memory  Access (DVMA). On these
         platforms, the device is provided with a virtual address
         by  the system in order to perform the transfer. In this
         case, the underlying platform provides an  IOMMU,  which
         translates  accesses to these virtual addresses into the
         proper physical addresses. Some of these platforms  also
         support  DMA.  DDI_DMA_FORCE_PHYSICAL indicates that the
         system should return physical rather  than  virtual  I/O
         addresses  if  the  system  supports both. If the system
         does not support physical DMA,  the  return  value  from
         ddi_dma_alloc_handle(9F)  will  be  DDI_DMA_BADATTR.  In
         this    case,    the     driver     has     to     clear
         DDI_DMA_FORCE_PHYSICAL and retry the operation.

+    DDI_DMA_FLAGERR
+
+	Using this value indicates that the driver is hardened (i.e,
+	able to cope with the incorrect results of DMA operations that
+	may result from an I/O fault), and that it will check its DMA
+	handle(s) for faults on a regular basis (using ddi_fm_dma_err_get(9F)).
+
+	if a DMA error is detected during a DMA access to an area mapped
+	by such a handle, then, if possible, the system should not panic,
+	but should instead mark the DMA handle as having faulted.
+
+	Note, this value is advisory: it tells the system that the driver
+	can continue in the face of I/O faults; it does not guarantee
+	that the system will not panic, as that depends on the nature of
+	the fault and the capabilities of the system. It is quite
+	legitimate for an implementation to ignore this flag and panic anyway.
+
	
EXAMPLES
     Example 1: Initializing the ddi_dma_attr_t Structure

     Assume a device has the following  DMA characteristics:

       o  Full 32-bit range addressable

       o  24-bit DMA counter register

       o  Byte alignment

       o  4- and 8-byte burst sizes support

       o  Minimum effective transfer size of 1 bytes

       o  64 Mbyte maximum transfer size limit

       o  Maximum segment size of 32 Kbyte

       o  17 scatter/gather list elements

       o  512-byte device transfer size granularity

     The corresponding ddi_dma_attr_t structure is initialized as
     follows:

     static ddi_dma_attr_t dma_attrs = {
              DMA_ATTR_V0              /* version number */
              (uint64_t)0x0,           /* low address */
              (uint64_t)0xffffffff,    /* high address */
              (uint64_t)0xffffff,      /* DMA counter max */
              (uint64_t)0x1            /* alignment */
              0x0c,                    /* burst sizes */
              0x1,                     /* minimum transfer size */
              (uint64_t)0x3ffffff,     /* maximum transfer size */
              (uint64_t)0x7fff,        /* maximum segment size */
              17,                      /* scatter/gather list lgth */
              512                      /* granularity */
              0                        /* DMA flags */
     };

SEE ALSO
     ddi_dma_addr_bind_handle(9F),      ddi_dma_alloc_handle(9F),
     ddi_dma_buf_bind_handle(9F),         ddi_dma_burstsizes(9F),
     ddi_dma_mem_alloc(9F),               ddi_dma_nextcookie(9F),
+    ddi_dma_cookie(9S),		  ddi_fm_dma_err_get(9F)




NAME
     ddi_device_acc_attr - data access attributes structure

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

INTERFACE LEVEL
     Solaris DDI specific (Solaris DDI).

DESCRIPTION
     The  ddi_device_acc_attr structure describes the data access
     characteristics and requirements of the device.

STRUCTURE MEMBERS
     ushort_t     devacc_attr_version;
     uchar_t      devacc_attr_endian_flags;
     uchar_t      devacc_attr_dataorder;
+    uchar_t      devacc_attr_access;

     The devacc_attr_version member identifies the version number
     of    this   structure.    The  current  version  number  is
     DDI_DEVICE_ATTR_V0.

     The devacc_attr_endian_flags  member  describes  the  endian
     characteristics  of the device. Specify one of the following
     values:

     DDI_NEVERSWAP_ACC               Data  access  with  no  byte
                                     swapping

     DDI_STRUCTURE_BE_ACC            Structural  data  access  in
                                     big-endian format

     DDI_STRUCTURE_LE_ACC            Structural  data  access  in
                                     little endian format

     DDI_STRUCTURE_BE_ACC and  DDI_STRUCTURE_LE_ACC describes the
     endian  characteristics  of  the  device  as  big-endian  or
     little-endian, respectively. Though most of the devices will
     have  the  same endian characteristics as their buses, exam-
     ples of devices that have opposite endian characteristics of
     the   buses   do   exist.   When   DDI_STRUCTURE_BE_ACC   or
     DDI_STRUCTURE_LE_ACC is set, byte swapping is  automatically
     performed  by  the system if the host machine and the device
     data  formats  have  opposite  endian  characteristics.  The
     implementation can take advantage of  hardware platform byte
     swapping capabilities.

     When you specify DDI_NEVERSWAP_ACC,  byte  swapping  is  not
     invoked in the data access functions.

     The devacc_attr_dataorder member describes  order  in  which
     the   CPU  will reference data. Specify one of the following
     values.

     DDI_STRICTORDER_ACC             The data references must  be
                                     issued  by  a CPU in program
                                     order.  Strict  ordering  is
                                     the default behavior.

     DDI_UNORDERED_OK_ACC            The  CPU  can  re-order  the
                                     data     references.    This
                                     includes all  kinds  of  re-
                                     ordering.   For  example,  a
                                     load followed by a store may
                                     be  replaced by a store fol-
                                     lowed by a load.

     DDI_MERGING_OK_ACC              The  CPU can  merge  indivi-
                                     dual  stores  to consecutive
                                     locations.  For example, the
                                     CPU can turn two consecutive
                                     byte stores into  one  half-
                                     word   store.  It  can  also
                                     batch individual loads.  For
                                     example,  the CPU might turn
                                     two consecutive  byte  loads
                                     into   one   halfword  load.
                                     DDI_MERGING_OK_ACC      also
                                     implies re-ordering.

     DDI_LOADCACHING_OK_ACC          The  CPU can cache the  data
                                     it   fetches  and  reuse  it
                                     until another store  occurs.
                                     The  default  behavior is to
                                     fetch  new  data  on   every
                                     load. DDI_LOADCACHING_OK_ACC
                                     also  implies  merging   and
                                     re-ordering.

     DDI_STORECACHING_OK_ACC         The  CPU can keep  the  data
                                     in  the cache and push it to
                                     the  device  (perhaps   with
                                     other data) at a later time.
                                     The default behavior  is  to
                                     push  the  data  right away.
                                     DDI_STORECACHING_OK_ACC also
                                     implies  load caching, merg-
                                     ing, and re-ordering.

     These values are advisory, not mandatory. For example,  data
     can be ordered without being merged or cached, even though a
     driver requests unordered, merged, and cached together.

+    The values defined for devacc_attr_access are:
+
+    #define DDI_DEFAULT_ACC         0x00
+    #define DDI_FLAGERR_ACC         0x01
+    #define DDI_CAUTIOUS_ACC        0x02
+
+    These flags have the following significance:
+
+    DDI_DEFAULT_ACC:	If an I/O fault occurs, the system will take
+			the default action, which may well be to panic.
+
+    DDI_FLAGERR_ACC:   Using this value indicates that the driver is
+                       hardened (i.e, able to cope with the incorrect
+                       results of I/O operations that may result from
+                       an I/O fault), and that it will check its
+                       access handle(s) for faults on a regular basis
+                       using ddi_fm_acc_err_get(9F).
+  
+    			if possible, the system should not panic on such an
+                       I/O fault, but should instead mark the I/O
+                       handle through which the access was made as
+                       having faulted.
+
+                       Note that this value is advisory: it tells the
+                       system that the driver can continue in the face
+                       of I/O faults; it does not guarantee that the
+                       system will not panic, as that depends on the
+                       nature of the fault and the capabilities of the
+                       system.  It is quite legitimate for an
+                       implementation to ignore this flag and panic
+                       anyway.
+
+    DDI_CAUTIOUS_ACC:  This value indicates that an I/O fault is
+                       anticipated and so should be handled as
+                       gracefully as possible.  For example, the
+                       framework should not print a console message.
+
+                       This value should be used when it is not
+                       certain that a device is physically present
+                       e.g. when probing.  As such, it provides an
+                       alternative within the DDI access framework to
+                       the existing peek/poke functions, which don't
+                       use access handles and therefore can't easily
+                       be integrated into a more general I/O fault
+                       handling framework.
+
+                       Note that in order to guarantee safe recovery
+                       from an I/O fault, it may be necessary (for
+                       example) to acquire exclusive access to the
+                       parent bus, or to synchronize across processors
+                       on an MP machine. "Cautious" accesses can
+                       therefore be quite expensive, and are only
+                       recommended for initial probing and possibly
+                       for any additional fault-recovery code.

EXAMPLES
     The following examples illustrate the use of device register
     address  mapping  setup  functions and different data access
     functions.

     Example     1:      Using      ddi_device_acc_attr()      in
     ddi_regs_map_setup(9F)

     This    example    demonstrates    the    use     of     the
     ddi_device_acc_attr()  structure in  ddi_regs_map_setup(9F).
     It also shows the use  of   ddi_getw(9F)  and   ddi_putw(9F)
     functions in accessing the register contents.

     dev_info_t *dip;
     uint_t     rnumber;
     ushort_t  *dev_addr;
     offset_t   offset;
     offset_t   len;
     ushort_t   dev_command;
     ddi_device_acc_attr_t dev_attr;
     ddi_acc_handle_t handle;

     ...

     /*
      * setup the device attribute structure for little endian,
      * strict ordering and 16-bit word access.
      */
     dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
     dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
     dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;

     /*
      * set up the device registers address mapping
      */
     ddi_regs_map_setup(dip, rnumber, (caddr_t *)&dev_addr, offset, len,
             &dev_attr, &handle);

     /* read a 16-bit word command register from the device      */
     dev_command = ddi_getw(handle, dev_addr);

     dev_command |= DEV_INTR_ENABLE;
     /* store a new value back to the device command register    */
     ddi_putw(handle, dev_addr, dev_command);

     Example 2: Accessing a Device with Different Apertures

     The following example illustrates the steps used to access a
     device   with  different  apertures.  Several  apertures are
     assumed to be grouped under  one  single  "reg"  entry.  For
     example,  the  sample  device  has four different apertures,
     each 32 Kbyte in size.  The apertures represent YUV  little-
     endian,  YUV  big-endian,  RGB  little-endian,  and RGB big-
     endian. This sample device uses entry 1 of the  "reg"   pro-
     perty  list  for this purpose. The size of the address space
     is 128 Kbyte with each 32 Kbyte range as  a  separate  aper-
     ture.  In  the  register  mapping setup function, the sample
     driver uses the  offset and  len parameters to  specify  one
     of the apertures.

     ulong_t   *dev_addr;
     ddi_device_acc_attr_t dev_attr;
     ddi_acc_handle_t handle;
     uchar_t buf[256];

     ...

     /*
      * setup the device attribute structure for never swap,
      * unordered and 32-bit word access.
      */
     dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
     dev_attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
     dev_attr.devacc_attr_dataorder = DDI_UNORDERED_OK_ACC;

     /*
      * map in the RGB big-endian aperture
      * while running in a big endian machine
      *  - offset 96K and len 32K
      */
     ddi_regs_map_setup(dip, 1, (caddr_t *)&dev_addr, 96*1024, 32*1024,
             &dev_attr, &handle);

     /*
      * Write to the screen buffer
      *  first 1K bytes words, each size 4 bytes
      */
     ddi_rep_putl(handle, buf, dev_addr, 256, DDI_DEV_AUTOINCR);

     Example 3: Functions That Call Out the Data Word Size

     The following example illustrates the use of  the  functions
     that  explicitly call out the data word size to override the
     data size in the device attribute structure.

     struct device_blk {
          ushort_t  d_command;     /* command register */
          ushort_t  d_status; /* status register */
          ulong         d_data;         /* data register */
     } *dev_blkp;
     dev_info_t *dip;
     caddr_t   dev_addr;
     ddi_device_acc_attr_t dev_attr;
     ddi_acc_handle_t handle;
     uchar_t buf[256];

     ...

     /*
      * setup the device attribute structure for never swap,
      * strict ordering and 32-bit word access.
      */
     dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
     dev_attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
     dev_attr.devacc_attr_dataorder= DDI_STRICTORDER_ACC;

     ddi_regs_map_setup(dip, 1, (caddr_t *)&dev_blkp, 0, 0,
             &dev_attr, &handle);

     /* write command to the 16-bit command register */
     ddi_putw(handle, &dev_blkp->d_command, START_XFER);

     /* Read the 16-bit status register */
     status = ddi_getw(handle, &dev_blkp->d_status);

     if (status & DATA_READY)
             /* Read 1K bytes off the 32-bit data register */
             ddi_rep_getl(handle, buf, &dev_blkp->d_data,
                     256, DDI_DEV_NO_AUTOINCR);

SEE ALSO
     ddi_getw(9F), ddi_putw(9F), ddi_regs_map_setup(9F)
+    ddi_fm_acc_err_get(9F)
