/*++
"This software program is available to you under a choice of one of two
licenses.  You may choose to be licensed under either the GNU General Public
License (GPL) Version 2, June 1991, available at
http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
the text of which follows:

"Recipient" has requested a license and Intel Corporation ("Intel") is willing
to grant a license for the software entitled InfiniBand(tm) System Software
(the "Software") being provided by Intel Corporation.

The following definitions apply to this License:

"Licensed Patents" means patent claims licensable by Intel Corporation which
are necessarily infringed by the use or sale of the Software alone or when
combined with the operating system referred to below.

"Recipient" means the party to whom Intel delivers this Software.
"Licensee" means Recipient and those third parties that receive a license to
any operating system available under the GNU Public License version 2.0 or
later.

Copyright (c) 1996-2003 Intel Corporation. All rights reserved.

The license is provided to Recipient and Recipient's Licensees under the
following terms.

Redistribution and use in source and binary forms of the Software, with or
without modification, are permitted provided that the following conditions are
met:
Redistributions of source code of the Software may retain the above copyright
notice, this list of conditions and the following disclaimer.

Redistributions in binary form of the Software may reproduce the above
copyright notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

Neither the name of Intel Corporation nor the names of its contributors shall
be used to endorse or promote products derived from this Software without
specific prior written permission.

Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
royalty-free patent license under Licensed Patents to make, use, sell, offer
to sell, import and otherwise transfer the Software, if any, in source code
and object code form. This license shall include changes to the Software that
are error corrections or other minor changes to the Software that do not add
functionality or features when the Software is incorporated in any version of
a operating system that has been distributed under the GNU General Public
License 2.0 or later.  This patent license shall apply to the combination of
the Software and any operating system licensed under the GNU Public License
version 2.0 or later if, at the time Intel provides the Software to Recipient,
such addition of the Software to the then publicly available versions of such
operating system available under the GNU Public License version 2.0 or later
(whether in gold, beta or alpha form) causes such combination to be covered by
the Licensed Patents. The patent license shall not apply to any other
combinations which include the Software. No hardware per se is licensed
hereunder.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
--*/

/*
 * Abstract:
 *	This module defines the data structure and APIs for the kernel mode
 *	component of the device framework.
 *
 * Environment:
 *	Linux Kernel Mode
 *
 * $Revision: 1.1 $
 */

#ifndef _CL_DEVICE_H_
#define _CL_DEVICE_H_

#include <complib/cl_types.h>
#include <complib/cl_qlist.h>
#include <complib/cl_qmap.h>
#include <complib/cl_waitobj.h>

#ifdef LINUX
#include <linux/ioctl.h>
#else
#include <sys/ioctl.h>
#endif
#ifdef __KERNEL__
#include <linux/mm.h>
#endif

/****h* Component Library/Device Framework
* NAME
*	Device Framework
*
* DESCRIPTION
*	The device framework provides functionality exchanging information between
*	kernel mode and user mode components.
*
*	In kernel mode, the device framework provides functionality for creating
*	devices and providing various entry points that are called when an
*	application	using the user-mode device framework accesses the device.
*
*	In user mode, the device framework provides applications with a simplified
*	device usage model, allowing access to a device created using the kernel
*	mode device framework.
*********/

/*
 * Generic way to define a IOCTL_CMD
 */

#define IOCTL_CMD(dev_id, command)	_IO((dev_id), (command))

/****d* Component Library: Device Framework/cl_dev_name_t
* NAME
*	cl_dev_name_t
*
* DESCRIPTION
*	cl_dev_name defines the name of the system device being created.
*
* SYNOPSIS
*/
typedef char *cl_dev_name_t;
/*
* NOTES
*	In Linux this string turns is similar to "/dev/iba0".
*********/

/****s* Component Library: Device Framework/cl_ioctl_info_t
* NAME
*	cl_ioctl_info_t
*
* PURPOSE
*	Defines the command and the input parameters for an ioctl passed
*	in from user mode.
*
* SYNOPSIS
*/
typedef struct _cl_ioctl_info {
	uintn_t command;	/* IOCTL Command */
	void *p_buf;		/* Pointer to the input buffer */
	uintn_t buf_size;	/* Size of the input buffer */
	uintn_t num_bytes_ret;	/* Bytes returned by the ioctl */
	cl_status_t io_status;	/* Status of the IOCTL */

} cl_ioctl_info_t;
/**********/

#ifdef __KERNEL__

/* Linux Kernel Mode */

/****d* Component Library: Device Framework/cl_dev_handle_t (Kernel Mode)
* NAME
*	cl_dev_handle_t (Kernel Mode)
*
* DESCRIPTION
*	Handle to an device framework created device object.
*
* SYNOPSIS
*/
typedef void *cl_dev_handle_t;
/*********/

/****d* Component Library: Device Framework/cl_pfn_dev_open_t
* NAME
*	cl_pfn_dev_open_t
*
* DESCRIPTION
*	Prototype of the driver exported "open" function. This function
*	is called when a user mode application opens the device
*
* SYNOPSIS
*/
typedef cl_status_t
    (*cl_pfn_dev_open_t) (IN void *p_device_context,
			  OUT void **pp_open_context);

/*
* PARAMETERS
*	p_device_context
*		[in] device specific context passed into the open function. This
*		is defined when the device is first created.
*
*	pp_open_context
*		[out] context specific to this open. This is set by the open call
*		and is passed into the read, write, mmap, ioctl and close calls.
*
* RETURN VALUE
*	This function returns a status of type cl_status_t
*	TBD
*
* NOTES
*
* SEE ALSO
*	Device Framework, cl_pfn_dev_close_t, cl_pfn_dev_ioctl_t, cl_pfn_dev_mmap_t
*************/

/****d* Component Library: Device Framework/cl_pfn_dev_close_t
* NAME
*	cl_pfn_dev_close_t
*
* DESCRIPTION
*	Prototype of the driver exported "close" function. This function
*	is called when a user mode application closes the device.
*
* SYNOPSIS
*/
typedef cl_status_t
    (*cl_pfn_dev_close_t) (IN void *p_device_context, IN void *p_open_context);

/*
* PARAMETERS
*	p_device_context
*		[in] device specific context passed into the close function. This
*		is defined when the device is first created.
*
*	p_open_context
*		[in] context specific to this open. This is set by the open call.
*
* RETURN VALUE
*	This function returns a status of type cl_status_t
*	TBD
*
* NOTES
*
* SEE ALSO
*	Device Framework, cl_pfn_dev_open_t, cl_pfn_dev_ioctl_t, cl_pfn_dev_mmap_t
*************/

/****d* Component Library: Device Framework/cl_pfn_dev_ioctl_t
* NAME
*	cl_pfn_dev_ioctl_t
*
* DESCRIPTION
*	Prototype of the driver exported "ioctl" function. This function
*	is called when a user mode application issues and IO control to
*	the device.
*
* SYNOPSIS
*/
typedef void
 (*cl_pfn_dev_ioctl_t) (IN void *p_device_context,
			IN void *p_open_context,
			IN OUT cl_ioctl_info_t * p_ioctl_info);
/*
* PARAMETERS
*	p_device_context
*		[in] device specific context passed into the open function. This
*		is created when the device is first created.
*
*	p_open_context
*		[in] context specific to this open. This is set by the open call.
*
*	p_ioctl_info
*		[in/out] On input contains the input parameters such as the command,
*		the input buffer and it's size. On output, contains the output
*		buffer and the number of bytes returned.
*
* RETURN VALUE
*	This function does not return a value.
*
* NOTES
*	The IOCTL completion status is returned in the status field of the
*	p_ioctl_info structure.
*
*	If set to CL_SUCCESS, the command completed successfully. The results
*	are returned in the same buffer (p_ioclt_info->p_in_buf) and num_ret_bytes
*	are copied by the device framework into the output buffer and returned
*	back to user mode.
*
*	If set to CL_PENDING, the command did not complete (further processing
*	required by the kernel handler). If the user application does not specify
*	an OS wait object (see cl_ioctl_info_t), the device framework will suspend
*	the execution of the current thread (put it to sleep). If a wait object is
*	provided, the device framework will return immediately. The user mode
*	application must check the status of the command and get results using
*	get_ioctl_status
*
*	Other failure status values will cause the device framework to perform
*	all necessary cleanup for the IOCTL before returning to the user.
*
*	The mechanism to support pending ioclts is currently not supported.
*
* SEE ALSO
*	Device Framework, cl_pfn_dev_open_t, cl_pfn_dev_close_t, cl_pfn_dev_mmap_t
************/

/****d* Component Library: Device Framework/cl_pfn_dev_cancel_ioctl_t
* NAME
*	cl_pfn_dev_cancel_ioctl_t
*
* DESCRIPTION
*	Prototype of the driver exported "ioctl" function. This function
*	is called when a blocked ioctl is interrupted due to a signal
*
* SYNOPSIS
*/
typedef void
 (*cl_pfn_dev_cancel_ioctl_t) (IN void *p_device_context,
			       IN void *p_open_context,
			       IN cl_ioctl_info_t * p_ioctl_info);
/*
* PARAMETERS
*	p_device_context
*		[in] device specific context passed into the open function. This
*		is created when the device is first created.
*
*	p_open_context
*		[in] context specific to this open. This is set by the open call.
*
*	p_ioctl_info
*		[in] contains the kernel ioctl buffer
*
* RETURN VALUE
*	This function does not return a value.
*
* NOTES
*
* SEE ALSO
*	Device Framework, cl_pfn_dev_open_t, cl_pfn_dev_close_t, cl_pfn_dev_mmap_t
************/

/****d* Component Library: Device Framework/cl_pfn_dev_mmap_t
* NAME
*	cl_pfn_dev_mmap_t
*
* DESCRIPTION
*	Prototype of the driver exported "mmap" function. This function
*	is called when a user mode application calls mmap on this device.
*
* SYNOPSIS
*/
typedef cl_status_t
    (*cl_pfn_dev_mmap_t) (IN void *p_device_context,
			  IN void *p_open_context,
			  IN struct vm_area_struct * p_vma);
/*
* PARAMETERS
*	p_device_context
*		[in] device specific context passed into the open function. This
*		is created when the device is first created.
*
*	pp_open_context
*		[out] context specific to this open. This is set by the open call.
*
* RETURN VALUE
*	CL_SUCCESS if the operation was successful.
*
*	CL_ERROR if the operation failed.
*
* SEE ALSO
*	Device Framework, cl_pfn_dev_open_t, cl_pfn_dev_close_t, cl_pfn_dev_ioctl_t
************/

/****s* Component Library: Device Framework/cl_dev_info_t
* NAME
*	cl_dev_info_t
*
* DESCRIPTION
*	Provides information about for creation of a system device.
*
* SYNOPSIS
*/
typedef struct _cl_dev_info {
	cl_dev_name_t name;	/* name of the device to create */
	void *p_device_context;	/* device context */
	cl_pfn_dev_open_t pfn_open;	/* open function */
	cl_pfn_dev_close_t pfn_close;	/* close function */
	cl_pfn_dev_ioctl_t pfn_ioctl;	/* ioctl function */
	cl_pfn_dev_cancel_ioctl_t pfn_cancel_ioctl;	/* cancel ioctl function */
	cl_pfn_dev_mmap_t pfn_mmap;	/* mmap function */
	uint32_t max_use_count;	/* maximum usage count */

} cl_dev_info_t;
/*
* FIELDS
*	name
*		Name of the device to create.
*
*	p_device_context
*		Device context.
*
*	pfn_open
*		open function.
*
*	pfn_close
*		close function.
*
*	pfn_ioctl
*		ioctl function.
*
*	pfn_mmap
*		mmap function.
*
*	max_use_count
*		maximum usage count.
*
* NOTES
*	The consumer of the device framework defines the name of the device,
*	a device context and various handlers and registers with the device
*	framework.
*
* SEE ALSO
*	Device Framework, cl_pfn_dev_open_t, cl_pfn_dev_close_t,
*	cl_pfn_dev_ioctl_t, cl_pfn_dev_mmap_t
**********/

/****f* Component Library: Device Framework/cl_dev_create
* NAME
*	cl_dev_create
*
* DESCRIPTION
*	This function creates a device accessible from a user mode application.
*	The device (a character device) can be accessed by opening it.
*
* SYNOPSIS
*/
cl_status_t
cl_dev_create(IN cl_dev_info_t * p_dev_info, OUT cl_dev_handle_t * ph_dev);
/*
* PARAMETERS
*	p_dev_info
*		[in] Pointer to the structure containing information about
*		the system device that needs to be created.
*
*	ph_dev
*		[out] Handle to the created system device.
*
* RETURN VALUE
*	CL_SUCCESS
*		The device is created successfully.
*
*	CL_INVALID_PARAMETER
*		An input parameter was invalid.
*
*	CL_ERROR
*		The function failed to create a device.
*
* SEE ALSO
*	Device Framework, cl_delete_device
*********/

/****d* Component Library: Device Framework/cl_delete_device
* NAME
*	cl_delete_device
*
* DESCRIPTION
*	Delete a system device.
*
* SYNOPSIS
*/
void
 cl_dev_destroy(IN cl_dev_handle_t h_dev);
/*
* PARAMETERS
*	h_dev
*		[in] handle to the system device. This is returned by cl_dev_create.
*
* RETURN VALUE
*	This function does not return a value.
*
* SEE ALSO
*	Device Framework, cl_dev_create
*********/

/****d* Component Library: Device Framework/cl_complete_io
* NAME
*	cl_complete_io
*
* DESCRIPTION
*	This function is used by the driver ioctl handler to indicate that a
*	pending ioctl command has completed. The device framework uses this
*	"notification" to wake up the blocked user mode thread and complete
*	the ioctl. The user mode thread is blocked when the driver ioctl handler
*	returns CL_PENDING (cannot complete the ioclt command immediately).
*
* SYNOPSIS
*/
cl_status_t cl_complete_io(IN cl_ioctl_info_t * p_ioctl_info);
/*
* PARAMETERS
*	p_ioctl_info
*		[in] Pointer to the kernel ioctl info structure that was passed in
*		by the device framework into the ioctl handler.
*
* RETURN VALUE
*	CL_SUCCESS
*		Completed pending ioctl operation from a previous ioctl command
*		successfully.
*
*	CL_INVALID_PARAMETER
*		The p_ioctl_info parameter was not valid.
*
* NOTES
*	When the kernel ioctl handler returns CL_PENDING for a command, the
*	user mode application is blocked (if the OS wait object is NULL) or
*	returned with CL_PENDING (if a wait object is specified). If a wait
*	object is specified, the wait object is now signaled and the user mode
*	application needs to call get_ioctl_status() to get results of the
*	ioctl command (This isn't supported yet). If the OS wait object isn't
*	specified, and the user mode application was blocked by the driver
*	framework, it is unblocked now and returned.
*
* SEE ALSO
*	Device Framework, cl_dev_create, cl_delete_device.
*********/

/****f* Component Library: Device Framework/cl_dev_init
* NAME
*	cl_dev_init
*
* DESCRIPTION
*	Initialize internal data structures for creating and managing system
*	devices and this framework.
*
* SYNOPSIS
*/
cl_status_t __cl_dev_frmwk_init(void);
/*
* RETURN VALUE
*	CL_SUCCESS
*		If the system device framework was initialized successfully.
*
*	CL_INSUFFICIENT_RESOURCES
*		Failed to allocate/acquire some system resource.
*
* NOTES
*	This function is called by drivers needing to use the driver framework.
*	For instance, the driver might need to support IOCTL calls.
*
* SEE ALSO
*	Device Framework, cl_dev_destroy
*********/

/****f* Component Library: Device Framework/cl_dev_destroy
* NAME
*	cl_dev_destroy
*
* DESCRIPTION
*	Cleanup all internal data structures, created in system_dev_init,
*	to support system devices and this framework
*
* SYNOPSIS
*/
void
 __cl_dev_frmwk_destroy(void);
/*
* RETURN VALUE
*	This function does not return a value.
*
* NOTES
*	This function is called by a driver that needed device framework support
*	and called system_dev_init. This function cleans up everything allocated
*	in system_dev_init.
*
* SEE ALSO
*	Device Framework, cl_dev_init
*********/

cl_status_t
cl_get_open_context(IN int fd,
		    OUT void **p_open_context, OUT cl_dev_info_t ** p_dev_info);

#else				/* __KERNEL__ */

/* Linux User Mode */

/****d* Component Library: Device Framework/cl_dev_handle_t (User Mode)
* NAME
*	cl_dev_handle_t (User Mode)
*
* DESCRIPTION
*	Handle to an device framework created device object.
*
* SYNOPSIS
*/
typedef intn_t cl_dev_handle_t;
/*********/

/****f* Component Library: Device Framework/cl_open_device
* NAME
*	cl_open_device
*
* DESCRIPTION
*	Opens a system device. A user mode application needs to open a device
*	and use the returned device handle to use the device.
*
*	The device must be closed when the application has finished using the
*	device.
*
* SYNOPSIS
*/
cl_status_t
cl_open_device(IN cl_dev_name_t device_name, OUT cl_dev_handle_t * ph_dev);

/*
* PARAMETERS
*	device_name
*		[in] Name of the device to open.  This is the same name that was used to
*		create the kernel mode device.
*
*	ph_dev
*		[out] pointer to the location that holds the device handle. This handle
*		is used to reference this device in other calls like cl_close_device etc.
*
* RETURN VALUE
*	CL_SUCCESS
*		The open call succeeded.
*
*	CL_INVALID_PARAMETER
*		The consumer passed in an invalid parameter.
*
*	CL_ERROR
*		The device does not exist, open failed.
*
* NOTES
*	A kernel driver must use the kernel mode device framework to create this
*	device before it can be opened.
*
* SEE ALSO
*	Device Framework, cl_close_device, cl_iocl_device.
********/

/****f* Component Library: Device Framework/cl_close_device
* NAME
*	cl_close_device
*
* DESCRIPTION
*	Closes an open system device.
*
* SYNOPSIS
*/
void
 cl_close_device(IN cl_dev_handle_t h_dev);

/*
* PARAMETERS
*	h_dev
*		[in] Handle to an open device returned by a previous call
*		to cl_open_device.
*
* RETURN VALUE
*	This function does not return a value.
*
* SEE ALSO
*	cl_open_device, cl_ioctl_device
********/

/****f* Component Library: Device Framework/cl_ioctl_device
* NAME
*	cl_ioctl_device
*
* DESCRIPTION
*	Issue an io control (ioctl) operation to a device. The device must
*	be opened before this can be done.
*
* SYNOPSIS
*/
cl_status_t
cl_ioctl_device(IN cl_dev_handle_t dev_handle,
		IN uint32_t command,
		IN void *p_buf,
		IN uintn_t buf_size, OUT uintn_t * p_num_bytes_ret);
/*
* PARAMETERS
*	dev_handle
*		[in] Handle to an open device. Returned by cl_open_device.
*	command
*		[in] The ioctl command for the kernel handler.
*	p_buf
*		[in] pointer to the input buffer to pass arguments to the kernel
*			 handler. The same buffer will hold the results too.
*	buf_size
*		[in] size of the previous argument (p_buf).
*	p_num_bytes_ret
*		[in] actual number of bytes returned in the output buffer by the
*			 kernel handler.
*
* RETURN VALUE
*	The ioctl status returned by the kernel handler.
*
* SEE ALSO
*	Device Framework, cl_open_device, cl_close_device.
********/

#endif				// __KERNEL__

#endif				// _CL_DEVICE_H_
