-
Notifications
You must be signed in to change notification settings - Fork 198
/
volume.c
128 lines (109 loc) · 2.8 KB
/
volume.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* volume.c
*
* Volume abstraction for low-level storage drivers.
*
* Written & released by Keir Fraser <[email protected]>
*
* This is free and unencumbered software released into the public domain.
* See the file COPYING for more details, or visit <http://unlicense.org>.
*/
extern struct volume_ops sd_ops;
extern struct volume_ops usb_ops;
static struct volume_ops *vol_ops = &usb_ops;
static struct cache *cache;
static void *metadata_addr;
#define SECSZ 512
#if !defined(BOOTLOADER)
void volume_cache_init(void *start, void *end)
{
volume_cache_destroy();
cache = cache_init(start, end, SECSZ);
}
void volume_cache_destroy(void)
{
cache = NULL;
metadata_addr = NULL;
}
void volume_cache_metadata_only(FIL *fp)
{
/* All metadata is accessed via the per-filesystem "sector window". */
metadata_addr = fp->obj.fs->win;
}
#endif
DSTATUS disk_initialize(BYTE pdrv)
{
/* Default to USB if inserted. */
vol_ops = &usb_ops;
if (!(usb_ops.initialize(pdrv) & STA_NOINIT))
goto out;
/* Try SD if the build and the board support it, and no USB drive is
* inserted. */
if ((board_id == BRDREV_Gotek_sd_card)
&& !usbh_msc_inserted()
&& !(sd_ops.initialize(pdrv) & STA_NOINIT)) {
vol_ops = &sd_ops;
}
out:
return disk_status(pdrv);
}
DSTATUS disk_status(BYTE pdrv)
{
return vol_ops->status(pdrv);
}
DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
{
DRESULT res;
const void *p;
struct cache *c;
if (((c = cache) == NULL)
|| (metadata_addr && (buff != metadata_addr)))
return vol_ops->read(pdrv, buff, sector, count);
while (count) {
if ((p = cache_lookup(c, sector)) == NULL)
goto read_tail;
memcpy(buff, p, SECSZ);
sector++;
count--;
buff += SECSZ;
}
return RES_OK;
read_tail:
res = vol_ops->read(pdrv, buff, sector, count);
if (res == RES_OK)
cache_update_N(c, sector, buff, count);
return res;
}
DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
{
DRESULT res = vol_ops->write(pdrv, buff, sector, count);
struct cache *c;
if ((res == RES_OK) && ((c = cache) != NULL)
&& (!metadata_addr || (buff == metadata_addr)))
cache_update_N(c, sector, buff, count);
return res;
}
DRESULT disk_ioctl(BYTE pdrv, BYTE ctrl, void *buff)
{
return vol_ops->ioctl(pdrv, ctrl, buff);
}
bool_t volume_connected(void)
{
/* Force switch to USB drive if inserted. */
if ((vol_ops == &sd_ops) && usbh_msc_inserted())
return FALSE;
return vol_ops->connected();
}
bool_t volume_readonly(void)
{
return vol_ops->readonly();
}
/*
* Local variables:
* mode: C
* c-file-style: "Linux"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/