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 YAFFS nand emulation on a file.
16// THis is only intended as test code to test persistence etc.
17
18const char *yaffs_flashif_c_version = "$Id: yaffs_fileem.c,v 1.1 2004/11/03 08:29:28 charles Exp $";
19
20
21#include "yportenv.h"
22
23#include "yaffs_flashif.h"
24#include "yaffs_guts.h"
25
26#include "devextras.h"
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <fcntl.h>
31#include <unistd.h>
32
33
34
35#define SIZE_IN_MB 16
36
37#define BLOCK_SIZE (32 * 528)
38#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512))
39
40
41
42typedef struct
43{
44	__u8 data[528]; // Data + spare
45} yflash_Page;
46
47typedef struct
48{
49	yflash_Page page[32]; // The pages in the block
50
51} yflash_Block;
52
53
54
55typedef struct
56{
57	int handle;
58	int nBlocks;
59} yflash_Device;
60
61static yflash_Device filedisk;
62
63static int  CheckInit(yaffs_Device *dev)
64{
65	static int initialised = 0;
66
67	int i;
68
69
70	int fSize;
71	int written;
72
73	yflash_Page p;
74
75	if(initialised)
76	{
77		return YAFFS_OK;
78	}
79
80	initialised = 1;
81
82
83	filedisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024);
84
85	filedisk.handle = open("yaffsemfile", O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
86
87	if(filedisk.handle < 0)
88	{
89		perror("Failed to open yaffs emulation file");
90		return YAFFS_FAIL;
91	}
92
93
94	fSize = lseek(filedisk.handle,0,SEEK_END);
95
96	if(fSize < SIZE_IN_MB * 1024 * 1024)
97	{
98		printf("Creating yaffs emulation file\n");
99
100		lseek(filedisk.handle,0,SEEK_SET);
101
102		memset(&p,0xff,sizeof(yflash_Page));
103
104		for(i = 0; i < SIZE_IN_MB * 1024 * 1024; i+= 512)
105		{
106			written = write(filedisk.handle,&p,sizeof(yflash_Page));
107
108			if(written != sizeof(yflash_Page))
109			{
110				printf("Write failed\n");
111				return YAFFS_FAIL;
112			}
113		}
114	}
115
116	return 1;
117}
118
119int yflash_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare)
120{
121	int written;
122
123	CheckInit(dev);
124
125
126
127	if(data)
128	{
129		lseek(filedisk.handle,chunkInNAND * 528,SEEK_SET);
130		written = write(filedisk.handle,data,512);
131
132		if(written != 512) return YAFFS_FAIL;
133	}
134
135	if(spare)
136	{
137		lseek(filedisk.handle,chunkInNAND * 528 + 512,SEEK_SET);
138		written = write(filedisk.handle,spare,16);
139
140		if(written != 16) return YAFFS_FAIL;
141	}
142
143
144	return YAFFS_OK;
145
146}
147
148
149int yflash_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare)
150{
151	int nread;
152
153	CheckInit(dev);
154
155
156
157	if(data)
158	{
159		lseek(filedisk.handle,chunkInNAND * 528,SEEK_SET);
160		nread = read(filedisk.handle,data,512);
161
162		if(nread != 512) return YAFFS_FAIL;
163	}
164
165	if(spare)
166	{
167		lseek(filedisk.handle,chunkInNAND * 528 + 512,SEEK_SET);
168		nread= read(filedisk.handle,spare,16);
169
170		if(nread != 16) return YAFFS_FAIL;
171	}
172
173
174	return YAFFS_OK;
175
176}
177
178
179int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
180{
181
182	int i;
183
184	CheckInit(dev);
185
186	if(blockNumber < 0 || blockNumber >= filedisk.nBlocks)
187	{
188		T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
189		return YAFFS_FAIL;
190	}
191	else
192	{
193
194		yflash_Page pg;
195
196		memset(&pg,0xff,sizeof(yflash_Page));
197
198		lseek(filedisk.handle, blockNumber * 32 * 528, SEEK_SET);
199
200		for(i = 0; i < 32; i++)
201		{
202			write(filedisk.handle,&pg,528);
203		}
204		return YAFFS_OK;
205	}
206
207}
208
209int yflash_InitialiseNAND(yaffs_Device *dev)
210{
211	dev->useNANDECC = 1; // force on useNANDECC which gets faked.
212						 // This saves us doing ECC checks.
213
214	return YAFFS_OK;
215}
216
217
218