/*  iopacket.h -- Define VIOS I/O Packet structure
 *  copyright (c) American Information Systems Corporation
 *	Daniel Steinberg
 *	November, 1984
 *
 */
#ifndef IOPACKET
#define IOPACKET

#include "devices.h"
#include "osiopkt.h"

#define PKTSIZE  ALIGN(sizeof(IO_PACKET))

/* Define the individual pieces */

typedef union
	{
	VDD_PTR virtual;	/* either a ptr to a virtual or */
	PDD_PTR physical;	/*   physical device descriptor */
	}  PKT_DEVPTR;

typedef struct
	{
	char  *virt;		/* user virtual address */
	char  *map;		/* user virtual -> physical mapping */	/*??*/
	}  PKT_UADDRESS;

typedef struct
	{
	PKT_UADDRESS     addr;	/* address of user buffer */
	unsigned   byte_count;	/* size of user buffer */
	}  PKT_UBUFFER;

#define Ubaddr(x)	((x)->addr.virt)
#define Ubmap(x)	((x)->addr.map)
#define Ubsize(x)	((x)->byte_count)


/* Define flags in Ubmap */

/*#define PHYS_BUFFER	NULL		/* OS buffer is Physical Address */
#define POOL_BUFFER	-1		/* Buffer is VIOS pool bufptr */
#define MAPPED_BUFFER	-2		/* Buffer is bufptr to mapping list */
	/* Any other value is PTB address for mapped buffer */


typedef struct
	{
	PKT_UBUFFER  buf_1;	/* I/O data buffer */
	char	     **aux;	/* aux. data or parameter buffer */
	unsigned     eter[4];	/* extra parameters */
	}  PKT_PARAMETERS;

typedef struct
	{
	union
	    {
	    UB16     unction;	/* either a single function number */
	    PKT_FUNCTION   u;	/*         or a code to pick apart */
	    }
	                f;	/* [one of the above]  */
	PKT_PARAMETERS  param;	/* function parameters */
	}  PKT_REQUEST;


typedef struct
	{
	union
	    {
	    int (*routine)();	/* either a completion routine address */
	    int intrpt_vector;	/*     or a simulated interrupt vector */
	    }
	              retn;		/* [one of the above] */
	union
	    {
	    PKT_UADDRESS addr;	/* addr & map of user status buffer */
	    int        **vspkt;	/* addr of packet to receive status */
	    }
	              stat;		/* [one of the above] */
	OS_IDENT   id;		/* operating system identifier */
	}  PKT_COMP_INFO;


/* Define the macros that extract fields from an indirected ptr to a packet */
/* #define Next(x)			((x)->next) */
/* #define Last(x)			((x)->last) */
#define Parent(x) 		((x)->parent)
#define Handler(x)		((x)->handler)
#define VDevice(x)		((x)->device.virtual)
#define PDevice(x)		((x)->device.physical)
#define Function(x)		((x)->request.f.unction)
#define Ftype(x)		((x)->request.f.u.nc_type)
#define Fcode(x)		((x)->request.f.u.nc_code)
#define Fmod(x)			((x)->request.f.u.nc_mod)
#define Ubuffer(x)		((x)->request.param.buf_1)
#define Ubufaddr(x)		((x)->request.param.buf_1.addr.virt)
#define Ubufmap(x)		((x)->request.param.buf_1.addr.map)
#define Ubufsize(x)		((x)->request.param.buf_1.byte_count)
#define Auxparam(x)		((x)->request.param.aux)
#define Params(x)		((x)->request.param.eter)
#define Param1(x)		((x)->request.param.eter[0])
#define Param2(x)		((x)->request.param.eter[1])
#define Param3(x)		((x)->request.param.eter[2])
#define Param4(x)		((x)->request.param.eter[3])
#define Status(x)		((x)->status)
#define Statcode(x)		((x)->status.code)
#define Statauxcode(x)		((x)->status.aux_code)
#define Statbcount(x)		((x)->status.bcount)
#define Stataux1(x)		((x)->status.bcount)
#define Stataux2(x)		((x)->status.aux_stat2)
#define Stataux3(x)		((x)->status.aux_stat3)
#define Stataux4(x)		((x)->status.aux_stat4)
#define Osid(x)			((x)->os)
#define Compos(x)		((x)->completion.id)
#define Comproutine(x)		((x)->completion.retn.routine)
#define Compvector(x)		((x)->completion.retn.intrpt_vector)
#define Cstataddr(x)		((x)->completion.stat.addr.virt)
#define Cstatmap(x)		((x)->completion.stat.addr.map)
#define Parentstat(x)		((x)->completion.stat.vspkt)
#define Timeout(x)		((x)->timeout.tmu)
#define Timecount(x)		((x)->timeout.tm.count)
#define Timescale(x)		((x)->timeout.tm.scale)
#define Priority(x)  		((x)->priority)
#define State(x)  		((x)->state)
#define Stnum(x)  		((x)->stnum)
#define Iocount(x)		((x)->iocount)

/* Now define the actual I/O Packet */

typedef struct  IO_PK
	{
	struct IO_PK    **next;		/* ptr to next packet in queue */
	struct IO_PK    **last;		/* ptr to previous packet in queue */
	struct IO_PK    **parent;	/* ptr to parent packet */
	PKT_HANDLER       handler;	/* address of current I/O handler */
	PKT_DEVPTR        device;	/* ptr to device descriptor */
	PKT_REQUEST       request;	/* Virtual or Primitive I/O request */
	PKT_IOSTATUS      status;	/* current I/O status */
	OS_IDENT          os;		/* owner of I/O request */
	PKT_COMP_INFO     completion;	/* I/O request completion info */
	PKT_TIMEOUT       timeout;	/* request timeout */
	PKT_PRIORITY      priority;	/* request priority */
	PKT_STATE         state;	/* current processing state */
	PKT_STNUM         stnum;	/* state number (used by handlers) */
	_IOCOUNT       iocount;		/* count of spawned I/O requests */
	}  IO_PACKET, **PKT_PTR;

#endif
