summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-08-14 15:13:00 +0000
committerThomas Martitz <kugel@rockbox.org>2011-08-14 15:13:00 +0000
commitd1322b71595336740eb5e18e5deed056ddb71c7a (patch)
tree812db6a9c2e9d78405ec0ed38465fd88dc5be748 /firmware
parent9b9bd73dfb212d4192fccc5fc5e269fc6499139c (diff)
downloadrockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.tar.gz
rockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.zip
GSoC/Buflib: Replace all direct accesses to audiobuf with buffer API functions.
Namely, introduce buffer_get_buffer() and buffer_release_buffer(). buffer_get_buffer() aquires all available and grabs a lock, attempting to call buffer_alloc() or buffer_get_buffer() while this lock is locked will cause a panicf() (doesn't actually happen, but is for debugging purpose). buffer_release_buffer() unlocks that lock and can additionally increment the audiobuf buffer to make an allocation. Pass 0 to only unlock if buffer was used temporarily only. buffer_available() is a replacement function to query audiobuflen, i.e. what's left in the buffer. Buffer init is moved up in the init chain and handles ipodvideo64mb internally. Further changes happened to mp3data.c and talk.c as to not call the above API functions, but get the buffer from callers. The caller is the audio system which has the buffer lock while mp3data.c and talk mess with the buffer. mpeg.c now implements some buffer related functions of playback.h, especially audio_get_buffer(), allowing to reduce #ifdef hell a tiny bit. audiobuf and audiobufend are local to buffer.c now. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30308 a1c6a512-1295-4272-9138-f99709370657
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;