fatlite.c

来自「cpc-1631的BSP包for VxWorks操作系统」· C语言 代码 · 共 1,760 行 · 第 1/5 页

C
1,760
字号
/*									*/
/* Parameters:                                                          */
/*	irHandle	: Drive number (0, 1, ...)			*/
/*      irData		: Address of user buffer to write from		*/
/*	irSectorNo	: First sector no. to write (sector 0 is the	*/
/*			  DOS boot sector).				*/
/*	irSectorCount	: Number of consectutive sectors to write	*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*	irSectorCount	: Number of sectors actually written		*/
/*----------------------------------------------------------------------*/

static FLStatus absWrite(Volume vol, IOreq FAR2 *ioreq)
{
  char FAR1 *userBuffer = (char FAR1 *) ioreq->irData;
  SectorNo currSector = vol.bootSectorNo + ioreq->irSectorNo;
  unsigned sectorCount = ioreq->irSectorCount;

  if (currSector < vol.secondFATSectorNo &&
      currSector + sectorCount > vol.firstFATSectorNo) {
    unsigned iSector;

    for (iSector = 0; iSector < sectorCount;
	 iSector++, currSector++, userBuffer += SECTOR_SIZE) {
      if (currSector >= vol.firstFATSectorNo &&
	  currSector < vol.secondFATSectorNo)
	replaceFATsector(&vol,currSector,userBuffer);
    }

    userBuffer = (char FAR1 *) ioreq->irData;
    currSector = vol.bootSectorNo + ioreq->irSectorNo;
  }

  for (ioreq->irSectorCount = 0;
       ioreq->irSectorCount < sectorCount;
       ioreq->irSectorCount++, currSector++, userBuffer += SECTOR_SIZE) {
    checkStatus(vol.tl.writeSector(vol.tl.rec,currSector,userBuffer));
  }

  return flOK;
}


/*----------------------------------------------------------------------*/
/*		          a b s D e l e t e 				*/
/*									*/
/* Marks absolute sectors by sector no. as deleted.			*/
/*									*/
/* Parameters:                                                          */
/*	irHandle	: Drive number (0, 1, ...)			*/
/*	irSectorNo	: First sector no. to write (sector 0 is the	*/
/*			  DOS boot sector).				*/
/*	irSectorCount	: Number of consectutive sectors to delete	*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus absDelete(Volume vol, IOreq FAR2 *ioreq)
{
  return vol.tl.deleteSector(vol.tl.rec,vol.bootSectorNo + ioreq->irSectorNo,ioreq->irSectorCount);
}


/*----------------------------------------------------------------------*/
/*		             g e t B P B 				*/
/*									*/
/* Reads the BIOS Parameter Block from the boot sector			*/
/*									*/
/* Parameters:                                                          */
/*	irHandle	: Drive number (0, 1, ...)			*/
/*      irData		: Address of user buffer to read BPB into	*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus getBPB(Volume vol, IOreq FAR2 *ioreq)
{
  BPB FAR1 *userBPB = (BPB FAR1 *) ioreq->irData;
  DOSBootSector FAR0 *bootSector;
  unsigned long noOfHiddenSectors;
  PartitionTable FAR0 *partitionTable;

  bootSector = (DOSBootSector FAR0 *) findSector(&vol,vol.bootSectorNo);
  if(bootSector == NULL)
    return flSectorNotFound;

  *userBPB = bootSector->bpb;
#if	FALSE
  tffscpy (userBPB, &bootSector->bpb, sizeof(BPB));
#endif	/* FALSE */

  /* take the number of hidden sectors from the partition table in case
     we don't have DOS format BPB					*/
  partitionTable = (PartitionTable FAR0 *) findSector(&vol,0);
  if(partitionTable == NULL)
    return flSectorNotFound;

  if (LE2(partitionTable->signature) == PARTITION_SIGNATURE &&
      partitionTable->type != 0) {
    noOfHiddenSectors = UNAL4(partitionTable->startingSectorOfPartition);
    toLE4(userBPB->noOfHiddenSectors, noOfHiddenSectors);
  }

  return flOK;
}

#endif /* ABS_READ_WRITE */

#ifdef LOW_LEVEL

/*----------------------------------------------------------------------*/
/*		             m o u n t L o w L e v e l 			*/
/*									*/
/* Mount a volume for low level operations. If a low level routine is   */
/* called and the volume is not mounted for low level operations, this	*/
/* routine is called atomatically. 					*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus mountLowLevel(Volume vol)
{
  checkStatus(flIdentifyFlash(vol.socket,&vol.flash));
  vol.flash.setPowerOnCallback(&vol.flash);
  vol.flags |= VOLUME_LOW_LVL_MOUNTED;

  return flOK;
}

/*----------------------------------------------------------------------*/
/*		             d i s m o u n t L o w L e v e l 		*/
/*									*/
/* Dismount the volume for low level operations.			*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/*----------------------------------------------------------------------*/

static void dismountLowLevel(Volume vol)
{
  /* mark the volume as unmounted for low level operations, untouch other flags */
  vol.flags &= ~VOLUME_LOW_LVL_MOUNTED;
}

/*----------------------------------------------------------------------*/
/*		             g e t P h y s i c a l I n f o 		*/
/*									*/
/* Get physical information of the media. The information includes	*/
/* JEDEC ID, unit size and media size.					*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*      irData		: Address of user buffer to read physical	*/
/*			  information into.				*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus getPhysicalInfo(Volume vol, IOreq FAR2 *ioreq)
{
  PhysicalInfo FAR2 *physicalInfo = (PhysicalInfo FAR2 *)ioreq->irData;

  physicalInfo->type = vol.flash.type;
  physicalInfo->unitSize = vol.flash.erasableBlockSize;
  physicalInfo->mediaSize = vol.flash.chipSize * vol.flash.noOfChips;

  return flOK;
}

/*----------------------------------------------------------------------*/
/*		             p h y s i c a l R e a d	 		*/
/*									*/
/* Read from a physical address.					*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*	irAddress	: Physical address to read from.		*/
/*	irByteCount	: Number of bytes to read.			*/
/*      irData		: Address of user buffer to read into.		*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus physicalRead(Volume vol, IOreq FAR2 *ioreq)
{
  /* check that we are reading whithin the media boundaries */
  if (ioreq->irAddress + (long)ioreq->irByteCount > vol.flash.chipSize *
				    vol.flash.noOfChips)
    return flBadParameter;

  /* We don't read accross a unit boundary */
  if ((long)ioreq->irByteCount > vol.flash.erasableBlockSize -
			   (ioreq->irAddress % vol.flash.erasableBlockSize))
    return flBadParameter;

  vol.flash.read(&vol.flash, ioreq->irAddress, ioreq->irData,
		 ioreq->irByteCount, 0);
  return flOK;
}

/*----------------------------------------------------------------------*/
/*		             p h y s i c a l W r i t e	 		*/
/*									*/
/* Write to a physical address.						*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*	irAddress	: Physical address to write to.			*/
/*	irByteCount	: Number of bytes to write.			*/
/*      irData		: Address of user buffer to write from.		*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus physicalWrite(Volume vol, IOreq FAR2 *ioreq)
{
  /* check that we are writing whithin the media boundaries */
  if (ioreq->irAddress + (long)ioreq->irByteCount > vol.flash.chipSize *
					       vol.flash.noOfChips)
    return flBadParameter;

  /* We don't write accross a unit boundary */
  if ((long)ioreq->irByteCount > vol.flash.erasableBlockSize -
			   (ioreq->irAddress % vol.flash.erasableBlockSize))
    return flBadParameter;

  checkStatus(vol.flash.write(&vol.flash, ioreq->irAddress, ioreq->irData,
			      ioreq->irByteCount, 0));
  return flOK;
}

/*----------------------------------------------------------------------*/
/*		             p h y s i c a l E r a s e	 		*/
/*									*/
/* Erase physical units.						*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*	irUnitNo	: First unit to erase.				*/
/*	irUnitCount	: Number of units to erase.			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus physicalErase(Volume vol, IOreq FAR2 *ioreq)
{
  if (ioreq->irUnitNo + (long)ioreq->irUnitCount > vol.flash.chipSize * vol.flash.noOfChips /
					       vol.flash.erasableBlockSize)
    return flBadParameter;

  checkStatus(vol.flash.erase(&vol.flash, ioreq->irUnitNo, ioreq->irUnitCount));
  return flOK;
}

#endif /* LOW_LEVEL */

#if FILES > 0

/*----------------------------------------------------------------------*/
/*		         f l u s h B u f f e r				*/
/*									*/
/* Writes the buffer contents if it is dirty.                           */
/*									*/
/* If this is a FAT sector, all FAT copies are written.			*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus flushBuffer(Volume vol)
{
  if (buffer.dirty) {
    FLStatus status;
    unsigned i;

#ifdef SINGLE_BUFFER
    Volume *bufferOwner = (Volume *) buffer.owner;

    if (&vol != bufferOwner) {
      flFreeMutex(&execInProgress);
      checkStatus(setBusy(bufferOwner,TFFS_ON));
    }
#else
    Volume *bufferOwner = &vol;
#endif

    status = (*bufferOwner).tl.writeSector((*bufferOwner).tl.rec, buffer.sectorNo,
					   buffer.data);
    if (status == flOK) {
      if (buffer.sectorNo >= (*bufferOwner).firstFATSectorNo &&
	  buffer.sectorNo < (*bufferOwner).secondFATSectorNo)
	for (i = 1; i < (*bufferOwner).numberOfFATS; i++)
	  checkStatus((*bufferOwner).tl.writeSector((*bufferOwner).tl.rec,
						    buffer.sectorNo + i * (*bufferOwner).sectorsPerFAT,
						    buffer.data));
    }
    else
      buffer.sectorNo = UNASSIGNED_SECTOR;
#ifdef SINGLE_BUFFER
    if (&vol != bufferOwner) {
      setBusy(bufferOwner,TFFS_OFF);
      if (!flTakeMutex(&execInProgress,1))
	return flGeneralFailure;
    }
#endif
    buffer.dirty = buffer.checkPoint = FALSE;

    return status;
  }
  else
    return flOK;
}


/*----------------------------------------------------------------------*/
/*		        u p d a t e S e c t o r				*/
/*									*/
/* Prepares a sector for update in the buffer				*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sectorNo	: Sector no. to read				*/
/*	read		: Whether to initialize buffer by reading, or	*/
/*                        clearing					*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, otherwise failed                */
/*----------------------------------------------------------------------*/

static FLStatus updateSector(Volume vol, SectorNo sectorNo, FLBoolean read)
{
  if (sectorNo != buffer.sectorNo || &vol != buffer.owner) {
    const void FAR0 *mappedSector;

    checkStatus(flushBuffer(&vol));
#ifdef SINGLE_BUFFER
  }

⌨️ 快捷键说明

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