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_flashif_c_version = "$Id: yaffs_flashif.c,v 1.1 2004/11/03 08:29:28 charles Exp $"; 20 21 22#include "yportenv.h" 23 24#include "yaffs_flashif.h" 25#include "yaffs_guts.h" 26#include "devextras.h" 27 28 29#define SIZE_IN_MB 16 30 31#define BLOCK_SIZE (32 * 528) 32#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512)) 33 34 35 36typedef struct 37{ 38 __u8 data[528]; // Data + spare 39} yflash_Page; 40 41typedef struct 42{ 43 yflash_Page page[32]; // The pages in the block 44 45} yflash_Block; 46 47 48 49typedef struct 50{ 51 yflash_Block **block; 52 int nBlocks; 53} yflash_Device; 54 55static yflash_Device ramdisk; 56 57static int CheckInit(yaffs_Device *dev) 58{ 59 static int initialised = 0; 60 61 int i; 62 int fail = 0; 63 int nAllocated = 0; 64 65 if(initialised) 66 { 67 return YAFFS_OK; 68 } 69 70 initialised = 1; 71 72 73 ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024); 74 75 ramdisk.block = YMALLOC(sizeof(yflash_Block *) * ramdisk.nBlocks); 76 77 if(!ramdisk.block) return 0; 78 79 for(i=0; i <ramdisk.nBlocks; i++) 80 { 81 ramdisk.block[i] = NULL; 82 } 83 84 for(i=0; i <ramdisk.nBlocks && !fail; i++) 85 { 86 if((ramdisk.block[i] = YMALLOC(sizeof(yflash_Block))) == 0) 87 { 88 fail = 1; 89 } 90 else 91 { 92 yflash_EraseBlockInNAND(dev,i); 93 nAllocated++; 94 } 95 } 96 97 if(fail) 98 { 99 for(i = 0; i < nAllocated; i++) 100 { 101 YFREE(ramdisk.block[i]); 102 } 103 YFREE(ramdisk.block); 104 105 T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n", 106 nAllocated/64,ramdisk.nBlocks * YAFFS_BYTES_PER_BLOCK)); 107 return 0; 108 } 109 110 111 112 return 1; 113} 114 115int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags) 116{ 117 int blk; 118 int pg; 119 120 121 CheckInit(dev); 122 123 blk = chunkInNAND/32; 124 pg = chunkInNAND%32; 125 126 127 if(data) 128 { 129 memcpy(ramdisk.block[blk]->page[pg].data,data,512); 130 } 131 132 133 if(tags) 134 { 135 yaffs_PackedTags pt; 136 yaffs_PackTags(&pt,tags); 137 memcpy(&ramdisk.block[blk]->page[pg].data[512],&pt,sizeof(pt)); 138 } 139 140 return YAFFS_OK; 141 142} 143 144 145int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Tags *tags) 146{ 147 int blk; 148 int pg; 149 150 151 CheckInit(dev); 152 153 blk = chunkInNAND/32; 154 pg = chunkInNAND%32; 155 156 157 if(data) 158 { 159 memcpy(data,ramdisk.block[blk]->page[pg].data,512); 160 } 161 162 163 if(tags) 164 { 165 yaffs_PackedTags pt; 166 memcpy(&pt,&ramdisk.block[blk]->page[pg].data[512],sizeof(yaffs_PackedTags)); 167 yaffs_UnpackTags(tags,&pt); 168 } 169 170 return YAFFS_OK; 171} 172 173 174int yflash_CheckChunkErased(yaffs_Device *dev,int chunkInNAND) 175{ 176 int blk; 177 int pg; 178 int i; 179 180 181 CheckInit(dev); 182 183 blk = chunkInNAND/32; 184 pg = chunkInNAND%32; 185 186 187 for(i = 0; i < 528; i++) 188 { 189 if(ramdisk.block[blk]->page[pg].data[i] != 0xFF) 190 { 191 return YAFFS_FAIL; 192 } 193 } 194 195 return YAFFS_OK; 196 197} 198 199int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber) 200{ 201 202 CheckInit(dev); 203 204 if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks) 205 { 206 T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber)); 207 return YAFFS_FAIL; 208 } 209 else 210 { 211 memset(ramdisk.block[blockNumber],0xFF,sizeof(yflash_Block)); 212 return YAFFS_OK; 213 } 214 215} 216 217int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo) 218{ 219 return YAFFS_OK; 220 221} 222int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber) 223{ 224 *state = YAFFS_BLOCK_STATE_EMPTY; 225 *sequenceNumber = 0; 226} 227 228 229int yflash_InitialiseNAND(yaffs_Device *dev) 230{ 231 return YAFFS_OK; 232} 233 234