embox

Форк
0
/
flash_fs.c 
230 строк · 5.1 Кб
1
/**
2
 * @brief Interface for flash subsystem. Device will appear in devfs
3
 *
4
 * @date 21.08.2013
5
 * @author Andrey Gazukin
6
 * @author Denis Deryugin
7
 */
8

9
#include <ctype.h>
10
#include <errno.h>
11
#include <limits.h>
12
#include <stdio.h>
13
#include <string.h>
14

15
#include <drivers/block_dev.h>
16
#include <drivers/flash/flash.h>
17
#include <util/err.h>
18

19
/* Interface for block device in devfs */
20
static int flashbdev_ioctl(struct block_dev *bdev, int cmd, void *buf,
21
    size_t size);
22
static int flashbdev_read(struct block_dev *bdev, char *buffer, size_t count,
23
    blkno_t blkno);
24
static int flashbdev_write(struct block_dev *bdev, char *buffer, size_t count,
25
    blkno_t blkno);
26

27
static const struct block_dev_ops flashbdev_pio_driver = {
28
    .bdo_ioctl = flashbdev_ioctl,
29
    .bdo_read = flashbdev_read,
30
    .bdo_write = flashbdev_write,
31
};
32

33
struct flash_dev *flash_create(const char *name, size_t size) {
34
	struct flash_dev *flash;
35
	char dev_name[FILENAME_MAX];
36

37
	assert(name);
38

39
	if (NULL == (flash = flash_alloc())) {
40
		return err2ptr(ENOMEM);
41
	}
42

43
	memset(dev_name, 0, sizeof(dev_name));
44
	snprintf(dev_name, sizeof(dev_name), "%s%d", name, flash->idx);
45

46
	flash->bdev = block_dev_create(dev_name, &flashbdev_pio_driver, flash);
47
	if (NULL == flash->bdev) {
48
		flash_free(flash);
49
		return err2ptr(EIO);
50
	}
51

52
	flash->bdev->size = size;
53

54
	flash->fld_word_size = 4;
55
	flash->fld_aligned_word = NULL;
56

57
	return flash;
58
}
59

60
int flash_delete(struct flash_dev *dev) {
61
	block_dev_destroy(dev->bdev);
62
	flash_free(dev);
63
	return 0;
64
}
65

66
/* Calls for access via devfs */
67
static int flashbdev_read(struct block_dev *bdev, char *buffer, size_t count,
68
    blkno_t blkno) {
69
	struct flash_dev *flash;
70
	uint32_t offset;
71

72
	assert(bdev);
73

74
	flash = block_dev_priv(bdev);
75
	assert(flash);
76

77
	//offset = flash_get_offset_by_block(flash, blkno);
78
	offset = bdev->block_size * blkno;
79

80
	return flash_read(flash, offset, buffer, count);
81
}
82

83
static int flashbdev_write(struct block_dev *bdev, char *buffer, size_t count,
84
    blkno_t blkno) {
85
	struct flash_dev *flash;
86
	uint32_t offset;
87

88
	assert(bdev);
89

90
	flash = block_dev_priv(bdev);
91
	assert(flash);
92

93
	//offset = flash_get_offset_by_block(flash, blkno);
94
	offset = bdev->block_size * blkno;
95

96
	return flash_write(flash, offset, buffer, count);
97
}
98

99
static int flashbdev_erase(struct flash_dev *dev, uint32_t flash_base,
100
    size_t len, uint32_t *err_address) {
101
	uint32_t cur_off, end_addr;
102
	int stat = 0;
103

104
	assert(dev);
105

106
	if ((!dev->drv) || (!dev->drv->flash_erase_block)) {
107
		return -EINVAL;
108
	}
109

110
	/* Check whether or not we are going past the end of this device, on
111
	 * to the next one. If so the next device will be handled by a
112
	 * recursive call later on.
113
	 */
114
	if ((dev->size - flash_base) < len) {
115
		end_addr = flash_base + dev->size;
116
	}
117
	else {
118
		end_addr = flash_base + len;
119
	}
120
	/* erase can only happen on a block boundary, so adjust for this */
121
	for (cur_off = flash_base; cur_off < end_addr; ) {
122
		int blk;
123
		
124
		blk = flash_get_block_by_offset(dev, cur_off);
125
		/* TODO we must be sure that it is start address of the block */
126
		assert(cur_off == flash_get_offset_by_block(dev, blk));
127

128
		stat = dev->drv->flash_erase_block(dev, blk);
129
		if (0 != stat) {
130
			if (err_address) {
131
				*err_address = cur_off;
132
			}
133
			break;
134
		}
135
		cur_off += flash_get_block_size(dev, blk);
136
	}
137

138
	return stat;
139
}
140

141
static int decode_flash_cmd(int cmd) {
142
	switch (cmd) {
143
	case IOCTL_GETBLKSIZE:
144
		return FLASH_IOCTL_BLOCKSIZE;
145
	case IOCTL_GETDEVSIZE:
146
		return FLASH_IOCTL_DEVSIZE;
147
	default:
148
		return cmd;
149
	}
150
}
151

152
static int flashbdev_ioctl(struct block_dev *bdev, int cmd, void *buf,
153
    size_t size) {
154
	struct flash_dev *dev;
155
	struct flash_ioctl_erase *e;
156
	uint32_t startpos, endpos;
157
	struct flash_ioctl_devsize *ds;
158
	struct flash_ioctl_devaddr *da;
159
	struct flash_ioctl_blocksize *bs;
160

161
	assert(bdev);
162

163
	dev = block_dev_priv(bdev);
164
	assert(dev);
165

166
	cmd = decode_flash_cmd(cmd);
167

168
	switch (cmd) {
169
	case FLASH_IOCTL_ERASE:
170
		e = (struct flash_ioctl_erase *)buf;
171
		startpos = e->offset;
172

173
		/* Unlike some other cases we _do_ do bounds checking on this all the time, because
174
		* the consequences of erasing the wrong bit of flash are so nasty.
175
		*/
176
		endpos = startpos + e->len - 1;
177

178
		if (endpos > dev->size) {
179
			return -EINVAL;
180
		}
181

182
		e->flasherr = flashbdev_erase(dev, startpos, e->len, &e->err_address);
183
		return ENOERR;
184

185
	case FLASH_IOCTL_DEVSIZE:
186
		ds = (struct flash_ioctl_devsize *)buf;
187

188
		if (NULL == ds) {
189
			return (dev->size + 1);
190
		}
191

192
		ds->dev_size = dev->size + 1;
193

194
		return ENOERR;
195

196
	case FLASH_IOCTL_DEVADDR:
197
		da = (struct flash_ioctl_devaddr *)buf;
198

199
		if (NULL == da) {
200
			return 0;
201
		}
202

203
		da->dev_addr = 0;
204

205
		return ENOERR;
206

207
	case FLASH_IOCTL_BLOCKSIZE:
208
		bs = (struct flash_ioctl_blocksize *)buf;
209
		/* NIY for num_block_infos > 1 */
210
		assert(dev->num_block_infos == 1); 
211
		if (NULL == bs) {
212
			/* FIXME FLASH block_size(0)*/
213
			return flash_get_block_size(dev, 0);
214
		}
215
		/* FIXME FLASH block_size(0)*/
216
		bs->block_size = flash_get_block_size(dev, 0);
217
		return ENOERR;
218

219
	default:
220
		return -EINVAL;
221
	}
222
}
223

224
/* XXX we have to do it because abstract modules
225
 * don't support unit init */
226
#include <embox/unit.h>
227
EMBOX_UNIT_INIT(_flash_devs_init);
228
static int _flash_devs_init(void) {
229
	return flash_devs_init();
230
}
231

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.