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

VxWorks

开发平台:

C/C++

  1. /* unixDrv.c - UNIX-file disk driver (VxSim for Solaris and VxSim for HP) */
  2. /* Copyright 1984-1999 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /* 
  5. modification history
  6. --------------------
  7. 01j,16mar99,elg  mention unixDrv is for Solaris and HP simulators (SPR 7719).
  8. 01i,11jul97,dgp  doc: ad (VxSim) to title line
  9. 01h,09jan97,pr    added ARCHCVTFLAGS for simsolaris
  10. 01g,30oct95,ism   added support for simsolaris
  11. 01f,31oct94,kdl   made conditional for simulator only.
  12. 01e,18aug93,gae   modified unix_stat for hp.
  13. 01d,30jul93,gae   doc touchup.
  14. 01c,23jan93,gae   ANSIfied.
  15. 01b,20jul92,gae   minor revision.
  16. 01a,01apr91,smeg  derived from ramDrv.
  17. */
  18. /*
  19. DESCRIPTION
  20. This driver emulates a VxWorks disk driver, but actually uses the UNIX
  21. file system to store the data.  The VxWorks disk appears under
  22. UNIX as a single file.
  23. The UNIX file name, and the size of the disk, may be specified during the 
  24. unixDiskDevCreate() call.
  25. USER-CALLABLE ROUTINES
  26. Most of the routines in this driver are accessible only through the I/O
  27. system. The routine unixDrv() must be called to initialize the driver and
  28. the unixDiskDevCreate() routine is used to create devices.
  29. CREATING UNIX DISKS
  30. Before a UNIX disk can be used, it must be created.  This is done
  31. with the unixDiskDevCreate() call.  The format of this call is:
  32. .CS
  33.     BLK_DEV *unixDiskDevCreate
  34. (
  35. char *unixFile, /@ name of the UNIX file to use @/
  36. int bytesPerBlk, /@ number of bytes per block @/
  37. int blksPerTrack, /@ number of blocks per track @/
  38. int nBlocks /@ number of blocks on this device @/
  39. )
  40. .CE
  41. The UNIX file must be pre-allocated separately.  This
  42. can be done using the UNIX mkfile(8) command.  Note that you have to
  43. create an appropriately sized file.  For example, to create a UNIX
  44. file system that is used as a common floppy dosFs file system, you
  45. would issue the comand:
  46. .CS
  47.     mkfile 1440k /tmp/floppy.dos
  48. .CE
  49. This will create space for a 1.44 Meg DOS floppy (1474560 bytes,
  50. or 2880 512-byte blocks).
  51. The <bytesPerBlk> parameter specifies the size of each logical block
  52. on the disk.  If <bytesPerBlk> is zero, 512 is the default.
  53. The <blksPerTrack> parameter specifies the number of blocks on each
  54. logical track of the UNIX disk.  If <blksPerTrack> is zero, the count of
  55. blocks per track will be set to <nBlocks> (i.e., the disk will be defined 
  56. as having only one track).  UNIX disk devices typically are specified
  57. with only one track.
  58. The <nBlocks> parameter specifies the size of the disk, in blocks.
  59. If <nBlocks> is zero the size of the UNIX file specified, divided by
  60. the number of bytes per block, is used.
  61. The formatting parameters (<bytesPerBlk>, <blksPerTrack>, and <nBlocks>)
  62. are critical only if the UNIX disk already contains the contents
  63. of a disk created elsewhere.  In that case, the formatting 
  64. parameters must be identical to those used when the image was created.  
  65. Otherwise, they may be any convenient number.
  66. Once the device has been created it still does not have a name or
  67. file system associated with it.  This must be done by using the file 
  68. system's device initialization routine (e.g., dosFsDevInit()).  The
  69. dosFs and rt11Fs file systems also provide make-file-system routines
  70. (dosFsMkfs() and rt11FsMkfs()), which may be used to associate a name
  71. and file system with the block device and initialize that file system
  72. on the device using default configuration parameters.
  73. The unixDiskDevCreate() call returns a pointer to a block device
  74. structure (BLK_DEV).  
  75. This structure contains fields that describe the physical properties of a 
  76. disk device and specify the addresses of routines within the UNIX disk driver.
  77. The BLK_DEV structure address must be passed to the desired file system 
  78. (dosFs, rt11Fs, or rawFs) during the file system's device 
  79. initialization or make-file-system routine.  Only then is a name and file 
  80. system associated with the device, making it available for use.
  81. As an example, to create a 200KB disk, 512-byte blocks, and only one track,
  82. the proper call would be:
  83. .CS
  84.     BLK_DEV *pBlkDev;
  85.     pBlkDev = unixDiskDevCreate ("/tmp/filesys1",  512,  400,  400,  0);
  86. .CE
  87. This will attach the UNIX file /tmp/filesys1 as a block device.
  88. A convenience routine, unixDiskInit(), is provided to do the
  89. unixDiskDevCreate() followed by either a dosFsMkFs() or dosFsDevInit(),
  90. whichever is appropriate.  
  91. The format of this call is:
  92. .CS
  93.     BLK_DEV *unixDiskInit
  94. (
  95. char * unixFile,  /@ name of the UNIX file to use @/
  96. char * volName,   /@ name of the dosFs volume to use @/
  97. int    nBytes     /@ number of bytes in dosFs volume @/
  98. )
  99. .CE
  100. This call will create the UNIX disk if required.
  101. IOCTL
  102. Only the FIODISKFORMAT request is supported; all other ioctl requests
  103. return an error, and set the task's errno to S_ioLib_UNKNOWN_REQUEST.
  104. SEE ALSO:
  105. dosFsDevInit(), dosFsMkfs(), rt11FsDevInit(), rt11FsMkfs(), rawFsDevInit(),
  106. .pG "I/O System, Local File Systems"
  107. LINTLIBRARY
  108. */
  109. #include "vxWorks.h"
  110. #include "blkIo.h"
  111. #include "ioLib.h"
  112. #include "iosLib.h"
  113. #include "memLib.h"
  114. #include "errno.h"
  115. /* #include "stdio.h" */
  116. #include "dosFsLib.h"
  117. #include "stdlib.h"
  118. /* USED ONLY WITH SIMULATOR */
  119. #if (CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS)
  120. #include "simLib.h"
  121. #include "u_Lib.h"
  122. extern int printErr ();
  123. int unixRWFlag = O_RDWR;
  124. int unixRWMode = 0;
  125. int unixCRFlag = O_RDWR | O_CREAT; /* 514 */
  126. int unixCRMode = 0644;
  127. #define DEFAULT_SEC_SIZE   512
  128. #define DEFAULT_DISK_SIZE  (1024*1024)
  129. typedef struct /* UNIXDISK_DEV - UNIX disk device descriptor */
  130.     {
  131.     BLK_DEV unixDiskBlkDev; /* generic block device structure */
  132.     int unixFd;  /* UNIX file descriptor */
  133.     } UNIXDISK_DEV;
  134. /* forward declarations */
  135. LOCAL STATUS unixDiskIoctl ();
  136. LOCAL STATUS unixDiskBlkRd ();
  137. LOCAL STATUS unixDiskBlkWrt ();
  138. /*******************************************************************************
  139. *
  140. * unixDrv - install UNIX disk driver
  141. *
  142. * Used in usrConfig.c to cause the UNIX disk driver to be linked in
  143. * when building VxWorks.  Otherwise, it is not necessary to call this
  144. * routine before using the UNIX disk driver.
  145. *
  146. * This routine is only applicable to VxSim for Solaris and VxSim for HP.
  147. *
  148. * RETURNS: OK (always).
  149. */
  150. STATUS unixDrv (void)
  151.     {
  152.     return (OK);
  153.     }
  154. /*******************************************************************************
  155. *
  156. * unixDiskDevCreate - create a UNIX disk device
  157. *
  158. * This routine creates a UNIX disk device.
  159. *
  160. * The <unixFile> parameter specifies the name of the UNIX file to use
  161. * for the disk device.
  162. * The <bytesPerBlk> parameter specifies the size of each logical block
  163. * on the disk.  If <bytesPerBlk> is zero, 512 is the default.
  164. * The <blksPerTrack> parameter specifies the number of blocks on each
  165. * logical track of the disk.  If <blksPerTrack> is zero, the count of
  166. * blocks per track is set to <nBlocks> (i.e., the disk is defined 
  167. * as having only one track).
  168. * The <nBlocks> parameter specifies the size of the disk, in blocks.
  169. * If <nBlocks> is zero, a default size is used.  The default is calculated
  170. * as the size of the UNIX disk divided by the number of bytes per block.
  171. * This routine is only applicable to VxSim for Solaris and VxSim for HP.
  172. *
  173. * RETURNS: A pointer to block device (BLK_DEV) structure,
  174. * or NULL, if unable to open the UNIX disk.
  175. */
  176. BLK_DEV *unixDiskDevCreate
  177.     (
  178.     char *unixFile, /* name of the UNIX file */
  179.     int bytesPerBlk, /* number of bytes per block */
  180.     int blksPerTrack, /* number of blocks per track */
  181.     int nBlocks /* number of blocks on this device */
  182.     )
  183.     {
  184.     FAST UNIXDISK_DEV *pUnixDiskDev; /* ptr to created UNIXDISK_DEV struct */
  185.     FAST BLK_DEV *pBlkDev;    /* ptr to BLK_DEV struct in UNIXDISK_DEV */
  186.     int fd;
  187.     /* Set up defaults for any values not specified */
  188.     if (bytesPerBlk == 0)
  189. bytesPerBlk = DEFAULT_SEC_SIZE;
  190.     if ((fd = u_open (unixFile, ARCHCVTFLAGS(unixRWFlag), unixRWMode)) < 0)
  191. {
  192. printErr ("unixDiskDevCreate: Could not open %s read/writen", unixFile);
  193. return (NULL);
  194. }
  195.     if (nBlocks == 0)
  196. {
  197. struct unix_stat buf;
  198. if (u_fstat (fd, (char*)&buf) < 0)
  199.     {
  200.     printErr ("unixDiskDevCreate: Could not stat %sn", unixFile);
  201.     u_close (fd);
  202.     return (NULL);
  203.     }
  204. nBlocks = (int) buf.st_size / bytesPerBlk;
  205. }
  206.     if (blksPerTrack == 0)
  207. blksPerTrack = nBlocks;
  208.     /* Allocate a UNIXDISK_DEV structure for device */
  209.     pUnixDiskDev = (UNIXDISK_DEV *) calloc (1, sizeof (UNIXDISK_DEV));
  210.     if (pUnixDiskDev == NULL)
  211. {
  212. u_close (fd);
  213. return (NULL); /* no memory */
  214. }
  215.     /* Initialize BLK_DEV structure (in UNIXDISK_DEV) */
  216.     pBlkDev = &pUnixDiskDev->unixDiskBlkDev;
  217.     pBlkDev->bd_nBlocks      = nBlocks; /* number of blocks */
  218.     pBlkDev->bd_bytesPerBlk  = bytesPerBlk; /* bytes per block */
  219.     pBlkDev->bd_blksPerTrack = blksPerTrack; /* blocks per track */
  220.     pBlkDev->bd_nHeads       = 1; /* one "head" */
  221.     pBlkDev->bd_removable    = FALSE; /* not removable */
  222.     pBlkDev->bd_retry      = 1; /* retry count */
  223.     pBlkDev->bd_mode      = UPDATE; /* initial mode for device */
  224.     pBlkDev->bd_readyChanged = TRUE; /* new ready status */
  225.     pBlkDev->bd_blkRd      = unixDiskBlkRd; /* read block function */
  226.     pBlkDev->bd_blkWrt      = unixDiskBlkWrt; /* write block function */
  227.     pBlkDev->bd_ioctl      = unixDiskIoctl; /* ioctl function */
  228.     pBlkDev->bd_reset      = NULL; /* no reset function */
  229.     pBlkDev->bd_statusChk    = NULL; /* no check-status function */
  230.     /* Initialize remainder of device struct */
  231.     pUnixDiskDev->unixFd = fd;
  232.     return (&pUnixDiskDev->unixDiskBlkDev);
  233.     }
  234. /*******************************************************************************
  235. *
  236. * unixDiskIoctl - do device specific control function
  237. *
  238. * This routine is called when the file system cannot handle an ioctl
  239. * function.
  240. *
  241. * The FIODISKFORMAT function always returns OK, since a UNIX file does
  242. * not require formatting.  All other requests return ERROR.
  243. *
  244. * RETURNS:  OK or ERROR.
  245. */
  246. LOCAL STATUS unixDiskIoctl
  247.     (
  248.     UNIXDISK_DEV *pUnixDiskDev, /* device structure pointer */
  249.     int function, /* function code */
  250.     int arg /* some argument */
  251.     )
  252.     {
  253.     FAST int status; /* returned status value */
  254.     switch (function)
  255. {
  256. case FIODISKFORMAT:
  257.     status = OK;
  258.     break;
  259. default:
  260.     status = ERROR;
  261.     errno = S_ioLib_UNKNOWN_REQUEST;
  262.     break;
  263. }
  264.     return (status);
  265.     }
  266. /*******************************************************************************
  267. *
  268. * unixDiskBlkRd - read one or more blocks from a unix file disk volume
  269. *
  270. * This routine reads one or more blocks from the specified volume,
  271. * starting with the specified block number.  The byte offset is
  272. * calculated and the UNIX disk data is copied to the specified buffer.
  273. *
  274. * RETURNS: OK for success and ERROR for bad block.
  275. */
  276. LOCAL STATUS unixDiskBlkRd
  277.     (
  278.     UNIXDISK_DEV *pUnixDiskDev, /* pointer to device desriptor */
  279.     int startBlk, /* starting block number to read */
  280.     int numBlks, /* number of blocks to read */
  281.     char *pBuffer /* pointer to buffer to receive data */
  282.     )
  283.     {
  284.     long offset;
  285.     int numBytes, ret;
  286.     FAST int bytesPerBlk; /* number of bytes per block */
  287.     bytesPerBlk = pUnixDiskDev->unixDiskBlkDev.bd_bytesPerBlk;
  288.     /* Add in the block offset */
  289.     offset = startBlk*bytesPerBlk;
  290.     if (u_lseek (pUnixDiskDev->unixFd, offset, 0) != offset)
  291. {
  292. printErr ("unixDiskBlkRd: lseek to offset %d failedn", offset);
  293. return (ERROR);
  294. }
  295.     numBytes = bytesPerBlk * numBlks;
  296.     /* Read the block(s) */
  297.     if ((ret = u_read (pUnixDiskDev->unixFd, pBuffer, numBytes)) != numBytes)
  298. {
  299. printErr ("unixDiskBlkRd: failed to read %d bytesn", numBytes);
  300. return (ERROR);
  301. }
  302.     return (OK);
  303.     }
  304. /*******************************************************************************
  305. *
  306. * unixDiskBlkWrt - write one or more blocks to a unix disk volume
  307. *
  308. * This routine writes one or more blocks to the specified volume,
  309. * starting with the specified block number.  The byte offset is
  310. * calculated and the buffer data is copied to the unix disk.
  311. *
  312. * RETURNS: OK for success and ERROR for bad block.
  313. */
  314. LOCAL STATUS unixDiskBlkWrt
  315.     (
  316.     UNIXDISK_DEV *pUnixDiskDev, /* pointer to device desriptor */
  317.     int startBlk, /* starting block number to write */
  318.     int numBlks, /* number of blocks to write */
  319.     char *pBuffer /* pointer to buffer of data to write */
  320.     )
  321.     {
  322.     long offset;
  323.     int numBytes, ret;
  324.     FAST int bytesPerBlk; /* number of bytes per block */
  325.     bytesPerBlk = pUnixDiskDev->unixDiskBlkDev.bd_bytesPerBlk;
  326.     /* Add in the block offset */
  327.     offset = startBlk * bytesPerBlk;
  328.     if (u_lseek (pUnixDiskDev->unixFd, offset, 0) != offset)
  329. {
  330. printErr ("unixDiskBlkWrt: lseek to offset %d failedn", offset);
  331. return (ERROR);
  332. }
  333.     numBytes = bytesPerBlk * numBlks;
  334.     if ((ret = u_write (pUnixDiskDev->unixFd, pBuffer, numBytes)) != numBytes)
  335. {
  336. printErr ("unixDiskBlkWrt: failed to write %d bytesn", numBytes);
  337. return (ERROR);
  338. }
  339.     return (OK);
  340.     }
  341. /*******************************************************************************
  342. *
  343. * unixDiskInit - initialize a dosFs disk on top of UNIX
  344. *
  345. * This routine provides some convenience for a user wanting to create
  346. * a UNIX disk-based dosFs file system under VxWorks.  The user only
  347. * specifes the UNIX file to use, the dosFs volume name, and the
  348. * size of the volume in bytes, if the UNIX file needs to be created.
  349. *
  350. * This routine is only applicable to VxSim for Solaris and VxSim for HP.
  351. *
  352. * RETURNS: N/A
  353. */
  354. void unixDiskInit
  355.     (
  356.     char *unixFile, /* UNIX file name */
  357.     char *volName, /* dosFs name */
  358.     int diskSize /* number of bytes */
  359.     )
  360.     {
  361.     int ix;
  362.     int fd;
  363.     int numEightKBlocks;
  364.     int numHalfKBlocks;
  365.     int create = 0;
  366.     int stat;
  367.     struct unix_stat buf;
  368.     char *emptySpace;
  369.     BLK_DEV *pBlkDev;
  370.     if (u_stat (unixFile, (char*)&buf) < 0)
  371. {
  372. printErr ("unixDiskInit: %s not found. Creating...", unixFile);
  373. if ((fd = u_open (unixFile, ARCHCVTFLAGS(unixCRFlag), unixCRMode)) < 0)
  374.     {
  375.     printErr ("permission deniedn");
  376.     return;
  377.     }
  378.         if (diskSize == 0)
  379.     diskSize = DEFAULT_DISK_SIZE;
  380. #define BLOCKSIZE 8192
  381. emptySpace = calloc (1, BLOCKSIZE);
  382. numEightKBlocks = diskSize / BLOCKSIZE;
  383. numHalfKBlocks = (diskSize % BLOCKSIZE) / DEFAULT_SEC_SIZE;
  384. for (ix = 0; ix < numEightKBlocks; ix++)
  385.     if (u_write (fd, emptySpace, BLOCKSIZE) < 0)
  386. {
  387. printErr ("Disk Write failed (disk full?)n");
  388. free (emptySpace);
  389. return;
  390. }
  391. for (ix = 0; ix < numHalfKBlocks; ix++)
  392.     if (u_write (fd, emptySpace, DEFAULT_SEC_SIZE) < 0)
  393. {
  394. printErr ("Disk Write failed (disk full?)n");
  395. free (emptySpace);
  396. return;
  397. }
  398. printErr ("donen");
  399. u_close (fd);
  400. free (emptySpace);
  401. create = 1;
  402. }
  403.     pBlkDev = unixDiskDevCreate (unixFile, DEFAULT_SEC_SIZE, 0, 0);
  404.     if (pBlkDev != NULL)
  405. {
  406. if (create)
  407.     stat = (dosFsMkfs (volName, pBlkDev) == NULL) ? -1 : 0;
  408. else
  409.     stat = (dosFsDevInit (volName, pBlkDev, 0) == NULL) ? -1 : 0;
  410. if (stat == -1)
  411.     {
  412.     printErr ("unixDiskInit: could not init dosFs file system on %sn",
  413. unixFile);
  414.     }
  415. else
  416.     {
  417.     printErr ("unixDiskInit: dosFs file system %s as device %sn",
  418. create ? "init'd" : "attached", volName);
  419.     }
  420. }
  421.     else
  422. printErr ("unixDiskInit: failedn");
  423.     }
  424. #endif /* (CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA) || CPU_FAMILY==SIMSPARCSOLARIS */