rawFsLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:48k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* rawFsLib.c - raw block device file system library */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 03j,30apr02,jkf  SPR#75255, corrected unneeded api change to rawFsDevInit()
  8.                  SPR#72300, 4GB drive failed with rawFsOpen()
  9.                  SPR#25017, corrected FIODISKFORMAT docs to reflect reality.
  10. 03i,09nov01,jkf  SPR#71633, dont set errno when DevCreate is called w/BLK_DEV
  11. 03h,20sep01,jkf  SPR#69031, common code for both AE & 5.x.
  12. 03g,31jul00,jkf  removal of RT-11 (rt11) file system, SPR#32821/31223
  13. 03f,29feb00,jkf  T3 changes, cleanup.
  14. 03e,31aug99,jkf  changes for new CBIO API.
  15. 03d,31jul99,jkf  T2 merge, tidiness & spelling, jdi's 01p SPR#(SPR 25663).
  16. 03c,23jul98,vld  fixed SPR#8309 : rawFsDevInit() calls rawFsInit()
  17.  with default parameters;
  18.  fixed SPR#21875/9418 : don't validate seeked position for
  19.  volume end overgoing.
  20. 03b,23jul98,vld  discontinued actual support for different
  21.  volume states except RAW_VD_MOUNTED and 
  22.  RAW_VD_READY_CHANGED;
  23. 03a,23jul98,vld  driver interface changed to support CBIO_DEV;
  24.  fixed SPR#22606 : CBIO on-byte base access functions
  25.  are used instead of per file descriptor buffers
  26. 02b,23jul98,vld  added support for 64-bit ioctl requests;
  27.                  32-bit restricted old ioctl functions improved to check
  28.              and to return ERROR for 32-bit overloading results;
  29.  added new routine rawFsIsValHuge().
  30. 02a,23jul98,vld  - added support for 64-bit arithmetic to serve huge volumes:
  31.  type of rawFdCurPtr, rawFdNewPtr and rawFdEndPtr
  32.                  fields of RAW_FILE_DESC changed to fsize_t;
  33.            - new type defined for block number (block_t);
  34.                  - "empty buffer" value constant
  35.  defined as BUF_EMPTY (block_t)(-1)
  36. 01p,14mar99,jdi  doc: removed refs to config.h and/or configAll.h (SPR 25663).
  37. 01l,02oct92,srh  added ioctl(FIOGETFL) to return file's open mode
  38. 01k,22jul92,kdl  changed from 4.0.2-style semaphores to mutexes.
  39. 01j,18jul92,smb  Changed errno.h to errnoLib.h.
  40. 01i,04jul92,jcf  scalable/ANSI/cleanup effort.
  41. 01h,26may92,rrr  the tree shuffle
  42. 01g,16dec91,gae  added includes for ANSI.
  43. 01f,19nov91,rrr  shut up some ansi warnings.
  44. 01e,04oct91,rrr  passed through the ansification filter
  45.                   -changed functions to ansi style
  46.   -changed READ, WRITE and UPDATE to O_RDONLY O_WRONLY and ...
  47.   -changed VOID to void
  48.   -changed copyright notice
  49. 01d,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  50.  doc review by kdl.
  51. 01c,21feb91,jaa  documentation cleanup.
  52. 01b,08oct90,kdl  lint.
  53. 01a,02oct90,kdl  written
  54. */
  55. /*
  56. This library provides basic services for disk devices that do not
  57. use a standard file or directory structure.  The disk volume is treated
  58. much like a large file.  Portions of it may be read, written, or the
  59. current position within the disk may be changed.  However, there
  60. is no high-level organization of the disk into files or directories.
  61. USING THIS LIBRARY
  62. The various routines provided by the VxWorks raw "file system" (rawFs) may
  63. be separated into three broad groups: general initialization,
  64. device initialization, and file system operation.
  65. The rawFsInit() routine is the principal initialization function;
  66. it need only be called once, regardless of how many rawFs devices
  67. will be used.
  68. A separate rawFs routine is used for device initialization.  For
  69. each rawFs device, rawFsDevInit() must be called to install the device.
  70. Several routines are provided to inform the file system of
  71. changes in the system environment.  The rawFsModeChange() routine may be
  72. used to modify the readability or writability of a particular device.
  73. The rawFsReadyChange() routine is used to inform the file system that a
  74. disk may have been swapped and that the next disk operation should first
  75. remount the disk.  The rawFsVolUnmount() routine informs the
  76. file system that a particular device should be synchronized and unmounted,
  77. generally in preparation for a disk change.
  78. INITIALIZATION
  79. Before any other routines in rawFsLib can be used, rawFsInit() 
  80. must be called to initialize the library.  This call specifies the
  81. maximum number of raw device file descriptors that can be open
  82. simultaneously and allocates memory for that many raw file descriptors.
  83. Any attempt to open more raw device file descriptors than the specified
  84. maximum will result in errors from open() or creat().
  85. During the rawFsInit() call, the raw device library is installed as a driver
  86. in the I/O system driver table.  The driver number associated with it is
  87. then placed in a global variable, `rawFsDrvNum'.
  88. This initialization is enabled when the configuration macro INCLUDE_RAWFS
  89. is defined; rawFsInit() is then called from the root task, usrRoot(), in
  90. usrConfig.c.
  91. DEFINING A RAW DEVICE
  92. To use this library for a particular device, the device structure
  93. used by the device driver must contain, as the very first item, a CBIO
  94. device description structure (CBIO_DEV) or block device description
  95. structure (BLK_DEV) .  This must be initialized
  96. before calling rawFsDevInit().
  97. The rawFsDevInit() routine is used to associate a device with the rawFsLib
  98. functions.  The <pVolName> parameter expected by rawFsDevInit() is a pointer to
  99. a name string, to be used to identify the device.  This will serve as
  100. the pathname for I/O operations which operate on the device.  This
  101. name will appear in the I/O system device table, which may be displayed
  102. using iosDevShow().
  103. The syntax of the rawFsDevInit()
  104. routine is as follows:
  105. .CS
  106.     rawFsDevInit
  107. (
  108. char     *pVolName, /@ name to be used for volume - iosDevAdd  @/
  109. BLK_DEV  *pDevice   /@ a pointer to BLK_DEV device or a CBIO_DEV_ID @/
  110. )
  111. .CE
  112. Unlike the VxWorks DOS file system, raw volumes do not
  113. require an %FIODISKINIT ioctl() function to initialize volume structures.
  114. (Such an ioctl() call can be made for a raw volume, but it has no effect.)
  115. As a result, there is no "make file system" routine for raw volumes
  116. (for comparison, see the manual entry for rawFsMkfs()).
  117. When rawFsLib receives a request from the I/O system, after rawFsDevInit()
  118. has been called, it calls the appropriate device driver routines
  119. to access the device.
  120. MULTIPLE LOGICAL DEVICES
  121. The block number passed to the block read and write routines is an absolute
  122. number, starting from block 0 at the beginning of the device.  If desired,
  123. the driver may add an offset from the beginning of the physical device
  124. before the start of the logical device.  This would normally be done by
  125. keeping an offset parameter in the driver's device-specific structure,
  126. and adding the proper number of blocks to the block number passed to the read
  127. and write routines.  See the ramDrv manual entry for an example.
  128. UNMOUNTING VOLUMES (CHANGING DISKS)
  129. A disk should be unmounted before it is removed.  When unmounted,
  130. any modified data that has not been written to the disk will be written
  131. out.  A disk may be unmounted by either calling rawFsVolUnmount() directly
  132. or calling ioctl() with a FIODISKCHANGE function code.
  133. There may be open file descriptors to a raw device volume when it is
  134. unmounted.  If this is the case, those file descriptors will be marked
  135. as obsolete.  Any attempts to use them for further I/O operations will
  136. return an S_rawFsLib_FD_OBSOLETE error.  To free such file descriptors, use the
  137. close() call, as usual.  This will successfully free the descriptor,
  138. but will still return S_rawFsLib_FD_OBSOLETE.
  139. SYNCHRONIZING VOLUMES
  140. A disk should be "synchronized" before it is unmounted.  To synchronize a
  141. disk means to write out all buffered data (the write buffers associated
  142. with open file descriptors), so that the disk is updated.  It may
  143. or may not be necessary to explicitly synchronize a disk, depending on
  144. how (or if) the driver issues the rawFsVolUnmount() call.
  145. When rawFsVolUnmount() is called, an attempt will be made to synchronize the
  146. device before unmounting.  However, if the rawFsVolUnmount() call is made by
  147. a driver in response to a disk being removed, it is obviously too late to
  148. synchronize.  Therefore, a separate ioctl() call specifying the FIOSYNC
  149. function should be made before the disk is removed.  (This could be done in
  150. response to an operator command.)
  151. If the disk will still be present and writable when rawFsVolUnmount() is
  152. called, it is not necessary to first synchronize the disk.  In
  153. all other circumstances, failure to synchronize the volume before
  154. unmounting may result in lost data.
  155. IOCTL FUNCTIONS
  156. The VxWorks raw block device file system supports the following ioctl()
  157. functions.  The functions listed are defined in the header ioLib.h.
  158. .iP "FIODISKFORMAT" 16 3
  159. No file system is initialized on the disk by this request.
  160. This ioctl is passed directly down to the driver-provided function:
  161. .CS
  162.     fd = open ("DEV1:", O_WRONLY);
  163.     status = ioctl (fd, FIODISKFORMAT, 0);
  164. .CE
  165. .iP "FIODISKINIT"
  166. Initializes a raw file system on the disk volume.
  167. Since there are no file system structures, this functions performs no action.
  168. It is provided only for compatibility with other VxWorks file systems.
  169. .iP "FIODISKCHANGE"
  170. Announces a media change.  It performs the same function as rawFsReadyChange().
  171. This function may be called from interrupt level:
  172. .CS
  173.     status = ioctl (fd, FIODISKCHANGE, 0);
  174. .CE
  175. .iP "FIOUNMOUNT"
  176. Unmounts a disk volume.  It performs the same function as rawFsVolUnmount().
  177. This function must not be called from interrupt level:
  178. .CS
  179.     status = ioctl (fd, FIOUNMOUNT, 0);
  180. .CE
  181. .iP "FIOGETNAME"
  182. Gets the file name of the file descriptor and copies it to the buffer 
  183. <nameBuf>:
  184. .CS
  185.     status = ioctl (fd, FIOGETNAME, &nameBuf);
  186. .CE
  187. .iP "FIOSEEK"
  188. Sets the current byte offset on the disk to the position specified
  189. by <newOffset>:
  190. .CS
  191.     status = ioctl (fd, FIOSEEK, newOffset);
  192. .CE
  193. .iP "FIOWHERE"
  194. Returns the current byte position from the start of the device
  195. for the specified file descriptor.
  196. This is the byte offset of the next byte to be read or written.
  197. It takes no additional argument:
  198. .CS
  199.     position = ioctl (fd, FIOWHERE, 0);
  200. .CE
  201. .iP "FIOFLUSH"
  202. Writes all modified file descriptor buffers to the physical device.
  203. .CS
  204.     status = ioctl (fd, FIOFLUSH, 0);
  205. .CE
  206. .iP "FIOSYNC"
  207. Performs the same function as FIOFLUSH.
  208. .iP "FIONREAD"
  209. Copies to <unreadCount> the number of bytes from the current file position
  210. to the end of the device:
  211. .CS
  212.     status = ioctl (fd, FIONREAD, &unreadCount);
  213. .CE
  214. .LP
  215. INCLUDE FILES: rawFsLib.h
  216. SEE ALSO: ioLib, iosLib, rawFsLib, ramDrv,
  217. .pG "I/O System, Local File Systems"
  218. */
  219. /* LINTLIBRARY */
  220. #include "vxWorks.h"
  221. #include "private/dosFsVerP.h"
  222. #include "ctype.h"
  223. #include "ioLib.h"
  224. #include "lstLib.h"
  225. #include "stdlib.h"
  226. #include "string.h"
  227. #include "semLib.h"
  228. #include "errnoLib.h"
  229. #include "assert.h"
  230. #include "cbioLib.h"
  231. #include "rawFsLib.h"
  232. #define SIZE64
  233. #ifdef SIZE64
  234. typedef long long       fsize_t;
  235. #define RAWFS_IS_VAL_HUGE( val )  ( ( (fsize_t)(val) >> 32 ) != 0 )
  236. #else
  237. typedef size_t          fsize_t;
  238. #define RAWFS_IS_VAL_HUGE( val )  FALSE
  239. #endif /* SIZE64 */
  240. /* Raw device file descriptor */
  241. typedef struct /* RAW_FILE_DESC */
  242.     {
  243.     NODE rawFdNode; /* linked list node info */
  244.     SEM_ID rawFdSemId; /* semaphore for this file descriptor */
  245.     int rawFdStatus; /* (OK | NOT_IN_USE) */
  246.     RAW_VOL_DESC * pRawFdVd; /* ptr to volume descriptor */
  247.     int rawFdMode; /* mode: O_RDONLY, O_WRONLY, O_RDWR */
  248.     fsize_t rawFdNewPtr; /* file byte ptr for new read/writes */
  249.     fsize_t rawFdEndPtr; /* file byte ptr to end of file */
  250.     cookie_t rawFdCookie; /* CBIO cookie of recently accessed sector */
  251.     } RAW_FILE_DESC;
  252. /* File descriptor status values */
  253. #define RAWFD_AVAILABLE -1 /* file descriptor available */
  254. #define RAWFD_IN_USE 0 /* file descriptor in-use */
  255. #define RAWFD_OBSOLETE 1 /* file descriptor obsolete */
  256. #define BUF_EMPTY (block_t)(-1) /* buffer not initialized */
  257. /* type definitions */
  258. /* GLOBALS */
  259. int  rawFsDrvNum   = ERROR;    /* I/O system driver number for rawFsLib */
  260. /* default mutex options */
  261. int rawFsVolMutexOptions    = (SEM_Q_PRIORITY | SEM_DELETE_SAFE);
  262. int rawFsFdListMutexOptions = (SEM_Q_PRIORITY | SEM_DELETE_SAFE);
  263. int rawFsFdMutexOptions     = (SEM_Q_PRIORITY | SEM_DELETE_SAFE);
  264. /* LOCALS */
  265. LOCAL LIST rawFsFdActiveList; /* linked list of in-use Fd's */
  266. LOCAL LIST rawFsFdFreeList; /* linked list of avail. Fd's */
  267. LOCAL SEM_ID  rawFsFdListSemId; /* file descr list semaphore  */
  268. LOCAL int  rawFsMaxFiles; /* max files open at once     */
  269. /* forward static functions */
  270. static STATUS rawFsBlkRdWr (RAW_VOL_DESC *pVd, block_t startBlk,
  271.       int numBlks, FAST char *pBuf, 
  272.                               CBIO_RW rw);
  273. static STATUS rawFsBtRdWr (RAW_VOL_DESC *pVd, block_t blk,
  274.      off_t offset, char * pBuf, size_t nBytes,
  275.      CBIO_RW rw, cookie_t * pCookie);
  276. static STATUS rawFsClose (RAW_FILE_DESC *pRawFd);
  277. static STATUS rawFsFdFlush (RAW_FILE_DESC *pRawFd);
  278. static void rawFsFdFree (RAW_FILE_DESC *pRawFd);
  279. static RAW_FILE_DESC *rawFsFdGet (void);
  280. static STATUS rawFsFlush (RAW_VOL_DESC *pVd);
  281. static STATUS rawFsIoctl (RAW_FILE_DESC *pRawFd, int function, int arg);
  282. static RAW_FILE_DESC *rawFsOpen (RAW_VOL_DESC *pVd, char *name, int flags);
  283. static int rawFsRead (RAW_FILE_DESC *pRawFd, char *pBuf, int maxBytes);
  284. static STATUS rawFsReset (RAW_VOL_DESC *pVd);
  285. static STATUS rawFsSeek (RAW_FILE_DESC *pRawFd, fsize_t position);
  286. static STATUS rawFsVolCheck (RAW_VOL_DESC *pVd);
  287. static STATUS rawFsVolFlush (RAW_VOL_DESC *pVd);
  288. static STATUS rawFsVolMount (RAW_VOL_DESC *pVd);
  289. static fsize_t rawFsWhere (RAW_FILE_DESC *pRawFd);
  290. static int rawFsWrite (RAW_FILE_DESC *pRawFd, char *pBuf, int maxBytes);
  291. /*******************************************************************************
  292. *
  293. * rawFsIsValHuge -  - check if value is greater, than 4GB (max 32 bit).
  294. *
  295. * * RETURNS: TRUE if is greater, else return FALSE.
  296. */
  297. LOCAL BOOL rawFsIsValHuge
  298.     (
  299.     fsize_t     val
  300.     )
  301.     {
  302.     return RAWFS_IS_VAL_HUGE( val );
  303.     } /* rawFsIsValHuge() */
  304. /*******************************************************************************
  305. *
  306. * rawFsBlkRdWr - read/write block(s) from/to a raw volume
  307. *
  308. * This routine reads/writes the specified block from/to the
  309. * specified volume.
  310. *
  311. * RETURNS:
  312. * OK, or
  313. * ERROR, if read/write error.
  314. */
  315. LOCAL STATUS rawFsBlkRdWr
  316.     (
  317.     FAST RAW_VOL_DESC   *pVd,          /* pointer to volume descriptor */
  318.     block_t             startBlk,       /* starting block for read */
  319.     int                 numBlks,        /* how many blocks to read */
  320.     FAST char           *pBuf,          /* buffer to receive block */
  321.     CBIO_RW rw /* read / write */
  322.     )
  323.     {
  324.     return (cbioBlkRW (pVd->rawVdCbio, startBlk, numBlks, pBuf, rw , NULL));
  325.     }
  326. /*******************************************************************************
  327. *
  328. * rawFsBtRdWr - read/write some bytes from/to block.
  329. *
  330. * This routine reads/writes the specified number of bytes
  331. * from/to specified block starting at specified offset.
  332. *
  333. * RETURNS:
  334. * OK, or
  335. * ERROR, if volume access error.
  336. */
  337. LOCAL STATUS rawFsBtRdWr
  338.     (
  339.     FAST RAW_VOL_DESC   *pVd,         /* pointer to volume descriptor */
  340.     block_t blkNum,       /* block number */
  341.     off_t offset, /* offset in block */
  342.     char *pBuf,          /* data buffer */
  343.     size_t numBytes,        /* how many bytes to process */
  344.     CBIO_RW rw, /* read / write */
  345.     cookie_t         *pCookie
  346.     )
  347.     {
  348.     return ( cbioBytesRW (
  349.      pVd->rawVdCbio, blkNum, offset, pBuf, numBytes, rw, pCookie));
  350.     }
  351. /*******************************************************************************
  352. *
  353. * rawFsClose - close raw volume
  354. *
  355. * This routine closes the specified raw volume file descriptor.  Any
  356. * buffered data for the descriptor is written to the physical device.
  357. *
  358. * If the file descriptor has been marked as obsolete (meaning the
  359. * volume was unmounted while the descriptor was open), the descriptor
  360. * is freed, but an error is returned.
  361. *
  362. * RETURNS: OK, or ERROR.
  363. */
  364. LOCAL STATUS rawFsClose
  365.     (
  366.     FAST RAW_FILE_DESC  *pRawFd         /* file descriptor pointer */
  367.     )
  368.     {
  369.     FAST STATUS       status;
  370.     FAST RAW_VOL_DESC *pVd = pRawFd->pRawFdVd;
  371. /* pointer to volume descriptor */
  372.     /* Take control of file descriptor */
  373.     semTake (pRawFd->rawFdSemId, WAIT_FOREVER); /* get ownership of fd */
  374.     /* If file descriptor is obsolete, free it but return error */
  375.     if (pRawFd->rawFdStatus == RAWFD_OBSOLETE)
  376. {
  377.      rawFsFdFree (pRawFd); /* put fd on free list */
  378. semGive (pRawFd->rawFdSemId); /* release fd */
  379. errnoSet (S_rawFsLib_FD_OBSOLETE);
  380. return (ERROR); /* volume was remounted */
  381. }
  382.     semTake (pVd->rawVdSemId, WAIT_FOREVER); /* get ownership of vol */
  383.     /* Write out file descriptor buffer, if necessary */
  384.     status = rawFsFdFlush (pRawFd);
  385.     semGive (pVd->rawVdSemId); /* release volume */
  386.     rawFsFdFree (pRawFd); /* put fd on free list */
  387.     semGive (pRawFd->rawFdSemId); /* release fd */
  388.     return (status);
  389.     }
  390. /*******************************************************************************
  391. *
  392. * rawFsDevInit - associate a block device with raw volume functions
  393. *
  394. * This routine takes a block device created by a device driver and
  395. * defines it as a raw file system volume.  As a result, when high-level 
  396. * I/O operations, such as open() and write(), are performed on the
  397. * device, the calls will be routed through rawFsLib.
  398. *
  399. * This routine associates <pVolName> with a device and installs it in
  400. * the VxWorks I/O System's device table.  The driver number used when
  401. * the device is added to the table is that which was assigned to the
  402. * raw library during rawFsInit().  (The driver number is kept in
  403. * the global variable `rawFsDrvNum'.)
  404. *
  405. * The pDevice is a CBIO_DEV_ID or BLK_DEV ptr and contains configuration
  406. * data describing the device and the addresses of routines which
  407. * will be called to access device. These routines
  408. * will not be called until they are required by subsequent I/O 
  409. * operations.
  410. *
  411. * INTERNAL
  412. * The semaphore in the device is given, so the device is available for
  413. * use immediately.
  414. *
  415. * RETURNS: A pointer to the volume descriptor (RAW_VOL_DESC),
  416. * or NULL if there is an error.
  417. */
  418. RAW_VOL_DESC *rawFsDevInit
  419.     (
  420.     char      * pVolName,       /* volume name to be used with iosDevAdd */
  421.     BLK_DEV   * pDevice         /* a pointer to a BLK_DEV or a CBIO_DEV_ID */
  422.     )
  423.     {
  424.     FAST RAW_VOL_DESC *pVd; /* pointer to new volume descriptor */
  425.     CBIO_DEV_ID cbio = NULL;
  426.     /* init RAW FS, if not yet */
  427.     
  428.     if (rawFsInit (0) == ERROR)
  429. return (NULL);
  430.     
  431.     if (ERROR == cbioDevVerify( (CBIO_DEV_ID) pDevice ))
  432.         {
  433.         /* attempt to handle BLK_DEV subDev */
  434.         cbio = cbioWrapBlkDev ( pDevice );
  435.         if( NULL != cbio )
  436.             {
  437.             /* SPR#71633, clear the errno set in cbioDevVerify() */
  438.             errno = 0;
  439.             }
  440.         }
  441.     else
  442. {
  443. cbio = (CBIO_DEV_ID) pDevice;
  444. }
  445.     if ( NULL == cbio )
  446. {
  447. return (NULL);
  448. }
  449.     /* Allocate a raw volume descriptor for device */
  450.     pVd = (RAW_VOL_DESC *) KHEAP_ALLOC (sizeof (RAW_VOL_DESC));
  451.     if (NULL == pVd) 
  452. {
  453. return (NULL); /* no memory */
  454. }
  455.     else
  456. {
  457.         bzero ((char *)pVd, sizeof (RAW_VOL_DESC));
  458. }
  459.     /* Add device to system device table */
  460.     if (iosDevAdd ((DEV_HDR *) pVd, pVolName, rawFsDrvNum) != OK)
  461. {
  462. KHEAP_FREE ((char *) pVd);
  463. return (NULL); /* can't add device */
  464. }
  465.     /* Initialize volume descriptor */
  466.     pVd->rawVdCbio  = cbio;
  467.     pVd->rawVdStatus = ERROR; /* have not been mounted yet */
  468.     pVd->rawVdState = RAW_VD_READY_CHANGED;
  469.     /* Create volume locking semaphore (initially available) */
  470.     pVd->rawVdSemId = semMCreate (rawFsVolMutexOptions);
  471.     if (pVd->rawVdSemId == NULL)
  472. {
  473. KHEAP_FREE ((char *) pVd);
  474. return (NULL); /* could not create semaphore */
  475. }
  476.     return (pVd);
  477.     }
  478. /*******************************************************************************
  479. *
  480. * rawFsFdFlush - initiate CBIO buffers flushing.
  481. *
  482. * RETURNS: CBIO ioctl return code.
  483. */
  484. LOCAL STATUS rawFsFdFlush
  485.     (
  486.     FAST RAW_FILE_DESC  *pRawFd         /* pointer to file descriptor */
  487.     )
  488.     {
  489.     /* device flush returns with ERROR, if device is unavailable */
  490.     
  491.     return (cbioIoctl (
  492.      pRawFd->pRawFdVd->rawVdCbio, CBIO_CACHE_FLUSH, 
  493.      (void*)(-1) ));
  494.     }
  495. /*******************************************************************************
  496. *
  497. * rawFsFdFree - free a file descriptor
  498. *
  499. * This routine removes a raw device file descriptor from the active
  500. * Fd list and places it on the free Fd list.
  501. *
  502. */
  503. LOCAL void rawFsFdFree
  504.     (
  505.     FAST RAW_FILE_DESC  *pRawFd      /* pointer to file descriptor to free */
  506.     )
  507.     {
  508.     semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of Fd lists */
  509.     pRawFd->rawFdStatus = RAWFD_AVAILABLE;
  510.     lstDelete (&rawFsFdActiveList, &pRawFd->rawFdNode);
  511. /* remove Fd from active list */
  512.     lstAdd (&rawFsFdFreeList, &pRawFd->rawFdNode);
  513. /* add Fd to free list */
  514.     semGive (rawFsFdListSemId); /* release Fd lists */
  515.     }
  516. /*******************************************************************************
  517. *
  518. * rawFsFdGet - get an available file descriptor
  519. *
  520. * This routine obtains a free raw volume file descriptor.
  521. *
  522. * RETURNS: Pointer to file descriptor, or NULL if none available.
  523. */
  524. LOCAL RAW_FILE_DESC *rawFsFdGet (void)
  525.     {
  526.     FAST RAW_FILE_DESC *pRawFd; /* ptr to newly acquired file descr */
  527.     semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of Fd lists */
  528.     pRawFd = (RAW_FILE_DESC *) lstGet (&rawFsFdFreeList);
  529. /* get a free Fd */
  530.     if (pRawFd != NULL)
  531. {
  532. pRawFd->rawFdStatus = RAWFD_IN_USE; /* mark Fd as in-use */
  533. lstAdd (&rawFsFdActiveList, (NODE *) pRawFd);
  534. /* add to active list */
  535. }
  536.     else
  537.      errnoSet (S_rawFsLib_NO_FREE_FILE_DESCRIPTORS);
  538. /* max files already open */
  539.     semGive (rawFsFdListSemId); /* release Fd lists */
  540.     return (pRawFd);
  541.     }
  542. /*******************************************************************************
  543. *
  544. * rawFsFlush - write all modified volume structures to disk
  545. *
  546. * This routine will write all buffered data for a volume to the physical
  547. * device.  It is called by issuing an ioctl() call with the FIOFLUSH or
  548. * FIOSYNC function codes.  It may be used periodically to provide enhanced
  549. * data integrity, or to prepare a volume for removal from the device.
  550. *
  551. * RETURNS: OK, or ERROR if volume could not be sync'd.
  552. *
  553. */
  554. LOCAL STATUS rawFsFlush
  555.     (
  556.     FAST RAW_VOL_DESC   *pVd          /* pointer to volume descriptor */
  557.     )
  558.     {
  559.     FAST STATUS status; /* return status */
  560.     /* Check that volume is available */
  561.     semTake (pVd->rawVdSemId, WAIT_FOREVER); /* get ownership of volume */
  562.     if (pVd->rawVdState != RAW_VD_MOUNTED)
  563.         {
  564.         semGive (pVd->rawVdSemId); /* release volume */
  565.         return (ERROR); /* cannot access volume */
  566.         }
  567.     /* Flush volume to disk */
  568.     status = rawFsVolFlush (pVd);
  569.     semGive (pVd->rawVdSemId); /* release volume */
  570.     return (status);
  571.     }
  572. /*******************************************************************************
  573. *
  574. * rawFsInit - prepare to use the raw volume library
  575. *
  576. * This routine initializes the raw volume library.  It must be called exactly
  577. * once, before any other routine in the library.  The argument specifies the
  578. * number of file descriptors that may be open at once.  This routine allocates
  579. * and sets up the necessary memory structures and initializes semaphores.
  580. *
  581. * This routine also installs raw volume library routines in the VxWorks I/O
  582. * system driver table.  The driver number assigned to rawFsLib is placed in
  583. * the global variable `rawFsDrvNum'.  This number will later be associated
  584. * with system file descriptors opened to rawFs devices.
  585. *
  586. * To enable this initialization, define INCLUDE_RAWFS in configAll.h;
  587. * rawFsInit() will then be called from the root task, usrRoot(), in usrConfig.c.
  588. *
  589. * RETURNS: OK or ERROR.
  590. */
  591. STATUS rawFsInit
  592.     (
  593.     int  maxFiles  /* max no. of simultaneously open files */
  594.     )
  595.     {
  596.     FAST RAW_FILE_DESC *pRawFd;/* pointer to created file descriptor */
  597.     FAST int ix; /* index var */
  598.     if (rawFsDrvNum != ERROR)
  599.      return (OK); /* initiation already done */
  600.     
  601.     maxFiles = (maxFiles <= 0)? RAWFS_DEF_MAX_FILES : maxFiles;
  602.     
  603.     /* Install rawFsLib routines in I/O system driver table
  604.      *   Note that there is no delete routine, and that the
  605.      *   rawFsOpen routine is also used as the create function.
  606.      */
  607.     rawFsDrvNum = iosDrvInstall ((FUNCPTR) rawFsOpen, (FUNCPTR) NULL,
  608.          (FUNCPTR) rawFsOpen, rawFsClose,
  609.          rawFsRead, rawFsWrite, rawFsIoctl);
  610.     if (rawFsDrvNum == ERROR)
  611. return (ERROR); /* can't install as driver */
  612.     /* Create semaphore for locking access to file descriptor list */
  613.     rawFsFdListSemId = semMCreate (rawFsFdListMutexOptions);
  614.     if (rawFsFdListSemId == NULL)
  615. return (ERROR); /* can't create semaphore */
  616.     semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of fd list */
  617.     /* Allocate memory for required number of file descriptors */
  618.     pRawFd = (RAW_FILE_DESC *) 
  619. KHEAP_ALLOC ((UINT) maxFiles * sizeof (RAW_FILE_DESC));
  620.     if (NULL == pRawFd)
  621. {
  622. return (ERROR); /* no memory */
  623. }
  624.     else
  625. {
  626. bzero ((char *)pRawFd, ((UINT) maxFiles * sizeof (RAW_FILE_DESC)));
  627. }
  628.     /* Create list containing required number of file descriptors */
  629.     rawFsMaxFiles = maxFiles;
  630.     for (ix = 0; ix < rawFsMaxFiles; ix++)
  631. {
  632. pRawFd->rawFdStatus = RAWFD_AVAILABLE;
  633. /* Create semaphore for this fd (initially available) */
  634.      pRawFd->rawFdSemId = semMCreate (rawFsFdMutexOptions);
  635.      if (pRawFd->rawFdSemId == NULL)
  636.     return ((int) NULL); /* could not create semaphore */
  637. /* Add file descriptor to free list */
  638. lstAdd (&rawFsFdFreeList, &pRawFd->rawFdNode);
  639. pRawFd++; /* next Fd */
  640. }
  641.     semGive (rawFsFdListSemId); /* release Fd lists */
  642.     return (OK);
  643.     }
  644. /*******************************************************************************
  645. *
  646. * rawFsIoctl - perform a device-specific control function
  647. *
  648. * This routine performs the following ioctl() functions:
  649. *
  650. * .CS
  651. *    FIODISKINIT:   Initialize the disk volume.  This routine does not
  652. *                   format the disk, that must be done by the driver.
  653. *    FIOSEEK:       Sets the file's current byte position to
  654. *                   the position specified by arg.
  655. *    FIOWHERE:      Returns the current byte position in the file.
  656. *    FIOSYNC:     Write all modified file descriptor buffers to device.
  657. *    FIOFLUSH:      Same as FIOSYNC.
  658. *    FIONREAD:      Return in arg the number of unread bytes.
  659. *    FIODISKCHANGE: Indicate media change.  See rawFsReadyChange().
  660. *    FIOUNMOUNT:    Unmount disk volume.  See rawFsVolUnmount().
  661. *    FIOGETFL:      Return in arg the file's open mode.
  662. * .CE
  663. *
  664. * If the ioctl (<function>) is not one of the above, the device driver
  665. * ioctl() routine is called to perform the function.
  666. *
  667. * If an ioctl() call fails, the task status (see errnoGet()) indicates
  668. * the nature of the error.
  669. *
  670. * RETURNS: OK, or ERROR if function failed or unknown function, or
  671. * current byte pointer for FIOWHERE.
  672. */
  673. LOCAL STATUS rawFsIoctl
  674.     (
  675.     FAST RAW_FILE_DESC  *pRawFd,       /* file descriptor of file to control */
  676.     int                 function,       /* function code */
  677.     int                 arg             /* some argument */
  678.     )
  679.     {
  680.     FAST int retValue = ERROR; /* return value */
  681.     fsize_t buf64 = 0;
  682.     semTake (pRawFd->rawFdSemId, WAIT_FOREVER); /* take control of fd */
  683.     /* Check that file descriptor is current */
  684.     if (pRawFd->rawFdStatus == RAWFD_OBSOLETE)
  685. {
  686. semGive (pRawFd->rawFdSemId); /* release fd */
  687. errnoSet (S_rawFsLib_FD_OBSOLETE);
  688. return (ERROR);
  689. }
  690.     /* Perform requested function */
  691.     switch (function)
  692. {
  693. case FIODISKINIT:
  694.     retValue = OK;
  695.     break;
  696. case FIOSEEK:
  697.             {
  698.             buf64 = (fsize_t)arg;
  699.     retValue = rawFsSeek (pRawFd, buf64);
  700.     break;
  701.          }
  702.      case FIOSEEK64:
  703.             {
  704.             retValue = rawFsSeek (pRawFd, *(fsize_t *)arg);
  705.             break;
  706.             } 
  707.  
  708. case FIOWHERE:
  709.             {
  710.     buf64 = rawFsWhere (pRawFd);
  711.             if( rawFsIsValHuge( buf64 ) )
  712.                 {
  713.                 errnoSet( S_rawFsLib_32BIT_OVERFLOW );
  714.           retValue = ERROR;
  715.                 }
  716.          else
  717.                 retValue = (u_int)buf64;
  718.     break;
  719.             }
  720.         case FIOWHERE64:        /* position within 64 bit boundary */
  721.             {
  722.             retValue = ERROR;
  723.             if( (void *)arg == NULL )
  724.                 {
  725.                 errnoSet( S_rawFsLib_INVALID_PARAMETER );
  726.                 }
  727.             else
  728.                 {
  729.                 *(fsize_t *)arg = rawFsWhere (pRawFd);
  730.                 retValue = OK;
  731.                 }
  732.             break;
  733.             }
  734.  
  735. case FIOFLUSH:
  736. case FIOSYNC:
  737.     retValue = rawFsFlush (pRawFd->pRawFdVd);
  738.     break;
  739. case FIONREAD:
  740.             {
  741.             buf64 = pRawFd->rawFdEndPtr - (rawFsWhere (pRawFd));
  742.          
  743.             retValue = ERROR;
  744.             if( (void *)arg == NULL )
  745.                 {
  746.                 errnoSet( S_rawFsLib_INVALID_PARAMETER );
  747.                 }
  748.             else if( rawFsIsValHuge( buf64 ) )
  749.                 {
  750.                 errnoSet( S_rawFsLib_32BIT_OVERFLOW );
  751.                 *(u_int *)arg = (-1);
  752.                 }
  753.             else
  754.                 {
  755.                 *(u_long *)arg = buf64;
  756.           retValue = OK;
  757.           }
  758.     break;
  759.             }
  760.         case FIONREAD64:
  761.             {
  762.             retValue = ERROR;
  763.             if( (void *)arg == NULL )
  764.                 {
  765.                 errnoSet( S_rawFsLib_INVALID_PARAMETER );
  766.                 }
  767.             else
  768.                 {
  769.                 *(fsize_t *)arg = pRawFd->rawFdEndPtr -
  770.                                   (rawFsWhere (pRawFd));
  771.                 retValue = OK;
  772.                 }
  773.          break;
  774.             }
  775. case FIODISKCHANGE:
  776.     rawFsReadyChange (pRawFd->pRawFdVd);
  777.     retValue = OK;
  778.     break;
  779. case FIOUNMOUNT:
  780.     retValue = rawFsVolUnmount (pRawFd->pRawFdVd);
  781.     break;
  782. case FIOGETFL:
  783.     *((int *) arg) = pRawFd->rawFdMode;
  784.     retValue = OK;
  785.     break;
  786. default:
  787.     /* Call device driver function */
  788.     retValue = (cbioIoctl
  789.        (pRawFd->pRawFdVd->rawVdCbio, function, 
  790.        (void *)arg));
  791. }
  792.     semGive (pRawFd->rawFdSemId); /* release fd */
  793.     return (retValue); /* return obtained result */
  794.     }
  795. /*******************************************************************************
  796. *
  797. * rawFsModeChange - modify the mode of a raw device volume
  798. *
  799. * This routine sets the device's mode to <newMode> by setting
  800. * the mode field in
  801. * the device structure.  This routine should be called whenever the read
  802. * and write capabilities are determined, usually after a ready change.
  803. *
  804. * The driver's device initialization routine should initially set the mode
  805. * to O_RDWR (i.e., both O_RDONLY and O_WRONLY).
  806. *
  807. * RETURNS: N/A
  808. *
  809. * SEE ALSO: rawFsReadyChange()
  810. */
  811. void rawFsModeChange
  812.     (
  813.     RAW_VOL_DESC  *pVd,       /* pointer to volume descriptor */
  814.     int           newMode       /* O_RDONLY/O_WRONLY/O_RDWR (both) */
  815.     )
  816.     {
  817.     cbioModeSet (pVd->rawVdCbio, newMode);
  818.     }
  819. /*******************************************************************************
  820. *
  821. * rawFsOpen - open a raw volume
  822. *
  823. * This routine opens the volume with the specified mode
  824. * (O_RDONLY/O_WRONLY/O_RDWR/CREATE/TRUNC).
  825. *
  826. * The specified <name> must be a null string, indicating that the
  827. * caller specified only the device name during open().
  828. *
  829. * If the device driver supplies a status-check routine, it will be
  830. * called before the volume state is examined.
  831. *
  832. * RETURNS: Pointer to raw volume file descriptor, or ERROR.
  833. */
  834. LOCAL RAW_FILE_DESC *rawFsOpen
  835.     (
  836.     FAST RAW_VOL_DESC   *pVd,         /* pointer to volume descriptor */
  837.     char                *name,          /* "file" name - should be empty str */
  838.     int                 flags           /* open flags */
  839.     )
  840.     {
  841.     FAST RAW_FILE_DESC *pRawFd; /* file descriptor pointer */
  842.     FAST CBIO_DEV_ID rawVdCbio = pVd->rawVdCbio;
  843. /* pointer to block device info */
  844.     CBIO_PARAMS cbioParams;
  845.     /* Get CBIO device parameters */
  846.     if (ERROR == cbioParamsGet (rawVdCbio, &cbioParams))
  847. {
  848. return ((RAW_FILE_DESC *) ERROR);
  849. }
  850.     /* Check for open of other than raw volume (non-null filename) */
  851.     if (name [0] != EOS)
  852. {
  853. errnoSet (S_rawFsLib_ILLEGAL_NAME);
  854. return ((RAW_FILE_DESC *) ERROR); /* cannot specify filename */
  855. }
  856.     /* Clear possible O_CREAT and O_TRUNC flag bits */
  857.     flags &= ~(O_CREAT | O_TRUNC);
  858.     /* Get a free file descriptor */
  859.     if ((pRawFd = rawFsFdGet()) == NULL)
  860. return ((RAW_FILE_DESC *) ERROR); /* max fd's already open */
  861.     semTake (pRawFd->rawFdSemId, WAIT_FOREVER); /* take control of fd */
  862.     /* Get ownership of volume */
  863.     semTake (pVd->rawVdSemId, WAIT_FOREVER); /* take volume */
  864.     /* Check that volume is available */
  865.     if (rawFsVolCheck (pVd) != OK)
  866. {
  867. semGive (pVd->rawVdSemId);
  868. rawFsFdFree (pRawFd);
  869. semGive (pRawFd->rawFdSemId);
  870. errnoSet (S_rawFsLib_VOLUME_NOT_AVAILABLE);
  871. return ((RAW_FILE_DESC *) ERROR); /* cannot access volume */
  872. }
  873.     /* Check for read-only volume opened for write/update */
  874.     if ((cbioModeGet(pVd->rawVdCbio) == O_RDONLY)  &&
  875. (flags == O_WRONLY || flags == O_RDWR))
  876. {
  877. semGive (pVd->rawVdSemId);
  878. rawFsFdFree (pRawFd);
  879. semGive (pRawFd->rawFdSemId);
  880. errnoSet (S_ioLib_WRITE_PROTECTED);
  881. return ((RAW_FILE_DESC *) ERROR); /* volume not writable */
  882. }
  883.     semGive (pVd->rawVdSemId); /* release volume */
  884.     pRawFd->rawFdMode    = flags;
  885.     pRawFd->pRawFdVd    = pVd;
  886.     pRawFd->rawFdNewPtr   = 0;
  887.     pRawFd->rawFdEndPtr   = (fsize_t) ((fsize_t)cbioParams.nBlocks * 
  888.                                        (fsize_t)cbioParams.bytesPerBlk);
  889.     semGive (pRawFd->rawFdSemId); /* release fd */
  890.     return (pRawFd);
  891.     }
  892. /*******************************************************************************
  893. *
  894. * rawFdRdWr - read from/write to a raw volume
  895. *
  896. * See rawFdRead()/rawFdWrite()
  897. *
  898. * RETURNS: Number of bytes actually processed, or 0 if end of file, or ERROR.
  899. */
  900. LOCAL int rawFdRdWr
  901.     (
  902.     FAST RAW_FILE_DESC  *pRawFd, /* file descriptor pointer */
  903.     char                *pBuf, /* addr of data buffer */
  904.     int                 maxBytes,/* maximum bytes to read/write into buffer */
  905.     CBIO_RW rw /* read / write */
  906.     )
  907.     {
  908.     int offset; /* position in file I/O buffer */
  909.     FAST int bytesLeft; 
  910.      /* count of remaining bytes to process */
  911.     FAST int nBytes; /* byte count from individual process */
  912.     FAST block_t blkNum; /* starting block for read */
  913.     FAST int numBlks; /* number of blocks to read */
  914.     FAST RAW_VOL_DESC *pVd = pRawFd->pRawFdVd;
  915. /* ptr to volume descriptor */
  916.     FAST CBIO_DEV_ID rawVdCbio = pRawFd->pRawFdVd->rawVdCbio;
  917. /* ptr to block device info */
  918.     CBIO_PARAMS cbioParams;
  919.     /* Get CBIO device parameters */
  920.     if (ERROR == cbioParamsGet (rawVdCbio, &cbioParams))
  921. {
  922. return (ERROR);
  923. }
  924.     
  925.     assert (rw == CBIO_WRITE || rw == CBIO_READ);
  926.     
  927.     semTake (pRawFd->rawFdSemId, WAIT_FOREVER); /* take control of fd */
  928.     /* Check that file descriptor is current */
  929.     if (pRawFd->rawFdStatus == RAWFD_OBSOLETE)
  930. {
  931. semGive (pRawFd->rawFdSemId);
  932. errnoSet (S_rawFsLib_FD_OBSOLETE);
  933. return (ERROR);
  934. }
  935.     /* Check that device was opened for writing, if write in progress */
  936.     if (rw == CBIO_WRITE && pRawFd->rawFdMode == O_RDONLY)
  937. {
  938. semGive (pRawFd->rawFdSemId);
  939.         errnoSet (S_rawFsLib_READ_ONLY);
  940. return (ERROR);
  941. }
  942.     /* Check for valid maxBytes */
  943.     if (maxBytes <= 0)
  944. {
  945. semGive (pRawFd->rawFdSemId);
  946. errnoSet (S_rawFsLib_INVALID_NUMBER_OF_BYTES);
  947. return (ERROR);
  948. }
  949.     semTake (pVd->rawVdSemId, WAIT_FOREVER); /* take control of volume */
  950.     /* Do successive operation until requested byte count or EOF */
  951.     bytesLeft = maxBytes; /* init number remaining */
  952.     blkNum = pRawFd->rawFdNewPtr / cbioParams.bytesPerBlk;
  953.      /* init current block number */
  954.     for (; bytesLeft > 0 && blkNum < cbioParams.nBlocks;
  955.         bytesLeft -= nBytes, pBuf += nBytes,
  956.            pRawFd->rawFdNewPtr += nBytes,
  957.            blkNum += numBlks)
  958. {
  959. nBytes = 0; /* init individual read count */
  960.      /* Do direct whole-block read if possible */
  961.      if (((ULONG)bytesLeft >= cbioParams.bytesPerBlk) &&
  962.     (pRawFd->rawFdNewPtr %cbioParams.bytesPerBlk == 0))
  963.     {
  964.     /* Calculate number of blocks to access */
  965.     numBlks = bytesLeft / cbioParams.bytesPerBlk;
  966.          nBytes = numBlks * cbioParams.bytesPerBlk;
  967.     /* Adjust if read would extend past end of device */
  968.     numBlks = min ((ULONG)numBlks, (cbioParams.nBlocks - blkNum));
  969.     /* execute operation on blocks */
  970.     if (rawFsBlkRdWr (pVd, blkNum, numBlks, pBuf, rw) != OK)
  971.      { /* read error */
  972. if (bytesLeft == maxBytes) /* if nothing read yet */
  973.     {
  974.          semGive (pVd->rawVdSemId);
  975.          semGive (pRawFd->rawFdSemId);
  976.     return (ERROR); /*  indicate error */
  977.     }
  978. else
  979.          break; /* return number read OK */
  980.      }
  981.     
  982.     pRawFd->rawFdCookie = (cookie_t) NULL; /* invalidate cookie */
  983.     continue; /* goto partial blocks access */
  984.     }
  985.      else /* if not whole-block transfer*/
  986.     {
  987.          /* partial blocks access */
  988.          
  989.          numBlks = 1;
  990.          offset = pRawFd->rawFdNewPtr % cbioParams.bytesPerBlk;
  991.          nBytes = min ((ULONG)bytesLeft,
  992.             cbioParams.bytesPerBlk - offset);
  993.          if ( rawFsBtRdWr (pVd, blkNum, offset, pBuf, nBytes,
  994.                 rw, & pRawFd->rawFdCookie) != OK)
  995. { /* probably nothing done */
  996. if (bytesLeft == maxBytes)
  997.     { /* if nothing read yet */
  998.          semGive (pVd->rawVdSemId);
  999.          semGive (pRawFd->rawFdSemId);
  1000.     return (ERROR);
  1001.     }
  1002. else
  1003.          break; /* return number read OK */
  1004. }
  1005.     }
  1006. }  /* end for */
  1007.     semGive (pVd->rawVdSemId); /* release volume */
  1008.     semGive (pRawFd->rawFdSemId); /* release fd */
  1009.     return (maxBytes - bytesLeft); /* number of bytes processed */
  1010.     }
  1011. /*******************************************************************************
  1012. *
  1013. * rawFsReadyChange - notify rawFsLib of a change in ready status
  1014. *
  1015. * This routine sets the volume descriptor state to RAW_VD_READY_CHANGED.
  1016. * It should be called whenever a driver senses that a device has come on-line
  1017. * or gone off-line, (e.g., a disk has been inserted or removed).
  1018. *
  1019. * After this routine has been called, the next attempt to use the volume
  1020. * will result in an attempted remount.
  1021. *
  1022. * RETURNS: N/A
  1023. */
  1024. void rawFsReadyChange
  1025.     (
  1026.     RAW_VOL_DESC *pVd         /* pointer to volume descriptor */
  1027.     )
  1028.     {
  1029.     pVd->rawVdState = RAW_VD_READY_CHANGED;
  1030.     }
  1031. /*******************************************************************************
  1032. *
  1033. * rawFsReset - reset a volume
  1034. *
  1035. * This routine calls the specified volume's reset routine, if any.
  1036. * If the reset fails, rawVdState is set to (RAW_VD_CANT_RESET)
  1037. * to indicate that disk won't reset.
  1038. *
  1039. * RETURNS: OK, or ERROR if driver returned error.
  1040. */
  1041. LOCAL STATUS rawFsReset
  1042.     (
  1043.     FAST RAW_VOL_DESC   *pVd          /* pointer to volume descriptor */
  1044.     )
  1045.     {
  1046.     if ( cbioIoctl (pVd->rawVdCbio, CBIO_RESET, NULL) != OK)
  1047. {
  1048. pVd->rawVdState = RAW_VD_CANT_RESET;
  1049. return (ERROR);
  1050. }
  1051.     
  1052.     pVd->rawVdState = RAW_VD_RESET;
  1053.     return (OK);
  1054.     }
  1055. /*******************************************************************************
  1056. *
  1057. * rawFsSeek - change file descriptor's current character position
  1058. *
  1059. * This routine sets the specified file descriptor's current character
  1060. * position to the specified position.  This only changes the pointer, it
  1061. * doesn't affect the hardware at all.
  1062. *
  1063. * Attempts to set the character pointer to a negative offset (i.e. before
  1064. * the start of the disk) or to a point beyond the end of the device
  1065. * will return ERROR.
  1066. *
  1067. * RETURNS: OK, or ERROR if invalid character offset.
  1068. */
  1069. LOCAL STATUS rawFsSeek
  1070.     (
  1071.     FAST RAW_FILE_DESC  *pRawFd,        /* file descriptor pointer */
  1072.     fsize_t             position      /* desired character position in file */
  1073.     )
  1074.     {
  1075.     /*
  1076.      * Check for valid new offset. Accept any positive offset.
  1077.      * volume end overgoing is checked within read/write
  1078.      */
  1079.     if (position < 0)
  1080. {
  1081. errnoSet (S_rawFsLib_BAD_SEEK);
  1082. return (ERROR);
  1083. }
  1084.     /* Update new file byte pointer */
  1085.     pRawFd->rawFdNewPtr = position;
  1086.     return (OK);
  1087.     }
  1088. /*******************************************************************************
  1089. *
  1090. * rawFsVolCheck - verify that volume descriptor is current
  1091. *
  1092. * This routine is called at the beginning of most operations on
  1093. * the device.  The status field in the volume descriptor is examined,
  1094. * and the appropriate action is taken.  In particular, the disk is
  1095. * mounted if it is currently unmounted or a ready-change has occurred.
  1096. *
  1097. * If the disk is already mounted or is successfully mounted as a
  1098. * result of this routine calling rawFsVolMount, this routine returns
  1099. * OK.  If the disk cannot be mounted, ERROR is returned.
  1100. *
  1101. * RETURNS: OK, or ERROR.
  1102. */
  1103. LOCAL STATUS rawFsVolCheck
  1104.     (
  1105.     FAST RAW_VOL_DESC   *pVd          /* pointer to volume descriptor   */
  1106.     )
  1107.     {
  1108.     FAST int status; /* return status value */
  1109.     status = OK; /* init return value */
  1110.     /* Check if device driver announced ready-change */
  1111.     if ( cbioIoctl (
  1112.      pVd->rawVdCbio, CBIO_STATUS_CHK, NULL) != OK ||
  1113.      TRUE == cbioRdyChgdGet (pVd->rawVdCbio))
  1114. {
  1115. pVd->rawVdState = RAW_VD_READY_CHANGED;
  1116. }
  1117.     /* Check volume status */
  1118.     switch (pVd->rawVdState)
  1119. {
  1120. case RAW_VD_MOUNTED:
  1121.     break; /* ready to go as is */
  1122. case RAW_VD_CANT_RESET:
  1123.     /* This state means we tried to reset and failed.
  1124.      * try again
  1125.      */
  1126. case RAW_VD_CANT_MOUNT:
  1127.     /* This state means we tried to mount and failed.
  1128.      * try again
  1129.      */
  1130. case RAW_VD_RESET:
  1131.     /* Volume reset but not mounted; mount */
  1132. case RAW_VD_READY_CHANGED:
  1133.     /* Ready change occurred; remount volume */
  1134.     if (rawFsVolMount (pVd) != OK)
  1135. {
  1136. pVd->rawVdState = RAW_VD_CANT_MOUNT; /* can't mount */
  1137. status = ERROR;   /* don't try again */
  1138. break;
  1139. }
  1140.     pVd->rawVdState = RAW_VD_MOUNTED; /* note vol mounted */
  1141.     break;
  1142. }
  1143.     return (status); /* return status value */
  1144.     }
  1145. /*******************************************************************************
  1146. *
  1147. * rawFsVolFlush - flush raw volume to disk
  1148. *
  1149. * This routine guarantees that any changes to the volume are actually
  1150. * written to disk.  Since there are no data structures kept on disk,
  1151. * the only possible changes are the file descriptor read/write buffers.
  1152. *
  1153. * INTERNAL
  1154. * Possession of the volume descriptor's semaphore must have been secured
  1155. * before this routine is called.
  1156. *
  1157. * RETURNS: OK, or ERROR.
  1158. */
  1159. LOCAL STATUS rawFsVolFlush
  1160.     (
  1161.     FAST RAW_VOL_DESC   *pVd          /* pointer to volume descriptor */
  1162.     )
  1163.     {
  1164.     FAST RAW_FILE_DESC *pRawFd; /* pointer to file descriptor */
  1165.     if (pVd->rawVdState != RAW_VD_MOUNTED)
  1166.      {
  1167.      return (ERROR);
  1168.      }
  1169.     
  1170.     /* Flush all modified file descriptor I/O buffers to disk */
  1171.     semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of Fd lists */
  1172.     pRawFd = (RAW_FILE_DESC *) lstFirst (&rawFsFdActiveList);
  1173. /* get first in-use Fd */
  1174.     while (pRawFd != NULL)
  1175. {
  1176. if (pRawFd->pRawFdVd == pVd) /* if correct volume */
  1177.     {
  1178.     if (rawFsFdFlush (pRawFd) != OK) /* write Fd buffer to disk */
  1179.      return (ERROR); /* error flushing buffer */
  1180.     }
  1181. pRawFd = (RAW_FILE_DESC *) lstNext (&pRawFd->rawFdNode);
  1182. /* get next in-use Fd */
  1183. }
  1184.     semGive (rawFsFdListSemId); /* release Fd lists */
  1185.     return (OK);
  1186.     }
  1187. /*******************************************************************************
  1188. *
  1189. * rawFsVolMount - prepare to use raw volume
  1190. *
  1191. * This routine prepares the library to use the raw volume on the device
  1192. * specified.
  1193. *
  1194. * This routine should be called every time a disk is changed (i.e. a floppy
  1195. * is swapped, or whatever), or before every open and create, if the driver
  1196. * can't tell when disks are changed.
  1197. *
  1198. * RETURNS: OK or ERROR.
  1199. */
  1200. LOCAL STATUS rawFsVolMount
  1201.     (
  1202.     FAST RAW_VOL_DESC   *pVd /* pointer to volume descriptor */
  1203.     )
  1204.     {
  1205.     semTake (pVd->rawVdSemId, WAIT_FOREVER); /* get ownership of volume */
  1206.     
  1207.     /* unmount volume prior mounting */
  1208.     
  1209.     if (pVd->rawVdStatus == OK)
  1210.      {
  1211.      rawFsVolUnmount (pVd);
  1212.      }
  1213.     
  1214.     /* update new volume parameters */
  1215.     
  1216.     if (rawFsReset (pVd) == OK)
  1217.      {
  1218.      pVd->rawVdStatus = OK;
  1219.      pVd->rawVdState = RAW_VD_MOUNTED;
  1220.      }
  1221.     
  1222.     semGive (pVd->rawVdSemId); /* release volume */
  1223.     
  1224.     return (pVd->rawVdStatus);
  1225.     }
  1226. /*******************************************************************************
  1227. *
  1228. * rawFsVolUnmount - disable a raw device volume
  1229. *
  1230. * This routine is called when I/O operations on a volume are to be
  1231. * discontinued.  This is commonly done before changing removable disks.
  1232. * All buffered data for the volume is written to the device (if possible),
  1233. * any open file descriptors are marked as obsolete, and the volume is
  1234. * marked as not mounted.
  1235. *
  1236. * Because this routine will flush data from memory to the physical
  1237. * device, it should not be used in situations where the disk-change is
  1238. * not recognized until after a new disk has been inserted.  In these
  1239. * circumstances, use the ready-change mechanism.  (See the manual entry for 
  1240. * rawFsReadyChange().)
  1241. *
  1242. * This routine may also be called by issuing an ioctl() call using the
  1243. * %FIOUNMOUNT function code.
  1244. *
  1245. * RETURNS: OK, or ERROR if the routine cannot access the volume.
  1246. *
  1247. * SEE ALSO: rawFsReadyChange()
  1248. */
  1249. STATUS rawFsVolUnmount
  1250.     (
  1251.     FAST RAW_VOL_DESC   *pVd          /* pointer to volume descriptor */
  1252.     )
  1253.     {
  1254.     FAST RAW_FILE_DESC *pRawFd; /* pointer to file descriptor */
  1255.     /* Check that volume is available */
  1256.     semTake (pVd->rawVdSemId, WAIT_FOREVER); /* get ownership of volume */
  1257.     
  1258.     /* nothing to be done, if volume was not mounted since last unmount */
  1259.     
  1260.     if (pVd->rawVdStatus != OK)
  1261.         {
  1262.         semGive (pVd->rawVdSemId); /* release volume */
  1263.         return (OK); /* cannot access volume */
  1264.         }
  1265.     /* do not check device state before flush, let flush just fail */
  1266.     
  1267.     /* Flush volume structures, if possible */
  1268.     (void) rawFsVolFlush (pVd); /* flush volume */
  1269.     /* Mark any open file descriptors as obsolete */
  1270.     semTake (rawFsFdListSemId, WAIT_FOREVER); /* take control of Fd lists */
  1271.     pRawFd = (RAW_FILE_DESC *) lstFirst (&rawFsFdActiveList);
  1272. /* get first in-use Fd */
  1273.     while (pRawFd != NULL)
  1274. {
  1275. if (pRawFd->pRawFdVd == pVd)
  1276.     {
  1277.     pRawFd->rawFdStatus = RAWFD_OBSOLETE;
  1278.     }
  1279. pRawFd = (RAW_FILE_DESC *) lstNext (&pRawFd->rawFdNode);
  1280. /* get next in-use Fd */
  1281. }
  1282.     semGive (rawFsFdListSemId); /* release Fd lists */
  1283.     /* Mark volume as no longer mounted */
  1284.     rawFsReadyChange (pVd);
  1285.     pVd->rawVdStatus = ERROR;
  1286.     semGive (pVd->rawVdSemId); /* release volume */
  1287.     return (OK);
  1288.     }
  1289. /*******************************************************************************
  1290. *
  1291. * rawFsWhere - return current character position on raw device
  1292. *
  1293. * This routine tells you where the character pointer is for a raw device.
  1294. * This character position applies only to the specified file descriptor;
  1295. * other file descriptor to the save raw device may have different character
  1296. * pointer values.
  1297. *
  1298. * RETURNS: Current character position of file descriptor.
  1299. */
  1300. LOCAL fsize_t rawFsWhere
  1301.     (
  1302.     FAST RAW_FILE_DESC *pRawFd  /* file descriptor pointer */
  1303.     )
  1304.     {
  1305.     return (pRawFd->rawFdNewPtr);
  1306.     }
  1307. /*******************************************************************************
  1308. *
  1309. * rawFsRead - read from a raw volume
  1310. *
  1311. * This routine reads from the volume specified by the file descriptor
  1312. * (returned by rawFsOpen()) into the specified buffer.
  1313. * <maxbytes> bytes will be read, if there is that much data in the file.
  1314. *
  1315. * RETURNS: Number of bytes actually read, or 0 if end of file, or ERROR.
  1316. */
  1317. LOCAL int rawFsRead
  1318.     (
  1319.     FAST RAW_FILE_DESC  *pRawFd, /* file descriptor pointer */
  1320.     char                *pBuf, /* addr of input buffer */
  1321.     int                 maxBytes /* maximum bytes to read into buffer */
  1322.     )
  1323.     {
  1324.     return rawFdRdWr (pRawFd, pBuf, maxBytes, CBIO_READ);
  1325.     }
  1326.     
  1327. /*******************************************************************************
  1328. *
  1329. * rawFsWrite - write to a raw volume
  1330. *
  1331. * This routine writes to the raw volume specified by the file descriptor
  1332. * from the specified buffer.  If the block containing the disk locations
  1333. * to be written is already in the file descriptor's read/write buffer,
  1334. * the buffer won't be flushed.  If another in-memory block is needed,
  1335. * any block already in memory will be flushed.
  1336. *
  1337. * This routine calls the device driver block-writing routine directly
  1338. * to write (possibly multiple) whole blocks.
  1339. *
  1340. * RETURNS: Number of bytes written (error if != maxBytes), or
  1341. * ERROR if maxBytes < 0, or no more space for the file,
  1342. * or can't write block.
  1343. */
  1344. LOCAL int rawFsWrite
  1345.     (
  1346.     FAST RAW_FILE_DESC  *pRawFd,        /* file descriptor pointer */
  1347.     char                *pBuf,          /* data to be written */
  1348.     int                 maxBytes        /* number of bytes to write */
  1349.     )
  1350.     {
  1351.     return rawFdRdWr (pRawFd, pBuf, maxBytes, CBIO_WRITE);
  1352.     }