/*-
 *  $Id: han.h,v 1.4 90/01/27 20:33:22 Rhialto Exp $
 *
 *  The header file for the MESSYDOS: file system handler
 *
-*/

#include "dev.h"

#define MODE_READWRITE	1004L
#define MODE_CREATEFILE (1L<<31)
#define FILE_DIR    1
#define FILE_FILE   -1


/* #define MS_BPS      512	/* Bytes per sector */
#define MS_SPC	    2		/* Sectors per cluster */
#define MS_RES	    1		/* Reserved sectors (boot block) */
#define MS_NFATS    2		/* Number of FATs */
#define MS_NDIRS    112 	/* Number of directory entries */
#define MS_NSECTS   1440	/* total number of sectors */
#define MS_SPF	    3		/* Sectors per FAT */
/* #define MS_SPT      9	/* Sectors per track */
/* #define MS_SPT_MAX  9	/* Max sectors per track */
/* #define MS_NSIDES   2	/* Tracks per cylinder */
#define MS_ROOTDIR  (MS_RES + MS_SPF * MS_NFATS)
#define MS_DIRENTSIZE  sizeof(struct MsDirEntry) /* size of a directory entry */

#define MS_FIRSTCLUST	2	/* Very strange convention... */

#define FAT_EOF     0xFFFF	/* end of file FAT entry */
#define FAT_UNUSED  0		/* unused block */
#define SEC_EOF     -1		/* end of FAT chain */

#define DIR_DELETED	    0xE5
#define DIR_DELETED_MASK    0x80

/*
 * This structure has its byte order wrong, when it is on the disk.
 */

struct MsDirEntry {
    byte	    msd_Name[8];
    byte	    msd_Ext[3];
    byte	    msd_Attributes;
    byte	    msd_Pad1[10];
    word	    msd_Time;	/* in 2s of seconds since begin of the day */
    word	    msd_Date;
    word	    msd_Cluster;
    ulong	    msd_Filesize;
};

#define ATTR_READONLY	    0x01
#define ATTR_HIDDEN	    0x02
#define ATTR_SYSTEM	    0x04
#define ATTR_VOLUMELABEL    0x08
#define ATTR_DIRECTORY	    0x10
#define ATTR_ARCHIVED	    0x20

#define ATTR_DIR	    (ATTR_DIRECTORY | ATTR_VOLUMELABEL)

#define DATE_MIN	    0x21

struct DirEntry {
    struct MsDirEntry de_Msd;
    word	    de_Sector;
    word	    de_Offset;
};

struct DiskParam {
    word	    bps;	/* bytes per sector. max MS_BPS supported */
    byte	    spc;	/* sectors per cluster */
    word	    res;	/* reserved sectors (boot block) */
    byte	    nfats;	/* number of fats */
    word	    ndirs;	/* number of directory entries */
    word	    nsects;	/* total number of sectors on disk */
    byte	    media;	/* media byte */
    word	    spf;	/* sectors per fat */
    word	    spt;	/* sectors per track. Only MS_SPT
				 * supported */
    word	    nsides;	/* # sides. Max MS_NSIDES supported */
    word	    nhid;	/* Number of hidden sectors */
    /* derived parameters */
    word	    start;	/* sector of cluster 0 */
    word	    maxclst;	/* highest cluster number */
    word	    rootdir;	/* first sector of root dir */
    word	    ndirsects;	/* # of root directory sectors */
    word	    datablock;	/* first block available for files &c */
    word	    bpc;	/* bytes per cluster */
    word	    nsectsfree; /* amount of free space */
    long	    lowcyl;	/* offset to lowcyl */
    struct DirEntry vollabel;	/* copy of volume label */
    word	    fat16bits;	/* Is the FAT 16 bits/entry? */
};

/*
 * A pointer to an MSFileLock is put into the fl_Key field of a DOS
 * FileLock structure. We share the MSFileLock with all FileLocks on the
 * same file. This way, you can compare FileLocks based on their fl_Key
 * and fl_Task fields, as seems to be done sometimes. Also, a pointer to
 * an MSFileLock is put in MSFileHandles.
 *
 * For ease, we keep a copy of the directory entry in core, WITH THE BYTE
 * ORDER CORRECTED FOR THIS PROCESSOR.
 */

struct MSFileLock {
    struct MinNode  msfl_Node;
    short	    msfl_Refcount;	/* -1: exclusive, >0: # of shared
					 * locks */
    struct MSFileLock *msfl_Parent;	/* Pointer to parent directory */
    struct MsDirEntry msfl_Msd; /* Copy of directory entry */
    word	    msfl_DirSector;	/* Location of directory entry */
    word	    msfl_DirOffset;
};

/*
 * A pointer to an MSFileHandle is put into the fh_Arg1 field of a DOS
 * FileHandle. We get that value with many DOS packets that manipulate the
 * contents of a file.
 */

struct MSFileHandle {
    struct MSFileLock *msfh_FileLock;
    long	    msfh_SeekPos;
    word	    msfh_Cluster;
};

/*
 * Return values of CompareNames.
 */

#define CMP_NOT_EQUAL	    0	/* Names do not match at all */
#define CMP_OK_DIR	    1	/* Name matches with a subdir entry */
#define CMP_OK_FILE	    2	/* Name matches with a file entry */
#define CMP_INVALID	    3	/* First part of name matches with a file
				 * entry, or other invalid component name */
#define CMP_FREE_SLOT	    5
#define CMP_END_OF_DIR	    6

struct LockList {
    struct MinList  ll_List;
    void	   *ll_Cookie;	/* we don't want to know what this is! */
};

struct CacheSec {
    struct MinNode  sec_Node;
    word	    sec_Number;
    word	    sec_Refcount;
    byte	    sec_Data[2];/* Really Disk.bps */
};

#define SEC_DIRTY   0x8000	/* Bit in sec_Refcount */

#define OFFSETOF(tag, member)   ((long)(&((struct tag *)0)->member))

#define     DELAY_OFF	    0	/* Motor is off */
#define     DELAY_RUNNING1  1	/* Motor may be on */
#define     DELAY_RUNNING2  2	/* Motor may be on */
#define     DELAY_RUNNING   3	/* Running1 | 2 */
#define     DELAY_DIRTY     4	/* We have dirty buffers to flush */


extern long	Wait();
extern struct MsgPort *CreatePort();
extern struct IOExtTD *CreateExtIO();
extern void    *AllocMem(), FreeMem();
extern byte    *index(), *rindex();
extern void    *CheckIO();

/*
 * PACK.C
 */
extern char *DevName;
extern long UnitNr;
extern ulong DevFlags;

/*
 * HANMAIN.C
 */
extern byte	ToUpper();
extern long	lmin();
extern byte    *ZapSpaces();
extern byte    *ToMSName();
extern long	MSDiskInfo();
extern void	MSDiskInserted();
extern int	MSDiskRemoved();
extern void	HanCloseDown();
extern int	HanOpenUp();

/*
 * HANSEC.C
 */
extern struct MsgPort *DiskReplyPort;
extern struct IOExtTD *DiskIOReq;
extern struct IOStdReq *DiskChangeReq;
extern struct DiskParam Disk;
extern byte    *Fat;
extern short	FatDirty;	/* Fat must be written to disk */
extern short	error;		/* To put the error value; for Result2 */
extern long	IDDiskState;	/* InfoData.id_DiskState */
extern long	IDDiskType;	/* InfoData.id_DiskType */
extern struct timerequest *TimeIOReq;	/* For motor-off delay */
extern struct MinList CacheList;/* Sector cache */
extern int	CurrentCache;	/* How many cached buffers do we have */
extern int	MaxCache;	/* Maximum amount of cached buffers */
extern ulong	BufMemType;
extern long	CacheBlockSize; /* Size of disk block + overhead */
extern int	DelayState;
extern byte    *Word8086;
extern word	Get8086Word();
extern word	OtherEndianWord();
extern ulong	OtherEndianLong();
extern void	OtherEndianMsd();
extern word	ClusterToSector();
extern word	ClusterOffsetToSector();
extern word	DirClusterToSector();
extern word	SectorToCluster();
extern word	NextCluster();
extern word	NextClusteredSector();
extern word	FindFreeSector();
extern struct CacheSec *FindSecByNumber();
extern struct CacheSec *FindSecByBuffer();
extern struct CacheSec *NewCacheSector();
extern void	FreeCacheSector();
extern void	InitCacheList();
extern void	FreeCacheList();
extern void	MSUpdate();
extern void	StartTimer();
extern byte    *GetSec();
extern byte    *EmptySec();
extern void	PutSec();
extern void	FreeSec();
extern void	MarkSecDirty();
extern void	WriteFat();
extern int	ReadBootBlock();
extern int	IdentifyDisk();
extern int	TDMotorOff();
extern int	TDGetNumCyls();

/*
 * HANLOCK.C
 */
extern struct LockList *LockList;	/* List of all locked files we
					 * have. Note this is not the same
					 * as all locks we have */
extern struct MSFileLock *RootLock;	/* Lock on root directory */
extern struct MSFileLock *EmptyFileLock;	/* 2nd result of MSLock() */

extern struct DirEntry FakeRootDirEntry;
extern int	CompareNames();
extern void	NextDirEntry();
extern struct DirEntry *FindNext();
extern struct MSFileLock *MakeLock();
extern void	WriteLock();
extern void	PrintDirEntry();
extern struct MSFileLock *MSLock();
extern struct MSFileLock *MSDupLock();
extern struct MSFileLock *MSParentDir();
extern int	MSUnLock();
extern void	ExamineDirEntry();
extern int	MSExamine();
extern int	MSExNext();
extern long	MSSetProtect();
extern void	WriteFileLock();
extern void	UpdateFileLock();
extern struct LockList *NewLockList();
extern void	FreeLockList();

/*
 * HANFILE.C
 */
extern int	GetFat();
extern void	FreeFat();
extern word	GetFatEntry();
extern void	SetFatEntry();
extern word	FindFreeCluster();
extern word	ExtendClusterChain();
extern void	FreeClusterChain();
extern struct MSFileHandle *MSOpen();
extern void	MSClose();
extern long	MSSeek();
extern long	MSRead();
extern long	MSWrite();
extern long	MSDeleteFile();
extern long	MSSetDate();
extern struct MSFileLock *MSCreateDir();

/*
 * DATE.C
 */
extern void	ToDateStamp();
extern void	ToMSDate();
