Home | History | Annotate | Download | only in direct
      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