/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_DCOPY_DEVICE_H
#define _SYS_DCOPY_DEVICE_H
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#include <sys/dcopy.h>
/*
* private command state. Space for this structure should be allocated during
* (*cb_cmd_alloc). The DMA driver must set dp_private in dcopy_cmd_t to point
* to the memory it allocated. Other than pr_device_cmd_private, the DMA driver
* should not touch any of the fields in this structure. pr_device_cmd_private
* is a private pointer for the DMA engine to use.
*/
struct dcopy_cmd_priv_s {
/*
* we only init the state used to track a command which blocks when it
* actually blocks. pr_block_init tells us when we need to clean it
* up during a cmd_free.
*/
boolean_t pr_block_init;
/* dcopy_poll blocking state */
list_node_t pr_poll_list_node;
volatile boolean_t pr_wait;
kmutex_t pr_mutex;
kcondvar_t pr_cv;
/* back pointer to the command */
dcopy_cmd_t pr_cmd;
/* shortcut to the channel we're on */
struct dcopy_channel_s *pr_channel;
/* DMA driver private pointer */
void *pr_device_cmd_private;
};
/* cb_version */
#define DCOPY_DEVICECB_V0 0
typedef struct dcopy_device_chaninfo_s {
uint_t di_chan_num;
} dcopy_device_chaninfo_t;
typedef struct dcopy_device_cb_s {
int cb_version;
int cb_res1;
/* allocate/free a DMA channel. See dcopy.h for return status */
int (*cb_channel_alloc)(void *device_private,
dcopy_handle_t handle, int flags, uint_t size,
dcopy_query_channel_t *info, void *channel_private);
void (*cb_channel_free)(void *channel_private);
/* allocate/free a command. See dcopy.h for return status */
int (*cb_cmd_alloc)(void *channel_private, int flags,
dcopy_cmd_t *cmd);
void (*cb_cmd_free)(void *channel_private, dcopy_cmd_t *cmd);
/*
* post a command/poll for command status. See dcopy.h for return
* status
*/
int (*cb_cmd_post)(void *channel_private, dcopy_cmd_t cmd);
int (*cb_cmd_poll)(void *channel_private, dcopy_cmd_t cmd);
/*
* if dcopy_device_unregister() returns DCOPY_PENDING, dcopy will
* call this routine when all the channels are no longer being
* used and have been free'd up. e.g. it's safe for the DMA driver
* to detach.
* status = DCOPY_SUCCESS || DCOPY_FAILURE
*/
void (*cb_unregister_complete)(void *device_private, int status);
} dcopy_device_cb_t;
typedef struct dcopy_device_info_s {
dev_info_t *di_dip;
dcopy_device_cb_t *di_cb; /* must be a static array */
uint_t di_num_dma;
uint_t di_maxxfer;
uint_t di_capabilities;
uint64_t di_id;
} dcopy_device_info_t;
typedef struct dcopy_device_s *dcopy_device_handle_t;
/* dcopy_device_notify() status */
#define DCOPY_COMPLETION 0
/*
* dcopy_device_register()
* register the DMA device with dcopy.
* return status => DCOPY_FAILURE, DCOPY_SUCCESS
*/
int dcopy_device_register(void *device_private, dcopy_device_info_t *info,
dcopy_device_handle_t *handle);
/*
* dcopy_device_unregister()
* try to unregister the DMA device with dcopy. If the DMA engines are
* still being used by upper layer modules, DCOPY_PENDING will be returned.
* return status => DCOPY_FAILURE, DCOPY_SUCCESS, DCOPY_PENDING
* if DCOPY_PENDING, (*cb_unregister_complete)() will be called when
* completed.
*/
int dcopy_device_unregister(dcopy_device_handle_t *handle);
/*
* dcopy_device_channel_notify()
* Notify dcopy of an event.
* dcopy_handle_t handle => what was passed into (*cb_alloc)()
* status => DCOPY_COMPLETION
*/
void dcopy_device_channel_notify(dcopy_handle_t handle, int status);
#ifdef __cplusplus
}
#endif
#endif /* _SYS_DCOPY_DEVICE_H */