tffsdrv.c
来自「cpc-1631的BSP包for VxWorks操作系统」· C语言 代码 · 共 830 行 · 第 1/2 页
C
830 行
return (ERROR);
}
ioreq.irHandle = pTffsDev->tffsDriveNo;
status = flCheckVolume(&ioreq);
if (status == flNotMounted)
{
status = flMountVolume(&ioreq);
if (status == flOK)
{
ioreq.irData = &bpb;
status = flGetBPB(&ioreq);
}
if (status != flOK)
{
pTffsDev->tffsBlkdev.bd_readyChanged = TRUE;
return (ERROR);
}
/* Modify BLK_DEV structure */
tffsSetFromBPB( &(pTffsDev->tffsBlkdev), &bpb);
pTffsDev->tffsBlkdev.bd_mode = O_RDWR; /* initial mode for device */
}
ioreq.irSectorNo = startBlk;
ioreq.irSectorCount = numBlks;
ioreq.irData = pBuffer;
status = flAbsRead(&ioreq);
/* if success cancel dosFs re-mount volume request */
if (status != flOK)
pTffsDev->tffsBlkdev.bd_readyChanged = TRUE;
return ((status == flOK) ? OK : ERROR);
}
/*******************************************************************************
*
* tffsBlkWrt - write sequence of blocks to TFFS device
*
* This routine writes a sequence of blocks to TrueFFS device.
*
* RETURNS: OK, or ERROR if it failed.
*
* NOMANUAL
*/
LOCAL STATUS tffsBlkWrt
(
FAST TFFS_DEV * pTffsDev, /* pointer to device descriptor */
int startBlk, /* starting block number to write */
int numBlks, /* number of blocks to write */
char * pBuffer /* pointer to buffer containing data */
)
{
FLStatus status = flOK;
IOreq ioreq;
BPB bpb;
if ( (NULL == pTffsDev) || (NULL == pBuffer) ||
(pTffsDev->tffsDriveNo >= DRIVES) )
{
return (ERROR);
}
ioreq.irHandle = pTffsDev->tffsDriveNo;
status = flCheckVolume(&ioreq);
if (status == flNotMounted)
{
status = flMountVolume(&ioreq);
if (status == flOK)
{
ioreq.irData = &bpb;
status = flGetBPB(&ioreq);
}
if (status != flOK)
{
pTffsDev->tffsBlkdev.bd_readyChanged = TRUE;
return (ERROR);
}
/* Modify BLK_DEV structure */
tffsSetFromBPB( &(pTffsDev->tffsBlkdev), &bpb);
pTffsDev->tffsBlkdev.bd_mode = O_RDWR; /* initial mode for device */
}
ioreq.irSectorNo = startBlk;
ioreq.irSectorCount = numBlks;
ioreq.irData = pBuffer;
status = flAbsWrite(&ioreq);
if (status == flWriteProtect)
{
flDismountVolume(&ioreq); /* force a remount */
pTffsDev->tffsBlkdev.bd_mode = O_RDONLY;
}
/* re-mount volume request */
if (status != flOK)
pTffsDev->tffsBlkdev.bd_readyChanged = TRUE;
return ((status == flOK) ? OK : ERROR);
}
/*******************************************************************************
*
* tffsSetFromBPB - copy some data from BIOS parameter block
*
* This routine copies BIOS parameter block data describing the flash device
* returned by TrueFFS into a device descriptor.
*
* RETURNS: N/A
*
* NOMANUAL
*/
LOCAL void tffsSetFromBPB
(
BLK_DEV * pBlkDev, /* pointer to device descriptor */
BPB * pBPB /* pointer to BIOS parameters block */
)
{
if ((NULL == pBlkDev) || (NULL == pBPB))
return;
pBlkDev->bd_nBlocks = 0;
pBlkDev->bd_bytesPerBlk = 0;
pBlkDev->bd_blksPerTrack = 0;
pBlkDev->bd_nHeads = 0; /* clear first */
if( UNAL2(pBPB->totalSectorsInVolumeDOS3) )
pBlkDev->bd_nBlocks = UNAL2(pBPB->totalSectorsInVolumeDOS3);
else
pBlkDev->bd_nBlocks = LE4(pBPB->totalSectorsInVolume);
pBlkDev->bd_bytesPerBlk = UNAL2(pBPB->bytesPerSector);
pBlkDev->bd_blksPerTrack = LE2(pBPB->sectorsPerTrack);
pBlkDev->bd_nHeads = LE2(pBPB->noOfHeads);
}
/*******************************************************************************
*
* tffsDiskChangeAnnounce - announce disk change to the file system attached
*
* This routine is called by TFFS to update the the readyChanged field in the
* device descriptor so that the file system can be notified of a disk change.
*
* RETURNS: N/A
*
* NOMANUAL
*/
void tffsDiskChangeAnnounce
(
unsigned volNo /* FLite drive number (0 - DRIVES-1) */
)
{
if ((volNo < DRIVES) && (tffsBlkDevs[volNo] != NULL))
tffsBlkDevs[volNo]->tffsBlkdev.bd_readyChanged = TRUE;
}
/*******************************************************************************
*
* tffsDevFormat - format a flash device for use with TrueFFS
*
* This routine formats a flash device for use with TrueFFS. It takes two
* parameters, a drive number and a pointer to a device format structure.
* This structure describes how the volume should be formatted. The structure
* is defined in dosformt.h. The drive number is assigned in the order that
* the socket component for the device was registered.
*
* The format process marks each erase unit with an Erase Unit Header (EUH) and
* creates the physical and virtual Block Allocation Maps (BAM) for the device.
* The erase units reserved for the "boot-image" are skipped and the first
* EUH is placed at number (boot-image length - 1). To write to the boot-image
* region, call tffsBootImagePut().
*
* WARNING: If any of the erase units in the boot-image
* region contains an erase unit header from a previous format call (this can
* happen if you reformat a flash device specifying a larger boot region)
* TrueFFS fails to mount the device. To fix this problem, use tffsRawio() to
* erase the problem erase units (thus removing the outdated EUH).
*
* The macro TFFS_STD_FORMAT_PARAMS defines the default values used for
* formatting a flask disk device. If the second argument to this routine
* is zero, tffsDevFormat() uses these default values.
*
* RETURNS: OK, or ERROR if it failed.
*/
STATUS tffsDevFormat
(
int tffsDriveNo, /* TrueFFS drive number (0 - DRIVES-1) */
int arg /* pointer to tffsDevFormatParams structure */
)
{
tffsDevFormatParams defaultParams = TFFS_STD_FORMAT_PARAMS;
tffsDevFormatParams *devFormatParams;
IOreq ioreq;
FLStatus status;
if (tffsDriveNo >= DRIVES)
return (ERROR);
/* tell dosFs to re-mount volume */
if (tffsBlkDevs[tffsDriveNo] != NULL)
tffsBlkDevs[tffsDriveNo]->tffsBlkdev.bd_readyChanged = TRUE;
if (arg == 0)
devFormatParams = &defaultParams;
else
devFormatParams = (tffsDevFormatParams *) arg;
ioreq.irHandle = tffsDriveNo;
ioreq.irFlags = devFormatParams->formatFlags;
ioreq.irData = &(devFormatParams->formatParams);
status = flFormatVolume(&ioreq);
return ((status == flOK) ? OK : ERROR);
}
/*******************************************************************************
*
* tffsRawio - low level I/O access to flash components
*
* Use the utilities provided by thisroutine with the utmost care. If you use
* these routines carelessly, you risk data loss as well as permanent
* physical damage to the flash device.
*
* This routine is a gateway to a series of utilities (listed below). Functions
* such as mkbootTffs() and tffsBootImagePut() use these tffsRawio() utilities
* to write boot sector information. The functions for physical read, write, and
* erase are made available with the intention that they be used on erase units
* allocated to the boot-image region by tffsDevFormat(). Using these functions
* elsewhere could be dangerous.
*
* The <arg0>, <arg1>, and <arg2> parameters to tffsRawio() are interpreted
* differently depending on the function number you specify for <functionNo>.
* The drive number is determined by the order in which the socket
* components were registered.
*
* .TS
* tab(|);
* lf3 lf3 lf3 lf3
* l l l l .
* Function Name | arg0 | arg1 | arg2
* _
* TFFS_GET_PHYSICAL_INFO | user buffer address | N/A | N/A
* TFFS_PHYSICAL_READ | address to read | byte count | user buffer address
* TFFS_PHYSICAL_WRITE | address to write | byte count | user buffer address
* TFFS_PHYSICAL_ERASE | first unit | number of units | N/A
* TFFS_ABS_READ | sector number | number of sectors | user buffer address
* TFFS_ABS_WRITE | sector number | number of sectors | user buffer address
* TFFS_ABS_DELETE | sector number | number of sectors | N/A
* TFFS_DEFRAGMENT_VOLUME | number of sectors | user buffer address | N/A
* .TE
*
* TFFS_GET_PHYSICAL_INFO writes the flash type, erasable block size, and media
* size to the user buffer specified in <arg0>.
*
* TFFS_PHYSICAL_READ reads <arg1> bytes from <arg0> and writes them to
* the buffer specified by <arg2>.
*
* TFFS_PHYSICAL_WRITE copies <arg1> bytes from the <arg2> buffer and writes
* them to the flash memory location specified by <arg0>.
* This aborts if the volume is already mounted to prevent the versions of
* translation data in memory and in flash from going out of synchronization.
*
* TFFS_PHYSICAL_ERASE erases <arg1> erase units, starting at the erase unit
* specified in <arg0>.
* This aborts if the volume is already mounted to prevent the versions of
* translation data in memory and in flash from going out of synchronization.
*
* TFFS_ABS_READ reads <arg1> sectors, starting at sector <arg0>, and writes
* them to the user buffer specified in <arg2>.
*
* TFFS_ABS_WRITE takes data from the <arg2> user buffer and writes <arg1>
* sectors of it to the flash location starting at sector <arg0>.
*
* TFFS_ABS_DELETE deletes <arg1> sectors of data starting at sector <arg0>.
*
* TFFS_DEFRAGMENT_VOLUME calls the defragmentation routine with the minimum
* number of sectors to be reclaimed, <arg0>, and writes the actual number
* reclaimed in the user buffer by <arg1>. Calling this function through some
* low priority task will make writes more deterministic.
* No validation is done of the user specified address fields, so the functions
* assume they are writable. If the address is invalid, you could see bus errors
* or segmentation faults.
*
* RETURNS: OK, or ERROR if it failed.
*/
STATUS tffsRawio
(
int tffsDriveNo, /* TrueFFS drive number (0 - DRIVES-1) */
int functionNo, /* TrueFFS function code */
int arg0, /* argument 0 */
int arg1, /* argument 1 */
int arg2 /* argument 2 */
)
{
IOreq ioreq;
FLStatus status;
int function;
if (tffsDriveNo >= DRIVES)
return (ERROR);
ioreq.irHandle = tffsDriveNo; /* drive number */
switch (functionNo)
{
case TFFS_GET_PHYSICAL_INFO:
function = FL_GET_PHYSICAL_INFO;
ioreq.irData = (char *)arg0; /* address of user buffer to store */
break;
case TFFS_PHYSICAL_READ:
function = FL_PHYSICAL_READ;
ioreq.irAddress = arg0; /* chip/card address to read/write */
ioreq.irByteCount = arg1; /* number of bytes to read/write */
ioreq.irData = (char *)arg2; /* address of user buffer to r/w */
break;
case TFFS_PHYSICAL_WRITE:
function = FL_PHYSICAL_WRITE;
ioreq.irAddress = arg0; /* chip/card address to read/write */
ioreq.irByteCount = arg1; /* number of bytes to read/write */
ioreq.irData = (char *)arg2; /* address of user buffer to r/w */
break;
case TFFS_PHYSICAL_ERASE:
function = FL_PHYSICAL_ERASE;
ioreq.irUnitNo = arg0; /* first unit to erase */
ioreq.irUnitCount = arg1; /* number of units to erase */
break;
case TFFS_ABS_READ:
function = FL_ABS_READ;
ioreq.irSectorNo = arg0; /* sector number to read/write */
ioreq.irSectorCount = arg1; /* number of sectors to read/write */
ioreq.irData = (char *)arg2; /* address of user buffer to r/w */
break;
case TFFS_ABS_WRITE:
function = FL_ABS_WRITE;
ioreq.irSectorNo = arg0; /* sector number to read/write */
ioreq.irSectorCount = arg1; /* number of sectors to read/write */
ioreq.irData = (char *)arg2; /* address of user buffer to r/w */
break;
case TFFS_ABS_DELETE:
function = FL_ABS_DELETE;
ioreq.irSectorNo = arg0; /* sector number to delete */
ioreq.irSectorCount = arg1; /* number of sectors to delete */
break;
case TFFS_DEFRAGMENT_VOLUME:
function = FL_DEFRAGMENT_VOLUME;
ioreq.irLength = arg0; /* minimum number of sectors to get */
break;
default:
return (ERROR);
}
status = flCall (function, &ioreq);
switch (functionNo)
{
case TFFS_DEFRAGMENT_VOLUME:
*(int *)arg1 = ioreq.irLength; /* min number of sectors gotten */
break;
}
return ((status == flOK) ? OK : ERROR);
}
#if (POLLING_INTERVAL > 0)
/*******************************************************************************
*
* flPollSemCreate - create semaphore for polling task
*
* This routine creates the semaphore used to delay socket polling until
* TrueFFS initialization is complete.
*
* RETURNS: flOK, or flNotEnoughMemory if it fails.
*/
LOCAL FLStatus flPollSemCreate (void)
{
if ((flPollSemId = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY)) == NULL)
return (flNotEnoughMemory);
else
return (flOK);
}
#endif /* (POLLING_INTERVAL > 0) */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?