Commit FS#6929 - Gigabeat bootloader improvements by Barry Wardell and myself.  This build fixes the problems seen with the latest builds on the Gigabeat X.  Added View IO Ports under the Debug menu for the Gigabeat.  Make sure you grab the latest bootloader from the Wiki as the old bootloader will not work properly with new builds.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13225 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/debug_menu.c b/apps/debug_menu.c
index 12d5f43..9f827e7 100644
--- a/apps/debug_menu.c
+++ b/apps/debug_menu.c
@@ -88,6 +88,10 @@
 #endif
 #include "hwcompat.h"
 
+#if CONFIG_CPU == S3C2440
+#include "s3c2440.h"
+#endif
+
 #ifndef SIMULATOR
 static bool dbg_list(char *title, int count, int selection_size,
                      int (*action_callback)(int btn, struct gui_synclist *lists), 
@@ -1133,6 +1137,43 @@
         if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL))
             return false;
     }
+#elif CONFIG_CPU == S3C2440
+    char buf[128];
+    int line, fd;
+
+    lcd_setmargins(0, 0);
+    lcd_clear_display();
+    lcd_setfont(FONT_SYSFIXED);
+
+    while(1)
+    {
+        line = 0;
+        snprintf(buf, sizeof(buf), "GPACON: %08x GPBCON: %08x", GPACON, GPBCON); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPADAT: %08x GPBDAT: %08x", GPADAT, GPBDAT); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPAUP:  %08x GPBUP:  %08x", 0, GPBUP); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPCCON: %08x GPDCON: %08x", GPCCON, GPDCON); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPCDAT: %08x GPDDAT: %08x", GPCDAT, GPDDAT); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPCUP:  %08x GPDUP:  %08x", GPCUP, GPDUP); lcd_puts(0, line++, buf);
+
+        snprintf(buf, sizeof(buf), "GPCCON: %08x GPDCON: %08x", GPCCON, GPDCON); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPCDAT: %08x GPDDAT: %08x", GPCDAT, GPDDAT); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPCUP:  %08x GPDUP:  %08x", GPCUP, GPDUP); lcd_puts(0, line++, buf);
+
+        snprintf(buf, sizeof(buf), "GPECON: %08x GPFCON: %08x", GPECON, GPFCON); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPEDAT: %08x GPFDAT: %08x", GPEDAT, GPFDAT); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPEUP:  %08x GPFUP:  %08x", GPEUP, GPFUP); lcd_puts(0, line++, buf);
+
+        snprintf(buf, sizeof(buf), "GPGCON: %08x GPHCON: %08x", GPGCON, GPHCON); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPGDAT: %08x GPHDAT: %08x", GPGDAT, GPHDAT); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPGUP:  %08x GPHUP:  %08x", GPGUP, GPHUP); lcd_puts(0, line++, buf);
+        
+        snprintf(buf, sizeof(buf), "GPJCON: %08x", GPJCON); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPJDAT: %08x", GPJDAT); lcd_puts(0, line++, buf);
+        snprintf(buf, sizeof(buf), "GPJUP:  %08x", GPJUP); lcd_puts(0, line++, buf);
+        lcd_update();
+        if (button_get_w_tmo(HZ/10) == (DEBUG_CANCEL|BUTTON_REL))
+            return false;
+    }
 #endif /* CPU */
     return false;
 }
@@ -2271,7 +2312,7 @@
     (defined(CPU_PP) && !defined(SANSA_E200))
         { "Dump ROM contents", dbg_save_roms },
 #endif
-#if CONFIG_CPU == SH7034 || defined(CPU_COLDFIRE) || defined(CPU_PP)
+#if CONFIG_CPU == SH7034 || defined(CPU_COLDFIRE) || defined(CPU_PP) || CONFIG_CPU == S3C2440
         { "View I/O ports", dbg_ports },
 #endif
 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
diff --git a/apps/main.c b/apps/main.c
index ab7f9f3..31bf32c 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -336,12 +336,8 @@
     lcd_remote_init();
 #endif
     font_init();
-    
-#if !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR)
+
     show_logo();
-#else
-    sleep(1);  /* Weird.  We crash w/o this tiny delay. */
-#endif    
     lang_init();
 
 #ifdef DEBUG
diff --git a/bootloader/common.c b/bootloader/common.c
index 51b751c..1ac8e8f 100644
--- a/bootloader/common.c
+++ b/bootloader/common.c
@@ -31,7 +31,7 @@
 /* TODO: Other bootloaders need to be adjusted to set this variable to true
    on a button press - currently only the ipod, H10 and Sansa versions do. */
 #if defined(IPOD_ARCH) || defined(IRIVER_H10) || defined(IRIVER_H10_5GB) || \
-    defined(SANSA_E200)
+    defined(SANSA_E200) || defined(GIGABEAT_F)
 bool verbose = false;
 #else
 bool verbose = true;
diff --git a/bootloader/gigabeat.c b/bootloader/gigabeat.c
index e4cf6f0..e482c70 100644
--- a/bootloader/gigabeat.c
+++ b/bootloader/gigabeat.c
@@ -20,7 +20,8 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <string.h>
+#include "inttypes.h"
+#include "string.h"
 #include "cpu.h"
 #include "system.h"
 #include "lcd.h"
@@ -32,250 +33,99 @@
 #include "font.h"
 #include "adc.h"
 #include "backlight.h"
+#include "backlight-target.h"
+#include "button.h"
 #include "panic.h"
 #include "power.h"
 #include "file.h"
-#include "button-target.h"
 #include "common.h"
+#include "rbunicode.h"
+#include "usb.h"
+#include "mmu-meg-fx.h"
 
-extern void map_memory(void);
+#include <stdarg.h>
 
 char version[] = APPSVERSION;
 
-static void go_usb_mode(void)
+void main(void)
 {
-    /* Drop into USB mode.  This does not check for disconnection. */
-    int i;
-
-    GPBDAT &= 0x7EF;
-    GPBCON |= 1<<8;
-
-    GPGDAT &= 0xE7FF;
-    GPGDAT |= 1<<11;
-
-    for(i = 0; i < 10000000; i++) {
-        continue;
-    }
-
-    GPBCON &= 0x2FFCFF;
-    GPBDAT |= 1<<5;
-    GPBDAT |= 1<<6;
-}
-
-
-/* Restores a factory kernel/bootloader from a known location                   */
-/* Restores the FWIMG01.DAT file back in the case of a bootloader failure       */
-/* The factory or "good" bootloader must be in /GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG */
-/* Returns non-zero on failure */
-int restore_fwimg01dat(void)
-{
-    int orig_file = 0, dest_file = 0;
-    int size = 0, size_read;
-    static char buf[4096];
-    
-    orig_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT.ORIG", O_RDONLY);
-    if(orig_file < 0) {
-        /* Couldn't open source file */
-        printf("Couldn't open FWIMG01.DAT.ORIG for reading");
-        return(1);
-    }
-
-    printf("FWIMG01.DAT.ORIG opened for reading");
-
-    dest_file = open("/GBSYSTEM/FWIMG/FWIMG01.DAT", O_RDWR);
-    if(dest_file < 0) {
-        /* Couldn't open destination file */
-        printf("Couldn't open FWIMG01.DAT.ORIG for writing");
-        close(orig_file);
-        return(2);
-    }
-
-    printf("FWIMG01.DAT opened for writing");
-
-    do {
-        /* Copy in chunks */
-        size_read = read(orig_file, buf, sizeof(buf));
-        if(size_read != write(dest_file, buf, size_read)) {
-            close(orig_file);
-            close(dest_file);
-            return(3);
-        }
-        size += size_read;
-
-    } while(size_read > 0);
-
-    close(orig_file);
-    close(dest_file);
-
-    printf("Finished copying %ld bytes from", size);
-    printf("FWIMG01.DAT.ORIG to FWIMG01.DAT");
-
-    return(0);
-}
-
-char buf[256];
-
-void display_instructions(void)
-{
-    lcd_setfont(FONT_SYSFIXED);
-    printf("Hold MENU when booting for rescue mode.");
-    printf("  \"VOL+\" button to restore original kernel");
-    printf("  \"A\" button to load original firmware");
-    printf("");
-    printf("FRAME %x TTB %x", FRAME, TTB_BASE);
-}
-
-void * main(void)
-{
-    int i;
-    struct partinfo* pinfo;
-    unsigned short* identify_info;
     unsigned char* loadbuffer;
     int buffer_size;
-    bool load_original = false;
     int rc;
     int(*kernel_entry)(void);
 
-    bool show_bootsplash = true;
+    memory_init();
+    power_init();
+    system_init();
+    lcd_init();
+    backlight_init();
+    font_init();
 
-    if(GPGDAT & 2)
-        show_bootsplash = false;
+    lcd_setfont(FONT_SYSFIXED);
 
-    if(!show_bootsplash) {
-        lcd_init();
-        display_instructions();
-        sleep(2*HZ);
+    usb_init();
+
+    /* Enter USB mode without USB thread */
+    if(usb_detect())
+    {
+        const char msg[] = "Bootloader USB mode";
+        reset_screen();
+        lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2,
+                    (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg);
+        lcd_update();
+
+        ata_enable(false);
+        sleep(HZ/20);
+        usb_enable(true);
+
+        while (usb_detect())
+            sleep(HZ);
+
+        usb_enable(false);
+
+        reset_screen();
+        lcd_update();
     }
-    if(GPGDAT & 2) {
-        lcd_init();
-        printf("Entering rescue mode..");
-        go_usb_mode();
-        while(1);
-    }
-    if(GPGDAT & 0x10) {
-        lcd_init();
-        load_original = true;
-        printf("Loading original firmware...");
+    
+    kernel_init();
+    adc_init();
+    button_init();
+
+    /* Show debug messages if button is pressed */
+    if(button_read_device())
+        verbose = true;
+
+    printf("Rockbox boot loader");
+    printf("Version %s", version);
+
+    rc = ata_init();
+    if(rc)
+    {
+        reset_screen();
+        error(EATA, rc);
     }
 
-    i = ata_init();
-    i = disk_mount_all();
-    if(!show_bootsplash) {
-        printf("disk_mount_all: %d", i);
-    }
-    if(show_bootsplash) {
-        int fd = open("/bootsplash.raw", O_RDONLY);
-        if(fd < 0)  {
-            show_bootsplash = false;
-            lcd_init();
-            display_instructions();
-        }
-        else {
-            read(fd, lcd_framebuffer, LCD_WIDTH*LCD_HEIGHT*2);
-            close(fd);
-            lcd_update();
-            lcd_init();
-        }
-    } 
-    /* hold VOL+ to enter rescue mode to copy old image */
-    /* needs to be after ata_init and disk_mount_all    */
-    if(GPGDAT & 4) {
+    disk_init();
 
-        /* Try to restore the original kernel/bootloader if a copy is found */
-        printf("Restoring FWIMG01.DAT...");
-
-        if(!restore_fwimg01dat()) {
-            printf("Restoring FWIMG01.DAT successful.");
-        } else {
-            printf("Restoring FWIMG01.DAT failed.");
-        }
-
-        printf("Now power cycle to boot original");
-        while(1);
+    rc = disk_mount_all();
+    if (rc<=0)
+    {
+        error(EDISK,rc);
     }
 
-    if(!show_bootsplash) {
-        identify_info = ata_get_identify();
-
-        for(i=0; i < 20; i++)
-            ((unsigned short*)buf)[i]=htobe16(identify_info[i+27]);
-
-        buf[40]=0;
-
-        /* kill trailing space */
-        for(i=39; i && buf[i]==' '; i--)
-            buf[i] = 0;
-
-        printf("Model");
-        printf(buf);
-
-        for(i=0; i < 4; i++)
-            ((unsigned short*)buf)[i]=htobe16(identify_info[i+23]);
-
-        buf[8]=0;
-
-        printf("Firmware");
-        printf(buf);
-
-        pinfo = disk_partinfo(0);
-        printf("Partition 0: 0x%02x %ld MB", pinfo->type, pinfo->size / 2048);
-    }
-    /* Load original firmware */
-    if(load_original) {
-        loadbuffer = (unsigned char*)0x30008000;
-        buffer_size =(unsigned char*)0x31000000 - loadbuffer;
-        rc = load_raw_firmware(loadbuffer, "/rockbox.gigabeat", buffer_size);
-        if(rc < EOK) {
-            printf("Error!");
-            printf("Failed to load original firmware:");
-            printf(strerror(rc));
-            printf("Loading rockbox");
-            sleep(2*HZ);
-            goto load_rockbox;
-        }
-
-        printf("Loaded: %d", rc);
-        sleep(2*HZ);
-
-        (*((int*)0x7000000)) = 333;
-        rc = *((int*)0x7000000+0x8000000);
-        printf("Bank0 mem test: %d", rc);
-        sleep(3*HZ);
-
-        printf("Woops, should not return from firmware!");
-        goto usb;
-    }
-
-load_rockbox:
-    map_memory();
-    if(!show_bootsplash) {
-        printf("Loading Rockbox...");
-    }
+    printf("Loading firmware");
 
     loadbuffer = (unsigned char*) 0x100;
     buffer_size = (unsigned char*)0x400000 - loadbuffer;
-    rc = load_raw_firmware(loadbuffer, "/.rockbox/rockbox.gigabeat", buffer_size);
-    if(rc < EOK) {
-        rc = load_raw_firmware(loadbuffer, "/rockbox.gigabeat", buffer_size);      
-    }
-    if(rc < EOK) {
-        printf("Error!");
-        printf("Can't load rockbox.gigabeat:");
-        printf(strerror(rc));
-    } else {
-        if(!show_bootsplash) {
-            printf("Rockbox loaded.");
-        }
+
+    rc = load_firmware(loadbuffer, BOOTFILE, buffer_size);
+    if(rc < 0)
+        error(EBOOTFILE, rc);
+
+    if (rc == EOK)
+    {
         kernel_entry = (void*) loadbuffer;
         rc = kernel_entry();
-        printf("Woops, should not return from firmware: %d", rc);
-        goto usb;
     }
-usb:
-    /* now wait in USB mode so the bootloader can be updated */
-    go_usb_mode();
-    while(1);
-
-    return((void *)0);
 }
 
diff --git a/firmware/export/config-gigabeat.h b/firmware/export/config-gigabeat.h
index ef6d824..6a6e1d2 100644
--- a/firmware/export/config-gigabeat.h
+++ b/firmware/export/config-gigabeat.h
@@ -6,7 +6,7 @@
 #define TOSHIBA_GIGABEAT_F 1
 
 /* For Rolo and boot loader */
-#define MODEL_NUMBER 1
+#define MODEL_NUMBER 18
 
 /* define this if you have a bitmap LCD display */
 #define HAVE_LCD_BITMAP
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c
index bc2b53d..34fbc2b 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c
@@ -52,8 +52,8 @@
     else
         USB_ATA_ENABLE;
 
-    GPBCON=( GPGCON&~(1<<11) ) | (1<<10); /* Make the pin an output */
-//    GPBUP|=1<<5;  /* Disable pullup in SOC as we are now driving */
+    GPBCON=( GPBCON&~(1<<11) ) | (1<<10); /* Make the pin an output */
+    GPBUP|=1<<5;  /* Disable pullup in SOC as we are now driving */
 }
 
 bool ata_is_coldstart(void)
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
index 1bb68f9..11edcfe 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
@@ -53,6 +53,23 @@
 /* LCD init */
 void lcd_init_device(void)
 {
+#ifdef BOOTLOADER
+    /* When the Rockbox bootloader starts, we are changing framebuffer address,
+       but we don't want what's shown on the LCD to change until we do an
+       lcd_update(), so copy the data from the old framebuffer to the new one */
+    int i;
+    unsigned short *buf = (unsigned short*)FRAME;
+
+    memcpy(FRAME, (short *)((LCDSADDR1)<<1), 320*240*2);
+
+    /* The Rockbox bootloader is transitioning from RGB555I to RGB565 mode
+       so convert the frambuffer data accordingly */
+    for(i=0; i< 320*240; i++){
+        *buf = ((*buf>>1) & 0x1F) | (*buf & 0xffc0);
+        buf++;
+    }
+#endif
+
     LCDSADDR1 = (LCDBANK((unsigned)FRAME) << 21) | (LCDBASEU((unsigned)FRAME));
     LCDSADDR2 = LCDBASEL((unsigned)FRAME);
     LCDSADDR3 = 0x000000F0;
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c
index 6142213..c47c133 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.c
@@ -3,7 +3,6 @@
 #include "mmu-meg-fx.h"
 #include "panic.h"
 
-void map_memory(void);
 static void enable_mmu(void);
 static void set_ttb(void);
 static void set_page_tables(void);
@@ -15,7 +14,7 @@
 #define BUFFERED (1 << 2)
 #define MB (1 << 20)
 
-void map_memory(void) {
+void memory_init(void) {
     set_ttb();
     set_page_tables();
     enable_mmu();
@@ -69,6 +68,20 @@
 }
 
 static void enable_mmu(void) {
+    int regread;
+
+    asm volatile(
+        "MRC p15, 0, %r0, c1, c0, 0\n"  /* Read reg1, control register */
+    : /* outputs */
+        "=r"(regread)
+    : /* inputs */
+    : /* clobbers */
+        "r0"
+    );
+
+    if ( !(regread & 0x04) || !(regread & 0x00001000) ) /* Was the ICache or DCache Enabled? */
+        clean_dcache(); /* If so we need to clean the DCache before invalidating below */
+
     asm volatile("mov r0, #0\n"
         "mcr p15, 0, r0, c8, c7, 0\n" /* invalidate TLB */
 
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h b/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h
index 71b1b83..5249788 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/mmu-meg-fx.h
@@ -32,4 +32,4 @@
 /* Cleans entire DCache */
 void clean_dcache(void);
 
-
+void memory_init(void);
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
index b7e59e6..6c5e35f 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
@@ -1,6 +1,7 @@
 #include "kernel.h"
 #include "system.h"
 #include "panic.h"
+#include "mmu-meg-fx.h"
 
 #include "lcd.h"
 #include <stdio.h>
@@ -11,6 +12,7 @@
 const int DMA1_MASK   = (1 << 18);
 const int DMA2_MASK   = (1 << 19);
 const int DMA3_MASK   = (1 << 20);
+const int ALARM_MASK  = (1 << 30);
 
 int system_memory_guard(int newmode)
 {
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c
index 3aed8c3..af66e2a 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/usb-meg-fx.c
@@ -44,7 +44,7 @@
 void usb_init_device(void)
 {
     /* Input is the default configuration, only pullups need to be disabled */
-    GPFUP|=0x02;
+/*    GPFUP|=0x02;  */
 
     USB_VPLUS_PWR_ASSERT;
     GPBCON=( GPBCON&~(1<<13) ) | (1 << 12);
diff --git a/tools/configure b/tools/configure
index 2f79755..a507fdd 100755
--- a/tools/configure
+++ b/tools/configure
@@ -1048,7 +1048,7 @@
     target="-DGIGABEAT_F"
     memory=32 # always
     arm9tdmicc
-    tool="cp"
+    tool="$rootdir/tools/scramble -add=giga"
     bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
     bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
     output="rockbox.gigabeat"
diff --git a/tools/scramble.c b/tools/scramble.c
index 9a64a5a..5317283 100644
--- a/tools/scramble.c
+++ b/tools/scramble.c
@@ -224,6 +224,8 @@
             modelnum = 16;
         else if(!strcmp(&argv[1][5], "iam5"))
             modelnum = 17;
+        else if(!strcmp(&argv[1][5], "giga"))
+            modelnum = 18;
         else {
             fprintf(stderr, "unsupported model: %s\n", &argv[1][5]);
             return 2;