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

📄 fsys.c

📁 MMURTL(tm) Computer Operating System Ver x0.8, source code.
💻 C
📖 第 1 页 / 共 5 页
字号:

	if (erc) break;		/* bad news. Exit for loop */
	}
SpecDepth = k;
return erc;
}


/*** Get Directory Sector *******************************
 Gets a 512 byte directory sector in sequence number from
 the directory path given. SectNum = 0 to nMax for Dir.
 This also returns the LBA for secotr itself for
 internal users of this call.
********************************************************/

U32 GetDirSectorM(char *pPath,
				 long cbPath,
				 char *pSectRet,
				 long cbRetMax,
				 long SectNum,
				 long *LBARet,
				 long iJob)
{
U32 sector, i, j, k, erc, spc, level, iSect;
U16 MaxClstr, Clstr, rClstr;
U8  fFound, *pEnt, Drive;

  if (cbRetMax > 512)	/* WHOA Bub, 1 Sector at a time! */
  	cbRetMax = 512;

  erc = ParseName(pPath, cbPath, iJob);

	/* The entire path has now been parsed out into an array of
	   arrays, each 11 bytes long that contain each directory name
	   in the path for the sector they want.
	   The first is always the root (entry 0).
	   The drive will be a letter in FDrive.
	*/

  if ((FDrive > 0x40) && (FDrive < 0x52))	 	/* A to J */
  	Drive = FDrive - 0x41;						/* Make it 0-9 */
  else
  	return(ErcNoSuchDrive);

  if (Ldrv[Drive].DevNum == 0xff)
	return(ErcNoSuchDrive);

  i = Ldrv[Drive].LBARoot;
  j = Ldrv[Drive].nRootDirEnt;

  if (FileSpec[0][0] == ' ') {		/* They want sector in root */
  	if (SectNum > j * 32)			/* Beyond Root entries! */
		return(ErcNoMatch);

	/* Else we can give them the sector NOW */
	erc = DeviceOp(Ldrv[Drive].DevNum, 1, i+SectNum, 1, abRawSector);
	if (!erc) {
		*LBARet = i+SectNum;
	  	CopyData(abRawSector, pSectRet, cbRetMax);
	}
	return(erc);
  }

	/* We have to run the root for a dir name... */

  fFound = 0;
  while ((j) && (!fFound)) {	/* while there are valid entries */
	erc = DeviceOp(Ldrv[Drive].DevNum, 1, i++, 1, abRawSector);
	if (erc)
		return(erc);
    pEnt = abRawSector;		/* Point to first entry */
	for (k=0; k<16; k++) {
		if (CompareNCS(pEnt, FileSpec[0], 11) == -1) {
			fFound=1;
			break;
		}
		--j;		/* one less dir ent */
		pEnt+=32;	/* 32 byte per entry */
	}
 }
 if (!fFound)
	return (ErcNoMatch);

  pDirEnt = pEnt;		/* Entry we just found in root was dir */

  if (!(pDirEnt->Attr & DIRECTORY))  {
	return(ErcNoSuchDir);
  }

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

  spc = Ldrv[Drive].SecPerClstr;	/* How many sectors per cluster */
  Clstr = pDirEnt->StartClstr;

  level = 1;	/* start at this directory+1, compare to FileSpec */

  while (!erc) {	/* looking for Dir */

	if (FileSpec[level][0] == ' ') { /* They want sector in this dir */

		if (!(pDirEnt->Attr & DIRECTORY))  {
			return(ErcNoSuchDir);
		}
		rClstr = SectNum /spc;	/* calc relative cluster from start clstr */
		iSect  = SectNum % spc;  /* Add this to cluster start for sector */
		sector = ClsToLBA(Clstr, Drive);	/* sector of first dir sector */
		while ((rClstr--) && (!erc))
			erc = NextFATClstr(Drive, Clstr, &Clstr);
		if (erc)
			return(erc);
		sector = ClsToLBA(Clstr, Drive);  /* LBA of this clstr */
		sector += iSect;
		erc = DeviceOp(Ldrv[Drive].DevNum, 1, sector, 1, abRawSector);
		if (!erc) {
		  	CopyData(abRawSector, pSectRet, cbRetMax);
			*LBARet = sector;
		}
		return(erc);
	}
	else {  /* Else we must find this sub dir name */

		sector = ClsToLBA(Clstr, Drive);	/* sector of first dir sector */
		fFound=0;
		i = 0;

		while (!fFound) {		/* while there are valid entries */

			if (i==spc) {		/* reached last dir sector of this cluster */
				erc = NextFATClstr(Drive, Clstr, &Clstr);
				if (!erc) {
					if (Clstr >= MaxClstr)			 /* last sector */
						return(ErcNoSuchFile);		 /* not found */
					sector = ClsToLBA(Clstr, Drive); /* LBA of next sector */
					i=0;
				}
				else
					return(erc);
			}

			erc = DeviceOp(Ldrv[Drive].DevNum, 1, sector++, 1, abRawSector);
			if (erc)
				return(erc);
			i++;	/* Next sector in this cluster */

		    pEnt = &abRawSector[0];
			for (k=0; k<16; k++) {		/* 16 entries per sector */
				if (CompareNCS(pEnt, FileSpec[level], 11) == -1) {
					fFound=1;
					break;
				}
				pEnt+=32;	/* 32 byte per entry */
			}
		}
		pDirEnt = pEnt;				  /* Entry we just found */
	    Clstr = pDirEnt->StartClstr;  /* Clstr @ start of dir entry */
	}
	++level;		/* next level of parsed filespec */
  }
return (erc);
}

/*******************************************************
 This is the BLOCK read for the MMURTL DOS file system.
 It reads whole sectors and returns them to pBytesRet.
 There are NO internal filesystem buffers for this call.
 Data is returned directly to your buffer from the Disk.
 This is the fastest method for reading a file.
 This is also used internally to fill a stream buffer.
********************************************************/

U32 ReadBlockM(U32 dHandle,
               U8  *pBytesRet,
               U32 nBytes,
               U32 dLFA,
               U32 *pdBytesRet,
               U8  fFill)			/* TRUE if filling a stream buffer */
{
U32 erc, j, LBA, iFCB, bpc, spc, nDone, rLFA, nLeft, nBlks;
U16 Clstr, MaxClstr;
U8 Drive;

  erc = ValidateHandle(dHandle, &iFCB);		/* Sets iFCB if OK */
  if (erc) return erc;

  /* Certain FUB fields have different meanings in stream */

  if ((paFUB[dHandle].fStream) && (!fFill))
  	return ErcStreamFile;

  /* set these up in advance */

  nBlks = nBytes/512;
  Drive = paFCB[iFCB]->Ldrv;			/* What logical drive are we on? */
  spc = Ldrv[Drive].SecPerClstr;		/* sectors per cluster */
  bpc = 512 * spc;                  	/* Bytes per cluster */
  if (Ldrv[Drive].fFAT16)
  	MaxClstr = 0xfff8;
  else
 	MaxClstr = 0xff8;	/* FAT12 */

  erc = GetAbsoluteClstr(dHandle, dLFA, &Clstr, &rLFA);

  LBA = ClsToLBA(Clstr, Drive);		/* Get LBA of the target cluster */

  /* Now LBA equals beginning of cluster that dLFA resides in.
     We must see which sector in Clstr is the starting LBA.  To do this
     we MOD (dLFA in sectors) by (sectors per cluster) and
     add the leftover amount (should be 0 to nSPC-1) to LBA before we
     read.  For example: if dLFA was 2560 and spc was 4, this
     would be 5 % 4 = 1.  We would add 1 to the LBA.
     This is only done for the first read in the loop.
     We also set nleft which is how many sectors are left in the
     current cluster we are reading from.
  */

  LBA += (dLFA/512) % spc;
  nLeft = spc - (dLFA/512) % spc;
  nDone = 0;

  while ((nBlks) && (!erc)) {	/* while buffer isn't full and no error */
	if (nBlks > nLeft)
		j = nLeft;
	else j = nBlks;

	paFUB[dHandle]->Clstr = Clstr;			/* Save Current cluster */
	paFUB[dHandle]->LFAClstr = rLFA; 		/* Save LFA for Clstr in FUB */

	erc = DeviceOp(Ldrv[Drive].DevNum, 1, LBA, j, pBytesRet);
	if (erc)
		break;
	pBytesRet += j * 512;	/* further into their buffer */
	nBlks -= j;
	nLeft -= j;
	nDone += j;

	if ((nBlks) && (!nLeft)) { 		/* current cluster has none left */
		nLeft = spc;
		erc = NextFATClstr(Drive, Clstr, &Clstr);	/* next FAT cluster */
		if (erc)
			return(erc);
		rLFA += bpc;						 /* Update rel LFA of new cluster*/
	    if (Clstr >= MaxClstr) erc = ErcEOF; /* Last cluster */
	    if (!Clstr) erc = ErcBrokenFile;	 /* No good next cluster! */
		LBA = ClsToLBA(Clstr, Drive);		 /* Get LBA of the target cluster*/
	}
  }
  *pdBytesRet = nDone*512;

  return erc;		/* WE'RE DONE, return the error (if any) */
}

/*** Write Block ***************************************
 This is the BLOCK write for the MMURTL FAT file system.
 dLFA must be the LFA of a valid portion of the file and
 nBlks must not extend beyond the last cluster allocated
 to the file. IOW, you must call SetFileSize first.
 In a block write dLFA is always written on
 a sector boundry. We must make sure that the filesize
 will accomadate the sectors we want to write!
********************************************************/

U32 WriteBlockM(U32 dHandle, char *pData, U32 nBytes,
                U32 dLFA, U8 *pdnBytesRet)
{
U32 erc, i, j, LBA, iFCB, bpc, spc, nDone, rLFA, nLeft, nBlks;
U16 Clstr, MaxClstr;
U8 Drive;

  erc = ValidateHandle(dHandle, &iFCB);		/* Sets iFCB if OK */
  if (erc) return erc;

  nBlks = nBytes*512;
  dLFA = (dLFA/512)*512;		/* round LFA down to nearest sector */

  if (!paFCB[iFCB]->Mode)		/* Is it open in Modify?? */
  	return(ErcReadOnly);

  i = (paFCB[iFCB]->FileSize/512);	/* Set i nBlks in file max */
  if (paFCB[iFCB]->FileSize%512)
  	i++;

  j = (dLFA/512) + nBlks;	/* blocks to write past dLFA*/

  if (j > i)
  	return(ErcBeyondEOF);

  /* It seems OK to write the blocks out, so now let's DO IT! */


  Drive = paFCB[iFCB]->Ldrv;			/* What logical drive are we on? */
  spc = Ldrv[Drive].SecPerClstr;		/* sectors per cluster */
  bpc = 512 * spc;                  	/* Bytes per cluster */
  if (Ldrv[Drive].fFAT16)
  	MaxClstr = 0xfff8;
  else
 	MaxClstr = 0xff8;	/* FAT12 */

  erc = GetAbsoluteClstr(dHandle, dLFA, &Clstr, &rLFA);
  if (erc)
  	return(erc);

  LBA = ClsToLBA(Clstr, Drive);		/* Get LBA of the target cluster */

  /* Now LBA equals beginning of cluster that dLFA resides in.
     We must see which sector in Clstr is the starting LBA.  To do this
     we MOD (dLFA in sectors) by (sectors per cluster) and
     add the leftover amount (should be 0 to nSPC-1) to LBA before we
     write.  For example: if dLFA was 2560 and spc was 4, this
     would be 5 % 4 = 1.  We would add 1 to the LBA.
     This is only done for the first write in the loop.
     We also set nleft which is how many sectors are left in the
     current cluster we are writing to.
  */

  LBA += (dLFA/512) % spc;
  nLeft = spc - (dLFA/512) % spc;
  nDone = 0;

  while ((nBlks) && (!erc)) {	/* while blocks are left to write */
	if (nBlks > nLeft)
		j = nLeft;
	else j = nBlks;

	paFUB[dHandle]->Clstr = Clstr;			/* Save Current cluster */
	paFUB[dHandle]->LFAClstr = rLFA; 		/* Save LFA for Clstr in FUB */

	erc = DeviceOp(Ldrv[Drive].DevNum, 2, LBA, j, pData);
	if (erc)
		break;
	pData += (j * 512);	/* Update address */
	nDone += j;			/* Total blocks done so far */
	nBlks -= j;
	nLeft -= j;

	if ((nBlks) && (!nLeft)) { 		/* done with current cluster */
		nLeft = spc;
		erc = NextFATClstr(Drive, Clstr, &Clstr);	/* next FAT cluster */
		if (erc)
			return(erc);
		rLFA += bpc;						 /* Update rel LFA of new cluster*/
	    if ((Clstr >= MaxClstr) && (nBlks))  /* Problem! */
	    	erc = ErcBeyondEOF; 			 /* Last cluster & they want more*/
	    if (!Clstr) erc = ErcBrokenFile;	 /* No good next cluster! */
		LBA = ClsToLBA(Clstr, Drive);		 /* Get LBA of the target cluster*/
	}
  }
  *pdnBytesRet = nDone * 512;
  return erc;		/* WE'RE DONE, return the error (if any) */
}


/*********************************************************
 Fills the stream buffer for the Current LFA in the FUB.
 We simply figure out which reative LBA we want in the
 buffer and call ReadBlockM to fill it.  We then set
 LFABuf in the FUB to show the LFA of the first byte
 in the buffer.
**********************************************************/

U32 FillStreamBuff(U32 dHandle, U8 fInitial)
{
U32 erc, i, LFA, cLFA, LFABuf, iFCB;
U32 sBuf;
U8  *pBuf;

  erc = 0;

  /* Set these up in advance */

  cLFA =  paFUB[dHandle]->CrntLFA;		/* Find out where we want to be */
  LFABuf = paFUB[dHandle]->LFABuf;		/* LFA of first byte in buffer now */
  pBuf = paFUB[dHandle]->pBuf;			/* Local ptr to buffer */
  sBuf = paFUB[dHandle]->sBuf;			/* size of buffer */
  iFCB = paFUB[dHandle]->iFCB;			/* FCB for this FUB */

	/*	If the file was just opened we fill with LFA 0 */

  if (fInitial) {
	erc = ReadBlockM(dHandle, pBuf, sBuf, 0, &i, TRUE);
  }

	/* Else If the LFA is already in the buffer we just exit OK */

  else if ((cLFA >= LFABuf) && (cLFA < (LFABuf + sBuf))) {
	erc = 0;
  }

	/* We must figure out what starting LFA we want and fill the buffer */

  else {
	LFA = (cLFA/512) * 512;		/* Round down to nearest sector */
	erc = ReadBlockM(dHandle, pBuf, sBuf, LFA, &i, 1);
    paFUB[dHandle]->LFABuf = LFA;
  }

  if (erc == ErcEOF)		/* We ignore this when filling the buffer */
  	erc = 0;
  return erc;		/* WE'RE DONE, return the error (if any, except EOF) */
}

/*******************************************************
 This is the STREAM read for the MMURTL FAT file system.
 Used in conjunction with Get & Set FileLFA, you can
 move to any portion of the file to read one or more bytes.
 Data is buffered in Page sized chunks by the file
 system. This is the easiest method for reading a file.
********************************************************/

U32 ReadBytesM(U32 dHandle, U8 *pBytesRet, U32 nBytes, U32 *pdReadRet)
{
U32 erc, iFCB, sBuf, cLFA, fSize;
U32 nBytesDone, 	/* Total read so far */
	lfaEOB, 		/* LFA end of Buffer */
	nBytesOut;		/* Number of bytes to copy (this buffer ful

⌨️ 快捷键说明

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