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