]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/fs/jffs2/v2_0/src/flashio.c
Initial revision
[karo-tx-redboot.git] / packages / fs / jffs2 / v2_0 / src / flashio.c
1 /*
2  * JFFS2 -- Journalling Flash File System, Version 2.
3  *
4  * Copyright (C) 2001-2003 Red Hat, Inc.
5  *
6  * Created by Dominic Ostrowski <dominic.ostrowski@3glab.com>
7  * Contributors: David Woodhouse, Nick Garnett, Richard Panton.
8  *
9  * For licensing information, see the file 'LICENCE' in this directory.
10  *
11  * $Id$
12  *
13  */
14
15 #include <linux/kernel.h>
16 #include "nodelist.h"
17
18 #include <cyg/io/io.h>
19 #include <cyg/io/config_keys.h>
20 #include <cyg/io/flash.h>
21
22 cyg_bool jffs2_flash_read(struct jffs2_sb_info * c,
23                           cyg_uint32 read_buffer_offset, const size_t size,
24                           size_t * return_size, unsigned char *write_buffer)
25 {
26         Cyg_ErrNo err;
27         cyg_uint32 len = size;
28         struct super_block *sb = OFNI_BS_2SFFJ(c);
29
30         //D2(printf("FLASH READ\n"));
31         //D2(printf("read address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + read_buffer_offset));
32         //D2(printf("write address = %x\n", write_buffer));
33         //D2(printf("size = %x\n", size));
34         err = cyg_io_bread(sb->s_dev, write_buffer, &len, read_buffer_offset);
35
36         *return_size = (size_t) len;
37         return ((err == ENOERR) ? ENOERR : -EIO);
38 }
39
40 cyg_bool jffs2_flash_write(struct jffs2_sb_info * c,
41                            cyg_uint32 write_buffer_offset, const size_t size,
42                            size_t * return_size, unsigned char *read_buffer)
43 {
44
45         Cyg_ErrNo err;
46         cyg_uint32 len = size;
47         struct super_block *sb = OFNI_BS_2SFFJ(c);
48
49         //    D2(printf("FLASH WRITE ENABLED!!!\n"));
50         //    D2(printf("write address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + write_buffer_offset));
51         //    D2(printf("read address = %x\n", read_buffer));
52         //    D2(printf("size = %x\n", size));
53
54         err = cyg_io_bwrite(sb->s_dev, read_buffer, &len, write_buffer_offset);
55         *return_size = (size_t) len;
56
57         return ((err == ENOERR) ? ENOERR : -EIO);
58 }
59
60 int
61 jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs,
62                    unsigned long count, loff_t to, size_t * retlen)
63 {
64         unsigned long i;
65         size_t totlen = 0, thislen;
66         int ret = 0;
67
68         for (i = 0; i < count; i++) {
69                 // writes need to be aligned but the data we're passed may not be
70                 // Observation suggests most unaligned writes are small, so we
71                 // optimize for that case.
72
73                 if (((vecs[i].iov_len & (sizeof (int) - 1))) ||
74                     (((unsigned long) vecs[i].
75                       iov_base & (sizeof (unsigned long) - 1)))) {
76                         // are there iov's after this one? Or is it so much we'd need
77                         // to do multiple writes anyway?
78                         if ((i + 1) < count || vecs[i].iov_len > 256) {
79                                 // cop out and malloc
80                                 unsigned long j;
81                                 ssize_t sizetomalloc = 0, totvecsize = 0;
82                                 char *cbuf, *cbufptr;
83
84                                 for (j = i; j < count; j++)
85                                         totvecsize += vecs[j].iov_len;
86
87                                 // pad up in case unaligned
88                                 sizetomalloc = totvecsize + sizeof (int) - 1;
89                                 sizetomalloc &= ~(sizeof (int) - 1);
90                                 cbuf = (char *) malloc(sizetomalloc);
91                                 // malloc returns aligned memory
92                                 if (!cbuf) {
93                                         ret = -ENOMEM;
94                                         goto writev_out;
95                                 }
96                                 cbufptr = cbuf;
97                                 for (j = i; j < count; j++) {
98                                         memcpy(cbufptr, vecs[j].iov_base,
99                                                vecs[j].iov_len);
100                                         cbufptr += vecs[j].iov_len;
101                                 }
102                                 ret =
103                                     jffs2_flash_write(c, to, sizetomalloc,
104                                                       &thislen, cbuf);
105                                 if (thislen > totvecsize)       // in case it was aligned up
106                                         thislen = totvecsize;
107                                 totlen += thislen;
108                                 free(cbuf);
109                                 goto writev_out;
110                         } else {
111                                 // otherwise optimize for the common case
112                                 int buf[256 / sizeof (int)];    // int, so int aligned
113                                 size_t lentowrite;
114
115                                 lentowrite = vecs[i].iov_len;
116                                 // pad up in case its unaligned
117                                 lentowrite += sizeof (int) - 1;
118                                 lentowrite &= ~(sizeof (int) - 1);
119                                 memcpy(buf, vecs[i].iov_base, lentowrite);
120
121                                 ret =
122                                     jffs2_flash_write(c, to, lentowrite,
123                                                       &thislen, (char *) &buf);
124                                 if (thislen > vecs[i].iov_len)
125                                         thislen = vecs[i].iov_len;
126                         }       // else
127                 } else
128                         ret =
129                             jffs2_flash_write(c, to, vecs[i].iov_len, &thislen,
130                                               vecs[i].iov_base);
131                 totlen += thislen;
132                 if (ret || thislen != vecs[i].iov_len)
133                         break;
134                 to += vecs[i].iov_len;
135         }
136       writev_out:
137         if (retlen)
138                 *retlen = totlen;
139
140         return ret;
141 }
142
143 cyg_bool jffs2_flash_erase(struct jffs2_sb_info * c,
144                            struct jffs2_eraseblock * jeb)
145 {
146         cyg_io_flash_getconfig_erase_t e;
147         void *err_addr;
148         Cyg_ErrNo err;
149         cyg_uint32 len = sizeof (e);
150         struct super_block *sb = OFNI_BS_2SFFJ(c);
151
152         e.offset = jeb->offset;
153         e.len = c->sector_size;
154         e.err_address = &err_addr;
155
156         //        D2(printf("FLASH ERASE ENABLED!!!\n"));
157         //        D2(printf("erase address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + jeb->offset));
158         //        D2(printf("size = %x\n", c->sector_size));
159
160         err = cyg_io_get_config(sb->s_dev, CYG_IO_GET_CONFIG_FLASH_ERASE,
161                                 &e, &len);
162
163         return (err != ENOERR || e.flasherr != 0);
164 }
165