1 /* 2 * YAFFS: Yet another FFS. A NAND-flash specific file system. 3 * yaffs_ramdisk.c: yaffs ram disk component 4 * 5 * Copyright (C) 2002 Aleph One Ltd. 6 * 7 * Created by Charles Manning <charles (at) aleph1.co.uk> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 */ 14 15 // This provides a rma disk under yaffs. 16 // NB this is not intended for NAND emulation. 17 // Use this with dev->useNANDECC enabled, then ECC overheads are not required. 18 19 const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.2 2004/11/22 03:22:25 charles Exp $"; 20 21 22 #include "yportenv.h" 23 24 #include "yaffs_ramdisk.h" 25 #include "yaffs_guts.h" 26 #include "devextras.h" 27 #include "yaffs_packedtags1.h" 28 29 30 31 #define SIZE_IN_MB 2 32 33 #define BLOCK_SIZE (32 * 528) 34 #define BLOCKS_PER_MEG ((1024*1024)/(32 * 512)) 35 36 37 38 39 40 typedef struct 41 { 42 __u8 data[528]; // Data + spare 43 } yramdisk_Page; 44 45 typedef struct 46 { 47 yramdisk_Page page[32]; // The pages in the block 48 49 } yramdisk_Block; 50 51 52 53 typedef struct 54 { 55 yramdisk_Block **block; 56 int nBlocks; 57 } yramdisk_Device; 58 59 static yramdisk_Device ramdisk; 60 61 static int CheckInit(yaffs_Device *dev) 62 { 63 static int initialised = 0; 64 65 int i; 66 int fail = 0; 67 //int nBlocks; 68 int nAllocated = 0; 69 70 if(initialised) 71 { 72 return YAFFS_OK; 73 } 74 75 initialised = 1; 76 77 78 ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024); 79 80 ramdisk.block = YMALLOC(sizeof(yramdisk_Block *) * ramdisk.nBlocks); 81 82 if(!ramdisk.block) return 0; 83 84 for(i=0; i <ramdisk.nBlocks; i++) 85 { 86 ramdisk.block[i] = NULL; 87 } 88 89 for(i=0; i <ramdisk.nBlocks && !fail; i++) 90 { 91 if((ramdisk.block[i] = YMALLOC(sizeof(yramdisk_Block))) == 0) 92 { 93 fail = 1; 94 } 95 else 96 { 97 yramdisk_EraseBlockInNAND(dev,i); 98 nAllocated++; 99 } 100 } 101 102 if(fail) 103 { 104 for(i = 0; i < nAllocated; i++) 105 { 106 YFREE(ramdisk.block[i]); 107 } 108 YFREE(ramdisk.block); 109 110 T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", 111 nAllocated/64,ramdisk.nBlocks * 528)); 112 return 0; 113 } 114 115 116 return 1; 117 } 118 119 int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) 120 { 121 int blk; 122 int pg; 123 124 125 CheckInit(dev); 126 127 blk = chunkInNAND/32; 128 pg = chunkInNAND%32; 129 130 131 if(data) 132 { 133 memcpy(ramdisk.block[blk]->page[pg].data,data,512); 134 } 135 136 137 if(tags) 138 { 139 yaffs_PackedTags1 pt; 140 141 yaffs_PackTags1(&pt,tags); 142 memcpy(&ramdisk.block[blk]->page[pg].data[512],&pt,sizeof(pt)); 143 } 144 145 return YAFFS_OK; 146 147 } 148 149 150 int yramdisk_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags) 151 { 152 int blk; 153 int pg; 154 155 156 CheckInit(dev); 157 158 blk = chunkInNAND/32; 159 pg = chunkInNAND%32; 160 161 162 if(data) 163 { 164 memcpy(data,ramdisk.block[blk]->page[pg].data,512); 165 } 166 167 168 if(tags) 169 { 170 yaffs_PackedTags1 pt; 171 172 memcpy(&pt,&ramdisk.block[blk]->page[pg].data[512],sizeof(pt)); 173 yaffs_UnpackTags1(tags,&pt); 174 175 } 176 177 return YAFFS_OK; 178 } 179 180 181 int yramdisk_CheckChunkErased(yaffs_Device *dev,int chunkInNAND) 182 { 183 int blk; 184 int pg; 185 int i; 186 187 188 CheckInit(dev); 189 190 blk = chunkInNAND/32; 191 pg = chunkInNAND%32; 192 193 194 for(i = 0; i < 528; i++) 195 { 196 if(ramdisk.block[blk]->page[pg].data[i] != 0xFF) 197 { 198 return YAFFS_FAIL; 199 } 200 } 201 202 return YAFFS_OK; 203 204 } 205 206 int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) 207 { 208 209 CheckInit(dev); 210 211 if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks) 212 { 213 T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); 214 return YAFFS_FAIL; 215 } 216 else 217 { 218 memset(ramdisk.block[blockNumber],0xFF,sizeof(yramdisk_Block)); 219 return YAFFS_OK; 220 } 221 222 } 223 224 int yramdisk_InitialiseNAND(yaffs_Device *dev) 225 { 226 //dev->useNANDECC = 1; // force on useNANDECC which gets faked. 227 // This saves us doing ECC checks. 228 229 return YAFFS_OK; 230 } 231 232 233