📄 rawfslib.c
字号:
* OK, or* ERROR, if write error and reset/retry failed.*/LOCAL STATUS rawFsBlkWrt ( FAST RAW_VOL_DESC *vdptr, /* pointer to volume descriptor */ int startBlk, /* starting block number for write */ int numBlks, /* how many blocks to write */ char *pBuf /* pointer to buffer to write to disk */ ) { FAST BLK_DEV *pBlkDev = vdptr->rawvd_pBlkDev; /* pointer to block device struct */ vdptr->rawvd_retry = 0; while (((* pBlkDev->bd_blkWrt) (pBlkDev, startBlk, numBlks, pBuf)) != OK) { /* write error: reset volume and retry, up to device's retry limit */ if (rawFsReset (vdptr) != OK) return (ERROR); /* drive won't reset! */ if (++(vdptr->rawvd_retry) > pBlkDev->bd_retry) return (ERROR); /* retry limit reached */ } return (OK); }/********************************************************************************* rawFsClose - close raw volume** This routine closes the specified raw volume file descriptor. Any* buffered data for the descriptor is written to the physical device.** If the file descriptor has been marked as obsolete (meaning the* volume was unmounted while the descriptor was open), the descriptor* is freed, but an error is returned.** RETURNS: OK, or ERROR.*/LOCAL STATUS rawFsClose ( FAST RAW_FILE_DESC *pRawFd /* file descriptor pointer */ ) { FAST STATUS status; FAST RAW_VOL_DESC *vdptr = pRawFd->rawfd_vdptr; /* pointer to volume descriptor */ /* Take control of file descriptor */ semTake (pRawFd->rawfd_semId, WAIT_FOREVER); /* get ownership of fd */ /* If file descriptor is obsolete, free it but return error */ if (pRawFd->rawfd_status == RAWFD_OBSOLETE) { free (pRawFd->rawfd_buffer); /* free file I/O buffer */ rawFsFdFree (pRawFd); /* put fd on free list */ semGive (pRawFd->rawfd_semId); /* release fd */ errnoSet (S_rawFsLib_FD_OBSOLETE); return (ERROR); /* volume was remounted */ } semTake (vdptr->rawvd_semId, WAIT_FOREVER); /* get ownership of vol */ /* Write out file descriptor buffer, if necessary */ status = rawFsFdFlush (pRawFd); semGive (vdptr->rawvd_semId); /* release volume */ free (pRawFd->rawfd_buffer); /* free file I/O buffer */ rawFsFdFree (pRawFd); /* put fd on free list */ semGive (pRawFd->rawfd_semId); /* release fd */ return (status); }/********************************************************************************* rawFsDevInit - associate a block device with raw volume functions** This routine takes a block device created by a device driver and* defines it as a raw file system volume. As a result, when high-level * I/O operations, such as open() and write(), are performed on the* device, the calls will be routed through rawFsLib.** This routine associates <volName> with a device and installs it in* the VxWorks I/O System's device table. The driver number used when* the device is added to the table is that which was assigned to the* raw library during rawFsInit(). (The driver number is kept in* the global variable `rawFsDrvNum'.)** The BLK_DEV structure specified by <pBlkDev> contains configuration* data describing the device and the addresses of five routines which* will be called to read blocks, write blocks, reset the device, check* device status, and perform other control functions (ioctl()). These routines* will not be called until they are required by subsequent I/O operations.** INTERNAL* The semaphore in the device is given, so the device is available for* use immediately.** RETURNS: A pointer to the volume descriptor (RAW_VOL_DESC),* or NULL if there is an error.*/RAW_VOL_DESC *rawFsDevInit ( char *volName, /* volume name */ FAST BLK_DEV *pBlkDev /* pointer to block device info */ ) { FAST RAW_VOL_DESC *vdptr; /* pointer to new volume descriptor */ /* Return error if no BLK_DEV */ if (pBlkDev == NULL) { errnoSet (S_rawFsLib_NO_BLOCK_DEVICE); return (NULL); } /* Allocate a raw volume descriptor for device */ if ((vdptr = (RAW_VOL_DESC *) calloc (sizeof (RAW_VOL_DESC), 1)) == NULL) return (NULL); /* no memory */ /* Add device to system device table */ if (iosDevAdd ((DEV_HDR *) vdptr, volName, rawFsDrvNum) != OK) { free ((char *) vdptr); return (NULL); /* can't add device */ } /* Initialize volume descriptor */ vdptr->rawvd_pBlkDev = pBlkDev; vdptr->rawvd_status = OK; vdptr->rawvd_state = RAW_VD_READY_CHANGED; /* Create volume locking semaphore (initially available) */ vdptr->rawvd_semId = semMCreate (rawFsVolMutexOptions); if (vdptr->rawvd_semId == NULL) return (NULL); /* could not create semaphore */ return (vdptr); }/********************************************************************************* rawFsFdFlush - flush raw volume file descriptor I/O buffer to disk** This routine causes the I/O buffer of a raw volume file descriptor* to be written out to the physical device.** RETURNS: OK, or ERROR if something could not be written out.*/LOCAL STATUS rawFsFdFlush ( FAST RAW_FILE_DESC *pRawFd /* pointer to file descriptor */ ) { if (pRawFd->rawfd_modified) { /* Write out the current (dirty) block and reset modified indicator */ if (rawFsBlkWrt (pRawFd->rawfd_vdptr, pRawFd->rawfd_bufBlk, 1, pRawFd->rawfd_buffer) != OK) return (ERROR); /* write error */ pRawFd->rawfd_modified = FALSE; } return (OK); }/********************************************************************************* rawFsFdFree - free a file descriptor** This routine removes a raw device file descriptor from the active* Fd list and places it on the free Fd list.**/LOCAL void rawFsFdFree ( FAST RAW_FILE_DESC *pRawFd /* pointer to file descriptor to free */ ) { semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of Fd lists */ pRawFd->rawfd_status = RAWFD_AVAILABLE; pRawFd->rawfd_bufBlk = NONE; lstDelete (&rawFsFdActiveList, &pRawFd->rawfd_node); /* remove Fd from active list */ lstAdd (&rawFsFdFreeList, &pRawFd->rawfd_node); /* add Fd to free list */ semGive (rawFsFdListSemId); /* release Fd lists */ }/********************************************************************************* rawFsFdGet - get an available file descriptor** This routine obtains a free raw volume file descriptor.** RETURNS: Pointer to file descriptor, or NULL if none available.*/LOCAL RAW_FILE_DESC *rawFsFdGet (void) { FAST RAW_FILE_DESC *pRawFd; /* ptr to newly acquired file descr */ semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of Fd lists */ pRawFd = (RAW_FILE_DESC *) lstGet (&rawFsFdFreeList); /* get a free Fd */ if (pRawFd != NULL) { pRawFd->rawfd_status = RAWFD_IN_USE; /* mark Fd as in-use */ lstAdd (&rawFsFdActiveList, (NODE *) pRawFd); /* add to active list */ } else errnoSet (S_rawFsLib_NO_FREE_FILE_DESCRIPTORS); /* max files already open */ semGive (rawFsFdListSemId); /* release Fd lists */ return (pRawFd); }/********************************************************************************* rawFsFlush - write all modified volume structures to disk** This routine will write all buffered data for a volume to the physical* device. It is called by issuing an ioctl() call with the FIOFLUSH or* FIOSYNC function codes. It may be used periodically to provide enhanced* data integrity, or to prepare a volume for removal from the device.** RETURNS: OK, or ERROR if volume could not be sync'd.**/LOCAL STATUS rawFsFlush ( FAST RAW_VOL_DESC *vdptr /* pointer to volume descriptor */ ) { FAST STATUS status; /* return status */ /* Check that volume is available */ semTake (vdptr->rawvd_semId, WAIT_FOREVER); /* get ownership of volume */ if ((rawFsVolCheck (vdptr) != OK) || (vdptr->rawvd_status != OK)) { semGive (vdptr->rawvd_semId); /* release volume */ errnoSet (S_rawFsLib_VOLUME_NOT_AVAILABLE); return (ERROR); /* cannot access volume */ } /* Flush volume to disk */ status = rawFsVolFlush (vdptr); semGive (vdptr->rawvd_semId); /* release volume */ return (status); }/********************************************************************************* rawFsInit - prepare to use the raw volume library** This routine initializes the raw volume library. It must be called exactly* once, before any other routine in the library. The argument specifies the* number of file descriptors that may be open at once. This routine allocates* and sets up the necessary memory structures and initializes semaphores.** This routine also installs raw volume library routines in the VxWorks I/O* system driver table. The driver number assigned to rawFsLib is placed in* the global variable `rawFsDrvNum'. This number will later be associated* with system file descriptors opened to rawFs devices.** This initialization is enabled when the configuration macro INCLUDE_RAWFS * is defined; rawFsInit() is then called from the root task, usrRoot(),* in usrConfig.c.** RETURNS: OK or ERROR.*/STATUS rawFsInit ( int maxFiles /* max no. of simultaneously open files */ ) { FAST RAW_FILE_DESC *pRawFd; /* pointer to created file descriptor */ FAST int ix; /* index var */ /* Install rawFsLib routines in I/O system driver table * Note that there is no delete routine, and that the * rawFsOpen routine is also used as the create function. */ rawFsDrvNum = iosDrvInstall ((FUNCPTR) rawFsOpen, (FUNCPTR) NULL, (FUNCPTR) rawFsOpen, rawFsClose, rawFsRead, rawFsWrite, rawFsIoctl); if (rawFsDrvNum == ERROR) return (ERROR); /* can't install as driver */ /* Create semaphore for locking access to file descriptor list */ rawFsFdListSemId = semMCreate (rawFsFdListMutexOptions); if (rawFsFdListSemId == NULL) return (ERROR); /* can't create semaphore */ semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of fd list */ /* Allocate memory for required number of file descriptors */ pRawFd = (RAW_FILE_DESC *) calloc ((UINT) maxFiles * sizeof (RAW_FILE_DESC), 1); if (pRawFd == NULL) return (ERROR); /* no memory */ /* Create list containing required number of file descriptors */ rawFsMaxFiles = maxFiles; for (ix = 0; ix < rawFsMaxFiles; ix++) { pRawFd->rawfd_status = RAWFD_AVAILABLE; /* Create semaphore for this fd (initially available) */ pRawFd->rawfd_semId = semMCreate (rawFsFdMutexOptions); if (pRawFd->rawfd_semId == NULL) return (NULL); /* could not create semaphore */ /* Add file descriptor to free list */ lstAdd (&rawFsFdFreeList, &pRawFd->rawfd_node); pRawFd++; /* next Fd */ } semGive (rawFsFdListSemId); /* release Fd lists */ return (OK); }/********************************************************************************* rawFsIoctl - perform a device-specific control function** This routine performs the following ioctl() functions:** .CS* FIODISKINIT: Initialize the disk volume. This routine does not* format the disk, that must be done by the driver.* FIOSEEK: Sets the file's current byte position to* the position specified by arg.* FIOWHERE: Returns the current byte position in the file.* FIOSYNC: Write all modified file descriptor buffers to device.* FIOFLUSH: Same as FIOSYNC.* FIONREAD: Return in arg the number of unread bytes.* FIODISKCHANGE: Indicate media change. See rawFsReadyChange().* FIOUNMOUNT: Unmount disk volume. See rawFsVolUnmount().* FIOGETFL: Return in arg the file's open mode.* .CE** If the ioctl (<function>) is not one of the above, the device driver* ioctl() routine is called to perform the function.** If an ioctl() call fails, the task status (see errnoGet()) indicates* the nature of the error.** RETURNS: OK, or ERROR if function failed or unknown function, or* current byte pointer for FIOWHERE.*/LOCAL STATUS rawFsIoctl ( FAST RAW_FILE_DESC *pRawFd, /* file descriptor of file to control */ int function, /* function code */ int arg /* some argument */ ) { FAST int retValue; /* return value */ semTake (pRawFd->rawfd_semId, WAIT_FOREVER); /* take control of fd */ /* Check that file descriptor is current */ if (pRawFd->rawfd_status == RAWFD_OBSOLETE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -