/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos72X src/bos/kernel/sys/dma.h 1.58.8.1                               */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 1988,2022              */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/* @(#)99     1.58.8.1  src/bos/kernel/sys/dma.h, sysios, bos72X, x2022_06A2 2/3/22 14:34:25 */

#ifndef _H_DMA
#define _H_DMA
/*
 * COMPONENT_NAME: (SYSIOS) IO subsystem
 *
 * FUNCTIONS: DMA external interface definition.
 *
 * ORIGINS: 27
 *
 * (C) COPYRIGHT International Business Machines Corp. 1988, 1997
 * All Rights Reserved
 * Licensed Materials - Property of IBM
 *
 * US Government Users Restricted Rights - Use, duplication or
 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 */

#include <sys/sysdma.h>
#include <sys/types.h>
#include <sys/xmem.h>
#include <sys/err_rec.h>
#include <sys/kerrno.h>

#ifdef __cplusplus
extern "C" {
#endif

/*****************************  IMPORTANT NOTICE  ***************************
*                                                                           *
* DO NOT MODIFY THIS FILE, BECAUSE IT WILL GLOBALLY AFFECT ALL PROGRAMS IN  *
* THE SYSTEM THAT INCLUDE THIS FILE.                                        *
*                                                                           *
****************************************************************************/

/****************************************************************************
 *	PCI/ISA Specific Flags, Structures, Functions, Macros, etc.         *
 ****************************************************************************/

/***********************  INITIALIZATION FLAGS ******************************/

/*
 * These are the flag values for the d_map_init and d_map_init_ext services. 
 * These flags must each be unique with respect to each other.
 */
#define		DMA_SLAVE	0x10		/* device is a DMA slave  */
#define		DMA_MASTER	0x00		/* device is a DMA master */

/*
* NOTE:  DMA_ENABLE_64 allows a 32-bit driver to use the 64-bit
*        interfaces (which are automatically used by 64-bit drivers).
*        DMA_ADDRESS_64_BIT indicates the device is capable of
*        generating 64-bit addresses.  Using the 64-bit interfaces
*        in conjunction with a device that supports 64-bit addressing
*        can avoid unnecessary address translation and latency, if all
*        intervening PCI bridges also support 64-bit addressing.
*
*        DMA_CONTIGUOUS specifies that a buffer mapped using this
*        handle will have contiguous bus addresses.  The d_map_init
*        call will fail if the system does not provide the resources
*        required to guarantee the contiguity property.
*/
#define		DMA_ADDRESS_64_BIT	0x80	/* can drive 64-bit address */
#define		DMA_ENABLE_64		0x100	/* enable 64-bit interfaces */
#define		DMA_CONTIGUOUS		0x800	/* only contiguous mapping  */

/*
* NOTE: DMA_NO_ZERO_ADDR flag should be used by those device drivers that
* cannot drive a PCI bus address of '0'. On systems with TCEs enabled (I/O
* address remapping hardware), specifying this flag will guarantee that the
* driver will never be given bus address '0'.  On LPAR systems, setting this
* flag has the additional side effect of reducing the driver's DMA mappable
* memory by 4K.  On systems without TCEs enabled, the presence of this flag
* will cause d_map_init to fail, since the system can not guarantee that the
* driver will never see bus address '0'.
*/
#define     DMA_NO_ZERO_ADDR      0x40    /* cannot drive bus addr '0' */

/*
 * For IA64 (no TCE hardware) it is important to know the addressing
 * capabilities (64 or 32 bit) of the bus and its path to system memory.
 * This information is available at initialization time via the
 * per-bus "pci_bus" structure. The PCI bus driver code preserves the
 * info in a flag bit for easy reference later. This flag value is
 * not intended to be supplied by the adapter driver.
 * The 0x200 position of the flag is defined in m_dma.h
*/
#define		DMA_64_BIT_PATH		0x400	/* 64-bit addressing path */
						/* to system memory       */

/*
* By default, the PCI bus device driver and the vdevice bus device driver
* allocates one additional page more DMA space than what the calling device
* driver requests via the DMA_MAXMIN_* flag.  This is done to support
* non-page aligned transfers of size MAXMIN.  A device driver may avoid
* the additional page by specifying DMA_MAXMIN_MAPSPACE in its flags at
* d_map_init time.  DMA_MAXMIN_MAPSPACE indicates that the DMA_MAXMIN_* flag
* represents the amount of mappable address space the device driver requires,
* rather than the maximum transfer value.
*
* Example:
* Assume that a device driver has specified DMA_MAXMIN_256K and that the page
* size is 4K.  Given these assumptions, that device driver must be able to
* ensure both of the following when using DMA_MAXMIN_MAPSPACE:
*
* 1. The largest successful non-page aligned single DMA transfer is
*    252K (256K - 4K).
* 2. The largest successful page aligned single DMA transfer is 256K.
*
* If the DMA_MAXMIN_MAPSPACE flag is not used, then the device driver's largest
* successful non-page aligned single DMA transfer is 256K.
*/
#define		DMA_MAXMIN_MAPSPACE	0x1000	/* do not add extra page to */
						/* requested size	    */

/*
* The DMA_MAXMIN_QUIET flag allows a driver to indicate that it makes
* multiple D_MAP_INIT calls with a decreasing value of the DMA_MAXMIN_* flag.
* This flag prevents an error from being logged when there is not enough DMA
* space to fulfill the request specified by the DMA_MAXMIN_* flag.
*/
#define		DMA_MAXMIN_QUIET	0x2000	/* do not log errors due to */
						/* insufficent DMA space to */
						/* fulfill request	    */

/* The DMA_MAXMIN_* encoded flag values should be used by the
 * device driver to represent AT A MINIMUM the largest required
 * minimum transfer for any device on that adapter to make forward
 * progress.  For example:
 *
 *     A SCSI adapter may have 3 disks (block size 512 bytes) and
 *     1 tape device (block size 8MB).  In this case, the SCSI
 *     adapter driver would have to specify at least a flag of
 *     DMA_MAXMIN_8M to guarantee that the SCSI Tape could do its
 *     minimum transfer.
 *
 * Another consideration is throughput.  In the above example,
 * each time a single tape operation takes place, the SCSI adapter
 * will be forced to throttle its queues, until there are no
 * outstanding commands to any devices in order for the 8MB mappable
 * I/O space to become free in order to do the single minimum tape transfer.
 * So it might be desirable to select a reasonable DMA_MAXMIN value to
 * allow a reasonable amount of concurrency per adapter.
 *
 * The default is 64K so these flags should be used only if the
 * device needs a guaranteed mapping that exceeds the default.
 *
 * WARNING: The solution is not to simply select the largest possible
 *          DMA_MAXMIN flag.  That most likely would result in either the
 *          requesting device not configuring (due to lack of resources) or
 *          to other devices on the same HostBridge not configuring.
 */
#define		DMA_MAXMIN_MASK		0xF
#define		DMA_MAXMIN_64K		0x0	/* 64K byte max minxfer size */
#define		DMA_MAXMIN_128K		0x1	/* 128K byte max minxfer size */
#define		DMA_MAXMIN_256K		0x2	/* 256K byte max minxfer size */
#define		DMA_MAXMIN_512K		0x3	/* 512K byte max minxfer size */
#define		DMA_MAXMIN_1M		0x4	/* 1M byte max minxfer size */
#define		DMA_MAXMIN_2M		0x5	/* 2M byte max minxfer size */
#define		DMA_MAXMIN_4M		0x6	/* 4M byte max minxfer size */
#define		DMA_MAXMIN_8M		0x7	/* 8M byte max minxfer size */
#define		DMA_MAXMIN_16M		0x8	/* 16M byte max minxfer size */
#define		DMA_MAXMIN_32M		0x9	/* 32M byte max minxfer size */
#define		DMA_MAXMIN_64M		0xA	/* 64M byte max minxfer size */
#define		DMA_MAXMIN_128M		0xB	/* 128M byte max minxfer size */
#define		DMA_MAXMIN_256M		0xC	/* 256M byte max minxfer size */
#define		DMA_MAXMIN_512M		0xD	/* 512M byte max minxfer size */
#define		DMA_MAXMIN_1G		0xE	/* 1G byte max minxfer size */
#define		DMA_MAXMIN_2G		0xF	/* 2G byte max minxfer size */

/*
 * This flag indicates to d_map_page and d_map_list services that the caller
 * of them understand and support DMA_STMAP flag. DMA_STMAP flag is useful
 * because it indicates to the DMA mapping services which mappings are for
 * a short-term DMA. DMA_INIT_STMAP_SUPPORT allows d_map_init_ext to 
 * initialize whatever is necessary to support DMA_STMAP. If a device driver
 * plans to use DMA_STMAP, it must set this flag in d_info_t.di_flags on
 * d_map_init_ext.
 */
#define		DMA_INIT_STMAP_SUPPORT	0x4000

/* This Flag indicates to D_MAP_INIT_EXT that the caller wishes to use
 * 64-Bit DMA Handles.This flag must be used with or after DMA_PRIME is used. 
 */
#define		DMA_HUGE	0x8000

/* This Flag indicates to D_MAP_INIT_EXT that the caller wishes to create
 * a 64-Bit DMA Windows. A Dynamic DMA Window will be created. 
 */
#define		DMA_PRIME	0x10000

/*
 * This Flag indicates to D_MAP_INIT/D_MAP_INIT_EXT that the caller wishes to
 * update I/O mapping table in bulk so as to reduce the number of mapping 
 * calls into the platform.
 */
#define		DMA_TCE_BULK	0x20000

/*
 * This flag indicates to D_MAP_INIT/D_MAP_INIT_EXT that the caller wishes to
 * eleminate AIX copy of I/O mapping to reduce the overhead. 
 */

#define		DMA_NO_MIRROR 	0x40000

/*
 * This flag specifies to D_MAP_INIT/D_MAP_INIT_EXT that a buffer mapped
 * using this handle will have contiguous bus address with minimal fragmentation.
 */
#define		DMA_CONTIGUOUS_FORCE 	0x80000

/*
 * So, in summary, here is the breakdown of the INITIALIZATION flags for
 * the d_map_init and d_map_init_ext service.
 *
 *   +---------------------------------------------------------------+
 *   |    R  e  s  e  r  v  e F|N B|P|H|S|Q|M|C|6|r|6|6|z| |S|  MAX  |
 *   |                        R|M L|R|U|T|U|A|O|4|s|4|4|r| |L|  MIN  |
 *   |                        C|R K|I|G|M|I|P|N|B|v|E|A|0| |V|  XFER |
 *   | | | | | | | | | | |1|1|1|1|1|1|1|1|1|1|2|2|2|2|2|2|2|2|2|2|3|3|
 *   |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
 *   +---------------------------------------------------------------+
 */

/****************************  SERVICE FLAGS ******************************/
/*
* These are the flag values for the d_map_page/d_map_list/d_map_slave services
*/
#define		DMA_READ	0x80		/* xfer from device to buffer*/
#define		BUS_DMA		0x100		/* buffer in bus memory   */
#define		DMA_STMAP   0x200       /* short term mapping  */
#define		DMA_BYPASS	0x4000		/* don't perform access check*/

/*
* This flag is defined for source-compatibility reasons only.
* It has no effect on the d_map_page/d_map_list/d_map_slave services
*/
#define		DMA_WRITE_ONLY	0x400	/* will not write to memory */


/*
 * So, in summary, here is the breakdown of the SERVICE flags for
 * the d_map_page/d_map_list/d_map_slave services
 *
 *   +---------------------------------------------------------------+
 *   |    R  e  s  e  r  v  e  d       |B|resvd|W|S|B|R|  reserved   |
 *   |                                 |y|     |R|T|U|d|             |
 *   |                                 |p|     |O|M|S| |             |
 *   | | | | | | | | | | |1|1|1|1|1|1|1|1|1|1|2|2|2|2|2|2|2|2|2|2|3|3|
 *   |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
 *   +---------------------------------------------------------------+
 */


/**************************************************************************/

/*
 * The following flags are specific to the d_map_slave() service, and
 * represent the definitions for the chan_flags parameter for the d_map_slave
 * service
 *   +---------------------------------------------------------------+
 *   |mod|I|A|Reserved |E|Tim|Adr|         R e s e r v e d           |
 *   |bit|n|u|         |O|Bit|Mod|                                   |
 *   |   |c|t|         |P|   |   |                                   |
 *   | | | | | | | | | | |1|1|1|1|1|1|1|1|1|1|2|2|2|2|2|2|2|2|2|2|3|3|
 *   |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
 *   +---------------------------------------------------------------+
 */
#define CH_DEFAULT	   0x00000000	/* run channel with default settings*/

#define CH_DEMAND          0x00000000   /* xfer until TC or device releases */
#define CH_SINGLE          0x40000000   /* single byte or word at a time    */
#define CH_BLOCK           0x80000000   /* lock out other devices until done*/
#define CH_CASCADE         0xC0000000   /* used for cascading ISA masters   */

#define CH_ADDR_INC        0x00000000   /* increment address during DMA     */

#define CH_AUTOINIT        0x10000000   /* at TC, reset address/count to orig*/

#define CH_EOP_OUTPUT      0x00000000   /* specifies EOP signal is output   */
#define CH_EOP_INPUT       0x00400000   /* specifies EOP signal as input    */

#define CH_COMPAT          0x00000000   /* compatible timing, 8 sysclks     */
#define CH_TYPE_A          0x00100000   /* shorter cycles, 6 sysclks        */
#define CH_TYPE_B          0x00200000   /* faster i/o timing, 5 sysclks     */
#define CH_TYPE_F          0x00300000   /* high performance, 3 sysclks      */

#define CH_8BIT_BYTES      0x00000000   /* 8 bit I/O device, count by bytes */
#define CH_16BIT_WORDS     0x00040000   /* 16 bit I/O device, count by words*/
#define CH_16BIT_BYTES     0x000C0000   /* 16 bit I/O device, count by bytes*/


/***************************  DATA STRUCTURES ****************************/

typedef uint_t          dma_channel_t; /* DMA channel */

/*
 * This structure must be passed into d_map_init_ext
 */
#define DMA_MAX_MAPPER_NAME	32
typedef struct d_info
{
	uint64_t	di_bid;
	uint64_t	di_flags;
	uint64_t	di_bus_flags;
	uint64_t	di_channel;
	uint64_t	di_min_mapmem;
	uint64_t	di_des_mapmem;
	uint64_t	di_max_mapmem;
	char		di_mapper_name[DMA_MAX_MAPPER_NAME] ;
	uint64_t	di_io_page_size;
	uint64_t	di_stab_id;
	uint64_t	di_rsvd[5];	/* Reserved words are expected 
					 * to be initialized to zero */
} d_info_t;


/* 
 * These Structures must be passed into d_map_query
 */
 
/* Commands */
#define DDW_QUERY 0x01
#define DMA_QUERY 0x02
#define DMA_ALLOC_GRANULE 0x03
#define DHANDLE_QUERY 0x04

/* D_MAP_QUERY Input Flags */
#define DMQ_32_BIT	0x01	/* Indicates caller is 32-bit device driver */

/* 
 * The dq_ddw_resources structure is to be used in D_MAP_QUERY with the
 * DDW_QUERY cmd specified
 */
typedef struct dq_ddw_resources
{
        /* input by caller */
        uint64_t dqdr_version;
    
        /* returned to caller */
	uint64_t dqdr_supported_page_sizes; 
	uint64_t dqdr_windows_avail;  /*Amount of Dynamic DMA windows available.
	 			       * If DDW, is not available 
	                               * 0 will be returned.*/ 
    	uint64_t dqdr_max_pages; /* Largest Number of contiguous 
	   			  * pages available.*/
    	uint64_t dqdr_rsvd1; /* reserved for future use */
    	uint64_t dqdr_rsvd2; /* reserved for future use */
    	uint64_t dqdr_rsvd3; /* reserved for future use */
    	uint64_t dqdr_rsvd4; /* reserved for future use */
} dq_ddw_resources_t;

#define DQDR_VERSION	 0x10001

/* 
 * The dq_dma_avaliable structure is to be used in D_MAP_QUERY with the 
 * DMA_QUERY cmd specified
 */
typedef struct dq_dma_available
{
        /*input by caller */
        uint64_t dqda_version;
        uint64_t dqda_io_page_size; /* Pagesize in Bytes, Should only be of a
	 				supported pagesize */
	
        /* returned to caller for DMA_Query*/
        uint64_t dqda_pages_available;
	uint	 dqda_flags;
	uint	 dqda_rsvd1; /* reserved for future use */
	uint64_t dqda_rsvd2; /* reserved for future use */
	uint64_t dqda_rsvd3; /* reserved for future use */
	uint64_t dqda_rsvd4; /* reserved for future use */
} dq_dma_available_t;

#define DQDA_VERSION	0x20002
#define DQ_MASK		0xF0000

/*
 * The dq_dma_granule structure is to be used in D_MAP_QUERY with the
 * DDW_QUERY cmd specified
 */
typedef struct dq_dma_granule * dq_dma_granule_t;
struct dq_dma_granule
{
	uint64_t dq_dma_version;	/* in parameter */
	uint64_t dma_request_size;	/* in parameter */
	uint64_t dma_iopagesize;	/* in parameter */
	uint64_t dma_alloc_granule;	/* out parameter*/
};

#define DQAG_VERSION 0x10001

/*
 * The dq_dhandle structure is to be used in D_MAP_QUERY with the
 * DHANDLE_QUERY cmd specified
 */
typedef struct dq_dhandle
{
	/*input by caller */
	uint64_t dqdh_version;
	void *	dhandle;	/* DMA handle to retrieve additional
				   DMA details for. */

	/* returned to caller for DMA_Query*/
	uint 	liobn;
	uint	dqdh_flags;
	uint64_t bus_base; 	/* Base bus address of this handle */
	uint64_t dqdh_rsvd3; 	/* reserved for future use */
	uint64_t dqdh_rsvd4; 	/* reserved for future use */
} dq_dhandle_t;

#define DQDH_VERSION	0x10002

   /*
    *   DMA_QUERY  Return Flags
    *   Bits 0 - 29 reserved
    *   30 = Window details are of a Default window 
    *   31 = Device Is DDW Capable
    *
    *
    *   +---------------------------------------------------------------+
    *   |                                                           |D| |
    *   |                                                           |F| |
    *   |                                                           |L| |
    *   |                                                           |T| |
    *   |                                                           |W|I|
    *   |                                                           |I|S|
    *   |                                                           |N| |
    *   |    R  e  s  e  r  v  e  d                                 |D|D|
    *   |                                                           |O|D|
    *   |                                                           |W|W|
    *   | | | | | | | | | | |1|1|1|1|1|1|1|1|1|1|2|2|2|2|2|2|2|2|2|2|3|3|
    *   |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
    *   +---------------------------------------------------------------+
    */
#define IS_DDW_CAPABLE		0x1
#define IS_DEFAULT_WINDOW	0x2

   /*
    *   DHANDLE_QUERY Return Flags
    *   Bits 0 - 30 reserved
    *   31 = LIOBN
    *   30 = BUS_BASE
    *
    *
    *   +---------------------------------------------------------------+
    *   |                                                           | | |
    *   |                                                           | | |
    *   |                                                           |B| |
    *   |                                                           |U| |
    *   |                                                           |S| |
    *   |                                                           | |L|
    *   |                                                           |B|I|
    *   |    R  e  s  e  r  v  e  d                                 |A|O|
    *   |                                                           |S|B|
    *   |                                                           |E|N|
    *   | | | | | | | | | | |1|1|1|1|1|1|1|1|1|1|2|2|2|2|2|2|2|2|2|2|3|3|
    *   |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
    *   +---------------------------------------------------------------+
    */
#define DQDH_LIOBN	0x1
#define DQDH_BUS_BASE	0x2

   /*
    * Supported Page sizes
    *   Bits 0 - 23 reserved
    *   24 = 16 GB page size supported
    *   25 = 256 MB page size supported
    *   26 = 128 MB page size supported
    *   27 = 64 MB page size supported
    *   28 = 32 MB page size supported
    *   29 = 16 MB page size supported
    *   30 = 64 KB page size supported
    *   31 = 4 KB page size supported
    *
    *
    *   +---------------------------------------------------------------+
    *   |                                               | |2|1| | | | | |
    *   |    R  e  s  e  r  v  e  d                     |1|5|2|6|3|1|6|4|
    *   |                                               |6|6|8|4|2|6|4|K|
    *   |                                               |G|M|M|M|M|M|K|B|
    *   | | | | | | | | | | |1|1|1|1|1|1|1|1|1|1|2|2|2|2|2|2|2|2|2|2|3|3|
    *   |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|
    *   +---------------------------------------------------------------+
    */
#define IO_PAGESIZE_4K		0x0001
#define IO_PAGESIZE_64K		0x0002
#define IO_PAGESIZE_16M		0x0004
#define IO_PAGESIZE_32M		0x0008
#define IO_PAGESIZE_64M		0x0010
#define IO_PAGESIZE_128M	0x0020
#define IO_PAGESIZE_256M	0x0040
#define IO_PAGESIZE_16G		0x0080

/*
 *  To pass a dma_data_ext struct instead of a dma_data struct,
 *  the caller must do the following:
 *
 *  1) Zero out the dma_data_ext struct
 *  2) Set dma_data.version to DMA_DATA_VERSION
 *  3) Set dma_data.dma_data_ext to 1
 *  4) Set dma_data.dma_data_size to DMA_DATA_SIZE
 *
 *  If the dma_data_ext struct is supported the dma_data_ext
 *  bit will be set in the dma_data_ext struct.  If the bit
 *  is not set, the dma_data_ext struct is not supported
 *  and only the dma_data struct will be populated.
 *
 */

typedef struct dma_data * dma_data_t;
struct dma_data
{
	uint version;
	uint is_ddw;
	uint64_t supported_pgsz;
	uint64_t total_available;
	uint32_t	dma_data_ext:	 1,
			rsvd:		31;
	uint32_t dma_data_size;
	uint64_t reserved2;
};

#define DMA_DATA_VERSION 0x30002
#define DMA_DATA_SIZE    (sizeof(dma_data_ext_t))

typedef enum
{
  DMA_DATA_DFT_WINDOW,
  DMA_DATA_DDW_WINDOW,
  DMA_DATA_MAX_WINDOW,
};


/*
 *  If the dma_data_ext bit is set, then the dma_data_ext struct
 *  is supported with the supported version returned in the version
 *  field and the supported version structure size returned in the
 *  in the dma_data_size field.
 *
 *  If the dma_data_ext bit is not set, then only the information
 *  in the dma_data struct is valid upon return of this structure.
 *
 *  If ddw_supported is set, then DDW is supported and the
 *  DDW fields in this struct are valid.
 *
 *  supported_pgsz is a bit encoded field indicating what page
 *  sizes are supported by the window.
 *  See IO_PAGESIZE_* for values.
 *
 *  max_pages holds the max number of pages for the window.
 *  The max possible window size for a given page size
 *  is determined by multiplying the desired page size by 
 *  max_pages.
 *
 *  max_ddw_windows indicates the max number of DDW windows
 *  that can be created.  A single DDW window can still be
 *  created if max_ddw_windows is zero and a default window
 *  exists but it's creation will remove the default window.
 *
 */

typedef struct dma_data_ext dma_data_ext_t;
struct dma_data_ext
{
        struct dma_data  dma_data;

		uint32_t dma_data_ext:        1,
			 ddw_supported:       1,
			 bit_rsvd1:          30;

        uint32_t bit_rsvd2;

        uint32_t dma_data_size;

        uint32_t version;

        uint64_t supported_pgsz[DMA_DATA_MAX_WINDOW];

        uint64_t max_pages[DMA_DATA_MAX_WINDOW];

        uint64_t max_ddw_windows;
};

/*
 * The dma_stab_info structure is used for CAPI AFUs with the
 * following commands:                                             */

#define DMA_ALLOC_STAB   0x1
#define DMA_FREE_STAB    0x2

struct dma_stab_info
{
	/* Input arguments */
	/* The eye_catcher and version must be the first two fields */
	eye_catch_t eyecatcher; 
	int version;
	int stab_id;	    /* STAB identifier */
	void *stab_address; /* starting address of the STAB */
	size_t stab_size;   /* STAB size in 4K pages */
	uint64_t reserved0[4];   /* Must be set to 0 */
};

#define DMA_STAB_INFO_EYEC	0x53544142696E666FULL /* STABinfo */
#define DMA_STAB_INFO_VER0      0x53490001
#define DMA_STAB_INFO_VER       DMA_STAB_INFO_VER0
/*
 * This is the dio and d_iovec structures for the d_map_* services
 */
struct d_iovec {
        caddr_t iov_base;       /* base memory address                  */
        int32long64_t  iov_len; /* length of transfer for this area     */
        struct xmem *xmp;       /* cross memory pointer for this address*/
#ifdef __ia64
        /* IA64 machines don't have TCE support */
        caddr_t  bounce_lo;     /* virtual addr of bounced page in low mem */
        caddr_t  bounce_hi;     /* ...in high mem */
#endif /* __ia64 */
};
typedef struct d_iovec * d_iovec_t;

struct dio {
        int32long64_t  total_iovecs; /* total available iovec entries    */
        int32long64_t  used_iovecs;  /* number of used iovecs            */
        int32long64_t  bytes_done;   /* count of bytes processed         */
        int32long64_t  resid_iov;    /* number of iovec that couldn't be */
				     /* fully mapped (for NORES, DIOFULL)*/
        d_iovec_t	dvec;        /* pointer to list of d_iovecs      */
#ifdef __ia64
        int            busdd_flags;  /* internal per-mapping flags, should */
                                     /* be preserved by adapter drivers    */
                                     /* between map and unmap calls.       */
#endif
};
typedef struct dio *	dio_t;

#ifndef __64BIT_KERNEL
/*
 * These are the dio_64 and d_iovec_64 structures for the d_map_* services
 * These are used when the 64-bit interfaces are selected on the d_map_init
 * call by setting the DMA_ENABLE_64 flags.
 * NOTE: The DMA_ENABLE_64 flag will ensure that the interfaces assigned
 *       on the D_MAP_INIT call will be the 64-bit interfaces.  However, the
 *	 DMA_ADDRESS_64_BIT flag must also be set to indicate that the device
 *       is truly 64-bit capable.  In other words, BOTH of these flags must
 *       be set to take advantage of 64-bit addressing by a PCI device.
 *	 The reason the flags are distinct is to allow a single device driver
 *	 to potentially control both a 32-bit and a 64-bit device.  In this
 *	 case, the 64-bit interfaces would be used for both (single common
 *       set of interfaces for the driver independent of the device), but
 *	 the DMA_ADDRESS_64_BIT would also be set for the 64-bit device.  This
 *	 will result in 32-bit address remapping for the 32-bit device (still
 *       using 64-bit interfaces), but straight 64-bit addressing for the 64-bit
 *	 device.
 */
struct d_iovec_64 {
        unsigned long long iov_base;  /* base memory address            */
        int     iov_len;        /* length of transfer for this area     */
        struct xmem *xmp;       /* cross memory pointer for this address*/
};
typedef struct d_iovec_64 * d_iovec_64_t;

struct dio_64 {
        int     total_iovecs;           /* total available iovec entries    */
        int     used_iovecs;            /* number of used iovecs            */
        int     bytes_done;             /* count of bytes processed         */
        int	resid_iov;              /* number of iovec that couldn't be */
					/* fully mapped (for NORES, DIOFULL)*/
        d_iovec_64_t	dvec;           /* pointer to list of d_iovecs      */
};
typedef struct dio_64 *	dio_64_t;
#endif /* ! __64BIT_KERNEL */

/*
 * This is the d_handle structure for the d_map_* services
 */
typedef struct d_handle *	d_handle_t;
struct d_handle {
    uint        id;                     /* identifier for this device       */
    uint        flags;                  /* device capabilities              */
#ifdef __64BIT_KERNEL
					/* pointer to d_map_page routine    */
    int         (*d_map_page)(d_handle_t,int,caddr_t, ulong *, struct xmem *);
					/* pointer to d_unmap_page routine  */
    void        (*d_unmap_page)(d_handle_t, ulong *);
					/* pointer to d_map_list routine    */
    int         (*d_map_list)(d_handle_t, int, int, dio_t, dio_t);
					/* pointer to d_unmap_list routine  */
    void        (*d_unmap_list)(d_handle_t, dio_t);
					/* pointer to d_map_slave routine   */
    int         (*d_map_slave)(d_handle_t, int, int, dio_t, uint);
					/* pointer to d_unmap_slave routine */
    int         (*d_unmap_slave)(d_handle_t);
					/* pointer to d_map_disable routine */
    int         (*d_map_disable)(d_handle_t);
					/* pointer to d_map_enable routine  */
    int         (*d_map_enable)(d_handle_t);
					/* pointer to d_map_clear routine   */
    void        (*d_map_clear)(d_handle_t);
					/* pointer to d_sync_mem routine    */
    int         (*d_sync_mem)(d_handle_t, dio_t);
#else
    int         (*d_map_page)();        /* pointer to d_map_page routine    */
    void        (*d_unmap_page)();      /* pointer to d_unmap_page routine  */
    int         (*d_map_list)();        /* pointer to d_map_list routine    */
    void        (*d_unmap_list)();      /* pointer to d_unmap_list routine  */
    int         (*d_map_slave)();       /* pointer to d_map_slave routine   */
    int         (*d_unmap_slave)();     /* pointer to d_unmap_slave routine */
    int         (*d_map_disable)();     /* pointer to d_map_disable routine */
    int         (*d_map_enable)();      /* pointer to d_map_enable routine  */
    void        (*d_map_clear)();       /* pointer to d_map_clear routine   */
    int         (*d_sync_mem)();        /* pointer to d_sync_mem routine    */
#endif /* __64BIT_KERNEL */
    int         bid;                    /* bus id passed to d_map_init      */
    void	*bus_sys_xlate_ptr;     /* pointer to dma bus to system
					   translation information          */
#ifdef __64BIT_KERNEL
    kerrno_t	(*d_map_attr)();	/* pointer to d_map_attr routine    */
#else
    uint        reserved1;              /* padding                          */
    uint        reserved2;              /* padding                          */
#endif
    uint        reserved3;              /* padding                          */
};

extern void *d_alloc_dmamem(d_handle_t d_handle, size_t size, uint align);
extern int d_free_dmamem(d_handle_t d_handle, void *addr, size_t size);

/****************************  MACROS ************************************/
/*
 * The following macros are for to the d_map_* services
 */

/*
 * Initialize a DIO structure
 *		DIO_INIT(struct dio *d,		- pointer to dio struct
 *			 int n_iovecs);         - number of iovecs
 *		(Must only be used from process level)
 */
#define DIO_INIT(d, n_iovecs)	\
	{	((struct dio *)(d))->dvec = (struct d_iovec *)xmalloc( \
			(sizeof(struct d_iovec) * (n_iovecs)), 2, pinned_heap);\
		if (((struct dio *)(d))->dvec == NULL)			\
			((struct dio *)(d))->total_iovecs = 0;		\
		else							\
			((struct dio *)(d))->total_iovecs = n_iovecs;	\
		((struct dio *)(d))->used_iovecs = 0;			\
		((struct dio *)(d))->bytes_done = 0;			\
		((struct dio *)(d))->resid_iov = 0;			\
	}

/*
 * Free elements of a DIO structure
 *		DIO_FREE(struct dio *d)		- pointer to dio struct
 *		(Must only be used from process level)
 */
#define DIO_FREE(d) xmfree(((struct dio *)(d))->dvec, pinned_heap)

#ifndef __64BIT_KERNEL
/*
 * Initialize a 64-bit DIO structure
 *	**USED WHEN 64-bit INTERFACES ARE SELECTED...SEE DMA_ENABLE_64**
 *		DIO_INIT_64(struct dio_64 *d,	- pointer to dio struct
 *			 int n_iovecs);         - number of iovecs
 *		(Must only be used from process level)
 */
#define DIO_INIT_64(d, n_iovecs)	\
	{	((struct dio_64 *)(d))->dvec = (struct d_iovec_64 *)xmalloc( \
		   (sizeof(struct d_iovec_64) * (n_iovecs)), 2, pinned_heap);\
		if (((struct dio_64 *)(d))->dvec == NULL)		\
			((struct dio_64 *)(d))->total_iovecs = 0;	\
		else							\
			((struct dio_64 *)(d))->total_iovecs = n_iovecs; \
		((struct dio_64 *)(d))->used_iovecs = 0;		\
		((struct dio_64 *)(d))->bytes_done = 0;			\
		((struct dio_64 *)(d))->resid_iov = 0;			\
	}

/*
 * Free elements of a 64-bit DIO structure
 *	**USED WHEN 64-bit INTERFACES ARE SELECTED...SEE DMA_ENABLE_64**
 *		DIO_FREE_64(struct dio_64 *d)	- pointer to dio struct
 *		(Must only be used from process level)
 */
#define DIO_FREE_64(d)	\
	xmfree(((struct dio_64 *)(d))->dvec, pinned_heap)

#endif /* ! __64BIT_KERNEL */
/*
 * Invoke the d_map_init service
 */
#define D_MAP_INIT(bid, flags, bus_flags, channel)	\
                d_map_init(bid, flags, bus_flags, channel)

/*
 * Invoke the d_map_init_ext service
 */
#define D_MAP_INIT_EXT(dma_input, info_size, handle)	\
                d_map_init_ext(dma_input, info_size, handle)

/* 
 * Invoke the d_map_query service
 */
#define D_MAP_QUERY(bid,slot,flags,cmd,dq_info)	\
		d_map_query(bid,slot,flags,cmd,dq_info)

/*
 * Invoke the d_map_clear service for a specific bus type
 */
#define D_MAP_CLEAR(handle) (handle->d_map_clear)(handle)

/*
 * Invoke the d_map_page service for a specific bus type
 */
#define D_MAP_PAGE(handle, flags, baddr, busaddr, xmp)		\
	      (handle->d_map_page != NULL) ?			\
              (handle->d_map_page)(handle, flags, baddr, busaddr, xmp) : \
		DMA_FAIL

/*
 * Invoke the d_unmap_page service for a specific bus type
 */
#define D_UNMAP_PAGE(handle, bus_addr)				\
                if (handle->d_unmap_page != NULL)		\
                        (handle->d_unmap_page)(handle, bus_addr)

/*
 * Invoke the d_map_list service for a specific bus type
 */
#define D_MAP_LIST(handle, flags, minxfer, virt_list, bus_list)		\
           (handle->d_map_list)(handle, flags, minxfer, virt_list, bus_list)

/*
 * Invoke the d_unmap_list service for a specific bus type
 */
#define D_UNMAP_LIST(handle, bus_list)				\
                if (handle->d_unmap_list != NULL)		\
                        (handle->d_unmap_list)(handle, bus_list)

/*
 * Invoke the d_map_slave service for a specific bus type
 */
#define D_MAP_SLAVE(handle, flags, minxfer, vlist, chan_flags)		\
           (handle->d_map_slave)(handle, flags, minxfer, vlist, chan_flags)

/*
 * Invoke the d_unmap_slave service for a specific bus type
 */
#define D_UNMAP_SLAVE(handle)					\
                (handle->d_unmap_slave != NULL) ?		\
                        (handle->d_unmap_slave)(handle) : DMA_SUCC

/*
 * Invoke the d_map_disable service for a specific bus type
 */
#define D_MAP_DISABLE(handle) (handle->d_map_disable)(handle)

/*
 * Invoke the d_map_enable service for a specific bus type
 */
#define D_MAP_ENABLE(handle) (handle->d_map_enable)(handle)

/*
 * Invoke the d_sync_mem service for a specific bus type
 */
#define D_SYNC_MEM(handle, bus_list)					\
                (handle->d_sync_mem != NULL) ?		\
                            (handle->d_sync_mem)(handle, bus_list) : DMA_SUCC

/*
 * Invoke the d_map_attr service for a specific bus type 
 */
#define D_MAP_ATTR(handle, cmd, attr, attr_size)		\
                (handle->d_map_attr != NULL) ?		\
                  (handle->d_map_attr)(handle, cmd, attr, attr_size) : DMA_SUCC

/*
 * Invoke the d_alloc_dmamem service
 */
#define D_ALLOC_DMAMEM	d_alloc_dmamem

/*
 * Invoke the d_free_dmamem service
 */
#define D_FREE_DMAMEM	d_free_dmamem

/****************************  RETURN CODES ******************************/
/*
* These are for the d_map_* services
*/
#define         DMA_FAIL        -1              /* error		*/
#define         DMA_SUCC        0               /* succesful completion */
#define         DMA_NOACC		-2      /* page access violation   */
#define         DMA_NORES		-3      /* resources exhausted     */
#define         DMA_DIOFULL		-4      /* dio structure exhausted */
#define         DMA_TC_NOTREACHED       -5      /* terminal count ! reached*/
#define         DMA_BAD_MODE		-6      /* unsupported mode setting*/
#define         DMA_R_FAIL		-7      /* remote mapping failed */
#define         DMA_R_NORES		-8      /* remote mapping failed due to
						 * duplicate mappings */
/*
 * These are the kerrno_t style return codes from the DMA services
 */
#define ENOMEM_D_MAP_INIT_EXT_1		KERROR(ENOMEM, rspcios_BLOCK_00, 0x010)
#define ENOMEM_D_MAP_INIT_EXT_2		KERROR(ENOMEM, rspcios_BLOCK_00, 0x011)
#define ENOMEM_D_MAP_INIT_EXT_3		KERROR(ENOMEM, rspcios_BLOCK_00, 0x012)
#define EINVAL_D_MAP_INIT_EXT_1		KERROR(EINVAL, rspcios_BLOCK_00, 0x013)
#define EINVAL_D_MAP_INIT_EXT_2		KERROR(EINVAL, rspcios_BLOCK_00, 0x014)
#define EINVAL_D_MAP_INIT_EXT_3		KERROR(EINVAL, rspcios_BLOCK_00, 0x015)

#define ENOMEM_D_MAP_ATTR		KERROR(ENOMEM, rspcios_BLOCK_00, 0x016)
#define EINVAL_D_MAP_ATTR		KERROR(EINVAL, rspcios_BLOCK_00, 0x017)
#define EINVAL_D_MAP_ATTR_2		KERROR(EINVAL, rspcios_BLOCK_00, 0x018)
#define EINVAL_D_MAP_ATTR_3		KERROR(EINVAL, rspcios_BLOCK_00, 0x019)

#define EINVAL_D_MAP_INIT_EXT_4		KERROR(EINVAL, rspcios_BLOCK_00, 0x01A)
#define EINVAL_D_MAP_INIT_EXT_5		KERROR(EINVAL, rspcios_BLOCK_00, 0x01B)
#define EINVAL_D_MAP_INIT_EXT_6		KERROR(EINVAL, rspcios_BLOCK_00, 0x01C)

#define ENOSYS_D_MAP_QUERY		KERROR(ENOSYS, rspcios_BLOCK_00, 0x01D)
#define EINVAL_D_MAP_QUERY		KERROR(EINVAL, rspcios_BLOCK_00, 0x01E)

/*
 * These are the commands for d_map_attr() service
 */
#define D_ATTR_SET_MIN_MAPMEM	0x1UL /* Only valid with PCI DMA handles  */
#define D_ATTR_SET_DES_MAPMEM	0x2UL /* Only valid with PCI DMA handles  */
#define D_ATTR_SET_PID          0x3UL /* Only valid with CAPI DMA handles */

/****************************  MISC MACROS ******************************/
#define TCE_MAP_SIZE    4096    /* bytes */

/*************************  FUNCTION PROTOTYPES ******************************/
#ifndef _NO_PROTO

/*
 * Initialize a session with the DMA mapping services (non-microchannel)
 */
d_handle_t d_map_init(int bid, int flags, int bus_flags, uint channel);
/* arguments:
 *	int bid;			bus type/number identifier
 *	int flags;			device capabilities
 *	int bus_flags;			flags specific to the target bus
 *	uint channel;			channel assignment specific to dev/bus
 */

/*
 * Initialize a session with the DMA mapping services (non-microchannel)
 */
kerrno_t d_map_init_ext(d_info_t *dma_input, size_t info_size,
							d_handle_t *handle_ptr);
/* arguments:
 *      dma_input                       contains info like bid, flags, etc.
 *      info_size                       size of 'dma_input' in bytes
 *      handle_ptr                      dma handle returned upon success
 */

kerrno_t d_map_query( uint64_t bid, uint64_t slot, uint64_t flags, 
                         uint64_t cmd, void* dq_info);
/* arguments:
 * 	bid				bus id of device
 *	slot				slot # of device
 *	flags				flags for the query function
 *	cmd				Which query command should be run
 *	dq_info			 	The command specific data structure
 */

#else

d_handle_t d_map_init();		/* Initialize session */
kerrno_t d_map_init_ext();              /* Initialize session */
kerrno_t d_map_query();			/* Query for information */

#endif /* not _NO_PROTO */

#ifdef _KERNEL
/*******************  DYNAMIC RECONFIG AWARE DMA MAPPERS ********************/
/*
 * The following definitions, structures, and prototypes make up the various
 * components for a DMA Mapper, any entity that manages an I/O translation
 * layer (TCEs) and/or utilizes a physical address for the purpose of direct
 * memory access, to register for and handle dynamic reconfiguration events
 * corresponding to the removal and/or migration of physical memory.
 */

/*
 * DMA Mapper DR Event Handler Registration/Unregistration
 */
typedef struct dr_dma_handler {
    struct dr_dma_handler *next;              /* list of dr_dma handlers      */
    struct dr_dma_handler *active;            /* active mapping list          */
					      /* event handler                */
    int     (*handler)(struct dr_dma_handler *drh, int event, ptr64 arg);
    uint64_t   handler_data;                  /* handlers private data field  */
    uint64_t   dr_data1;		      /* data field for DR            */
    uint64_t   dr_data2;		      /* data field for DR            */
    uint       flags;			      /* flags at register time       */
    uint       dr_rsvd1;		      /* reserved                     */
    uint64_t   dr_rsvd2;		      /* reserved                     */
} dr_dma_handler_t;

/* dr_register_dma_mapperx flags
 */
#define DR_DMA_DRUNSAFE      0x1UL            /* mapper not DR-Safe           */
#define DR_DMA_SUPER_PAGE         0x2UL   /* super page mapper  */
#define DR_DMA_SUPER_PAGE_UNSAFE  0x4UL   /* mapper can't handle super page */
#define DR_DMA_ALLFLAGS      \
		(DR_DMA_DRUNSAFE|DR_DMA_SUPER_PAGE|DR_DMA_SUPER_PAGE_UNSAFE)

void dr_register_dma_mapper(dr_dma_handler_t *, rpn_t *);
int  dr_register_dma_mapperx(dr_dma_handler_t *, rpn_t *, ulong);
void dr_unregister_dma_mapper(dr_dma_handler_t *);

/*
 * DMA Handler Events and Structures
 *
 *  Event identifier and structure definition that "arg" can be cast to
 */

/*
 * Notification that memory remove is about to begin, or that it
 * is complete
 */
#define DR_DMA_RMLMB_START        0x1
#define DR_DMA_RMLMB_END          0x2
struct dr_dma_rmlmb {
    rpn_t   start;       /* starting RPN of memory range to be removed (input)*/
    rpn_t   end;         /* ending RPN (inclusive) of memory range (input)    */
    rpn_t   gencount;	 /* memory remove generation count */
};

/*
 * Query if a physical page is currently mapped for DMA
 * Returns count of mappings.
 * "arg" == RPN to query
 */
#define DR_DMA_RPN_QUERY           0x3

/*
 * Notification that migration of specified RPN is starting, and request
 * list of all active mappings for that RPN
 * Notification that physical page has been migrated (or aborted if new == old)
 */
#define DR_DMA_RPN_MIGRATE_START   0x4
#define DR_DMA_RPN_MIGRATE_END     0x5
#define DR_DMA_RPN_MAX_MAPPINGS	   256
struct dr_dma_mapping {
	uint busnum;        /* logical bus#, ibm,dma-window property (output) */
	uint hi;            /* high 4 bytes of io address (output) */
	uint mid;           /* middle 4 bytes of io address (output) */
	uint lo;            /* low 4 bytes of io address (output) */
};
struct dr_dma_rpn_migrate {
    rpn_t   rpn;            /* rpn to migrate/query (input) */
    rpn_t   new_rpn;        /* new rpn after migrate (input) */
    int     table_entries;  /* number of table entries (input) */
    int     num_mappings;   /* number of mappings (output) */
    struct dr_dma_mapping *dma_tbl; /* table of dma mappings */
};

/**************************** Non-exported Stuff ****************************/
#ifdef _KERNSYS

/* internal DR DMA services */
int dr_dma_rmlmb_start(rpn_t, rpn_t, rpn_t);
int dr_dma_rpn_query(rpn_t, int, int, int);
int dr_dma_migrate_rpn_start(rpn_t, rpn_t, int, int, int *, int *, int *);
int dr_dma_migrate_rpn(rpn_t, rpn_t, int, int, int, struct dr_dma_migfail *);
int dr_dma_migrate_rpn_io_super_page(int *, pshift_t, int, rpn_t, rpn_t, int,
				      int, struct dr_dma_migfail *);
void dr_dma_migrate_rpn_end(rpn_t, rpn_t, int, int);
void dr_dma_rmlmb_end(rpn_t, rpn_t, int *, unsigned long long *);
int  dr_dma_drunsafe(void);
int  dr_dma_get_io_super_page_option(void);
void dr_dma_set_io_super_page_option(int);


/* Error log template data */
struct  dr_dma_migfail {
    struct err_rec0   hdr; 		/* mandatory header */
    uint	      rc_hi;		/* Return code */
    uint	      rc_lo; 	
    uint              memory_address_hi; /* logical memory address */
    uint              memory_address_lo; 
    uint              hyp_rc; 		/* Hypervisor return code */
    uint	      liobn; 		/* Logical I/O Bus Number */
    uint	      dma_address_hi;	/* Hi 32-bits of 12-byte DMA address*/
    uint              dma_address_mid; 	/* DMA address */
    uint              dma_address_lo; 
};

#endif /* _KERNSYS */
/****************************************************************************/

#endif /* _KERNEL */

#ifdef __cplusplus
}
#endif

#endif /* _H_DMA */