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@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 19const 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 40typedef struct 41{ 42 __u8 data[528]; // Data + spare 43} yramdisk_Page; 44 45typedef struct 46{ 47 yramdisk_Page page[32]; // The pages in the block 48 49} yramdisk_Block; 50 51 52 53typedef struct 54{ 55 yramdisk_Block **block; 56 int nBlocks; 57} yramdisk_Device; 58 59static yramdisk_Device ramdisk; 60 61static 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 119int 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 150int 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 181int 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 206int 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 224int 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