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