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

VxWorks

开发平台:

C/C++

  1. /* tffsDrv.c - TrueFFS interface for VxWorks */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /* 
  5.  * FAT-FTL Lite Software Development Kit
  6.  * Copyright (C) M-Systems Ltd. 1995-1997
  7.  */
  8. /*
  9. modification history
  10. --------------------
  11. 01l,19jun02,nrv  SPR#78569/35046, only set readyChanged bit if R/W error.
  12.                  Added NULL check to Rd/Wrt, corrected formatting.
  13. 01k,15oct01,nrv  documenting PHYSICAL_WRITE and PHYSICAL_ERASE as per SPR
  14.                  23200
  15. 01j,22aug01,dgp  correct typo in library description per SPR 28713
  16. 01i,11dec98,yp   added function tffsDevOptionsSet() to disable FAT monitoring
  17. 01h,09mar98,kbw  making man page edits to fix problems found by QE
  18. 01h,26jan98,kbw  making man page edits
  19. 01g,18dec97,yp   more doc fixups
  20. 01f,16dec97,yp   documentation and cleanup.
  21. 01e,16dec97,hdn  supported a return value of DEFRAGMENT_VOLUME.
  22. 01d,15dec97,hdn  added four new functions to tffsRawio().
  23. 01c,05dec97,hdn  added tffsRawio().
  24. 01b,07nov97,hdn  cleaned up.
  25. 01a,25aug97,and  written by Andray in M-Systems
  26. */
  27. /*
  28. DESCRIPTION
  29. This module defines the routines that VxWorks uses to create a TrueFFS
  30. block device.  Using this block device, dosFs can access a board-resident
  31. flash memory array or a flash memory card (in the PCMCIA slot) just as if 
  32. it was a standard disk drive.  Also defined in this file are functions that 
  33. you can use to format the flash medium, as well as well as functions that 
  34. handle the low-level I/O to the device.
  35. To include TrueFFS for Tornado in a VxWorks image, you must edit your BSP's
  36. config.h and define INCLUDE_TFFS, or, for some hardware, INCLUDE_PCMCIA. If
  37. you define INCLUDE_TFFS, this configures usrRoot() to call tffsDrv().  If you
  38. defined INCLUDE_PCMCIA, the call to tffsDrv() is made from pccardTffsEnabler().
  39. The call to tffsDrv() sets up the structures, global variables, and mutual 
  40. exclusion semaphore needed to manage TrueFFS.  This call to tffsDrv() also 
  41. registers socket component drivers for each flash device found attached to 
  42. the target. 
  43. These socket component drivers are not quite block devices, but they are 
  44. an essential layer within TrueFFS.  Their function is to manage the hardware
  45. interface to the flash device, and they are intelligent enough to handle 
  46. formatting and raw I/O requests to the flash device.  The other two layers 
  47. within TrueFFS are known as the translation layer and the MTD (the Memory 
  48. Technology Driver).  The translation layer of TrueFFS implements the error 
  49. recover and wear-leveling features of TrueFFS.  The MTD implements the 
  50. low-level programming (map, read, write, and erase) of the flash medium.  
  51. To implement the socket layer, each BSP that supports TrueFFS includes 
  52. a sysTffs.c file.  This file contains the code that defines the socket 
  53. component driver.  This file also contains a set of defines that you can use 
  54. to configure which translation layer modules and MTDs are included in TrueFFS.
  55. Which translation layer modules and MTDs you should include depends on
  56. which types of flash devices you need to support.  Currently, there are 
  57. three basic flash memory technologies, NAND-based, NOR-based, and SSFDC.
  58. Within sysTffs.c, define:
  59. .IP "INCLUDE_TL_NFTL" 
  60. To include the NAND-based translation layer module.
  61. .IP "INCLUDE_TL_FTL"
  62. To include the NOR-based translation layer module.
  63. .IP "INCLUDE_TL_SSFDC" 
  64. To include the SSFDC-appropriate translation layer module. 
  65. .LP
  66. To support these different technologies, TrueFFS ships with three different
  67. implementations of the translation layer.  Optionally, TrueFFS can include
  68. all three modules.  TrueFFS later binds the appropriate translation layer 
  69. module to the flash device when it registers a socket component driver for
  70. the device.  
  71. Within these three basic flash device categories there are still other 
  72. differences (largely manufacturer-specific).  These differences have no 
  73. impact on the translation layer.  However, they do make a difference for 
  74. the MTD.  Thus, TrueFFS ships with eight different MTDs that can support a 
  75. variety of flash devices from Intel, Sharp, Samsung, National, Toshiba, AMD, 
  76. and Fujitsu.  Within sysTffs.c, define:
  77. .IP "INCLUDE_MTD_I28F016"
  78. For Intel 28f016 flash devices.
  79. .IP "INCLUDE_MTD_I28F008"
  80. For Intel 28f008 flash devices.
  81. .IP "INCLUDE_MTD_I28F008_BAJA"
  82. For Intel 28f008 flash devices on the Heurikon Baja 4000.
  83. .IP "INCLUDE_MTD_AMD"
  84. For AMD, Fujitsu: 29F0{40,80,16} 8-bit flash devices.
  85. .IP "INCLUDE_MTD_CDSN"
  86. For Toshiba, Samsung: NAND CDSN flash devices.
  87. .IP "INCLUDE_MTD_DOC2"
  88. For Toshiba, Samsung: NAND DOC flash devices.
  89. .IP "INCLUDE_MTD_CFISCS"
  90. For CFI/SCS flash devices.
  91. .IP "INCLUDE_MTD_WAMD"
  92. For AMD, Fujitsu 29F0{40,80,16} 16-bit flash devices.
  93. .LP
  94. The socket component driver and the MTDs are provided in source form.  If 
  95. you need to write your own socket driver or MTD, use these working drivers
  96. as a model for your own.
  97. EXTERNALLY CALLABLE ROUTINES
  98. Most of the routines defined in this file are accessible through the I/O
  99. system only.  However, four routines are callable externally.  These
  100. are: tffsDrv(), tffsDevCreate(), tffsDevFormat(), and tffsRawio().
  101. The first routine called from this library must be tffsDrv().  Call this 
  102. routine exactly once.  Normally, this is handled automatically for you 
  103. from within usrRoot(), if INCLUDE_TFFS is defined, or from 
  104. within pccardTffsEnabler(), if INCLUDE_PCMCIA is defined.  
  105. Internally, this call to tffsDrv() registers socket component drivers for 
  106. all the flash devices connected to your system.  After registering a socket
  107. component driver for the device, TrueFFS can support calls to tffsDevFormat() 
  108. or tffsRawio().  However, before you can mount dosFs on the flash device, you 
  109. must call tffsDevCreate().  This call creates a block device on top of the 
  110. socket component driver, but does not mount dosFs on the device.  Because 
  111. mounting dosFs on the device is what you will want to do most of the time, 
  112. the sysTffs.c file defines a helper function, usrTffsConfig().  
  113. Internally, this function calls tffsDevCreate() and then does everything 
  114. necessary (such as calling the dosFsDevInit() routine) to mount dosFs on the 
  115. resulting block device.
  116. LOW LEVEL I/O
  117. Normally, you should handle your I/O to the flash device using dosFs.  
  118. However, there are situations when that level of indirection is a problem.
  119. To handle such situations, this library defines tffsRawio().  Using this 
  120. function, you can bypass both dosFs and the TrueFFS translation services
  121. to program the flash medium directly.  
  122. However, you should not try to program the flash device directly unless 
  123. you are intimately familiar with the physical limits of your flash device 
  124. as well as with how TrueFFS formats the flash medium.  Otherwise you risk 
  125. not only corrupting the medium entirely but permanently damaging the flash 
  126. device.
  127. If all you need to do is write a boot image to the flash device, use
  128. the tffsBootImagePut() utility instead of tffsRawio().  This function 
  129. provides safer access to the flash medium.  
  130. IOCTL
  131. This driver responds to all ioctl codes by setting a global error flag.
  132. Do not attempt to format a flash drive using ioctl calls. 
  133. INCLUDE FILES: tffsDrv.h, fatlite.h
  134. */
  135. /* includes */
  136. #include "tffsDrv.h"
  137. #include "fatlite.h"
  138. /* defines */
  139. /* externs */
  140. /* globals */
  141. #if     (POLLING_INTERVAL > 0)
  142. SEM_ID    flPollSemId;
  143. #endif  /* (POLLING_INTERVAL > 0) */
  144. /* locals */
  145. LOCAL BOOL tffsDrvInstalled = FALSE; /* TRUE, if installed */
  146. LOCAL BOOL tffsDrvStatus = ERROR; /* OK, if succeeded */
  147. LOCAL TFFS_DEV * tffsBlkDevs[DRIVES] = {NULL}; /* FLite block Devices */
  148. /* forward declarations */
  149. LOCAL void   tffsSetFromBPB (BLK_DEV *pBlkDev, BPB *pBPB);
  150. LOCAL STATUS tffsIoctl (TFFS_DEV * pTffsDev, int function, int arg);
  151. LOCAL STATUS tffsBlkRd (TFFS_DEV * pTffsDev, int startBlk, 
  152.  int numBlks, char * pBuffer);
  153. LOCAL STATUS tffsBlkWrt (TFFS_DEV * pTffsDev, int startBlk, 
  154.  int numBlks, char * pBuffer);
  155. #if     (POLLING_INTERVAL > 0)
  156. LOCAL FLStatus flPollSemCreate (void);
  157. #endif /* (POLLING_INTERVAL > 0) */
  158. /*******************************************************************************
  159. *
  160. * tffsDrv - initialize the TrueFFS system
  161. *
  162. * This routine sets up the structures, the global variables, and the mutual 
  163. * exclusion semaphore needed to manage TrueFFS. This call also registers 
  164. * socket component drivers for all the flash devices attached to your target.  
  165. *
  166. * Because tffsDrv() is the call that initializes the TrueFFS system, this
  167. * function must be called (exactly once) before calling any other TrueFFS
  168. * utilities, such as tffsDevFormat() or tffsDevCreate().  Typically, the call
  169. * to tffsDrv() is handled for you automatically.  If you defined INCLUDE_TFFS
  170. * in your BSP's config.h, the call to tffsDrv() is made from usrRoot().  If
  171. * your BSP's config.h defines INCLUDE_PCMCIA, the call to tffsDrv() is made
  172. * from pccardTffsEnabler().
  173. * RETURNS: OK, or ERROR if it fails.
  174. */
  175. STATUS tffsDrv (void)
  176.     {
  177.     if (!tffsDrvInstalled)
  178. {
  179.         /* FLite initialization:                                  */
  180.         /*      - register all the components and initialize them */
  181.         /*      - create socket polling task                      */
  182.         /*      - create task for background FLite operations      */
  183. #if     (POLLING_INTERVAL > 0)
  184.         /* Create Synchronisation semaphore */
  185.         if (flPollSemCreate() != flOK)
  186.             return (ERROR);
  187. #endif /* (POLLING_INTERVAL > 0) */
  188.         tffsDrvStatus = (flInit() == flOK) ? OK : ERROR;
  189. tffsDrvInstalled = TRUE;
  190. #if     (POLLING_INTERVAL > 0)
  191. if (tffsDrvStatus == flOK)
  192.     semGive (flPollSemId);
  193. #endif /* (POLLING_INTERVAL > 0) */
  194. }
  195.     return (tffsDrvStatus);
  196.     }
  197. /*******************************************************************************
  198. *
  199. * tffsDevCreate - create a TrueFFS block device suitable for use with dosFs
  200. *
  201. * This routine creates a TFFS block device on top of a flash device. It takes 
  202. * as arguments a drive number, determined from the order in which the socket
  203. * components were registered, and a flag integer that indicates whether the 
  204. * medium is removable or not. A zero indicates a non removable medium. A one 
  205. * indicates a removable medium.  If you intend to mount dosFs on this block 
  206. * device, you probably do not want to call tffsDevCreate(), but should 
  207. * call usrTffsConfig() instead.  Internally, usrTffsConfig() 
  208. * calls tffsDevCreate() for you.  It then does everything necessary (such as 
  209. * calling the dosFsDevInit() routine) to mount dosFs on the just created 
  210. * block device.  
  211. *
  212. * RETURNS: BLK_DEV pointer, or NULL if it failed.
  213. */
  214. BLK_DEV * tffsDevCreate 
  215.     (
  216.     int tffsDriveNo, /* TFFS drive number (0 - DRIVES-1) */
  217.     int removableMediaFlag /* 0 - nonremovable flash media */
  218.     )
  219.     {
  220.     FAST TFFS_DEV  *pTffsDev;           /* ptr to created TFFS_DEV struct */
  221.     FAST BLK_DEV   *pBlkDev;            /* ptr to BLK_DEV struct          */
  222.     FLStatus        status = flOK;
  223.     BPB             bpb;
  224.     IOreq           ioreq;
  225.     if (tffsDriveNo >= DRIVES)
  226.         return (NULL);
  227.     ioreq.irHandle = tffsDriveNo;
  228.     /* create and initialize BLK_DEV structure */
  229.     pTffsDev = (TFFS_DEV *) malloc (sizeof (TFFS_DEV));
  230.     if (pTffsDev == NULL)
  231.         return (NULL);
  232.     status = flMountVolume(&ioreq);
  233.     if (status == flOK)
  234.         {
  235.         ioreq.irData = &bpb;
  236.         status = flGetBPB(&ioreq);
  237.         if (status == flOK)
  238.             {
  239.             pBlkDev = &pTffsDev->tffsBlkdev;
  240.             tffsSetFromBPB (pBlkDev, &bpb);
  241.             if (removableMediaFlag)
  242.                 pBlkDev->bd_removable  = TRUE;    /* removable                */
  243.             else
  244.                 pBlkDev->bd_removable  = FALSE;   /* not removable            */
  245.             pBlkDev->bd_retry        = 1;         /* retry count              */
  246.             pBlkDev->bd_mode         = O_RDWR;    /* initial mode for device  */
  247.             pBlkDev->bd_readyChanged = TRUE;      /* new ready status         */
  248.             pBlkDev->bd_blkRd        = tffsBlkRd; /* read block function      */
  249.             pBlkDev->bd_blkWrt       = tffsBlkWrt;/* write block function     */
  250.             pBlkDev->bd_ioctl        = tffsIoctl; /* ioctl function           */
  251.             pBlkDev->bd_reset        = NULL;      /* no reset function        */
  252.             pBlkDev->bd_statusChk    = NULL;      /* no check-status function */
  253.             pTffsDev->tffsDriveNo    = tffsDriveNo;
  254.             }
  255.         else
  256.     ;
  257.         }
  258.     if (status != flOK)
  259.         return (NULL);
  260.     /* remember that we have created FLite device */
  261.     tffsBlkDevs[tffsDriveNo] = pTffsDev;
  262.     return (&pTffsDev->tffsBlkdev);
  263.     }
  264. /*******************************************************************************
  265. *
  266. * tffsDevOptionsSet - set TrueFFS volume options
  267. *
  268. * This routine is intended to set various TrueFFS volume options. At present
  269. * it only disables FAT monitoring. If VxWorks long file names are to be used
  270. * with TrueFFS, FAT monitoring must be turned off.
  271. *
  272. * RETURNS: OK, or ERROR if it failed.
  273. */
  274. STATUS tffsDevOptionsSet
  275.     (
  276.     TFFS_DEV * pTffsDev                /* pointer to device descriptor */
  277.     )
  278.     {
  279.     FLStatus        status;
  280.     IOreq           ioreq;
  281.     /* Note : it is expected that as more volume option that would 
  282.      *        need to get set via this routine are detected a second
  283.      *        parameter will be added to indicate the option that needs
  284.      *        to get set.
  285.      */
  286.     if ((pTffsDev == NULL) || (pTffsDev->tffsDriveNo >= DRIVES))
  287.         return (ERROR);
  288.     ioreq.irHandle = pTffsDev->tffsDriveNo;
  289.     /* disable FAT monitoring for TrueFFS volumes */
  290.     status = flDontMonitorFAT(&ioreq);
  291.     return ((status == flOK) ? OK : ERROR);
  292.     }
  293. /*******************************************************************************
  294. *
  295. * tffsIoctl - handle IOCTL calls to TFFS driver
  296. *
  297. * This routine handles IOCTL calls to TrueFFS driver. Currently it sets a global
  298. * error flag and exits. The ioctl FIODISKFORMAT should not be used with TrueFFS
  299. * devices. Use tffsDevFormat() to format TrueFFS drives.
  300. *
  301. * RETURNS: ERROR always.
  302. *
  303. * ERRNO: S_ioLib_UNKNOWN_REQUEST
  304. *
  305. */
  306. LOCAL STATUS tffsIoctl 
  307.     (
  308.     TFFS_DEV * pTffsDev, /* pointer to device descriptor */
  309.     int function, /* function code */
  310.     int arg /* some argument */
  311.     )
  312.     {
  313.     errnoSet (S_ioLib_UNKNOWN_REQUEST);
  314.     return (ERROR);
  315.     }
  316. /*******************************************************************************
  317. *
  318. * tffsBlkRd - reads sequence of blocks from TFFS device
  319. *
  320. * This routine reads a sequence of blocks from TrueFFS formatted device.
  321. *
  322. * RETURNS: OK, or ERROR if it failed.
  323. *
  324. * NOMANUAL
  325. */
  326. LOCAL STATUS tffsBlkRd 
  327.     (
  328.     FAST TFFS_DEV * pTffsDev, /* pointer to device descriptor */
  329.     int startBlk, /* starting block number to read */
  330.     int numBlks, /* number of blocks to read */
  331.     char * pBuffer /* pointer to buffer to receive data */
  332.     )
  333.     {
  334.     FLStatus    status = flOK;
  335.     IOreq       ioreq;
  336.     BPB         bpb;
  337.     if ( (NULL == pTffsDev) || (NULL == pBuffer) ||
  338.          (pTffsDev->tffsDriveNo >= DRIVES) )
  339.         {
  340.         return (ERROR);
  341.         }
  342.     ioreq.irHandle = pTffsDev->tffsDriveNo;
  343.     status = flCheckVolume(&ioreq);
  344.     if (status == flNotMounted)
  345.         {
  346.         status = flMountVolume(&ioreq);
  347.         if (status == flOK)
  348.             {
  349.             ioreq.irData = &bpb;
  350.             status = flGetBPB(&ioreq);
  351.             }
  352.         if (status != flOK)
  353.             {
  354.             pTffsDev->tffsBlkdev.bd_readyChanged = TRUE;
  355.             return (ERROR);
  356.             }
  357.         /* Modify BLK_DEV structure */
  358.         tffsSetFromBPB( &(pTffsDev->tffsBlkdev), &bpb);
  359.         pTffsDev->tffsBlkdev.bd_mode = O_RDWR; /* initial mode for device */
  360.         }
  361.     ioreq.irSectorNo    = startBlk;
  362.     ioreq.irSectorCount = numBlks;
  363.     ioreq.irData        = pBuffer;
  364.     status = flAbsRead(&ioreq);
  365.     /* if success cancel dosFs re-mount volume request */
  366.     if (status != flOK)
  367.         pTffsDev->tffsBlkdev.bd_readyChanged = TRUE;
  368.     return ((status == flOK) ? OK : ERROR);
  369.     }
  370. /*******************************************************************************
  371. *
  372. * tffsBlkWrt - write sequence of blocks to TFFS device
  373. *
  374. * This routine writes a sequence of blocks to TrueFFS device.
  375. *
  376. * RETURNS: OK, or ERROR if it failed.
  377. *
  378. * NOMANUAL
  379. */
  380. LOCAL STATUS tffsBlkWrt 
  381.     (
  382.     FAST TFFS_DEV * pTffsDev, /* pointer to device descriptor */
  383.     int startBlk, /* starting block number to write */
  384.     int numBlks, /* number of blocks to write */
  385.     char * pBuffer /* pointer to buffer containing data */
  386.     )
  387.     {
  388.     FLStatus   status = flOK;
  389.     IOreq      ioreq;
  390.     BPB        bpb;
  391.     if ( (NULL == pTffsDev) || (NULL == pBuffer) ||
  392.          (pTffsDev->tffsDriveNo >= DRIVES) )
  393.         {
  394.         return (ERROR);
  395.         }
  396.     ioreq.irHandle = pTffsDev->tffsDriveNo;
  397.     status = flCheckVolume(&ioreq);
  398.     if (status == flNotMounted)
  399.         {
  400.         status = flMountVolume(&ioreq);
  401.         if (status == flOK)
  402.             {
  403.             ioreq.irData = &bpb;
  404.             status = flGetBPB(&ioreq);
  405.             }
  406.         if (status != flOK)
  407.             {
  408.             pTffsDev->tffsBlkdev.bd_readyChanged = TRUE;
  409.             return (ERROR);
  410.             }
  411.         /* Modify BLK_DEV structure */
  412.         tffsSetFromBPB( &(pTffsDev->tffsBlkdev), &bpb);
  413.         pTffsDev->tffsBlkdev.bd_mode = O_RDWR; /* initial mode for device */
  414.         }
  415.     ioreq.irSectorNo    = startBlk;
  416.     ioreq.irSectorCount = numBlks;
  417.     ioreq.irData        = pBuffer;
  418.     status = flAbsWrite(&ioreq);
  419.     if (status == flWriteProtect)
  420.         {
  421.         flDismountVolume(&ioreq); /* force a remount */
  422.         pTffsDev->tffsBlkdev.bd_mode = O_RDONLY;
  423.         }
  424.     /* re-mount volume request */
  425.     if (status != flOK)
  426.         pTffsDev->tffsBlkdev.bd_readyChanged = TRUE;
  427.     return ((status == flOK) ? OK : ERROR);
  428.     }
  429. /*******************************************************************************
  430. *
  431. * tffsSetFromBPB - copy some data from BIOS parameter block
  432. *
  433. * This routine copies BIOS parameter block data describing the flash device
  434. * returned by TrueFFS into a device descriptor.
  435. *
  436. * RETURNS: N/A
  437. *
  438. * NOMANUAL
  439. */
  440. LOCAL void tffsSetFromBPB 
  441.     (
  442.     BLK_DEV * pBlkDev, /* pointer to device descriptor */
  443.     BPB * pBPB /* pointer to BIOS parameters block */
  444.     )
  445.     {
  446.     if ((NULL == pBlkDev) || (NULL == pBPB))
  447.         return;
  448.     pBlkDev->bd_nBlocks      = 0;
  449.     pBlkDev->bd_bytesPerBlk  = 0;
  450.     pBlkDev->bd_blksPerTrack = 0;
  451.     pBlkDev->bd_nHeads       = 0;     /* clear first */
  452.     if( UNAL2(pBPB->totalSectorsInVolumeDOS3) )
  453.         pBlkDev->bd_nBlocks  = UNAL2(pBPB->totalSectorsInVolumeDOS3);
  454.     else
  455.         pBlkDev->bd_nBlocks  = LE4(pBPB->totalSectorsInVolume);
  456.     pBlkDev->bd_bytesPerBlk  = UNAL2(pBPB->bytesPerSector);
  457.     pBlkDev->bd_blksPerTrack = LE2(pBPB->sectorsPerTrack);
  458.     pBlkDev->bd_nHeads       = LE2(pBPB->noOfHeads);
  459.     }
  460. /*******************************************************************************
  461. *
  462. * tffsDiskChangeAnnounce - announce disk change to the file system attached
  463. *
  464. * This routine is called by TFFS to update the the readyChanged field in the
  465. * device descriptor so that the file system can be notified of a disk change.
  466. *
  467. * RETURNS: N/A
  468. *
  469. * NOMANUAL
  470. */
  471. void tffsDiskChangeAnnounce
  472.     (
  473.     unsigned volNo /* FLite drive number (0 - DRIVES-1) */
  474.     )
  475.     {
  476.     if ((volNo < DRIVES) && (tffsBlkDevs[volNo] != NULL))
  477.         tffsBlkDevs[volNo]->tffsBlkdev.bd_readyChanged = TRUE;
  478.     }
  479. /*******************************************************************************
  480. *
  481. * tffsDevFormat - format a flash device for use with TrueFFS
  482. *
  483. * This routine formats a flash device for use with TrueFFS.  It takes two 
  484. * parameters, a drive number and a pointer to a device format structure. 
  485. * This structure describes how the volume should be formatted.  The structure 
  486. * is defined in dosformt.h.  The drive number is assigned in the order that 
  487. * the socket component for the device was registered.
  488. *
  489. * The format process marks each erase unit with an Erase Unit Header (EUH) and
  490. * creates the physical and virtual Block Allocation Maps (BAM) for the device. 
  491. * The erase units reserved for the "boot-image" are skipped and the first
  492. * EUH is placed at number (boot-image length - 1). To write to the boot-image
  493. * region, call tffsBootImagePut(). 
  494. * WARNING: If any of the erase units in the boot-image 
  495. * region contains an erase unit header from a previous format call (this can
  496. * happen if you reformat a flash device specifying a larger boot region) 
  497. * TrueFFS fails to mount the device.  To fix this problem, use tffsRawio() to
  498. * erase the problem erase units (thus removing the outdated EUH).  
  499. *
  500. * The macro TFFS_STD_FORMAT_PARAMS defines the default values used for 
  501. * formatting a flask disk device. If the second argument to this routine 
  502. * is zero, tffsDevFormat() uses these default values.
  503. *
  504. * RETURNS: OK, or ERROR if it failed.
  505. */
  506. STATUS tffsDevFormat 
  507.     (
  508.     int tffsDriveNo, /* TrueFFS drive number (0 - DRIVES-1) */
  509.     int arg /* pointer to tffsDevFormatParams structure */
  510.     )
  511.     {
  512.     tffsDevFormatParams defaultParams = TFFS_STD_FORMAT_PARAMS;
  513.     tffsDevFormatParams *devFormatParams;
  514.     IOreq                ioreq;
  515.     FLStatus             status;
  516.     if (tffsDriveNo >= DRIVES)
  517.         return (ERROR);
  518.     /* tell dosFs to re-mount volume */
  519.   
  520.     if (tffsBlkDevs[tffsDriveNo] != NULL)
  521.         tffsBlkDevs[tffsDriveNo]->tffsBlkdev.bd_readyChanged = TRUE;
  522.     if (arg == 0)
  523.         devFormatParams = &defaultParams;
  524.     else
  525.         devFormatParams = (tffsDevFormatParams *) arg;
  526.     ioreq.irHandle = tffsDriveNo;
  527.     ioreq.irFlags  = devFormatParams->formatFlags;
  528.     ioreq.irData   = &(devFormatParams->formatParams);
  529.     status = flFormatVolume(&ioreq);
  530.     return ((status == flOK) ? OK : ERROR);
  531.     }
  532. /*******************************************************************************
  533. *
  534. * tffsRawio - low level I/O access to flash components
  535. *
  536. * Use the utilities provided by thisroutine with the utmost care. If you use 
  537. * these routines carelessly, you risk data loss as well as  permanent 
  538. * physical damage to the flash device.
  539. *
  540. * This routine is a gateway to a series of utilities (listed below). Functions 
  541. * such as mkbootTffs() and tffsBootImagePut() use these tffsRawio() utilities 
  542. * to write boot sector information. The functions for physical read, write, and 
  543. * erase are made available with the intention that they be used on erase units 
  544. * allocated to the boot-image region by tffsDevFormat(). Using these functions 
  545. * elsewhere could be dangerous.
  546. *
  547. * The <arg0>, <arg1>, and <arg2> parameters to tffsRawio() are interpreted 
  548. * differently depending on the function number you specify for <functionNo>. 
  549. * The drive number is determined by the order in which the socket 
  550. * components were registered. 
  551. *
  552. * .TS
  553. * tab(|);
  554. * lf3 lf3 lf3 lf3
  555. * l l l l .
  556. * Function Name | arg0 | arg1 | arg2
  557. * _
  558. * TFFS_GET_PHYSICAL_INFO | user buffer address | N/A | N/A
  559. * TFFS_PHYSICAL_READ | address to read | byte count | user buffer address
  560. * TFFS_PHYSICAL_WRITE | address to write | byte count | user buffer address
  561. * TFFS_PHYSICAL_ERASE | first unit | number of units | N/A
  562. * TFFS_ABS_READ | sector number | number of sectors | user buffer address
  563. * TFFS_ABS_WRITE | sector number | number of sectors | user buffer address
  564. * TFFS_ABS_DELETE | sector number | number of sectors | N/A
  565. * TFFS_DEFRAGMENT_VOLUME | number of sectors | user buffer address | N/A
  566. * .TE
  567. *
  568. * TFFS_GET_PHYSICAL_INFO writes the flash type, erasable block size, and media
  569. * size to the user buffer specified in <arg0>.
  570. *
  571. * TFFS_PHYSICAL_READ reads <arg1> bytes from <arg0> and writes them to 
  572. * the buffer specified by <arg2>.
  573. *
  574. * TFFS_PHYSICAL_WRITE copies <arg1> bytes from the <arg2> buffer and writes 
  575. * them to the flash memory location specified by <arg0>.  
  576. * This aborts if the volume is already mounted to prevent the versions of 
  577. * translation data in memory and in flash from going out of synchronization.
  578. *
  579. * TFFS_PHYSICAL_ERASE erases <arg1> erase units, starting at the erase unit
  580. * specified in <arg0>.
  581. * This aborts if the volume is already mounted to prevent the versions of 
  582. * translation data in memory and in flash from going out of synchronization.
  583. *
  584. * TFFS_ABS_READ reads <arg1> sectors, starting at sector <arg0>, and writes
  585. * them to the user buffer specified in <arg2>.
  586. *
  587. * TFFS_ABS_WRITE takes data from the <arg2> user buffer and writes <arg1> 
  588. * sectors of it to the flash location starting at sector <arg0>.
  589. * TFFS_ABS_DELETE deletes <arg1> sectors of data starting at sector <arg0>. 
  590. *
  591. * TFFS_DEFRAGMENT_VOLUME calls the defragmentation routine with the minimum
  592. * number of sectors to be reclaimed, <arg0>, and writes the actual number 
  593. * reclaimed in the user buffer by <arg1>. Calling this function through some 
  594. * low priority task will make writes more deterministic.
  595. * No validation is done of the user specified address fields, so the functions 
  596. * assume they are writable. If the address is invalid, you could see bus errors
  597. * or segmentation faults.
  598. * RETURNS: OK, or ERROR if it failed.
  599. */
  600. STATUS tffsRawio 
  601.     (
  602.     int tffsDriveNo, /* TrueFFS drive number (0 - DRIVES-1) */
  603.     int functionNo, /* TrueFFS function code */
  604.     int arg0, /* argument 0 */
  605.     int arg1, /* argument 1 */
  606.     int arg2 /* argument 2 */
  607.     )
  608.     {
  609.     IOreq ioreq;
  610.     FLStatus status;
  611.     int function;
  612.     if (tffsDriveNo >= DRIVES)
  613.         return (ERROR);
  614.     ioreq.irHandle = tffsDriveNo; /* drive number */
  615.     switch (functionNo)
  616. {
  617. case TFFS_GET_PHYSICAL_INFO:
  618.     function = FL_GET_PHYSICAL_INFO;
  619.     ioreq.irData = (char *)arg0; /* address of user buffer to store */
  620.     break;
  621. case TFFS_PHYSICAL_READ:
  622.     function = FL_PHYSICAL_READ;
  623.     ioreq.irAddress = arg0; /* chip/card address to read/write */
  624.     ioreq.irByteCount = arg1; /* number of bytes to read/write */
  625.     ioreq.irData = (char *)arg2; /* address of user buffer to r/w */
  626.     break;
  627. case TFFS_PHYSICAL_WRITE:
  628.     function = FL_PHYSICAL_WRITE;
  629.     ioreq.irAddress = arg0; /* chip/card address to read/write */
  630.     ioreq.irByteCount = arg1; /* number of bytes to read/write */
  631.     ioreq.irData = (char *)arg2; /* address of user buffer to r/w */
  632.     break;
  633. case TFFS_PHYSICAL_ERASE:
  634.     function = FL_PHYSICAL_ERASE;
  635.     ioreq.irUnitNo = arg0; /* first unit to erase */
  636.     ioreq.irUnitCount = arg1; /* number of units to erase */
  637.     break;
  638. case TFFS_ABS_READ:
  639.     function = FL_ABS_READ;
  640.     ioreq.irSectorNo = arg0; /* sector number to read/write */
  641.     ioreq.irSectorCount = arg1; /* number of sectors to read/write */
  642.     ioreq.irData = (char *)arg2; /* address of user buffer to r/w */
  643.     break;
  644. case TFFS_ABS_WRITE:
  645.     function = FL_ABS_WRITE;
  646.     ioreq.irSectorNo = arg0; /* sector number to read/write */
  647.     ioreq.irSectorCount = arg1; /* number of sectors to read/write */
  648.     ioreq.irData = (char *)arg2; /* address of user buffer to r/w */
  649.     break;
  650. case TFFS_ABS_DELETE:
  651.     function = FL_ABS_DELETE;
  652.     ioreq.irSectorNo = arg0; /* sector number to delete */
  653.     ioreq.irSectorCount = arg1; /* number of sectors to delete */
  654.     break;
  655. case TFFS_DEFRAGMENT_VOLUME:
  656.     function = FL_DEFRAGMENT_VOLUME;
  657.     ioreq.irLength = arg0; /* minimum number of sectors to get */
  658.     break;
  659. default:
  660.     return (ERROR);
  661. }
  662.     status = flCall (function, &ioreq);
  663.     switch (functionNo)
  664. {
  665. case TFFS_DEFRAGMENT_VOLUME:
  666.     *(int *)arg1 = ioreq.irLength; /* min number of sectors gotten */
  667.     break;
  668. }
  669.     return ((status == flOK) ? OK : ERROR);
  670.     }
  671. #if     (POLLING_INTERVAL > 0)
  672. /*******************************************************************************
  673. *
  674. * flPollSemCreate - create semaphore for polling task
  675. *
  676. * This routine creates the semaphore used to delay socket polling until
  677. * TrueFFS initialization is complete.
  678. *
  679. * RETURNS: flOK, or flNotEnoughMemory if it fails.
  680. */
  681. LOCAL FLStatus flPollSemCreate (void)
  682.     {
  683.     if ((flPollSemId = semBCreate (SEM_Q_PRIORITY, SEM_EMPTY)) == NULL)
  684.         return (flNotEnoughMemory);
  685.     else
  686.         return (flOK);
  687.     }
  688. #endif /* (POLLING_INTERVAL > 0) */