#ifndef DEVICES_XFLOPPY_H
#define DEVICES_XFLOPPY_H

#ifndef EXEC_DEVICES_H
#include <exec/devices.h>
#endif
#ifndef EXEC_IO_H
#include <exec/io.h>
#endif
#ifndef EXEC_ERRORS_H
#include <exec/errors.h>
#endif
#ifndef DEVICES_TRACKDISK_H
#include <devices/trackdisk.h>
#endif

#ifndef CLIB_EXEC_PROTOS_H
#include <clib/exec_protos.h>
#endif

#define	XFLOPPYVERSION		1
#define	XFLOPPYREVISION		1

#define	XFD_MAXUNIT		3
#define XFD_RAWBUFSIZE		13000
#define	XFD_RAWREADSIZE		12200
#define	XFD_RAWWRITESIZE	12200

#define XFD_TRACKSECTORS	14
#define XFD_TRACKSIZE		(XFD_TRACKSECTORS*512)
#define XFD_TRACKBUFSIZE	XFD_TRACKSIZE

#define XFD_DD_TOTSECTORS	(XFD_TRACKSECTORS*2*80)
#define XFD_DD_CYLSECTORS	(XFD_TRACKSECTORS*2)
#define XFD_DD_TRACKSECTORS	XFD_TRACKSECTORS
#define XFD_HD_TOTSECTORS	(XFD_TRACKSECTORS*2*80*2)
#define XFD_HD_CYLSECTORS	(XFD_TRACKSECTORS*2*2)
#define XFD_HD_TRACKSECTORS	(XFD_TRACKSECTORS*2)

#define	XFD_SYNCWORD	0x92
#define	XFD_SYNCTRAIL	0xaa

#define	XFLOPPYNAME		"xfloppy.device"


/* debugging */
/*#define DEBUG*/

#define bug kprintf
#ifdef DEBUG
void kprintf(UBYTE *fmt,...);
#define D(x) x
#else
#define D(x) 
#endif


struct xfd_OpenSingle {
    struct Task			*xos_Task; /* pointer to task to signal */
    struct xfdOpenSingle	*xos_next; /* next entry */
};
#define WAKEUPSIGF  ((long)1<<15)    /* ctrl e */

struct XFDevice {
	struct Device	xfd_Device;
	LONG		xfd_SegList;		/* pointer to device segment-list */
/*	APTR		xfd_RawBuffer;		 * common buffer for raw read/write */
	struct	XFDUnit*xfd_Unit[XFD_MAXUNIT];	/* pointers to unit tasks */
/*	WORD		xfd_OpenFree;	 TRUE if no entries in OpenWait queue */
	struct	xfd_OpenSingle *xfd_OpenWait;	
				/* list for singlethreading opendev calls*/
/*	struct	IOExtTD *xfd_TDIOReq[XFD_MAXUNIT;*/ /*pointers to unit TD io reqs */
};

struct XFDUnit {
	struct  MsgPort xdu_MsgPort;
	UBYTE		xdu_Flags;
	UBYTE		xdu_pad;
	UWORD		xdu_OpenCnt;
	UWORD		xdu_UnitNr;		/* our unit number */
	struct IOExtTD *xdu_TDIOReq;	/* TDioreq for this unit */
	UBYTE 		*xdu_TrackBuffer;	/* trackbuffer */
	WORD		xdu_BuffTrNum;	/* nr of track currently in buffer */
					/* -1 -> buffer is empty  */
	APTR		xdu_RawBuffer;  /* raw data buffer */
};

#define XFDB_BUFDIRTY	4
#define XFDF_BUFDIRTY	(1<<4)


struct XFDIOReq {
	struct	Message		io_Message;
	struct	XFDevice       *io_Device;	/* device node pointer  */
	struct	XFDUnit        *io_Unit;	/* unit (driver private)*/
	UWORD	io_Command;			/* device command */
	UBYTE	io_Flags;
	BYTE	io_Error;			/* error or warning num */
	ULONG	io_Actual;		/* actual number of bytes transferred */
	ULONG	io_Length;		/* requested number bytes transferred*/
	APTR    io_Data;		/* points to data area */
	ULONG   io_Offset;		/* offset for block structured devices */
	ULONG	io_Count;		/* diskchange count */
};

struct xfd_startupmsg {
	struct	Message st_msg;
	struct XFDevice *st_Device;
	struct XFDUnit  *st_Unit;
	UWORD		st_cmd;
	UBYTE		st_unitnum;
	UBYTE		st_result;
};
    
/*  COMMANDS */

#define XFF_EXTCOM (1<<15)

#define XF_MOTOR        (CMD_NONSTD+0)
#define XF_SEEK         (CMD_NONSTD+1)
#define XF_FORMAT       (CMD_NONSTD+2)
#define XF_REMOVE       (CMD_NONSTD+3)  /* notify when disk changes */
#define XF_CHANGENUM    (CMD_NONSTD+4)  /* number of disk changes */
#define XF_CHANGESTATE  (CMD_NONSTD+5)  /* is there a disk in the drive? */
#define XF_PROTSTATUS   (CMD_NONSTD+6)  /* is the disk write protected? */
#define XF_RAWREAD      (CMD_NONSTD+7)  /* read raw bits from the disk */
#define XF_RAWWRITE     (CMD_NONSTD+8)  /* write raw bits to the disk */
#define XF_GETDRIVETYPE (CMD_NONSTD+9)  /* get the type of the disk drive */
#define XF_GETNUMTRACKS (CMD_NONSTD+10) /* # of tracks for this type drive */
#define XF_ADDCHANGEINT (CMD_NONSTD+11)
#define XF_REMCHANGEINT (CMD_NONSTD+12) /* remove softint set by ADDCHANGEINT */
#define XF_GETGEOMETRY  (CMD_NONSTD+13) /* gets the disk geometry table */
#define XF_EJECT        (CMD_NONSTD+14) /* for those drives that support it */
#define XF_STARTUP		33000	 /* for marking the startup msg */   
#define XF_STOPDOWN		33001	 /* for marking the stopdown msg */   

/* ERRORS */

#define	XFDERR_NotAligned	36	/* data request  not sector aligned */
#define	XFDERR_Coding		37	/* error at coding */
#define XFDERR_Decoding		38	/* error at decoding */
#define XFDERR_NoSyncTrail	39	/* sync trail a trackbegin not found */
#define XFDERR_LongSyncTrail	40	/* sync trail too long */
#define XFDERR_NoSyncWord	41	/* no sync word found */

#endif
