1*17169044Sbrutus /* 2*17169044Sbrutus * CDDL HEADER START 3*17169044Sbrutus * 4*17169044Sbrutus * The contents of this file are subject to the terms of the 5*17169044Sbrutus * Common Development and Distribution License (the "License"). 6*17169044Sbrutus * You may not use this file except in compliance with the License. 7*17169044Sbrutus * 8*17169044Sbrutus * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*17169044Sbrutus * or http://www.opensolaris.org/os/licensing. 10*17169044Sbrutus * See the License for the specific language governing permissions 11*17169044Sbrutus * and limitations under the License. 12*17169044Sbrutus * 13*17169044Sbrutus * When distributing Covered Code, include this CDDL HEADER in each 14*17169044Sbrutus * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*17169044Sbrutus * If applicable, add the following below this CDDL HEADER, with the 16*17169044Sbrutus * fields enclosed by brackets "[]" replaced with your own identifying 17*17169044Sbrutus * information: Portions Copyright [yyyy] [name of copyright owner] 18*17169044Sbrutus * 19*17169044Sbrutus * CDDL HEADER END 20*17169044Sbrutus */ 21*17169044Sbrutus 22*17169044Sbrutus /* 23*17169044Sbrutus * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*17169044Sbrutus * Use is subject to license terms. 25*17169044Sbrutus */ 26*17169044Sbrutus 27*17169044Sbrutus #ifndef _SYS_DCOPY_H 28*17169044Sbrutus #define _SYS_DCOPY_H 29*17169044Sbrutus 30*17169044Sbrutus #pragma ident "%Z%%M% %I% %E% SMI" 31*17169044Sbrutus 32*17169044Sbrutus #ifdef __cplusplus 33*17169044Sbrutus extern "C" { 34*17169044Sbrutus #endif 35*17169044Sbrutus 36*17169044Sbrutus #include <sys/types.h> 37*17169044Sbrutus 38*17169044Sbrutus /* 39*17169044Sbrutus * *** This interface is for private use by the IP stack only *** 40*17169044Sbrutus */ 41*17169044Sbrutus 42*17169044Sbrutus /* Private dcopy/uioa interface for dcopy to enable/disable dcopy KAPI */ 43*17169044Sbrutus extern void uioa_dcopy_enable(); 44*17169044Sbrutus extern void uioa_dcopy_disable(); 45*17169044Sbrutus 46*17169044Sbrutus /* Function return status */ 47*17169044Sbrutus #define DCOPY_FAILURE (-1) 48*17169044Sbrutus #define DCOPY_SUCCESS (0) 49*17169044Sbrutus #define DCOPY_NORESOURCES (1) /* _alloc & _cmd_alloc, _cmd_post only */ 50*17169044Sbrutus #define DCOPY_PENDING (0x10) /* dcopy_poll(), dcopy_unregister() */ 51*17169044Sbrutus #define DCOPY_COMPLETED (0x20) /* dcopy_poll() only */ 52*17169044Sbrutus 53*17169044Sbrutus 54*17169044Sbrutus /* dq_version */ 55*17169044Sbrutus #define DCOPY_QUERY_V0 0 56*17169044Sbrutus 57*17169044Sbrutus typedef struct dcopy_query_s { 58*17169044Sbrutus int dq_version; /* DCOPY_QUERY_V0 */ 59*17169044Sbrutus uint_t dq_num_channels; /* number of dma channels */ 60*17169044Sbrutus } dcopy_query_t; 61*17169044Sbrutus 62*17169044Sbrutus /* 63*17169044Sbrutus * dcopy_query() 64*17169044Sbrutus * query for the number of DMA engines usable in the system. 65*17169044Sbrutus */ 66*17169044Sbrutus void dcopy_query(dcopy_query_t *query); 67*17169044Sbrutus 68*17169044Sbrutus 69*17169044Sbrutus typedef struct dcopy_channel_s *dcopy_handle_t; 70*17169044Sbrutus 71*17169044Sbrutus /* dcopy_alloc() and dcopy_cmd_alloc() common flags */ 72*17169044Sbrutus #define DCOPY_SLEEP (0) 73*17169044Sbrutus #define DCOPY_NOSLEEP (1 << 0) 74*17169044Sbrutus 75*17169044Sbrutus /* 76*17169044Sbrutus * dcopy_alloc() 77*17169044Sbrutus * Allocate a DMA channel which is used for posting DMA requests. Note: this 78*17169044Sbrutus * does not give the caller exclusive access to the DMA engine. Commands 79*17169044Sbrutus * posted to a channel will complete in order. 80*17169044Sbrutus * flags - (DCOPY_SLEEP, DCOPY_NOSLEEP) 81*17169044Sbrutus * returns => DCOPY_FAILURE, DCOPY_SUCCESS, DCOPY_NORESOURCES 82*17169044Sbrutus */ 83*17169044Sbrutus int dcopy_alloc(int flags, dcopy_handle_t *handle); 84*17169044Sbrutus 85*17169044Sbrutus /* 86*17169044Sbrutus * dcopy_free() 87*17169044Sbrutus * Free the DMA channel. The client can no longer use the handle to post or 88*17169044Sbrutus * poll for status on posts which were previously done on this channel. 89*17169044Sbrutus */ 90*17169044Sbrutus void dcopy_free(dcopy_handle_t *handle); 91*17169044Sbrutus 92*17169044Sbrutus /* dq_version */ 93*17169044Sbrutus #define DCOPY_QUERY_CHANNEL_V0 0 94*17169044Sbrutus 95*17169044Sbrutus /* Per DMA channel info */ 96*17169044Sbrutus typedef struct dcopy_query_channel_s { 97*17169044Sbrutus int qc_version; /* DCOPY_QUERY_CHANNEL_V0 */ 98*17169044Sbrutus 99*17169044Sbrutus /* Does DMA channel support DCA */ 100*17169044Sbrutus boolean_t qc_dca_supported; 101*17169044Sbrutus 102*17169044Sbrutus /* device id and device specific capabilities */ 103*17169044Sbrutus uint64_t qc_id; 104*17169044Sbrutus uint64_t qc_capabilities; 105*17169044Sbrutus 106*17169044Sbrutus /* 107*17169044Sbrutus * DMA channel size. This may not be the same as the number of posts 108*17169044Sbrutus * that the DMA channel can handle since a post may consume 1 or more 109*17169044Sbrutus * entries. 110*17169044Sbrutus */ 111*17169044Sbrutus uint64_t qc_channel_size; 112*17169044Sbrutus 113*17169044Sbrutus /* DMA channel number within the device. Not unique across devices */ 114*17169044Sbrutus uint64_t qc_chan_num; 115*17169044Sbrutus } dcopy_query_channel_t; 116*17169044Sbrutus 117*17169044Sbrutus /* 118*17169044Sbrutus * dcopy_query_channel() 119*17169044Sbrutus * query DMA engines capabilities 120*17169044Sbrutus */ 121*17169044Sbrutus void dcopy_query_channel(dcopy_handle_t handle, dcopy_query_channel_t *query); 122*17169044Sbrutus 123*17169044Sbrutus 124*17169044Sbrutus /* dp_version */ 125*17169044Sbrutus #define DCOPY_CMD_V0 0 126*17169044Sbrutus 127*17169044Sbrutus /* dp_cmd */ 128*17169044Sbrutus #define DCOPY_CMD_COPY 0x1 129*17169044Sbrutus 130*17169044Sbrutus /* dp_flags */ 131*17169044Sbrutus /* 132*17169044Sbrutus * DCOPY_CMD_QUEUE 133*17169044Sbrutus * Hint to queue up the post but don't notify the DMA engine. This can be 134*17169044Sbrutus * used as an optimization when multiple posts are going to be queued up and 135*17169044Sbrutus * you only want notify the DMA engine after the last post. Note, this does 136*17169044Sbrutus * not mean the DMA engine won't process the request since it could notice 137*17169044Sbrutus * it anyway. 138*17169044Sbrutus * DCOPY_CMD_NOSTAT 139*17169044Sbrutus * Don't generate a status. If this flag is used, You cannot poll for 140*17169044Sbrutus * completion status on this command. This can be a useful performance 141*17169044Sbrutus * optimization if your posting multiple commands and just want to poll on 142*17169044Sbrutus * the last command. 143*17169044Sbrutus * DCOPY_CMD_DCA 144*17169044Sbrutus * If DCA is supported, direct this and all future command data (until the 145*17169044Sbrutus * next command with DCOPY_POST_DCA set) to the processor specified in 146*17169044Sbrutus * dp_dca_id. This flag is ignored if DCA is not supported. 147*17169044Sbrutus * DCOPY_CMD_INTR 148*17169044Sbrutus * Generate an interrupt when command completes. This flag is required if 149*17169044Sbrutus * the caller is going to call dcopy_cmd_poll(() with DCOPY_POLL_BLOCK set 150*17169044Sbrutus * for this command. 151*17169044Sbrutus */ 152*17169044Sbrutus #define DCOPY_CMD_NOFLAGS (0) 153*17169044Sbrutus #define DCOPY_CMD_QUEUE (1 << 0) 154*17169044Sbrutus #define DCOPY_CMD_NOSTAT (1 << 1) 155*17169044Sbrutus #define DCOPY_CMD_DCA (1 << 2) 156*17169044Sbrutus #define DCOPY_CMD_INTR (1 << 3) 157*17169044Sbrutus 158*17169044Sbrutus typedef struct dcopy_cmd_copy_s { 159*17169044Sbrutus uint64_t cc_source; /* Source physical address */ 160*17169044Sbrutus uint64_t cc_dest; /* Destination physical address */ 161*17169044Sbrutus size_t cc_size; 162*17169044Sbrutus } dcopy_cmd_copy_t; 163*17169044Sbrutus 164*17169044Sbrutus typedef union dcopy_cmd_u { 165*17169044Sbrutus dcopy_cmd_copy_t copy; 166*17169044Sbrutus } dcopy_cmd_u_t; 167*17169044Sbrutus 168*17169044Sbrutus typedef struct dcopy_cmd_priv_s *dcopy_cmd_priv_t; 169*17169044Sbrutus 170*17169044Sbrutus struct dcopy_cmd_s { 171*17169044Sbrutus uint_t dp_version; /* DCOPY_CMD_V0 */ 172*17169044Sbrutus uint_t dp_flags; 173*17169044Sbrutus uint64_t dp_cmd; 174*17169044Sbrutus dcopy_cmd_u_t dp; 175*17169044Sbrutus uint32_t dp_dca_id; 176*17169044Sbrutus dcopy_cmd_priv_t dp_private; 177*17169044Sbrutus }; 178*17169044Sbrutus typedef struct dcopy_cmd_s *dcopy_cmd_t; 179*17169044Sbrutus 180*17169044Sbrutus 181*17169044Sbrutus /* 182*17169044Sbrutus * dcopy_cmd_alloc() specific flags 183*17169044Sbrutus * DCOPY_ALLOC_LINK - when set, the caller passes in a previously alloced 184*17169044Sbrutus * command in cmd. dcopy_cmd_alloc() will allocate a new command and 185*17169044Sbrutus * link it to the old command. The caller can use this to build a 186*17169044Sbrutus * chain of commands, keeping only the last cmd alloced. calling 187*17169044Sbrutus * dcopy_cmd_free() with the last cmd alloced in the chain will free all of 188*17169044Sbrutus * the commands in the chain. dcopy_cmd_post() and dcopy_cmd_poll() have 189*17169044Sbrutus * no knowledge of a chain of commands. It's only used for alloc/free. 190*17169044Sbrutus */ 191*17169044Sbrutus #define DCOPY_ALLOC_LINK (1 << 16) 192*17169044Sbrutus 193*17169044Sbrutus /* 194*17169044Sbrutus * dcopy_cmd_alloc() 195*17169044Sbrutus * allocate a command. A command can be re-used after it completes. 196*17169044Sbrutus * flags - (DCOPY_SLEEP || DCOPY_NOSLEEP), DCOPY_ALLOC_LINK 197*17169044Sbrutus * returns => DCOPY_FAILURE, DCOPY_SUCCESS, DCOPY_NORESOURCES 198*17169044Sbrutus */ 199*17169044Sbrutus int dcopy_cmd_alloc(dcopy_handle_t handle, int flags, dcopy_cmd_t *cmd); 200*17169044Sbrutus 201*17169044Sbrutus /* 202*17169044Sbrutus * dcopy_cmd_free() 203*17169044Sbrutus * free the command. This call cannot be called after dcopy_free(). 204*17169044Sbrutus */ 205*17169044Sbrutus void dcopy_cmd_free(dcopy_cmd_t *cmd); 206*17169044Sbrutus 207*17169044Sbrutus /* 208*17169044Sbrutus * dcopy_cmd_post() 209*17169044Sbrutus * post a command (allocated from dcopy_cmd_alloc()) to the DMA channel 210*17169044Sbrutus * returns => DCOPY_FAILURE, DCOPY_SUCCESS, DCOPY_NORESOURCES 211*17169044Sbrutus */ 212*17169044Sbrutus int dcopy_cmd_post(dcopy_cmd_t cmd); 213*17169044Sbrutus 214*17169044Sbrutus /* dcopy_cmd_poll() flags */ 215*17169044Sbrutus #define DCOPY_POLL_NOFLAGS (0) 216*17169044Sbrutus #define DCOPY_POLL_BLOCK (1 << 0) 217*17169044Sbrutus 218*17169044Sbrutus /* 219*17169044Sbrutus * dcopy_cmd_poll() 220*17169044Sbrutus * poll on completion status of a previous post. This call cannot be called 221*17169044Sbrutus * after dcopy_free(). 222*17169044Sbrutus * 223*17169044Sbrutus * if flags == DCOPY_POLL_NOFLAGS, return status can be DCOPY_FAILURE, 224*17169044Sbrutus * DCOPY_PENDING, or DCOPY_COMPLETED. 225*17169044Sbrutus * 226*17169044Sbrutus * if flags & DCOPY_POLL_BLOCK, return status can be DCOPY_FAILURE or 227*17169044Sbrutus * DCOPY_COMPLETED. DCOPY_POLL_BLOCK can only be set in base context. 228*17169044Sbrutus * 229*17169044Sbrutus * The command cannot be re-used or freed until the command has completed 230*17169044Sbrutus * (e.g. DCOPY_FAILURE or DCOPY_COMPLETED). 231*17169044Sbrutus */ 232*17169044Sbrutus int dcopy_cmd_poll(dcopy_cmd_t cmd, int flags); 233*17169044Sbrutus 234*17169044Sbrutus 235*17169044Sbrutus #ifdef __cplusplus 236*17169044Sbrutus } 237*17169044Sbrutus #endif 238*17169044Sbrutus 239*17169044Sbrutus #endif /* _SYS_DCOPY_H */ 240