PP502x: Add some important information about CPU/COP_CTL register to the header glean...
[Rockbox.git] / apps / plugins / test_disk.c
blob5799f4ce0be2dde7256fdf93d9d03dd8e22623d1
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Jens Arnold
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "plugin.h"
21 #include "oldmenuapi.h"
23 PLUGIN_HEADER
25 #define TESTBASEDIR "/__TEST__"
26 #define TEST_FILE TESTBASEDIR "/test_disk.tmp"
27 #define FRND_SEED 0x78C3 /* arbirary */
29 #ifdef HAVE_MMC
30 #define TEST_SIZE (20*1024*1024)
31 #else
32 #define TEST_SIZE (300*1024*1024)
33 #endif
34 #define TEST_TIME 10 /* in seconds */
36 static struct plugin_api* rb;
37 static unsigned char* audiobuf;
38 static ssize_t audiobuflen;
40 static unsigned short frnd_buffer;
41 static int line = 0;
42 static int max_line = 0;
43 static int log_fd;
44 static char logfilename[MAX_PATH];
45 static const char testbasedir[] = TESTBASEDIR;
47 static void mem_fill_frnd(unsigned char *addr, int len)
49 unsigned char *end = addr + len;
50 unsigned random = frnd_buffer;
52 while (addr < end)
54 random = 75 * random + 74;
55 *addr++ = random >> 8;
57 frnd_buffer = random;
60 static bool mem_cmp_frnd(unsigned char *addr, int len)
62 unsigned char *end = addr + len;
63 unsigned random = frnd_buffer;
65 while (addr < end)
67 random = 75 * random + 74;
68 if (*addr++ != ((random >> 8) & 0xff))
69 return false;
71 frnd_buffer = random;
72 return true;
75 static bool log_init(void)
77 int h;
79 rb->lcd_setmargins(0, 0);
80 rb->lcd_getstringsize("A", NULL, &h);
81 max_line = LCD_HEIGHT / h;
82 line = 0;
83 rb->lcd_clear_display();
84 rb->lcd_update();
86 rb->create_numbered_filename(logfilename, "/", "test_disk_log_", ".txt",
87 2 IF_CNFN_NUM_(, NULL));
88 log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC);
89 return log_fd >= 0;
92 static void log_text(char *text, bool advance)
94 rb->lcd_puts(0, line, text);
95 rb->lcd_update();
96 if (advance)
98 if (++line >= max_line)
99 line = 0;
100 rb->fdprintf(log_fd, "%s\n", text);
104 static void log_close(void)
106 rb->close(log_fd);
109 static bool test_fs(void)
111 unsigned char text_buf[32];
112 int total, current, align;
113 int fd;
115 log_init();
116 log_text("test_disk WRITE&VERIFY", true);
117 rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
118 *rb->cpu_frequency);
119 log_text(text_buf, true);
120 log_text("----------------------", true);
121 rb->snprintf(text_buf, sizeof text_buf, "Data size: %dKB", (TEST_SIZE>>10));
122 log_text(text_buf, true);
124 fd = rb->creat(TEST_FILE);
125 if (fd < 0)
127 rb->splash(HZ, "creat() failed.");
128 goto error;
131 frnd_buffer = FRND_SEED;
132 total = TEST_SIZE;
133 while (total > 0)
135 current = rb->rand() % (audiobuflen - 4);
136 current = MIN(current, total);
137 align = rb->rand() & 3;
138 rb->snprintf(text_buf, sizeof text_buf, "Wrt %dKB, %dKB left",
139 current >> 10, total >> 10);
140 log_text(text_buf, false);
142 mem_fill_frnd(audiobuf + align, current);
143 if (current != rb->write(fd, audiobuf + align, current))
145 rb->splash(0, "write() failed.");
146 rb->close(fd);
147 goto error;
149 total -= current;
151 rb->close(fd);
153 fd = rb->open(TEST_FILE, O_RDONLY);
154 if (fd < 0)
156 rb->splash(0, "open() failed.");
157 goto error;
160 frnd_buffer = FRND_SEED;
161 total = TEST_SIZE;
162 while (total > 0)
164 current = rb->rand() % (audiobuflen - 4);
165 current = MIN(current, total);
166 align = rb->rand() & 3;
167 rb->snprintf(text_buf, sizeof text_buf, "Cmp %dKB, %dKB left",
168 current >> 10, total >> 10);
169 log_text(text_buf, false);
171 if (current != rb->read(fd, audiobuf + align, current))
173 rb->splash(0, "read() failed.");
174 rb->close(fd);
175 goto error;
177 if (!mem_cmp_frnd(audiobuf + align, current))
179 log_text(text_buf, true);
180 log_text("Compare error.", true);
181 rb->close(fd);
182 goto error;
184 total -= current;
186 rb->close(fd);
187 log_text(text_buf, true);
188 log_text("Test passed.", true);
190 error:
191 log_close();
192 rb->remove(TEST_FILE);
193 rb->button_clear_queue();
194 rb->button_get(true);
196 return false;
199 static bool file_speed(int chunksize, bool align)
201 unsigned char text_buf[64];
202 int fd;
203 long filesize = 0;
204 long size, time;
206 if (chunksize >= audiobuflen)
207 return false;
209 log_text("--------------------", true);
211 /* File creation write speed */
212 fd = rb->creat(TEST_FILE);
213 if (fd < 0)
215 rb->splash(HZ, "creat() failed.");
216 goto error;
218 time = *rb->current_tick;
219 while (TIME_BEFORE(*rb->current_tick, time + TEST_TIME*HZ))
221 if (chunksize != rb->write(fd, audiobuf + (align ? 0 : 1), chunksize))
223 rb->splash(HZ, "write() failed.");
224 rb->close(fd);
225 goto error;
227 filesize += chunksize;
229 time = *rb->current_tick - time;
230 rb->close(fd);
231 rb->snprintf(text_buf, sizeof text_buf, "Create (%d,%c): %ld KB/s",
232 chunksize, align ? 'A' : 'U', (25 * filesize / time) >> 8);
233 log_text(text_buf, true);
235 /* Existing file write speed */
236 fd = rb->open(TEST_FILE, O_WRONLY);
237 if (fd < 0)
239 rb->splash(0, "open() failed.");
240 goto error;
242 time = *rb->current_tick;
243 for (size = filesize; size > 0; size -= chunksize)
245 if (chunksize != rb->write(fd, audiobuf + (align ? 0 : 1), chunksize))
247 rb->splash(0, "write() failed.");
248 rb->close(fd);
249 goto error;
252 time = *rb->current_tick - time;
253 rb->close(fd);
254 rb->snprintf(text_buf, sizeof text_buf, "Write (%d,%c): %ld KB/s",
255 chunksize, align ? 'A' : 'U', (25 * filesize / time) >> 8);
256 log_text(text_buf, true);
258 /* File read speed */
259 fd = rb->open(TEST_FILE, O_RDONLY);
260 if (fd < 0)
262 rb->splash(0, "open() failed.");
263 goto error;
265 time = *rb->current_tick;
266 for (size = filesize; size > 0; size -= chunksize)
268 if (chunksize != rb->read(fd, audiobuf + (align ? 0 : 1), chunksize))
270 rb->splash(0, "read() failed.");
271 rb->close(fd);
272 goto error;
275 time = *rb->current_tick - time;
276 rb->close(fd);
277 rb->snprintf(text_buf, sizeof text_buf, "Read (%d,%c): %ld KB/s",
278 chunksize, align ? 'A' : 'U', (25 * filesize / time) >> 8);
279 log_text(text_buf, true);
280 rb->remove(TEST_FILE);
281 return true;
283 error:
284 rb->remove(TEST_FILE);
285 return false;
288 static bool test_speed(void)
290 unsigned char text_buf[64];
291 DIR *dir = NULL;
292 struct dirent *entry = NULL;
293 int fd, last_file;
294 int i, n;
295 long time;
297 rb->memset(audiobuf, 'T', audiobuflen);
298 log_init();
299 log_text("test_disk SPEED TEST", true);
300 rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
301 *rb->cpu_frequency);
302 log_text(text_buf, true);
303 log_text("--------------------", true);
305 /* File creation speed */
306 time = *rb->current_tick + TEST_TIME*HZ;
307 for (i = 0; TIME_BEFORE(*rb->current_tick, time); i++)
309 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
310 fd = rb->creat(text_buf);
311 if (fd < 0)
313 last_file = i;
314 rb->splash(HZ, "creat() failed.");
315 goto error;
317 rb->close(fd);
319 last_file = i;
320 rb->snprintf(text_buf, sizeof(text_buf), "Create: %d files/s",
321 last_file / TEST_TIME);
322 log_text(text_buf, true);
324 /* File open speed */
325 time = *rb->current_tick + TEST_TIME*HZ;
326 for (n = 0, i = 0; TIME_BEFORE(*rb->current_tick, time); n++, i++)
328 if (i >= last_file)
329 i = 0;
330 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
331 fd = rb->open(text_buf, O_RDONLY);
332 if (fd < 0)
334 rb->splash(HZ, "open() failed.");
335 goto error;
337 rb->close(fd);
339 rb->snprintf(text_buf, sizeof(text_buf), "Open: %d files/s", n / TEST_TIME);
340 log_text(text_buf, true);
342 /* Directory scan speed */
343 time = *rb->current_tick + TEST_TIME*HZ;
344 for (n = 0; TIME_BEFORE(*rb->current_tick, time); n++)
346 if (entry == NULL)
348 if (dir != NULL)
349 rb->closedir(dir);
350 dir = rb->opendir(testbasedir);
351 if (dir == NULL)
353 rb->splash(HZ, "opendir() failed.");
354 goto error;
357 entry = rb->readdir(dir);
359 rb->closedir(dir);
360 rb->snprintf(text_buf, sizeof(text_buf), "Dirscan: %d files/s", n / TEST_TIME);
361 log_text(text_buf, true);
363 /* File delete speed */
364 time = *rb->current_tick;
365 for (i = 0; i < last_file; i++)
367 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
368 rb->remove(text_buf);
370 rb->snprintf(text_buf, sizeof(text_buf), "Delete: %ld files/s",
371 last_file * HZ / (*rb->current_tick - time));
372 log_text(text_buf, true);
374 if (file_speed(512, true)
375 && file_speed(512, false)
376 && file_speed(4096, true)
377 && file_speed(4096, false)
378 && file_speed(1048576, true))
379 file_speed(1048576, false);
381 log_text("DONE", false);
382 log_close();
383 rb->button_clear_queue();
384 rb->button_get(true);
385 return false;
387 error:
388 for (i = 0; i < last_file; i++)
390 rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
391 rb->remove(text_buf);
393 log_text("DONE", false);
394 log_close();
395 rb->button_clear_queue();
396 rb->button_get(true);
397 return false;
401 /* this is the plugin entry point */
402 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
404 static const struct menu_item items[] = {
405 { "Disk speed", test_speed },
406 { "Write & verify", test_fs },
408 int m;
409 int align;
410 DIR *dir;
412 (void)parameter;
413 rb = api;
415 if ((dir = rb->opendir(testbasedir)) == NULL)
417 if (rb->mkdir(testbasedir) < 0)
419 rb->splash(HZ*2, "Can't create test directory.");
420 return PLUGIN_ERROR;
423 else
425 rb->closedir(dir);
428 audiobuf = rb->plugin_get_audio_buffer((size_t *)&audiobuflen);
429 /* align start and length to 32 bit */
430 align = (-(int)audiobuf) & 3;
431 audiobuf += align;
432 audiobuflen = (audiobuflen - align) & ~3;
434 rb->srand(*rb->current_tick);
436 if (rb->global_settings->backlight_timeout > 0)
437 rb->backlight_set_timeout(1); /* keep the light on */
439 m = menu_init(rb, items, sizeof(items) / sizeof(*items), NULL,
440 NULL, NULL, NULL);
441 menu_run(m);
442 menu_exit(m);
444 /* restore normal backlight setting */
445 rb->backlight_set_timeout(rb->global_settings->backlight_timeout);
447 rb->rmdir(testbasedir);
449 return PLUGIN_OK;