00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <SdFat.h>
00021
00022
00023
00024 uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF;
00025 cache_t SdVolume::cacheBuffer_;
00026 Sd2Card* SdVolume::sdCard_;
00027 uint8_t SdVolume::cacheDirty_ = 0;
00028 uint32_t SdVolume::cacheMirrorBlock_ = 0;
00029
00030
00031 uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
00032
00033 uint32_t bgnCluster;
00034
00035
00036 uint8_t setStart;
00037
00038
00039 if (*curCluster) {
00040
00041 bgnCluster = *curCluster + 1;
00042
00043
00044 setStart = false;
00045 } else {
00046
00047 bgnCluster = allocSearchStart_;
00048
00049
00050 setStart = 1 == count;
00051 }
00052
00053 uint32_t endCluster = bgnCluster;
00054
00055
00056 uint32_t fatEnd = clusterCount_ + 1;
00057
00058
00059 for (uint32_t n = 0;; n++, endCluster++) {
00060
00061 if (n >= clusterCount_) return false;
00062
00063
00064 if (endCluster > fatEnd) {
00065 bgnCluster = endCluster = 2;
00066 }
00067 uint32_t f;
00068 if (!fatGet(endCluster, &f)) return false;
00069
00070 if (f != 0) {
00071
00072 bgnCluster = endCluster + 1;
00073 } else if ((endCluster - bgnCluster + 1) == count) {
00074
00075 break;
00076 }
00077 }
00078
00079 if (!fatPutEOC(endCluster)) return false;
00080
00081
00082 while (endCluster > bgnCluster) {
00083 if (!fatPut(endCluster - 1, endCluster)) return false;
00084 endCluster--;
00085 }
00086 if (*curCluster != 0) {
00087
00088 if (!fatPut(*curCluster, bgnCluster)) return false;
00089 }
00090
00091 *curCluster = bgnCluster;
00092
00093
00094 if (setStart) allocSearchStart_ = bgnCluster + 1;
00095
00096 return true;
00097 }
00098
00099 uint8_t SdVolume::cacheFlush(void) {
00100 if (cacheDirty_) {
00101 if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data)) {
00102 return false;
00103 }
00104
00105 if (cacheMirrorBlock_) {
00106 if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data)) {
00107 return false;
00108 }
00109 cacheMirrorBlock_ = 0;
00110 }
00111 cacheDirty_ = 0;
00112 }
00113 return true;
00114 }
00115
00116 uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) {
00117 if (cacheBlockNumber_ != blockNumber) {
00118 if (!cacheFlush()) return false;
00119 if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false;
00120 cacheBlockNumber_ = blockNumber;
00121 }
00122 cacheDirty_ |= action;
00123 return true;
00124 }
00125
00126
00127 uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) {
00128 if (!cacheFlush()) return false;
00129
00130
00131 for (uint16_t i = 0; i < 512; i++) {
00132 cacheBuffer_.data[i] = 0;
00133 }
00134 cacheBlockNumber_ = blockNumber;
00135 cacheSetDirty();
00136 return true;
00137 }
00138
00139
00140 uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const {
00141 uint32_t s = 0;
00142 do {
00143 if (!fatGet(cluster, &cluster)) return false;
00144 s += 512UL << clusterSizeShift_;
00145 } while (!isEOC(cluster));
00146 *size = s;
00147 return true;
00148 }
00149
00150
00151 uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const {
00152 if (cluster > (clusterCount_ + 1)) return false;
00153 uint32_t lba = fatStartBlock_;
00154 lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;
00155 if (lba != cacheBlockNumber_) {
00156 if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
00157 }
00158 if (fatType_ == 16) {
00159 *value = cacheBuffer_.fat16[cluster & 0XFF];
00160 } else {
00161 *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
00162 }
00163 return true;
00164 }
00165
00166
00167 uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) {
00168
00169 if (cluster < 2) return false;
00170
00171
00172 if (cluster > (clusterCount_ + 1)) return false;
00173
00174
00175 uint32_t lba = fatStartBlock_;
00176 lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;
00177
00178 if (lba != cacheBlockNumber_) {
00179 if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
00180 }
00181
00182 if (fatType_ == 16) {
00183 cacheBuffer_.fat16[cluster & 0XFF] = value;
00184 } else {
00185 cacheBuffer_.fat32[cluster & 0X7F] = value;
00186 }
00187 cacheSetDirty();
00188
00189
00190 if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
00191 return true;
00192 }
00193
00194
00195 uint8_t SdVolume::freeChain(uint32_t cluster) {
00196
00197 allocSearchStart_ = 2;
00198
00199 do {
00200 uint32_t next;
00201 if (!fatGet(cluster, &next)) return false;
00202
00203
00204 if (!fatPut(cluster, 0)) return false;
00205
00206 cluster = next;
00207 } while (!isEOC(cluster));
00208
00209 return true;
00210 }
00211
00227 uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) {
00228 uint32_t volumeStartBlock = 0;
00229 sdCard_ = dev;
00230
00231
00232 if (part) {
00233 if (part > 4)return false;
00234 if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
00235 part_t* p = &cacheBuffer_.mbr.part[part-1];
00236 if ((p->boot & 0X7F) !=0 ||
00237 p->totalSectors < 100 ||
00238 p->firstSector == 0) {
00239
00240 return false;
00241 }
00242 volumeStartBlock = p->firstSector;
00243 }
00244 if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
00245 bpb_t* bpb = &cacheBuffer_.fbs.bpb;
00246 if (bpb->bytesPerSector != 512 ||
00247 bpb->fatCount == 0 ||
00248 bpb->reservedSectorCount == 0 ||
00249 bpb->sectorsPerCluster == 0) {
00250
00251 return false;
00252 }
00253 fatCount_ = bpb->fatCount;
00254 blocksPerCluster_ = bpb->sectorsPerCluster;
00255
00256
00257 clusterSizeShift_ = 0;
00258 while (blocksPerCluster_ != (1 << clusterSizeShift_)) {
00259
00260 if (clusterSizeShift_++ > 7) return false;
00261 }
00262 blocksPerFat_ = bpb->sectorsPerFat16 ?
00263 bpb->sectorsPerFat16 : bpb->sectorsPerFat32;
00264
00265 fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount;
00266
00267
00268 rootDirEntryCount_ = bpb->rootDirEntryCount;
00269
00270
00271 rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_;
00272
00273
00274 dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511)/512);
00275
00276
00277 uint32_t totalBlocks = bpb->totalSectors16 ?
00278 bpb->totalSectors16 : bpb->totalSectors32;
00279
00280 clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
00281
00282
00283 clusterCount_ >>= clusterSizeShift_;
00284
00285
00286 if (clusterCount_ < 4085) {
00287 fatType_ = 12;
00288 } else if (clusterCount_ < 65525) {
00289 fatType_ = 16;
00290 } else {
00291 rootDirStart_ = bpb->fat32RootCluster;
00292 fatType_ = 32;
00293 }
00294 return true;
00295 }