summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/buffer.c75
-rw-r--r--firmware/common/dircache.c22
-rw-r--r--firmware/export/audio.h6
-rw-r--r--firmware/include/buffer.h18
-rw-r--r--firmware/include/dircache.h3
-rw-r--r--firmware/rolo.c28
6 files changed, 119 insertions, 33 deletions
diff --git a/firmware/buffer.c b/firmware/buffer.c
index c317cec924..2168087bd9 100644
--- a/firmware/buffer.c
+++ b/firmware/buffer.c
@@ -19,19 +19,33 @@
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include <stdio.h> 21#include <stdio.h>
22#include <stdint.h>
23#include "system.h"
22#include "buffer.h" 24#include "buffer.h"
23#include "panic.h" 25#include "panic.h"
24#include "logf.h" 26#include "logf.h"
25 27
26#if (CONFIG_PLATFORM & PLATFORM_HOSTED) 28#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
27unsigned char audiobuffer[(MEMORYSIZE*1024-256)*1024];
28unsigned char *audiobufend = audiobuffer + sizeof(audiobuffer);
29#else 29#else
30#endif
31
32/* defined in linker script */
33#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
34#if defined(IPOD_VIDEO)
35extern unsigned char *audiobufend_lds[];
36unsigned char *audiobufend;
37#else /* !IPOD_VIDEO */
38extern unsigned char audiobufend[];
39#endif
30/* defined in linker script */ 40/* defined in linker script */
31extern unsigned char audiobuffer[]; 41extern unsigned char audiobuffer[];
42#else /* PLATFORM_HOSTED */
43unsigned char audiobuffer[(MEMORYSIZE*1024-256)*1024];
44unsigned char *audiobufend = audiobuffer + sizeof(audiobuffer);
45extern unsigned char *audiobufend;
32#endif 46#endif
33 47
34unsigned char *audiobuf; 48static unsigned char *audiobuf;
35 49
36#ifdef BUFFER_ALLOC_DEBUG 50#ifdef BUFFER_ALLOC_DEBUG
37static unsigned char *audiobuf_orig_start; 51static unsigned char *audiobuf_orig_start;
@@ -54,13 +68,68 @@ void buffer_init(void)
54{ 68{
55 /* 32-bit aligned */ 69 /* 32-bit aligned */
56 audiobuf = (void *)(((unsigned long)audiobuffer + 3) & ~3); 70 audiobuf = (void *)(((unsigned long)audiobuffer + 3) & ~3);
71
72#if defined(IPOD_VIDEO)
73 audiobufend=(unsigned char *)audiobufend_lds;
74 if(MEMORYSIZE==64 && probed_ramsize!=64)
75 {
76 audiobufend -= (32<<20);
77 }
78#endif
79
57#ifdef BUFFER_ALLOC_DEBUG 80#ifdef BUFFER_ALLOC_DEBUG
58 audiobuf_orig_start = audiobuf; 81 audiobuf_orig_start = audiobuf;
59#endif /* BUFFER_ALLOC_DEBUG */ 82#endif /* BUFFER_ALLOC_DEBUG */
60} 83}
61 84
85/* protect concurrent access */
86static volatile int lock;
87
88/*
89 * Give the entire buffer, return the size in size.
90 * The caller needs to make sure audiobuf is not otherwise used
91 *
92 * Note that this does not modify the buffer position (buffer_release_buffer()
93 * does), so call this if you want to aquire temporary memory
94 **/
95#define _ALIGN (sizeof(char*))
96void *buffer_get_buffer(size_t *size)
97{
98 if (lock)
99 panicf("concurrent audiobuf access");
100 lock = 1;
101 audiobuf = ALIGN_UP(audiobuf, sizeof(intptr_t));
102 *size = (audiobufend - audiobuf);
103 return audiobuf;
104}
105
106/*
107 * Release the buffer gotten with buffer_get_buffer
108 *
109 * size should have the amount of bytes (from the front) that caller keeps for
110 * its own, 0 if the entire buffer is to be released
111 *
112 * safe to be called with size=0 even if the buffer wasn't claimed before
113 **/
114void buffer_release_buffer(size_t size)
115{
116 audiobuf += size;
117 /* ensure alignment */
118 audiobuf = ALIGN_UP(audiobuf, sizeof(intptr_t));
119 lock = 0;
120}
121
122/*
123 * Query how much free space the buffer has */
124size_t buffer_available(void)
125{
126 return audiobufend - audiobuf;
127}
128
62void *buffer_alloc(size_t size) 129void *buffer_alloc(size_t size)
63{ 130{
131 if (lock) /* it's not save to call this here */
132 panicf("buffer_alloc(): exclusive buffer owner");
64 void *retval; 133 void *retval;
65#ifdef BUFFER_ALLOC_DEBUG 134#ifdef BUFFER_ALLOC_DEBUG
66 struct buffer_start_marker *start; 135 struct buffer_start_marker *start;
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 08fe5098f5..d114a6ac62 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -862,22 +862,26 @@ int dircache_build(int last_size)
862 * and their corresponding d_name from the end 862 * and their corresponding d_name from the end
863 * after generation the buffer will be compacted with DIRCACHE_RESERVE 863 * after generation the buffer will be compacted with DIRCACHE_RESERVE
864 * free bytes inbetween */ 864 * free bytes inbetween */
865 audiobuf = ALIGN_UP(audiobuf, sizeof(struct dircache_entry)); 865 size_t got_size;
866 dircache_root = (struct dircache_entry*)audiobuf; 866 char* buf = buffer_get_buffer(&got_size);
867 d_names_start = d_names_end = audiobufend - 1; 867 ALIGN_BUFFER(buf, got_size, sizeof(struct dircache_entry));
868 d_names_start = d_names_end = (char*)dircache_root + got_size - 1;
868 dircache_size = 0; 869 dircache_size = 0;
869 generate_dot_d_names(); 870 generate_dot_d_names();
870 871
871 /* Start a non-transparent rebuild. */ 872 /* Start a non-transparent rebuild. */
872 int res = dircache_do_rebuild(); 873 int res = dircache_do_rebuild();
873 if (res < 0) 874 if (res < 0)
874 return res; 875 goto fail;
875 876
876 /* now compact the dircache buffer */ 877 /* now compact the dircache buffer */
877 char* dst = ((char*)&dircache_root[entry_count] + DIRCACHE_RESERVE); 878 char* dst = ((char*)&dircache_root[entry_count] + DIRCACHE_RESERVE);
878 ptrdiff_t offset = d_names_start - dst; 879 ptrdiff_t offset = d_names_start - dst;
879 if (offset <= 0) /* something went wrong */ 880 if (offset <= 0) /* something went wrong */
880 return -1; 881 {
882 res = -1;
883 goto fail;
884 }
881 885
882 /* memmove d_names down, there's a possibility of overlap 886 /* memmove d_names down, there's a possibility of overlap
883 * equivaent to dircache_size - entry_count*sizeof(struct dircache_entry) */ 887 * equivaent to dircache_size - entry_count*sizeof(struct dircache_entry) */
@@ -896,15 +900,19 @@ int dircache_build(int last_size)
896 /* equivalent to dircache_size + DIRCACHE_RESERVE */ 900 /* equivalent to dircache_size + DIRCACHE_RESERVE */
897 allocated_size = (d_names_end - (char*)dircache_root); 901 allocated_size = (d_names_end - (char*)dircache_root);
898 reserve_used = 0; 902 reserve_used = 0;
899 audiobuf += allocated_size;
900 903
904 buffer_release_buffer(allocated_size);
905 return res;
906fail:
907 dircache_disable();
908 buffer_release_buffer(0);
901 return res; 909 return res;
902} 910}
903 911
904/** 912/**
905 * Steal the allocated dircache buffer and disable dircache. 913 * Steal the allocated dircache buffer and disable dircache.
906 */ 914 */
907void* dircache_steal_buffer(long *size) 915void* dircache_steal_buffer(size_t *size)
908{ 916{
909 dircache_disable(); 917 dircache_disable();
910 if (dircache_size == 0) 918 if (dircache_size == 0)
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index 910791c7fd..6757bf143b 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -51,6 +51,8 @@
51void audio_init(void) INIT_ATTR; 51void audio_init(void) INIT_ATTR;
52void audio_play(long offset); 52void audio_play(long offset);
53void audio_stop(void); 53void audio_stop(void);
54/* Stops audio from serving playback and frees resources*/
55void audio_hard_stop(void);
54void audio_pause(void); 56void audio_pause(void);
55void audio_resume(void); 57void audio_resume(void);
56void audio_next(void); 58void audio_next(void);
@@ -68,11 +70,11 @@ void audio_error_clear(void);
68int audio_get_file_pos(void); 70int audio_get_file_pos(void);
69void audio_beep(int duration); 71void audio_beep(int duration);
70 72
71#if CONFIG_CODEC == SWCODEC
72/* Required call when audio buffer is required for some other purpose */ 73/* Required call when audio buffer is required for some other purpose */
74/* implemented in apps but called from firmware(!) */
73unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size); 75unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size);
74/* only implemented in playback.c, but called from firmware */
75 76
77#if CONFIG_CODEC == SWCODEC
76void audio_next_dir(void); 78void audio_next_dir(void);
77void audio_prev_dir(void); 79void audio_prev_dir(void);
78 80
diff --git a/firmware/include/buffer.h b/firmware/include/buffer.h
index 18f53f0000..bdf91bcb3f 100644
--- a/firmware/include/buffer.h
+++ b/firmware/include/buffer.h
@@ -22,21 +22,13 @@
22#define BUFFER_H 22#define BUFFER_H
23 23
24#include "config.h" 24#include "config.h"
25/* defined in linker script */
26#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
27#if defined(IPOD_VIDEO)
28extern unsigned char *audiobufend_lds[];
29unsigned char *audiobufend;
30#else
31extern unsigned char audiobufend[];
32#endif
33#else
34extern unsigned char *audiobufend;
35#endif
36
37extern unsigned char *audiobuf;
38 25
39void buffer_init(void) INIT_ATTR; 26void buffer_init(void) INIT_ATTR;
27
28void* buffer_get_buffer(size_t *size);
29void buffer_release_buffer(size_t size);
30size_t buffer_available(void);
31
40void *buffer_alloc(size_t size); 32void *buffer_alloc(size_t size);
41 33
42#ifdef BUFFER_ALLOC_DEBUG 34#ifdef BUFFER_ALLOC_DEBUG
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index 0ac937df84..6beeeb6c23 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -23,6 +23,7 @@
23 23
24#include "config.h" 24#include "config.h"
25#include "dir_uncached.h" 25#include "dir_uncached.h"
26#include <string.h> /* size_t */
26 27
27#ifdef HAVE_DIRCACHE 28#ifdef HAVE_DIRCACHE
28 29
@@ -65,7 +66,7 @@ void dircache_init(void) INIT_ATTR;
65int dircache_load(void); 66int dircache_load(void);
66int dircache_save(void); 67int dircache_save(void);
67int dircache_build(int last_size); 68int dircache_build(int last_size);
68void* dircache_steal_buffer(long *size); 69void* dircache_steal_buffer(size_t *size);
69bool dircache_is_enabled(void); 70bool dircache_is_enabled(void);
70bool dircache_is_initializing(void); 71bool dircache_is_initializing(void);
71void dircache_set_appflag(long mask); 72void dircache_set_appflag(long mask);
diff --git a/firmware/rolo.c b/firmware/rolo.c
index 078a4e9827..9b6f4fec4a 100644
--- a/firmware/rolo.c
+++ b/firmware/rolo.c
@@ -99,6 +99,7 @@ void rolo_restart_cop(void)
99 99
100static void rolo_error(const char *text) 100static void rolo_error(const char *text)
101{ 101{
102 buffer_release_buffer(0);
102 lcd_clear_display(); 103 lcd_clear_display();
103 lcd_puts(0, 0, "ROLO error:"); 104 lcd_puts(0, 0, "ROLO error:");
104 lcd_puts_scroll(0, 1, text); 105 lcd_puts_scroll(0, 1, text);
@@ -213,6 +214,8 @@ int rolo_load(const char* filename)
213 unsigned short checksum,file_checksum; 214 unsigned short checksum,file_checksum;
214#endif 215#endif
215 unsigned char* ramstart = (void*)&loadaddress; 216 unsigned char* ramstart = (void*)&loadaddress;
217 unsigned char* filebuf;
218 size_t filebuf_size;
216 219
217 lcd_clear_display(); 220 lcd_clear_display();
218 lcd_puts(0, 0, "ROLO..."); 221 lcd_puts(0, 0, "ROLO...");
@@ -235,6 +238,10 @@ int rolo_load(const char* filename)
235 238
236 length = filesize(fd) - FIRMWARE_OFFSET_FILE_DATA; 239 length = filesize(fd) - FIRMWARE_OFFSET_FILE_DATA;
237 240
241 /* get the system buffer. release only in case of error, otherwise
242 * we don't return anyway */
243 filebuf = buffer_get_buffer(&filebuf_size);
244
238#if CONFIG_CPU != SH7034 245#if CONFIG_CPU != SH7034
239 /* Read and save checksum */ 246 /* Read and save checksum */
240 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET); 247 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
@@ -260,7 +267,14 @@ int rolo_load(const char* filename)
260 267
261 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); 268 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
262 269
263 if (read(fd, audiobuf, length) != length) { 270 /* this shouldn't happen, but well */
271 if ((long)filebuf_size < length)
272 {
273 rolo_error("File too big");
274 return -1;
275 }
276
277 if (read(fd, filebuf, length) != length) {
264 rolo_error("Error Reading File"); 278 rolo_error("Error Reading File");
265 return -1; 279 return -1;
266 } 280 }
@@ -268,12 +282,12 @@ int rolo_load(const char* filename)
268#ifdef MI4_FORMAT 282#ifdef MI4_FORMAT
269 /* Check CRC32 to see if we have a valid file */ 283 /* Check CRC32 to see if we have a valid file */
270 chksum_crc32gentab(); 284 chksum_crc32gentab();
271 checksum = chksum_crc32 (audiobuf, length); 285 checksum = chksum_crc32 (filebuf, length);
272#else 286#else
273 checksum = MODEL_NUMBER; 287 checksum = MODEL_NUMBER;
274 288
275 for(i = 0;i < length;i++) { 289 for(i = 0;i < length;i++) {
276 checksum += audiobuf[i]; 290 checksum += filebuf[i];
277 } 291 }
278#endif 292#endif
279 293
@@ -329,12 +343,12 @@ int rolo_load(const char* filename)
329 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); 343 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
330 344
331 /* verify that file can be read and descrambled */ 345 /* verify that file can be read and descrambled */
332 if ((audiobuf + (2*length)+4) >= audiobufend) { 346 if ((size_t)((2*length)+4) >= filebuf_size) {
333 rolo_error("Not enough room to load file"); 347 rolo_error("Not enough room to load file");
334 return -1; 348 return -1;
335 } 349 }
336 350
337 if (read(fd, &audiobuf[length], length) != (int)length) { 351 if (read(fd, &filebuf[length], length) != (int)length) {
338 rolo_error("Error Reading File"); 352 rolo_error("Error Reading File");
339 return -1; 353 return -1;
340 } 354 }
@@ -342,7 +356,7 @@ int rolo_load(const char* filename)
342 lcd_puts(0, 1, "Descramble"); 356 lcd_puts(0, 1, "Descramble");
343 lcd_update(); 357 lcd_update();
344 358
345 checksum = descramble(audiobuf + length, audiobuf, length); 359 checksum = descramble(filebuf + length, filebuf, length);
346 360
347 /* Verify checksum against file header */ 361 /* Verify checksum against file header */
348 if (checksum != file_checksum) { 362 if (checksum != file_checksum) {
@@ -374,7 +388,7 @@ int rolo_load(const char* filename)
374 PAIOR = 0x0FA0; 388 PAIOR = 0x0FA0;
375#endif 389#endif
376#endif 390#endif
377 rolo_restart(audiobuf, ramstart, length); 391 rolo_restart(filebuf, ramstart, length);
378 392
379 return 0; /* this is never reached */ 393 return 0; /* this is never reached */
380 (void)checksum; (void)file_checksum; 394 (void)checksum; (void)file_checksum;