/* 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 #include #include #include #include #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 */