#ifndef DEVICES_VDISK_H
#define DEVICES_VDISK_H

/*
**	$Filename: devices/vdisk.h $
**	$Revision: 3.0 $
**	$Date: 2001/08/19 16:09:32 $
**
**	vdisk device structure and value definitions version 3.6
**
**	(C) Copyright 1993-2003 by Etienne Vogt
**
*/

#ifndef EXEC_IO_H
#include "exec/io.h"
#endif

#ifndef EXEC_DEVICES_H
#include "exec/devices.h"
#endif

#ifndef EXEC_SEMAPHORES_H
#include "exec/semaphores.h"
#endif

#ifndef EXEC_MEMORY_H
#include "exec/memory.h"
#endif

#ifndef EXEC_RESIDENT_H
#include "exec/resident.h"
#endif

#ifndef	DEVICES_TIMER_H
#include "devices/timer.h"
#endif

/*
 *--------------------------------------------------------------------
 *
 * Virtual disk constants
 *
 *--------------------------------------------------------------------
 */


#define	VD_NUMSECS	32		/* Sectors per virtual track (NEW in V3) */
#define	VD_NUMSECLOG	5		/* Binary Log of sectors per track */
#define VD_NUMUNITS	16		/* Max number of units */
#define VD_NUMHEADS	1		/* Only one head !!! */


/*
 *--------------------------------------------------------------------
 *
 * Driver Specific Commands
 *
 *--------------------------------------------------------------------
 */

/*
 *-- VD_NAME is a generic macro to get the name of the driver.	This
 *-- way if the name is ever changed you will pick up the change
 *-- automatically.
 *--
 *-- Normal usage would be:
 *--
 *-- char internalName[] = VD_NAME;
 *--
 */

#define	VD_NAME	"vdisk.device"

/*-- Extended commands are not supported !
 *-- CLEAN and DELETE custom commands have disappeared : Use the functions instead
 */

#define	VD_MOTOR	(CMD_NONSTD+0)	/* DUMMY : returns 1 to Make-User-Happy */
#define	VD_SEEK		(CMD_NONSTD+1)	/* just verify track numbers */
#define	VD_FORMAT	(CMD_NONSTD+2)	/* AS WRITE (NEW in 2.0 !) */
#define	VD_REMOVE	(CMD_NONSTD+3)	/* INVALID : returns error */
#define	VD_CHANGENUM	(CMD_NONSTD+4)	/* returns 0 if unit valid, else 1 */
#define	VD_CHANGESTATE	(CMD_NONSTD+5)	/* returns 0 if unit valid, else 1 */
#define	VD_PROTSTATUS	(CMD_NONSTD+6)	/* DUMMY : always returns 0 */
#define	VD_RAWREAD	(CMD_NONSTD+7)	/* INVALID : returns error */
#define	VD_RAWWRITE	(CMD_NONSTD+8)	/* INVALID : returns error */
#define	VD_GETDRIVETYPE	(CMD_NONSTD+9)	/* DUMMY : returns 0 */
#define	VD_GETNUMTRACKS	(CMD_NONSTD+10)	/* get number of virtual tracks on this unit */
#define VD_ADDCHANGEINT	(CMD_NONSTD+11)	/* INVALID : returns error */
#define VD_REMCHANGEINT	(CMD_NONSTD+12)	/* INVALID : returns error */
#define VD_GETGEOMETRY	(CMD_NONSTD+13)	/* gets the unit geometry table (NEW in V3) */
#define	VD_LASTCOMM	(CMD_NONSTD+14)	/* dummy placeholder for end of list */


/*
 *--------------------------------------------------------------------
 *
 * Driver error defines
 *
 *--------------------------------------------------------------------
 */

#define	VDERR_NotSpecified	20	/* general catchall */
#define	VDERR_NoVTrack		21	/* virtual track is completely out-to-lunch */
#define	VDERR_BadVTrack		22	/* virtual track looks wrong */
#define	VDERR_BadSecSum		25	/* sector data had incorrect checksum */
#define	VDERR_NoVDisk		29	/* unit is not valid */
#define	VDERR_SeekError		30	/* virtual track number didn't match */
#define	VDERR_NoMem		31	/* no memory for virtual track */
#define	VDERR_BadUnit		32	/* bad unit number or pointer */

/*
 *--------------------------------------------------------------------
 *
 * Virtual Disk recovery Errors
 *
 *--------------------------------------------------------------------
 */

#define	VDE_Deleted	1	/* unit has been deleted */
#define	VDE_NoRoot	2	/* no root structure found (normal at coldstart) */
#define	VDE_BadRootSum	3	/* root structure had incorrect checksum */
#define	VDE_BadSecSum	4	/* a sector checksum failed */
#define	VDE_NoVTrack	5	/* a virtual track was invalid */
#define	VDE_AllocError	6	/* something couldn't be reallocated */
#define VDE_NoUnit	7	/* couldn't find unit structure */
#define VDE_BadUnitSum	8	/* unit structure had incorrect checksum */
#define	VDE_BadRootVer	9	/* root structure version mismatch */
#define VDE_Unknown	10	/* unknown error */


/*
 *---------------------------------------------------------------------
 *
 * Device Data structures
 * Note that most fields are private, subject to change and have indeed
 * already changed between various versions.
 *
 *---------------------------------------------------------------------
 */

#ifndef DOS_DOS_H
typedef long BPTR;
#endif

struct VDT_VTrack {
	struct MemChunk  vdt_MC;	/* leave space for a memory chunk at start */
	ULONG	vdt_CheckMark;		/* virtual track structure identifier */
	UWORD	vdt_TrackNum;		/* virtual track number */
	UWORD	vdt_SectorSize;		/* physical sector size (512, 1024 or 2048) */
	ULONG	vdt_SectorUse;		/* sector usage flags */
	ULONG	vdt_SectorSums[VD_NUMSECS];  /* sector data checksums */
	ULONG	vdt_Sectors[0];		/* sector data start here */
};

#define	MAX_DNAME_SIZE	10

struct VDU_Unit {
	struct MemChunk  vdu_MC;	/* leave space for a memory chunk at start */
	ULONG	vdu_CheckMark;		/* unit structure identifier */
	struct VD_Dev	*vdu_Device;	/* pointer to device structure */
	ULONG	vdu_IOCount;		/* IO operations counter */
	ULONG	vdu_CleanCount;		/* cleaning operations counter */
	ULONG	vdu_CheckSum;		/* unit structure checksum */
	UBYTE	vdu_UnitNum;		/* unit number */
	UBYTE	vdu_Flags;		/* unit flags */
	UWORD	vdu_NumTracks;		/* number of virtual tracks */
	UWORD	vdu_RootTrack;		/* root track number */
	BYTE	vdu_Priority;		/* boot priority order */
	UBYTE	vdu_SecSizeLog;		/* sector size binary logarithm */
	ULONG	vdu_DOSType;		/* DOSType identifier */
	UWORD	vdu_AllocFlags;		/* Memory request attributes */
	UWORD	vdu_SectorSize;		/* physical sector size (512, 1024 or 2048) */
	ULONG	vdu_RootKey;		/* filesystem root block number */
	UWORD	vdu_DosHighCyl;		/* HighCyl value as given in mountfile */
	UWORD	vdu_DosSurfaces;	/* Surfaces value as given in mountfile */
	UWORD	vdu_DosSectPerTrack;	/* SectorsPerTrack value as given in mountfile */
	UBYTE	vdu_DosName[MAX_DNAME_SIZE];	/* AmigaDOS device name */
	struct VDT_VTrack  *vdu_VTracks[0];  /* pointers to virtual tracks */
};

struct VDR_Root {
	struct MemChunk  vdr_MC;	/* leave space for a memory chunk at start */
	ULONG	vdr_CheckMark;		/* root structure identifier */
	ULONG	vdr_CheckSum;		/* root structure checksum */
	UBYTE	vdr_Version;		/* root version ID */
	UBYTE	vdr_LinkNum;		/* order in linked list (not used yet) */
	UWORD	vdr_LostUnits;		/* number of lost units */
	struct VDU_Unit	 *vdr_Units[VD_NUMUNITS];  /* pointers to unit structures */
	UBYTE	vdr_RecErrs[VD_NUMUNITS];  /*units recovery error codes */
	UWORD	vdr_Hotspots[8];	/* false fast mem hotspots saved here */
	ULONG	vdr_UnitSizes[VD_NUMUNITS]; /* Sizes of unit structures */
	APTR	vdr_Link;		/* pointer to another root (not used yet) */
	struct Resident vdr_Resident;	/* RomTag for resident module */
	UBYTE	vdr_ResNameBuffer[14];	/* Buffer for module name (vdisk.root) */
	struct EClockVal vdr_EClockStamp; /* Expunge Time stamp (used when reloading) */
	APTR	vdr_KickTagArray[2];	/* Array for link into KickTagPtr */
	struct MemList vdr_MemList;	/* Struct MemList and MemEntry for KickMemPtr */
	ULONG	vdr_EndMark;		/* end of root structure identifier */
	ULONG	vdr_Reserved;		/* reserved null longword */
};

struct VD_Dev {
	struct Library  vd_Lib;		/* Library structure */
	struct ExecBase	*vd_Execbase;	/* pointer to exec */
	BPTR	vd_SegList;		/* BCPL pointer to device code segment */
	struct VDR_Root	 *vd_Root;	/* pointer to root structure */
	ULONG	vd_RecErr;		/* recovery error code for unit 0 */
	UWORD	vd_ActUnits;		/* number of active units */
	UWORD	vd_RealOpnCnt;		/* real device open count */
	struct SignalSemaphore	vd_SigSem;  /* signal semaphore for memory arbitration */
	struct DosLibrary *vd_DOSBase;	/* pointer to dos (PRIVATE !) */
	APTR	vd_PhantomRoot;		/* pointer to bad root structure (PRIVATE !) */
	struct Interrupt vd_MemHandler; /* Low memory handler (OS 3.x only) */
	ULONG	vd_TempData;		/* Temporary storage */
	struct timerequest vd_TimerReq;	/* Timerequest structure */
	struct EClockVal vd_EClock;	/* EClockVal structure */
};


/* Structure CheckMarks */

#define VD_ROOTID	0x05407210
#define VD_UNITID	0x05408440
#define VD_TRACKID	0x05409670


/* PRIVATE Unit flags (others below) */

#define VDUB_VALID	7		/* Indicate a valid unit */

#define VDUF_VALID	(1L << VDUB_VALID)

/* Public Unit Flags passed to OpenDevice() */

#define	VDB_AUTOCLEAN	0		/* Request autocleaning */
#define VDB_ALLOCRETRY	1		/* Request allocation retry */
#define	VDB_ERRORKILL	2		/* Data error on init will kill unit */
#define	VDB_AUTOMOUNT	3		/* Unit will be remounted on early init */
#define	VDB_BOOTABLE	4		/* Unit will be bootable */
#define	VDB_NOCLEAN	5		/* Don't try to reclaim memory from this unit */
#define	VDB_VOLATILE	6		/* Don't preserve content across reboots */

#define VDF_AUTOCLEAN	(1L << VDB_AUTOCLEAN)
#define VDF_ALLOCRETRY	(1L << VDB_ALLOCRETRY)
#define VDF_ERRORKILL	(1L << VDB_ERRORKILL)
#define VDF_AUTOMOUNT	(1L << VDB_AUTOMOUNT)
#define	VDF_BOOTABLE	(1L << VDB_BOOTABLE)
#define	VDF_NOCLEAN	(1L << VDB_NOCLEAN)
#define	VDF_VOLATILE	(1L << VDB_VOLATILE)

/* Alert definitions */

#define AN_VDisk	0x50000000	/* SubSystem ID */
#define AN_VDRootMem	0x50010001	/* No memory for root structure */
#define AN_VDUnitMem	0x50010002	/* No memory for unit structure */
#define AN_VDReAlloc	0x50010003	/* Memory reallocation failed */
#define AN_VDAllocAbs	0x50010004	/* AllocAbs() failed in AllocReverse */
#define	AN_VDBadStartup	0x50000005	/* Error in Unit Startup (mountlist) */
#define AN_VDBadRootLoc	0x50010006	/* Root Structure in bad False Fast Memory */
#define	AO_VDisk	0x00008050	/* Alert Object */

/* Flags for CleanVdisk() */

#define	VDCB_FREECHIP	0		/* Try to free CHIP memory */
#define	VDCB_REBUILD	1		/* Correct potential recovery problems */
#define	VDCB_FORCE	2		/* Overrides VDB_NOCLEAN */

#define VDCF_FREECHIP	(1L << VDCB_FREECHIP)
#define VDCF_REBUILD	(1L << VDCB_REBUILD)
#define VDCF_FORCE	(1L << VDCB_FORCE)

#endif	/* DEVICES_VDISK_H */
