make the runtime view nicer.
[Rockbox.git] / firmware / rolo.c
blob0689e8be5b3ae9dfbe53de6b680b079d436e5cc5
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Randy D. Wood
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 "config.h"
21 #include "lcd.h"
22 #include "lcd-remote.h"
23 #include "kernel.h"
24 #include "sprintf.h"
25 #include "button.h"
26 #include "file.h"
27 #include "audio.h"
28 #include "system.h"
29 #include "i2c.h"
30 #include "string.h"
31 #include "buffer.h"
33 #if !defined(IRIVER_IFP7XX_SERIES) && \
34 (CONFIG_CPU != PP5002) && (CONFIG_CPU != S3C2440)
35 /* FIX: this doesn't work on iFP, 3rd Gen ipods */
37 #define IRQ0_EDGE_TRIGGER 0x80
39 #ifdef CPU_PP
40 /* Handle the COP properly - it needs to jump to a function outside SDRAM while
41 * the new firmware is being loaded, and then jump to the start of SDRAM
42 * TODO: Use the mailboxes built into the PP processor for this
45 volatile unsigned char IDATA_ATTR cpu_message = 0;
46 volatile unsigned char IDATA_ATTR cpu_reply = 0;
48 void rolo_restart_cop(void) ICODE_ATTR;
49 void rolo_restart_cop(void)
51 /* Invalidate cache */
52 outl(inl(0xf000f044) | 0x6, 0xf000f044);
53 while ((CACHE_CTL & 0x8000) != 0) {}
55 /* Disable cache */
56 CACHE_CTL = CACHE_DISABLE;
58 /* Tell the main core that we're ready to reload */
59 cpu_reply = 2;
61 /* Wait while RoLo loads the image into SDRAM */
62 /* TODO: Accept checksum failure gracefully */
63 while(cpu_message == 1) {}
65 /* Acknowledge the CPU and then reload */
66 cpu_reply = 1;
68 asm volatile(
69 "mov r0, #0x10000000 \n"
70 "mov pc, r0 \n"
73 #endif
75 static void rolo_error(const char *text)
77 lcd_clear_display();
78 lcd_puts(0, 0, "ROLO error:");
79 lcd_puts_scroll(0, 1, text);
80 lcd_update();
81 button_get(true);
82 button_get(true);
83 button_get(true);
84 lcd_stop_scroll();
87 #if CONFIG_CPU == SH7034
88 /* these are in assembler file "descramble.S" */
89 extern unsigned short descramble(const unsigned char* source,
90 unsigned char* dest, int length);
91 extern void rolo_restart(const unsigned char* source, unsigned char* dest,
92 int length);
93 #else
94 void rolo_restart(const unsigned char* source, unsigned char* dest,
95 long length) __attribute__ ((section (".icode")));
96 void rolo_restart(const unsigned char* source, unsigned char* dest,
97 long length)
99 long i;
100 unsigned char* localdest = dest;
101 #if (CONFIG_CPU==PP5020) || (CONFIG_CPU==PP5024)
102 unsigned long* memmapregs = (unsigned long*)0xf000f000;
103 #endif
105 for(i = 0;i < length;i++)
106 *localdest++ = *source++;
108 #if defined(CPU_COLDFIRE)
109 asm (
110 "movec.l %0,%%vbr \n"
111 "move.l (%0)+,%%sp \n"
112 "move.l (%0),%0 \n"
113 "jmp (%0) \n"
114 : : "a"(dest)
116 #elif (CONFIG_CPU==PP5020) || (CONFIG_CPU==PP5024)
118 /* Tell the COP that we've finished loading and started rebooting */
119 cpu_message = 0;
121 /* Flush cache */
122 outl(inl(0xf000f044) | 0x2, 0xf000f044);
123 while ((CACHE_CTL & 0x8000) != 0) {}
125 /* Disable cache */
126 CACHE_CTL = CACHE_DISABLE;
128 /* Reset the memory mapping registers to zero */
129 for (i=0;i<8;i++)
130 memmapregs[i]=0;
132 /* Wait for the COP to tell us it is rebooting */
133 while(cpu_reply != 1) {}
135 asm volatile(
136 "mov r0, #0x10000000 \n"
137 "mov pc, r0 \n"
139 #endif
141 #endif
143 /* This is assigned in the linker control file */
144 extern unsigned long loadaddress;
146 /***************************************************************************
148 * Name: rolo_load_app(char *filename,int scrambled)
149 * Filename must be a fully defined filename including the path and extension
151 ***************************************************************************/
152 int rolo_load(const char* filename)
154 int fd;
155 long length;
156 #if defined(CPU_COLDFIRE) || defined(CPU_PP)
157 int i;
158 unsigned long checksum,file_checksum;
159 #else
160 long file_length;
161 unsigned short checksum,file_checksum;
162 #endif
163 unsigned char* ramstart = (void*)&loadaddress;
165 lcd_clear_display();
166 lcd_puts(0, 0, "ROLO...");
167 lcd_puts(0, 1, "Loading");
168 lcd_update();
169 #ifdef HAVE_REMOTE_LCD
170 lcd_remote_clear_display();
171 lcd_remote_puts(0, 0, "ROLO...");
172 lcd_remote_puts(0, 1, "Loading");
173 lcd_remote_update();
174 #endif
176 audio_stop();
178 fd = open(filename, O_RDONLY);
179 if(-1 == fd) {
180 rolo_error("File not found");
181 return -1;
184 length = filesize(fd) - FIRMWARE_OFFSET_FILE_DATA;
186 #if defined(CPU_COLDFIRE) || defined(CPU_PP)
187 /* Read and save checksum */
188 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
189 if (read(fd, &file_checksum, 4) != 4) {
190 rolo_error("Error Reading checksum");
191 return -1;
194 /* Rockbox checksums are big-endian */
195 file_checksum = betoh32(file_checksum);
196 #ifdef CPU_PP
197 cpu_message = COP_REBOOT;
198 COP_CTL = PROC_WAKE;
199 lcd_puts(0, 2, "Waiting for coprocessor...");
200 lcd_update();
201 while(cpu_reply != 2) {}
202 lcd_puts(0, 2, " ");
203 lcd_update();
204 #endif
206 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
208 if (read(fd, audiobuf, length) != length) {
209 rolo_error("Error Reading File");
210 return -1;
213 checksum = MODEL_NUMBER;
215 for(i = 0;i < length;i++) {
216 checksum += audiobuf[i];
219 /* Verify checksum against file header */
220 if (checksum != file_checksum) {
221 rolo_error("Checksum Error");
222 return -1;
225 lcd_puts(0, 1, "Executing");
226 lcd_update();
227 #ifdef HAVE_REMOTE_LCD
228 lcd_remote_puts(0, 1, "Executing");
229 lcd_remote_update();
230 #endif
232 set_irq_level(HIGHEST_IRQ_LEVEL);
233 #elif CONFIG_CPU == SH7034
234 /* Read file length from header and compare to real file length */
235 lseek(fd, FIRMWARE_OFFSET_FILE_LENGTH, SEEK_SET);
236 if(read(fd, &file_length, 4) != 4) {
237 rolo_error("Error Reading File Length");
238 return -1;
240 if (length != file_length) {
241 rolo_error("File length mismatch");
242 return -1;
245 /* Read and save checksum */
246 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
247 if (read(fd, &file_checksum, 2) != 2) {
248 rolo_error("Error Reading checksum");
249 return -1;
251 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
253 /* verify that file can be read and descrambled */
254 if ((audiobuf + (2*length)+4) >= audiobufend) {
255 rolo_error("Not enough room to load file");
256 return -1;
259 if (read(fd, &audiobuf[length], length) != (int)length) {
260 rolo_error("Error Reading File");
261 return -1;
264 lcd_puts(0, 1, "Descramble");
265 lcd_update();
267 checksum = descramble(audiobuf + length, audiobuf, length);
269 /* Verify checksum against file header */
270 if (checksum != file_checksum) {
271 rolo_error("Checksum Error");
272 return -1;
275 lcd_puts(0, 1, "Executing ");
276 lcd_update();
278 set_irq_level(HIGHEST_IRQ_LEVEL);
280 /* Calling these 2 initialization routines was necessary to get the
281 the origional Archos version of the firmware to load and execute. */
282 system_init(); /* Initialize system for restart */
283 i2c_init(); /* Init i2c bus - it seems like a good idea */
284 ICR = IRQ0_EDGE_TRIGGER; /* Make IRQ0 edge triggered */
285 TSTR = 0xE0; /* disable all timers */
286 /* model-specific de-init, needed when flashed */
287 /* Especially the Archos software is picky about this */
288 #if defined(ARCHOS_RECORDER) || defined(ARCHOS_RECORDERV2) || \
289 defined(ARCHOS_FMRECORDER)
290 PAIOR = 0x0FA0;
291 #endif
292 #endif
293 rolo_restart(audiobuf, ramstart, length);
295 return 0; /* this is never reached */
297 #else /* !defined(IRIVER_IFP7XX_SERIES) */
298 int rolo_load(const char* filename)
300 /* dummy */
301 (void)filename;
302 return 0;
305 #endif /* !defined(IRIVER_IFP7XX_SERIES) */