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 #include <fs/fs.h>
00036 #include <sys/nutdebug.h>
00037 
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <fcntl.h>
00041 #include <sys/stat.h>
00042 #include <string.h>
00043 #include <errno.h>
00044 #include <dirent.h>
00045 
00046 #include <dev/spi_at45dib.h>
00047 #include <fs/uflashfs.h>
00048 
00049 #if 0
00050 
00051 #define NUTDEBUG
00052 #include <stdio.h>
00053 #endif
00054 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00097 
00098 
00099 #ifndef UFLASH_MAX_BLOCKS
00100 
00101 #define UFLASH_MAX_BLOCKS       8192
00102 #endif
00103 
00104 #ifndef UFLASH_BLOCK_UNITS
00105 
00106 #define UFLASH_BLOCK_UNITS      4
00107 #endif
00108 
00109 #ifndef UFLASH_ENTRIES
00110 
00111 #define UFLASH_ENTRIES          128
00112 #endif
00113 
00114 #ifndef UFLASH_USAGE_CACHE
00115 
00116 #define UFLASH_USAGE_CACHE      32
00117 #endif
00118 
00119 #if UFLASH_MAX_BLOCKS <= 255
00120 typedef uint8_t blknum_t;
00121 typedef uint_fast8_t blknum_fast_t;
00122 #elif UFLASH_MAX_BLOCKS <= 65535
00123 typedef uint16_t blknum_t;
00124 typedef uint_fast16_t blknum_fast_t;
00125 #else
00126 typedef uint32_t blknum_t;
00127 typedef uint_fast32_t blknum_fast_t;
00128 #endif
00129 
00130 #ifndef UFLASH_MAX_PATH
00131 
00138 #define UFLASH_MAX_PATH      0
00139 #endif
00140 
00141 #define UFLASH_BLOCK_INVALID    ((blknum_t)-1)
00142 
00146 typedef struct _BLOCK_USAGE {
00147     uint8_t use_cnt;
00148     blknum_t use_phyblk;
00149 } BLOCK_USAGE;
00150 
00154 static BLOCK_USAGE min_used[UFLASH_USAGE_CACHE];
00155 
00161 typedef struct __attribute__ ((packed)) _BLOCKHEAD {
00162     blknum_t bh_logblk;         
00163     blknum_t bh_version;        
00164     blknum_t bh_entblk;         
00165     blknum_t bh_entseq;         
00166 } BLOCKHEAD;
00167 
00173 typedef struct __attribute__ ((packed)) _BLOCKFOOT {
00174 #ifdef UFLASH_USE_TIMESTAMP
00175     time_t bf_time;             
00176 #endif
00177     uint8_t bf_wear;            
00178 } BLOCKFOOT;
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 
00187 
00188 typedef struct __attribute__ ((packed)) _ENTRYHEAD {
00189     
00190     uint8_t eh_attr;
00191     
00192     uint8_t eh_nlen;
00193 } ENTRYHEAD;
00194 
00198 typedef struct _UFLASHENTRY {
00200     blknum_t ent_id;
00202     uint32_t ent_pos;
00204     blknum_t ent_bidx;
00206     uint16_t ent_sidx;
00208     uint16_t ent_uidx;
00210     uint16_t ent_upos;
00211 
00213     uint32_t ent_mode;
00215     uint8_t ent_attr;
00217     uint8_t ent_namlen;
00219     uint32_t ent_size;
00220 
00222     uint16_t ent_eoff;
00223 } UFLASHENTRY;
00224 
00225 #define UFLASH_VOLF_FIXED       0x80
00226 
00228 typedef struct _UFLASHVOLUME UFLASHVOLUME;
00229 
00233 struct _UFLASHVOLUME {
00235     NUTSERIALFLASH *vol_ifc;
00237     HANDLE vol_mutex;
00239     uint8_t vol_attrib;
00241     blknum_t vol_blocks;
00243     blknum_t *vol_l2p;
00244 };
00245 
00249 typedef struct _UFLASHFIND {
00250     blknum_t uff_lbe;
00251     char *uff_path;
00252 } UFLASHFIND;
00253 
00257 static int FlashUnitCopy(NUTSERIALFLASH * ifc, blknum_t b_src, blknum_t b_dst, sf_unit_t unit)
00258 {
00259     unit += ifc->sf_rsvbot;
00260     return (*ifc->sf_copy) (ifc, b_src * UFLASH_BLOCK_UNITS + unit, b_dst * UFLASH_BLOCK_UNITS + unit);
00261 }
00262 
00266 static void FlashUnitCommit(NUTSERIALFLASH * ifc, blknum_t b, sf_unit_t unit)
00267 {
00268     (*ifc->sf_commit) (ifc, b * UFLASH_BLOCK_UNITS + unit + ifc->sf_rsvbot);
00269 }
00270 
00274 static int FlashUnitRead(NUTSERIALFLASH * ifc, blknum_t b, sf_unit_t unit, int upos, void *data, int len)
00275 {
00276     int rc = ifc->sf_unit_size - upos;
00277 
00278     if (unit == UFLASH_BLOCK_UNITS - 1) {
00279         rc -= sizeof(BLOCKFOOT);
00280     }
00281     if (rc > len) {
00282         rc = len;
00283     }
00284     (*ifc->sf_read) (ifc, b * UFLASH_BLOCK_UNITS + unit + ifc->sf_rsvbot, upos, data, rc);
00285 
00286     return rc;
00287 }
00288 
00292 static int FlashUnitWrite(NUTSERIALFLASH * ifc, blknum_t b, sf_unit_t unit, int upos, CONST void *data, int len)
00293 {
00294     int rc = ifc->sf_unit_size - upos;
00295 
00296     if (unit == UFLASH_BLOCK_UNITS - 1) {
00297         rc -= sizeof(BLOCKFOOT);
00298     }
00299     if (rc > len) {
00300         rc = len;
00301     }
00302     (*ifc->sf_write) (ifc, b * UFLASH_BLOCK_UNITS + unit + ifc->sf_rsvbot, upos, data, rc);
00303 
00304     return rc;
00305 }
00306 
00310 static int FlashCheckBlock(NUTSERIALFLASH * ifc, blknum_t b)
00311 {
00312     return (*ifc->sf_check) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, UFLASH_BLOCK_UNITS);
00313 }
00314 
00318 static int FlashReadBlockHead(NUTSERIALFLASH * ifc, blknum_t b, BLOCKHEAD * bh)
00319 {
00320     return (*ifc->sf_read) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, 0, bh, sizeof(BLOCKHEAD));
00321 }
00322 
00326 static int FlashWriteBlockHead(NUTSERIALFLASH * ifc, blknum_t b, BLOCKHEAD * bh)
00327 {
00328     
00329     bh->bh_version++;
00330     return (*ifc->sf_write) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, 0, bh, sizeof(BLOCKHEAD));
00331 }
00332 
00336 static int FlashReadEntry(NUTSERIALFLASH * ifc, blknum_t b, ENTRYHEAD * eh, char **name)
00337 {
00338     int rc;
00339 
00340     
00341     rc = (*ifc->sf_read) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD), eh, sizeof(ENTRYHEAD));
00342     if (rc == 0 && name) {
00343         *name = malloc(eh->eh_nlen + 1);
00344         if (*name == NULL) {
00345             rc = -1;
00346         } else {
00347             *(*name + eh->eh_nlen) = '\0';
00348             rc = (*ifc->sf_read) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD) + sizeof(ENTRYHEAD), *name,
00349                                   eh->eh_nlen);
00350         }
00351     }
00352     return rc;
00353 }
00354 
00358 static int FlashBlockCmpEntryName(NUTSERIALFLASH * ifc, blknum_t b, CONST char *name, uint8_t len)
00359 {
00360     return (*ifc->sf_compare) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD) + sizeof(ENTRYHEAD), name, len);
00361 }
00362 
00366 static int FlashWriteEntry(NUTSERIALFLASH * ifc, blknum_t b, CONST ENTRYHEAD * eh, CONST char *name)
00367 {
00368     int rc;
00369 
00370     rc = (*ifc->sf_write) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD), eh, sizeof(ENTRYHEAD));
00371     if (rc == 0) {
00372         rc = (*ifc->sf_write) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, sizeof(BLOCKHEAD) + sizeof(ENTRYHEAD), name,
00373                                eh->eh_nlen);
00374     }
00375     return rc;
00376 }
00377 
00381 static int FlashReadBlockFoot(NUTSERIALFLASH * ifc, blknum_t b, BLOCKFOOT * bf)
00382 {
00383     return (*ifc->sf_read) (ifc, (b + 1) * UFLASH_BLOCK_UNITS - 1 + ifc->sf_rsvbot, -(int) sizeof(BLOCKFOOT), bf,
00384                             sizeof(BLOCKFOOT));
00385 }
00386 
00390 static int FlashWriteBlockFoot(NUTSERIALFLASH * ifc, blknum_t b, BLOCKFOOT * bf)
00391 {
00392     bf->bf_wear++;
00393 #ifdef UFLASH_USE_TIMESTAMP
00394     bf->bf_time = time(NULL);
00395 #endif
00396     return (*ifc->sf_write) (ifc, (b + 1) * UFLASH_BLOCK_UNITS - 1 + ifc->sf_rsvbot, -(int) sizeof(BLOCKFOOT), bf,
00397                              sizeof(BLOCKFOOT));
00398 }
00399 
00403 static int FlashEraseEntry(NUTSERIALFLASH * ifc, blknum_t b)
00404 {
00405     return (*ifc->sf_erase) (ifc, b * UFLASH_BLOCK_UNITS + ifc->sf_rsvbot, 1);
00406 }
00407 
00411 static int FlashEraseBlockData(NUTSERIALFLASH * ifc, blknum_t b)
00412 {
00413     return (*ifc->sf_erase) (ifc, b * UFLASH_BLOCK_UNITS + 1 + ifc->sf_rsvbot, UFLASH_BLOCK_UNITS - 1);
00414 }
00415 
00419 static int FlashEraseBlocks(NUTSERIALFLASH * ifc, int n)
00420 {
00421     return (*ifc->sf_erase) (ifc, ifc->sf_rsvbot, n * UFLASH_BLOCK_UNITS);
00422 }
00423 
00431 static void CollectLeastUsed(UFLASHVOLUME * vol, uint8_t * usage)
00432 {
00433     uint8_t rmin;
00434     uint8_t rmax;
00435     blknum_t b;
00436 
00437     
00438     rmin = usage[0];
00439     rmax = rmin;
00440     for (b = 1; b < vol->vol_blocks; b++) {
00441         if (usage[b] < rmin) {
00442             rmin = usage[b];
00443             if (rmax - rmin >= 128) {
00444                 break;
00445             }
00446         } else if (usage[b] > rmax) {
00447             rmax = usage[b];
00448             if (rmax - rmin >= 128) {
00449                 break;
00450             }
00451         }
00452     }
00453 
00454     
00455 
00456 
00457 
00458 
00459     if (b < vol->vol_blocks) {
00460         rmax = 0;
00461         for (b = 0; b < vol->vol_blocks; b++) {
00462             usage[b] += 128;
00463             if (usage[b] > rmax) {
00464                 rmax = usage[b];
00465             }
00466         }
00467     }
00468 
00469     
00470 
00471 
00472     memset(min_used, 0xff, sizeof(min_used));
00473     for (b = 0; b < vol->vol_blocks; b++) {
00474         int j = UFLASH_USAGE_CACHE - 1;
00475 
00476         if (min_used[j].use_phyblk > vol->vol_blocks || min_used[j].use_cnt > usage[b]) {
00477             while (--j >= 0) {
00478                 if (usage[b] >= min_used[j].use_cnt && min_used[j].use_phyblk < vol->vol_blocks) {
00479                     break;
00480                 }
00481                 min_used[j + 1] = min_used[j];
00482             }
00483             min_used[j + 1].use_cnt = usage[b];
00484             min_used[j + 1].use_phyblk = b;
00485         }
00486     }
00487 }
00488 
00489 static blknum_t PhysBlkAllocate(UFLASHVOLUME * vol, int level);
00490 
00499 static int PhysBlkMove(UFLASHVOLUME * vol, blknum_t src, blknum_t dst)
00500 {
00501     int rc = 0;
00502     BLOCKHEAD bh;
00503     BLOCKFOOT bf;
00504     uint_fast8_t u;
00505 
00506     
00507     FlashReadBlockHead(vol->vol_ifc, src, &bh);
00508     
00509     FlashReadBlockFoot(vol->vol_ifc, dst, &bf);
00510     
00511     FlashEraseBlockData(vol->vol_ifc, dst);
00512     
00513     for (u = 0; rc == 0 && u < UFLASH_BLOCK_UNITS; u++) {
00514         FlashUnitCopy(vol->vol_ifc, src, dst, u);
00515         
00516         if (u == 0) {
00517             FlashWriteBlockHead(vol->vol_ifc, dst, &bh);
00518         }
00519         
00520         else if (u == UFLASH_BLOCK_UNITS - 1) {
00521             FlashWriteBlockFoot(vol->vol_ifc, dst, &bf);
00522         }
00523         
00524         FlashUnitCommit(vol->vol_ifc, dst, u);
00525     }
00526     
00527 
00528     FlashEraseEntry(vol->vol_ifc, src);
00529 
00530     return 0;
00531 }
00532 
00538 static blknum_t PhysBlkUnused(UFLASHVOLUME * vol)
00539 {
00540     BLOCKHEAD bh;
00541     blknum_t b;
00542 
00543     for (b = 0; b < vol->vol_blocks; b++) {
00544         FlashReadBlockHead(vol->vol_ifc, b, &bh);
00545         if (bh.bh_logblk >= vol->vol_blocks) {
00546             break;
00547         }
00548     }
00549     return b;
00550 }
00551 
00557 static int PhysBlkRequest(UFLASHVOLUME * vol, int level, blknum_t n)
00558 {
00559     blknum_t b;
00560 
00561     
00562     for (b = 0; b < vol->vol_blocks; b++) {
00563         if (vol->vol_l2p[b] == n) {
00564             blknum_t nn;
00565 
00566             nn = PhysBlkAllocate(vol, level + 1);
00567             if (nn >= vol->vol_blocks) {
00568                 return -1;
00569             }
00570             vol->vol_l2p[b] = nn;
00571             PhysBlkMove(vol, n, nn);
00572             break;
00573         }
00574     }
00575     return 0;
00576 }
00577 
00583 static blknum_t PhysBlkAllocate(UFLASHVOLUME * vol, int level)
00584 {
00585     uint8_t *phy_use;
00586     int i;
00587 
00588     for (;;) {
00589         if (level || min_used[UFLASH_USAGE_CACHE - (UFLASH_USAGE_CACHE / 4)].use_phyblk < vol->vol_blocks) {
00590             for (i = 0; i < UFLASH_USAGE_CACHE; i++) {
00591                 blknum_t n = min_used[i].use_phyblk;
00592 
00593                 if (n < vol->vol_blocks) {
00594                     min_used[i].use_phyblk = UFLASH_BLOCK_INVALID;
00595                     if (PhysBlkRequest(vol, level, n)) {
00596                         return UFLASH_BLOCK_INVALID;
00597                     }
00598                     return n;
00599                 }
00600             }
00601         }
00602         
00603         phy_use = calloc(vol->vol_blocks, 1);
00604         if (phy_use == NULL) {
00605             break;
00606         }
00607         for (i = 0; i < vol->vol_blocks; i++) {
00608             BLOCKFOOT bf;
00609 
00610             FlashReadBlockFoot(vol->vol_ifc, i, &bf);
00611             phy_use[i] = bf.bf_wear;
00612         }
00613         for (i = 0; i < vol->vol_blocks; i++) {
00614             if (vol->vol_l2p[i] < vol->vol_blocks) {
00615                 phy_use[vol->vol_l2p[i]] += UFLASH_USAGE_CACHE - 1;
00616             }
00617         }
00618         CollectLeastUsed(vol, phy_use);
00619         free(phy_use);
00620         if (level) {
00621             break;
00622         }
00623     }
00624     return PhysBlkUnused(vol);
00625 }
00626 
00632 static blknum_t LogBlkAllocate(UFLASHVOLUME * vol, blknum_t lb)
00633 {
00634     int lb_last = lb ? vol->vol_blocks : UFLASH_ENTRIES;
00635 
00636     
00637     for (; lb < lb_last; lb++) {
00638         if (vol->vol_l2p[lb] >= vol->vol_blocks) {
00639             
00640             vol->vol_l2p[lb] = PhysBlkAllocate(vol, 0);
00641             break;
00642         }
00643     }
00644     return lb;
00645 }
00646 
00652 static blknum_t LogBlkReallocate(UFLASHVOLUME * vol, blknum_t lb)
00653 {
00654     blknum_t b_old;
00655     blknum_t b_new;
00656 
00657     
00658 
00659     b_new = PhysBlkAllocate(vol, 0);
00660     if (b_new >= vol->vol_blocks) {
00661         b_old = b_new;
00662     } else {
00663         b_old = vol->vol_l2p[lb];
00664         vol->vol_l2p[lb] = b_new;
00665     }
00666     return b_old;
00667 }
00668 
00674 static int LogBlkRelease(UFLASHVOLUME * vol, blknum_t lb)
00675 {
00676     blknum_t b;
00677 
00678     b = vol->vol_l2p[lb];
00679     vol->vol_l2p[lb] = UFLASH_BLOCK_INVALID;
00680 
00681     return FlashEraseEntry(vol->vol_ifc, b);
00682 }
00683 
00695 static blknum_t EntrySeek(UFLASHVOLUME * vol, blknum_t lbe, blknum_t seq)
00696 {
00697     blknum_t lb = lbe;
00698 
00699     
00700 
00701     if (seq) {
00702         
00703         NutEventWait(&vol->vol_mutex, 0);
00704         
00705         for (lb = UFLASH_ENTRIES; lb < vol->vol_blocks; lb++) {
00706             blknum_t b = vol->vol_l2p[lb];
00707 
00708             
00709             if (b < vol->vol_blocks) {
00710                 BLOCKHEAD bh;
00711 
00712                 FlashReadBlockHead(vol->vol_ifc, b, &bh);
00713                 if (bh.bh_entblk == lbe && bh.bh_entseq == seq) {
00714                     
00715                     break;
00716                 }
00717             }
00718         }
00719         
00720         NutEventPost(&vol->vol_mutex);
00721     }
00722     return lb;
00723 }
00724 
00728 static void EntryPosSet(NUTFILE * nfp, long pos)
00729 {
00730     uint16_t seq;
00731     uint32_t off;
00732     UFLASHENTRY *ent;
00733     UFLASHVOLUME *vol;
00734 
00735     ent = (UFLASHENTRY *) nfp->nf_fcb;
00736     vol = (UFLASHVOLUME *) nfp->nf_dev->dev_dcb;
00737 
00738     
00739     ent->ent_pos = pos;
00740     off = ent->ent_eoff + ent->ent_pos;
00741 
00742     
00743     seq = (uint16_t) (off / (vol->vol_ifc->sf_unit_size * UFLASH_BLOCK_UNITS - (sizeof(BLOCKHEAD) + sizeof(BLOCKFOOT))));
00744     if (seq != ent->ent_sidx) {
00745         ent->ent_sidx = seq;
00746         ent->ent_bidx = UFLASH_BLOCK_INVALID;
00747     }
00748 
00749     off -= ent->ent_sidx * (vol->vol_ifc->sf_unit_size * UFLASH_BLOCK_UNITS - (sizeof(BLOCKHEAD) + sizeof(BLOCKFOOT)));
00750 
00751     
00752     ent->ent_uidx = (uint16_t) ((off + sizeof(BLOCKHEAD)) / vol->vol_ifc->sf_unit_size);
00753     off -= ent->ent_uidx * vol->vol_ifc->sf_unit_size;
00754 
00755     
00756     ent->ent_upos = (uint16_t) off + sizeof(BLOCKHEAD);
00757 }
00758 
00759 static void EntryPosInc(NUTFILE * nfp, int step)
00760 {
00761     UFLASHENTRY *ent;
00762     UFLASHVOLUME *vol;
00763 
00764     ent = (UFLASHENTRY *) nfp->nf_fcb;
00765     vol = (UFLASHVOLUME *) nfp->nf_dev->dev_dcb;
00766 
00767     ent->ent_pos += step;
00768     ent->ent_upos += step;
00769     if (ent->ent_uidx < UFLASH_BLOCK_UNITS - 1) {
00770         step = vol->vol_ifc->sf_unit_size - ent->ent_upos;
00771     } else {
00772         step = vol->vol_ifc->sf_unit_size - sizeof(BLOCKFOOT) - ent->ent_upos;
00773     }
00774     if (step == 0) {
00775         ent->ent_uidx++;
00776         if (ent->ent_uidx >= UFLASH_BLOCK_UNITS) {
00777             ent->ent_upos = sizeof(BLOCKHEAD);
00778             ent->ent_uidx = 0;
00779             ent->ent_sidx++;
00780             ent->ent_bidx = UFLASH_BLOCK_INVALID;
00781         } else {
00782             ent->ent_upos = 0;
00783         }
00784     }
00785 }
00786 
00792 static long EntryScan(UFLASHVOLUME * vol, blknum_t lbe, time_t * mod)
00793 {
00794     long siz;
00795     int p;
00796     int i;
00797     int off;
00798     BLOCKHEAD bh;
00799     blknum_t lb;
00800     blknum_t lbs = lbe;
00801     blknum_t seq = 0;
00802 
00803 #ifdef UFLASH_USE_TIMESTAMP
00804     if (mod) {
00805         BLOCKFOOT bf;
00806 
00807         FlashReadBlockFoot(vol->vol_ifc, vol->vol_l2p[lbe] / UFLASH_BLOCK_UNITS, &bf);
00808         *mod = bf.bf_time;
00809     }
00810 #endif
00811 
00812     
00813     for (lb = UFLASH_ENTRIES; lb < vol->vol_blocks; lb++) {
00814         p = vol->vol_l2p[lb];
00815         if (p < vol->vol_blocks) {
00816             p *= UFLASH_BLOCK_UNITS;
00817             FlashReadBlockHead(vol->vol_ifc, p / UFLASH_BLOCK_UNITS, &bh);
00818             if (bh.bh_entblk == lbe) {
00819                 if (seq < bh.bh_entseq) {
00820                     seq = bh.bh_entseq;
00821                     lbs = lb;
00822                 }
00823 #ifdef UFLASH_USE_TIMESTAMP
00824                 if (mod) {
00825                     BLOCKFOOT bf;
00826 
00827                     FlashReadBlockFoot(vol->vol_ifc, p / UFLASH_BLOCK_UNITS, &bf);
00828                     if (*mod < bf.bf_time) {
00829                         *mod = bf.bf_time;
00830                     }
00831                 }
00832 #endif
00833             }
00834         }
00835     }
00836     
00837     siz = seq * (vol->vol_ifc->sf_unit_size * UFLASH_BLOCK_UNITS - (sizeof(BLOCKHEAD) + sizeof(BLOCKFOOT)));
00838 
00839     
00840     p = vol->vol_l2p[lbs] * UFLASH_BLOCK_UNITS;
00841     off = -(int) sizeof(BLOCKFOOT);
00842     for (i = UFLASH_BLOCK_UNITS; --i >= 0;) {
00843         int s = (*vol->vol_ifc->sf_used) (vol->vol_ifc, p + i + vol->vol_ifc->sf_rsvbot, off);
00844 
00845         off = 0;
00846         if (s) {
00847             siz += s + i * vol->vol_ifc->sf_unit_size - sizeof(BLOCKHEAD);
00848             break;
00849         }
00850     }
00851     return siz;
00852 }
00853 
00869 static int EntrySearchNext(UFLASHVOLUME * vol, CONST char *name, ENTRYHEAD * eh, blknum_t lbs)
00870 {
00871     blknum_t lbe;
00872     blknum_t b;
00873     int nlen;
00874 
00875     nlen = strlen(name);
00876     
00877     NutEventWait(&vol->vol_mutex, 0);
00878     for (lbe = lbs == UFLASH_ENTRIES ? 0 : lbs; lbe < UFLASH_ENTRIES; lbe++) {
00879         b = vol->vol_l2p[lbe];
00880         if (b < vol->vol_blocks) {
00881             
00882             if (FlashReadEntry(vol->vol_ifc, b, eh, NULL) == 0) {
00883                 
00884                 if (eh->eh_nlen == nlen || (lbs != UFLASH_ENTRIES && eh->eh_nlen >= nlen)) {
00885                     if (FlashBlockCmpEntryName(vol->vol_ifc, b, name, nlen) == 0) {
00886                         NutEventPost(&vol->vol_mutex);
00887                         return lbe;
00888                     }
00889                 }
00890             }
00891         }
00892     }
00893     NutEventPost(&vol->vol_mutex);
00894     return UFLASH_ENTRIES;
00895 }
00896 
00902 static int EntrySearch(UFLASHVOLUME * vol, CONST char *name, ENTRYHEAD * eh)
00903 {
00904     return EntrySearchNext(vol, name, eh, UFLASH_ENTRIES);
00905 }
00906 
00912 static int EntryTruncateSeq(UFLASHVOLUME * vol, int lbe)
00913 {
00914     blknum_t lb;
00915     BLOCKHEAD bh;
00916 
00917     for (lb = UFLASH_ENTRIES; lb < vol->vol_blocks; lb++) {
00918         if (vol->vol_l2p[lb] < vol->vol_blocks) {
00919             FlashReadBlockHead(vol->vol_ifc, vol->vol_l2p[lb], &bh);
00920             if (bh.bh_entblk == lbe) {
00921                 LogBlkRelease(vol, lb);
00922             }
00923         }
00924     }
00925     return 0;
00926 }
00927 
00933 static int EntryTruncate(UFLASHVOLUME * vol, blknum_t lbe)
00934 {
00935     BLOCKHEAD bh;
00936     ENTRYHEAD eh;
00937     BLOCKFOOT bf;
00938     blknum_t b;
00939     blknum_t b_old;
00940     char *name = NULL;
00941 
00942     EntryTruncateSeq(vol, lbe);
00943 
00944     
00945     b = PhysBlkAllocate(vol, 0);
00946     if (b >= vol->vol_blocks) {
00947         return -1;
00948     }
00949     b_old = vol->vol_l2p[lbe];
00950 
00951     vol->vol_l2p[lbe] = b;
00952 
00953     
00954     FlashReadBlockFoot(vol->vol_ifc, b, &bf);
00955     FlashEraseBlockData(vol->vol_ifc, b);
00956 
00957     
00958 
00959 
00960     FlashReadBlockHead(vol->vol_ifc, b_old, &bh);
00961     FlashReadEntry(vol->vol_ifc, b_old, &eh, &name);
00962     FlashWriteBlockHead(vol->vol_ifc, b, &bh);
00963     FlashWriteEntry(vol->vol_ifc, b, &eh, name);
00964     FlashUnitCommit(vol->vol_ifc, b, 0);
00965 
00966     
00967     FlashWriteBlockFoot(vol->vol_ifc, b, &bf);
00968     FlashUnitCommit(vol->vol_ifc, b, UFLASH_BLOCK_UNITS - 1);
00969 
00970     
00971     FlashEraseEntry(vol->vol_ifc, b_old);
00972 
00973     return 0;
00974 }
00975 
00981 static int EntryCreate(UFLASHVOLUME * vol, blknum_t lbe, ENTRYHEAD * eh, CONST char *name)
00982 {
00983     BLOCKHEAD bh;
00984     BLOCKFOOT bf;
00985     blknum_t b;
00986 
00987     b = vol->vol_l2p[lbe];
00988 
00989     
00990     FlashReadBlockFoot(vol->vol_ifc, b, &bf);
00991     FlashEraseBlockData(vol->vol_ifc, b);
00992 
00993     
00994     bh.bh_logblk = lbe;
00995     bh.bh_version = UFLASH_BLOCK_INVALID;
00996     bh.bh_entblk = lbe;
00997     bh.bh_entseq = 0;
00998     FlashWriteBlockHead(vol->vol_ifc, b, &bh);
00999 
01000     
01001     FlashWriteEntry(vol->vol_ifc, b, eh, name);
01002     FlashUnitCommit(vol->vol_ifc, b, 0);
01003 
01004     
01005     FlashWriteBlockFoot(vol->vol_ifc, b, &bf);
01006     FlashUnitCommit(vol->vol_ifc, b, UFLASH_BLOCK_UNITS - 1);
01007 
01008     return 0;
01009 }
01010 
01014 static int UFlashFileRemove(NUTDEVICE * dev, CONST char *name)
01015 {
01016     blknum_t lbe;
01017     ENTRYHEAD eh;
01018     UFLASHVOLUME *vol;
01019 
01020     vol = (UFLASHVOLUME *) dev->dev_dcb;
01021 
01022     while (*name == '/') {
01023         name++;
01024     }
01025     lbe = EntrySearch(vol, name, &eh);
01026     if (lbe >= UFLASH_ENTRIES || vol->vol_l2p[lbe] > vol->vol_blocks) {
01027         return -1;
01028     }
01029     NutEventWait(&vol->vol_mutex, 0);
01030     EntryTruncateSeq(vol, lbe);
01031     LogBlkRelease(vol, lbe);
01032     NutEventPost(&vol->vol_mutex);
01033 
01034     return 0;
01035 }
01036 
01040 static int UFlashFileStatus(NUTDEVICE * dev, CONST char *name, struct stat *st)
01041 {
01042     blknum_t lbe;
01043     ENTRYHEAD eh;
01044     UFLASHVOLUME *vol;
01045     uint_fast8_t partial = 0;
01046 
01047     vol = (UFLASHVOLUME *) dev->dev_dcb;
01048 
01049     while (*name == '/') {
01050         name++;
01051     }
01052     lbe = EntrySearch(vol, name, &eh);
01053     if (lbe >= UFLASH_ENTRIES || vol->vol_l2p[lbe] > vol->vol_blocks) {
01054         lbe = EntrySearchNext(vol, name, &eh, 0);
01055         if (lbe >= UFLASH_ENTRIES || vol->vol_l2p[lbe] > vol->vol_blocks) {
01056             return -1;
01057         }
01058         partial = 1;
01059     }
01060     memset(st, 0, sizeof(struct stat));
01061     if (partial) {
01062         st->st_mode = 1;
01063 #ifdef UFLASH_USE_TIMESTAMP
01064         EntryScan(vol, lbe, &st->st_mtime);
01065 #endif
01066     } else {
01067         NutEventWait(&vol->vol_mutex, 0);
01068 #ifdef UFLASH_USE_TIMESTAMP
01069         st->st_size = EntryScan(vol, lbe, &st->st_mtime);
01070 #else
01071         st->st_size = EntryScan(vol, lbe, NULL);
01072 #endif
01073         NutEventPost(&vol->vol_mutex);
01074 #if UFLASH_MAX_PATH
01075         st->st_size -= sizeof(ENTRYHEAD) + UFLASH_MAX_PATH;
01076 #else
01077         st->st_size -= sizeof(ENTRYHEAD) + eh.eh_nlen;
01078 #endif
01079     }
01080     return 0;
01081 }
01082 
01091 static NUTFILE *UFlashDirOpen(NUTDEVICE * dev, CONST char *dpath)
01092 {
01093     NUTFILE *ndp;
01094     UFLASHFIND *uff;
01095 
01096     ndp = malloc(sizeof(NUTFILE));
01097     if (ndp) {
01098         uff = malloc(sizeof(UFLASHFIND));
01099         if (uff) {
01100             uff->uff_lbe = 0;
01101             uff->uff_path = strdup(dpath + (*dpath == '/'));
01102             if (uff->uff_path) {
01103                 ndp->nf_dev = dev;
01104                 ndp->nf_fcb = uff;
01105 
01106                 return ndp;
01107             }
01108             free(uff);
01109         }
01110         free(ndp);
01111     }
01112     return NUTFILE_EOF;
01113 }
01114 
01118 static int UFlashDirClose(NUTFILE * ndp)
01119 {
01120     UFLASHFIND *uff;
01121 
01122     uff = (UFLASHFIND *) ndp->nf_fcb;
01123     free(uff->uff_path);
01124     free(uff);
01125     free(ndp);
01126 
01127     return 0;
01128 }
01129 
01133 static int UFlashDirRead(DIR * dir)
01134 {
01135     struct dirent *ent;
01136     NUTFILE *ndp;
01137     NUTDEVICE *dev;
01138     UFLASHFIND *uff;
01139     UFLASHVOLUME *vol;
01140     ENTRYHEAD eh;
01141     char *name = NULL;
01142     char *cp;
01143 
01144     ndp = dir->dd_fd;
01145     uff = (UFLASHFIND *) ndp->nf_fcb;
01146     dev = ndp->nf_dev;
01147     vol = (UFLASHVOLUME *) dev->dev_dcb;
01148 
01149     uff->uff_lbe = EntrySearchNext(vol, uff->uff_path, &eh, uff->uff_lbe);
01150     if (uff->uff_lbe >= UFLASH_ENTRIES) {
01151         return -1;
01152     }
01153 
01154     ent = (struct dirent *) dir->dd_buf;
01155     memset(dir->dd_buf, 0, sizeof(struct dirent));
01156     FlashReadEntry(vol->vol_ifc, vol->vol_l2p[uff->uff_lbe], &eh, &name);
01157     cp = strchr(name + strlen(uff->uff_path), '/');
01158     if (cp) {
01159         *cp = '\0';
01160         ent->d_type = 1;
01161     } else {
01162         ent->d_type = 0;
01163     }
01164     strcpy(ent->d_name, name + strlen(uff->uff_path));
01165     ent->d_namlen = strlen(name + strlen(uff->uff_path));
01166     free(name);
01167 
01168     uff->uff_lbe++;
01169 
01170     return 0;
01171 }
01172 
01182 static int UFlashFileRename(NUTDEVICE * dev, CONST char *old_path, CONST char *new_path)
01183 {
01184     blknum_t lbe;
01185     blknum_t b;
01186     blknum_t b_old;
01187     uint_fast8_t u;
01188     ENTRYHEAD eh;
01189     UFLASHVOLUME *vol;
01190     BLOCKHEAD bh;
01191     BLOCKFOOT bf;
01192 
01193     NUTASSERT(dev != NULL);
01194     NUTASSERT(old_path != NULL);
01195 #if UFLASH_MAX_PATH
01196     NUTASSERT(strlen(old_path) <= UFLASH_MAX_PATH);
01197 #endif
01198     NUTASSERT(new_path != NULL);
01199 #if UFLASH_MAX_PATH
01200     NUTASSERT(strlen(new_path) <= UFLASH_MAX_PATH);
01201 #endif
01202     vol = (UFLASHVOLUME *) dev->dev_dcb;
01203     NUTASSERT(vol != NULL);
01204 
01205     vol = (UFLASHVOLUME *) dev->dev_dcb;
01206 
01207     while (*old_path == '/') {
01208         old_path++;
01209     }
01210     while (*new_path == '/') {
01211         new_path++;
01212     }
01213     lbe = EntrySearch(vol, old_path, &eh);
01214     if (lbe >= UFLASH_ENTRIES || vol->vol_l2p[lbe] > vol->vol_blocks) {
01215         return -1;
01216     }
01217 #if UFLASH_MAX_PATH == 0
01218     if (eh.eh_nlen < strlen(new_path)) {
01219         return -1;
01220     }
01221 #endif
01222     eh.eh_nlen = strlen(new_path);
01223 
01224     
01225     NutEventWait(&vol->vol_mutex, 0);
01226 
01227     
01228     b = PhysBlkAllocate(vol, 0);
01229     if (b >= vol->vol_blocks) {
01230         
01231         NutEventPost(&vol->vol_mutex);
01232         return -1;
01233     }
01234 
01235     
01236     b_old = vol->vol_l2p[lbe];
01237     vol->vol_l2p[lbe] = b;
01238 
01239     
01240 
01241     FlashReadBlockFoot(vol->vol_ifc, b, &bf);
01242     FlashEraseBlockData(vol->vol_ifc, b);
01243 
01244     
01245     for (u = 0; u < UFLASH_BLOCK_UNITS; u++) {
01246         FlashUnitCopy(vol->vol_ifc, b_old, b, u);
01247         
01248         if (u == 0) {
01249             
01250 
01251             FlashReadBlockHead(vol->vol_ifc, b, &bh);
01252             FlashWriteBlockHead(vol->vol_ifc, b, &bh);
01253 
01254             
01255             FlashWriteEntry(vol->vol_ifc, b, &eh, new_path);
01256         }
01257         
01258         else if (u == UFLASH_BLOCK_UNITS - 1) {
01259             FlashWriteBlockFoot(vol->vol_ifc, b, &bf);
01260         }
01261         
01262         FlashUnitCommit(vol->vol_ifc, b, u);
01263     }
01264 
01265     
01266     FlashEraseEntry(vol->vol_ifc, b_old);
01267 
01268     
01269     NutEventPost(&vol->vol_mutex);
01270 
01271     return 0;
01272 }
01273 
01285 static long UFlashFileSize(NUTFILE * nfp)
01286 {
01287     NUTASSERT(nfp != NULL);
01288     NUTASSERT(nfp->nf_fcb != NULL);
01289 
01290     return ((UFLASHENTRY *) nfp->nf_fcb)->ent_size;
01291 }
01292 
01306 static NUTFILE *UFlashFileOpen(NUTDEVICE * dev, CONST char *path, int mode, int acc)
01307 {
01308     int rc = -1;
01309     NUTFILE *nfp = NUTFILE_EOF;
01310     UFLASHENTRY *ent;
01311     UFLASHVOLUME *vol;
01312     blknum_t lbe;
01313     ENTRYHEAD eh;
01314     long datsiz = 0;
01315 
01316     NUTASSERT(dev != NULL);
01317     NUTASSERT(path != NULL);
01318     vol = (UFLASHVOLUME *) dev->dev_dcb;
01319     NUTASSERT(vol != NULL);
01320 
01321     while (*path == '/') {
01322         path++;
01323     }
01324     
01325     ent = calloc(1, sizeof(UFLASHENTRY));
01326     if (ent == NULL) {
01327         return NUTFILE_EOF;
01328     }
01329     ent->ent_mode = mode;
01330 
01331     lbe = EntrySearch(vol, path, &eh);
01332 
01333     NutEventWait(&vol->vol_mutex, 0);
01334     
01335 
01336 
01337     if (lbe < UFLASH_ENTRIES) {
01338         if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
01339             errno = EEXIST;
01340         } else {
01341             
01342             if ((mode & _O_TRUNC) == _O_TRUNC) {
01343                 rc = EntryTruncate(vol, lbe);
01344             }
01345             
01346             else {
01347                 rc = 0;
01348                 datsiz = EntryScan(vol, lbe, NULL);
01349 #if UFLASH_MAX_PATH
01350                 datsiz -= sizeof(ENTRYHEAD) + UFLASH_MAX_PATH;
01351 #else
01352                 datsiz -= sizeof(ENTRYHEAD) + eh.eh_nlen;
01353 #endif
01354             }
01355         }
01356     }
01357 
01358     
01359 
01360 
01361     else {
01362         if ((mode & _O_CREAT) == _O_CREAT) {
01363             lbe = LogBlkAllocate(vol, 0);
01364             if (lbe < UFLASH_ENTRIES) {
01365                 eh.eh_nlen = strlen(path);
01366                 eh.eh_attr = 0;
01367                 rc = EntryCreate(vol, lbe, &eh, path);
01368             }
01369         } else {
01370             errno = ENOENT;
01371         }
01372     }
01373 
01374     if (rc) {
01375         free(ent);
01376     } else {
01377         ent->ent_attr = eh.eh_attr;
01378         ent->ent_namlen = eh.eh_nlen;
01379 #if UFLASH_MAX_PATH
01380         ent->ent_eoff = sizeof(ENTRYHEAD) + UFLASH_MAX_PATH;
01381 #else
01382         ent->ent_eoff = sizeof(ENTRYHEAD) + eh.eh_nlen;
01383 #endif
01384         ent->ent_id = lbe;
01385         ent->ent_size = datsiz;
01386 
01387         
01388         nfp = malloc(sizeof(NUTFILE));
01389         if (nfp == NULL) {
01390             free(ent);
01391             NutEventPost(&vol->vol_mutex);
01392             return NUTFILE_EOF;
01393         }
01394         nfp->nf_next = NULL;
01395         nfp->nf_dev = dev;
01396         nfp->nf_fcb = ent;
01397 
01398         if ((mode & _O_APPEND) == _O_APPEND) {
01399             ent->ent_bidx = UFLASH_BLOCK_INVALID;
01400             EntryPosSet(nfp, datsiz);
01401         } else {
01402             ent->ent_bidx = lbe;
01403             EntryPosSet(nfp, 0);
01404         }
01405     }
01406     NutEventPost(&vol->vol_mutex);
01407     return nfp;
01408 }
01409 
01418 static int UFlashFileClose(NUTFILE * nfp)
01419 {
01420     NUTASSERT(nfp != NULL);
01421     NUTASSERT(nfp->nf_dev != NULL);
01422     NUTASSERT(nfp->nf_fcb != NULL);
01423 
01424     free(nfp->nf_fcb);
01425     free(nfp);
01426 
01427     return 0;
01428 }
01429 
01441 static int UFlashFileRead(NUTFILE * nfp, void *data, int size)
01442 {
01443     int u;
01444     int step;
01445     int rc;
01446     uint8_t *dptr;
01447     UFLASHENTRY *ent;
01448     UFLASHVOLUME *vol;
01449 
01450     
01451     if (data == NULL || size == 0) {
01452         return 0;
01453     }
01454     dptr = (uint8_t *) data;
01455 
01456     NUTASSERT(nfp != NULL);
01457     NUTASSERT(nfp->nf_dev != NULL);
01458     ent = (UFLASHENTRY *) nfp->nf_fcb;
01459     NUTASSERT(ent != NULL);
01460     vol = (UFLASHVOLUME *) nfp->nf_dev->dev_dcb;
01461     NUTASSERT(vol != NULL);
01462 
01463     
01464     if (size > (int) (ent->ent_size - ent->ent_pos)) {
01465         size = (int) (ent->ent_size - ent->ent_pos);
01466     }
01467 
01468     
01469 
01470 
01471     for (rc = 0; rc < size;) {
01472         
01473         if (ent->ent_bidx >= vol->vol_blocks) {
01474             
01475             ent->ent_bidx = EntrySeek(vol, ent->ent_id, ent->ent_sidx);
01476             if (ent->ent_bidx >= vol->vol_blocks) {
01477                 
01478                 errno = EIO;
01479                 return -1;
01480             }
01481         }
01482         
01483         for (u = ent->ent_uidx; rc < size && u < UFLASH_BLOCK_UNITS; u++) {
01484             NutEventWait(&vol->vol_mutex, 0);
01485             step = FlashUnitRead(vol->vol_ifc, vol->vol_l2p[ent->ent_bidx], u, ent->ent_upos, dptr, size - rc);
01486             NutEventPost(&vol->vol_mutex);
01487             if (step < 0) {
01488                 
01489                 errno = EIO;
01490                 return -1;
01491             }
01492             
01493             rc += step;
01494             dptr += step;
01495             EntryPosInc(nfp, step);
01496         }
01497     }
01498     return rc;
01499 }
01500 
01513 static int UFlashFileWrite(NUTFILE * nfp, CONST void *data, int len)
01514 {
01515     int u;
01516     blknum_t b;
01517     blknum_t b_old;
01518     int step;
01519     int siz = len;
01520     uint8_t *dptr;
01521     BLOCKHEAD bh;
01522     BLOCKFOOT bf;
01523     UFLASHENTRY *ent;
01524     UFLASHVOLUME *vol;
01525 
01526     
01527     if (data == NULL || len == 0) {
01528         return 0;
01529     }
01530     dptr = (uint8_t *) data;
01531 
01532     
01533     NUTASSERT(nfp != NULL);
01534     NUTASSERT(nfp->nf_fcb != NULL);
01535     NUTASSERT(nfp->nf_dev != NULL);
01536     NUTASSERT(nfp->nf_dev->dev_dcb != NULL);
01537 
01538     ent = (UFLASHENTRY *) nfp->nf_fcb;
01539     vol = (UFLASHVOLUME *) nfp->nf_dev->dev_dcb;
01540 
01541     
01542 
01543 
01544     while (len) {
01545         
01546         if (ent->ent_bidx >= vol->vol_blocks) {
01547             
01548 
01549             ent->ent_bidx = EntrySeek(vol, ent->ent_id, ent->ent_sidx);
01550         }
01551 
01552         
01553 
01554 
01555 
01556         NutEventWait(&vol->vol_mutex, 0);
01557         if (ent->ent_bidx < vol->vol_blocks) {
01558             b_old = LogBlkReallocate(vol, ent->ent_bidx);
01559             if (b_old >= vol->vol_blocks) {
01560                 
01561                 NutEventPost(&vol->vol_mutex);
01562                 return -1;
01563             }
01564             
01565             FlashReadBlockHead(vol->vol_ifc, b_old, &bh);
01566         }
01567 
01568         
01569 
01570 
01571 
01572         else {
01573             ent->ent_bidx = LogBlkAllocate(vol, UFLASH_ENTRIES);
01574             if (ent->ent_bidx >= vol->vol_blocks) {
01575                 
01576                 NutEventPost(&vol->vol_mutex);
01577                 return -1;
01578             }
01579             
01580             b_old = vol->vol_l2p[ent->ent_bidx];
01581             
01582             bh.bh_logblk = ent->ent_bidx;
01583             bh.bh_entblk = ent->ent_id;
01584             bh.bh_entseq = ent->ent_sidx;
01585             bh.bh_version = UFLASH_BLOCK_INVALID;
01586         }
01587         
01588         b = vol->vol_l2p[ent->ent_bidx];
01589 
01590         
01591         FlashReadBlockFoot(vol->vol_ifc, b, &bf);
01592         
01593 
01594         FlashEraseBlockData(vol->vol_ifc, b);
01595 
01596         
01597 
01598 
01599         for (u = 0; u < UFLASH_BLOCK_UNITS; u++) {
01600             
01601 
01602             FlashUnitCopy(vol->vol_ifc, b_old, b, u);
01603             
01604             if (u == 0) {
01605                 FlashWriteBlockHead(vol->vol_ifc, b, &bh);
01606             }
01607             
01608             if (len && u == ent->ent_uidx) {
01609                 step = FlashUnitWrite(vol->vol_ifc, b, u, ent->ent_upos, dptr, len);
01610                 
01611                 len -= step;
01612                 dptr += step;
01613                 EntryPosInc(nfp, step);
01614                 if (ent->ent_size < ent->ent_pos) {
01615                     ent->ent_size = ent->ent_pos;
01616                 }
01617             }
01618             
01619             if (u == UFLASH_BLOCK_UNITS - 1) {
01620                 FlashWriteBlockFoot(vol->vol_ifc, b, &bf);
01621             }
01622             FlashUnitCommit(vol->vol_ifc, b, u);
01623         }
01624         
01625 
01626 
01627 
01628 
01629         if (b != b_old) {
01630             FlashEraseEntry(vol->vol_ifc, b_old);
01631         }
01632         NutEventPost(&vol->vol_mutex);
01633     }
01634     return siz;
01635 }
01636 
01637 #ifdef __HARVARD_ARCH__
01638 
01655 static int UFlashFileWrite_P(NUTFILE * nfp, PGM_P buffer, int len)
01656 {
01657     return -1;
01658 }
01659 #endif
01660 
01673 static int UFlashFileSeek(NUTFILE * nfp, long *pos, int whence)
01674 {
01675     int rc = 0;
01676     long npos;
01677     UFLASHENTRY *ent;
01678 
01679     NUTASSERT(nfp != NULL);
01680     NUTASSERT(nfp->nf_fcb != NULL);
01681 
01682     ent = (UFLASHENTRY *) nfp->nf_fcb;
01683 
01684     NUTASSERT(pos != NULL);
01685     npos = *pos;
01686 
01687     switch (whence) {
01688     case SEEK_CUR:
01689         
01690         npos += ent->ent_pos;
01691         break;
01692     case SEEK_END:
01693         
01694         npos += ent->ent_size;
01695         break;
01696     }
01697 
01698     
01699     if (npos < 0 || npos > (long) ent->ent_size) {
01700         errno = EINVAL;
01701         rc = -1;
01702     } else {
01703         EntryPosSet(nfp, npos);
01704         *pos = npos;
01705     }
01706     return rc;
01707 }
01708 
01716 static int UFlashMount(NUTDEVICE * dev)
01717 {
01718     int b;
01719     BLOCKHEAD bh;
01720     UFLASHVOLUME *vol;
01721 
01722     NUTASSERT(dev != NULL);
01723     NUTASSERT(dev->dev_icb != NULL);
01724     NUTASSERT(dev->dev_dcb == NULL);
01725 
01726     
01727     vol = calloc(1, sizeof(UFLASHVOLUME));
01728     if (vol == NULL) {
01729         return -1;
01730     }
01731     dev->dev_dcb = vol;
01732     vol->vol_ifc = (NUTSERIALFLASH *) dev->dev_icb;
01733 
01734     
01735     vol->vol_blocks =
01736         (blknum_t) ((vol->vol_ifc->sf_units - vol->vol_ifc->sf_rsvbot - vol->vol_ifc->sf_rsvtop) / UFLASH_BLOCK_UNITS);
01737     if (vol->vol_blocks > UFLASH_MAX_BLOCKS) {
01738         vol->vol_blocks = UFLASH_MAX_BLOCKS;
01739     }
01740 
01741     
01742     vol->vol_l2p = malloc(vol->vol_blocks * sizeof(blknum_t));
01743     if (vol->vol_l2p == NULL) {
01744         free(vol);
01745         return -1;
01746     }
01747     memset(vol->vol_l2p, 0xff, vol->vol_blocks * sizeof(blknum_t));
01748 
01749     memset(min_used, 0xff, sizeof(min_used));
01750 
01751     
01752 
01753 
01754     for (b = 0; b < vol->vol_blocks; b++) {
01755         FlashReadBlockHead(vol->vol_ifc, b, &bh);
01756         
01757         if (bh.bh_logblk < vol->vol_blocks) {
01758             
01759             if (FlashCheckBlock(vol->vol_ifc, b)) {
01760                 
01761                 FlashEraseEntry(vol->vol_ifc, b);
01762                 
01763                 vol->vol_attrib |= UFLASH_VOLF_FIXED;
01764             } else {
01765                 
01766                 if (vol->vol_l2p[bh.bh_logblk] < vol->vol_blocks) {
01767                     BLOCKHEAD bho;
01768 
01769                     
01770                     FlashReadBlockHead(vol->vol_ifc, vol->vol_l2p[bh.bh_logblk], &bho);
01771                     
01772                     if (bho.bh_version > bh.bh_version) {
01773                         if (bho.bh_version - bh.bh_version > vol->vol_blocks) {
01774                             
01775                             FlashEraseEntry(vol->vol_ifc, b);
01776                         } else {
01777                             FlashEraseEntry(vol->vol_ifc, vol->vol_l2p[bh.bh_logblk]);
01778                             vol->vol_l2p[bh.bh_logblk] = b;
01779                         }
01780                     } else if (bh.bh_version - bho.bh_version < vol->vol_blocks) {
01781                         
01782                         FlashEraseEntry(vol->vol_ifc, b);
01783                     } else {
01784                         FlashEraseEntry(vol->vol_ifc, vol->vol_l2p[bh.bh_logblk]);
01785                         vol->vol_l2p[bh.bh_logblk] = b;
01786                     }
01787                     
01788                     vol->vol_attrib |= UFLASH_VOLF_FIXED;
01789                 } else {
01790                     
01791                     vol->vol_l2p[bh.bh_logblk] = b;
01792                 }
01793             }
01794         }
01795     }
01796     
01797     NutEventPost(&vol->vol_mutex);
01798     return 0;
01799 }
01800 
01808 static int UFlashUnmount(NUTDEVICE * dev)
01809 {
01810     UFLASHVOLUME *vol;
01811 
01812     
01813     NUTASSERT(dev != NULL);
01814 
01815     
01816     NUTASSERT(dev->dev_dcb != NULL);
01817     vol = (UFLASHVOLUME *) dev->dev_dcb;
01818 
01819     
01820     NUTASSERT(vol->vol_l2p != NULL);
01821     free(vol->vol_l2p);
01822     free(vol);
01823 
01824     
01825     dev->dev_dcb = NULL;
01826 
01827     return 0;
01828 }
01829 
01842 int UFlashAttach(NUTDEVICE * dev, NUTSERIALFLASH * sfi, NUTSPIBUS * bus)
01843 {
01844     
01845     NUTASSERT(dev != NULL);
01846     NUTASSERT(sfi != NULL);
01847     NUTASSERT(sfi->sf_node != NULL);
01848     NUTASSERT(sfi->sf_init != NULL);
01849     NUTASSERT(bus != NULL);
01850     NUTASSERT(bus->bus_initnode != NULL);
01851 
01852     sfi->sf_node->node_bus = bus;
01853     if ((*bus->bus_initnode) (sfi->sf_node)) {
01854         return -1;
01855     }
01856     NutEventPost(&sfi->sf_node->node_bus->bus_mutex);
01857 
01858     if ((*sfi->sf_init) (sfi) == 0) {
01859         dev->dev_icb = (void *) sfi;
01860         if (UFlashMount(dev) == 0) {
01861             return 0;
01862         }
01863         dev->dev_icb = NULL;
01864     }
01865     return -1;
01866 }
01867 
01877 void UFlashDetach(NUTDEVICE * dev)
01878 {
01879     NUTSERIALFLASH *sfi;
01880 
01881     UFlashUnmount(dev);
01882 
01883     
01884     sfi = (NUTSERIALFLASH *) dev->dev_icb;
01885     NUTASSERT(sfi != NULL);
01886     NUTASSERT(sfi->sf_exit != NULL);
01887     (*sfi->sf_exit) (sfi);
01888     dev->dev_icb = NULL;
01889 }
01890 
01905 int UFlashFormat(NUTDEVICE * dev, NUTSERIALFLASH * sfi, NUTSPIBUS * bus)
01906 {
01907     int rc;
01908     blknum_t n;
01909 
01910     
01911     NUTASSERT(dev != NULL);
01912     NUTASSERT(sfi != NULL);
01913     NUTASSERT(dev->dev_dcb == NULL);
01914 
01915     sfi->sf_node->node_bus = bus;
01916     if ((*sfi->sf_node->node_bus->bus_initnode) (sfi->sf_node)) {
01917         return -1;
01918     }
01919     NutEventPost(&sfi->sf_node->node_bus->bus_mutex);
01920 
01921     rc = (*sfi->sf_init) (sfi);
01922     if (rc == 0) {
01923         n = (blknum_t) ((sfi->sf_units - sfi->sf_rsvbot - sfi->sf_rsvtop) / UFLASH_BLOCK_UNITS);
01924         if (n > UFLASH_MAX_BLOCKS) {
01925             n = UFLASH_MAX_BLOCKS;
01926         }
01927         FlashEraseBlocks(sfi, n);
01928         (*sfi->sf_exit) (sfi);
01929     }
01930     return 0;
01931 }
01932 
01957 static int UFlashIOCtl(NUTDEVICE * dev, int req, void *conf)
01958 {
01959     int rc = -1;
01960 
01961     switch (req) {
01962     case FS_STATUS:
01963         NUTASSERT(conf != NULL);
01964         {
01965             FSCP_STATUS *par = (FSCP_STATUS *) conf;
01966             rc = UFlashFileStatus(dev, par->par_path, par->par_stp);
01967         }
01968         break;
01969     case FS_DIR_CREATE:
01970         rc = 0;
01971         break;
01972     case FS_DIR_REMOVE:
01973         rc = 0;
01974         break;
01975     case FS_DIR_OPEN:
01976         
01977         NUTASSERT(conf != NULL);
01978         {
01979             DIR *dir = (DIR *) conf;
01980 
01981             if ((dir->dd_fd = UFlashDirOpen(dev, dir->dd_buf)) != NUTFILE_EOF) {
01982                 rc = 0;
01983             }
01984         }
01985         break;
01986     case FS_DIR_CLOSE:
01987         NUTASSERT(conf != NULL);
01988         rc = UFlashDirClose(((DIR *) conf)->dd_fd);
01989         break;
01990     case FS_DIR_READ:
01991         rc = UFlashDirRead((DIR *) conf);
01992         break;
01993     case FS_FILE_DELETE:
01994         rc = UFlashFileRemove(dev, (char *) conf);
01995         break;
01996     case FS_FILE_SEEK:
01997         NUTASSERT(conf != NULL);
01998         UFlashFileSeek((NUTFILE *) ((IOCTL_ARG3 *) conf)->arg1, 
01999                        (long *) ((IOCTL_ARG3 *) conf)->arg2,    
02000                        (int) ((IOCTL_ARG3 *) conf)->arg3);
02001         break;
02002     case FS_RENAME:
02003         
02004         NUTASSERT(conf != NULL);
02005         {
02006             FSCP_RENAME *par = (FSCP_RENAME *) conf;
02007             rc = UFlashFileRename(dev, par->par_old, par->par_new);
02008         }
02009         break;
02010     case FS_VOL_MOUNT:
02011         
02012         rc = UFlashMount(dev);
02013         break;
02014     case FS_VOL_UNMOUNT:
02015         
02016         rc = UFlashUnmount(dev);
02017         break;
02018     }
02019     return rc;
02020 }
02021 
02031 static int UFlashInit(NUTDEVICE * dev)
02032 {
02033     return 0;
02034 }
02035 
02039 NUTDEVICE devUFlash0 = {
02040     0,                          
02041     {'U', 'F', 'L', 'A', 'S', 'H', '0', 0, 0}
02042     ,                           
02043     IFTYP_FS,                   
02044     0,                          
02045     0,                          
02046     NULL,                       
02047     NULL,                       
02048     UFlashInit,                 
02049     UFlashIOCtl,                
02050     UFlashFileRead,             
02051     UFlashFileWrite,            
02052 #ifdef __HARVARD_ARCH__
02053     UFlashFileWrite_P,          
02054 #endif
02055     UFlashFileOpen,             
02056     UFlashFileClose,            
02057     UFlashFileSize              
02058 };
02059 
02063 NUTDEVICE devUFlash1 = {
02064     0,                          
02065     {'U', 'F', 'L', 'A', 'S', 'H', '1', 0, 0}
02066     ,                           
02067     IFTYP_FS,                   
02068     1,                          
02069     0,                          
02070     NULL,                       
02071     NULL,                       
02072     UFlashInit,                 
02073     UFlashIOCtl,                
02074     UFlashFileRead,             
02075     UFlashFileWrite,            
02076 #ifdef __HARVARD_ARCH__
02077     UFlashFileWrite_P,          
02078 #endif
02079     UFlashFileOpen,             
02080     UFlashFileClose,            
02081     UFlashFileSize              
02082 };
02083