rawfs.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. /*
  2. * Copyright (C) 2008-2009 by egnite GmbH
  3. * Copyright (C) 2005-2006 by egnite Software GmbH
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. */
  35. /*!
  36. * \file fs/rawfs.c
  37. * \brief Raw device file system.
  38. *
  39. * This file system provides a single file entry only, which is mapped to
  40. * the entire volume. This implies, that there is no file name and that
  41. * the size of the file is fixed.
  42. *
  43. * \verbatim
  44. * $Id: rawfs.c 5472 2013-12-06 00:16:28Z olereinhardt $
  45. * \endverbatim
  46. */
  47. #include <dev/blockdev.h>
  48. #include <sys/event.h>
  49. #include <sys/nutdebug.h>
  50. #include <fs/fs.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53. #include <errno.h>
  54. #include <memdebug.h>
  55. #include <fs/rawfs.h>
  56. #if 0
  57. /* Use for local debugging. */
  58. #define NUTDEBUG
  59. #include <stdio.h>
  60. #endif
  61. #ifndef SEEK_SET
  62. # define SEEK_SET 0 /* Seek from beginning of file. */
  63. # define SEEK_CUR 1 /* Seek from current position. */
  64. # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
  65. #endif
  66. /*!
  67. * \addtogroup xgRawFs
  68. */
  69. /*@{*/
  70. /*!
  71. * \brief Flush sector buffer.
  72. *
  73. * The volume must be locked when calling this function.
  74. *
  75. * \param dev Specifies the file system device.
  76. *
  77. * \return 0 on success, -1 on failures.
  78. */
  79. static int RawFsSectorFlush(NUTDEVICE * dev)
  80. {
  81. int rc = 0;
  82. RAWVOLUME *vol = (RAWVOLUME *) dev->dev_dcb;
  83. /* Write dirty sectors only. */
  84. if (vol->vol_sect_dirty) {
  85. BLKPAR_SEEK pars;
  86. NUTFILE *blkmnt = dev->dev_icb;
  87. NUTDEVICE *blkdev = blkmnt->nf_dev;
  88. /* Set the block device's sector position. */
  89. pars.par_nfp = blkmnt;
  90. pars.par_blknum = vol->vol_sect_num;
  91. rc = (*blkdev->dev_ioctl) (blkdev, NUTBLKDEV_SEEK, &pars);
  92. if (rc == 0) {
  93. /* Write single block to the device. */
  94. if ((*blkdev->dev_write) (blkmnt, vol->vol_sect_buf, 1) == 1) {
  95. /* Success, buffer is clean. */
  96. vol->vol_sect_dirty = 0;
  97. } else {
  98. rc = -1;
  99. }
  100. }
  101. }
  102. return rc;
  103. }
  104. /*!
  105. * \brief Load sector.
  106. *
  107. * \param dev Specifies the file system device.
  108. * \param sect Sector to load.
  109. *
  110. * \return 0 on success, -1 on failures.
  111. */
  112. static int RawFsSectorLoad(NUTDEVICE * dev, uint32_t sect)
  113. {
  114. int rc = -1;
  115. RAWVOLUME *vol;
  116. NUTASSERT(dev != NULL);
  117. vol = (RAWVOLUME *) dev->dev_dcb;
  118. /* Gain mutex access. */
  119. NUTASSERT(vol != NULL);
  120. NutEventWait(&vol->vol_iomutex, 0);
  121. /* Nothing to do if sector is already loaded. */
  122. if (vol->vol_sect_num == sect) {
  123. rc = 0;
  124. }
  125. /* Make sure that the sector buffer is clean. */
  126. else if (RawFsSectorFlush(dev) == 0) {
  127. NUTFILE *blkmnt = dev->dev_icb;
  128. NUTDEVICE *blkdev = blkmnt->nf_dev;
  129. BLKPAR_SEEK pars;
  130. blkmnt = dev->dev_icb;
  131. NUTASSERT(blkmnt != NULL);
  132. blkdev = blkmnt->nf_dev;
  133. NUTASSERT(blkdev != NULL);
  134. /* Set the block device's sector position. */
  135. pars.par_nfp = blkmnt;
  136. pars.par_blknum = sect;
  137. if ((*blkdev->dev_ioctl) (blkdev, NUTBLKDEV_SEEK, &pars) == 0) {
  138. /* Read a single block from the device. */
  139. if ((*blkdev->dev_read) (blkmnt, vol->vol_sect_buf, 1) == 1) {
  140. vol->vol_sect_num = sect;
  141. rc = 0;
  142. }
  143. }
  144. }
  145. /* Release mutex access. */
  146. NutEventPostAsync(&vol->vol_iomutex);
  147. return rc;
  148. }
  149. /*!
  150. * \brief Flush file buffers.
  151. *
  152. * \param nfp Specifies the file.
  153. *
  154. * \return 0 on success, -1 otherwise.
  155. */
  156. static int RawFsFileFlush(NUTFILE * nfp)
  157. {
  158. int rc;
  159. NUTDEVICE *dev;
  160. RAWVOLUME *vol;
  161. NUTASSERT(nfp != NULL);
  162. dev = nfp->nf_dev;
  163. NUTASSERT(dev != NULL);
  164. vol = (RAWVOLUME *) dev->dev_dcb;
  165. NUTASSERT(vol != NULL);
  166. /* Gain mutex access. */
  167. NutEventWait(&vol->vol_iomutex, 0);
  168. /* Flush sector buffer. */
  169. rc = RawFsSectorFlush(nfp->nf_dev);
  170. /* Release mutex access. */
  171. NutEventPost(&vol->vol_iomutex);
  172. return rc;
  173. }
  174. /*!
  175. * \brief Open a raw file.
  176. *
  177. * This function is called by the low level open routine of the C runtime
  178. * library, using the _NUTDEVICE::dev_open entry.
  179. *
  180. * \param dev Specifies the file system device.
  181. * \param path Pathname of the file to open which is ignored here, because
  182. * the raw file system doesn't support multiple file entries.
  183. * \param mode Operation mode.
  184. * \param acc File attribute, ignored.
  185. *
  186. * \return Pointer to a NUTFILE structure if successful or NUTFILE_EOF otherwise.
  187. *
  188. * \bug Append mode not working as expected.
  189. */
  190. NUTFILE *RawFsFileOpen(NUTDEVICE * dev, const char *path, int mode, int acc)
  191. {
  192. NUTFILE *nfp;
  193. RAWFILE *fcb;
  194. /* Allocate a private file control block. */
  195. fcb = malloc(sizeof(RAWFILE));
  196. if (fcb) {
  197. memset(fcb, 0, sizeof(RAWFILE));
  198. fcb->f_mode = mode;
  199. /* Allocate a file information structure. */
  200. nfp = malloc(sizeof(NUTFILE));
  201. if (nfp) {
  202. nfp->nf_dev = dev;
  203. nfp->nf_fcb = fcb;
  204. /* Successfully opened. */
  205. return nfp;
  206. }
  207. free(fcb);
  208. }
  209. /* Return failure. */
  210. return NUTFILE_EOF;
  211. }
  212. /*!
  213. * \brief Close a raw file.
  214. *
  215. * \param nfp Pointer to a \ref NUTFILE structure, obtained by a previous
  216. * call to RawFsFileOpen().
  217. *
  218. * \return 0 on success, -1 otherwise.
  219. */
  220. int RawFsFileClose(NUTFILE * nfp)
  221. {
  222. int rc;
  223. NUTASSERT(nfp != NULL);
  224. rc = RawFsFileFlush(nfp);
  225. if (nfp->nf_fcb) {
  226. free(nfp->nf_fcb);
  227. }
  228. free(nfp);
  229. return rc;
  230. }
  231. /*!
  232. * \brief Write data to a file.
  233. *
  234. * \param nfp Pointer to a \ref NUTFILE structure, obtained by a previous
  235. * call to RawFsFileOpen().
  236. * \param buffer Pointer to the data to be written. If zero, then the
  237. * output buffer will be flushed.
  238. * \param len Number of bytes to write.
  239. *
  240. * \return The number of bytes written. A return value of -1 indicates an
  241. * error.
  242. */
  243. int RawFsFileWrite(NUTFILE * nfp, const void *buffer, int len)
  244. {
  245. int rc;
  246. int step;
  247. uint8_t *buf;
  248. RAWFILE *fcb;
  249. RAWVOLUME *vol;
  250. NUTASSERT(nfp != NULL);
  251. /* Flush file if buffer is a NULL pointer. */
  252. if (buffer == NULL || len == 0) {
  253. return RawFsFileFlush(nfp);
  254. }
  255. /* Sanity check. */
  256. NUTASSERT(nfp->nf_fcb != NULL);
  257. NUTASSERT(nfp->nf_dev != NULL);
  258. NUTASSERT(nfp->nf_dev->dev_dcb != NULL);
  259. fcb = (RAWFILE *) nfp->nf_fcb;
  260. vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
  261. /*
  262. * Write the data.
  263. */
  264. buf = (uint8_t *) buffer;
  265. for (rc = 0, step = 0; rc < len; rc += step) {
  266. /* Did we reach the end of a sector? */
  267. if (fcb->f_sect_pos >= vol->vol_sect_len) {
  268. /* Yes, move to the next sector. */
  269. fcb->f_sect_num++;
  270. fcb->f_sect_pos -= vol->vol_sect_len;
  271. }
  272. /* Load the sector we want to write to. */
  273. if (RawFsSectorLoad(nfp->nf_dev, fcb->f_sect_num)) {
  274. rc = -1;
  275. break;
  276. }
  277. /* The number of bytes we write to this sector. */
  278. step = (int) (vol->vol_sect_len - fcb->f_sect_pos);
  279. if (step > len - rc) {
  280. step = len - rc;
  281. }
  282. /* Copy data to this sector. */
  283. memcpy(&vol->vol_sect_buf[fcb->f_sect_pos], &buf[rc], step);
  284. vol->vol_sect_dirty = 1;
  285. /* Advance file pointers. */
  286. fcb->f_pos += step;
  287. fcb->f_sect_pos += step;
  288. }
  289. return rc;
  290. }
  291. #ifdef __HARVARD_ARCH__
  292. /*!
  293. * \brief Write data from program space to a file.
  294. *
  295. * This function is not yet implemented and will always return -1.
  296. *
  297. * Similar to RawFsFileWrite() except that the data is located in
  298. * program memory.
  299. *
  300. * \param nfp Pointer to a \ref NUTFILE structure, obtained by a previous
  301. * call to RawFsFileOpen().
  302. * \param buffer Pointer to the data in program space. If zero, then the
  303. * output buffer will be flushed.
  304. * \param len Number of bytes to write.
  305. *
  306. * \return The number of bytes written. A return value of -1 indicates an
  307. * error.
  308. */
  309. int RawFsFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
  310. {
  311. return -1;
  312. }
  313. #endif
  314. /*!
  315. * \brief Read data from a file.
  316. *
  317. * \param nfp Pointer to a \ref NUTFILE structure, obtained by a previous
  318. * call to RawFsFileOpen().
  319. * \param buffer Pointer to the data buffer to fill.
  320. * \param size Maximum number of bytes to read.
  321. *
  322. * \return The number of bytes actually read. A return value of -1 indicates
  323. * an error.
  324. */
  325. int RawFsFileRead(NUTFILE * nfp, void *buffer, int size)
  326. {
  327. int rc;
  328. int step;
  329. uint8_t *buf;
  330. RAWVOLUME *vol;
  331. RAWFILE *fcb;
  332. /* Ignore input flush. */
  333. if (buffer == NULL || size == 0) {
  334. return 0;
  335. }
  336. NUTASSERT(nfp != NULL);
  337. NUTASSERT(nfp->nf_dev != NULL);
  338. fcb = nfp->nf_fcb;
  339. NUTASSERT(fcb != NULL);
  340. vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
  341. NUTASSERT(vol != NULL);
  342. buf = (uint8_t *) buffer;
  343. for (rc = 0, step = 0; rc < size; rc += step) {
  344. /* Did we reach the end of a sector? */
  345. if (fcb->f_sect_pos >= vol->vol_sect_len) {
  346. /* Yes, move to the next sector. */
  347. fcb->f_sect_num++;
  348. fcb->f_sect_pos -= vol->vol_sect_len;
  349. }
  350. /* Make sure that the required sector is loaded. */
  351. if (RawFsSectorLoad(nfp->nf_dev, fcb->f_sect_num)) {
  352. rc = -1;
  353. break;
  354. }
  355. step = (int) (vol->vol_sect_len - fcb->f_sect_pos);
  356. if (step > size - rc) {
  357. step = size - rc;
  358. }
  359. memcpy(&buf[rc], &vol->vol_sect_buf[fcb->f_sect_pos], step);
  360. fcb->f_pos += step;
  361. fcb->f_sect_pos += step;
  362. }
  363. return rc;
  364. }
  365. /*!
  366. * \brief Retrieve the size of a previously opened file.
  367. *
  368. * This function is called by the low level size routine of the C runtime
  369. * library, using the _NUTDEVICE::dev_size entry.
  370. *
  371. * \param nfp Pointer to a \ref _NUTFILE structure, obtained by a
  372. * previous call to RawFsFileOpen().
  373. *
  374. * \return Size of the file.
  375. */
  376. static long RawFsFileSize(NUTFILE * nfp)
  377. {
  378. RAWVOLUME *vol;
  379. NUTASSERT(nfp != NULL);
  380. NUTASSERT(nfp->nf_dev != NULL);
  381. vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
  382. return vol->vol_sect_cnt * vol->vol_sect_len;
  383. }
  384. /*!
  385. * \brief Move file pointer to a specified position.
  386. *
  387. * Moving beyond the current file size is not supported.
  388. *
  389. * \param nfp File descriptor.
  390. * \param pos Requested file position.
  391. * \param whence Positioning directive.
  392. *
  393. * \return 0 on success, -1 otherwise. In the latter case the position
  394. * is unspecified.
  395. */
  396. static int RawFsFileSeek(NUTFILE * nfp, long *pos, int whence)
  397. {
  398. int rc = 0;
  399. long npos;
  400. RAWFILE *fcb;
  401. NUTASSERT(nfp != NULL);
  402. NUTASSERT(nfp->nf_fcb != NULL);
  403. fcb = nfp->nf_fcb;
  404. NUTASSERT(pos != NULL);
  405. npos = *pos;
  406. switch (whence) {
  407. case SEEK_CUR:
  408. /* Relative to current position. */
  409. npos += fcb->f_pos;
  410. break;
  411. case SEEK_END:
  412. /* Relative to file end. */
  413. npos += RawFsFileSize(nfp);
  414. break;
  415. }
  416. /* Make sure that we are within limits. */
  417. if (npos < 0 || npos > RawFsFileSize(nfp)) {
  418. errno = EINVAL;
  419. rc = -1;
  420. } else {
  421. RAWVOLUME *vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
  422. NUTASSERT(nfp != NULL);
  423. NUTASSERT(nfp != NULL);
  424. vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
  425. *pos = npos;
  426. fcb->f_pos = npos;
  427. fcb->f_sect_num = 0;
  428. while (npos >= (long)vol->vol_sect_len) {
  429. fcb->f_sect_num++;
  430. npos -= vol->vol_sect_len;
  431. }
  432. fcb->f_sect_pos = npos;
  433. }
  434. return rc;
  435. }
  436. /*!
  437. * \brief Unmount a raw volume.
  438. *
  439. * This routine is called by the block device driver while unmounting a
  440. * partition.
  441. *
  442. * \param dev Specifies the file system device.
  443. *
  444. * \return 0 on success or -1 in case of an error.
  445. */
  446. int RawFsUnmount(NUTDEVICE * dev)
  447. {
  448. RAWVOLUME *vol;
  449. NUTASSERT(dev != NULL);
  450. vol = (RAWVOLUME *) dev->dev_dcb;
  451. /* Flush sector buffer. */
  452. RawFsSectorFlush(dev);
  453. /* Release the volume information structure */
  454. if (vol) {
  455. free(vol);
  456. }
  457. return 0;
  458. }
  459. /*!
  460. * \brief Mount a raw volume.
  461. *
  462. * This routine is called by the block device driver while mounting a
  463. * partition.
  464. *
  465. * The routine may also initializes any caching mechanism. Thus, it must
  466. * be called before any other read or write access.
  467. *
  468. * \param dev Specifies the file system device.
  469. * \param blkmnt Handle of the block device's partition mount.
  470. * \param part_type Partition type, ignored.
  471. *
  472. * \return 0 on success or -1 in case of an error.
  473. */
  474. int RawFsMount(NUTDEVICE * dev, NUTFILE * blkmnt, uint8_t part_type)
  475. {
  476. BLKPAR_INFO pari;
  477. RAWVOLUME *vol;
  478. NUTASSERT(blkmnt != NULL);
  479. NUTASSERT(blkmnt->nf_dev != NULL);
  480. NUTASSERT(dev != NULL);
  481. /* Allocate the volume information structure */
  482. if ((dev->dev_dcb = malloc(sizeof(RAWVOLUME))) == 0) {
  483. return -1;
  484. }
  485. vol = (RAWVOLUME *) memset(dev->dev_dcb, 0, sizeof(RAWVOLUME));
  486. /*
  487. * Query information from the block device driver.
  488. */
  489. pari.par_nfp = blkmnt;
  490. if ((*blkmnt->nf_dev->dev_ioctl) (blkmnt->nf_dev, NUTBLKDEV_INFO, &pari)) {
  491. free(vol);
  492. errno = ENODEV;
  493. return -1;
  494. }
  495. vol->vol_sect_num = pari.par_nblks;
  496. vol->vol_sect_cnt = pari.par_nblks;
  497. vol->vol_sect_len = (size_t) pari.par_blksz;
  498. vol->vol_sect_buf = pari.par_blkbp;
  499. /* Initialize mutual exclusion semaphores. */
  500. NutEventPost(&vol->vol_fsmutex);
  501. NutEventPost(&vol->vol_iomutex);
  502. dev->dev_icb = blkmnt;
  503. return 0;
  504. }
  505. /*!
  506. * \brief File system specific functions.
  507. *
  508. * \param dev Identifies the file system device that receives the
  509. * control function.
  510. * \param req Requested control function. May be set to one of the
  511. * following constants:
  512. * - FS_FILE_SEEK
  513. * - FS_VOL_MOUNT, conf points to an FSCP_VOL_MOUNT structure.
  514. * - FS_VOL_UNMOUNT, conf should be a NULL pointer.
  515. * \param conf Points to a buffer that contains any data required for
  516. * the given control function or receives data from that
  517. * function.
  518. *
  519. * \return 0 on success, -1 otherwise.
  520. */
  521. static int RawFsIOCtl(NUTDEVICE * dev, int req, void *conf)
  522. {
  523. int rc = -1;
  524. switch (req) {
  525. case FS_FILE_SEEK:
  526. NUTASSERT(conf != NULL);
  527. RawFsFileSeek((NUTFILE *) ((IOCTL_ARG3 *) conf)->arg1, /* */
  528. (long *) ((IOCTL_ARG3 *) conf)->arg2, /* */
  529. (int) ((IOCTL_ARG3 *) conf)->arg3);
  530. break;
  531. case FS_VOL_MOUNT:
  532. {
  533. /* Mount a volume. */
  534. FSCP_VOL_MOUNT *par = (FSCP_VOL_MOUNT *) conf;
  535. NUTASSERT(par != NULL);
  536. NUTASSERT(dev != NULL);
  537. rc = RawFsMount(dev, par->fscp_bmnt, par->fscp_part_type);
  538. if (rc) {
  539. /* Release resources on failures. */
  540. RawFsUnmount(dev);
  541. }
  542. }
  543. break;
  544. case FS_VOL_UNMOUNT:
  545. /* Unmount a volume. */
  546. NUTASSERT(dev != NULL);
  547. rc = RawFsUnmount(dev);
  548. break;
  549. }
  550. return rc;
  551. }
  552. /*!
  553. * \brief Initialize the raw device file system driver.
  554. *
  555. * This routine is called during device registration.
  556. *
  557. * \param dev Specifies the file system device.
  558. *
  559. * \return Zero on success. Otherwise an error code is returned.
  560. */
  561. static int RawFsInit(NUTDEVICE * dev)
  562. {
  563. /* Nothing to do. */
  564. return 0;
  565. }
  566. /*!
  567. * \brief Reentrant variant of RawFsFileOpen().
  568. */
  569. static NUTFILE *RawFsApiFileOpen(NUTDEVICE * dev, const char *path, int mode, int acc)
  570. {
  571. NUTFILE *rc;
  572. RAWVOLUME *vol;
  573. NUTASSERT(dev != NULL);
  574. vol = (RAWVOLUME *) dev->dev_dcb;
  575. NUTASSERT(vol != NULL);
  576. /* Lock filesystem access. */
  577. NutEventWait(&vol->vol_fsmutex, 0);
  578. /* Call worker routine. */
  579. rc = RawFsFileOpen(dev, path, mode, acc);
  580. /* Release filesystem lock. */
  581. NutEventPost(&vol->vol_fsmutex);
  582. return rc;
  583. }
  584. /*!
  585. * \brief Reentrant variant of RawFsFileClose().
  586. */
  587. static int RawFsApiFileClose(NUTFILE * nfp)
  588. {
  589. int rc;
  590. RAWVOLUME *vol;
  591. NUTASSERT(nfp != NULL);
  592. NUTASSERT(nfp->nf_dev != NULL);
  593. vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
  594. NUTASSERT(vol != NULL);
  595. /* Lock filesystem access. */
  596. NutEventWait(&vol->vol_fsmutex, 0);
  597. /* Call worker routine. */
  598. rc = RawFsFileClose(nfp);
  599. /* Release filesystem lock. */
  600. NutEventPost(&vol->vol_fsmutex);
  601. return rc;
  602. }
  603. /*!
  604. * \brief Reentrant variant of RawFsFileWrite().
  605. */
  606. static int RawFsApiFileWrite(NUTFILE * nfp, const void *buffer, int len)
  607. {
  608. int rc;
  609. RAWVOLUME *vol;
  610. NUTASSERT(nfp != NULL);
  611. NUTASSERT(nfp->nf_dev != NULL);
  612. vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
  613. NUTASSERT(vol != NULL);
  614. /* Lock filesystem access. */
  615. NutEventWait(&vol->vol_fsmutex, 0);
  616. /* Call worker routine. */
  617. rc = RawFsFileWrite(nfp, buffer, len);
  618. /* Release filesystem lock. */
  619. NutEventPost(&vol->vol_fsmutex);
  620. return rc;
  621. }
  622. #ifdef __HARVARD_ARCH__
  623. /*!
  624. * \brief Reentrant variant of RawFsFileWrite_P().
  625. */
  626. static int RawFsApiFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
  627. {
  628. int rc;
  629. RAWVOLUME *vol;
  630. NUTASSERT(nfp != NULL);
  631. NUTASSERT(nfp->nf_dev != NULL);
  632. vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
  633. NUTASSERT(vol != NULL);
  634. /* Lock filesystem access. */
  635. NutEventWait(&vol->vol_fsmutex, 0);
  636. /* Call worker routine. */
  637. rc = RawFsFileWrite_P(nfp, buffer, len);
  638. /* Release filesystem lock. */
  639. NutEventPost(&vol->vol_fsmutex);
  640. return rc;
  641. }
  642. #endif
  643. /*!
  644. * \brief Reentrant variant of RawFsFileRead().
  645. */
  646. static int RawFsApiFileRead(NUTFILE * nfp, void *buffer, int size)
  647. {
  648. int rc;
  649. RAWVOLUME *vol;
  650. NUTASSERT(nfp != NULL);
  651. NUTASSERT(nfp->nf_dev != NULL);
  652. vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
  653. NUTASSERT(vol != NULL);
  654. /* Lock filesystem access. */
  655. NutEventWait(&vol->vol_fsmutex, 0);
  656. /* Call worker routine. */
  657. rc = RawFsFileRead(nfp, buffer, size);
  658. /* Release filesystem lock. */
  659. NutEventPost(&vol->vol_fsmutex);
  660. return rc;
  661. }
  662. /*!
  663. * \brief Reentrant variant of RawFsIOCtl().
  664. */
  665. static int RawFsApiIOCtl(NUTDEVICE * dev, int req, void *conf)
  666. {
  667. int rc;
  668. RAWVOLUME *vol;
  669. NUTASSERT(dev != NULL);
  670. vol = (RAWVOLUME *) dev->dev_dcb;
  671. /* Lock filesystem access. */
  672. if (req != FS_VOL_MOUNT && vol) {
  673. NutEventWait(&vol->vol_fsmutex, 0);
  674. }
  675. /* Call worker routine. */
  676. rc = RawFsIOCtl(dev, req, conf);
  677. /* Release filesystem lock. */
  678. if (req != FS_VOL_MOUNT && req != FS_VOL_UNMOUNT && vol) {
  679. NutEventPost(&vol->vol_fsmutex);
  680. }
  681. return rc;
  682. }
  683. /*!
  684. * \brief Raw device file system driver information structure.
  685. *
  686. * A pointer to this structure must be passed to NutRegisterDevice()
  687. * to bind this file system driver to the Nut/OS kernel.
  688. * An application may then call
  689. * /verbatim
  690. * _open("AT45D0:0/RAWFS0", _O_RDWR | _O_BINARY);
  691. * /endverbatim
  692. * to mount the file system on the previously registered block
  693. * device (devSpiAt45d0 in this example).
  694. */
  695. NUTDEVICE devRawFs0 = {
  696. 0, /*!< Pointer to next device, dev_next. */
  697. {'R', 'A', 'W', 'F', 'S', '0', 0, 0, 0}
  698. , /*!< Unique device name, dev_name. */
  699. IFTYP_FS, /*!< Type of device, dev_type. Obsolete. */
  700. 0, /*!< Base address, dev_base. Unused. */
  701. 0, /*!< First interrupt number, dev_irq. Unused. */
  702. 0, /*!< Mounted block device partition, dev_icb. */
  703. 0, /*!< Volume information, dev_dcb. */
  704. RawFsInit, /*!< Driver initialization routine, dev_init. */
  705. RawFsApiIOCtl, /*!< Driver specific control function, dev_ioctl. */
  706. RawFsApiFileRead, /*!< Read data from a file, dev_read. */
  707. RawFsApiFileWrite, /*!< Write data to a file, dev_write. */
  708. #ifdef __HARVARD_ARCH__
  709. RawFsApiFileWrite_P, /*!< Write data from program space to a file, dev_write_P. */
  710. #endif
  711. RawFsApiFileOpen, /*!< Open a file, dev_open. */
  712. RawFsApiFileClose, /*!< Close a file, dev_close. */
  713. RawFsFileSize, /*!< Return file size, dev_size. */
  714. NULL, /*!< Select function, optional, not yet implemented */
  715. };
  716. /*@}*/