summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2006-08-05 20:19:10 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2006-08-05 20:19:10 +0000
commit954b73265404075ec4d379ddea14e626113a8677 (patch)
tree5c6ff0056ebd118aadb896856e7679a41c595cba /firmware
parent85ba65d2a3fa3d10799efadbe3a33f026bf354df (diff)
downloadrockbox-954b73265404075ec4d379ddea14e626113a8677.zip
rockbox-954b73265404075ec4d379ddea14e626113a8677.tar.gz
rockbox-954b73265404075ec4d379ddea14e626113a8677.tar.bz2
rockbox-954b73265404075ec4d379ddea14e626113a8677.tar.xz
Initial support and use for EEPROM memory on H120 & H140 players when
Rockbox firmware has been flashed over original firmware (not yet possible to do). Dircache & tagcache serialization for fast bootup without the need to scan disk when Rockbox is in flash. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10464 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES4
-rw-r--r--firmware/common/crc32.c4
-rw-r--r--firmware/common/dircache.c32
-rw-r--r--firmware/drivers/eeprom_24cxx.c6
-rw-r--r--firmware/eeprom_settings.c116
-rw-r--r--firmware/export/config-h100.h6
-rw-r--r--firmware/export/config-h120.h10
-rw-r--r--firmware/export/eeprom_settings.h48
-rw-r--r--firmware/export/system.h8
-rw-r--r--firmware/include/crc32.h2
-rw-r--r--firmware/powermgmt.c4
-rw-r--r--firmware/system.c21
12 files changed, 241 insertions, 20 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 8e2ca74..480c7ce 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -145,6 +145,10 @@ drivers/mas.c
#ifdef IRIVER_H300_SERIES
drivers/pcf50606.c
#endif
+#ifdef HAVE_EEPROM
+drivers/eeprom_24cxx.c
+eeprom_settings.c
+#endif
#ifdef IPOD_ARCH
drivers/pcf50605.c
#endif
diff --git a/firmware/common/crc32.c b/firmware/common/crc32.c
index 18ee6ac..21fefac 100644
--- a/firmware/common/crc32.c
+++ b/firmware/common/crc32.c
@@ -21,8 +21,10 @@
/* Tool function to calculate a CRC32 across some buffer */
/* third argument is either 0xFFFFFFFF to start or value from last piece */
-unsigned crc_32(unsigned char* buf, unsigned len, unsigned crc32)
+unsigned crc_32(const void *src, unsigned len, unsigned crc32)
{
+ const unsigned char *buf = (const unsigned char *)src;
+
/* CCITT standard polynomial 0x04C11DB7 */
static const unsigned crc32_lookup[16] =
{ /* lookup table for 4 bits at a time is affordable */
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 6167aa3..d2c77a2 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -402,7 +402,7 @@ static struct dircache_entry* dircache_get_entry(const char *path,
return cache_entry;
}
-#if 0
+#if 1
/**
* Function to load the internal cache structure from disk to initialize
* the dircache really fast and little disk access.
@@ -423,32 +423,41 @@ int dircache_load(const char *path)
if (fd < 0)
return -2;
- dircache_root = (struct dircache_entry *)(((long)audiobuf & ~0x03) + 0x04);
bytes_read = read(fd, &maindata, sizeof(struct dircache_maindata));
if (bytes_read != sizeof(struct dircache_maindata)
- || (long)maindata.root_entry != (long)dircache_root
|| maindata.size <= 0)
{
+ logf("Dircache file header error");
close(fd);
return -3;
}
+ dircache_root = buffer_alloc(0);
+ if ((long)maindata.root_entry != (long)dircache_root)
+ {
+ logf("Position missmatch");
+ close(fd);
+ return -4;
+ }
+
+ dircache_root = buffer_alloc(maindata.size + DIRCACHE_RESERVE);
entry_count = maindata.entry_count;
bytes_read = read(fd, dircache_root, MIN(DIRCACHE_LIMIT, maindata.size));
close(fd);
if (bytes_read != maindata.size)
+ {
+ logf("Dircache read failed");
return -6;
+ }
/* Cache successfully loaded. */
dircache_size = maindata.size;
+ allocated_size = dircache_size + DIRCACHE_RESERVE;
+ reserve_used = 0;
logf("Done, %d KiB used", dircache_size / 1024);
dircache_initialized = true;
memset(fd_bindings, 0, sizeof(fd_bindings));
-
- /* We have to long align the audiobuf to keep the buffer access fast. */
- audiobuf += (long)((dircache_size & ~0x03) + 0x04);
- audiobuf += DIRCACHE_RESERVE;
return 0;
}
@@ -472,7 +481,7 @@ int dircache_save(const char *path)
return -1;
logf("Saving directory cache");
- fd = open(path, O_WRONLY | O_CREAT);
+ fd = open(path, O_WRONLY | O_CREAT | O_TRUNC);
maindata.magic = DIRCACHE_MAGIC;
maindata.size = dircache_size;
@@ -484,6 +493,7 @@ int dircache_save(const char *path)
if (bytes_written != sizeof(struct dircache_maindata))
{
close(fd);
+ logf("dircache: write failed #1");
return -2;
}
@@ -491,8 +501,11 @@ int dircache_save(const char *path)
bytes_written = write(fd, dircache_root, dircache_size);
close(fd);
if (bytes_written != dircache_size)
+ {
+ logf("dircache: write failed #2");
return -3;
-
+ }
+
return 0;
}
#endif /* #if 0 */
@@ -616,6 +629,7 @@ int dircache_build(int last_size)
return -3;
logf("Building directory cache");
+ /* Background build, dircache has been previously allocated */
if (dircache_size > 0)
{
thread_enabled = true;
diff --git a/firmware/drivers/eeprom_24cxx.c b/firmware/drivers/eeprom_24cxx.c
index 4f7362e..33c02f1 100644
--- a/firmware/drivers/eeprom_24cxx.c
+++ b/firmware/drivers/eeprom_24cxx.c
@@ -308,7 +308,7 @@ bool eeprom_24cxx_read_byte(unsigned int address, char *c)
bool eeprom_24cxx_write_byte(unsigned int address, char c)
{
int ret;
- int count = 10;
+ int count = 100;
if (address >= EEPROM_SIZE)
{
@@ -318,10 +318,6 @@ bool eeprom_24cxx_write_byte(unsigned int address, char c)
do {
ret = sw_i2c_write_byte(address, c);
- if (ret < 0)
- {
- logf("EEPROM Fail: %d/%d", ret, address);
- }
} while (ret < 0 && count--) ;
if (ret < 0)
diff --git a/firmware/eeprom_settings.c b/firmware/eeprom_settings.c
new file mode 100644
index 0000000..43f519d
--- /dev/null
+++ b/firmware/eeprom_settings.c
@@ -0,0 +1,116 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Miika Pekkarinen
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "eeprom_settings.h"
+#include "eeprom_24cxx.h"
+#include "crc32.h"
+
+#include "string.h"
+#include "logf.h"
+
+struct eeprom_settings firmware_settings;
+
+static void reset_config(void)
+{
+ memset(&firmware_settings, 0, sizeof(struct eeprom_settings));
+ firmware_settings.version = EEPROM_SETTINGS_VERSION;
+ firmware_settings.initialized = true;
+ firmware_settings.boot_disk = false;
+ firmware_settings.bl_version = 0;
+}
+
+bool eeprom_settings_init(void)
+{
+ bool ret;
+ uint32_t sum;
+
+ eeprom_24cxx_init();
+
+ /* Check if player has been flashed. */
+ if (!detect_flashed_rockbox())
+ {
+ memset(&firmware_settings, 0, sizeof(struct eeprom_settings));
+ firmware_settings.initialized = false;
+ logf("Rockbox in flash is required");
+ return false;
+ }
+
+ ret = eeprom_24cxx_read(0, &firmware_settings,
+ sizeof(struct eeprom_settings));
+
+ if (!ret)
+ {
+ memset(&firmware_settings, 0, sizeof(struct eeprom_settings));
+ firmware_settings.initialized = false;
+ return false;
+ }
+
+ sum = crc_32(&firmware_settings, sizeof(struct eeprom_settings)-4,
+ 0xffffffff);
+
+ if (firmware_settings.checksum != sum)
+ {
+ logf("Checksum mismatch");
+ reset_config();
+ return true;
+ }
+
+ if (firmware_settings.version != EEPROM_SETTINGS_VERSION)
+ {
+ logf("Version mismatch");
+ reset_config();
+ return true;
+ }
+
+#ifndef BOOTLOADER
+ if (firmware_settings.bl_version < EEPROM_SETTINGS_BL_MINVER)
+ {
+ logf("Too old bootloader: %d", firmware_settings.bl_version);
+ reset_config();
+ return true;
+ }
+#endif
+
+ return true;
+}
+
+bool eeprom_settings_store(void)
+{
+ bool ret;
+ uint32_t sum;
+
+ if (!firmware_settings.initialized || !detect_flashed_rockbox())
+ {
+ logf("Rockbox in flash is required");
+ return false;
+ }
+
+ /* Update the checksum. */
+ sum = crc_32(&firmware_settings, sizeof(struct eeprom_settings)-4,
+ 0xffffffff);
+ firmware_settings.checksum = sum;
+ ret = eeprom_24cxx_write(0, &firmware_settings,
+ sizeof(struct eeprom_settings));
+
+ if (!ret)
+ firmware_settings.initialized = false;
+
+ return ret;
+}
+
diff --git a/firmware/export/config-h100.h b/firmware/export/config-h100.h
index 6d204c3..7310dfa 100644
--- a/firmware/export/config-h100.h
+++ b/firmware/export/config-h100.h
@@ -123,7 +123,10 @@
#define BOOTFILE_EXT "iriver"
#define BOOTFILE "rockbox." BOOTFILE_EXT
-#endif
+/* Define this if there is an EEPROM chip */
+#define HAVE_EEPROM
+
+#endif /* !SIMULATOR */
/* Define this for S/PDIF input available */
#define HAVE_SPDIF_IN
@@ -134,3 +137,4 @@
/* Define this if you can control the S/PDIF power */
#define HAVE_SPDIF_POWER
#define SPDIF_POWER_INVERTED
+
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index 5635a92..ca61813 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -118,7 +118,14 @@
#define BOOTFILE_EXT "iriver"
#define BOOTFILE "rockbox." BOOTFILE_EXT
-#endif
+#define BOOTLOADER_ENTRYPOINT 0x001F0000
+#define FLASH_ENTRYPOINT 0x00001000
+#define FLASH_MAGIC 0xfbfbfbf1
+
+/* Define this if there is an EEPROM chip */
+#define HAVE_EEPROM
+
+#endif /* !SIMULATOR */
/* Define this for S/PDIF input available */
#define HAVE_SPDIF_IN
@@ -128,3 +135,4 @@
/* Define this if you can control the S/PDIF power */
#define HAVE_SPDIF_POWER
+
diff --git a/firmware/export/eeprom_settings.h b/firmware/export/eeprom_settings.h
new file mode 100644
index 0000000..a3515bd
--- /dev/null
+++ b/firmware/export/eeprom_settings.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Miika Pekkarinen
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _EEPROM_SETTINGS_H_
+#define _EEPROM_SETTINGS_H_
+
+#include <stdbool.h>
+#include "inttypes.h"
+
+#define EEPROM_SETTINGS_VERSION 0x24c01001
+#define EEPROM_SETTINGS_BL_MINVER 7
+
+struct eeprom_settings
+{
+ long version; /* Settings version number */
+ bool initialized; /* Is eeprom_settings ready to be used */
+ bool disk_clean; /* Is disk intact from last reboot */
+ bool boot_disk; /* Load firmware from disk (default=FLASH) */
+ uint8_t bl_version; /* Installed bootloader version */
+
+ /* This must be the last entry */
+ uint32_t checksum; /* Checksum of this structure */
+};
+
+extern struct eeprom_settings firmware_settings;
+
+bool detect_flashed_rockbox(void);
+bool eeprom_settings_init(void);
+bool eeprom_settings_store(void);
+
+#endif
+
diff --git a/firmware/export/system.h b/firmware/export/system.h
index dae5d95..1b326e1 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -45,6 +45,14 @@ static inline void udelay(unsigned usecs)
}
#endif
+struct flash_header {
+ unsigned long magic;
+ unsigned long length;
+ char version[32];
+};
+
+bool detect_flashed_rockbox(void);
+
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
#define FREQ cpu_frequency
void set_cpu_frequency(long frequency);
diff --git a/firmware/include/crc32.h b/firmware/include/crc32.h
index 5e998ab..a2b7ae2 100644
--- a/firmware/include/crc32.h
+++ b/firmware/include/crc32.h
@@ -19,7 +19,7 @@
#ifndef _CRC32_H
#define _CRC32_H
-unsigned crc_32(unsigned char* buf, unsigned len, unsigned crc32);
+unsigned crc_32(const void *src, unsigned len, unsigned crc32);
#endif
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index 4bccd4e..a8e641e 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -993,8 +993,8 @@ void sys_poweroff(void)
{
logf("sys_poweroff()");
/* If the main thread fails to shut down the system, we will force a
- power off after an 8 second timeout */
- shutdown_timeout = HZ*8;
+ power off after an 20 second timeout */
+ shutdown_timeout = HZ*20;
queue_post(&button_queue, SYS_POWEROFF, NULL);
}
diff --git a/firmware/system.c b/firmware/system.c
index 1874c04..bb09dbc 100644
--- a/firmware/system.c
+++ b/firmware/system.c
@@ -24,6 +24,8 @@
#include "system.h"
#include "kernel.h"
#include "timer.h"
+#include "inttypes.h"
+#include "string.h"
#ifndef SIMULATOR
long cpu_frequency = CPU_FREQ;
@@ -76,6 +78,25 @@ void cpu_idle_mode(bool on_off)
#endif
+#if defined(IRIVER_H100_SERIES) && !defined(SIMULATOR)
+bool detect_flashed_rockbox(void)
+{
+ struct flash_header hdr;
+ uint8_t *src = (uint8_t *)FLASH_ENTRYPOINT;
+
+ memcpy(&hdr, src, sizeof(struct flash_header));
+ if (hdr.magic != FLASH_MAGIC)
+ return false;
+
+ return true;
+}
+#else
+bool detect_flashed_rockbox(void)
+{
+ return false;
+}
+#endif
+
#if CONFIG_CPU == TCC730
void* volatile interrupt_vector[16] __attribute__ ((section(".idata")));