⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsys.c

📁 MMURTL(tm) Computer Operating System Ver x0.8, source code.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* This is the MMURTL, MS-DOS Compatible (FAT) File system.  */

/*
  MMURTL Operating System Source Code
  Copyright 1991,1992,1993, Richard A. Burgess
  ALL RIGHTS RESERVED
  Version x0.8
*/

/*
About MS-DOS disk formats and how MMURTL handles them.

Physical Disk Layouts
  From the disk controller's standpoint:
	  Cylinder numbers run from 0 to nMaxCyls-1.
	  Head numbers run from 0 to nMaxheads-1.
	  Sector numbers run from 1 to nMaxSectorsPerTrack.

Physical (Absolute) Sector Numbers

  Physical sector numbers (absolute) begin at Cyl 0, Head 0, Sector 1.
  As the physical sector number rolls over (nMaxSectorsPerTrack+1),
  the Head number is incremented which moves us to the next track
  (same cylinder, next head).  When the head number rolls over
  (nMaxHeads is reached) the cylinder number is incremented.

  Note: Track and cylinder are NOT interchangable terms in the
  above text.  If you have 6 heads on your drive, you have
  6 tracks per cylinder.  This can be confusing because many
  books and documents use the terms interchangably.
  And you can, so long as you know that's what you're doing.

Hidden Sectors

  MS-DOS reserves a section of the physical hard disk. This area
  is called the Hidden Sectors.  This is usually the very first
  track on the disk (begins at Cyl 0, head 0, Sector 1).  The
  partition tables are kept at the very end of the first sector in
  this hidden area (offset 01BEh in the first sector to be exact).
  The partition tables are 16 byte entries that describe
  "logical" sections of the disk that can be treated as separate drives.
  There are usually no "hidden sectors" on floppy disks, nor are there
  any partition tables.


MMURTL Logical Block Address (LBA)

  MMURTL device drivers treat the entire disk as a single physical
  drive.  The MMURTL file system reads the partition tables,
  then sets up the device driver to span the entire physical disk
  as 0 to nMaxBlockNumbers-1.  This is refered to as the Logical Block
  Address (LBA) and is the value passed in to the DeviceOp call for
  the MMURTL hard/floppy disk device drivers (LBAs are used with
  all MMURTL devices).

  Note: DO NOT confuse MMURTL's LBA for the sector number in an MS-DOS
  logical drive.  MMURTL calls these logical blocks because we still
  have to convert them into physical cylinder, head and sector to
  retrieve the data.

MS-DOS Boot Sector

  The first sector of an MS-DOS logical drive will be its boot
  sector. Each of the MS-DOS logical partitions will have a boot
  sector although only the first will be marked as bootable (if any are).
  It's position on the disk is calculated from the partition table
  information.

MMURTL File System Initialization

  The MMURTL-FAT file system reads the partition table and saves
  the starting LBA and length of each of DOS logical disk that is
  found.  Armed with this information, MMURTL can access each of
  the DOS logical disks as a separate disk drive. To maintain some
  sanity, the MMURTL file system gives all of its logical drives
  a letter just like MS-DOS.  MMURTL supports two floppy drives
  (A & B) and up to eight logical hard disk (C-J).  All information
  on the Logical Drives are kept in an array of records (Ldrvs).
  This includes the logical letter to physical drive conversions.

  Once we have the layout of each of the partitons, we read the boot
  sector from the first DOS logical drive.  The boot sector contains
  several pieces of important information about the drive geometry
  (numbers of heads, sectors per track, etc.), which are also placed
  in the Logical Drive stuctures.

  Once we have the drive geometry information we setup the MMURTL
  device driver.  This tells the device driver how many cylinders,
  heads and sectors per track are on the physical disk.
  Until this is done, the device driver assumes a minimum drive size
  and you should only read the partition table (or boot sector if no
  partition table is on the disk).  This provides enough
  information to do a DeviceInit call to set up proper drive
  geometry.

  If you were building a loadable file system to replace the one that
  is included in MMURTL, you would call your routine to initialize
  the file system very early in the main program block.  You must
  not service file system requests until this is done.

*/

#define U32 unsigned long
#define U16 unsigned int
#define U8  unsigned char
#define S32 long
#define S16 int
#define S8  char
#define TRUE 1
#define FALSE 0

/*********** MMURTL Public Prototypes ***************/

/* From MKernel */

extern far AllocExch(long *pExchRet);
extern far U32 GetTSSExch(U32  *pExchRet);
extern far SpawnTask(char *pEntry,
		             long dPriority,
                     long fDebug,
                     char *pStack,
           		     long fOSCode);
extern far long WaitMsg(long Exch, char *pMsgRet);
extern far long CheckMsg(long Exch, char *pMsgRet);
extern far long Request(unsigned char *pSvcName,
						unsigned int  wSvcCode,
						unsigned long dRespExch,
						unsigned long *pRqHndlRet,
						unsigned long dnpSend,
						unsigned char *pData1,
						unsigned long dcbData1,
						unsigned char *pData2,
						unsigned long dcbData2,
						unsigned long dData0,
						unsigned long dData1,
						unsigned long dData2);

extern far long Respond(long dRqHndl, long dStatRet);

/* From MData */
extern far void CopyData(U8 *pSource, U8 *pDestination, U32 dBytes);
extern far void FillData(U8 *pDest, U32 cBytes, U8 bFill);
extern far long CompareNCS(U8 *pS1, U8 *pS2, U32 dSize);

/* From MTimer.h */
extern far long GetCMOSTime(long *pTimeRet);
extern far long GetCMOSDate(long *pTimeRet);
extern far long GetTimerTick(long *pTickRet);

/* From MVid.h */
extern far long TTYOut (char *pTextOut, long ddTextOut, long ddAttrib);
extern far long GetNormVid(long *pNormVidRet);

#include "MKbd.h"

/* From MDevDrv */
extern far U32  DeviceOp(U32  dDevice,
 		                 U32  dOpNum,
						 U32  dLBA,
						 U32  dnBlocks,
						 U8  *pData);

extern far U32  DeviceStat(U32  dDevice,
						   S8 * pStatRet,
						   U32  dStatusMax,
						   U32  *pdSatusRet);

extern far U32  DeviceInit(U32  dDevNum,
						   S8  *pInitData,
						   U32   sdInitData);

/* From MMemory.h */
extern far U32 AllocOSPage(U32 nPages, U8 *ppMemRet);
extern far U32 DeAllocPage(U8 *pOrigMem, U32 nPages);

/* From MJob.h */
extern far U32 GetPath(long JobNum, char *pPathRet, long *pdcbPathRet);
extern far U32 RegisterSvc(S8 *pName, U32 Exch);

/* NEAR support for debugging */

extern long xprintf(char *fmt, ...);
extern U32 Dump(unsigned char *pb, long cb);

/* File System error codes */

#define ErcOK			 0		/* Alls Well */
#define ErcEOF			 1		/* DUH... The END */
#define ErcBadSvcCode	 32		/* Service doesn't handle that code */

#define ErcBadFileSpec	 200	/* invalid file spec (not correct format)*/
#define ErcNoSuchDrive	 201	/* Try another letter bozo */
#define ErcNotAFile		 202	/* Open a directory?? NOT */
#define ErcNoSuchFile	 203	/* No can do! It ain't there...*/
#define ErcNoSuchDir	 204	/* Ain't no such dir... */
#define ErcReadOnly		 205	/* You can't modify it bubba */
#define ErcNoFreeFCB	 206	/* We're really hurtin... */
#define ErcBadOpenMode	 207	/* Say what? Mode??? */
#define ErcFileInUse	 208	/* File is open in incompatible mode */
#define ErcNoFreeFUB	 209	/* Sorry, out of File User Blocks */
#define ErcBadFileHandle 210	/* WHOAAA, bad handle buddy! */
#define ErcBrokenFile	 211	/* Cluster chain broken on file */
#define ErcBadFCB		 213	/* We got REAL problems... */
#define ErcStreamFile	 214	/* Operation not allowed on Stream File */
#define ErcBlockFile	 215	/* Operation not allowed on Block File */
#define ErcBeyondEOF	 217	/* SetLFA or WriteBlock beyond EOF */
#define ErcNoParTable	 218	/* No partiton table found on disk!!! */
#define ErcBadFATClstr   220    /* File system screwed up (or your disk is) */
#define ErcRenameDrv     222	/* They have tried to rename across Dir/Vol*/
#define ErcRenameDir     223	/* They have tried to rename across Dir/Vol*/
#define ErcNoMatch       224	/* No matching directory entry */

#define ErcWriteOnly	 225	/* Attempt to read write-only device */
#define ErcDupName		 226	/* Name exists as a file or dir already */
#define ErcNotSupported	 227	/* Not supported on this file  */
#define ErcRootFull		 228	/* The Root Directory is Full  */
#define ErcDiskFull		 230	/* No more free CLUSTERS!!!  */
#define ErcDirFull		 231	/* No free Dir entries TEMP ERROR  */

#define ErcNewMedia		 605	/* for floppy mounting from FDD */

/**************** FAT Buffer control structure **********************/

/*
   The Fat structures are for keeping track of the FAT buffers.
   We never want to have more than one copy of a FAT sector in
   memory at one time, and we also never want to read one when
   its already here (a waste of time)!  We also keep track
   of the last time it was used and deallocate the oldest (LRU -
   Least Recently Used). Initially filling out the Fat control
   structure is part of the file system initialization.  If the
   FAT sector we are in has been modified (data written to clusters
   in it & FAT updated) we write it ASAP!
*/

#define nFATBufs 16		/* 16 * 512 = 8192, 2 pages */

struct {				/* */
	U8  *pBuf;			/* points to beginning of fat buffer  */
	U32 LastUsed;		/* Tick when last used (0 = Never) */
	U32 LBASect;		/* LBA this FAT sector came from */
	U16 iClstrStart;	/* Starting cluster for each buf  */
	U8  Drive;			/* LDrive this FAT sector is from */
	U8  fModLock;		/* Bit 0 = Modified, bit 1 = Locked  */
	} Fat[nFATBufs];	/* 12 bytes total */

#define FATMOD  0x01
#define FATLOCK 0x02

/**************** File Contol Block Structures (FCBs) **********/
/* One FCB is allocated and filled out for each file that is open.
   The actual directory entry structure from the disk is embedded
   in the FCB so it can be copied directly to/from the directory
   sector on the disk.
*/
#define nFCBs 128
#define sFCB  64

struct FCB {
	S8  Name[8];		/* From here to Filesize is copy of DirEnt */
	S8  Ext[3];
	S8  Attr;			/* from MS-DOS */
	U8  Resvd1[10];		/* ????????  */
	U16 Time;			/* Only changed when created or updated */
	U16 Date;
	U16 StartClstr;		/* At least one per file!! */
	U32 FileSize;		/* last entry in FAT Dir Ent (32 bytes) */
	U32 LBADirSect;		/* LBA of directory sector this is from */
	U16 oSectDirEnt;	/* Offset in sector for the dir entry */
	U8  Ldrv;			/* Logical drive this is on (A-J, 0-9) */
	U8  Mode;			/* 0 or 1 (Read or Modify). */
	U8  nUsers;			/* Active FUBs for this file (255 MAX). 0= Free FCB */
    U8  fMod;			/* This file was modified! */
	U8  Resvd[22];		/* Out to 64 bytes */
	};

struct FCB *paFCB;		/* a pointer to array of allocated FCBs. */
struct FCB *pFCB;		/* pointer to one FCB */

/********************** File User Blocks **************************/

/* Each user of an open file is assigned a FUB.  The FUB number is the
   filehandle (beginning with 3). ) 0, 1 & 2 are reserved for NUL,
   KBD and VID devices.
*/

#define nFUBs 128
#define sFUB  32

/* The FUB contains information on a file related to a user's view
   of the file.  It is used to hold information on files opened
   in stream and block mode. Three important fields in the FUB are:
   LFABuf - LFA of first byte in buffer for a stream file.
   Clstr - Clstr of last block read or stream fill.
   LFAClstr - LFA of first byte in Clstr.

   LFAClstr and Clstr give us a relative starting point when
   reading a file from disk.  If we didn't save this information
   on the last access, we would have to "run" the cluster chain
   everytime we wanted to read or access a file beyond the last
   point we read. */

struct FUB {
	U16 Job;			/* User's Job Number. 0 if FUB is free. */
	U16 iFCB;			/* FCB number for this file (0 to nFCBs-1) */
	U32 CrntLFA;		/* Current Logical File Address (File Ptr) */
	U8  *pBuf;			/* Ptr to buffer if stream mode */
	U32 sBuf;			/* Size of buffer for Stream file in bytes */
	U32	LFABuf;			/* S-First LFA in Clstr Buffer */
	U32 LFAClstr;		/* LFA of Clstr (below). */
	U16 Clstr;			/* Last Cluster read */
	U8  fModified;		/* Data in buffer was modified */
	U8  fStream;		/* NonZero for STREAM mode */
	U8  Rsvd[4];		/* Pad to 32 bytes */
	};

struct FUB *paFUB;		/* a pointer to allocated FUBs. Set up at init. */
struct FUB *pFUB;		/* a pointer to allocated FUBs. Set up at init. */

/* Boot sector info (62 byte structure) */
struct {
	  U8  Jmp[3];
	  U8  OEMname[8];
	  U16 bps;
	  U8  SecPerClstr;
	  U16 ResSectors;
	  U8  FATs;
	  U16 RootDirEnts;
	  U16 Sectors;
	  U8  Media;
	  U16 SecPerFAT;
	  U16 SecPerTrack;
	  U16 Heads;
	  U32 HiddenSecs;
	  U32 HugeSecs;
	  U8  DriveNum;
	  U8  Rsvd1;
	  U8  BootSig;
	  U32 VolID;
	  U8  VolLabel[11];
	  U8  FileSysType[8];		/* 62 bytes */
	  } fsb;


/* Partition Table Entry info. 16 bytes */
struct partent {
  U8  fBootable;
  U8  HeadStart;
  U8  SecStart;
  U8  CylStart;
  U8  FATType;
  U8  HeadEnd;
  U8  SecEnd;
  U8  CylEnd;
  U32 nFirstSector;
  U32 nSectorsTotal;
  };

struct partent partab[4];	/* 4 partition table entries 64 bytes */
U16 partsig;

/* Bit definitions in attribute field for a directory entry */

#define ATTRNORM  0x00
#define READONLY  0x01
#define HIDDEN    0x02
#define SYSTEM    0x04
#define VOLNAME   0x08
#define DIRECTORY 0x10
#define ARCHIVE   0x20

/* Directory Entry Record, 32 bytes */

struct dirstruct {
	U8  Name[8];
	U8  Ext[3];
	U8  Attr;
	U8  Rsvd[10];
	U16 Time;
	U16 Date;
	U16 StartClstr;
	U32 FileSize;
	} dirent;

struct dirstruct *pDirEnt;		/* a pointer to a dir entry */

/* When a file is opened, the filename is parsed into an array
   to facilitate searching the directory tree.  IN MS-DOS all
   dir and file names are SPACE padded (20h).  The FileSpec array
   contains the fully parsed path of the file.  For instance,
   If you were to open "A:\Dog\Food\IsGood.txt" the FileSpec
   array would look like this:
   FileSpec[0] = "DOG        "
   FileSpec[1] = "FOOD       "
   FileSpec[2] = "ISGOOD  TXT"
   FileSpec[3][0] = NULL;
   Note that the DOT is not inlcuded (it's not in the DOS directory
   either), and the next unused FileSpec entry contain NULL in the
   first byte.	SpecDepth tells us how many directories deep the
   name goes.
*/

U8 FDrive					/* Drive parsed from file operation */
U8 FileSpec[7][11];			/* Hierarchy from file spec parsing */
U8 SpecDepth;				/* Depth of parse (0=Root File) */

/* Used for Rename */
U8 FDrive1					/* Drive parsed from file operation */
U8 FileSpec1[7][11];		/* Hierarchy from file spec parsing */
U8 SpecDepth1;				/* Depth of parse (0=Root File) */

/* raw sector buffer for all kinds of stuff */

U8  abRawSector[516];
U8  abTmpSector[516];
U8  abDirSectBuf[516];

/* These arrays keep track of physical drive data (0-4). */
#define nPDrvs 4

struct phydrv {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -