1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 
  23 /*
  24  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
  25  */
  26 
  27 /*
  28  * Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
  29  * Use is subject to license terms.
  30  */
  31 
  32 /*      Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
  33 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T       */
  34 /*        All Rights Reserved   */
  35 
  36 /*      Copyright (c) 1988, 1989 Intel Corp.                    */
  37 /*              All Rights Reserved                             */
  38 
  39 #ifndef _SYS_DMAENGINE_H
  40 #define _SYS_DMAENGINE_H
  41 
  42 #include <sys/types.h>
  43 #include <sys/dditypes.h>
  44 
  45 #ifdef  __cplusplus
  46 extern "C" {
  47 #endif
  48 
  49 #define NCHANS  8
  50 
  51 /*
  52  * the DMA Engine Request structure
  53  */
  54 struct ddi_dmae_req {
  55         dev_info_t *der_rdip;   /* original requester's dev_info_t */
  56         uchar_t der_command;    /* Read/Write/Translate/Verify */
  57         uchar_t der_bufprocess; /* NoAuto_init/Chain/Auto_init */
  58         uchar_t der_step;       /* Inc / Dec / Hold */
  59         uchar_t der_trans;      /* Single/Demand/Block/Cascade */
  60         uchar_t der_path;       /* 8/16/32 */
  61         uchar_t der_cycles;     /* 1 or 2 */
  62         uchar_t der_dest;       /* Memory / IO */
  63         uchar_t der_arbus;      /* MicroChannel arbitration reg */
  64         ushort_t der_ioadr;     /* MicroChannel i/o address reg */
  65         ddi_dma_cookie_t *(*proc)(); /* address of application call routine */
  66         void *procparms;        /* parameter buffer for appl call */
  67 };
  68 
  69 #define DMAE_CMD_VRFY    0
  70 #define DMAE_CMD_WRITE   1      /* from memory to device */
  71 #define DMAE_CMD_READ    2      /* from device to memory */
  72 #define DMAE_CMD_TRAN    3
  73 
  74 #define DMAE_BUF_NOAUTO  0      /* default */
  75 #define DMAE_BUF_CHAIN   0x1
  76 #define DMAE_BUF_AUTO    0x2
  77 
  78 #define DMAE_STEP_INC    0      /* default */
  79 #define DMAE_STEP_DEC    1
  80 #define DMAE_STEP_HOLD   2
  81 
  82 #define DMAE_TRANS_SNGL  0      /* default */
  83 #define DMAE_TRANS_BLCK  1
  84 #define DMAE_TRANS_DMND  2
  85 #define DMAE_TRANS_CSCD  3
  86 
  87 
  88 /*
  89  * For the EISA bus
  90  */
  91 #define DMAE_PATH_DEF   0       /* default to ISA xfer width */
  92 #define DMAE_PATH_8     1       /* ISA default for chnl 0..3 */
  93 #define DMAE_PATH_16    2       /* ISA default for chnl 5..7 */
  94 #define DMAE_PATH_32    3
  95 #define DMAE_PATH_64    4
  96 #define DMAE_PATH_16B   5       /* 16-bit path but byte count */
  97 
  98 #define DMAE_CYCLES_1   0       /* Compatible timing */
  99 #define DMAE_CYCLES_2   1       /* Type "A" timing */
 100 #define DMAE_CYCLES_3   2       /* Type "B" timing */
 101 #define DMAE_CYCLES_4   3       /* Burst timing */
 102 
 103 #define DMAE_DEST_IO    0       /* default */
 104 #define DMAE_DEST_MEM   1
 105 
 106 
 107 
 108 /* public function routines */
 109 extern int i_dmae_init(dev_info_t *);
 110 extern ddi_dma_cookie_t *_dmae_nxcookie(int);
 111 extern int i_dmae_acquire(dev_info_t *, int, int (*)(), caddr_t);
 112 extern int i_dmae_free(dev_info_t *, int);
 113 extern int i_dmae_prog(dev_info_t *, struct ddi_dmae_req *,
 114         ddi_dma_cookie_t *, int);
 115 extern int i_dmae_swsetup(dev_info_t *, struct ddi_dmae_req *,
 116         ddi_dma_cookie_t *, int);
 117 extern void i_dmae_swstart(dev_info_t *, int);
 118 extern void i_dmae_stop(dev_info_t *, int);
 119 extern void i_dmae_enable(dev_info_t *, int);
 120 extern void i_dmae_disable(dev_info_t *, int);
 121 extern void i_dmae_get_chan_stat(dev_info_t *dip, int chnl,
 122         ulong_t *addressp, int *countp);
 123 
 124 /*
 125  * the DMA Channel Block structure
 126  */
 127 struct dmae_chnl {
 128         ksema_t dch_lock;               /* semaphore for this channel */
 129         ddi_dma_cookie_t *dch_cookiep;  /* current dma mapping cookie */
 130         ddi_dma_cookie_t *(*proc)();    /* address of application call */
 131                                         /* routine */
 132         void *procparms;                /* parameter buffer for appl call */
 133 };
 134 
 135 
 136 /*
 137  * DMA Engine DDI functions
 138  */
 139 
 140 /*
 141  * Get DMA engine attributes
 142  *
 143  * The attributes of the DMA engine of the parent bus-nexus are copied into
 144  * the provided structure. This should be called at driver attach time,
 145  * rather than for each DMA bind.
 146  */
 147 
 148 int ddi_dmae_getattr(dev_info_t *dip, ddi_dma_attr_t *attrp);
 149 
 150 /*
 151  * DMA channel allocation
 152  *
 153  * The allocation function must be called prior to any other DMA engine
 154  * function on a channel.  The channel should be freed after completion of the
 155  * DMA / device operation if the channel is to be shared.
 156  *
 157  * Specifics of arguments to ddi_dmae_alloc:
 158  *
 159  * dip - dev_info pointer, which identifies the base device that wishes
 160  * to use the DMA channel.
 161  *
 162  * chnl - a DMA channel number.
 163  *
 164  * dmae_waitfp - wait/callback_function pointer, which operates in the same
 165  * manner as in ddi_dma_setup().  The value DDI_DMA_DONTWAIT will cause an
 166  * immediate return if the channel cannot be acquired.  The value
 167  * DDI_DMA_SLEEP will will cause the thread to sleep and not return until
 168  * the channel has been acquired.  Any other value is assumed to be a
 169  * callback function address.
 170  *
 171  * When resources might be available, the callback function is called
 172  * (with the argument specified in arg) from interrupt context.
 173  *
 174  * When the callback function dmae_waitfp() is called, it should attempt to
 175  * allocate the DMA channel again. If it succeeds or does not need the
 176  * channel any more, it must return the value DDI_DMA_CALLBACK_DONE.
 177  * If it does not want to allocate the channel, but instead wishes to be
 178  * called back again later, it must return the value DDI_DMA_CALLBACK_LATER.
 179  * If it tries to allocate the channel, but fails to do so, it must return the
 180  * value DDI_DMA_CALLBACK_RUNOUT.
 181  *
 182  * Failure to observe this protocol will have unpredictable results.
 183  *
 184  * The callback function must provide its own data structure integrity
 185  * when it is invoked.
 186  */
 187 
 188 int ddi_dmae_alloc(dev_info_t *dip, int chnl, int (*dmae_waitfp)(),
 189     caddr_t arg);
 190 
 191 /*
 192  * DMA channel deallocation
 193  *
 194  * The deallocation function should be called after completion of the
 195  * DMA / device operation if the channel is to be shared.
 196  */
 197 
 198 int ddi_dmae_release(dev_info_t *dip, int chnl);
 199 
 200 /*
 201  * DMA channel used in 1st party DMA scheme
 202  *
 203  * The specified channel will be configured to operate in a "slave" mode
 204  * to a first_party DMA engine that also uses the channel.
 205  */
 206 
 207 int ddi_dmae_1stparty(dev_info_t *dip, int chnl);
 208 
 209 /*
 210  * Program DMA channel
 211  *
 212  * The DMA channel is setup for an operation using ddi_dmae_prog().
 213  * This function is implemented to access all capabilities of the DMA engine
 214  * hardware.  This function disables the channel prior to setup, and enables
 215  * the channel before returning.
 216  *
 217  * Specifics of arguments to ddi_dmae_prog:
 218  *
 219  * dmaereqp - pointer to a DMA engine request structure. This structure
 220  * is implementation specific and contains all the info necessary to
 221  * setup the channel, except for the memory address and count.
 222  * This structure is implemented with default values equal to zero,
 223  * so that normally only der_command has to be set with a read or write
 224  * command value.  Once the channel has been setup, subsequent calls to
 225  * ddi_dmae_prog() can have dmaereqp set to NULL if only the address and
 226  * count have to be updated.
 227  *
 228  * cookiep - pointer to a ddi_dma_cookie object which contains address,
 229  * count and intermediate memory mapping information.
 230  */
 231 
 232 int ddi_dmae_prog(dev_info_t *dip, struct ddi_dmae_req *dmaereqp,
 233         ddi_dma_cookie_t *cookiep, int chnl);
 234 
 235 int ddi_dmae_swsetup(dev_info_t *dip, struct ddi_dmae_req *dmaereqp,
 236         ddi_dma_cookie_t *cookiep, int chnl);
 237 
 238 int ddi_dmae_swstart(dev_info_t *dip, int chnl);
 239 
 240 /*
 241  * Stop DMA channel
 242  *
 243  * The DMA channel is disabled and any active operation is terminated.
 244  */
 245 
 246 int ddi_dmae_stop(dev_info_t *dip, int chnl);
 247 
 248 /*
 249  * Enable DMA channel
 250  *
 251  * The DMA channel is enabled for operation.  The channel is also enabled
 252  * after successful setup in ddi_dmae_prog().
 253  */
 254 
 255 int ddi_dmae_enable(dev_info_t *dip, int chnl);
 256 
 257 /*
 258  * Disable DMA channel
 259  *
 260  * The DMA channel is disabled so that transfers cannot continue.
 261  */
 262 
 263 int ddi_dmae_disable(dev_info_t *dip, int chnl);
 264 
 265 /*
 266  * Get remaining xfer count
 267  *
 268  * The count register of the DMA channel is read.  The channel is assumed
 269  * to be stopped.
 270  */
 271 
 272 int ddi_dmae_getcnt(dev_info_t *dip, int chnl, int *count);
 273 
 274 #ifdef  __cplusplus
 275 }
 276 #endif
 277 
 278 #endif  /* !_SYS_DMAENGINE_H */