📄 rawfslib.c
字号:
/* rawFsLib.c - raw block device file system library *//* Copyright 1984-1998 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01p,14mar99,jdi doc: removed refs to config.h and/or configAll.h (SPR 25663).01o,29sep98,lrn merged mod 01n for T2.x, fixed copyright01n,30oct97,wil SPR# 9418: added check for new position past end of device to rawFsRead().01m,27jan93,jdi documentation cleanup for 5.1; added 3rd param to ioctl() examples.01l,02oct92,srh added ioctl(FIOGETFL) to return file's open mode01k,22jul92,kdl changed from 4.0.2-style semaphores to mutexes.01j,18jul92,smb Changed errno.h to errnoLib.h.01i,04jul92,jcf scalable/ANSI/cleanup effort.01h,26may92,rrr the tree shuffle01g,16dec91,gae added includes for ANSI.01f,19nov91,rrr shut up some ansi warnings.01e,04oct91,rrr passed through the ansification filter -changed functions to ansi style -changed READ, WRITE and UPDATE to O_RDONLY O_WRONLY and ... -changed VOID to void -changed copyright notice01d,05apr91,jdi documentation -- removed header parens and x-ref numbers; doc review by kdl.01c,21feb91,jaa documentation cleanup.01b,08oct90,kdl lint.01a,02oct90,kdl written*//*This library provides basic services for disk devices that do notuse a standard file or directory structure. The disk volume is treatedmuch like a large file. Portions of it may be read, written, or thecurrent position within the disk may be changed. However, thereis no high-level organization of the disk into files or directories.USING THIS LIBRARYThe various routines provided by the VxWorks raw "file system" (rawFs) maybe separated into three broad groups: general initialization,device initialization, and file system operation.The rawFsInit() routine is the principal initialization function;it need only be called once, regardless of how many rawFs deviceswill be used.A separate rawFs routine is used for device initialization. Foreach rawFs device, rawFsDevInit() must be called to install the device.Several routines are provided to inform the file system ofchanges in the system environment. The rawFsModeChange() routine may beused to modify the readability or writability of a particular device.The rawFsReadyChange() routine is used to inform the file system that adisk may have been swapped and that the next disk operation should firstremount the disk. The rawFsVolUnmount() routine informs thefile system that a particular device should be synchronized and unmounted,generally in preparation for a disk change.INITIALIZATIONBefore any other routines in rawFsLib can be used, rawFsInit() must be called to initialize the library. This call specifies themaximum number of raw device file descriptors that can be opensimultaneously and allocates memory for that many raw file descriptors.Any attempt to open more raw device file descriptors than the specifiedmaximum will result in errors from open() or creat().During the rawFsInit() call, the raw device library is installed as a driverin the I/O system driver table. The driver number associated with it isthen placed in a global variable, `rawFsDrvNum'.This initialization is enabled when the configuration macro INCLUDE_RAWFSis defined; rawFsInit() is then called from the root task, usrRoot(), inusrConfig.c.DEFINING A RAW DEVICETo use this library for a particular device, the device structureused by the device driver must contain, as the very first item, ablock device description structure (BLK_DEV). This must be initializedbefore calling rawFsDevInit(). In the BLK_DEV structure, the driver includesthe addresses of five routines it must supply: one that reads oneor more blocks, one that writes one or more blocks, one that performsI/O control (ioctl()) on the device, one that checks the status of thethe device, and one that resets the device. The BLK_DEV structure alsocontains fields that describe the physical configuration of the device. Formore information about defining block devices, see the .I "VxWorks Programmer's Guide: I/O System."The rawFsDevInit() routine is used to associate a device with the rawFsLibfunctions. The <volName> parameter expected by rawFsDevInit() is a pointer toa name string, to be used to identify the device. This will serve asthe pathname for I/O operations which operate on the device. Thisname will appear in the I/O system device table, which may be displayedusing iosDevShow().The <pBlkDev> parameter that rawFsDevInit() expects is a pointerto the BLK_DEV structure describing the device and contains theaddresses of the required driver functions. The syntax of the rawFsDevInit()routine is as follows:.CS rawFsDevInit ( char *volName, /@ name to be used for volume @/ BLK_DEV *pBlkDev /@ pointer to device descriptor @/ ).CEUnlike the VxWorks DOS and RT-11 file systems, raw volumes do notrequire an \%FIODISKINIT ioctl() function to initialize volume structures.(Such an ioctl() call can be made for a raw volume, but it has no effect.)As a result, there is no "make file system" routine for raw volumes(for comparison, see the manual entries for dosFsMkfs() and rt11Mkfs()).When rawFsLib receives a request from the I/O system, after rawFsDevInit()has been called, it calls the device driver routines (whose addresses werepassed in the BLK_DEV structure) to access the device.MULTIPLE LOGICAL DEVICESThe block number passed to the block read and write routines is an absolutenumber, starting from block 0 at the beginning of the device. If desired,the driver may add an offset from the beginning of the physical devicebefore the start of the logical device. This would normally be done bykeeping an offset parameter in the driver's device-specific structure,and adding the proper number of blocks to the block number passed to the readand write routines. See the ramDrv manual entry for an example.UNMOUNTING VOLUMES (CHANGING DISKS)A disk should be unmounted before it is removed. When unmounted,any modified data that has not been written to the disk will be writtenout. A disk may be unmounted by either calling rawFsVolUnmount() directlyor calling ioctl() with a FIODISKCHANGE function code.There may be open file descriptors to a raw device volume when it isunmounted. If this is the case, those file descriptors will be markedas obsolete. Any attempts to use them for further I/O operations willreturn an S_rawFsLib_FD_OBSOLETE error. To free such file descriptors, use theclose() call, as usual. This will successfully free the descriptor,but will still return S_rawFsLib_FD_OBSOLETE.SYNCHRONIZING VOLUMESA disk should be "synchronized" before it is unmounted. To synchronize adisk means to write out all buffered data (the write buffers associatedwith open file descriptors), so that the disk is updated. It mayor may not be necessary to explicitly synchronize a disk, depending onhow (or if) the driver issues the rawFsVolUnmount() call.When rawFsVolUnmount() is called, an attempt will be made to synchronize thedevice before unmounting. However, if the rawFsVolUnmount() call is made bya driver in response to a disk being removed, it is obviously too late tosynchronize. Therefore, a separate ioctl() call specifying the FIOSYNCfunction should be made before the disk is removed. (This could be done inresponse to an operator command.)If the disk will still be present and writable when rawFsVolUnmount() iscalled, it is not necessary to first synchronize the disk. Inall other circumstances, failure to synchronize the volume beforeunmounting may result in lost data.IOCTL FUNCTIONSThe VxWorks raw block device file system supports the following ioctl()functions. The functions listed are defined in the header ioLib.h..iP "FIODISKFORMAT" 16 3Formats the entire disk with appropriate hardware track and sector marks.No file system is initialized on the disk by this request.Note that this is a driver-provided function:.CS fd = open ("DEV1:", O_WRONLY); status = ioctl (fd, FIODISKFORMAT, 0);.CE.iP "FIODISKINIT"Initializes a raw file system on the disk volume.Since there are no file system structures, this functions performs no action.It is provided only for compatibility with other VxWorks file systems..iP "FIODISKCHANGE"Announces a media change. It performs the same function as rawFsReadyChange().This function may be called from interrupt level:.CS status = ioctl (fd, FIODISKCHANGE, 0);.CE.iP "FIOUNMOUNT"Unmounts a disk volume. It performs the same function as rawFsVolUnmount().This function must not be called from interrupt level:.CS status = ioctl (fd, FIOUNMOUNT, 0);.CE.iP "FIOGETNAME"Gets the file name of the file descriptor and copies it to the buffer <nameBuf>:.CS status = ioctl (fd, FIOGETNAME, &nameBuf);.CE.iP "FIOSEEK"Sets the current byte offset on the disk to the position specifiedby <newOffset>:.CS status = ioctl (fd, FIOSEEK, newOffset);.CE.iP "FIOWHERE"Returns the current byte position from the start of the devicefor the specified file descriptor.This is the byte offset of the next byte to be read or written.It takes no additional argument:.CS position = ioctl (fd, FIOWHERE, 0);.CE.iP "FIOFLUSH"Writes all modified file descriptor buffers to the physical device..CS status = ioctl (fd, FIOFLUSH, 0);.CE.iP "FIOSYNC"Performs the same function as FIOFLUSH..iP "FIONREAD"Copies to <unreadCount> the number of bytes from the current file positionto the end of the device:.CS status = ioctl (fd, FIONREAD, &unreadCount);.CE.LPINCLUDE FILES: rawFsLib.hSEE ALSO: ioLib, iosLib, dosFsLib, rt11FsLib, ramDrv,.pG "I/O System, Local File Systems"*//* LINTLIBRARY */#include "vxWorks.h"#include "ctype.h"#include "ioLib.h"#include "lstLib.h"#include "stdlib.h"#include "string.h"#include "semLib.h"#include "errnoLib.h"#include "rawFsLib.h"/* Raw device file descriptor */typedef struct /* RAW_FILE_DESC */ { NODE rawfd_node; /* linked list node info */ SEM_ID rawfd_semId; /* semaphore for this file descriptor */ int rawfd_status; /* (OK | NOT_IN_USE) */ RAW_VOL_DESC *rawfd_vdptr; /* ptr to volume descriptor */ int rawfd_mode; /* mode: O_RDONLY, O_WRONLY, O_RDWR */ UINT rawfd_curptr; /* file byte ptr of I/O buffer byte 0 */ UINT rawfd_newptr; /* file byte ptr for new read/writes */ UINT rawfd_endptr; /* file byte ptr to end of file */ BOOL rawfd_modified; /* TRUE = buffer has been modified */ char *rawfd_buffer; /* pointer to read/write buffer area */ int rawfd_bufBlk; /* number of block in I/O buffer */ } RAW_FILE_DESC;/* File descriptor status values */#define RAWFD_AVAILABLE -1 /* file descriptor available */#define RAWFD_IN_USE 0 /* file descriptor in-use */#define RAWFD_OBSOLETE 1 /* file descriptor obsolete *//* GLOBALS */int rawFsDrvNum = ERROR; /* I/O system driver number for rawFsLib */ /* default mutex options */int rawFsVolMutexOptions = (SEM_Q_PRIORITY | SEM_DELETE_SAFE);int rawFsFdListMutexOptions = (SEM_Q_PRIORITY | SEM_DELETE_SAFE);int rawFsFdMutexOptions = (SEM_Q_PRIORITY | SEM_DELETE_SAFE);/* LOCALS */LOCAL LIST rawFsFdActiveList; /* linked list of in-use Fd's */LOCAL LIST rawFsFdFreeList; /* linked list of avail. Fd's */LOCAL SEM_ID rawFsFdListSemId; /* file descr list semaphore */LOCAL int rawFsMaxFiles; /* max files open at once *//* forward static functions */static int rawFsBlkNew (RAW_FILE_DESC *pRawFd);static STATUS rawFsBlkRd (RAW_VOL_DESC *vdptr, int startBlk, int numBlks, char *pBuf);static STATUS rawFsBlkWrt (RAW_VOL_DESC *vdptr, int startBlk, int numBlks, char *pBuf);static STATUS rawFsClose (RAW_FILE_DESC *pRawFd);static STATUS rawFsFdFlush (RAW_FILE_DESC *pRawFd);static void rawFsFdFree (RAW_FILE_DESC *pRawFd);static RAW_FILE_DESC *rawFsFdGet (void);static STATUS rawFsFlush (RAW_VOL_DESC *vdptr);static STATUS rawFsIoctl (RAW_FILE_DESC *pRawFd, int function, int arg);static RAW_FILE_DESC *rawFsOpen (RAW_VOL_DESC *vdptr, char *name, int flags);static int rawFsRead (RAW_FILE_DESC *pRawFd, char *pBuf, int maxBytes);static STATUS rawFsReset (RAW_VOL_DESC *vdptr);static STATUS rawFsSeek (RAW_FILE_DESC *pRawFd, int position);static STATUS rawFsVolCheck (RAW_VOL_DESC *vdptr);static STATUS rawFsVolFlush (RAW_VOL_DESC *vdptr);static STATUS rawFsVolMount (RAW_VOL_DESC *vdptr);static int rawFsWhere (RAW_FILE_DESC *pRawFd);static int rawFsWrite (RAW_FILE_DESC *pRawFd, char *pBuf, int maxBytes);/********************************************************************************* rawFsBlkNew - make file descriptor buffer contain new block** This routine does whatever is necessary to make the block buffer* of the specified file descriptor contain the byte addressed by* the current pointer in the descriptor. In particular, if on entry* the buffer already contains the desired byte, then no action is taken.* Otherwise if the buffer is modified (contains data written by user* but not yet on disk) then the block is written. Then the correct* block is read if the mode is O_RDONLY or O_RDWR.** RETURNS:* Number of bytes in buffer if successful, or* 0 if end of file, or* ERROR if unable to read/write block.*/LOCAL int rawFsBlkNew ( FAST RAW_FILE_DESC *pRawFd /* file descriptor pointer */ ) { FAST int curBlkNum; /* current block in buffer */ FAST int newBlkNum; /* new block number */ FAST RAW_VOL_DESC *vdptr = pRawFd->rawfd_vdptr; /* pointer to volume descriptor */ FAST BLK_DEV *pBlkDev = pRawFd->rawfd_vdptr->rawvd_pBlkDev; /* pointer to block device info */ /* Calculate num of desired new block and of current block */ newBlkNum = pRawFd->rawfd_newptr / pBlkDev->bd_bytesPerBlk; curBlkNum = pRawFd->rawfd_curptr / pBlkDev->bd_bytesPerBlk; /* Check if new block already in current buffer */ if ((newBlkNum == curBlkNum) && (pRawFd->rawfd_bufBlk != NONE)) return (pBlkDev->bd_bytesPerBlk); /* ready to go as is */ /* Flush current block buffer */ if (rawFsFdFlush (pRawFd) != OK) return (ERROR); /* Check for new position past end of device */ if (newBlkNum >= pBlkDev->bd_nBlocks) { errnoSet (S_rawFsLib_END_OF_DEVICE); return (ERROR); } /* Read in new block, unless opened for write only */ if (pRawFd->rawfd_mode != O_WRONLY) { if (rawFsBlkRd (vdptr, newBlkNum, 1, pRawFd->rawfd_buffer) != OK) return (ERROR); } /* Update file descriptor */ pRawFd->rawfd_curptr = newBlkNum * pBlkDev->bd_bytesPerBlk; /* set pointer to buf start */ pRawFd->rawfd_bufBlk = newBlkNum; return (pBlkDev->bd_bytesPerBlk); /* return size of buffer */ }/********************************************************************************* rawFsBlkRd - read block(s) from a raw volume** This routine reads the specified block from the specified volume.* A limited number of retries is allowed. If the block still cannot* be read, an error is returned.** RETURNS:* OK, or* ERROR, if read error and reset/retry failed.*/LOCAL STATUS rawFsBlkRd ( FAST RAW_VOL_DESC *vdptr, /* pointer to volume descriptor */ int startBlk, /* starting block for read */ int numBlks, /* how many blocks to read */ FAST char *pBuf /* buffer to receive block */ ) { FAST BLK_DEV *pBlkDev = vdptr->rawvd_pBlkDev; /* pointer to block device struct */ vdptr->rawvd_retry = 0; while (((* pBlkDev->bd_blkRd) (pBlkDev, startBlk, numBlks, pBuf)) != OK) { /* read 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); }/********************************************************************************* rawFsBlkWrt - write block(s) to a raw volume** This routine writes the specified blocks to the specified volume.* A limited number of retries is allowed. If the blocks still cannot* be written, an error is returned.** RETURNS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -