xref: /nrf52832-nimble/rt-thread/components/dfs/filesystems/uffs/src/emu/uffs_fileem_ecc_soft.c (revision 104654410c56c573564690304ae786df310c91fc)
1 /*
2   This file is part of UFFS, the Ultra-low-cost Flash File System.
3 
4   Copyright (C) 2005-2010 Ricky Zheng <[email protected]>
5 
6   UFFS is free software; you can redistribute it and/or modify it under
7   the GNU Library General Public License as published by the Free Software
8   Foundation; either version 2 of the License, or (at your option) any
9   later version.
10 
11   UFFS is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   or GNU Library General Public License, as applicable, for more details.
15 
16   You should have received a copy of the GNU General Public License
17   and GNU Library General Public License along with UFFS; if not, write
18   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19   Boston, MA  02110-1301, USA.
20 
21   As a special exception, if other files instantiate templates or use
22   macros or inline functions from this file, or you compile this file
23   and link it with other works to produce a work based on this file,
24   this file does not by itself cause the resulting work to be covered
25   by the GNU General Public License. However the source code for this
26   file must still be made available in accordance with section (3) of
27   the GNU General Public License v2.
28 
29   This exception does not invalidate any other reasons why a work based
30   on this file might be covered by the GNU General Public License.
31 */
32 
33 /**
34  * \file uffs_fileem_ecc_soft.c
35  * \brief emulate uffs file system for software ECC
36  * \author Ricky Zheng @ Oct, 2010
37  */
38 
39 #include <sys/types.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include "uffs_config.h"
44 #include "uffs/uffs_device.h"
45 #include "uffs/uffs_flash.h"
46 #include "uffs_fileem.h"
47 
48 #define PFX "femu: "
49 #define MSG(msg,...) uffs_PerrorRaw(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__)
50 #define MSGLN(msg,...) uffs_Perror(UFFS_MSG_NORMAL, msg, ## __VA_ARGS__)
51 
femu_WritePage(uffs_Device * dev,u32 block,u32 page_num,const u8 * data,int data_len,const u8 * spare,int spare_len)52 static int femu_WritePage(uffs_Device *dev, u32 block, u32 page_num,
53 							const u8 *data, int data_len, const u8 *spare, int spare_len)
54 {
55 	int written;
56 	int abs_page;
57 	int full_page_size;
58 	uffs_FileEmu *emu;
59 	struct uffs_StorageAttrSt *attr = dev->attr;
60 
61 	emu = (uffs_FileEmu *)(dev->attr->_private);
62 
63 	if (!emu || !(emu->fp)) {
64 		goto err;
65 	}
66 
67 	abs_page = attr->pages_per_block * block + page_num;
68 	full_page_size = attr->page_data_size + attr->spare_size;
69 
70 	if (data && data_len > 0) {
71 		if (data_len > attr->page_data_size)
72 			goto err;
73 
74 		emu->em_monitor_page[abs_page]++;
75 		if (emu->em_monitor_page[abs_page] > PAGE_DATA_WRITE_COUNT_LIMIT) {
76 			MSGLN("Warrning: block %d page %d exceed it's maximum write time!", block, page_num);
77 			goto err;
78 		}
79 
80 		fseek(emu->fp, abs_page * full_page_size, SEEK_SET);
81 
82 		written = fwrite(data, 1, data_len, emu->fp);
83 
84 		if (written != data_len) {
85 			MSGLN("write page I/O error ?");
86 			goto err;
87 		}
88 
89 		dev->st.page_write_count++;
90 		dev->st.io_write += written;
91 	}
92 
93 	if (spare && spare_len > 0) {
94 		if (spare_len > attr->spare_size)
95 			goto err;
96 
97 		emu->em_monitor_spare[abs_page]++;
98 		if (emu->em_monitor_spare[abs_page] > PAGE_SPARE_WRITE_COUNT_LIMIT) {
99 			MSGLN("Warrning: block %d page %d (spare) exceed it's maximum write time!", block, page_num);
100 			goto err;
101 		}
102 
103 		fseek(emu->fp, abs_page * full_page_size + attr->page_data_size, SEEK_SET);
104 		written = fwrite(spare, 1, spare_len, emu->fp);
105 		if (written != spare_len) {
106 			MSGLN("write spare I/O error ?");
107 			goto err;
108 		}
109 
110 		dev->st.spare_write_count++;
111 		dev->st.io_write += written;
112 	}
113 
114 	if (data == NULL && spare == NULL) {
115 		// mark bad block
116 		fseek(emu->fp, abs_page * full_page_size + attr->page_data_size + attr->block_status_offs, SEEK_SET);
117 		written = fwrite("\0", 1, 1, emu->fp);
118 		if (written != 1) {
119 			MSGLN("write bad block mark I/O error ?");
120 			goto err;
121 		}
122 		dev->st.io_write++;
123 	}
124 
125 	fflush(emu->fp);
126 	return UFFS_FLASH_NO_ERR;
127 err:
128 	fflush(emu->fp);
129 	return UFFS_FLASH_IO_ERR;
130 }
131 
132 
femu_ReadPage(uffs_Device * dev,u32 block,u32 page_num,u8 * data,int data_len,u8 * ecc,u8 * spare,int spare_len)133 static URET femu_ReadPage(uffs_Device *dev, u32 block, u32 page_num, u8 *data, int data_len, u8 *ecc,
134 							u8 *spare, int spare_len)
135 {
136 	int nread;
137 	uffs_FileEmu *emu;
138 	int abs_page;
139 	int full_page_size;
140 	struct uffs_StorageAttrSt *attr = dev->attr;
141 	unsigned char status;
142 
143 	emu = (uffs_FileEmu *)(dev->attr->_private);
144 
145 	if (!emu || !(emu->fp)) {
146 		goto err;
147 	}
148 
149 	abs_page = attr->pages_per_block * block + page_num;
150 	full_page_size = attr->page_data_size + attr->spare_size;
151 
152 	if (data && data_len > 0) {
153 		if (data_len > attr->page_data_size)
154 			goto err;
155 
156 		fseek(emu->fp, abs_page * full_page_size, SEEK_SET);
157 		nread = fread(data, 1, data_len, emu->fp);
158 
159 		if (nread != data_len) {
160 			MSGLN("read page I/O error ?");
161 			goto err;
162 		}
163 		dev->st.io_read += nread;
164 		dev->st.page_read_count++;
165 	}
166 
167 	if (spare && spare_len > 0) {
168 		if (spare_len > attr->spare_size)
169 			goto err;
170 
171 		fseek(emu->fp, abs_page * full_page_size + attr->page_data_size, SEEK_SET);
172 		nread = fread(spare, 1, spare_len, emu->fp);
173 
174 		if (nread != spare_len) {
175 			MSGLN("read page spare I/O error ?");
176 			goto err;
177 		}
178 		dev->st.io_read += nread;
179 		dev->st.spare_read_count++;
180 	}
181 
182 	if (data == NULL && spare == NULL) {
183 		// read bad block mark
184 		fseek(emu->fp, abs_page * full_page_size + attr->page_data_size + attr->block_status_offs, SEEK_SET);
185 		nread = fread(&status, 1, 1, emu->fp);
186 
187 		if (nread != 1) {
188 			MSGLN("read badblock mark I/O error ?");
189 			goto err;
190 		}
191 		dev->st.io_read++;
192 
193 		return status == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK;
194 	}
195 
196 	return UFFS_FLASH_NO_ERR;
197 err:
198 	return UFFS_FLASH_IO_ERR;
199 }
200 
201 
202 uffs_FlashOps g_femu_ops_ecc_soft = {
203 	femu_InitFlash,		// InitFlash()
204 	femu_ReleaseFlash,	// ReleaseFlash()
205 	femu_ReadPage,		// ReadPage()
206 	NULL,				// ReadPageWithLayout
207 	femu_WritePage,		// WritePage()
208 	NULL,				// WirtePageWithLayout
209 	NULL,				// IsBadBlock(), let UFFS take care of it.
210 	NULL,				// MarkBadBlock(), let UFFS take care of it.
211 	femu_EraseBlock,	// EraseBlock()
212 };
213