Move around the option in Kconfig so that depending stuff are nicely indented.
[yaffs2.git] / yaffs_mtdif.c
1 /*
2  * YAFFS: Yet another FFS. A NAND-flash specific file system. 
3  * yaffs_mtdif.c  NAND mtd wrapper functions.
4  *
5  * Copyright (C) 2002 Aleph One Ltd.
6  *   for Toby Churchill Ltd and Brightstar Engineering
7  *
8  * Created by Charles Manning <charles@aleph1.co.uk>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  */
15
16 const char *yaffs_mtdif_c_version = "$Id: yaffs_mtdif.c,v 1.7 2005-08-01 20:52:35 luc Exp $";
17  
18 #include "yportenv.h"
19
20 #ifdef CONFIG_YAFFS_YAFFS1
21
22 #include "yaffs_mtdif.h"
23
24 #include "linux/mtd/mtd.h"
25 #include "linux/types.h"
26 #include "linux/time.h"
27 #include "linux/mtd/nand.h"
28
29 static struct nand_oobinfo yaffs_oobinfo = {
30         .useecc = 1,
31         .eccpos = {8, 9, 10, 13, 14, 15}
32 };
33
34 static struct nand_oobinfo yaffs_noeccinfo = {
35         .useecc = 0,
36 };
37
38
39 int nandmtd_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare)
40 {
41         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
42         size_t dummy;
43     int retval = 0;
44         
45         loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk;
46         
47         __u8 *spareAsBytes = (__u8 *)spare;
48
49         if(data && spare)
50         {
51                 if(dev->useNANDECC)
52                         mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_oobinfo);
53                 else
54                         mtd->write_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_noeccinfo);
55         }
56         else
57         {
58         if(data)
59                 retval = mtd->write(mtd,addr,dev->nBytesPerChunk,&dummy,data);
60         if(spare)
61                 retval = mtd->write_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes);
62         }
63
64     if (retval == 0)
65         return YAFFS_OK;
66     else
67         return YAFFS_FAIL;
68 }
69
70 int nandmtd_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare)
71 {
72         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
73         size_t dummy;
74     int retval = 0;
75         
76         loff_t addr = ((loff_t)chunkInNAND) * dev->nBytesPerChunk;
77         
78         __u8 *spareAsBytes = (__u8 *)spare;
79         
80         if(data && spare)
81         {
82                 if(dev->useNANDECC)
83                 {   // Careful, this call adds 2 ints to the end of the spare data.  Calling function should
84             // allocate enough memory for spare, i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)].
85                 retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_oobinfo);            
86                 }
87                 else
88                 {
89                         retval = mtd->read_ecc(mtd,addr,dev->nBytesPerChunk,&dummy,data,spareAsBytes,&yaffs_noeccinfo);
90                 }
91         }
92         else
93         {
94         if(data)
95                 retval = mtd->read(mtd,addr,dev->nBytesPerChunk,&dummy,data);
96         if(spare)
97                 retval = mtd->read_oob(mtd,addr,YAFFS_BYTES_PER_SPARE,&dummy,spareAsBytes);
98         }
99
100     if (retval == 0)
101         return YAFFS_OK;
102     else
103         return YAFFS_FAIL;
104 }
105
106 // Callback not needed for NAND
107 #if 0
108 static void nandmtd_EraseCallback(struct erase_info *ei)
109 {
110         yaffs_Device *dev = (yaffs_Device *)ei->priv;   
111         up(&dev->sem);
112 }
113 #endif
114
115
116 int nandmtd_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
117 {
118         struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
119         __u32 addr = ((loff_t) blockNumber) * dev->nBytesPerChunk * dev->nChunksPerBlock;
120         struct erase_info ei;
121     int retval = 0;
122         
123         ei.mtd = mtd;
124         ei.addr = addr;
125         ei.len = dev->nBytesPerChunk * dev->nChunksPerBlock;
126         ei.time = 1000;
127         ei.retries = 2;
128         ei.callback = NULL;
129         ei.priv = (u_long)dev;
130         
131         // Todo finish off the ei if required
132         
133         sema_init(&dev->sem,0);
134
135         retval = mtd->erase(mtd,&ei);   
136         
137         //No need for callback 
138         // down(&dev->sem); // Wait for the erasure to complete
139
140     if (retval == 0)    
141         return YAFFS_OK;
142     else
143         return YAFFS_FAIL;
144 }
145
146 int nandmtd_InitialiseNAND(yaffs_Device *dev)
147 {
148         return YAFFS_OK;
149 }
150
151 #endif // CONFIG_YAFFS_YAFFS1
152