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

📄 fsys.c

📁 MMURTL(tm) Computer Operating System Ver x0.8, source code.
💻 C
📖 第 1 页 / 共 5 页
字号:
	    CopyData(&paFCB[iFCB], &abDirSectBuf[j], 32);
		erc = DeviceOp(Ldrv[Drive].DevNum, 2, i, 1, abDirSectBuf);
	}
  return erc;
}


/*******************************************************
  Checks the validity of the a file handle and also
  returns the index to the FCB if the handle is OK.
  The function return OK (0) if handle is good, else
  a proper error code is returned.
********************************************************/
U32 ValidateHandle(U32 dHandle, U32 *iFCBRet)
{
  /* get some checks out of the way first */

  if (dHandle < 3) return ErcBadFileHandle;
  if (dHandle >= nFUBs) return ErcBadFileHandle;
  if (!paFUB[dHandle].Job) return ErcBadFileHandle;

  /* Looks like a valid handle */
  *iFCBRet = paFUB[dHandle]->iFCB;
  return 0;
}

/*********************************************
  Returns absolute disk address for the
  cluster number you specify. This gives us
  the LBA of the first sector of data that
  the cluster number represents.
  The sector number is returned from the fucntion.
  Uses: Ldrv[CrntDrv].LBAData
  		Ldrv[CrntDrv].SecPerClstr
**********************************************/

U32 ClsToLBA(U16 Clstr, U8 Drive)
{
U32 LBA;

 Clstr-=2;		/* Minus 2 cause 0 and 1 are reserved clusters */
 LBA = Ldrv[Drive].SecPerClstr * Clstr;
 LBA += Ldrv[Drive].LBAData;
 return LBA;
}


/*******************************************************
  This writes out the specified FAT sector back into
  the FAT. It also checks to see if there is more
  than one copy of the fat and updates the second copy
  if it exists.
********************************************************/
U32 UpdateFAT(U32 iFAT)
{
U32 erc, i;
U8 Drive;

  erc = 0;
  if (Fat[iFAT].fModLock & FATMOD) {	/* Modified?? */
	Drive = Fat[iFAT].Drive;		/* What logical drive are we on? */
    i = Fat[iFAT].LBASect;				/* Where to write it back */
	erc = DeviceOp(Ldrv[Drive].DevNum, 2, i, 1, Fat[iFAT].pBuf);
	if (!erc) {
		Fat[iFAT].fModLock &= ~FATMOD;	/* Not modified anymore */
		if (Ldrv[Drive].nFATS > 1)  { 	/* 2 FATS! */
			/* if we have two FATS we must update the second fat
			also. This will be located directly aftrer the first
			FAT (by exactly	LDrv.sFat secotrs).
			*/
			i+= Ldrv[Drive].sFAT;
			erc = DeviceOp(Ldrv[Drive].DevNum, 2, i, 1, Fat[iFAT].pBuf);
		}
	}
  }
  return erc;
}

/*******************************************************
 Reads in the FAT sector that contains the Cluster we
 specified into a FAT buffer if it isn't already in
 one.  The index to the FAT buffer is returned.
 Returns Error if not in FAT.
 Uses: Ldrv[LDrive].LBAFAT
	   Ldrv[LDrive].fFAT16
	   Ldrv[LDrive].DevNum
 Each sector of the FAT contains 256 cluster entries
 if FAT16, or 384 entries is FAT12.  To find it, we
 Divide the cluster number by the count of entries
 (256 or 384), and add this to the beginning sector
 of the FAT.  It is SOOO important (for speed) to have
 the FAT sectors in memory, that we allocate the FAT
 buffers on a Least Recently Used (LRU) basis.
*******************************************************/

U32 FindFatSect(U8 Drive, U16 Clstr, U32 *piFatRecRet, U8 fLock)
{
U32 i, j, first, oSector, erc, LRU, iLRU, iFound, Tick;
U16 MaxClstr;

  if (Ldrv[Drive].fFAT16)
	MaxClstr = 0xfff8;
  else
	MaxClstr = 0xff8;	/* FAT12 */

 if (Clstr >= MaxClstr)
 	return(ErcEOF);

 if (Clstr < 2)
 	return (ErcBadFATClstr);

 erc = 0;		/* default to no error */

 /* Set oSector to offset of sector in FAT */

 if (Ldrv[Drive].fFAT16) {
	oSector = Clstr/256;
	first = Clstr-(Clstr%256);
	}
 else {
	oSector = Clstr/384;
	first = Clstr-(Clstr%384);
	}

 /* Set i to LBA of FAT sector we need by adding offset to beginning of FAT */

 i = oSector + Ldrv[Drive].LBAFAT;

 /* If FAT sector is out of range there's a BAD problem... */

 if (i >= Ldrv[Drive].sFAT)
 	return (ErcBadFATClstr);

 else {   /* Else we get it for them */

	/* Loop through the Fat bufs and see if its in one already. */
	/* Save the index of the LRU in case it's not there. */
	/* Set iFound to index of FatBuf (if found). */
	/* Otherwise, Set up iLRU to indicate what the oldest buffer is  */

	iFound = 0xffffffff;
	LRU = 0xffffffff;	/* saves tick of oldest one so far */
	iLRU = 0;			/* default */
	for (j=0; j<nFATBufs; j++) {
		if (Fat[j].LastUsed > 0) {		/* Valid ? (ever been used) */
			if ((first == Fat[j].iClstrStart) &&
				(Drive == Fat[j].Drive)) {
					iFound = j;
					if (fLock)
	                    Fat[j].fModLock |= FATLOCK;
					break;		/* Already IN! */
				}
		}
		if (Fat[j].LastUsed < LRU) {
			LRU = Fat[j].LastUsed;
			iLRU = j;
		}
	}

	GetTimerTick(&Tick);

	if (iFound != 0xffffffff) {		/* Its already in memory */
        Fat[j].LastUsed = Tick;		/* update LRU */
	}
	else {       			   		/* else put into oldest buffer */
		j = iLRU;

		/* Check to see if Fat[iLRU] is valid and has been
		   modified. If it is, write it out before we read
		   the next one into this buffer. This done by
		   calling UpdateFAT(iFatRec).
		*/
        if (Fat[j].fModLock & FATMOD)
	        erc = UpdateFAT(j);

		if (!erc) {
			erc = DeviceOp(Ldrv[Drive].DevNum, 1, i, 1, Fat[j].pBuf);
			Fat[j].Drive = Drive;			/* Update Drive */
    	    Fat[j].LastUsed = Tick;			/* update LRU */
        	Fat[j].iClstrStart = first;		/* update first cluster num */
	        Fat[j].LBASect = i;				/* LBA this FAt sect came from */
		}
	}

 *piFatRecRet = j;  /* Buffer that holds the sector */
 return (erc);		/* Disk error Bad news */
 }
}

/*********************************************
  Returns the value found for this cluster
  entry in a fat sector buffer.  Values can be:
                              FAT16     FAT12
  	Next entry in the chain (0002-FFF0 (002-FF0)
  	Last entry in chain     (FFF8     )(FF8    )
  	Available cluster       (0        )(0      )
  	Bad Cluster             (FFF7     )(FF7    )
	(other vlaues are reserved).
**********************************************/

U32 GetClstrValue(U16 Clstr, U8 Drive, U8 fLock, U16 *pValRet, U32 *iFatBufRet)
{
U32 erc, oClstr, iFat;
U16 ClstrVal, *pClstr;

	erc = FindFatSect(Drive, Clstr, &iFat, fLock);
	if (erc) {
		*pValRet= 0;
		return(erc);
	}

	pClstr = Fat[iFat].pBuf;
	oClstr = Clstr - Fat[iFat].iClstrStart;    /* offset into FatBuf */

	if (Ldrv[Drive].fFAT16) {	/* if drive is FAT16 type */
		pClstr += oClstr * 2;     				/* WORDS in */
		ClstrVal = *pClstr;
	}
		/* FAT12 entries are 1.5 bytes long (what a pain).
		   This means we get the offset and see whether it
		   is an odd or even byte, then take the proper nibble
		   by ANDing or shifting.
		*/
	else {						/* a FAT12... */
		pClstr += oClstr + (oClstr/2);			/* 1.5 bytes in */
		ClstrVal = *pClstr;					/* We have 16 bits */
		if (Clstr & 1)                 			/* Odd, must shift */
			ClstrVal >>= 4;
		ClstrVal &= 0xfff;
	}
	*pValRet= ClstrVal;
    *iFatBufRet = iFat;
	return(erc);
}


/*************************************************
  Sets the value in Clstr to the value in
  NextClstr which will be one of the following
  values:                     FAT16     FAT12
  	Next entry in the chain (0002-FFEF (002-FEF)
  	Last entry in chain     (FFFF     )(FFF    )
  	Available cluster       (0        )(0      )
  	Bad Cluster             (FFF7     )(FF7    )
	(other vlaues are reserved).
  This marks the associated fat buffer as modified.
  This is the ONLY call that modifies a FAT buffer!
**************************************************/

U32 SetClstrValue(U16 Clstr, U16 NewClstrVal, U8 Drive, U32 *iFatBufRet)
{
U32 erc, oClstr, iFat;
U16 ClstrVal, *pClstr, ClstrSave;

	erc = FindFatSect(Drive, Clstr, &iFat, 0);
	if (erc) {
		*iFatBufRet = 0;
		return(erc);
	}

	pClstr = Fat[iFat].pBuf;
	oClstr = Clstr - Fat[iFat].iClstrStart;    /* offset into FatBuf*/
	if (Ldrv[Drive].fFAT16) {	/* if drive is FAT16 type */
		pClstr += oClstr * 2;     				/* WORDS in */
		*pClstr = NewClstrVal;
	}
		/* FAT12 entries are 1.5 bytes long (remember??).
		   SAVE THE CORRECT NIBBLE OF THE ADJACENT CLUSTER!!
		*/
	else {						/* a FAT12... */
		pClstr += oClstr + (oClstr/2);			/* 1.5 bytes in */
		ClstrSave = *pClstr;						/* We have 16 bits */
		if (Clstr & 1) {        	   			/* Odd, must shift */
			NewClstrVal <<= 4;
			NewClstrVal &= 0xfff0;
			ClstrVal = (ClstrSave & 0x0F) | NewClstrVal;
		}
		else {
			NewClstrVal &= 0x0fff;
			ClstrVal = (ClstrSave & 0xf000) | NewClstrVal;
		}
		*pClstr = ClstrVal;
	}
    Fat[iFat].fModLock |= FATMOD;
    *iFatBufRet = iFat;
	return(erc);
}


/*************************************************
 Read the FAT and get the cluster number for the
 next cluster in the chain for the Clstr specifed.
 This returns 0 and an error if failed.
 0 is an illegal cluster number.
 Remember, the cluster you are on is actually the
 number of the next cluster in a linked list!
**************************************************/

U32 NextFATClstr(U8 Drive, U16 Clstr, U16 *pNextClstrRet)
{
U32 erc, i, NextClstr;

	erc = GetClstrValue(Clstr, Drive, 0, &NextClstr, &i);
	if (erc) {
		*pNextClstrRet = 0;
		return(erc);
	}
	*pNextClstrRet = NextClstr;
	return(0);
}

/*************************************************
 This allocates the next empty cluster on the disk
 to the tail of the clstr that is passed in.
 LastClstr is a valid cluster of a file (and MUST be
 the last one).  We error out if it isn't!
 This returns 0 and an error if it fails.
 Remember, the cluster you are on is actually the
 number of the next cluster in a linked list!
 This looks through the current and succesive
 FAT sectors (if needed) to add to the file.
 A cluster is available to allocate if it is
 0.  This is strictly a first fit algorithm.
**************************************************/

U32 ExtendClstrChain(U8 Drive, U16 LastClstr, U16 *pNextClstrRet)
{
U32 erc, i, j, k;
U16 ClstrValue, MaxClstr, CrntClstr;
U8 fFound;

	if (Ldrv[Drive].fFAT16)
		MaxClstr = 0xfff8;
	else
		MaxClstr = 0xff8;	/* FAT12 */

	/* i is index to Fat with last sector of current chain */

	erc = GetClstrValue(LastClstr, Drive, 1, &ClstrValue, &i);
	if (erc) {
		*pNextClstrRet = 0;
		return(erc);
	}

	if (ClstrValue < MaxClstr) {		/* no need to extend it */
    	*pNextClstrRet = ClstrValue;
        Fat[i].fModLock &= ~FATLOCK;		/* unlock it */
		return(0);
	}

	/* OK... now we have the Fat sector and the offset in the Fat
	buf of the last	cluster allocated to this file.  Let's go
	further into the buffer and try to get an empty one.
	*/

	CrntClstr = LastClstr;
	fFound = 0;
	while (!fFound) {
		++CrntClstr;		/* next cluster */
		erc = GetClstrValue(CrntClstr, Drive, 0, &ClstrValue, &j);
		if (erc) {
			*pNextClstrRet = 0;
	        Fat[i].fModLock &= ~FATLOCK;	/* unlock previous lastclstr */
			return(erc);
		}
		if (!ClstrValue) {
			fFound = 1; 	/* found an empty one */
		}
	}

	if (fFound) {	/* CrntClstr is index to empty one */

		/* Set the LastCluster to point to the new cluster found */

		erc = SetClstrValue(LastClstr, CrntClstr, Drive, &k);
		if (erc) {
			*pNextClstrRet = 0;
	        Fat[i].fModLock &= ~FATLOCK;	/* unlock previous lastclstr */
			return(erc);
		}
        Fat[k].fModLock &= ~FATLOCK;		/* unlock it */

		/* Set the newcluster to "end Cluster" chain value */

		erc = SetClstrValue(CrntClstr, 0xFFFF, Drive, &j);
	}
	*pNextClstrRet = CrntClstr;
	return(erc);
}

/*************************************************
 This truncates the file chain to the cluster
 specified (makes it the last cluster).
 This means we walk the rest of the chain setting
 all the entries to 0 (so they can be reallocated).
 This returns an error if failed.
**************************************************/

U32 TruncClstrChain(U8 Drive, U16 Clstr)
{
U32 erc, i;
U16 MaxClstr, NextClstr, CrntClstr;

	if (Ldrv[Drive].fFAT16)
		MaxClstr = 0xfff8;
	else
		MaxClstr = 0xff8;	/* FAT12 */

	/* i will be index to FatRec with last sector of current chain */

	erc = GetClstrValue(Clstr, Drive, 0, &NextClstr, &i);
	if (erc)
		return(erc);

	if (NextClstr >= MaxClstr) {		/* no need to truncate it */
		return(0);						/* It's already the end. */
	}

	/* OK... now we cut it off all the way down the chain.
	We start by placing MaxClstr in the last sector and
	then 0 in all entries to the end of the chain.

⌨️ 快捷键说明

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