]> git.gag.com Git - fw/altos/blob - src/core/ao_storage.c
altos: Do not block igniters on the radio mutex.
[fw/altos] / src / core / ao_storage.c
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include <ao.h>
19
20 uint8_t
21 ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
22 {
23         uint16_t this_len;
24         uint16_t this_off;
25
26         ao_storage_setup();
27         if (pos >= ao_storage_total || pos + len > ao_storage_total)
28                 return 0;
29         while (len) {
30
31                 /* Compute portion of transfer within
32                  * a single block
33                  */
34                 this_off = (uint16_t) pos & (ao_storage_unit - 1);
35                 this_len = ao_storage_unit - this_off;
36                 if (this_len > len)
37                         this_len = len;
38
39                 if (!ao_storage_device_read(pos, buf, this_len))
40                         return 0;
41
42                 /* See how much is left */
43                 buf += this_len;
44                 len -= this_len;
45                 pos += this_len;
46         }
47         return 1;
48 }
49
50 uint8_t
51 ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant
52 {
53         uint16_t this_len;
54         uint16_t this_off;
55
56         ao_storage_setup();
57         if (pos >= ao_storage_total || pos + len > ao_storage_total)
58                 return 0;
59         while (len) {
60
61                 /* Compute portion of transfer within
62                  * a single block
63                  */
64                 this_off = (uint16_t) pos & (ao_storage_unit - 1);
65                 this_len = ao_storage_unit - this_off;
66                 if (this_len > len)
67                         this_len = len;
68
69                 if (!ao_storage_device_write(pos, buf, this_len))
70                         return 0;
71
72                 /* See how much is left */
73                 buf += this_len;
74                 len -= this_len;
75                 pos += this_len;
76         }
77         return 1;
78 }
79
80 static __xdata uint8_t storage_data[8];
81
82 static void
83 ao_storage_dump(void) __reentrant
84 {
85         uint8_t i, j;
86
87         ao_cmd_hex();
88         if (ao_cmd_status != ao_cmd_success)
89                 return;
90         for (i = 0; ; i += 8) {
91                 if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i,
92                                   storage_data,
93                                   8)) {
94                         ao_cmd_put16((uint16_t) i);
95                         for (j = 0; j < 8; j++) {
96                                 putchar(' ');
97                                 ao_cmd_put8(storage_data[j]);
98                         }
99                         putchar ('\n');
100                 }
101                 if (i == 248)
102                         break;
103         }
104 }
105
106 #if HAS_STORAGE_DEBUG
107
108 /* not enough space for this today
109  */
110 static void
111 ao_storage_store(void) __reentrant
112 {
113         uint16_t block;
114         uint8_t i;
115         uint16_t len;
116         static __xdata uint8_t b;
117         uint32_t addr;
118
119         ao_cmd_hex();
120         block = ao_cmd_lex_i;
121         ao_cmd_hex();
122         i = ao_cmd_lex_i;
123         addr = ((uint32_t) block << 8) | i;
124         ao_cmd_hex();
125         len = ao_cmd_lex_i;
126         if (ao_cmd_status != ao_cmd_success)
127                 return;
128         while (len--) {
129                 ao_cmd_hex();
130                 if (ao_cmd_status != ao_cmd_success)
131                         return;
132                 b = ao_cmd_lex_i;
133                 ao_storage_write(addr, &b, 1);
134                 addr++;
135         }
136 }
137 #endif
138
139 void
140 ao_storage_zap(void) __reentrant
141 {
142         ao_cmd_hex();
143         if (ao_cmd_status != ao_cmd_success)
144                 return;
145         ao_storage_erase((uint32_t) ao_cmd_lex_i << 8);
146 }
147
148 void
149 ao_storage_zapall(void) __reentrant
150 {
151         uint32_t        pos;
152
153         ao_cmd_white();
154         if (!ao_match_word("DoIt"))
155                 return;
156         for (pos = 0; pos < ao_storage_config; pos += ao_storage_block)
157                 ao_storage_erase(pos);
158 }
159
160 void
161 ao_storage_info(void) __reentrant
162 {
163         ao_storage_setup();
164         printf("Storage size: %ld\n", ao_storage_total);
165         printf("Storage erase unit: %ld\n", ao_storage_block);
166         ao_storage_device_info();
167 }
168
169 __code struct ao_cmds ao_storage_cmds[] = {
170         { ao_storage_info, "f\0Show storage" },
171         { ao_storage_dump, "e <block>\0Dump flash" },
172 #if HAS_STORAGE_DEBUG
173         { ao_storage_store, "w <block> <start> <len> <data> ...\0Write data to flash" },
174 #endif
175         { ao_storage_zap, "z <block>\0Erase <block>" },
176         { ao_storage_zapall,"Z <key>\0Erase all. <key> is doit with D&I" },
177         { 0, NULL },
178 };
179
180 void
181 ao_storage_init(void)
182 {
183         ao_storage_device_init();
184         ao_cmd_register(&ao_storage_cmds[0]);
185 }