00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00049 #include <dev/blockdev.h>
00050 #include <sys/event.h>
00051 #include <sys/nutdebug.h>
00052
00053 #include <fs/fs.h>
00054
00055 #include <stdlib.h>
00056 #include <string.h>
00057 #include <errno.h>
00058 #include <memdebug.h>
00059
00060 #include <fs/rawfs.h>
00061
00062 #if 0
00063
00064 #define NUTDEBUG
00065 #include <stdio.h>
00066 #endif
00067
00068 #ifndef SEEK_SET
00069 # define SEEK_SET 0
00070 # define SEEK_CUR 1
00071 # define SEEK_END 2
00072 #endif
00073
00078
00088 static int RawFsSectorFlush(NUTDEVICE * dev)
00089 {
00090 int rc = 0;
00091 RAWVOLUME *vol = (RAWVOLUME *) dev->dev_dcb;
00092
00093
00094 if (vol->vol_sect_dirty) {
00095 BLKPAR_SEEK pars;
00096 NUTFILE *blkmnt = dev->dev_icb;
00097 NUTDEVICE *blkdev = blkmnt->nf_dev;
00098
00099
00100 pars.par_nfp = blkmnt;
00101 pars.par_blknum = vol->vol_sect_num;
00102 rc = (*blkdev->dev_ioctl) (blkdev, NUTBLKDEV_SEEK, &pars);
00103 if (rc == 0) {
00104
00105 if ((*blkdev->dev_write) (blkmnt, vol->vol_sect_buf, 1) == 1) {
00106
00107 vol->vol_sect_dirty = 0;
00108 } else {
00109 rc = -1;
00110 }
00111 }
00112 }
00113 return rc;
00114 }
00115
00124 static int RawFsSectorLoad(NUTDEVICE * dev, uint32_t sect)
00125 {
00126 int rc = -1;
00127 RAWVOLUME *vol;
00128
00129 NUTASSERT(dev != NULL);
00130 vol = (RAWVOLUME *) dev->dev_dcb;
00131
00132
00133 NUTASSERT(vol != NULL);
00134 NutEventWait(&vol->vol_iomutex, 0);
00135
00136
00137 if (vol->vol_sect_num == sect) {
00138 rc = 0;
00139 }
00140
00141 else if (RawFsSectorFlush(dev) == 0) {
00142 NUTFILE *blkmnt = dev->dev_icb;
00143 NUTDEVICE *blkdev = blkmnt->nf_dev;
00144 BLKPAR_SEEK pars;
00145
00146 blkmnt = dev->dev_icb;
00147 NUTASSERT(blkmnt != NULL);
00148 blkdev = blkmnt->nf_dev;
00149 NUTASSERT(blkdev != NULL);
00150
00151
00152 pars.par_nfp = blkmnt;
00153 pars.par_blknum = sect;
00154 if ((*blkdev->dev_ioctl) (blkdev, NUTBLKDEV_SEEK, &pars) == 0) {
00155
00156 if ((*blkdev->dev_read) (blkmnt, vol->vol_sect_buf, 1) == 1) {
00157 vol->vol_sect_num = sect;
00158 rc = 0;
00159 }
00160 }
00161 }
00162
00163
00164 NutEventPostAsync(&vol->vol_iomutex);
00165
00166 return rc;
00167 }
00168
00176 static int RawFsFileFlush(NUTFILE * nfp)
00177 {
00178 int rc;
00179 NUTDEVICE *dev;
00180 RAWVOLUME *vol;
00181
00182 NUTASSERT(nfp != NULL);
00183 dev = nfp->nf_dev;
00184 NUTASSERT(dev != NULL);
00185 vol = (RAWVOLUME *) dev->dev_dcb;
00186 NUTASSERT(vol != NULL);
00187
00188
00189 NutEventWait(&vol->vol_iomutex, 0);
00190
00191 rc = RawFsSectorFlush(nfp->nf_dev);
00192
00193 NutEventPost(&vol->vol_iomutex);
00194
00195 return rc;
00196 }
00197
00214 NUTFILE *RawFsFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
00215 {
00216 NUTFILE *nfp;
00217 RAWFILE *fcb;
00218
00219
00220 fcb = malloc(sizeof(RAWFILE));
00221 if (fcb) {
00222 memset(fcb, 0, sizeof(RAWFILE));
00223 fcb->f_mode = mode;
00224
00225 nfp = malloc(sizeof(NUTFILE));
00226 if (nfp) {
00227 nfp->nf_next = 0;
00228 nfp->nf_dev = dev;
00229 nfp->nf_fcb = fcb;
00230
00231 return nfp;
00232 }
00233 free(fcb);
00234 }
00235
00236 return NUTFILE_EOF;
00237 }
00238
00247 int RawFsFileClose(NUTFILE * nfp)
00248 {
00249 int rc;
00250
00251 NUTASSERT(nfp != NULL);
00252
00253 rc = RawFsFileFlush(nfp);
00254 if (nfp->nf_fcb) {
00255 free(nfp->nf_fcb);
00256 }
00257 free(nfp);
00258
00259 return rc;
00260 }
00261
00274 int RawFsFileWrite(NUTFILE * nfp, CONST void *buffer, int len)
00275 {
00276 int rc;
00277 int step;
00278 uint8_t *buf;
00279 RAWFILE *fcb;
00280 RAWVOLUME *vol;
00281
00282 NUTASSERT(nfp != NULL);
00283
00284
00285 if (buffer == NULL || len == 0) {
00286 return RawFsFileFlush(nfp);
00287 }
00288
00289
00290 NUTASSERT(nfp->nf_fcb != NULL);
00291 NUTASSERT(nfp->nf_dev != NULL);
00292 NUTASSERT(nfp->nf_dev->dev_dcb != NULL);
00293
00294 fcb = (RAWFILE *) nfp->nf_fcb;
00295 vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
00296
00297
00298
00299
00300 buf = (uint8_t *) buffer;
00301 for (rc = 0, step = 0; rc < len; rc += step) {
00302
00303 if (fcb->f_sect_pos >= vol->vol_sect_len) {
00304
00305 fcb->f_sect_num++;
00306 fcb->f_sect_pos -= vol->vol_sect_len;
00307 }
00308
00309 if (RawFsSectorLoad(nfp->nf_dev, fcb->f_sect_num)) {
00310 rc = -1;
00311 break;
00312 }
00313
00314 step = (int) (vol->vol_sect_len - fcb->f_sect_pos);
00315 if (step > len - rc) {
00316 step = len - rc;
00317 }
00318
00319 memcpy(&vol->vol_sect_buf[fcb->f_sect_pos], &buf[rc], step);
00320 vol->vol_sect_dirty = 1;
00321
00322 fcb->f_pos += step;
00323 fcb->f_sect_pos += step;
00324 }
00325 return rc;
00326 }
00327
00328 #ifdef __HARVARD_ARCH__
00329
00346 int RawFsFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00347 {
00348 return -1;
00349 }
00350 #endif
00351
00363 int RawFsFileRead(NUTFILE * nfp, void *buffer, int size)
00364 {
00365 int rc;
00366 int step;
00367 uint8_t *buf;
00368 RAWVOLUME *vol;
00369 RAWFILE *fcb;
00370
00371
00372 if (buffer == NULL || size == 0) {
00373 return 0;
00374 }
00375
00376 NUTASSERT(nfp != NULL);
00377 NUTASSERT(nfp->nf_dev != NULL);
00378 fcb = nfp->nf_fcb;
00379 NUTASSERT(fcb != NULL);
00380 vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
00381 NUTASSERT(vol != NULL);
00382
00383 buf = (uint8_t *) buffer;
00384 for (rc = 0, step = 0; rc < size; rc += step) {
00385
00386 if (fcb->f_sect_pos >= vol->vol_sect_len) {
00387
00388 fcb->f_sect_num++;
00389 fcb->f_sect_pos -= vol->vol_sect_len;
00390 }
00391
00392 if (RawFsSectorLoad(nfp->nf_dev, fcb->f_sect_num)) {
00393 rc = -1;
00394 break;
00395 }
00396 step = (int) (vol->vol_sect_len - fcb->f_sect_pos);
00397 if (step > size - rc) {
00398 step = size - rc;
00399 }
00400 memcpy(&buf[rc], &vol->vol_sect_buf[fcb->f_sect_pos], step);
00401 fcb->f_pos += step;
00402 fcb->f_sect_pos += step;
00403 }
00404 return rc;
00405 }
00406
00418 static long RawFsFileSize(NUTFILE * nfp)
00419 {
00420 RAWVOLUME *vol;
00421
00422 NUTASSERT(nfp != NULL);
00423 NUTASSERT(nfp->nf_dev != NULL);
00424 vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
00425
00426 return vol->vol_sect_cnt * vol->vol_sect_len;
00427 }
00428
00441 static int RawFsFileSeek(NUTFILE * nfp, long *pos, int whence)
00442 {
00443 int rc = 0;
00444 long npos;
00445 RAWFILE *fcb;
00446
00447 NUTASSERT(nfp != NULL);
00448 NUTASSERT(nfp->nf_fcb != NULL);
00449 fcb = nfp->nf_fcb;
00450
00451 NUTASSERT(pos != NULL);
00452 npos = *pos;
00453
00454 switch (whence) {
00455 case SEEK_CUR:
00456
00457 npos += fcb->f_pos;
00458 break;
00459 case SEEK_END:
00460
00461 npos += RawFsFileSize(nfp);
00462 break;
00463 }
00464
00465
00466 if (npos < 0 || npos > RawFsFileSize(nfp)) {
00467 errno = EINVAL;
00468 rc = -1;
00469 } else {
00470 RAWVOLUME *vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
00471
00472 NUTASSERT(nfp != NULL);
00473 NUTASSERT(nfp != NULL);
00474 vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
00475
00476 *pos = npos;
00477 fcb->f_pos = npos;
00478 fcb->f_sect_num = 0;
00479 while (npos >= (long)vol->vol_sect_len) {
00480 fcb->f_sect_num++;
00481 npos -= vol->vol_sect_len;
00482 }
00483 fcb->f_sect_pos = npos;
00484 }
00485 return rc;
00486 }
00487
00498 int RawFsUnmount(NUTDEVICE * dev)
00499 {
00500 RAWVOLUME *vol;
00501
00502 NUTASSERT(dev != NULL);
00503 vol = (RAWVOLUME *) dev->dev_dcb;
00504
00505
00506 RawFsSectorFlush(dev);
00507
00508 if (vol) {
00509 free(vol);
00510 }
00511 return 0;
00512 }
00513
00529 int RawFsMount(NUTDEVICE * dev, NUTFILE * blkmnt, uint8_t part_type)
00530 {
00531 BLKPAR_INFO pari;
00532 RAWVOLUME *vol;
00533
00534 NUTASSERT(blkmnt != NULL);
00535 NUTASSERT(blkmnt->nf_dev != NULL);
00536 NUTASSERT(dev != NULL);
00537
00538
00539 if ((dev->dev_dcb = malloc(sizeof(RAWVOLUME))) == 0) {
00540 return -1;
00541 }
00542 vol = (RAWVOLUME *) memset(dev->dev_dcb, 0, sizeof(RAWVOLUME));
00543
00544
00545
00546
00547 pari.par_nfp = blkmnt;
00548 if ((*blkmnt->nf_dev->dev_ioctl) (blkmnt->nf_dev, NUTBLKDEV_INFO, &pari)) {
00549 free(vol);
00550 errno = ENODEV;
00551 return -1;
00552 }
00553 vol->vol_sect_num = pari.par_nblks;
00554 vol->vol_sect_cnt = pari.par_nblks;
00555 vol->vol_sect_len = (size_t) pari.par_blksz;
00556 vol->vol_sect_buf = pari.par_blkbp;
00557
00558
00559 NutEventPost(&vol->vol_fsmutex);
00560 NutEventPost(&vol->vol_iomutex);
00561
00562 dev->dev_icb = blkmnt;
00563
00564 return 0;
00565 }
00566
00583 static int RawFsIOCtl(NUTDEVICE * dev, int req, void *conf)
00584 {
00585 int rc = -1;
00586
00587 switch (req) {
00588 case FS_FILE_SEEK:
00589 NUTASSERT(conf != NULL);
00590 RawFsFileSeek((NUTFILE *) ((IOCTL_ARG3 *) conf)->arg1,
00591 (long *) ((IOCTL_ARG3 *) conf)->arg2,
00592 (int) ((IOCTL_ARG3 *) conf)->arg3);
00593 break;
00594 case FS_VOL_MOUNT:
00595 {
00596
00597 FSCP_VOL_MOUNT *par = (FSCP_VOL_MOUNT *) conf;
00598
00599 NUTASSERT(par != NULL);
00600 NUTASSERT(dev != NULL);
00601 rc = RawFsMount(dev, par->fscp_bmnt, par->fscp_part_type);
00602 if (rc) {
00603
00604 RawFsUnmount(dev);
00605 }
00606 }
00607 break;
00608 case FS_VOL_UNMOUNT:
00609
00610 NUTASSERT(dev != NULL);
00611 rc = RawFsUnmount(dev);
00612 break;
00613 }
00614 return rc;
00615 }
00616
00626 static int RawFsInit(NUTDEVICE * dev)
00627 {
00628
00629 return 0;
00630 }
00631
00635 static NUTFILE *RawFsApiFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
00636 {
00637 NUTFILE *rc;
00638 RAWVOLUME *vol;
00639
00640 NUTASSERT(dev != NULL);
00641 vol = (RAWVOLUME *) dev->dev_dcb;
00642 NUTASSERT(vol != NULL);
00643
00644
00645 NutEventWait(&vol->vol_fsmutex, 0);
00646
00647 rc = RawFsFileOpen(dev, path, mode, acc);
00648
00649 NutEventPost(&vol->vol_fsmutex);
00650
00651 return rc;
00652 }
00653
00657 static int RawFsApiFileClose(NUTFILE * nfp)
00658 {
00659 int rc;
00660 RAWVOLUME *vol;
00661
00662 NUTASSERT(nfp != NULL);
00663 NUTASSERT(nfp->nf_dev != NULL);
00664 vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
00665 NUTASSERT(vol != NULL);
00666
00667
00668 NutEventWait(&vol->vol_fsmutex, 0);
00669
00670 rc = RawFsFileClose(nfp);
00671
00672 NutEventPost(&vol->vol_fsmutex);
00673
00674 return rc;
00675 }
00676
00680 static int RawFsApiFileWrite(NUTFILE * nfp, CONST void *buffer, int len)
00681 {
00682 int rc;
00683 RAWVOLUME *vol;
00684
00685 NUTASSERT(nfp != NULL);
00686 NUTASSERT(nfp->nf_dev != NULL);
00687 vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
00688 NUTASSERT(vol != NULL);
00689
00690
00691 NutEventWait(&vol->vol_fsmutex, 0);
00692
00693 rc = RawFsFileWrite(nfp, buffer, len);
00694
00695 NutEventPost(&vol->vol_fsmutex);
00696
00697 return rc;
00698 }
00699
00700 #ifdef __HARVARD_ARCH__
00701
00704 static int RawFsApiFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
00705 {
00706 int rc;
00707 RAWVOLUME *vol;
00708
00709 NUTASSERT(nfp != NULL);
00710 NUTASSERT(nfp->nf_dev != NULL);
00711 vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
00712 NUTASSERT(vol != NULL);
00713
00714
00715 NutEventWait(&vol->vol_fsmutex, 0);
00716
00717 rc = RawFsFileWrite_P(nfp, buffer, len);
00718
00719 NutEventPost(&vol->vol_fsmutex);
00720
00721 return rc;
00722 }
00723 #endif
00724
00728 static int RawFsApiFileRead(NUTFILE * nfp, void *buffer, int size)
00729 {
00730 int rc;
00731 RAWVOLUME *vol;
00732
00733 NUTASSERT(nfp != NULL);
00734 NUTASSERT(nfp->nf_dev != NULL);
00735 vol = (RAWVOLUME *) nfp->nf_dev->dev_dcb;
00736 NUTASSERT(vol != NULL);
00737
00738
00739 NutEventWait(&vol->vol_fsmutex, 0);
00740
00741 rc = RawFsFileRead(nfp, buffer, size);
00742
00743 NutEventPost(&vol->vol_fsmutex);
00744
00745 return rc;
00746 }
00747
00751 static int RawFsApiIOCtl(NUTDEVICE * dev, int req, void *conf)
00752 {
00753 int rc;
00754 RAWVOLUME *vol;
00755
00756 NUTASSERT(dev != NULL);
00757 vol = (RAWVOLUME *) dev->dev_dcb;
00758
00759
00760 if (req != FS_VOL_MOUNT && vol) {
00761 NutEventWait(&vol->vol_fsmutex, 0);
00762 }
00763
00764 rc = RawFsIOCtl(dev, req, conf);
00765
00766 if (req != FS_VOL_MOUNT && req != FS_VOL_UNMOUNT && vol) {
00767 NutEventPost(&vol->vol_fsmutex);
00768 }
00769 return rc;
00770 }
00771
00784 NUTDEVICE devRawFs0 = {
00785 0,
00786 {'R', 'A', 'W', 'F', 'S', '0', 0, 0, 0}
00787 ,
00788 IFTYP_FS,
00789 0,
00790 0,
00791 0,
00792 0,
00793 RawFsInit,
00794 RawFsApiIOCtl,
00795 RawFsApiFileRead,
00796 RawFsApiFileWrite,
00797 #ifdef __HARVARD_ARCH__
00798 RawFsApiFileWrite_P,
00799 #endif
00800 RawFsApiFileOpen,
00801 RawFsApiFileClose,
00802 RawFsFileSize
00803 };
00804