7b3b5e8b78a5e213d0a55ea3d03c2e8e24a1b2b8
[my-code/arm.git] / betty / pffs.c
1 /*
2  * pffs.c - pseudo flash filesystem
3  *
4  * author: hackbard@hackdaworld.org
5  *
6  */
7
8 #include "pffs.h"
9
10 /*
11  * functions
12  */
13
14 u32 pffs_get_ptr(t_pffs *pffs,u8 sector) {
15
16         u16 data[3];
17         u32 iaddr;
18         u32 daddr;
19         u8 fnlen;
20         u8 found;
21
22         iaddr=0;
23         daddr=0;
24         found=0;
25
26         while(1) {
27                 pffs->fr(pffs->base_addr+pffs->sec_addr[sector]+iaddr,data,6);
28                 if(!((data[0]&0xff00)==PFFS_INDEX_MAGIC))
29                         break;
30                 found=1;
31                 fnlen=(data[0]&0x00f0)>>4;
32                 iaddr+=(6+fnlen+fnlen);
33                 daddr=((data[0]&0x000f)<<16)|data[1];
34         }
35
36         pffs->data_ptr=daddr;
37
38         if(found) {
39                 pffs->index_ptr=pffs->sec_addr[sector]+iaddr;
40                 return 0;
41         }
42         else
43                 return -1;
44 }
45
46 int pffs_sec_empty(t_pffs *pffs,u8 sec) {
47
48         u32 addr;
49         u16 data;
50
51         addr=pffs->base_addr|pffs->sec_addr[sec];
52
53         while(addr<(pffs->base_addr|pffs->sec_addr[sec+1])) {
54                 data=*((u16 *)(addr));
55                 if(data!=0xffff)
56                         return 0;
57                 addr+=2;
58         }
59
60         return 1;
61 }
62
63 #define pffs_sec_erase(pffs,sec) pffs->fe(pffs->base_addr|pffs->sec_addr[sec])
64
65 int pffs_reorientate(t_pffs *pffs) {
66
67         u8 sec,sec0,sec1;
68
69         /* check index sectors */
70         sec0=pffs->sec_num_index[0];
71         sec1=pffs->sec_num_index[1];
72         if(!(pffs_get_ptr(pffs,sec0)&pffs_get_ptr(pffs,sec1)))
73                 return 0;
74
75         /* initial run => no data + no index assumed => check whether erased! */
76         // erase index sectors
77         if(!pffs_sec_empty(pffs,sec0))
78                 pffs_sec_erase(pffs,sec0);
79         if(!pffs_sec_empty(pffs,sec1))
80                 pffs_sec_erase(pffs,sec1);
81         // erase data sectors
82         sec0=pffs->sec_num_data[0];
83         sec1=pffs->sec_num_data[1];
84         for(sec=sec0;sec<=sec1;sec++)
85                 if(!pffs_sec_empty(pffs,sec))
86                         pffs_sec_erase(pffs,sec);
87
88         return 0;
89 }
90
91 int pffs_flash_register(t_pffs *pffs,u32 base_addr,u8 sec_num,u32 *sec_addr,
92                         u8 sec_num_data_min,u8 sec_num_data_max,
93                         u8 sec_num_index0,u8 sec_num_index1,
94                         int (*fw)(u32 addr,u16 *buf,int len),
95                         int (*fr)(u32 addr,u16 *buf,int len),
96                         int (*fe)(u32 addr)) {
97
98         /* assign physical flash specs */
99         pffs->base_addr=base_addr;
100         pffs->sec_num=sec_num;
101         pffs->sec_addr=sec_addr;
102
103         /* specified index and data sectors */
104         pffs->sec_num_data[0]=sec_num_data_min;
105         pffs->sec_num_data[1]=sec_num_data_max;
106         pffs->sec_num_index[0]=sec_num_index0;
107         pffs->sec_num_index[1]=sec_num_index1;
108
109         /* flash acccess function pointers */
110         pffs->fw=fw;
111         pffs->fr=fr;
112         pffs->fe=fe;
113
114         /* orientate */
115         pffs_reorientate(pffs);
116
117         pffs->state|=PFFS_REGISTERED;
118
119         return 0;
120 }
121
122 int pffs_init(t_pffs *pffs) {
123
124         if(!(pffs->state&PFFS_REGISTERED))
125                 return -1;
126
127         return 0;
128 }
129