
/*
 Copyright 1999 by Digi International (www.digi.com)

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the 
 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 PURPOSE.  See the GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
 *      DXB Message types
 *
 *	It is believed that these structures will be effectively "packed"
 *	with any compiler we are likely to deal with.  If not, we will
 *	need to uglify this file with conditional directives to invoke
 *	non-standard packing extensions to C.
 *
 *	However, just as a precaution against compilers which might pad
 *	the total structure length out to a multiple of the machine wordsize
 *	(which may be 64 bits), we have include DXB_MSG_*_SIZE #defines,
 *	which are probably preferable to use instead of sizeof() when
 *	the length of a message must be determined.
 *
 */
#ifndef _DXBGLBL_H
#define	_DXBGLBL_H

/*
 *	An open message
 */
#define DXB_TYPE_OPEN   	0x08
#define DXB_MSG_OPEN_SIZE	8
typedef struct dxb_msg_open
{
	dxb_uint8	type;
	dxb_uint8	channel;
	#ifdef DXBOLD
		dxb_uint16	credit_award;
	#else
		dxb_uint8	fixed_cost;
		dxb_uint8	unused;
	#endif
	dxb_uint16	ctrl_len;
	dxb_uint16	data_len;
} DXB_MSG_OPEN;

/*
 *	A close message
 */
#define DXB_TYPE_CLOSE		0x09
#define DXB_MSG_CLOSE_SIZE	4
typedef struct dxb_msg_close
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	pad;
} DXB_MSG_CLOSE;


/*
 *	A data message
 */
#define DXB_TYPE_DATA   	0x02
#define	DXB_MSG_DATA_SIZE	4
typedef struct dxb_msg_data
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	data_len;
} DXB_MSG_DATA;

/*
 *	A cdata message
 */
#define DXB_TYPE_CDATA  0x03
#define	DXB_MSG_CDATA_SIZE	8
typedef struct dxb_msg_cdata
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	priority;
	dxb_uint16	ctrl_len;
	dxb_uint16	data_len;
} DXB_MSG_CDATA;

/*
 *	A queue start message.  When never generate these in this
 *	implementation.  This may be deprecated.
 */
#define DXB_TYPE_START  	0x01
#define	DXB_MSG_START_SIZE	4
typedef struct dxb_msg_start
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	pad;
} DXB_MSG_START;

/*
 *	A credit message
 */
#define DXB_TYPE_CREDIT 	0x06
#define	DXB_MSG_CREDIT_SIZE	4
typedef struct dxb_msg_credit
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	credit_award;
} DXB_MSG_CREDIT;

/*
 *	A cancel message
 */
#define DXB_TYPE_CANCEL		0x0b
#define DXB_MSG_CANCEL_SIZE	4
typedef struct dxb_msg_cancel
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	command;
} DXB_MSG_CANCEL;

/*
 *	A link message
 */
#define DXB_TYPE_LINK		0x05
#define	DXB_MSG_LINK_SIZE	8
typedef struct dxb_msg_link
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	other_channel;
	dxb_uint16	ctrl_len;
	dxb_uint16	data_len;
} DXB_MSG_LINK;

/*
 *	An unlink message
 */
#define DXB_TYPE_UNLINK		0x0a
#define	DXB_MSG_UNLINK_SIZE	8
typedef struct dxb_unlink
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	mux_id;
	dxb_uint16	ctrl_len;
	dxb_uint16	data_len;
} DXB_MSG_UNLINK;

/*
 *	A push message
 */
#define DXB_TYPE_PUSH		0x0c
#define	DXB_MSG_PUSH_SIZE	8
typedef struct dxb_msg_push
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	pad;
	dxb_uint16	ctrl_len;
	dxb_uint16	data_len;
} DXB_MSG_PUSH;

/*
 *	A pop message
 */
#define DXB_TYPE_POP		0x0d
#define	DXB_MSG_POP_SIZE	8
typedef struct dxb_msg_pop
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	pad;
	dxb_uint16	ctrl_len;
	dxb_uint16	data_len;
} DXB_MSG_POP;

/*
 *	A flush message
 */
#define DXB_TYPE_FLUSH		0x07
#define	DXB_MSG_FLUSH_SIZE	8
typedef struct dxb_msg_flush
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint8	flush_read;
	dxb_uint8	flush_write;
	dxb_uint16	ctrl_len;
	dxb_uint16	data_len;
} DXB_MSG_FLUSH;

/*
 *	An ioctl message
 */
#define DXB_TYPE_IOCTL		0x04
#define	DXB_MSG_IOCTL_SIZE	8
typedef struct dxb_msg_ioctl
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	command;
	dxb_uint16	ctrl_len;
	dxb_uint16	data_len;
} DXB_MSG_IOCTL;

/*
 *	A generic message used for implementations to switch on message type
 *	This message is never sent.
 */
#define	DXB_MSG_GENERIC_SIZE	8
typedef struct dxb_msg_generic
{
	dxb_uint8	type;
	dxb_uint8	channel;
	dxb_uint16	pad[3];
} DXB_MSG_GENERIC;


/*
 *	DXB message error codes
 */
#define	DXB_OK			0
#define	DXB_UNKNOWN_VALUE	1
#define	DXB_INVALID_CHANNEL	2
#define	DXB_OUT_OF_RANGE	3
#define	DXB_REFUSED		4
#define	DXB_INTERRUPTED		5
#define	DXB_UNAVAILABLE		6

/*
 *	DXB  Global Communication structures.
 */

/*
 *	This controls the maximum number of pages that a buffer may be
 *	split into.  It is a manifest constant of the implementation of both
 *	the driver and the FEP.  Changing this requires recompiling both.
 *
 *	Thus, we have made it bigger than anybody could possible need (haha).
 */
#define	DXB_MAX_PHYS_PAGES	128

/*
 *	We need to be able to communicate the bus addresses of the host's
 *	queue in/out locations to the board.  This structure holds those
 *	addresses.
 *
 * 	This structure is intentionally not "endian safe".  See the note
 *	attached to DXBBUF for details.
 */
typedef struct
{
	uint32	host2adapter_in;
	uint32	host2adapter_out;
	uint32	adapter2host_in;
	uint32	adapter2host_out;
} DXBQPHYS;

/*
 *	The DXB queue structures need to hold address(es) of the page(s) of
 *	circular buffers for the queues.  On the host side, these addresses
 *	are typically virtual addresses.  But on the board side, these
 *	addresses are typically bus addresses (a.k.a. physical addresses
 *	on Intel architectures, but not the same on, say, Alpha).
 *
 *	We would like to have just one definition of the DXB structures
 *	regardless of which side of the bus we are on, so we define this
 *	union.  The "alloc" member serves to insure that we always allocate
 *	the same amount of storage for this whether or not a (void *) is
 *	32 bits or 64 bits.
 *
 *	NOTE: any structure definitions that have members of this type
 *	must insure that this type is aligned on a 64 bit boundary.
 */
typedef union dxbaddr
{
	uint8		*virt;
	uint32		bus;
	uint32		alloc[2];
} DXBADDR;

/*
 *	Before the FEP is started, the host fills in the GLOBAL_HOST_DATA
 *	structure and leaves the bus address of it at GLOBAL_HOST_OFFSET
 *	in shared mem.  This stucture contains the DXBPHYS structure below.
 *
 *	The FEP DMA's this information to its side of the bus and uses
 *	this to size its queues accordingly.
 *
 *	The DXBPHYS structure contains two DXBBUF structures which define
 *	the physical page(s) of the two circular buffers on the host side.
 *	It also contains the DXBQPHYS structure which has the physical
 *	addresses of the four in/out pointers on the host side.
 *
 *	An implicit agreement is made that npages*pagesize is a power
 *	of two.  If the host can allocate physically contiguous memory
 *	of any size, it can simply set npages to 1 and pagesize to the
 *	size of the queue.  Otherwise, it must break up the allocation
 *	into multiple pages.
 *
 *	These structures must a multiple of 32 bytes in size, to avoid
 *	screwing up the cacheline-32 safeness of other structures that
 *	include these structures.
 * 
 *	This structure is intentionally not "endian safe" and is written
 * 	and read in the native endianness of each side.   Since this data
 *	is written once by each side and read a zillion times, dxb_pys_init()
 *	handles any needed swapping on the way in.
 * 
 *	**IMPORTANT NOTE** This means if you change anything in this 
 * 			   structure, you must examine dxb_phys_init() 
 *			   and manually handle endianenss issues.
 *	
 */
typedef struct
{
	uint32	npages;		/* Number of pages host is providing */
	uint32	pagesize;	/* Size of a "page" */

	uint32	pagemask;	/* Size of a page - 1 */
	uint32	pageshift;	/* Shift amt to convert addr to page */
	uint32	size;		/* Total size of buffer */
	uint32	mask;		/* Mask to wrap in/out offsets */
	uint32	mask4;		/* mask & ~3 */

	pad_32	pad[1];			/* Keep size a multiple of 32 */

	DXBADDR	page[DXB_MAX_PHYS_PAGES];/* Physical addresses of a page */
} DXBBUF;

typedef struct
{
	DXBBUF		host2adapter_q;

	DXBBUF		adapter2host_q;

	DXBQPHYS	qphys;

	/*
	 *	Keep the size of this structure a multiple of 32 bytes
	 */
	pad_32	pad[6];
} DXBPHYS;

#endif
