]> www.infradead.org Git - users/rw/ppcboot.git/commitdiff
* Added support for MBX860T (thanks to Rob Taylor)
authorwdenk <wdenk>
Mon, 20 Nov 2000 17:19:27 +0000 (17:19 +0000)
committerwdenk <wdenk>
Mon, 20 Nov 2000 17:19:27 +0000 (17:19 +0000)
* Added support for Sandpoint8240 (thanks to Rob Taylor); this is
  Work In Progress (TM); current status: boots to command line input.
  EPIC code non-functional (interrupts disabled), No net, No IDE.

* Add support for Status LED

* Optionally panic() to reboot instead of hanging

* Misc bug fixes

* All frequencies in HZ now (internally)

* Add support for BOOTP Domain Name Server Option

96 files changed:
CHANGELOG
CREDITS
MAKEALL
Makefile
README
common/board.c
common/cmd_ide.c
common/main.c
config.mk
etx094/flash.c
include/asm/8xx_immap.h
include/asm/io.h [new file with mode: 0755]
include/asm/mc146818rtc.h [new file with mode: 0755]
include/asm/pci_io.h [new file with mode: 0755]
include/asm/processor.h
include/commproc.h
include/config_ETX094.h
include/config_IVMS8.h
include/config_Sandpoint8240.h [new file with mode: 0644]
include/config_TQM850L.h
include/linux/mc146818rtc.h [new file with mode: 0755]
include/mpc8240.h [new file with mode: 0755]
include/pcmcia.h
include/ppc_asm.tmpl
include/status_led.h [new file with mode: 0644]
ivms8/ivms8.c
mpc8240/Makefile [new file with mode: 0644]
mpc8240/config.mk [new file with mode: 0644]
mpc8240/cpu.c [new file with mode: 0644]
mpc8240/cpu_init.c [new file with mode: 0644]
mpc8240/drivers/dma/Makefile [new file with mode: 0644]
mpc8240/drivers/dma/Makefile_pc [new file with mode: 0644]
mpc8240/drivers/dma/README [new file with mode: 0644]
mpc8240/drivers/dma/dma.h [new file with mode: 0644]
mpc8240/drivers/dma/dma1.c [new file with mode: 0644]
mpc8240/drivers/dma/dma2.S [new file with mode: 0644]
mpc8240/drivers/dma/dma_export.h [new file with mode: 0644]
mpc8240/drivers/dma_export.h [new file with mode: 0644]
mpc8240/drivers/epic.h [new file with mode: 0644]
mpc8240/drivers/epic/README [new file with mode: 0644]
mpc8240/drivers/epic/epic.h [new file with mode: 0644]
mpc8240/drivers/epic/epic1.c [new file with mode: 0644]
mpc8240/drivers/epic/epic2.S [new file with mode: 0644]
mpc8240/drivers/epic/epicutil.S [new file with mode: 0644]
mpc8240/drivers/errors.h [new file with mode: 0644]
mpc8240/drivers/i2c/Makefile [new file with mode: 0644]
mpc8240/drivers/i2c/Makefile_pc [new file with mode: 0644]
mpc8240/drivers/i2c/README [new file with mode: 0644]
mpc8240/drivers/i2c/i2c.h [new file with mode: 0644]
mpc8240/drivers/i2c/i2c1.c [new file with mode: 0644]
mpc8240/drivers/i2c/i2c2.S [new file with mode: 0644]
mpc8240/drivers/i2c/i2c_export.h [new file with mode: 0644]
mpc8240/drivers/i2c_export.h [new file with mode: 0644]
mpc8240/drivers/i2o.h [new file with mode: 0644]
mpc8240/drivers/i2o/Makefile [new file with mode: 0644]
mpc8240/drivers/i2o/Makefile_pc [new file with mode: 0644]
mpc8240/drivers/i2o/i2o.h [new file with mode: 0644]
mpc8240/drivers/i2o/i2o1.c [new file with mode: 0644]
mpc8240/drivers/i2o/i2o2.S [new file with mode: 0644]
mpc8240/interrupts.c [new file with mode: 0644]
mpc8240/start.S [new file with mode: 0644]
mpc8240/start1.S [new file with mode: 0644]
mpc8240/traps.c [new file with mode: 0644]
mpc8xx/Makefile
mpc8xx/fec.c
mpc8xx/fec.h [new file with mode: 0644]
mpc8xx/interrupts.c
mpc8xx/scc.c
mpc8xx/status_led.c [new file with mode: 0644]
net/bootp.c
ppc/vsprintf.c
ppc4xx/405gp_enet.c
ppc4xx/miiphy.c
sandpoint/Makefile [new file with mode: 0644]
sandpoint/board_init.c [new file with mode: 0644]
sandpoint/config.mk [new file with mode: 0644]
sandpoint/flash.c [new file with mode: 0644]
sandpoint/interrupts.c [new file with mode: 0644]
sandpoint/interrupts.h [new file with mode: 0644]
sandpoint/ns16550.c [new file with mode: 0644]
sandpoint/ns16550.h [new file with mode: 0644]
sandpoint/ns87308.c [new file with mode: 0644]
sandpoint/ns87308.h [new file with mode: 0644]
sandpoint/ppcboot.lds [new file with mode: 0644]
sandpoint/ppcboot.lds.mw.debug [new file with mode: 0644]
sandpoint/sandpoint.c [new file with mode: 0644]
sandpoint/serial.c [new file with mode: 0644]
sandpoint/serial.h [new file with mode: 0644]
sandpoint/speed.c [new file with mode: 0644]
sandpoint/speed.h [new file with mode: 0644]
sandpoint/w83c553f.c [new file with mode: 0644]
sandpoint/w83c553f.h [new file with mode: 0644]
tools/gdb/Makefile
tools/gdb/remote.c
tools/img2srec.c
tools/mkimage.c

index eb1656cf38e63ad0c929ef40a7d463bce3d122c5..294e31ed5da62e6602099fd19a0f18b4ce98ef9f 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,11 @@
 Open Issues:
 ======================================================================
 
+* Enabling too many BOOTP Vendor Extensions easily overflows the 64
+  byte limit imposed by the BOOTP header definition. While this is
+  not a problem on our side, some DHCP servers will complain. Should
+  we break up long BOOTP requests into several shorter ones?
+
 * Boot with RAMDisk:
 
   No need to copy ramdisk image when it's already in RAM ??? Or do we
@@ -56,6 +61,16 @@ To do:
 Modifications for 0.6.3:
 ======================================================================
 
+* Added support for MBX860T (thanks to Rob Taylor)
+
+* Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+  Work In Progress (TM); current status: boots to command line input.
+  EPIC code non-functional (interrupts disabled), No net, No IDE.
+
+* Add support for Status LED
+
+* Optionally panic() to reboot instead of hanging
+
 * Misc bug fixes
 
 * All frequencies in HZ now (internally)
diff --git a/CREDITS b/CREDITS
index fbf70343dcd08a1bd0b58f1f86ec5ecf327f562b..3c1a80cac3b9a6f74fb0e5ca9b60192e70d4b3f2 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -66,7 +66,11 @@ D: Author of LiMon-1.4.2, which contributed some ideas
 
 N: Paolo Scaffardi
 E: arsenio@tin.it
-D: FADS823 configuration, MPC823 video support, I2C, wireless keyboard
+D: FADS823 configuration, MPC823 video support, I2C, wireless keyboard, lots more
+
+N: Rob Taylor
+E: robt@flyingpig.com
+D: Port to MBX860T and Sandpoint8240
 
 N: Christian Vejlbo
 E: christian.vejlbo@tellabs.com
diff --git a/MAKEALL b/MAKEALL
index 0778e9062fab962c5c0316db00ec9266859f1ad7..31d7ad9fc5e93f1505b5fefeb2a6ee5e55cce3d4 100755 (executable)
--- a/MAKEALL
+++ b/MAKEALL
@@ -10,7 +10,8 @@ for i in TQM823L TQM850L TQM855L TQM860L FPS850L SM850 \
         CPCI405 ADCIOP \
         cogent_mpc8xx \
         GENIETV \
-        cogent_mpc8260 hymod
+        cogent_mpc8260 hymod \
+        Sandpoint8240
 do
        make distclean >/dev/null
        make ${i}_config
index 61c8a9f6499ab0d95be9fb181e9b3a4eaa19ee97..abc308b331388d2731ebe7fe2cbb7cde4b03999a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -191,6 +191,22 @@ MBX_config:        unconfig
        echo "CPU   = mpc8xx"   >>config.mk ;   \
        echo "#include <config_$(@:_config=).h>" >config.h
 
+MBX860T_config:        unconfig
+       @echo "Configuring for $(@:_config=) Board..." ; \
+       cd include ;                            \
+       echo "ARCH  = ppc"      > config.mk ;   \
+       echo "BOARD = mbx"      >>config.mk ;   \
+       echo "CPU   = mpc8xx"   >>config.mk ;   \
+       echo "#include <config_$(@:_config=).h>" >config.h
+
+Sandpoint8240_config: unconfig
+       @echo "Configuring for $(@:_config=) Board..." ; \
+       cd include ;                            \
+       echo "ARCH  = ppc"      > config.mk ;   \
+       echo "BOARD = sandpoint"        >>config.mk ;   \
+       echo "CPU   = mpc8240"  >>config.mk ;   \
+       echo "#include <config_$(@:_config=).h>" >config.h
+
 hymod_config:  unconfig
        @echo "Configuring for $(@:_config=) Board..." ; \
        cd include ;                            \
diff --git a/README b/README
index 6afb4029b1e9895d872d59e561a2d2038132393a..afbd36836555e973fce819304d160d3eb6d8ff52 100644 (file)
--- a/README
+++ b/README
@@ -67,20 +67,23 @@ Directory Hierarchy:
 - ppc          Files generic to PowerPC architecture
 - tools                Tools to build S-Record or PPCBoot images, etc.
 
-- mpc8xx       Files specific to Motorola MPC8xx CPUs
-- ppc4xx       Files specific to IBM 4xx CPUs
+- mpc8xx       Files specific to Motorola MPC8xx  CPUs
+- mpc8240      Files specific to Motorola MPC8240 CPU
+- mpc8260      Files specific to Motorola MPC8260 CPU
+- ppc4xx       Files specific to IBM      4xx     CPUs
 
 - adciop       Files specific to ADCIOP   boards
 - cogent       Files specific to Cogent   boards
                (need further configuration)
 - cpci405      Files specific to CPCI405  boards
 - etx094       Files specific to ETX_094  boards
-- fads         Files specific to Motorola FADS boards
+- fads         Files specific to FADS     boards
 - genietv      Files specific to GENIETV  boards
 - hymod                Files specific to HYMOD    boards
 - ivms8                Files specific to IVMS8    boards
-- mbx8xx       Files specific to Motorola MBX  boards
+- mbx8xx       Files specific to MBX      boards
 - spd8xx       Files specific to SPD8xxTS boards
+- sandpoint    Files specific to Sandpoint boards
 - tqm8xx       Files specific to TQM8xxL  boards
 
 
index 1b377792ea14c961117fa070943c1533d13de3ee..6540fcaa13accd721f4bdd92c55e3621e41f2233 100644 (file)
@@ -31,6 +31,9 @@
 #if (CONFIG_COMMANDS & CFG_CMD_KGDB)
 #include <kgdb.h>
 #endif
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
 #include <version.h>
 
 static char *failed = "*** failed ***\n";
@@ -470,6 +473,9 @@ void    board_init_r  (bd_t *bd, ulong dest_addr)
      * Enable Interrupts
      */
     interrupt_init (bd);
+#ifdef CONFIG_STATUS_LED
+    status_led_set (STATUS_LED_BLINKING);
+#endif
 
     udelay(20);
 
index 167cdd1fa93f5c3ab8b78e0621b64150001a6d1c..693034aee52b3565c12669280c095a045031dd4e 100644 (file)
@@ -27,7 +27,7 @@
  */
 #include <mpc8xx_irq.h>
 #include <ppcboot.h>
-#include <config.h>            /* for PIO mode selection */
+#include <config.h>
 #include <command.h>
 #include <image.h>
 #ifdef CONFIG_IDE_PCMCIA
@@ -49,7 +49,9 @@ extern ldiv_t ldiv (long int __numer, long int __denom);
 # define __ldiv_t_defined      1
 #endif
 
-#ifdef DEBUG
+#undef IDE_DEBUG
+
+#ifdef IDE_DEBUG
 #define        PRINTF(fmt,args...)     do {                            \
                                        printf (fmt ,##args);   \
                                } while (0)
@@ -97,107 +99,6 @@ static int pio_mode = CFG_PIO_MODE;
 
 /* ------------------------------------------------------------------------- */
 
-#ifdef CONFIG_IDE_PCMCIA
-/*
- * Allow configuration to select PCMCIA slot,
- * or try to generate a useful default
- */
-#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
-
-                                       /* The RPX series use SLOT_B    */
-#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
-# define CONFIG_PCMCIA_SLOT_B
-#elif defined(CONFIG_ADS)              /* The ADS  board use SLOT_A    */
-# define CONFIG_PCMCIA_SLOT_A
-#elif defined(CONFIG_FADS)             /* The FADS series are a mess   */
-# if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)
-#  define CONFIG_PCMCIA_SLOT_A
-# else
-#  define CONFIG_PCMCIA_SLOT_B
-# endif
-#elif defined(CONFIG_TQM860L) || defined(CONFIG_TQM855L) /* The TQM8xxL modules */
-# define       CONFIG_PCMCIA_SLOT_A    /* ... use SLOT_A on MPC860/855 */
-#elif defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L)
-# define       CONFIG_PCMCIA_SLOT_B    /* ... and SLOT_B else          */
-#elif defined(CONFIG_SPD823TS)         /* The SPD8xx use SLOT_B        */
-# define CONFIG_PCMCIA_SLOT_B
-#else
-# error "PCMCIA Slot not configured"
-#endif
-
-#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
-
-/* Make sure exactly one slot is defined - we support only one for now */
-#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
-#error Neither CONFIG_PCMCIA_SLOT_A nor CONFIG_PCMCIA_SLOT_B configured
-#endif
-#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
-#error Both CONFIG_PCMCIA_SLOT_A and CONFIG_PCMCIA_SLOT_B configured
-#endif
-
-#define PCMCIA_SOCKETS_NO      1
-#define PCMCIA_MEM_WIN_NO      4
-#define PCMCIA_IO_WIN_NO       2
-
-/* define _slot_ to be able to optimize macros */
-#ifdef CONFIG_PCMCIA_SLOT_A
-# define _slot_                        0
-# define PCMCIA_SLOT_MSG       "SLOT_A"
-#else
-# define _slot_                        1
-# define PCMCIA_SLOT_MSG       "SLOT_B"
-#endif
-
-/*
- * The TQM850L hardware has two pins swapped! Grrrrgh!
- */
-#ifdef CONFIG_TQM850L
-#define __MY_PCMCIA_GCRX_CXRESET       PCMCIA_GCRX_CXOE
-#define __MY_PCMCIA_GCRX_CXOE          PCMCIA_GCRX_CXRESET
-#else
-#define __MY_PCMCIA_GCRX_CXRESET       PCMCIA_GCRX_CXRESET
-#define __MY_PCMCIA_GCRX_CXOE          PCMCIA_GCRX_CXOE
-#endif
-
-/* look up table for pgcrx registers */
-
-#if 0
-static u_int *pcmcia_pgcrx[2] = {
-       &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra,
-       &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb,
-};
-
-#define PCMCIA_PGCRX(slot)     (*pcmcia_pgcrx[slot])
-#endif
-
-/*
- * This structure is used to address each window in the PCMCIA controller.
- *
- * Keep in mind that we assume that pcmcia_win_t[n+1] is mapped directly
- * after pcmcia_win_t[n]...
- */
-
-typedef struct {
-       ulong   br;
-       ulong   or;
-} pcmcia_win_t;
-
-/* ------------------------------------------------------------------------- */
-
-/*
- * Memory Map Information:
- *
- * BR0 / OR0:  EPROM1  Base 0xFF000000 Size 512KB
- * BR1 / OR1:  EPROM2  Base 0xFF080000 Size 512KB
- * BR2 / OR2:  SRAM    Base 0xFE200000 Size   2MB
- * BR3 / OR3:  SDRAM   Base 0x00000000 Size  16MB (max. 64 MB used)
- * BR4 / OR4:  PER-8   Base 0xFE000000 Size   1MB
- * BR5 / OR5:  SHARC   Base 0xFE400000 Size   4MB
- */
-/* ------------------------------------------------------------------------- */
-
-#endif /* CONFIG_IDE_PCMCIA */
-
 /* Current I/O Device  */
 static int curr_device = -1;
 
@@ -572,7 +473,6 @@ void ide_init (bd_t *bd)
                        udelay (10000);         /* 10 ms */
 
                        c = inb (dev, ATA_STATUS);
-                       ++i;
                        if (i > (ATA_RESET_TIME * 100)) {
                                puts ("** Timeout **\n");
                                ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */
@@ -640,6 +540,7 @@ set_pcmcia_timing (int pmode)
                        | timings
 #endif
                        ;
+       PRINTF ("PBR0: %08x  POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0);
 
        pcmp->pcmc_pbr1 = CFG_PCMCIA_PBR1;
        pcmp->pcmc_por1 = CFG_PCMCIA_POR1
@@ -647,6 +548,7 @@ set_pcmcia_timing (int pmode)
                        | timings
 #endif
                        ;
+       PRINTF ("PBR1: %08x  POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1);
 
        pcmp->pcmc_pbr2 = CFG_PCMCIA_PBR2;
        pcmp->pcmc_por2 = CFG_PCMCIA_POR2
@@ -654,6 +556,7 @@ set_pcmcia_timing (int pmode)
                        | timings
 #endif
                        ;
+       PRINTF ("PBR2: %08x  POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2);
 
        pcmp->pcmc_pbr3 = CFG_PCMCIA_PBR3;
        pcmp->pcmc_por3 = CFG_PCMCIA_POR3
@@ -661,6 +564,7 @@ set_pcmcia_timing (int pmode)
                        | timings
 #endif
                        ;
+       PRINTF ("PBR3: %08x  POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3);
 
        /* IDE 1
         */
@@ -670,6 +574,7 @@ set_pcmcia_timing (int pmode)
                        | timings
 #endif
                        ;
+       PRINTF ("PBR4: %08x  POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4);
 
        pcmp->pcmc_pbr5 = CFG_PCMCIA_PBR5;
        pcmp->pcmc_por5 = CFG_PCMCIA_POR5
@@ -677,6 +582,7 @@ set_pcmcia_timing (int pmode)
                        | timings
 #endif
                        ;
+       PRINTF ("PBR5: %08x  POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5);
 
        pcmp->pcmc_pbr6 = CFG_PCMCIA_PBR6;
        pcmp->pcmc_por6 = CFG_PCMCIA_POR6
@@ -684,6 +590,7 @@ set_pcmcia_timing (int pmode)
                        | timings
 #endif
                        ;
+       PRINTF ("PBR6: %08x  POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6);
 
        pcmp->pcmc_pbr7 = CFG_PCMCIA_PBR7;
        pcmp->pcmc_por7 = CFG_PCMCIA_POR7
@@ -691,6 +598,7 @@ set_pcmcia_timing (int pmode)
                        | timings
 #endif
                        ;
+       PRINTF ("PBR7: %08x  POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7);
 
 }
 
@@ -848,6 +756,7 @@ static void ide_print (int device)
 {
        ldiv_t mb, gb;
        ide_dev_id_t *idp = &(ide_device[device]);
+       char *mod, *ser;
 
        if (idp->size == 0) {
                puts ("not available\n");
@@ -864,7 +773,10 @@ static void ide_print (int device)
        gb.rem += 512;
        gb.rem /= 1024;
 
-       printf ("Model: %s  Serial #: %s  ", idp->model, idp->serial_no);
+       mod = idp->model;       while (*mod && (*mod==' ')) ++mod;
+       ser = idp->serial_no;   while (*ser && (*ser==' ')) ++ser;
+
+       printf ("Model: %s  Serial #: %s  ", mod, ser);
        printf ("Capacity: %ld.%ld MB = %ld.%ld GB\n",
                mb.quot, mb.rem, gb.quot, gb.rem);
 }
@@ -1030,14 +942,32 @@ static void ide_reset (void)
        immr->im_ioport.iop_pcso  &= ~(CFG_PC_IDE_RESET);
        immr->im_ioport.iop_pcdir |=   CFG_PC_IDE_RESET;        /* Make output  */
 
+#if 1
        /* assert IDE RESET signal */
        immr->im_ioport.iop_pcdat &= ~(CFG_PC_IDE_RESET);
        udelay (20000);
        /* de-assert RESET signal of IDE */
        immr->im_ioport.iop_pcdat |=   CFG_PC_IDE_RESET;
+#else
+       /* assert IDE RESET signal */
+       immr->im_ioport.iop_pcdat |=   CFG_PC_IDE_RESET;
+       udelay (20000);
+       /* de-assert RESET signal of IDE */
+       immr->im_ioport.iop_pcdat &= ~(CFG_PC_IDE_RESET);
+#endif
 #else
 #error IDE reset pin not configured
 #endif
+
+#ifdef CFG_PB_IDE_MOTOR
+       immr->im_cpm.cp_pbpar &= ~(CFG_PB_IDE_MOTOR);   /* IDE Motor in pin */
+       immr->im_cpm.cp_pbodr &= ~(CFG_PB_IDE_MOTOR);
+       immr->im_cpm.cp_pbdir &= ~(CFG_PB_IDE_MOTOR); /* input */
+       if ((immr->im_cpm.cp_pbdat & CFG_PB_IDE_MOTOR) == 0) {
+               printf ("\nWarning: 5V for IDE Motor missing\n");
+       }
+#endif /* CFG_PB_IDE_MOTOR */
+
        udelay (100000);
 }
 
index b7ac76cdd795c113cedd2c993cb23e8777d68b07..b4f03838f91320b2013770fab8bc25cf0a78df1d 100644 (file)
@@ -405,6 +405,7 @@ static int process_separators (char *s, int len,
                                        return 0;
                                }
 
+#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
                                /* avoid "bootd" recursion */
                                if ((len < 0) && (cmdtp->cmd == do_bootd)) {
 #ifdef DEBUG_PARSER
@@ -413,7 +414,7 @@ static int process_separators (char *s, int len,
                                        printf ("'bootd' recursion detected\n");
                                        return 0;
                                }
-
+#endif /* CFG_CMD_BOOTD */
                                /* OK - call function */
                                (cmdtp->cmd) (cmdtp, bd, flag, argc, argv);
 
index 3e34010f70e6a39f25d348b3cc4fc4b560b0fee8..0596d9b831100cc673968aee016de1c74d9f4fdf 100644 (file)
--- a/config.mk
+++ b/config.mk
@@ -68,7 +68,7 @@ OPTFLAGS= -Os -fomit-frame-pointer
 LDSCRIPT := $(BOARD)/ppcboot.lds
 
 CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS)        \
-       -D__KERNEL__                            \
+       -D__KERNEL__ -D__powerpc__              \
        -I$(TOPDIR)/include                     \
        -fno-builtin                            \
        -pipe $(PLATFORM_CPPFLAGS)
index 6c1cb121fb1ee6abb69a70b487eec69200ff6845..5d8560a4c26bf065f794a0b0cc5934f3a083c9d3 100644 (file)
@@ -480,7 +480,7 @@ void        flash_erase (flash_info_t *info, int s_first, int s_last)
 {
        vu_long *addr = (vu_long*)(info->start[0]);
        int flag, prot, sect;
-       ulong start, now, last;
+       ulong type, start, now, last;
 
        if ((s_first < 0) || (s_first > s_last)) {
                if (info->flash_id == FLASH_UNKNOWN) {
@@ -491,9 +491,10 @@ void       flash_erase (flash_info_t *info, int s_first, int s_last)
                return;
        }
 
-       if ((info->flash_id == FLASH_UNKNOWN) ||
-           (info->flash_id > FLASH_AMD_COMP)) {
-               printf ("Can't erase unknown flash type - aborted\n");
+       type = (info->flash_id & FLASH_VENDMASK);
+       if ((type != FLASH_MAN_SST) && (type != FLASH_MAN_STM)) {
+               printf ("Can't erase unknown flash type %08lx - aborted\n",
+                       info->flash_id);
                return;
        }
 
index e616ac6d8708c20ddc9d4596c2535fd9459c44f3..af2a3ded5b5137f6f7da86f15ca260e6ea401706 100644 (file)
@@ -335,38 +335,39 @@ typedef struct smc {              /* Serial management channels */
 /* MPC860T Fast Ethernet Controller.  It isn't part of the CPM, but
  * it fits within the address space.
  */
+
 typedef struct fec {
-       uint    fec_addr_low;           /* LS 32 bits of station address */
-       ushort  fec_addr_high;          /* MS 16 bits of address */
-       ushort  res1;
-       uint    fec_hash_table_high;
-       uint    fec_hash_table_low;
-       uint    fec_r_des_start;
-       uint    fec_x_des_start;
-       uint    fec_r_buff_size;
-       uint    res2[9];
-       uint    fec_ecntrl;
-       uint    fec_ievent;
-       uint    fec_imask;
-       uint    fec_ivec;
-       uint    fec_r_des_active;
-       uint    fec_x_des_active;
-       uint    res3[10];
-       uint    fec_mii_data;
-       uint    fec_mii_speed;
-       uint    res4[17];
-       uint    fec_r_bound;
-       uint    fec_r_fstart;
-       uint    res5[6];
-       uint    fec_x_fstart;
-       uint    res6[17];
-       uint    fec_fun_code;
-       uint    res7[3];
-       uint    fec_r_cntrl;
-       uint    fec_r_hash;
-       uint    res8[14];
-       uint    fec_x_cntrl;
-       uint    res9[0x1e];
+       uint    fec_addr_low;           /* lower 32 bits of station address     */
+       ushort  fec_addr_high;          /* upper 16 bits of station address     */
+       ushort  res1;                   /* reserved                             */
+       uint    fec_hash_table_high;    /* upper 32-bits of hash table          */
+       uint    fec_hash_table_low;     /* lower 32-bits of hash table          */
+       uint    fec_r_des_start;        /* beginning of Rx descriptor ring      */
+       uint    fec_x_des_start;        /* beginning of Tx descriptor ring      */
+       uint    fec_r_buff_size;        /* Rx buffer size                       */
+       uint    res2[9];                /* reserved                             */
+       uint    fec_ecntrl;             /* ethernet control register            */
+       uint    fec_ievent;             /* interrupt event register             */
+       uint    fec_imask;              /* interrupt mask register              */
+       uint    fec_ivec;               /* interrupt level and vector status    */
+       uint    fec_r_des_active;       /* Rx ring updated flag                 */
+       uint    fec_x_des_active;       /* Tx ring updated flag                 */
+       uint    res3[10];               /* reserved                             */
+       uint    fec_mii_data;           /* MII data register                    */
+       uint    fec_mii_speed;          /* MII speed control register           */
+       uint    res4[17];               /* reserved                             */
+       uint    fec_r_bound;            /* end of RAM (read-only)               */
+       uint    fec_r_fstart;           /* Rx FIFO start address                */
+       uint    res5[6];                /* reserved                             */
+       uint    fec_x_fstart;           /* Tx FIFO start address                */
+       uint    res6[17];               /* reserved                             */
+       uint    fec_fun_code;           /* fec SDMA function code               */
+       uint    res7[3];                /* reserved                             */
+       uint    fec_r_cntrl;            /* Rx control register                  */
+       uint    fec_r_hash;             /* Rx hash register                     */
+       uint    res8[14];               /* reserved                             */
+       uint    fec_x_cntrl;            /* Tx control register                  */
+       uint    res9[0x1e];             /* reserved                             */
 } fec_t;
 
 /* The FEC and LCD color map share the same address space....
diff --git a/include/asm/io.h b/include/asm/io.h
new file mode 100755 (executable)
index 0000000..426f926
--- /dev/null
@@ -0,0 +1,180 @@
+/* originally from linux source.
+ * removed the dependacies on CONFIG_ values
+ * removed virt_to_phys stuff (and in fact everything surrounded by #if __KERNEL__)
+ * Modified By Rob Taylor, Flying Pig Systems, 2000
+ */
+
+#ifndef _PPC_IO_H
+#define _PPC_IO_H
+
+#include <linux/config.h>
+#include <asm/byteorder.h>
+
+#define SIO_CONFIG_RA   0x398
+#define SIO_CONFIG_RD   0x399
+
+
+#define readb(addr) in_8((volatile u8 *)(addr))
+#define writeb(b,addr) out_8((volatile u8 *)(addr), (b))
+#if !defined(__BIG_ENDIAN)
+#define readw(addr) (*(volatile u16 *) (addr))
+#define readl(addr) (*(volatile u32 *) (addr))
+#define writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
+#define writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
+#else
+#define readw(addr) in_le16((volatile u16 *)(addr))
+#define readl(addr) in_le32((volatile u32 *)(addr))
+#define writew(b,addr) out_le16((volatile u16 *)(addr),(b))
+#define writel(b,addr) out_le32((volatile u32 *)(addr),(b))
+#endif
+
+/*
+ * The insw/outsw/insl/outsl macros don't do byte-swapping.
+ * They are only used in practice for transferring buffers which
+ * are arrays of bytes, and byte-swapping is not appropriate in
+ * that case.  - paulus
+ */
+#define insb(port, buf, ns) _insb((u8 *)((port)+_IO_BASE), (buf), (ns))
+#define outsb(port, buf, ns)    _outsb((u8 *)((port)+_IO_BASE), (buf), (ns))
+#define insw(port, buf, ns) _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define outsw(port, buf, ns)    _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define insl(port, buf, nl) _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define outsl(port, buf, nl)    _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+
+#define inb(port)       in_8((u8 *)((port)+_IO_BASE))
+#define outb(val, port)     out_8((u8 *)((port)+_IO_BASE), (val))
+#if !defined(__BIG_ENDIAN)
+#define inw(port)       in_be16((u16 *)((port)+_IO_BASE))
+#define outw(val, port)     out_be16((u16 *)((port)+_IO_BASE), (val))
+#define inl(port)       in_be32((u32 *)((port)+_IO_BASE))
+#define outl(val, port)     out_be32((u32 *)((port)+_IO_BASE), (val))
+#else
+#define inw(port)       in_le16((u16 *)((port)+_IO_BASE))
+#define outw(val, port)     out_le16((u16 *)((port)+_IO_BASE), (val))
+#define inl(port)       in_le32((u32 *)((port)+_IO_BASE))
+#define outl(val, port)     out_le32((u32 *)((port)+_IO_BASE), (val))
+#endif
+
+#define inb_p(port)     in_8((u8 *)((port)+_IO_BASE))
+#define outb_p(val, port)   out_8((u8 *)((port)+_IO_BASE), (val))
+#define inw_p(port)     in_le16((u16 *)((port)+_IO_BASE))
+#define outw_p(val, port)   out_le16((u16 *)((port)+_IO_BASE), (val))
+#define inl_p(port)     in_le32((u32 *)((port)+_IO_BASE))
+#define outl_p(val, port)   out_le32((u32 *)((port)+_IO_BASE), (val))
+
+extern void _insb(volatile u8 *port, void *buf, int ns);
+extern void _outsb(volatile u8 *port, const void *buf, int ns);
+extern void _insw(volatile u16 *port, void *buf, int ns);
+extern void _outsw(volatile u16 *port, const void *buf, int ns);
+extern void _insl(volatile u32 *port, void *buf, int nl);
+extern void _outsl(volatile u32 *port, const void *buf, int nl);
+extern void _insw_ns(volatile u16 *port, void *buf, int ns);
+extern void _outsw_ns(volatile u16 *port, const void *buf, int ns);
+extern void _insl_ns(volatile u32 *port, void *buf, int nl);
+extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
+
+/*
+ * The *_ns versions below don't do byte-swapping.
+ * Neither do the standard versions now, these are just here
+ * for older code.
+ */
+#define insw_ns(port, buf, ns)  _insw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define outsw_ns(port, buf, ns) _outsw_ns((u16 *)((port)+_IO_BASE), (buf), (ns))
+#define insl_ns(port, buf, nl)  _insl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+#define outsl_ns(port, buf, nl) _outsl_ns((u32 *)((port)+_IO_BASE), (buf), (nl))
+
+
+#define IO_SPACE_LIMIT ~0
+
+#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c)  memcpy((void *)(a),(b),(c))
+
+/*
+ * Enforce In-order Execution of I/O:
+ * Acts as a barrier to ensure all previous I/O accesses have
+ * completed before any further ones are issued.
+ */
+#define eieio() __asm__ __volatile__ ("eieio" : : : "memory");
+#define sync()  __asm__ __volatile__ ("sync" : : : "memory");
+
+/* Enforce in-order execution of data I/O.
+ * No distinction between read/write on PPC; use eieio for all three.
+ */
+#define iobarrier_rw() eieio()
+#define iobarrier_r()  eieio()
+#define iobarrier_w()  eieio()
+
+/*
+ * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
+ */
+extern inline int in_8(volatile u8 *addr)
+{
+    int ret;
+
+    __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
+    return ret;
+}
+
+extern inline void out_8(volatile u8 *addr, int val)
+{
+    __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
+}
+
+extern inline int in_le16(volatile u16 *addr)
+{
+    int ret;
+
+    __asm__ __volatile__("lhbrx %0,0,%1; eieio" : "=r" (ret) :
+                  "r" (addr), "m" (*addr));
+    return ret;
+}
+
+extern inline int in_be16(volatile u16 *addr)
+{
+    int ret;
+
+    __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
+    return ret;
+}
+
+extern inline void out_le16(volatile u16 *addr, int val)
+{
+    __asm__ __volatile__("sthbrx %1,0,%2; eieio" : "=m" (*addr) :
+                  "r" (val), "r" (addr));
+}
+
+extern inline void out_be16(volatile u16 *addr, int val)
+{
+    __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
+}
+
+extern inline unsigned in_le32(volatile u32 *addr)
+{
+    unsigned ret;
+
+    __asm__ __volatile__("lwbrx %0,0,%1; eieio" : "=r" (ret) :
+                 "r" (addr), "m" (*addr));
+    return ret;
+}
+
+extern inline unsigned in_be32(volatile u32 *addr)
+{
+    unsigned ret;
+
+    __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr));
+    return ret;
+}
+
+extern inline void out_le32(volatile unsigned *addr, int val)
+{
+    __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) :
+                 "r" (val), "r" (addr));
+}
+
+extern inline void out_be32(volatile unsigned *addr, int val)
+{
+    __asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
+}
+
+#endif
diff --git a/include/asm/mc146818rtc.h b/include/asm/mc146818rtc.h
new file mode 100755 (executable)
index 0000000..5f806c4
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Machine dependent access functions for RTC registers.
+ */
+#ifndef __ASM_PPC_MC146818RTC_H
+#define __ASM_PPC_MC146818RTC_H
+
+#include <asm/io.h>
+
+#ifndef RTC_PORT
+#define RTC_PORT(x) (0x70 + (x))
+#define RTC_ALWAYS_BCD  1   /* RTC operates in binary mode */
+#endif
+
+/*
+ * The yet supported machines all access the RTC index register via
+ * an ISA port access but the way to access the date register differs ...
+ */
+#define CMOS_READ(addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+inb_p(RTC_PORT(1)); \
+})
+#define CMOS_WRITE(val, addr) ({ \
+outb_p((addr),RTC_PORT(0)); \
+outb_p((val),RTC_PORT(1)); \
+})
+
+#endif /* __ASM_PPC_MC146818RTC_H */
diff --git a/include/asm/pci_io.h b/include/asm/pci_io.h
new file mode 100755 (executable)
index 0000000..0f57b53
--- /dev/null
@@ -0,0 +1,43 @@
+/* originally from linux source (asm-ppc/io.h).
+ * Sanity added by Rob Taylor, Flying Pig Systems, 2000
+ */
+#ifndef _PCI_IO_H_
+#define _PCI_IO_H_
+
+#include "io.h"
+
+
+#define pci_read_le16(addr, dest) \
+    __asm__ __volatile__("lhbrx %0,0,%1" : "=r" (dest) : \
+                  "r" (addr), "m" (*addr));
+
+#define pci_write_le16(addr, val) \
+    __asm__ __volatile__("sthbrx %1,0,%2" : "=m" (*addr) : \
+                  "r" (val), "r" (addr));
+
+
+#define pci_read_le32(addr, dest) \
+    __asm__ __volatile__("lwbrx %0,0,%1" : "=r" (dest) : \
+                 "r" (addr), "m" (*addr));
+
+#define pci_write_le32(addr, val) \
+__asm__ __volatile__("stwbrx %1,0,%2" : "=m" (*addr) : \
+                 "r" (val), "r" (addr));
+
+#define pci_readb(addr,b) ((b) = *(volatile u8 *) (addr))
+#define pci_writeb(b,addr) ((*(volatile u8 *) (addr)) = (b))
+
+#if !defined(__BIG_ENDIAN)
+#define pci_readw(addr,b) ((b) = *(volatile u16 *) (addr))
+#define pci_readl(addr,b) ((b) = *(volatile u32 *) (addr))
+#define pci_writew(b,addr) ((*(volatile u16 *) (addr)) = (b))
+#define pci_writel(b,addr) ((*(volatile u32 *) (addr)) = (b))
+#else
+#define pci_readw(addr,b) pci_read_le16((volatile u16 *)(addr),(b))
+#define pci_readl(addr,b) pci_read_le32((volatile u32 *)(addr),(b))
+#define pci_writew(b,addr) pci_write_le16((volatile u16 *)(addr),(b))
+#define pci_writel(b,addr) pci_write_le32((volatile u32 *)(addr),(b))
+#endif
+
+
+#endif /* _PCI_IO_H_ */
index 7f8d7bf98d6d9934c7da5b1298bb35855927c577..cbc5f90f73222e7bb593e3c10e950119e8f8b911 100644 (file)
 #define _MACH_oak      0x00000800      /* IBM "Oak" 403 eval. board */
 #define _MACH_walnut   0x00001000      /* IBM "Walnut" 405GP eval. board */
 #define _MACH_8260     0x00002000      /* Generic 8260 */
-#define _MACH_tqm860   0x00004000      /* TQM860/L */
-#define _MACH_tqm8xxL  0x00008000      /* TQM8xxL */
+#define _MACH_sandpoint 0x00004000     /* Motorola SPS Processor eval board */
+#define _MACH_tqm860   0x00008000      /* TQM860/L */
+#define _MACH_tqm8xxL  0x00010000      /* TQM8xxL */
 
 
 /* see residual.h for these */
@@ -556,6 +557,8 @@ n:
                                     : "=r" (rval)); rval;})
 #define mtspr(rn, v)   asm volatile("mtspr " stringify(rn) ",%0" : : "r" (v))
 
+#define tlbie(v)       asm volatile("tlbie %0 \n sync" : : "r" (v))
+
 /* Segment Registers */
 
 #define SR0    0
@@ -723,6 +726,9 @@ void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
 #elif defined(CONFIG_8260)
 #define _machine _MACH_8260
 #define have_of 0
+#elif defined(CONFIG_SANDPOINT)
+#define _machine _MACH_sandpoint
+#define have_of 0
 #else
 #error "Machine not defined correctly"
 #endif
index e1a2d597fe07c46ea0dcfff351825526edbbb508..e6ba1fc5425356ef93664d09f0b2aee5f5008c64 100644 (file)
@@ -382,6 +382,15 @@ typedef struct scc_enet {
        ushort  sen_taddrl;     /* temp address (LSB) */
 } scc_enet_t;
 
+/**********************************************************************
+ *
+ * Board specific configuration settings.
+ *
+ * Please note that we use the presence of a #define SCC_ENET and/or
+ * #define FEC_ENET to enable the SCC resp. FEC ethernet drivers.
+ **********************************************************************/
+
+
 /***  MBX  ************************************************************/
 
 #ifdef CONFIG_MBX
@@ -733,6 +742,37 @@ typedef struct scc_enet {
 #define SICR_ENET_CLKRT        ((uint)0x00260000)
 #endif /* CONFIG_SM850 */
 
+/*** IVMS8  **********************************************************/
+
+/* The IVMS8 uses the FEC on a MPC860T for Ethernet */
+
+#ifdef CONFIG_IVMS8
+
+#define        FEC_ENET        /* use FEC for EThernet */
+#undef SCC_ENET
+
+#define        PB_ENET_POWER   ((uint)0x00010000)      /* PB 15 */
+
+#define PC_ENET_RESET  ((ushort)0x0010)        /* PC 11 */
+
+#define PD_MII_TXD1    ((ushort)0x1000)        /* PD  3 */
+#define PD_MII_TXD2    ((ushort)0x0800)        /* PD  4 */
+#define PD_MII_TXD3    ((ushort)0x0400)        /* PD  5 */
+#define PD_MII_RX_DV   ((ushort)0x0200)        /* PD  6 */
+#define PD_MII_RX_ERR  ((ushort)0x0100)        /* PD  7 */
+#define PD_MII_RX_CLK  ((ushort)0x0080)        /* PD  8 */
+#define PD_MII_TXD0    ((ushort)0x0040)        /* PD  9 */
+#define PD_MII_RXD0    ((ushort)0x0020)        /* PD 10 */
+#define PD_MII_TX_ERR  ((ushort)0x0010)        /* PD 11 */
+#define PD_MII_MDC     ((ushort)0x0008)        /* PD 12 */
+#define PD_MII_RXD1    ((ushort)0x0004)        /* PD 13 */
+#define PD_MII_RXD2    ((ushort)0x0002)        /* PD 14 */
+#define PD_MII_RXD3    ((ushort)0x0001)        /* PD 15 */
+
+#define PD_MII_MASK    ((ushort)0x1FFF)        /* PD 3...15 */
+
+#endif /* CONFIG_IVMS8 */
+
 /*********************************************************************/
 
 /* SCC Event register as used by Ethernet.
index 91d06fe8b2789a13128d798280f4802aa6d727e5..5324169638dfad3a4490a6e9162c30626a1df8c2 100644 (file)
@@ -56,6 +56,8 @@
 
 #undef CONFIG_WATCHDOG                 /* watchdog disabled            */
 
+#define        CONFIG_STATUS_LED       1       /* Status LED enabled           */
+
 #define CONFIG_BOOTP_MASK      CONFIG_BOOTP_ALL
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
index c9297bbf6f27abbdd2eb3adb1d374f64042b2f28..b038861466c085feb0b61d56e23c7e960312689b 100644 (file)
@@ -60,9 +60,9 @@
 #if 0
 #define CONFIG_COMMANDS        \
   ((CONFIG_CMD_DFL & ~(CFG_CMD_FLASH)) | CFG_CMD_IDE) /* no Flash, but IDE */
+#define CONFIG_COMMANDS                ((CONFIG_CMD_DFL | CFG_CMD_IDE) & ~(CFG_CMD_NET))
 #else
-#define CONFIG_COMMANDS                \
-  (CONFIG_CMD_DFL & ~(CFG_CMD_NET))
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | CFG_CMD_IDE)
 #endif /* 0 */
 
 #define CONFIG_BOOTP_MASK      CONFIG_BOOTP_DEFAULT
 
 #define CFG_PB_SDRAM_CLKE      0x00008000              /* PB 16        */
 #define CFG_PB_ETH_POWERDOWN   0x00010000              /* PB 15        */
+#define CFG_PB_IDE_MOTOR       0x00020000              /* PB 14        */
 
 #define CFG_PC_ETH_RESET       ((ushort)0x0010)        /* PC 11        */
 #define CFG_PC_IDE_RESET       ((ushort)0x0020)        /* PC 10        */
  */
 #define SCCR_MASK      SCCR_EBDF11
 /* 0x01800014 */
-#define CFG_SCCR       (SCCR_COM00     | /*SCCR_TBS|*/         \
+#define CFG_SCCR       (SCCR_COM01     | /*SCCR_TBS|*/         \
                         SCCR_RTDIV     |   SCCR_RTSEL    |     \
                         /*SCCR_CRQEN|*/  /*SCCR_PRQEN|*/       \
                         SCCR_EBDF00    |   SCCR_DFSYNC00 |     \
 #define CFG_PCMCIA_IO_ADDR     (0xEC000000)
 #define CFG_PCMCIA_IO_SIZE     ( 64 << 20 )
 
+/*-----------------------------------------------------------------------
+ * IDE/ATA stuff
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_IDE_PCMCIA      1       /* PCMCIA interface required    */
+#if 0
+#define CONFIG_IDE_LED         1       /* LED   for ide supported      */
+#endif
+#define CONFIG_IDE_RESET       1       /* reset for ide supported      */
+
+#define CFG_IDE_MAXBUS         1       /* The IVMS8 has only 1 IDE bus */
+#define CFG_IDE_MAXDEVICE      1       /*    ... and only 1 IDE device */
+
+#define CFG_ATA_BASE_ADDR      0xFE100000
+#define CFG_ATA_IDE0_OFFSET    0x0000
+#undef CFG_ATA_IDE1_OFFSET             /* only one IDE bus available   */
+
+#define CFG_ATA_DATA_OFFSET    0x0000  /* Offset for data I/O                  */
+#define CFG_ATA_REG_OFFSET     0x0080  /* Offset for normal register accesses  */
+#define CFG_ATA_ALT_OFFSET     0x0100  /* Offset for alternate registers       */
+
 /*-----------------------------------------------------------------------
  * 
  *-----------------------------------------------------------------------
diff --git a/include/config_Sandpoint8240.h b/include/config_Sandpoint8240.h
new file mode 100644 (file)
index 0000000..ba950f6
--- /dev/null
@@ -0,0 +1,222 @@
+
+
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC8240      1
+#define CONFIG_SANDPOINT    1
+
+#define CONFIG_BAUDRATE     9600
+#define CONFIG_DRAM_SPEED   100   /* MHz      */
+#define CONFIG_BOOTCOMMAND  "bootm FE020000"    /* autoboot command */
+#define CONFIG_BOOTARGS     " "
+
+#define CONFIG_COMMANDS  (CONFIG_CMD_DFL & ~CFG_CMD_NET)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+
+/*
+ * Miscellaneous configurable options
+ */
+#undef  CFG_LONGHELP            /* undef to save memory     */
+#define CFG_PROMPT      ":>"        /* Monitor Command Prompt   */
+#define CFG_CBSIZE      256     /* Console I/O Buffer Size  */
+#define CFG_PBSIZE      (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS     8       /* max number of command args   */
+#define CFG_BARGSIZE    CFG_CBSIZE  /* Boot Argument Buffer Size    */
+#define CFG_LOAD_ADDR   0x00100000  /* default load address */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE      0x00000000
+#define CFG_FLASH_BASE      0xFFF00000
+#define CFG_FLASH_SIZE      ((uint)(512 * 1024))   /* sandpoint has tiny eeprom */
+
+#ifdef DEBUG
+  #define CFG_MONITOR_BASE    CFG_SDRAM_BASE
+#else
+  #define CFG_MONITOR_BASE    CFG_FLASH_BASE
+#endif
+
+#ifdef DEBUG
+#define CFG_MONITOR_LEN     (4 <<20)   /* if we're running in ram, give us plenty of space for debug info*/
+#else
+#define CFG_MONITOR_LEN     (512 << 10)        /* Reserve 512 kB for Monitor   */
+#endif
+#define CFG_MALLOC_LEN      (512 << 10)        /* Reserve 512 kB for malloc()  */
+
+#define CFG_TFTP_LOADADDR   0x00100000 /* default load address */
+
+#define CFG_MEMTEST_START   0x00000000 /* memtest works on */
+#define CFG_MEMTEST_END     0x02000000 /* 0 ... 32 MB in DRAM   */
+
+#define CFG_EUMB_ADDR       0xFC000000
+
+#define CFG_ISA_MEM         0xFD000000
+#define CFG_ISA_IO          0xFE000000
+
+#define FLASH_BASE0_PRELIM  0xFFF00000  /* sandpoint flash    */
+#define FLASH_BASE1_PRELIM  0xFF000000  /* PMC onboard flash*/
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR CFG_SDRAM_BASE + CFG_MONITOR_LEN
+#define CFG_INIT_RAM_END   0x3000  /* End of used area in DPRAM  */
+#define CFG_INIT_DATA_SIZE  64  /* size in bytes reserved for initial data */
+#define CFG_INIT_DATA_OFFSET  (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET  CFG_INIT_DATA_OFFSET
+
+
+#define CFG_WINBOND_83C553      1           /*has a winbond bridge  */
+#define CFG_USE_WINBOND_IDE     0           /*use winbond 83c553 internal ide controller */
+#define CFG_WINBOND_ISA_CFG_ADDR    0x80005800  /*pci-isa bridge config addr */
+#define CFG_WINBOND_IDE_CFG_ADDR    0x80005900  /*ide config addr */
+#define CFG_NS87308_BADDR_10    1
+
+
+#define CFG_NS_PC87308UL        1           /* Nat Semi super-io controller on ISA bus */
+
+/*
+ * Low Level Configuration Settings
+ * (address mappings, register initial values, etc.)
+ * You should know what you are doing if you make changes here.
+ */
+
+
+#define CFG_ROMNAL          8       /*rom/flash next access time*/
+#define CFG_ROMFAL          16      /*rom/flash access time*/
+
+#define CFG_REFINT          430     /* no of clock cycles between CBR refresh cycles*/
+/* the following are for SDRAM only*/
+#define CFG_BSTOPRE         604     /* Burst To Precharge, sets open page interval */
+#define CFG_REFREC          8       /* Refresh to activate interval */
+#define CFG_RDLAT           4       /* data latancy from read command*/
+#define CFG_PRETOACT        3       /* Precharge to activate interval */
+#define CFG_ACTTOPRE        5       /* Activate to Precharge interval */
+#define CFG_SDMODE_CAS_LAT  3       /* SDMODE CAS latancy */
+#define CFG_SDMODE_WRAP     0       /* SDMODE wrap type */
+#define CFG_SDMODE_BURSTLEN 2       /* SDMODE Burst length 2=4, 3=8 */
+
+#define CFG_REGISTERD_TYPE_BUFFER   1
+
+/* memory bank settings*/
+/* only bits 20-29 are actually used from these vales to set the stare/end address
+   the upper two bits will be 0, and the lower 20 bits will be set to
+   0x00000 for a start address, or 0xfffff for an end address*/
+
+#define CFG_BANK0_START     0x00000000
+
+#define CFG_BANK0_END       0x01ffffff
+#define CFG_BANK0_ENABLE    1
+#define CFG_BANK1_START     0x01000000
+#define CFG_BANK1_END       0x00ffffff
+#define CFG_BANK1_ENABLE    0
+#define CFG_BANK2_START     0x02000000
+#define CFG_BANK2_END       0x02ffffff
+#define CFG_BANK2_ENABLE    0
+#define CFG_BANK3_START     0x03000000
+#define CFG_BANK3_END       0x03ffffff
+#define CFG_BANK3_ENABLE    0
+#define CFG_BANK4_START     0x04000000
+#define CFG_BANK4_END       0x04ffffff
+#define CFG_BANK4_ENABLE    0
+#define CFG_BANK5_START     0x05000000
+#define CFG_BANK5_END       0x05ffffff
+#define CFG_BANK5_ENABLE    0
+#define CFG_BANK6_START     0x06000000
+#define CFG_BANK6_END       0x06ffffff
+#define CFG_BANK6_ENABLE    0
+#define CFG_BANK7_START     0x07000000
+#define CFG_BANK7_END       0x07ffffff
+#define CFG_BANK7_ENABLE    0
+
+#define CFG_ODCR            0xff /* configures line driver impedances,
+                                    see 8240 book for bit definitions */
+#define CFG_PGMAX           0x32 /* how long the 8240 reatins the currently accessed page in memory
+                                    see 8240 book for details*/
+#define CFG_IBAT0L  FLASH_BASE0_PRELIM | BATL_CACHEINHIBIT | BATL_PP_10
+#define CFG_IBAT0U  FLASH_BASE0_PRELIM | BATU_BL_16M | BATU_VS | BATU_VP
+#define CFG_IBAT1L  0x00000000 | BATL_CACHEINHIBIT | BATL_PP_10
+#define CFG_IBAT1U  0x00000000 | BATU_BL_128M | BATU_VS | BATU_VP
+#define CFG_IBAT2L  CFG_ISA_MEM | BATL_MEMCOHERENCE | BATL_PP_10
+#define CFG_IBAT2U  CFG_ISA_MEM | BATU_BL_16M | BATU_VS | BATU_VP
+#define CFG_IBAT3L  CFG_ISA_IO | BATL_MEMCOHERENCE | BATL_PP_10
+#define CFG_IBAT3U  CFG_ISA_IO | BATU_BL_16M | BATU_VS | BATU_VP
+#define CFG_DBAT0L  FLASH_BASE0_PRELIM | BATL_MEMCOHERENCE | BATL_WRITETHROUGH | BATL_PP_10
+#define CFG_DBAT0U  FLASH_BASE0_PRELIM | BATU_BL_16M | BATU_VS | BATU_VP
+#define CFG_DBAT1L  0x00000000 | BATL_MEMCOHERENCE | BATL_WRITETHROUGH | BATL_PP_10
+#define CFG_DBAT1U  0x00000000 | BATU_BL_128M | BATU_VS | BATU_VP
+#define CFG_DBAT2L  CFG_ISA_MEM | BATL_MEMCOHERENCE | BATL_PP_10
+#define CFG_DBAT2U  CFG_ISA_MEM | BATU_BL_16M | BATU_VS | BATU_VP
+#define CFG_DBAT3L  CFG_ISA_IO | BATL_MEMCOHERENCE | BATL_PP_10
+#define CFG_DBAT3U  CFG_ISA_IO | BATU_BL_16M | BATU_VS | BATU_VP
+
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ       (8 << 20)   /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS 2           /* max number of memory banks       */
+#define CFG_MAX_FLASH_SECT  8           /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT    120000  /* Timeout for Flash Erase (in ms)  */
+#define CFG_FLASH_WRITE_TOUT    500     /* Timeout for Flash Write (in ms)  */
+
+#define CFG_FLASH_ENV_ALIGN 15  /*  Bitshift for Environment Sector */
+#define CFG_FLASH_ENV_SIZE  0x4000  /* Total Size of Environment Sector */
+/* the other CS:s are determined by looking at parameters in BCSRx */
+
+/* values according to the manual */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE  16          /* For all MPC8xx CPUs          */
+
+
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD           0x01        /* Normal Power-On: Boot from FLASH */
+#define BOOTFLAG_WARM           0x02        /* Software reboot          */
+
+
+/* values according to the manual */
+
+#define CONFIG_DRAM_50MHZ       1
+#define CONFIG_SDRAM_50MHZ
+
+#undef NR_8259_INTS
+#define NR_8259_INTS    1
+
+
+#define CONFIG_DISK_SPINUP_TIME 1000000
+
+
+#endif  /* __CONFIG_H */
index 3770d5f4ac8b09ec56c9890840abb8883cb8437e..9f01771b29a6b6e574bc3c1325a02c9a2d4ac3db 100644 (file)
@@ -60,6 +60,8 @@
 
 #undef CONFIG_WATCHDOG                 /* watchdog disabled            */
 
+#define        CONFIG_STATUS_LED       1       /* Status LED enabled           */
+
 #define CONFIG_BOOTP_MASK      CONFIG_BOOTP_DEFAULT
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
diff --git a/include/linux/mc146818rtc.h b/include/linux/mc146818rtc.h
new file mode 100755 (executable)
index 0000000..227feeb
--- /dev/null
@@ -0,0 +1,98 @@
+/* mc146818rtc.h - register definitions for the Real-Time-Clock / CMOS RAM
+ * Copyright Torsten Duwe <duwe@informatik.uni-erlangen.de> 1993
+ * derived from Data Sheet, Copyright Motorola 1984 (!).
+ * It was written to be part of the Linux operating system.
+ */
+/* permission is hereby granted to copy, modify and redistribute this code
+ * in terms of the GNU Library General Public License, Version 2 or later,
+ * at your option.
+ */
+
+#ifndef _MC146818RTC_H
+#define _MC146818RTC_H
+
+#include <asm/io.h>
+#include <linux/rtc.h>          /* get the user-level API */
+#include <asm/mc146818rtc.h>        /* register access macros */
+
+/**********************************************************************
+ * register summary
+ **********************************************************************/
+#define RTC_SECONDS     0
+#define RTC_SECONDS_ALARM   1
+#define RTC_MINUTES     2
+#define RTC_MINUTES_ALARM   3
+#define RTC_HOURS       4
+#define RTC_HOURS_ALARM     5
+/* RTC_*_alarm is always true if 2 MSBs are set */
+# define RTC_ALARM_DONT_CARE    0xC0
+
+#define RTC_DAY_OF_WEEK     6
+#define RTC_DAY_OF_MONTH    7
+#define RTC_MONTH       8
+#define RTC_YEAR        9
+
+/* control registers - Moto names
+ */
+#define RTC_REG_A       10
+#define RTC_REG_B       11
+#define RTC_REG_C       12
+#define RTC_REG_D       13
+
+/**********************************************************************
+ * register details
+ **********************************************************************/
+#define RTC_FREQ_SELECT RTC_REG_A
+
+/* update-in-progress  - set to "1" 244 microsecs before RTC goes off the bus,
+ * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete,
+ * totalling to a max high interval of 2.228 ms.
+ */
+# define RTC_UIP        0x80
+# define RTC_DIV_CTL        0x70
+   /* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */
+#  define RTC_REF_CLCK_4MHZ 0x00
+#  define RTC_REF_CLCK_1MHZ 0x10
+#  define RTC_REF_CLCK_32KHZ    0x20
+   /* 2 values for divider stage reset, others for "testing purposes only" */
+#  define RTC_DIV_RESET1    0x60
+#  define RTC_DIV_RESET2    0x70
+  /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */
+# define RTC_RATE_SELECT    0x0F
+
+/**********************************************************************/
+#define RTC_CONTROL RTC_REG_B
+# define RTC_SET 0x80       /* disable updates for clock setting */
+# define RTC_PIE 0x40       /* periodic interrupt enable */
+# define RTC_AIE 0x20       /* alarm interrupt enable */
+# define RTC_UIE 0x10       /* update-finished interrupt enable */
+# define RTC_SQWE 0x08      /* enable square-wave output */
+# define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
+# define RTC_24H 0x02       /* 24 hour mode - else hours bit 7 means pm */
+# define RTC_DST_EN 0x01    /* auto switch DST - works f. USA only */
+
+/**********************************************************************/
+#define RTC_INTR_FLAGS  RTC_REG_C
+/* caution - cleared by read */
+# define RTC_IRQF 0x80      /* any of the following 3 is active */
+# define RTC_PF 0x40
+# define RTC_AF 0x20
+# define RTC_UF 0x10
+
+/**********************************************************************/
+#define RTC_VALID   RTC_REG_D
+# define RTC_VRT 0x80       /* valid RAM and time */
+/**********************************************************************/
+
+/* example: !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+ * determines if the following two #defines are needed
+ */
+#ifndef BCD_TO_BIN
+#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
+#endif
+
+#ifndef BIN_TO_BCD
+#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
+#endif
+
+#endif /* _MC146818RTC_H */
diff --git a/include/mpc8240.h b/include/mpc8240.h
new file mode 100755 (executable)
index 0000000..f1b8f3a
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * Copyright Rob Taylor, Flying Pig Systems Ltd. 2000.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __MPC8240_H__
+#define __MPC8240_H__
+
+/*-----------------------------------------------------------------------
+ * Exception offsets (PowerPC standard)
+ */
+#define EXC_OFF_RESERVED0   0x0000  /* Reserved */
+#define EXC_OFF_SYS_RESET   0x0100  /* System reset */
+#define EXC_OFF_MACH_CHCK   0x0200  /* Machine Check */
+#define EXC_OFF_DATA_STOR   0x0300  /* Data Storage */
+#define EXC_OFF_INS_STOR    0x0400  /* Instruction Storage */
+#define EXC_OFF_EXTERNAL    0x0500  /* External */
+#define EXC_OFF_ALIGN       0x0600  /* Alignment */
+#define EXC_OFF_PROGRAM     0x0700  /* Program */
+#define EXC_OFF_FPUNAVAIL   0x0800  /* Floating-point Unavailable */
+#define EXC_OFF_DECR        0x0900  /* Decrementer */
+#define EXC_OFF_RESERVED1   0x0A00  /* Reserved */
+#define EXC_OFF_RESERVED2   0x0B00  /* Reserved */
+#define EXC_OFF_SYS_CALL    0x0C00  /* System Call */
+#define EXC_OFF_TRACE       0x0D00  /* Trace */
+#define EXC_OFF_FPUNASSIST  0x0E00  /* Floating-point Assist */
+
+        /* 0x0E10 - 0x0FFF are marked reserved in The PowerPC Architecture book */
+        /* these found in DINK code  - may not apply to 8240*/
+#define EXC_OFF_PMI         0x0F00  /* Performance Monitoring Interrupt */
+#define EXC_OFF_VMXUI       0x0F20  /* VMX (AltiVec) Unavailable Interrupt */
+
+        /* 0x1000 - 0x2FFF are implementation specific */
+        /* these found in DINK code  - may not apply to 8240 */
+#define EXC_OFF_ITME        0x1000  /* Instruction Translation Miss Exception */
+#define EXC_OFF_DLTME       0x1100  /* Data Load Translation Miss Exception */
+#define EXC_OFF_DSTME       0x1200  /* Data Store Translation Miss Exception */
+#define EXC_OFF_IABE        0x1300  /* Instruction Address Breakpoint Exception */
+#define EXC_OFF_SMIE        0x1400  /* System Management Interrupt Exception */
+#define EXC_OFF_JMDDI       0x1600  /* Java Mode denorm detection Interrupt -- WTF??*/
+#define EXC_OFF_RMTE        0x2000  /* Run Mode or Trace Exception */
+
+#define MAP_A_CONFIG_ADDR_HIGH     0x8000  /* Upper half of CONFIG_ADDR for Map A */
+#define MAP_A_CONFIG_ADDR_LOW      0x0CF8  /* Lower half of CONFIG_ADDR for Map A */
+#define MAP_A_CONFIG_DATA_HIGH      0x8000  /* Upper half of CONFIG_DAT for Map A */
+#define MAP_A_CONFIG_DATA_LOW       0x0CFC  /* Lower half of CONFIG_DAT for Map A */
+#define MAP_B_CONFIG_ADDR_HIGH     0xfec0  /* Upper half of CONFIG_ADDR for Map B */
+#define MAP_B_CONFIG_ADDR_LOW      0x0000  /* Lower half of CONFIG_ADDR for Map B */
+#define MAP_B_CONFIG_DATA_HIGH      0xfee0  /* Upper half of CONFIG_DAT for Map B */
+#define MAP_B_CONFIG_DATA_LOW       0x0000  /* Lower half of CONFIG_DAT for Map B */
+
+
+#if defined(CFG_ADDR_MAP_A)
+#define CONFIG_ADDR_HIGH     MAP_A_CONFIG_ADDR_HIGH /* Upper half of CONFIG_ADDR */
+#define CONFIG_ADDR_LOW      MAP_A_CONFIG_ADDR_LOW  /* Lower half of CONFIG_ADDR */
+#define CONFIG_DATA_HIGH     MAP_A_CONFIG_DATA_HIGH  /* Upper half of CONFIG_DAT */
+#define CONFIG_DATA_LOW      MAP_A_CONFIG_DATA_LOW    /* Lower half of CONFIG_DAT */
+#else /* Assume Map B, default */
+#define CONFIG_ADDR_HIGH     MAP_B_CONFIG_ADDR_HIGH /* Upper half of CONFIG_ADDR */
+#define CONFIG_ADDR_LOW      MAP_B_CONFIG_ADDR_LOW  /* Lower half of CONFIG_ADDR */
+#define CONFIG_DATA_HIGH      MAP_B_CONFIG_DATA_HIGH  /* Upper half of CONFIG_DAT */
+#define CONFIG_DATA_LOW       MAP_B_CONFIG_DATA_LOW   /* Lower half of CONFIG_DAT */
+#endif
+
+#define CONFIG_ADDR          (CONFIG_ADDR_HIGH << 16 | CONFIG_ADDR_LOW)
+
+#define CONFIG_DATA          (CONFIG_DATA_HIGH << 16 | CONFIG_DATA_LOW)
+
+/*macros to wite to conif registers. addr should be a constant in all cases */
+
+#define CONFIG_WRITE_BYTE( addr, data ) \
+  __asm__ ( \
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stb %3, %4(%2)\n \
+    sync " \
+  : /* no output */ \
+  : "r" (CONFIG_ADDR), "r" ((addr) & ~3), \
+    "r" (CONFIG_DATA), "r" (data), \
+    "n" ((addr) & 3));
+
+#define CONFIG_WRITE_HALFWORD( addr, data ) \
+  __asm__ ( \
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stwbrx %3, %4, %2\n \
+    sync " \
+  : /* no output */ \
+  : "r" (CONFIG_ADDR), "r" (addr), \
+    "r" (CONFIG_DATA), "r" (data), \
+    "n" ((addr) & 3));
+
+/* this assumes it's writeing on word boundaries*/
+#define CONFIG_WRITE_WORD( addr, data ) \
+  __asm__ ( \
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stwbrx %3, 0, %2\n \
+    sync " \
+  : /* no output */ \
+  : "r" (CONFIG_ADDR), "r" (addr), \
+    "r" (CONFIG_DATA), "r" (data));
+
+/* Configuration register reads*/
+
+#define CONFIG_READ_BYTE( addr , reg ) \
+  __asm__ ( \
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lbz   %0, %4(%3)\n \
+    sync " \
+  : "=r" (reg) \
+  : "r" ((addr) & ~3), "r" (CONFIG_ADDR), \
+    "r" (CONFIG_DATA), "n" ((addr) & 3));
+
+
+#define CONFIG_READ_HALFWORD( addr , reg ) \
+  __asm__ ( \
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lhbrx %0, %4, %3\n \
+    sync " \
+  : "=r" (reg) \
+  : "r" (addr), "r" (CONFIG_ADDR), \
+    "r" (CONFIG_DATA), \
+    "n" ((addr)&3));
+
+/* this assumes it's reading on word boundaries*/
+#define CONFIG_READ_WORD( addr , reg ) \
+  __asm__ ( \
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lwbrx %0, 0, %3\n \
+    sync " \
+  : "=r" (reg) \
+  : "r" (addr), "r" (CONFIG_ADDR),\
+    "r" (CONFIG_DATA));
+
+/*
+    configuration register 'addresses'.
+    These are described in chaper 5 of the 8240 users manual.
+    Where the register has an abreviation in the manual, this has been usaed here,
+    otherwise a name in keeping with the norm has been invented,
+    Note that some of these registers aren't documented in the manual
+*/
+
+#define PCICR           0x80000004  /* PCI Command Register */
+#define PCISR           0x80000006  /* PCI Status Register */
+#define PIR             0x80000009  /* PCI Programming Interface Register */
+#define PBCCR           0x8000000b  /* PCI Base Class Code Register */
+#define PCLSR           0x8000000c  /* Processor Cache Line Size Register */
+#define PLTR            0x8000000d  /* PCI Latancy Timer Register */
+#define PHTR            0x8000000e  /* PCI Header Type Register */
+#define BISTCTRL        0x8000000f  /* BIST Control */
+#define LMBAR           0x80000010  /* Local Base Addres Register */
+#define PCSRBAR         0x80000014  /* PCSR Base Address Register */
+#define ILR             0x8000003c  /* PCI Interrupt Line Register */
+#define IPR             0x8000003d  /* Interrupt Pin Register */
+#define MINGNT          0x8000003e  /* MIN GNI */
+#define MAXLAT          0x8000003f  /* MAX LAT */
+#define PCIACR          0x80000046  /* PCI Arbiter Control Register */
+#define PMCR1           0x80000070  /* Power management config. 1 */
+#define PMCR2           0x80000072  /* Power management config. 2 */
+#define ODCR            0x80000073  /* Output Driver Control Register */
+#define CLKDCR          0x80000074  /* CLK Driver Control Register */
+#define EUMBBAR         0x80000078  /* Embedded Utilities Memory Block Base Address Register */
+#define MSAR1           0x80000080  /* Memory Starting Address Register 1 */
+#define MSAR2           0x80000084  /* Memory Starting Address Register 2 */
+#define EMSAR1          0x80000088  /* Extended Memory Starting Address Register 1*/
+#define EMSAR2          0x8000008c  /* Extended Memory Starting Address Register 2*/
+#define MEAR1           0x80000090  /* Memory Ending Address Register 1 */
+#define MEAR2           0x80000094  /* Memory Ending Address Register 2 */
+#define EMEAR1          0x80000098  /* Extended Memory Ending Address Register 1 */
+#define EMEAR2          0x8000009c  /* Extended Memory Ending Address Register 2 */
+#define MBER            0x800000a0  /* Memory bank Enable Register*/
+#define MPMR            0x800000a3  /* Memory Page Mode Register (stores PGMAX) */
+#define PICR1           0x800000a8  /* Processor Interface Configuration Register 1 */
+#define PICR2           0x800000ac  /* Processor Interface Configuration Register 2 */
+#define ECCSBECR        0x800000b8  /* ECC Single-Bit Error Counter Register */
+#define ECCSBETR        0x800000b8  /* ECC Single-Bit Error Trigger Register */
+#define ERRENR1         0x800000c0  /* Error Enableing Register 1 */
+#define ERRENR2         0x800000c0  /* Error Enableing Register 2 */
+#define ERRDR1          0x800000c1  /* Error Detection Register 1 */
+#define IPBESR          0x800000c3  /* Internal Processor Error Status Register */
+#define ERRDR2          0x800000c5  /* Error Detection Register 2 */
+#define PBESR           0x800000c7  /* PCI Bus Error Status Register */
+#define PBEAR           0x800000c8  /* Processor/PCI Bus Error Status Register */
+#define AMBOR           0x800000e0  /* Address Map B Options Register */
+#define MCCR1           0x800000f0  /* Memory Control Configuration Register 1 */
+#define MCCR2           0x800000f4  /* Memory Control Configuration Register 2 */
+#define MCCR3           0x800000f8  /* Memory Control Configuration Register 3 */
+#define MCCR4           0x800000fc  /* Memory Control Configuration Register 4 */
+
+/* some values for soem of the above */
+
+#define PICR1_CF_APARK      0x00000008
+#define PICR1_LE_MODE       0x00000020
+#define PICR1_ST_GATH_EN    0x00000040
+#define PICR1_EN_PCS        0x00000080 /* according to dink code, sets the 8240 to handle pci config space */
+#define PICR1_CF_DPARK      0x00000200
+#define PICR1_MCP_EN        0x00000800
+#define PICR1_FLASH_WR_EN   0x00001000
+#define PICR1_ADDRESS_NAP   0x00010000
+#define PICR1_PROC_TYPE_MSK     0x00060000
+#define PICR1_PROC_TYPE_603E    0x00040000
+#define PICR1_RCS0          0x00100000
+#define PIRC1_MSK           0xff000000
+
+#define PICR2_CF_SNOOP_WS_MASK  0x000c0000
+#define PICR2_CF_SNOOP_WS_0WS   0x00000000
+#define PICR2_CF_SNOOP_WS_1WS   0x00040000
+#define PICR2_CF_SNOOP_WS_2WS   0x00080000
+#define PICR2_CF_SNOOP_WS_3WS   0x000c0000
+#define PICR2_CF_APHASE_WS_MASK 0x0000000c
+#define PICR2_CF_APHASE_WS_0WS  0x00000000
+#define PICR2_CF_APHASE_WS_1WS  0x00000004
+#define PICR2_CF_APHASE_WS_2WS  0x00000008
+#define PICR2_CF_APHASE_WS_3WS  0x0000000c
+
+#define MCCR1_ROMNAL_SHIFT      28
+#define MCCR1_ROMNAL_MSK        0xf0000000
+#define MCCR1_ROMFAL_SHIFT      23
+#define MCCR1_ROMFAL_MSK        0x0f800000
+#define MCCR1_BURST             0x00100000
+#define MCCR1_MEMGO             0x00080000
+#define MCCR1_SREN              0x00040000
+#define MCCR1_RAM_TYPE          0x00020000
+#define MCCR1_PCKEN             0x00010000
+
+#define MCCR2_TS_WAIT_TIMER_MSK 0xe0000000
+#define MCCR2_TS_WAIT_TIMER_SHIFT 29
+#define MCCR2_ASRISE_MSK        0x1e000000
+#define MCCR2_ASRISE_SHIFT      25
+#define MCCR2_ASFALL_MSK        0x01e00000
+#define MCCR2_ASFALL_SHIFT      21
+
+#define MCCR2_INLINE_PAR_NOT_ECC    0x00100000
+#define MCCR2_WRITE_PARITY_CHK  0x00080000
+#define MCCR2_INLFRD_PARECC_CHK_EN  0x00040000
+#define MCCR2_ECC_EN            0x00020000
+#define MCCR2_EDO               0x00010000
+#define MCCR2_REFINT_MSK        0x0000fffc
+#define MCCR2_REFINT_SHIFT      2
+#define MCCR2_RSV_PG            0x00000002
+#define MCCR2_PMW_PAR           0x00000001
+
+#define MCCR3_BSTOPRE2TO5_MSK   0xf0000000 /*BSTOPRE[2-5]*/
+#define MCCR3_BSTOPRE2TO5_SHIFT 28
+#define MCCR3_REFREC_MSK        0x0f000000
+#define MCCR3_REFREC_SHIFT      24
+#define MCCR3_RDLAT_MSK         0x00f00000
+#define MCCR3_RDLAT_SHIFT       20
+#define MCCR3_CPX               0x00010000
+#define MCCR3_RAS6P_MSK         0x00078000
+#define MCCR3_RAS6P_SHIFT       15
+#define MCCR3_CAS5_MSK          0x00007000
+#define MCCR3_CAS5_SHIFT        12
+#define MCCR3_CP4_MSK           0x00000e00
+#define MCCR3_CP4_SHIFT         9
+#define MCCR3_CAS3_MSK          0x000001c0
+#define MCCR3_CAS3_SHIFT        6
+#define MCCR3_RCD2_MSK          0x00000038
+#define MCCR3_RCD2_SHIFT        3
+#define MCCR3_RP1_MSK           0x00000007
+#define MCCR3_RP1_SHIFT         0
+
+#define MCCR4_PRETOACT_MSK      0xf0000000
+#define MCCR4_PRETOACT_SHIFT    28
+#define MCCR4_ACTTOPRE_MSK      0x0f000000
+#define MCCR4_ACTTOPRE_SHIFT    24
+#define MCCR4_WMODE             0x00800000
+#define MCCR4_INLINE            0x00400000
+#define MCCR4_BIT21             0x00200000 /* this include cos DINK code sets it- unknown function*/
+#define MCCR4_REGISTERED        0x00100000
+#define MCCR4_BSTOPRE0TO1_MSK   0x000c0000 /*BSTOPRE[0-1]*/
+#define MCCR4_BSTOPRE0TO1_SHIFT 18
+#define MCCR4_REGDIMM           0x00008000
+#define MCCR4_SDMODE_MSK        0x00007f00
+#define MCCR4_SDMODE_SHIFT      8
+#define MCCR4_ACTTORW_MSK       0x000000f0
+#define MCCR4_ACTTORW_SHIFT     4
+#define MCCR4_BSTOPRE6TO9_MSK   0x0000000f /*BSTOPRE[0-1]*/
+#define MCCR4_BSTOPRE6TO9_SHIFT 0
+
+#define MICR_ADDR_MASK          0x0ff00000
+#define MICR_EADDR_MASK         0x30000000
+
+#define BATU_BEPI_MSK            0xfffe0000
+#define BATU_BL_MSK              0x00001ffc
+
+#define BATU_BL_128K             0x00000000
+#define BATU_BL_256K             0x00000004
+#define BATU_BL_512K             0x0000000c
+#define BATU_BL_1M               0x0000001c
+#define BATU_BL_2M               0x0000003c
+#define BATU_BL_4M               0x0000007c
+#define BATU_BL_8M               0x000000fc
+#define BATU_BL_16M              0x000001fc
+#define BATU_BL_32M              0x000003fc
+#define BATU_BL_64M              0x000007fc
+#define BATU_BL_128M             0x00000ffc
+#define BATU_BL_256M             0x00001ffc
+
+#define BATU_VS                  0x00000002
+#define BATU_VP                  0x00000001
+
+#define BATL_BRPN_MSK            0xfffe0000
+#define BATL_WIMG_MSK            0x00000078
+#define BATL_WRITETHROUGH        0x00000008
+#define BATL_CACHEINHIBIT        0x00000010
+#define BATL_MEMCOHERENCE        0x00000020
+#define BATL_GUARDEDSTORAGE      0x00000040
+#define BATL_PP_MSK              0x00000003
+#define BATL_PP_00               0x00000000
+#define BATL_PP_01               0x00000001
+#define BATL_PP_10               0x00000002
+#define BATL_PP_11               0x00000003
+
+/* I'd attempt to do defines for the PP bits, but it's use is a bit too complex,
+ * see the PowerPC Operating Environment Architecture section in the PowerPc arch book.
+ * chapter 4
+ */
+
+/*eumb and epic config*/
+
+#define EPIC_FPR                  0x00041000
+#define EPIC_GCR                  0x00041020
+#define EPIC_EICR                 0x00041030
+#define EPIC_EVI                  0x00041080
+#define EPIC_PI                   0x00041090
+#define EPIC_SVR                  0x000410E0
+#define EPIC_TFRR                 0x000410F0
+
+/*note the information for these is rather mangled in the 8240 manual. these are guesses*/
+#define EPIC_GTCCR0               0x00041100
+#define EPIC_GTCCR1               0x00041140
+#define EPIC_GTCCR2               0x00041180
+#define EPIC_GTCCR3               0x000411C0
+#define EPIC_GTBCR0               0x00041110
+#define EPIC_GTBCR1               0x00041150
+#define EPIC_GTBCR2               0x00041190
+#define EPIC_GTBCR3               0x000411D0
+#define EPIC_GTVPR0               0x00041120
+#define EPIC_GTVPR1               0x00041160
+#define EPIC_GTVPR2               0x000411a0
+#define EPIC_GTVPR3               0x000411e0
+#define EPIC_GTDR0                0x00041130
+#define EPIC_GTDR1                0x00041170
+#define EPIC_GTDR2                0x000411b0
+#define EPIC_GTDR3                0x000411f0
+
+#define EPIC_IVPR0                0x00050200
+#define EPIC_IVPR1                0x00050220
+#define EPIC_IVPR2                0x00050240
+#define EPIC_IVPR3                0x00050260
+#define EPIC_IVPR4                0x00050280
+
+#define EPIC_SVPR0                0x00050200
+#define EPIC_SVPR1                0x00050220
+#define EPIC_SVPR2                0x00050240
+#define EPIC_SVPR3                0x00050260
+#define EPIC_SVPR4                0x00050280
+#define EPIC_SVPR5                0x000502A0
+#define EPIC_SVPR6                0x000502C0
+#define EPIC_SVPR7                0x000502E0
+#define EPIC_SVPR8                0x00050300
+#define EPIC_SVPR9                0x00050320
+#define EPIC_SVPRa                0x00050340
+#define EPIC_SVPRb                0x00050360
+#define EPIC_SVPRc                0x00050380
+#define EPIC_SVPRd                0x000503A0
+#define EPIC_SVPRe                0x000503C0
+#define EPIC_SVPRf                0x000503E0
+
+#endif /* __MPC8240_H__ */
index 1f0337644e663677fac025bf17c551e7d03c0794..3cf43bce1c665647aedbe91d1f7c5352521750f6 100644 (file)
 #ifndef        _PCMCIA_H
 #define _PCMCIA_H
 
+#include <ppcboot.h>
+#include <config.h>
+
+#ifdef CONFIG_IDE_PCMCIA
+/*
+ * Allow configuration to select PCMCIA slot,
+ * or try to generate a useful default
+ */
+#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
+
+                                       /* The RPX series use SLOT_B    */
+#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)
+# define CONFIG_PCMCIA_SLOT_B
+#elif defined(CONFIG_ADS)              /* The ADS  board use SLOT_A    */
+# define CONFIG_PCMCIA_SLOT_A
+#elif defined(CONFIG_FADS)             /* The FADS series are a mess   */
+# if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)
+#  define CONFIG_PCMCIA_SLOT_A
+# else
+#  define CONFIG_PCMCIA_SLOT_B
+# endif
+#elif defined(CONFIG_TQM860L) || defined(CONFIG_TQM855L) /* The TQM8xxL modules */
+# define       CONFIG_PCMCIA_SLOT_A    /* ... use SLOT_A on MPC860/855 */
+#elif defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L)
+# define       CONFIG_PCMCIA_SLOT_B    /* ... and SLOT_B else          */
+#elif defined(CONFIG_SPD823TS)         /* The SPD8xx use SLOT_B        */
+# define CONFIG_PCMCIA_SLOT_B
+#elif defined(CONFIG_IVMS8)            /* The IVMS8 use SLOT_A         */
+# define CONFIG_PCMCIA_SLOT_A
+#else
+# error "PCMCIA Slot not configured"
+#endif
+
+#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) */
+
+/* Make sure exactly one slot is defined - we support only one for now */
+#if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)
+#error Neither CONFIG_PCMCIA_SLOT_A nor CONFIG_PCMCIA_SLOT_B configured
+#endif
+#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)
+#error Both CONFIG_PCMCIA_SLOT_A and CONFIG_PCMCIA_SLOT_B configured
+#endif
+
+#define PCMCIA_SOCKETS_NO      1
+#define PCMCIA_MEM_WIN_NO      4
+#define PCMCIA_IO_WIN_NO       2
+
+/* define _slot_ to be able to optimize macros */
+#ifdef CONFIG_PCMCIA_SLOT_A
+# define _slot_                        0
+# define PCMCIA_SLOT_MSG       "SLOT_A"
+# define PCMCIA_SLOT_x         PCMCIA_PSLOT_A
+#else
+# define _slot_                        1
+# define PCMCIA_SLOT_MSG       "SLOT_B"
+# define PCMCIA_SLOT_x         PCMCIA_PSLOT_B
+#endif
+
+/*
+ * The TQM850L hardware has two pins swapped! Grrrrgh!
+ */
+#ifdef CONFIG_TQM850L
+#define __MY_PCMCIA_GCRX_CXRESET       PCMCIA_GCRX_CXOE
+#define __MY_PCMCIA_GCRX_CXOE          PCMCIA_GCRX_CXRESET
+#else
+#define __MY_PCMCIA_GCRX_CXRESET       PCMCIA_GCRX_CXRESET
+#define __MY_PCMCIA_GCRX_CXOE          PCMCIA_GCRX_CXOE
+#endif
+
+/* look up table for pgcrx registers */
+
+#if 0
+static u_int *pcmcia_pgcrx[2] = {
+       &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra,
+       &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb,
+};
+
+#define PCMCIA_PGCRX(slot)     (*pcmcia_pgcrx[slot])
+#endif
+
+/*
+ * This structure is used to address each window in the PCMCIA controller.
+ *
+ * Keep in mind that we assume that pcmcia_win_t[n+1] is mapped directly
+ * after pcmcia_win_t[n]...
+ */
+
+typedef struct {
+       ulong   br;
+       ulong   or;
+} pcmcia_win_t;
+
+#endif /* CONFIG_IDE_PCMCIA */
+
 /*
  * Definitions for PCMCIA control registers to operate in IDE mode
  *
  */
 
 /* Window 0:
- *     Base: 0x04100000        CS1
+ *     Base: 0xFE100000        CS1
  *     Port Size:     2 Bytes
  *     Port Size:    16 Bit
  *     Common Memory Space
 #define CFG_PCMCIA_POR0            (   PCMCIA_BSIZE_2  \
                            |   PCMCIA_PPS_16   \
                            |   PCMCIA_PRS_MEM  \
-                           |   PCMCIA_PSLOT_B  \
+                           |   PCMCIA_SLOT_x   \
                            |   PCMCIA_PV       \
                            )
 
 /* Window 1:
- *     Base: 0x04100080        CS1
+ *     Base: 0xFE100080        CS1
  *     Port Size:     8 Bytes
  *     Port Size:     8 Bit
  *     Common Memory Space
 #define CFG_PCMCIA_POR1            (   PCMCIA_BSIZE_8  \
                            |   PCMCIA_PPS_8    \
                            |   PCMCIA_PRS_MEM  \
-                           |   PCMCIA_PSLOT_B  \
+                           |   PCMCIA_SLOT_x   \
                            |   PCMCIA_PV       \
                            )
 
 /* Window 2:
- *     Base: 0x04100100        CS2
+ *     Base: 0xFE100100        CS2
  *     Port Size:     8 Bytes
  *     Port Size:     8 Bit
  *     Common Memory Space
 #define CFG_PCMCIA_POR2            (   PCMCIA_BSIZE_8  \
                            |   PCMCIA_PPS_8    \
                            |   PCMCIA_PRS_MEM  \
-                           |   PCMCIA_PSLOT_B  \
+                           |   PCMCIA_SLOT_x   \
                            |   PCMCIA_PV       \
                            )
 
 #define        CFG_PCMCIA_POR3         0
 
 /* Window 4:
- *     Base: 0x041000C00       CS1
+ *     Base: 0xFE100C00        CS1
  *     Port Size:     2 Bytes
  *     Port Size:    16 Bit
  *     Common Memory Space
 #define CFG_PCMCIA_POR4            (   PCMCIA_BSIZE_2  \
                            |   PCMCIA_PPS_16   \
                            |   PCMCIA_PRS_MEM  \
-                           |   PCMCIA_PSLOT_B  \
+                           |   PCMCIA_SLOT_x   \
                            |   PCMCIA_PV       \
                            )
 
 /* Window 5:
- *     Base: 0x04100C80        CS1
+ *     Base: 0xFE100C80        CS1
  *     Port Size:     8 Bytes
  *     Port Size:     8 Bit
  *     Common Memory Space
 #define CFG_PCMCIA_POR5            (   PCMCIA_BSIZE_8  \
                            |   PCMCIA_PPS_8    \
                            |   PCMCIA_PRS_MEM  \
-                           |   PCMCIA_PSLOT_B  \
+                           |   PCMCIA_SLOT_x   \
                            |   PCMCIA_PV       \
                            )
 
 /* Window 6:
- *     Base: 0x04100D00        CS2
+ *     Base: 0xFE100D00        CS2
  *     Port Size:     8 Bytes
  *     Port Size:     8 Bit
  *     Common Memory Space
 #define CFG_PCMCIA_POR6            (   PCMCIA_BSIZE_8  \
                            |   PCMCIA_PPS_8    \
                            |   PCMCIA_PRS_MEM  \
-                           |   PCMCIA_PSLOT_B  \
+                           |   PCMCIA_SLOT_x   \
                            |   PCMCIA_PV       \
                            )
 
index d83ec19b591885d59644515e810b4a0da172a714..63000b1ea960bdc3b4aacfede4ef37b453d4f5b3 100644 (file)
@@ -96,7 +96,7 @@
 #define        r31     31
 
 
-#if defined(CONFIG_8xx)
+#if defined(CONFIG_8xx) || defined(CONFIG_MPC8240)
 
 /* Some special registers */
 
 #define LCTRL2 157     /* Load/Store Support       (37-41) */
 #define ICTRL  158
 
+#endif /* CONFIG_8xx, CONFIG_MPC8240 */
+
+#if defined(CONFIG_8xx)
 
 /* Registers in the processor's internal memory map that we use.
 */
diff --git a/include/status_led.h b/include/status_led.h
new file mode 100644 (file)
index 0000000..8c97cb6
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * The purpose of this code is to signal the operational status of a
+ * target which usually boots over the network; while running in
+ * PCBoot, a status LED is blinking. As soon as a valid BOOTP reply
+ * message has been received, the LED is turned off. The Linux
+ * kernel, once it is running, will start blinking the LED again,
+ * with another frequency.
+ */
+
+#ifndef _STATUS_LED_H_
+#define        _STATUS_LED_H_
+
+#ifdef CONFIG_STATUS_LED
+
+
+#if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) || \
+    defined(CONFIG_TQM855L) || defined(CONFIG_TQM860L)
+
+# define STATUS_LED_PAR                im_cpm.cp_pbpar
+# define STATUS_LED_DIR                im_cpm.cp_pbdir
+# define STATUS_LED_ODR                im_cpm.cp_pbodr
+# define STATUS_LED_DAT                im_cpm.cp_pbdat
+
+# define STATUS_LED_BIT                0x00000001
+
+# define STATUS_LED_PERIOD     500
+
+#elif defined(CONFIG_ETX094)
+
+# define STATUS_LED_PAR                im_ioport.iop_pdpar
+# define STATUS_LED_DIR                im_ioport.iop_pddir
+# undef  STATUS_LED_ODR
+# define STATUS_LED_DAT                im_ioport.iop_pddat
+
+# define STATUS_LED_BIT                0x00000001
+
+# define STATUS_LED_PERIOD     500
+
+#else
+# error Status LED configuration missing
+#endif
+
+#define        STATUS_LED_OFF          0
+#define STATUS_LED_BLINKING    1
+#define STATUS_LED_ON          2
+
+void status_led_tick (unsigned long timestamp);
+void status_led_set  (int state);
+
+
+#endif /* CONFIG_STATUS_LED */
+#endif /* _STATUS_LED_H_ */
index 04f242db8598d0cdaf12a8c41171a17bddd0fa9a..4e77c6e5094cdb682b8b028d6fbfd4d70f835df6 100644 (file)
@@ -174,11 +174,13 @@ initdram (int board_type)
     memctl->memc_br2 = CFG_BR2;
 #endif
 
+#if 0
     /*
      * Map controller bank 4 to the PER8 bank.
      */
     memctl->memc_or4 = CFG_OR4;
     memctl->memc_br4 = CFG_BR4;
+#endif
 
 #if 0
     /* Configure SHARC at UMA */
diff --git a/mpc8240/Makefile b/mpc8240/Makefile
new file mode 100644 (file)
index 0000000..0bb8a01
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = lib$(CPU).a
+
+START  = start.S
+OBJS   = traps.o cpu.o cpu_init.o interrupts.o \
+          drivers/epic/epic1.o 
+
+all:   .depend $(START) $(LIB)
+
+$(LIB):        $(OBJS) 
+       $(AR) crv $@ $(OBJS) 
+
+#########################################################################
+
+.depend:       Makefile $(START:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(START:.o=.S)  $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/mpc8240/config.mk b/mpc8240/config.mk
new file mode 100644 (file)
index 0000000..05222ea
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+PLATFORM_RELFLAGS += -ffixed-r14
+
+PLATFORM_CPPFLAGS += -DCONFIG_MPC8240 -ffixed-r2 -mstring -mcpu=603e -msoft-float
diff --git a/mpc8240/cpu.c b/mpc8240/cpu.c
new file mode 100644 (file)
index 0000000..85acc65
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <mpc8240.h>
+#include <ppcboot.h>
+#include <command.h>
+
+int checkcpu(long clock)
+{
+  unsigned int pvr = get_pvr();
+  unsigned int version = pvr >>16;
+  unsigned int revision = pvr &0xffff;
+
+  switch(version)
+  {
+    case 0x0081:
+      printf("MPC8240");
+      break;
+    default:
+      return -1; /*not valid for this source*/
+  }
+
+  switch(revision)
+  {
+    default: /*currently no info on revision numbers*/
+      printf(" Revsion %d.%d",revision>>8, revision & 0xff);
+  }
+
+  printf(" at %lu MHz:", clock);
+
+  printf(" %u kB I-Cache", checkicache() >> 10);
+  printf(" %u kB D-Cache", checkdcache() >> 10);
+  return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* L1 i-cache                                                                */
+
+int checkicache(void)
+{
+    /*TODO*/
+  return 128*4*32;
+};
+/* ------------------------------------------------------------------------- */
+/* L1 d-cache                                                                */
+
+int checkdcache(void)
+{
+    /*TODO*/
+  return 128*4*32;
+
+};
+
+/*------------------------------------------------------------------- */
+
+void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+    ulong msr, addr;
+
+
+    /* Interrupts and MMU off */
+    __asm__ ("mtspr    81, 0
+          mfmsr    %0": "=r"(msr) : );
+    msr &= ~0x1030;
+    __asm__ ("mtmsr    %0"::"r"(msr) );
+
+    /* jump to reset vector*/
+    addr = 0xfff0100;
+    ((void (*)(void ))addr)();
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Get timebase clock frequency (like cpu_clk in Hz)
+ *
+ */
+unsigned long get_tbclk (void)
+{
+       ulong tbclk;
+       /* Pointer to initial global data area */
+       init_data_t *idata =
+               (init_data_t *)(CFG_INIT_RAM_ADDR+CFG_INIT_DATA_OFFSET);
+
+       tbclk = (idata->cpu_clk + 3L) / 4L;
+
+       return (tbclk);
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/mpc8240/cpu_init.c b/mpc8240/cpu_init.c
new file mode 100644 (file)
index 0000000..7aae577
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor. Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <asm/processor.h>
+#include <mpc8240.h>
+
+/*
+ * Breath some life into the CPU...
+ *
+ * Set up the memory map,
+ * initialize a bunch of registers,
+ */
+void
+cpu_init_f (void)
+{
+    register unsigned long val;
+    CONFIG_WRITE_WORD( PCICR, 0x06); /* Bus Master, respond to PCI memory space acesses*/
+/*    CONFIG_WRITE_HALFWORD(PCISR, 0xffff); *//*reset PCISR*/
+
+    CONFIG_READ_WORD(PICR1, val);
+    CONFIG_WRITE_WORD( PICR1,
+       (val & (PICR1_ADDRESS_NAP | PICR1_RCS0)) |
+               PIRC1_MSK | PICR1_PROC_TYPE_603E |
+               PICR1_FLASH_WR_EN | PICR1_MCP_EN |
+               PICR1_CF_DPARK | PICR1_EN_PCS |
+               PICR1_CF_APARK );
+    CONFIG_READ_WORD(PICR2, val);
+    val= val & ~ (PICR2_CF_SNOOP_WS_MASK | PICR2_CF_APHASE_WS_MASK); /*mask off waitstate bits*/
+    CONFIG_WRITE_WORD(PICR2, val | PICR2_CF_SNOOP_WS_1WS | PICR2_CF_APHASE_WS_1WS); /*1 wait state*/
+    CONFIG_WRITE_WORD(EUMBBAR, CFG_EUMB_ADDR);
+#ifndef DEBUG
+    CONFIG_WRITE_WORD(MCCR1, (CFG_ROMNAL << MCCR1_ROMNAL_SHIFT) |
+                             (CFG_ROMFAL << MCCR1_ROMFAL_SHIFT));
+
+    CONFIG_WRITE_WORD(MCCR2, CFG_REFINT << MCCR2_REFINT_SHIFT);
+
+    CONFIG_WRITE_WORD(MCCR3,
+        (((CFG_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) |
+        (CFG_REFREC << MCCR3_REFREC_SHIFT) |
+        (CFG_RDLAT  << MCCR3_RDLAT_SHIFT));
+
+    CONFIG_WRITE_WORD(MCCR4,
+        (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) |
+        (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) |
+        MCCR4_BIT21 |
+        (CFG_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) |
+        ((CFG_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) |
+        ((CFG_SDMODE_CAS_LAT <<4) | (CFG_SDMODE_WRAP <<3) | (CFG_SDMODE_BURSTLEN) <<MCCR4_SDMODE_SHIFT) |
+        ((CFG_BSTOPRE & 0x03c0) <<MCCR4_BSTOPRE6TO9_SHIFT ));
+
+    CONFIG_WRITE_WORD(MSAR1,
+        ( CFG_BANK0_START & MICR_ADDR_MASK) |
+        ((CFG_BANK1_START & MICR_ADDR_MASK) << 8) |
+        ((CFG_BANK2_START & MICR_ADDR_MASK) << 16) |
+        ((CFG_BANK3_START & MICR_ADDR_MASK) << 24));
+    CONFIG_WRITE_WORD(EMSAR1,
+        ( CFG_BANK0_START & MICR_EADDR_MASK) |
+        ((CFG_BANK1_START & MICR_EADDR_MASK) << 8) |
+        ((CFG_BANK2_START & MICR_EADDR_MASK) << 16) |
+        ((CFG_BANK3_START & MICR_EADDR_MASK) << 24));
+    CONFIG_WRITE_WORD(MSAR2,
+        ( CFG_BANK4_START & MICR_ADDR_MASK) |
+        ((CFG_BANK5_START & MICR_ADDR_MASK) << 8) |
+        ((CFG_BANK6_START & MICR_ADDR_MASK) << 16) |
+        ((CFG_BANK7_START & MICR_ADDR_MASK) << 24));
+    CONFIG_WRITE_WORD(EMSAR2,
+        ( CFG_BANK4_START & MICR_EADDR_MASK) |
+        ((CFG_BANK5_START & MICR_EADDR_MASK) << 8) |
+        ((CFG_BANK6_START & MICR_EADDR_MASK) << 16) |
+        ((CFG_BANK7_START & MICR_EADDR_MASK) << 24));
+    CONFIG_WRITE_WORD(MEAR1,
+        ( CFG_BANK0_END & MICR_ADDR_MASK) |
+        ((CFG_BANK1_END & MICR_ADDR_MASK) << 8) |
+        ((CFG_BANK2_END & MICR_ADDR_MASK) << 16) |
+        ((CFG_BANK3_END & MICR_ADDR_MASK) << 24));
+    CONFIG_WRITE_WORD(EMEAR1,
+        ( CFG_BANK0_END & MICR_EADDR_MASK) |
+        ((CFG_BANK1_END & MICR_EADDR_MASK) << 8) |
+        ((CFG_BANK2_END & MICR_EADDR_MASK) << 16) |
+        ((CFG_BANK3_END & MICR_EADDR_MASK) << 24));
+    CONFIG_WRITE_WORD(MEAR2,
+        ( CFG_BANK4_END & MICR_ADDR_MASK) |
+        ((CFG_BANK5_END & MICR_ADDR_MASK) << 8) |
+        ((CFG_BANK6_END & MICR_ADDR_MASK) << 16) |
+        ((CFG_BANK7_END & MICR_ADDR_MASK) << 24));
+    CONFIG_WRITE_WORD(EMEAR2,
+        ( CFG_BANK4_END & MICR_EADDR_MASK) |
+        ((CFG_BANK5_END & MICR_EADDR_MASK) << 8) |
+        ((CFG_BANK6_END & MICR_EADDR_MASK) << 16) |
+        ((CFG_BANK7_END & MICR_EADDR_MASK) << 24));
+
+    CONFIG_WRITE_BYTE(ODCR, CFG_ODCR);
+    CONFIG_WRITE_BYTE(MBER,
+         CFG_BANK0_ENABLE |
+        (CFG_BANK1_ENABLE << 1) |
+        (CFG_BANK2_ENABLE << 2) |
+        (CFG_BANK3_ENABLE << 3) |
+        (CFG_BANK4_ENABLE << 4) |
+        (CFG_BANK5_ENABLE << 5) |
+        (CFG_BANK6_ENABLE << 6) |
+        (CFG_BANK7_ENABLE << 7));
+
+    //! Wait 200us before initialize other registers
+    /*FIXME: write a decent udelay wait */
+    __asm__ __volatile__(
+      " mtctr   %0 \n \
+       0: bdnz   0b\n"
+      :
+      : "r" (0x10000));
+
+   CONFIG_READ_WORD(MCCR1, val);
+   CONFIG_WRITE_WORD(MCCR1, val | MCCR1_MEMGO); //set memory access going
+   __asm__ __volatile__("eieio");
+#endif
+
+   /*map BAT areas - I think this should go somewhere else,
+    *but it'll be fine here for now
+    */
+    mtspr (IBAT0L, CFG_IBAT0L);
+    mtspr (IBAT0U, CFG_IBAT0U);
+    mtspr (IBAT1L, CFG_IBAT1L);
+    mtspr (IBAT1U, CFG_IBAT1U);
+    mtspr (IBAT2L, CFG_IBAT2L);
+    mtspr (IBAT2U, CFG_IBAT2U);
+    mtspr (IBAT3L, CFG_IBAT3L);
+    mtspr (IBAT3U, CFG_IBAT3U);
+    mtspr (DBAT0L, CFG_DBAT0L);
+    mtspr (DBAT0U, CFG_DBAT0U);
+    mtspr (DBAT1L, CFG_DBAT1L);
+    mtspr (DBAT1U, CFG_DBAT1U);
+    mtspr (DBAT2L, CFG_DBAT2L);
+    mtspr (DBAT2U, CFG_DBAT2U);
+    mtspr (DBAT3L, CFG_DBAT3L);
+    mtspr (DBAT3U, CFG_DBAT3U);
+
+   /*initialise TLB
+    */
+    for (val = 0; val < 0x20000; val+=0x1000)
+      tlbie(val);
+
+}
+
+/*
+ * initialize higher level parts of CPU like time base and timers
+ */
+void
+cpu_init_r  (bd_t *bd)
+{
+
+}
diff --git a/mpc8240/drivers/dma/Makefile b/mpc8240/drivers/dma/Makefile
new file mode 100644 (file)
index 0000000..ae2df2f
--- /dev/null
@@ -0,0 +1,131 @@
+##########################################################################
+#
+# $Id: Makefile,v 1.1 2000/11/20 17:22:32 wdenk Exp $
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and 
+#       distribute the SOFTWARE so long as this entire notice is retained 
+#       without alteration in any modified and/or redistributed versions, 
+#       and that such modified versions are clearly identified as such.  
+#       No licenses are granted by implication, estoppel or otherwise under 
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.  
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS 
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED 
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH 
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS 
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. 
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL 
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF 
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS 
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR 
+#       INABILITY TO USE THE SOFTWARE. 
+#
+# $Log: Makefile,v $
+# Revision 1.1  2000/11/20 17:22:32  wdenk
+#
+# * Added support for MBX860T (thanks to Rob Taylor)
+#
+# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+#   Work In Progress (TM); current status: boots to command line input.
+#   EPIC code non-functional (interrupts disabled), No net, No IDE.
+#
+# * Add support for Status LED
+#
+# * Optionally panic() to reboot instead of hanging
+#
+# * Misc bug fixes
+#
+# * All frequencies in HZ now (internally)
+#
+# * Add support for BOOTP Domain Name Server Option
+#
+# Revision 1.1.1.1  2000/11/14 16:54:07  robt
+# no message
+#
+# Revision 1.1.1.1  2000/11/14 14:49:39  robt
+# no message
+#
+# Revision 1.4  1999/05/28 21:23:18  charliem
+# First pass at cleaning up DMA interface.  This version is verified with
+# transfers from and to local memory (M2M).
+#
+# Revision 1.3  1999/02/13 02:21:02  wyin
+# Added DMAStatus enum type for better information exchange.
+#
+# Revision 1.2  1999/02/05 01:54:51  wyin
+# modified to set up soft line for hearder files
+#
+# Revision 1.1  1999/02/03 18:56:13  wyin
+# Base line
+#
+# Revision 1.12  1998/11/20 01:34:55  wyin
+# Added INTMEM function and data structure.
+# Enabled DCACHE.
+# There is a minor problem with DCACHE, the cache policy had to be write-through.
+# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length.
+# But consequence measurement is fine.
+#
+#
+############################################################################
+TARGET = libdma.a
+
+DEBUG   = -DDMADBG
+LST     = -Hanno -S
+OPTIM   = 
+CC      = /risc/tools/pkgs/metaware/bin/hcppc 
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc 
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG = -l -fm
+AS      = /risc/tools/pkgs/metaware/bin/asppc
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -q -r -Qn
+LKCMD   =
+LINK    =  /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = dma1.o dma2.o
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+objects: dma1.o
+
+clean: 
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+     
+.s.o:  
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:  
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+dma1.o: dma_export.h dma.h dma1.c
+
+dma2.o: dma.h dma2.s
diff --git a/mpc8240/drivers/dma/Makefile_pc b/mpc8240/drivers/dma/Makefile_pc
new file mode 100644 (file)
index 0000000..8d8c9b9
--- /dev/null
@@ -0,0 +1,138 @@
+##########################################################################
+#
+#   makefile_pc  for use with mksnt tools   drivers/dma
+#  $Id: Makefile_pc,v 1.1 2000/11/20 17:22:32 wdenk Exp $
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and 
+#       distribute the SOFTWARE so long as this entire notice is retained 
+#       without alteration in any modified and/or redistributed versions, 
+#       and that such modified versions are clearly identified as such.  
+#       No licenses are granted by implication, estoppel or otherwise under 
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.  
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS 
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED 
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH 
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS 
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. 
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL 
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF 
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS 
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR 
+#       INABILITY TO USE THE SOFTWARE. 
+#
+# $Log: Makefile_pc,v $
+# Revision 1.1  2000/11/20 17:22:32  wdenk
+#
+# * Added support for MBX860T (thanks to Rob Taylor)
+#
+# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+#   Work In Progress (TM); current status: boots to command line input.
+#   EPIC code non-functional (interrupts disabled), No net, No IDE.
+#
+# * Add support for Status LED
+#
+# * Optionally panic() to reboot instead of hanging
+#
+# * Misc bug fixes
+#
+# * All frequencies in HZ now (internally)
+#
+# * Add support for BOOTP Domain Name Server Option
+#
+# Revision 1.1.1.1  2000/11/14 16:54:07  robt
+# no message
+#
+# Revision 1.1.1.1  2000/11/14 14:49:39  robt
+# no message
+#
+# Revision 1.1  1999/06/11 20:04:36  maurie
+# support for compiling dink on PC
+#
+# Revision 1.4  1999/05/28 21:23:18  charliem
+# First pass at cleaning up DMA interface.  This version is verified with
+# transfers from and to local memory (M2M).
+#
+# Revision 1.3  1999/02/13 02:21:02  wyin
+# Added DMAStatus enum type for better information exchange.
+#
+# Revision 1.2  1999/02/05 01:54:51  wyin
+# modified to set up soft line for hearder files
+#
+# Revision 1.1  1999/02/03 18:56:13  wyin
+# Base line
+#
+# Revision 1.12  1998/11/20 01:34:55  wyin
+# Added INTMEM function and data structure.
+# Enabled DCACHE.
+# There is a minor problem with DCACHE, the cache policy had to be write-through.
+# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length.
+# But consequence measurement is fine.
+#
+#
+############################################################################
+TARGET = libdma.a
+
+DEBUG   = -DDMADBG
+LST     = -Hanno -S
+OPTIM   = 
+CC      = m:/old_tools/tools/hcppc/bin/hcppc 
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc 
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG = -l -fm
+AS      = m:/old_tools/tools/hcppc/bin/asppc 
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -q -r -Qn
+LKCMD   =
+LINK    = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = dma1.o dma2.o
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+objects: dma1.o
+
+clean: 
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+     
+.s.o:  
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:  
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+dma1.o: dma_export.h dma.h dma1.c
+       $(CCobj) $<
+
+dma2.o: dma.h dma2.s
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
diff --git a/mpc8240/drivers/dma/README b/mpc8240/drivers/dma/README
new file mode 100644 (file)
index 0000000..db7acb8
--- /dev/null
@@ -0,0 +1,102 @@
+CONTENT:
+
+   dma.h
+   dma1.c
+   dma2.s
+
+WHAT ARE THESE FILES:
+
+These files contain MPC8240 (Kahlua) DMA controller
+driver routines. The driver routines are not 
+written for any specific operating system. 
+They serves the purpose of code sample, and 
+jump-start for using the MPC8240 DMA controller.
+
+For the reason of correctness of C language
+syntax, these files are compiled by Metaware
+C compiler and assembler.
+
+ENDIAN NOTATION:
+
+The algorithm is designed for big-endian mode,
+software is responsible for byte swapping.
+
+USAGE:
+
+1. The host system that is running on MPC8240 
+   or using MPC8240 as I/O device shall link
+   the files listed here. The memory location 
+   of driver routines shall take into account of 
+   that driver routines need to run in supervisor 
+   mode and they process DMA controller interrupt.
+
+2. The host system is responsible for configuring
+   the MPC8240 including Embedded Utilities Memory 
+   Block. Since the DMA controller on MPC8240 can 
+   be accessed by either local 603e core or the host 
+   that MPC8240 serves as I/O processor through host 
+   PCI configuration, it is important that the local
+   processor uses EUMBBAR to access its local DMA 
+   controller while the PCI master uses I/O 
+   processor's PCSRBAR to access the DMA controller 
+   on I/O device.
+
+   To qualify whether is EUMBBAR or PCSRBAR, one
+   additional parameter is requied from the host
+   system, LOCAL or REMOTE so that the base value 
+   can be correctly interpreted.
+
+3. If the host system is also using the EPIC unit
+   on MPC8240, the system can register the
+   DMA_ISR with the EPIC including other
+   desired resources.  
+
+   If the host system does not using the EPIC unit
+   on MPC8240, DMA_ISR function can be called for 
+   each desired time interval.
+
+   In both cases, the host system is free to 
+   provide its own interrupt service routine.
+  
+4. To start a direct mode DMA transaction,
+   use DMA_Bld_Curr with the start parameter 
+   set to 1.
+
+   To start a chaining mode DMA transaction,
+   the application shall build descriptors
+   in memory first, next, use DMA_Bld_Desp
+   with the start parameter set to 1.
+
+5. DMA_Start function clears, then sets the CS 
+   bit of DMA mode register.
+
+   DMA_Halt function clears the CS bit of DMA 
+   mode register.
+
+   These functions can be used to start and
+   halt the DMA transaction.
+
+   If the chaining descriptors has been
+   modified since the last time a DMA 
+   transaction started, use DMA_Chn_Cnt
+   function to let DMA controller process
+   the modified descriptor chain without 
+   stopping or disturbing the current DMA 
+   transaction.
+
+   It is the host system's responsibility of
+   setting up the correct DMA transfer mode 
+   and pass the correct memory address parameters.
+
+6. It is the host system's responsibility of
+   queueing the DMA I/O request. The host 
+   system can call the DMA_ISR with its own
+   desired interrupt service subroutines to 
+   handle each individual interrupt and queued
+   DMA I/O requests.
+   
+7. The DMA driver routines contains a set 
+   of utilities, Set and Get, for host system
+   to query and modify the desired DMA registers.
+
+   
diff --git a/mpc8240/drivers/dma/dma.h b/mpc8240/drivers/dma/dma.h
new file mode 100644 (file)
index 0000000..23f644c
--- /dev/null
@@ -0,0 +1,327 @@
+#ifndef DMA_H
+#define DMA_H
+/*******************************************************
+ * $Id: dma.h,v 1.1 2000/11/20 17:22:32 wdenk Exp $
+ *
+ * copyright @ Motorola 1999
+ *
+ *******************************************************/
+#define NUM_DMA_REG   7
+#define DMA_MR_REG    0
+#define DMA_SR_REG    1
+#define DMA_CDAR_REG  2
+#define DMA_SAR_REG   3
+#define DMA_DAR_REG   4
+#define DMA_BCR_REG   5
+#define DMA_NDAR_REG  6
+
+typedef enum _dmastatus
+{
+       DMASUCCESS = 0x1000,
+       DMALMERROR,
+       DMAPERROR,
+       DMACHNBUSY,
+       DMAEOSINT,
+       DMAEOCAINT,
+       DMAINVALID,
+       DMANOEVENT,
+} DMAStatus;
+
+typedef enum _location
+{
+       LOCAL = 0,     /* local processor accesses on board DMA,
+                                 local processor's eumbbar is required */
+       REMOTE = 1,    /* PCI master accesses DMA on I/O board,
+                                 I/O processor's pcsrbar is required */
+} LOCATION;
+
+typedef enum dma_mr_bit
+{
+       IRQS    = 0x00080000,
+    PDE     = 0x00040000,
+       DAHTS   = 0x00030000,
+       SAHTS   = 0x0000c000,
+       DAHE    = 0x00002000,
+       SAHE    = 0x00001000,
+       PRC     = 0x00000c00,
+       EIE     = 0x00000080,
+       EOTIE   = 0x00000040,
+       DL      = 0x00000008,
+       CTM     = 0x00000004,
+       CC      = 0x00000002,
+       CS      = 0x00000001,
+} DMA_MR_BIT;
+
+typedef enum dma_sr_bit
+{
+       LME     = 0x00000080,
+       PE      = 0x00000010,
+       CB      = 0x00000004,
+       EOSI    = 0x00000002,
+       EOCAI   = 0x00000001,
+} DMA_SR_BIT;
+
+/* structure for DMA Mode Register */
+typedef struct _dma_mr
+{
+       unsigned int  reserved0 : 12;
+       unsigned int  irqs      : 1;
+       unsigned int  pde       : 1;
+       unsigned int  dahts     : 2;
+    unsigned int  sahts     : 2;
+       unsigned int  dahe      : 1;
+       unsigned int  sahe      : 1;
+       unsigned int  prc       : 2;
+       unsigned int  reserved1 : 1;
+       unsigned int  eie       : 1;
+       unsigned int  eotie     : 1;
+       unsigned int  reserved2 : 3;
+       unsigned int  dl        : 1;
+       unsigned int  ctm       : 1;
+       /* if chaining mode is enabled, any time, user can modify the
+        * descriptor and does not need to halt the current DMA transaction.
+        * Set CC bit, enable DMA to process the modified descriptors 
+        * Hardware will clear this bit each time, DMA starts.
+        */
+       unsigned int  cc        : 1;
+       /* cs bit has dua role, halt the current DMA transaction and
+        * (re)start DMA transaction. In chaining mode, if the descriptor
+        * needs modification, cs bit shall be used not the cc bit.
+        * Hardware will not set/clear this bit each time DMA transaction 
+        * stops or starts. Software shall do it.
+        *
+        * cs bit shall not be used to halt chaining DMA transaction for
+        * modifying the descriptor. That is the role of CC bit.
+        */
+       unsigned int  cs        : 1;
+} DMA_MR;
+
+/* structure for DMA Status register */
+typedef struct _dma_sr
+{
+       unsigned int  reserved0 : 24;
+       unsigned int  lme       : 1;
+       unsigned int  reserved1 : 2;
+       unsigned int  pe        : 1;
+       unsigned int  reserved2 : 1;
+       unsigned int  cb        : 1;
+       unsigned int  eosi      : 1;
+       unsigned int  eocai     : 1;
+} DMA_SR;
+
+/* structure for DMA current descriptor address register */
+typedef struct _dma_cdar
+{
+       unsigned int  cda    : 27;
+       unsigned int snen    : 1;
+       unsigned int eosie   : 1;
+       unsigned int ctt     : 2;
+       unsigned int eotd    : 1;
+} DMA_CDAR;
+
+/* structure for DMA byte count register */
+typedef struct _dma_bcr
+{
+       unsigned int reserved : 6;
+       unsigned int  bcr      : 26;
+} DMA_BCR;
+
+/* structure for DMA Next Descriptor Address register */
+typedef struct _dma_ndar
+{
+       unsigned int nda    : 27;
+       unsigned int ndsnen : 1;
+       unsigned int ndeosie: 1;
+       unsigned int ndctt  : 2;
+       unsigned int eotd   : 1;
+} DMA_NDAR;
+
+/* structure for DMA current transaction info */
+typedef struct _dma_curr
+{
+       unsigned int src_addr;
+       unsigned int dest_addr;
+       unsigned int byte_cnt;
+} DMA_CURR;
+
+/************************* Kernel API********************
+ * Kernel APIs are used to interface with O.S. kernel. 
+ * They are the functions required by O.S. kernel to 
+ * provide I/O service.
+ ********************************************************/
+
+/**************DMA Device Control Functions ********/
+
+/**
+ * Note:
+ *
+ * In all following functions, the host (KAHLUA) processor has a
+ * choice of accessing on board local DMA (LOCAL),
+ * or DMA on a distributed KAHLUA (REMOTE). In either case,
+ * the caller shall pass the configured embedded utility memory
+ * block base address relative to the DMA. If LOCAL DMA is used,
+ * this parameter shall be EUMBBAR, if REMOTE is used, the
+ * parameter shall be the corresponding PCSRBAR.
+ **/
+
+/**************************************************************
+ * function: DMA_Get_Stat
+ *
+ * description: return the content of status register of 
+ *              the given DMA channel
+ *              if error, return DMAINVALID. Otherwise return
+ *              DMASUCCESS.
+ *
+ **************************************************************/
+static DMAStatus DMA_Get_Stat( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_SR * );
+
+/**************************************************************
+ * function: DMA_Get_Mode
+ *
+ * description: return the content of mode register of the 
+ *              given DMA channel
+ *              if error, return DMAINVALID. Otherwise return DMASUCCESS.
+ *
+ **************************************************************/
+static DMAStatus DMA_Get_Mode( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_MR * );
+
+/**************************************************************
+ * function: DMA_Set_Mode
+ *
+ * description: Set a new mode to a given DMA channel 
+ *              return DMASUCCESS if success, otherwise return DMACHNINVALID
+ *
+ * note: It is not a good idea of changing the DMA mode during
+ *       the middle of a transaction.
+ **************************************************************/
+static DMAStatus DMA_Set_Mode( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_MR mode );
+
+/*************************************************************
+ * function: DMA_ISR
+ *
+ * description: DMA interrupt service routine
+ *              return DMAStatus based on the status
+ *
+ *************************************************************/
+static DMAStatus    DMA_ISR( unsigned int eumbbar,
+                                                        unsigned int channel,
+                                                    DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ),
+                                                DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ),
+                                                DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ),
+                                                DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus ));
+
+static DMAStatus dma_error_func( unsigned int, unsigned int, DMAStatus );
+
+/********************* DMA I/O function ********************/
+
+/************************************************************
+ * function: DMA_Start
+ * 
+ * description: start a given DMA channel transaction
+ *              return DMASUCCESS if success, otherwise return DMACHNINVALID
+ *
+ * note: this function will clear DMA_MR(CC) first, then
+ *       set DMA_MR(CC).
+ ***********************************************************/
+static DMAStatus DMA_Start( LOCATION, unsigned int eumbbar,unsigned int channel );
+
+/***********************************************************
+ * function: DMA_Halt
+ *
+ * description: halt the current dma transaction on the specified
+ *              channel.
+ *              return DMASUCCESS if success, otherwise return DMACHNINVALID
+ *
+ * note: if the specified DMA channel is idle, nothing happens
+ *************************************************************/
+static DMAStatus DMA_Halt( LOCATION, unsigned int eumbbar,unsigned int channel );
+
+/*************************************************************
+ * function: DMA_Chn_Cnt
+ *
+ * description: set the DMA_MR(CC) bit for a given channel
+ *              that is in chaining mode. 
+ *              return DMASUCCESS if successfule, otherwise return DMACHNINVALID
+ *
+ * note: if the given channel is not in chaining mode, nothing
+ *       happen.
+ *
+ *************************************************************/
+static DMAStatus DMA_Chn_Cnt( LOCATION, unsigned int eumbbar,unsigned int channel );
+
+/*********************** App. API ***************************
+ * App. API are the APIs Kernel provides for the application
+ * level program 
+ ************************************************************/
+/**************************************************************
+ * function: DMA_Bld_Curr
+ *
+ * description: set current src, dest, byte count registers
+ *              according to the desp for a given channel
+ *
+ *              if the given channel is busy,  no change made,
+ *              return DMACHNBUSY.
+ *
+ *              otherwise return DMASUCCESS.
+ *
+ * note:
+ **************************************************************/
+static DMAStatus DMA_Bld_Curr( LOCATION,
+                                                                 unsigned int eumbbar,
+                                                                 unsigned int channel,
+                                                             DMA_CURR     desp );
+
+/**************************************************************
+ * function: DMA_Poke_Curr
+ *
+ * description: poke the current src, dest, byte count registers
+ *              for a given channel.
+ *
+ *              return DMASUCCESS if no error otherwise return DMACHNERROR
+ *
+ * note:        Due to the undeterministic parallelism, in chaining
+ *              mode, the value returned by this function shall
+ *              be taken as reference when the query is made rather
+ *              than the absolute snapshot when the value is returned.
+ **************************************************************/
+static DMAStatus DMA_Poke_Curr( LOCATION,
+                                                          unsigned int eumbbar,
+                                                          unsigned int channel,
+                                                      DMA_CURR*    desp );
+
+/**************************************************************
+ * function: DMA_Bld_Desp
+ *
+ * description: set current descriptor address register
+ *              according to the desp for a given channel
+ *
+ *              if the given channel is busy return DMACHNBUSY
+ *              and no change made, otherwise return DMASUCCESS.
+ *
+ * note:
+ **************************************************************/
+static DMAStatus DMA_Bld_Desp( LOCATION host,
+                                                 unsigned int eumbbar,
+                                                 unsigned int channel,
+                                                 DMA_CDAR     desp );
+
+/**************************************************************
+ * function: DMA_Poke_Desp
+ *
+ * description: poke the current descriptor address register
+ *              for a given channel
+ *
+ *              return DMASUCCESS if no error otherwise return
+ *              DMAINVALID
+ *
+ * note: Due to the undeterministic parallellism of DMA operation,
+ *       the value returned by this function shall be taken as
+ *       the most recently used descriptor when the last time
+ *       DMA starts a chaining mode operation.
+ **************************************************************/
+static DMAStatus DMA_Poke_Desp( LOCATION,
+                                                          unsigned int eumbbar,
+                                                          unsigned int channel,
+                                                      DMA_CDAR     *desp );
+
+#endif
diff --git a/mpc8240/drivers/dma/dma1.c b/mpc8240/drivers/dma/dma1.c
new file mode 100644 (file)
index 0000000..cfdb17b
--- /dev/null
@@ -0,0 +1,802 @@
+/************************************************************
+ * $Id: dma1.c,v 1.1 2000/11/20 17:22:32 wdenk Exp $
+ *
+ * copyright @ Motorola, 1999
+ *
+ * App. API
+ *
+ * App. API are the APIs Kernel provides for the application
+ * level program 
+ * 
+ ************************************************************/
+#include "dma_export.h"
+#include "dma.h"
+
+/* Define a macro to use an optional application-layer print function, if
+ * one was passed to the library during initialization.  If there was no
+ * function pointer passed, this protects against referencing a NULL pointer.  
+ * Also define The global variable that holds the passed pointer.
+ */
+#define PRINT if ( app_print ) app_print
+static int (*app_print)(char *,...);
+
+/* Set by call to get_eumbbar during DMA_Initialize.
+ * This could be globally available to the library, but there is
+ * an advantage to passing it as a parameter: it is already in a register
+ * and doesn't have to be loaded from memory.  Also, that is the way the
+ * library was already implemented and I don't want to change it without
+ * a more detailed analysis.
+ * It is being set as a global variable during initialization to hide it from
+ * the DINK application layer, because it is Kahlua-specific.  I think that
+ * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in
+ * a Kahlua-specific library dealing with the embedded utilities memory block.
+ * Right now, get_eumbbar is defined in dink32/kahlua.s.  The other two are
+ * defined in dink32/drivers/i2c/i2c2.s, drivers/dma/dma2.s, etc.
+ */
+static unsigned int Global_eumbbar = 0;
+extern unsigned int get_eumbbar();
+
+
+extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
+#pragma Alias( load_runtime_reg, "load_runtime_reg" );
+
+extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
+#pragma Alias( store_runtime_reg, "store_runtime_reg" );
+
+unsigned int dma_reg_tb[][14] = {
+       /* local DMA registers */
+       { 
+      /* DMA_0_MR   */  0x00001100,
+      /* DMA_0_SR   */  0x00001104,
+      /* DMA_0_CDAR */  0x00001108,
+      /* DMA_0_SAR  */  0x00001110,
+      /* DMA_0_DAR  */  0x00001118,
+      /* DMA_0_BCR  */  0x00001120,
+      /* DMA_0_NDAR */  0x00001124,
+      /* DMA_1_MR   */  0x00001200,
+      /* DMA_1_SR   */  0x00001204,
+      /* DMA_1_CDAR */  0x00001208,
+      /* DMA_1_SAR  */  0x00001210,
+      /* DMA_1_DAR  */  0x00001218,
+      /* DMA_1_BCR  */  0x00001220,
+      /* DMA_1_NDAR */  0x00001224,
+       },
+       /* remote DMA registers */
+       { 
+      /* DMA_0_MR   */  0x00000100,
+      /* DMA_0_SR   */  0x00000104,
+      /* DMA_0_CDAR */  0x00000108,
+      /* DMA_0_SAR  */  0x00000110,
+      /* DMA_0_DAR  */  0x00000118,
+      /* DMA_0_BCR  */  0x00000120,
+      /* DMA_0_NDAR */  0x00000124,
+      /* DMA_1_MR   */  0x00000200,
+      /* DMA_1_SR   */  0x00000204,
+      /* DMA_1_CDAR */  0x00000208,
+      /* DMA_1_SAR  */  0x00000210,
+      /* DMA_1_DAR  */  0x00000218,
+      /* DMA_1_BCR  */  0x00000220,
+      /* DMA_1_NDAR */  0x00000224,
+       },
+};     
+
+/* API functions */
+
+/*  Initialize DMA unit with the following:
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  ???
+ *  Interrupt enables, modes, etc. are set for each transfer.
+ *
+ *  This function must be called before DMA unit can be used.
+ */
+extern 
+DMA_Status DMA_Initialize( int (*p)(char *,...))
+{
+  DMAStatus status;
+  /* establish the pointer, if there is one, to the application's "printf" */
+  app_print = p;
+
+  /* If this is the first call, get the embedded utilities memory block
+   * base address.  I'm not sure what to do about error handling here:
+   * if a non-zero value is returned, accept it.
+   */
+  if ( Global_eumbbar == 0)
+     Global_eumbbar = get_eumbbar();
+  if ( Global_eumbbar == 0)
+  {
+    PRINT( "DMA_Initialize: can't find EUMBBAR\n" );
+    return DMA_ERROR;
+  }
+
+  return DMA_SUCCESS;
+}
+
+
+/* Perform the DMA transfer, only direct mode is currently implemented.
+ * At this point, I think it would be better to define a different
+ * function for chaining mode.
+ * Also, I'm not sure if it is appropriate to have the "generic" API
+ * accept snoop and int_steer parameters.  The DINK user interface allows
+ * them, so for now I'll leave them.
+ *
+ * int_steer controls DMA interrupt steering to PCI or local processor
+ * type is the type of transfer: M2M, M2P, P2M, P2P
+ * source is the source address of the data
+ * dest is the destination address of the data
+ * len is the length of data to transfer
+ * channel is the DMA channel to use for the transfer
+ * snoop is the snoop enable control
+ */
+extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer,
+                                       DMA_TRANSFER_TYPE type,
+                                       unsigned int source,
+                                       unsigned int dest,
+                                       unsigned int len,
+                                       DMA_CHANNEL channel,
+                                       DMA_SNOOP_MODE snoop)
+{
+    DMA_MR md;
+    DMA_CDAR cdar;
+    /* it's inappropriate for curr to be a struct, but I'll leave it */
+    DMA_CURR curr;
+
+    DMAStatus stat;
+
+       /* The rest of this code was moved from device.c test_dma to here.
+        * It needs to be cleaned up and validated, but at least it is removed
+        * from the application and API.  Most of the mode is left hard coded.  
+        * This should be changed after the final API is defined and the user
+        * application has a way to control the transfer.
+        * 
+        */
+
+       if ( DMA_Get_Mode( LOCAL, Global_eumbbar, channel, &md ) != DMASUCCESS )
+       {
+               return DMA_ERROR;
+       }
+
+       md.irqs = int_steer;
+       md.pde = 0;
+       md.dahts = 3; /* 8 - byte */
+       md.sahts = 3; /* 8 - byte */
+       md.dahe = 0;
+       md.sahe = 0;
+       md.prc = 0;
+       /* if steering interrupts to local processor, use polling mode */
+       if ( int_steer == DMA_INT_STEER_PCI )
+       {
+               md.eie = 1;
+               md.eotie = 1;
+       } else {
+               md.eie = 0;
+               md.eotie = 0;
+       }
+       md.dl = 0;
+       md.ctm = 1;   /* direct mode */
+    md.cc = 0;
+
+       /* validate the length range */
+       if (len > 0x3ffffff )
+       {
+               PRINT( "dev DMA: length of transfer too large: %d\n", len );
+               return DMA_ERROR;
+       }
+
+       /* inappropriate to use a struct, but leave as is for now */
+       curr.src_addr = source;
+       curr.dest_addr = dest;
+       curr.byte_cnt = len;
+
+       (void)DMA_Poke_Desp( LOCAL, Global_eumbbar, channel, &cdar );
+       cdar.snen = snoop;
+       cdar.ctt = type;
+       
+       if ( ( stat = DMA_Bld_Desp( LOCAL, Global_eumbbar, channel, cdar )) 
+                       != DMASUCCESS ||
+                ( stat = DMA_Bld_Curr( LOCAL, Global_eumbbar, channel, curr )) 
+                       != DMASUCCESS ||            
+            ( stat = DMA_Set_Mode( LOCAL, Global_eumbbar, channel, md )) 
+                       != DMASUCCESS ||
+                ( stat = DMA_Start( LOCAL, Global_eumbbar, channel )) 
+                       != DMASUCCESS )
+       {
+               if ( stat == DMACHNBUSY )
+               {
+                       PRINT( "dev DMA: channel %d busy.\n", channel );
+               }
+               else
+               {
+                       PRINT( "dev DMA: invalid channel request.\n", channel );
+               }
+               
+               return DMA_ERROR;
+       }
+
+/* Since we are interested at the DMA performace right now,
+   we are going to do as less as possible to burden the
+   603e core.
+
+   if you have epic enabled or don't care the return from
+   DMA operation, you can just return SUCCESS.
+
+   if you don't have epic enabled and care the DMA result,
+   you can use the polling method below.
+
+   Note: I'll attempt to activate the code for handling polling.
+ */
+
+#if 0
+       /* if steering interrupt to local processor, let it handle results */
+       if ( int_steer == DMA_INT_STEER_LOCAL )
+       {
+           return DMA_SUCCESS;
+       }
+
+       /* polling since interrupt goes to PCI */
+       do
+       {
+               stat = DMA_ISR( Global_eumbbar, channel, dma_error_func, 
+                       dma_error_func, dma_error_func, dma_error_func );
+       }
+       while ( stat == DMANOEVENT );
+#endif
+
+    return DMA_SUCCESS;
+}
+
+/* DMA library internal functions */
+
+/**
+ * Note:
+ *
+ * In all following functions, the host (KAHLUA) processor has a
+ * choice of accessing on board local DMA (LOCAL),
+ * or DMA on a distributed KAHLUA (REMOTE). In either case,
+ * the caller shall pass the configured embedded utility memory
+ * block base address relative to the DMA. If LOCAL DMA is used,
+ * this parameter shall be EUMBBAR, if REMOTE is used, the
+ * parameter shall be the corresponding PCSRBAR.
+ **/
+    
+/**************************************************************
+ * function: DMA_Get_Stat
+ *
+ * description: return the content of status register of 
+ *              the given DMA channel
+ *
+ *              if error, reserved0 field all 1s.
+ **************************************************************/
+static
+DMAStatus DMA_Get_Stat( LOCATION host, unsigned int eumbbar, unsigned int channel, DMA_SR *stat )
+{
+    unsigned int tmp;
+   
+   if ( channel != 0 && channel != 1 || stat == 0 )
+   {
+       return DMAINVALID;
+   }
+
+    tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG] );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) stat = 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG], tmp );
+#endif
+   
+        stat->reserved0 = ( tmp & 0xffffff00 ) >> 8;
+        stat->lme       = ( tmp & 0x00000080 ) >> 7;
+        stat->reserved1 = ( tmp & 0x00000060 ) >> 5;
+        stat->pe        = ( tmp & 0x00000010 ) >> 4;
+        stat->reserved2 = ( tmp & 0x00000008 ) >> 3;
+        stat->cb        = ( tmp & 0x00000004 ) >> 2;
+        stat->eosi      = ( tmp & 0x00000002 ) >> 1;
+        stat->eocai     = ( tmp & 0x00000001 );
+   
+   return DMASUCCESS;
+}
+
+/**************************************************************
+ * function: DMA_Get_Mode
+ *
+ * description: return the content of mode register of the 
+ *              given DMA channel 
+ *
+ *              if error, return DMAINVALID, otherwise return
+ *              DMASUCCESS
+ **************************************************************/
+static
+DMAStatus DMA_Get_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR *mode )
+{
+    unsigned int tmp;
+   if ( channel != 0 && channel != 1 || mode == 0 )
+   {
+     return DMAINVALID;
+   }
+
+    tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG] );
+
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) mode = 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG], tmp );
+#endif
+   
+        mode->reserved0 = (tmp & 0xfff00000) >> 20;
+        mode->irqs      = (tmp & 0x00080000) >> 19;
+        mode->pde       = (tmp & 0x00040000) >> 18;
+        mode->dahts     = (tmp & 0x00030000) >> 16;
+     mode->sahts     = (tmp & 0x0000c000) >> 14;
+        mode->dahe      = (tmp & 0x00002000) >> 13;
+        mode->sahe      = (tmp & 0x00001000) >> 12;
+        mode->prc       = (tmp & 0x00000c00) >> 10;
+        mode->reserved1 = (tmp & 0x00000200) >> 9;
+        mode->eie       = (tmp & 0x00000100) >> 8;
+        mode->eotie     = (tmp & 0x00000080) >> 7;
+        mode->reserved2 = (tmp & 0x00000070) >> 4;
+        mode->dl        = (tmp & 0x00000008) >> 3;
+        mode->ctm       = (tmp & 0x00000004) >> 2;
+        mode->cc        = (tmp & 0x00000002) >> 1;
+        mode->cs        = (tmp & 0x00000001);
+
+   return DMASUCCESS;
+}
+
+/**************************************************************
+ * function: DMA_Set_Mode
+ *
+ * description: Set a new mode to a given DMA channel 
+ *
+ * note: It is not a good idea of changing the DMA mode during
+ *       the middle of a transaction.
+ **************************************************************/
+static
+DMAStatus DMA_Set_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR mode )
+{
+    unsigned int tmp;
+   if ( channel != 0 && channel != 1 )
+   {
+          return DMAINVALID;
+   }
+
+   tmp = ( mode.reserved0 & 0xfff ) << 20;
+   tmp |= ( ( mode.irqs  & 0x1 ) << 19);
+   tmp |= ( ( mode.pde   & 0x1 ) << 18 );
+   tmp |= ( ( mode.dahts & 0x3 ) << 16 );
+   tmp |= ( ( mode.sahts & 0x3 ) << 14 );
+   tmp |= ( ( mode.dahe  & 0x1 ) << 13 );
+   tmp |= ( ( mode.sahe  & 0x1 ) << 12 );
+   tmp |= ( ( mode.prc   & 0x3 ) << 10 );
+   tmp |= ( ( mode.reserved1 & 0x1 ) << 9 );
+   tmp |= ( ( mode.eie   & 0x1 ) << 8 );
+   tmp |= ( ( mode.eotie & 0x1 ) << 7 );
+   tmp |= ( ( mode.reserved2 & 0x7 ) << 4 );
+   tmp |= ( ( mode.dl    & 0x1 ) << 3 );
+   tmp |= ( ( mode.ctm   & 0x1 ) << 2 );
+   tmp |= ( ( mode.cc    & 0x1 ) << 1 ) ;
+   tmp |= ( mode.cs    & 0x1 );
+   
+   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], tmp );
+   return DMASUCCESS;
+}
+
+/************************************************************
+ * function: DMA_Start
+ * 
+ * description: start a given DMA channel transaction
+ *              return DMASUCCESS if success otherwise return
+ *              DMAStatus value
+ *
+ * note: this function will clear DMA_MR(CC) first, then
+ *       set DMA_MR(CC).
+ ***********************************************************/
+static
+DMAStatus DMA_Start( LOCATION host, unsigned int eumbbar, unsigned int channel )
+{
+   DMA_SR stat;
+   unsigned int mode;
+   
+   if ( channel != 0 && channel != 1 )
+   {
+          return DMAINVALID;
+   }
+
+   if ( DMA_Get_Stat( host, eumbbar, channel, &stat ) != DMASUCCESS )
+   {
+                  return DMAINVALID;
+   }
+   
+   if ( stat.cb == 1 )
+   {
+          /* DMA is not free */
+          return DMACHNBUSY;
+   }
+   
+   mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG] );
+   /* clear DMA_MR(CS) */
+   mode &= 0xfffffffe;
+   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
+
+   /* set DMA_MR(CS) */
+   mode |= CS;
+   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode ); 
+   return DMASUCCESS;
+}
+
+/***********************************************************
+ * function: DMA_Halt
+ *
+ * description: halt the current dma transaction on the specified
+ *              channel.
+ *              return DMASUCCESS if success otherwise return DMAINVALID
+ *
+ * note: if the specified DMA channel is idle, nothing happens
+ *************************************************************/
+static
+DMAStatus DMA_Halt( LOCATION host, unsigned int eumbbar, unsigned int channel )
+{
+   unsigned int mode;
+   if ( channel != 0 && channel != 1 )
+   {
+          return DMAINVALID;
+   }
+
+   mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG]);
+
+   /* clear DMA_MR(CS) */
+   mode &= 0xfffffffe;
+   store_runtime_reg(eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
+   return DMASUCCESS;
+}
+
+/*************************************************************
+ * function: DMA_Chn_Cnt
+ *
+ * description: set the DMA_MR(CC) bit for a given channel
+ *              that is in chaining mode. 
+ *              return DMASUCCESS if successfule, otherwise return
+ *              DMAINVALID.
+ *
+ * note: if the given channel is not in chaining mode, nothing
+ *       happen.
+ *
+ *************************************************************/
+static
+DMAStatus DMA_Chn_Cnt( LOCATION host, unsigned int eumbbar, unsigned int channel )
+{
+       DMA_MR mode;    
+       if ( channel != 0 && channel != 1 )
+       {
+               return DMAINVALID;
+       }
+
+       if ( DMA_Get_Mode( host, eumbbar, channel, &mode ) != DMASUCCESS )
+       {
+                       return DMAINVALID;
+       }
+       
+       if ( mode.ctm == 0 )
+       {
+               /* either illegal mode or not chaining mode */
+               return DMAINVALID;
+       }
+
+       mode.cc = 1;
+       return DMA_Set_Mode( host, eumbbar, channel, mode );
+}
+
+/**************************************************************
+ * function: DMA_Bld_Desp
+ *
+ * description: set current descriptor address register
+ *              according to the desp for a given channel
+ *
+ *              if the given channel is busy return DMACHNBUSY
+ *              and no change made, otherwise return DMASUCCESS.
+ *
+ * note:
+ **************************************************************/
+static
+DMAStatus DMA_Bld_Desp( LOCATION host,
+                                                  unsigned int eumbbar,
+                                                  unsigned int channel,
+                                                  DMA_CDAR     desp )
+{
+       DMA_SR status;
+       unsigned int temp;
+       
+       if ( channel != 0 && channel != 1 )
+       {
+               /* channel number out of range */
+               return DMAINVALID;
+       }
+
+       if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
+       {
+                       return DMAINVALID;
+       }
+       
+       if ( status.cb == 1 )
+       {
+               /* channel busy */
+               return DMACHNBUSY;
+       }
+
+       temp = ( desp.cda & 0x7ffffff ) << 5;
+       temp |= (( desp.snen & 0x1 ) << 4 );
+       temp |= (( desp.eosie & 0x1 ) << 3 );
+       temp |= (( desp.ctt   & 0x3 ) << 1 );
+    temp |= ( desp.eotd  & 0x1 );
+
+    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
+       
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) cdar := 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
+#endif
+
+       return DMASUCCESS;
+}
+
+/**************************************************************
+ * function: DMA_Poke_Desp
+ *
+ * description: poke the current descriptor address register
+ *              for a given channel
+ *
+ *              return DMASUCCESS if no error
+ *
+ * note: Due to the undeterministic parallellism of DMA operation,
+ *       the value returned by this function shall be taken as
+ *       the most recently used descriptor when the last time
+ *       DMA starts a chaining mode operation.
+ **************************************************************/
+static
+DMAStatus DMA_Poke_Desp( LOCATION host,
+                                                   unsigned int eumbbar,
+                                                   unsigned int channel,
+                                                   DMA_CDAR     *desp )
+{
+       unsigned int cdar;
+       if ( channel != 0 && channel != 1 || desp == 0 )
+       {
+                       return DMAINVALID;
+       }
+
+    cdar = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG] );
+
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) cdar : 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], cdar );
+#endif
+
+       
+       desp->cda   = ( cdar & 0xffffffe0 ) >> 5;
+       desp->snen  = ( cdar & 0x00000010 ) >> 4;
+       desp->eosie = ( cdar & 0x00000008 ) >> 3;
+       desp->ctt   = ( cdar & 0x00000006 ) >> 1;
+       desp->eotd  = ( cdar & 0x00000001 );
+
+       return DMASUCCESS;
+}
+
+/**************************************************************
+ * function: DMA_Bld_Curr
+ *
+ * description: set current src, dest, byte count registers
+ *              according to the desp for a given channel
+ *              return DMASUCCESS if no error.
+ *
+ * note:
+ **************************************************************/
+static
+DMAStatus DMA_Bld_Curr( LOCATION host,
+                                          unsigned int eumbbar,
+                                          unsigned int channel,
+                                          DMA_CURR     desp )
+{
+       DMA_SR status;  
+       if ( channel != 0 && channel != 1 )
+       {
+               /* channel number out of range */
+               return DMAINVALID;
+       }
+
+       if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
+       {
+                return DMAINVALID;
+       }
+       
+       if ( status.cb == 1  )
+       {
+               /* channel busy */
+               return DMACHNBUSY;
+       }
+       
+       desp.byte_cnt &= 0x03ffffff; /* upper 6-bits are 0s */
+
+    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG], desp.src_addr );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) src := 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.src_addr );
+#endif
+       
+    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG], desp.dest_addr );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) dest := 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.dest_addr );
+#endif
+       
+    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG], desp.byte_cnt );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) count := 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt );
+#endif
+       
+
+       return DMASUCCESS;
+
+}
+
+/**************************************************************
+ * function: DMA_Poke_Curr
+ *
+ * description: poke the current src, dest, byte count registers
+ *              for a given channel.
+ *
+ *              return DMASUCCESS if no error
+ *
+ * note:        Due to the undeterministic parallelism, in chaining
+ *              mode, the value returned by this function shall
+ *              be taken as reference when the query is made rather
+ *              than the absolute snapshot when the value is returned.
+ **************************************************************/
+static
+DMAStatus DMA_Poke_Curr( LOCATION host,
+                                           unsigned int eumbbar,
+                                           unsigned int channel,
+                                           DMA_CURR*    desp )
+{
+       if ( channel != 0 && channel != 1 || desp == 0 )
+       {
+                       return DMAINVALID;
+       }
+
+       desp->src_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG] );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) src : 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->src_addr );
+#endif
+       
+       desp->dest_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG] );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) dest : 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->dest_addr );
+#endif
+       
+    desp->byte_cnt = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG] );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) count : 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt );
+#endif
+       
+
+       return DMASUCCESS;
+}
+
+/*****************************************************************
+ * function: dma_error_func
+ *
+ * description: display the error information
+ *
+ * note: This seems like a highly convoluted way to handle messages,
+ * but I'll leave it as it was in device.c when I moved it into the
+ * DMA library source.
+ ****************************************************************/
+static
+DMAStatus dma_error_func( unsigned int eumbbar, unsigned int chn, DMAStatus err)
+{
+       unsigned char *msg[] =
+               {
+                       "Local Memory Error",
+                       "PCI Error",                    
+                       "Channel Busy", 
+                       "End-of-Segment Interrupt",
+                       "End-of-Chain/Direct Interrupt",
+               };
+
+          if ( err >= DMALMERROR && err <= DMAEOCAINT )
+          {
+            PRINT( "DMA Status: channel %d  %s\n", chn, msg[err-DMASUCCESS-1] );
+          }
+       
+          return err;
+
+}
+
+/*************************************************************
+ * function: DMA_ISR
+ *
+ * description: DMA interrupt service routine
+ *              return DMAStatus value based on
+ *              the status
+ *
+ *************************************************************/
+static
+DMAStatus DMA_ISR( unsigned int eumbbar,
+                                 unsigned int channel,
+                                 DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ),
+                                 DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ),
+                                 DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ),
+                                 DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus ))
+{
+
+       DMA_SR stat;
+       DMAStatus rval = DMANOEVENT;
+    unsigned int temp;
+       
+       if ( channel != 0 && channel != 1 )
+       {
+               return DMAINVALID;
+       }
+       
+       if ( DMA_Get_Stat( LOCAL, eumbbar, channel, &stat ) != DMASUCCESS )
+       {
+                       return DMAINVALID;
+       }
+
+       if ( stat.lme == 1 )
+       {
+               /* local memory error */
+               rval = DMALMERROR;
+               if ( lme_func != 0 )
+               {
+                 rval = (*lme_func)(eumbbar, channel, DMALMERROR );
+           }
+               
+       }
+       else if ( stat.pe == 1 )
+       {
+        /* PCI error */
+               rval = DMAPERROR;
+               if ( pe_func != 0 )
+               {
+                 rval = (*pe_func)(eumbbar, channel, DMAPERROR );
+           }
+
+       }
+       else if ( stat.eosi == 1 )
+       {
+               /* end-of-segment interrupt */
+               rval = DMAEOSINT;
+               if ( eosi_func != 0 )
+               {
+                 rval = (*eosi_func)(eumbbar, channel, DMAEOSINT );
+           }
+       }
+       else
+       {
+               /* End-of-chain/direct interrupt */
+               rval = DMAEOCAINT;
+               if ( eocai_func != 0 )
+               {
+                 rval = (*eocai_func)(eumbbar, channel, DMAEOCAINT );
+           }
+       }
+
+    temp = ( stat.reserved0 & 0xffffff ) << 8;
+       temp |= ( ( stat.lme       & 0x1 ) << 7 );  /* write one to clear */
+       temp |= ( ( stat.reserved1 & 0x3 ) << 5 );
+    temp |= ( ( stat.pe        & 0x1 ) << 4 );  /* write one to clear */       
+    temp |= ( ( stat.reserved2 & 0x1 ) << 3 );
+       temp |= ( ( stat.cb        & 0x1 ) << 2 );  /* write one to clear */
+    temp |= ( ( stat.eosi      & 0x1 ) << 1 );  /* write one to clear */
+    temp |= ( stat.eocai & 0x1 );               /* write one to clear */
+       
+    store_runtime_reg( eumbbar, dma_reg_tb[LOCAL][channel*NUM_DMA_REG + DMA_SR_REG], temp );
+
+#ifdef DMADBG0
+       PRINT( "%s(%d): DMA channel %d SR := 0x%08x\n", __FILE__, __LINE__, channel, temp );
+#endif
+       
+       return rval;
+}
diff --git a/mpc8240/drivers/dma/dma2.S b/mpc8240/drivers/dma/dma2.S
new file mode 100644 (file)
index 0000000..fb176a0
--- /dev/null
@@ -0,0 +1,46 @@
+/**************************************
+ * $Id: dma2.S,v 1.1 2000/11/20 17:22:32 wdenk Exp $
+ *
+ * copyright @ Motorola, 1999
+ *
+ **************************************/
+
+/**********************************************************
+ * function: load_runtime_reg
+ *
+ * input:  r3 - value of eumbbar
+ *         r4 - register offset in embedded utility space
+ *
+ * output: r3 - register content
+ **********************************************************/
+      .text
+      .align 2
+      .global load_runtime_reg
+
+load_runtime_reg:
+
+             lwbrx     r3,r4,r3
+             sync
+
+             bclr 20, 0
+
+/****************************************************************
+ * function: store_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ *        r4 - register offset in embedded utility space
+ *        r5 - new value to be stored 
+ *
+ ****************************************************************/
+           .text
+           .align 2
+           .global store_runtime_reg
+store_runtime_reg:
+
+             stwbrx r5,  r4, r3
+             sync
+
+                 bclr   20,0
+
+
+
diff --git a/mpc8240/drivers/dma/dma_export.h b/mpc8240/drivers/dma/dma_export.h
new file mode 100644 (file)
index 0000000..2c9ca71
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef DMA_EXPORT_H
+#define DMA_EXPORT_H
+
+/****************************************************
+ * $Id: 
+ *
+ * Copyright Motorola 1999
+ *
+ * $Log: 
+ *
+ ****************************************************/
+
+/* These are the defined return values for the DMA_* functions.
+ * Any non-zero value indicates failure.  Failure modes can be added for 
+ * more detailed error reporting.
+ */
+typedef enum _dma_status
+{
+ DMA_SUCCESS     = 0,
+ DMA_ERROR,
+} DMA_Status;
+
+/* These are the defined channel transfer types.  */
+typedef enum _dma_transfer_types
+{
+       DMA_M2M =  0,   /* local memory to local memory */
+       DMA_M2P =  1,   /* local memory to PCI */
+       DMA_P2M =  2,   /* PCI to local memory */
+       DMA_P2P =  3,   /* PCI to PCI */
+} DMA_TRANSFER_TYPE;
+
+typedef enum _dma_interrupt_steer
+{
+       DMA_INT_STEER_LOCAL =  0, /* steer DMA int to local processor */
+       DMA_INT_STEER_PCI = 1,    /* steer DMA int to PCI bus through INTA_ */
+} DMA_INTERRUPT_STEER;
+
+typedef enum _dma_channel
+{
+       DMA_CHN_0 =  0, /* kahlua has two dma channels: 0 and 1 */
+       DMA_CHN_1 =  1,
+} DMA_CHANNEL;
+
+typedef enum _dma_snoop_mode
+{
+       DMA_SNOOP_DISABLE =  0,
+       DMA_SNOOP_ENABLE = 1,
+} DMA_SNOOP_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application 
+ * to use the functionality provided by DMA driver.
+ * This is a "generic" DMA interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ * 
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we currently transfer whatever
+ *       we are given - Big/Little Endian.  This could
+ *       become part of the DMA config, though.
+ **************************************************/
+
+
+/*  Initialize DMA unit with the following:
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  ???
+ *  Interrupt enables, modes, etc. are set for each transfer.
+ *
+ *  This function must be called before DMA unit can be used.
+ */
+extern DMA_Status DMA_Initialize( 
+        int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+                                                 * provided by application
+                                                 */
+
+/* Perform the DMA transfer, only direct mode is currently implemented.
+ * At this point, I think it would be better to define a different
+ * function for chaining mode.
+ * Also, I'm not sure if it is appropriate to have the "generic" API
+ * accept snoop and int_steer parameters.  The DINK user interface allows
+ * them, so for now I'll leave them.
+ * 
+ * int_steer controls DMA interrupt steering to PCI or local processor
+ * type is the type of transfer: M2M, M2P, P2M, P2P
+ * source is the source address of the data
+ * dest is the destination address of the data
+ * len is the length of data to transfer
+ * channel is the DMA channel to use for the transfer
+ * snoop is the snoop enable control
+ */
+extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer,
+                                       DMA_TRANSFER_TYPE type,
+                                       unsigned int source,
+                                       unsigned int dest,
+                                       unsigned int len,
+                                       DMA_CHANNEL channel,
+                                       DMA_SNOOP_MODE snoop);
+#endif
diff --git a/mpc8240/drivers/dma_export.h b/mpc8240/drivers/dma_export.h
new file mode 100644 (file)
index 0000000..2c9ca71
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef DMA_EXPORT_H
+#define DMA_EXPORT_H
+
+/****************************************************
+ * $Id: 
+ *
+ * Copyright Motorola 1999
+ *
+ * $Log: 
+ *
+ ****************************************************/
+
+/* These are the defined return values for the DMA_* functions.
+ * Any non-zero value indicates failure.  Failure modes can be added for 
+ * more detailed error reporting.
+ */
+typedef enum _dma_status
+{
+ DMA_SUCCESS     = 0,
+ DMA_ERROR,
+} DMA_Status;
+
+/* These are the defined channel transfer types.  */
+typedef enum _dma_transfer_types
+{
+       DMA_M2M =  0,   /* local memory to local memory */
+       DMA_M2P =  1,   /* local memory to PCI */
+       DMA_P2M =  2,   /* PCI to local memory */
+       DMA_P2P =  3,   /* PCI to PCI */
+} DMA_TRANSFER_TYPE;
+
+typedef enum _dma_interrupt_steer
+{
+       DMA_INT_STEER_LOCAL =  0, /* steer DMA int to local processor */
+       DMA_INT_STEER_PCI = 1,    /* steer DMA int to PCI bus through INTA_ */
+} DMA_INTERRUPT_STEER;
+
+typedef enum _dma_channel
+{
+       DMA_CHN_0 =  0, /* kahlua has two dma channels: 0 and 1 */
+       DMA_CHN_1 =  1,
+} DMA_CHANNEL;
+
+typedef enum _dma_snoop_mode
+{
+       DMA_SNOOP_DISABLE =  0,
+       DMA_SNOOP_ENABLE = 1,
+} DMA_SNOOP_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application 
+ * to use the functionality provided by DMA driver.
+ * This is a "generic" DMA interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ * 
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we currently transfer whatever
+ *       we are given - Big/Little Endian.  This could
+ *       become part of the DMA config, though.
+ **************************************************/
+
+
+/*  Initialize DMA unit with the following:
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  ???
+ *  Interrupt enables, modes, etc. are set for each transfer.
+ *
+ *  This function must be called before DMA unit can be used.
+ */
+extern DMA_Status DMA_Initialize( 
+        int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+                                                 * provided by application
+                                                 */
+
+/* Perform the DMA transfer, only direct mode is currently implemented.
+ * At this point, I think it would be better to define a different
+ * function for chaining mode.
+ * Also, I'm not sure if it is appropriate to have the "generic" API
+ * accept snoop and int_steer parameters.  The DINK user interface allows
+ * them, so for now I'll leave them.
+ * 
+ * int_steer controls DMA interrupt steering to PCI or local processor
+ * type is the type of transfer: M2M, M2P, P2M, P2P
+ * source is the source address of the data
+ * dest is the destination address of the data
+ * len is the length of data to transfer
+ * channel is the DMA channel to use for the transfer
+ * snoop is the snoop enable control
+ */
+extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer,
+                                       DMA_TRANSFER_TYPE type,
+                                       unsigned int source,
+                                       unsigned int dest,
+                                       unsigned int len,
+                                       DMA_CHANNEL channel,
+                                       DMA_SNOOP_MODE snoop);
+#endif
diff --git a/mpc8240/drivers/epic.h b/mpc8240/drivers/epic.h
new file mode 100644 (file)
index 0000000..2803f63
--- /dev/null
@@ -0,0 +1 @@
+#include "epic/epic.h"
diff --git a/mpc8240/drivers/epic/README b/mpc8240/drivers/epic/README
new file mode 100644 (file)
index 0000000..7fea4e1
--- /dev/null
@@ -0,0 +1,104 @@
+CONTENT:
+
+   epic.h
+   epic1.c
+   epic2.s
+
+WHAT ARE THESE FILES:
+
+These files contain MPC8240 (Kahlua) EPIC
+driver routines. The driver routines are not 
+written for any specific operating system. 
+They serves the purpose of code sample, and 
+jump-start for using the MPC8240 EPIC unit.
+
+For the reason of correctness of C language
+syntax, these files are compiled by Metaware
+C compiler and assembler.
+
+ENDIAN NOTATION:
+
+The algorithm is designed for big-endian mode,
+software is responsible for byte swapping.
+
+USAGE:
+
+1. The host system that is running on MPC8240 
+   shall link the files listed here. The memory 
+   location of driver routines shall take into 
+   account of that driver routines need to run 
+   in supervisor mode and they process external
+   interrupts.
+
+   The routine epic_exception shall be called by
+   exception vector at location 0x500, i.e., 
+   603e core external exception vector.
+
+2. The host system is responsible for configuring
+   the MPC8240 including Embedded Utilities Memory 
+   Block. All EPIC driver functions require the
+   content of Embedded Utilities Memory Block
+   Base Address Register, EUMBBAR, as the first
+   parameter.
+
+3. Before EPIC unit of MPC8240 can be used,
+   initialize EPIC unit by calling epicInit 
+   with the corresponding parameters.
+
+   The initialization shall disable the 603e
+   core External Exception by calling CoreExtIntDisable( ).
+   Next, call epicInit( ). Last, enable the 603e core 
+   External Exception by calling CoreExtIntEnable( ).
+
+4. After EPIC unit has been successfully initialized,
+   epicIntSourceSet( ) shall be used to register each
+   external interrupt source. Anytime, an external
+   interrupt source can be disabled or enabled by 
+   calling corresponding function, epicIntDisable( ), 
+   or epicIntEnable( ).
+
+   Global Timers' resource, base count and frequency,
+   can be changed by calling epicTmFrequencySet( )
+   and epicTmBaseSet( ).
+
+   To stop counting a specific global timer, use
+   the function, epicTmInhibit while epicTmEnable
+   can be used to start counting a timer.
+
+5. To mask a set of external interrupts that are
+   are certain level below, epicIntPrioritySet( )
+   can be used. For example, if the processor's
+   current task priority register is set to 0x7,
+   only interrupts of priority 0x8 or higher will
+   be passed to the processor.
+
+   Be careful when using this function. It may
+   corrupt the current interrupt pending, selector,
+   and request registers, resulting an invalid vetor.
+
+   After enabling an interrupt, disable it may also
+   cause an invalid vector. User may consider using 
+   the spurious vector interrupt service routine to 
+   handle this case.
+
+6. The EPIC driver routines contains a set 
+   of utilities, Set and Get, for host system
+   to query and modify the desired EPIC source
+   registers.
+  
+7. Each external interrupt source shall register
+   its interrupt service routine. The routine
+   shall contain all interrupt source specific
+   processes and keep as short as possible.
+
+   Special customized end of interrupt routine 
+   is optional. If it is needed, it shall contain
+   the external interrupt source specific end of 
+   interrupt process. 
+
+   External interrupt exception vector at 0x500
+   shall always call the epicEOI just before
+   rfi instruction. Refer to the routine,
+   epic_exception, for a code sample.
+   
+   
diff --git a/mpc8240/drivers/epic/epic.h b/mpc8240/drivers/epic/epic.h
new file mode 100644 (file)
index 0000000..76c5d4e
--- /dev/null
@@ -0,0 +1,160 @@
+/*********************************************************************
+ * mpc8240epic.h - EPIC module of the MPC8240 micro-controller
+ *
+ * Copyrigh 1999  Motorola Inc.
+ *
+ * Modification History:
+ * =====================
+ * 01a,04Feb99,My  Created.
+ * 15Nov200, robt -modified to use in ppcboot
+ *
+*/
+
+#ifndef __INCEPICh
+#define __INCEPICh
+
+#define ULONG unsigned long
+#define MAXVEC             20
+#define MAXIRQ        5 /* IRQs */
+#define EPIC_DIRECT_IRQ     0 /* Direct interrupt type */
+
+/* EPIC register addresses */
+
+#define EPIC_EUMBBAR      0x40000     /* EUMBBAR of EPIC  */
+#define EPIC_FEATURES_REG (EPIC_EUMBBAR + 0x01000)/* Feature reporting */
+#define EPIC_GLOBAL_REG   (EPIC_EUMBBAR + 0x01020)/* Global config.  */
+#define EPIC_INT_CONF_REG (EPIC_EUMBBAR + 0x01030)/* Interrupt config. */
+#define EPIC_VENDOR_ID_REG  (EPIC_EUMBBAR + 0x01080)/* Vendor id */
+#define EPIC_PROC_INIT_REG  (EPIC_EUMBBAR + 0x01090)/* Processor init. */
+#define EPIC_SPUR_VEC_REG (EPIC_EUMBBAR + 0x010e0)/* Spurious vector */
+#define EPIC_TM_FREQ_REG  (EPIC_EUMBBAR + 0x010f0)/* Timer Frequency */
+
+#define EPIC_TM0_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x01100)/* Gbl TM0 Cur. Count*/
+#define EPIC_TM0_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01110)/* Gbl TM0 Base Count*/
+#define EPIC_TM0_VEC_REG  (EPIC_EUMBBAR + 0x01120)/* Gbl TM0 Vector Pri*/
+#define EPIC_TM0_DES_REG  (EPIC_EUMBBAR + 0x01130)/* Gbl TM0 Dest. */
+
+#define EPIC_TM1_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x01140)/* Gbl TM1 Cur. Count*/
+#define EPIC_TM1_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01150)/* Gbl TM1 Base Count*/
+#define EPIC_TM1_VEC_REG  (EPIC_EUMBBAR + 0x01160)/* Gbl TM1 Vector Pri*/
+#define EPIC_TM1_DES_REG  (EPIC_EUMBBAR + 0x01170)/* Gbl TM1 Dest. */
+
+#define EPIC_TM2_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x01180)/* Gbl TM2 Cur. Count*/
+#define EPIC_TM2_BASE_COUNT_REG (EPIC_EUMBBAR + 0x01190)/* Gbl TM2 Base Count*/
+#define EPIC_TM2_VEC_REG  (EPIC_EUMBBAR + 0x011a0)/* Gbl TM2 Vector Pri*/
+#define EPIC_TM2_DES_REG  (EPIC_EUMBBAR + 0x011b0)/* Gbl TM2 Dest */
+
+#define EPIC_TM3_CUR_COUNT_REG  (EPIC_EUMBBAR + 0x011c0)/* Gbl TM3 Cur. Count*/
+#define EPIC_TM3_BASE_COUNT_REG (EPIC_EUMBBAR + 0x011d0)/* Gbl TM3 Base Count*/
+#define EPIC_TM3_VEC_REG  (EPIC_EUMBBAR + 0x011e0)/* Gbl TM3 Vector Pri*/
+#define EPIC_TM3_DES_REG  (EPIC_EUMBBAR + 0x011f0)/* Gbl TM3 Dest. */
+
+#define EPIC_EX_INT0_VEC_REG  (EPIC_EUMBBAR + 0x10200)/* Ext. Int. Sr0 Des */
+#define EPIC_EX_INT0_DES_REG  (EPIC_EUMBBAR + 0x10210)/* Ext. Int. Sr0 Vect*/
+#define EPIC_EX_INT1_VEC_REG  (EPIC_EUMBBAR + 0x10220)/* Ext. Int. Sr1 Des */
+#define EPIC_EX_INT1_DES_REG  (EPIC_EUMBBAR + 0x10230)/* Ext. Int. Sr1 Vect*/
+#define EPIC_EX_INT2_VEC_REG  (EPIC_EUMBBAR + 0x10240)/* Ext. Int. Sr2 Des */
+#define EPIC_EX_INT2_DES_REG  (EPIC_EUMBBAR + 0x10250)/* Ext. Int. Sr2 Vect*/
+#define EPIC_EX_INT3_VEC_REG  (EPIC_EUMBBAR + 0x10260)/* Ext. Int. Sr3 Des */
+#define EPIC_EX_INT3_DES_REG  (EPIC_EUMBBAR + 0x10270)/* Ext. Int. Sr3 Vect*/
+#define EPIC_EX_INT4_VEC_REG  (EPIC_EUMBBAR + 0x10280)/* Ext. Int. Sr4 Des */
+#define EPIC_EX_INT4_DES_REG  (EPIC_EUMBBAR + 0x10290)/* Ext. Int. Sr4 Vect*/
+
+#define EPIC_SR_INT0_VEC_REG  (EPIC_EUMBBAR + 0x10200)/* Sr. Int. Sr0 Des */
+#define EPIC_SR_INT0_DES_REG  (EPIC_EUMBBAR + 0x10210)/* Sr. Int. Sr0 Vect */
+#define EPIC_SR_INT1_VEC_REG  (EPIC_EUMBBAR + 0x10220)/* Sr. Int. Sr1 Des */
+#define EPIC_SR_INT1_DES_REG  (EPIC_EUMBBAR + 0x10230)/* Sr. Int. Sr1 Vect.*/
+#define EPIC_SR_INT2_VEC_REG  (EPIC_EUMBBAR + 0x10240)/* Sr. Int. Sr2 Des */
+#define EPIC_SR_INT2_DES_REG  (EPIC_EUMBBAR + 0x10250)/* Sr. Int. Sr2 Vect.*/
+#define EPIC_SR_INT3_VEC_REG  (EPIC_EUMBBAR + 0x10260)/* Sr. Int. Sr3 Des */
+#define EPIC_SR_INT3_DES_REG  (EPIC_EUMBBAR + 0x10270)/* Sr. Int. Sr3 Vect.*/
+#define EPIC_SR_INT4_VEC_REG  (EPIC_EUMBBAR + 0x10280)/* Sr. Int. Sr4 Des */
+#define EPIC_SR_INT4_DES_REG  (EPIC_EUMBBAR + 0x10290)/* Sr. Int. Sr4 Vect.*/
+
+#define EPIC_SR_INT5_VEC_REG  (EPIC_EUMBBAR + 0x102a0)/* Sr. Int. Sr5 Des */
+#define EPIC_SR_INT5_DES_REG  (EPIC_EUMBBAR + 0x102b0)/* Sr. Int. Sr5 Vect.*/
+#define EPIC_SR_INT6_VEC_REG  (EPIC_EUMBBAR + 0x102c0)/* Sr. Int. Sr6 Des */
+#define EPIC_SR_INT6_DES_REG  (EPIC_EUMBBAR + 0x102d0)/* Sr. Int. Sr6 Vect.*/
+#define EPIC_SR_INT7_VEC_REG  (EPIC_EUMBBAR + 0x102e0)/* Sr. Int. Sr7 Des */
+#define EPIC_SR_INT7_DES_REG  (EPIC_EUMBBAR + 0x102f0)/* Sr. Int. Sr7 Vect.*/
+#define EPIC_SR_INT8_VEC_REG  (EPIC_EUMBBAR + 0x10300)/* Sr. Int. Sr8 Des */
+#define EPIC_SR_INT8_DES_REG  (EPIC_EUMBBAR + 0x10310)/* Sr. Int. Sr8 Vect.*/
+#define EPIC_SR_INT9_VEC_REG  (EPIC_EUMBBAR + 0x10320)/* Sr. Int. Sr9 Des */
+#define EPIC_SR_INT9_DES_REG  (EPIC_EUMBBAR + 0x10330)/* Sr. Int. Sr9 Vect.*/
+
+#define EPIC_SR_INT10_VEC_REG (EPIC_EUMBBAR + 0x10340)/* Sr. Int. Sr10 Des */
+#define EPIC_SR_INT10_DES_REG (EPIC_EUMBBAR + 0x10350)/* Sr. Int. Sr10 Vect*/
+#define EPIC_SR_INT11_VEC_REG (EPIC_EUMBBAR + 0x10360)/* Sr. Int. Sr11 Des */
+#define EPIC_SR_INT11_DES_REG (EPIC_EUMBBAR + 0x10370)/* Sr. Int. Sr11 Vect*/
+#define EPIC_SR_INT12_VEC_REG (EPIC_EUMBBAR + 0x10380)/* Sr. Int. Sr12 Des */
+#define EPIC_SR_INT12_DES_REG (EPIC_EUMBBAR + 0x10390)/* Sr. Int. Sr12 Vect*/
+#define EPIC_SR_INT13_VEC_REG (EPIC_EUMBBAR + 0x103a0)/* Sr. Int. Sr13 Des */
+#define EPIC_SR_INT13_DES_REG (EPIC_EUMBBAR + 0x103b0)/* Sr. Int. Sr13 Vect*/
+#define EPIC_SR_INT14_VEC_REG (EPIC_EUMBBAR + 0x103c0)/* Sr. Int. Sr14 Des */
+#define EPIC_SR_INT14_DES_REG (EPIC_EUMBBAR + 0x103d0)/* Sr. Int. Sr14 Vect*/
+#define EPIC_SR_INT15_VEC_REG (EPIC_EUMBBAR + 0x103e0)/* Sr. Int. Sr15 Des */
+#define EPIC_SR_INT15_DES_REG (EPIC_EUMBBAR + 0x103f0)/* Sr. Int. Sr15 Vect*/
+
+#define EPIC_I2C_INT_VEC_REG  (EPIC_EUMBBAR + 0x11020)/* I2C Int. Vect Pri.*/
+#define EPIC_I2C_INT_DES_REG  (EPIC_EUMBBAR + 0x11030)/* I2C Int. Dest */
+#define EPIC_DMA0_INT_VEC_REG (EPIC_EUMBBAR + 0x11040)/* DMA0 Int. Vect Pri*/
+#define EPIC_DMA0_INT_DES_REG (EPIC_EUMBBAR + 0x11050)/* DMA0 Int. Dest */
+#define EPIC_DMA1_INT_VEC_REG (EPIC_EUMBBAR + 0x11060)/* DMA1 Int. Vect Pri*/
+#define EPIC_DMA1_INT_DES_REG (EPIC_EUMBBAR + 0x11070)/* DMA1 Int. Dest */
+#define EPIC_MSG_INT_VEC_REG  (EPIC_EUMBBAR + 0x110c0)/* Msg Int. Vect Pri*/
+#define EPIC_MSG_INT_DES_REG  (EPIC_EUMBBAR + 0x110d0)/* Msg Int. Dest  */
+
+#define EPIC_PROC_CTASK_PRI_REG (EPIC_EUMBBAR + 0x20080)/* Proc. current task*/
+#define EPIC_PROC_INT_ACK_REG (EPIC_EUMBBAR + 0x200a0)/* Int. acknowledge */
+#define EPIC_PROC_EOI_REG (EPIC_EUMBBAR + 0x200b0)/* End of interrupt */
+
+/* Error code */
+
+#define OK       0
+#define ERROR    -1
+
+/* function prototypes */
+
+void epicVendorId( unsigned int *step,
+       unsigned int *devId,
+       unsigned int *venId
+     );
+void epicFeatures( unsigned int *noIRQs,
+             unsigned int *noCPUs,
+       unsigned int *VerId );
+extern void epicInit( unsigned int IRQType, unsigned int clkRatio);
+ULONG sysEUMBBARRead ( ULONG regNum );
+void sysEUMBBARWrite ( ULONG regNum, ULONG regVal);
+extern void epicTmFrequencySet( unsigned int frq );
+extern unsigned int epicTmFrequencyGet(void);
+extern unsigned int epicTmBaseSet( ULONG srcAddr,
+                 unsigned int cnt,
+                 unsigned int inhibit );
+extern unsigned int epicTmBaseGet ( ULONG srcAddr, unsigned int *val );
+extern unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val );
+extern unsigned int epicTmInhibit( unsigned int timer );
+extern unsigned int epicTmEnable( ULONG srcAdr );
+extern void CoreExtIntEnable(void);  /* Enable 603e external interrupts */
+extern void CoreExtIntDisable(void); /* Disable 603e external interrupts */
+extern unsigned char epicIntTaskGet(void);
+extern void epicIntTaskSet( unsigned char val );
+extern unsigned int epicIntAck(void);
+extern void epicSprSet( unsigned int eumbbar, unsigned char );
+extern void epicConfigGet( unsigned int *clkRatio,
+               unsigned int *serEnable );
+extern void SrcVecTableInit(void);
+extern unsigned int  epicModeGet(void);
+extern void epicIntEnable(int Vect);
+extern void epicIntDisable(int Vect);
+extern int epicIntSourceConfig(int Vect, int Polarity, int Sense, int Prio);
+extern unsigned int epicIntAck(void);
+extern void epicEOI(void);
+extern int epicCurTaskPrioSet(int Vect);
+
+struct SrcVecTable
+    {
+     ULONG srcAddr;
+     char  srcName[40];
+    };
+
+#endif   /*  EPIC_H */
diff --git a/mpc8240/drivers/epic/epic1.c b/mpc8240/drivers/epic/epic1.c
new file mode 100644 (file)
index 0000000..e9d3861
--- /dev/null
@@ -0,0 +1,517 @@
+/**************************************************
+ * $Id: epic1.c,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+ *
+ * copyright @ motorola, 1999
+ *
+ *************************************************/
+#include <mpc8240.h>
+#include <ppcboot.h>
+#include "epic.h"
+
+
+#define PRINT(format, args...) printf(format , ## args)
+
+#define LONGSWAP(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\
+                     (((x) & 0x00ff0000) >>  8) | (((x) & 0xff000000) >> 24) )
+
+typedef void (*VOIDFUNCPTR)  (void);  /* ptr to function returning void */
+struct SrcVecTable SrcVecTable[MAXVEC] = /* Addr/Vector cross-reference tbl */
+    {
+    { EPIC_EX_INT0_VEC_REG,  "External Direct/Serial Source 0"},
+    { EPIC_EX_INT1_VEC_REG,  "External Direct/Serial Source 1"},
+    { EPIC_EX_INT2_VEC_REG,  "External Direct/Serial Source 2"},
+    { EPIC_EX_INT3_VEC_REG,  "External Direct/Serial Source 3"},
+    { EPIC_EX_INT4_VEC_REG,  "External Direct/Serial Source 4"},
+
+    { EPIC_SR_INT5_VEC_REG,  "External Serial Source 5"},
+    { EPIC_SR_INT6_VEC_REG,  "External Serial Source 6"},
+    { EPIC_SR_INT7_VEC_REG,  "External Serial Source 7"},
+    { EPIC_SR_INT8_VEC_REG,  "External Serial Source 8"},
+    { EPIC_SR_INT9_VEC_REG,  "External Serial Source 9"},
+    { EPIC_SR_INT10_VEC_REG, "External Serial Source 10"},
+    { EPIC_SR_INT11_VEC_REG, "External Serial Source 11"},
+    { EPIC_SR_INT12_VEC_REG, "External Serial Source 12"},
+    { EPIC_SR_INT13_VEC_REG, "External Serial Source 13"},
+    { EPIC_SR_INT14_VEC_REG, "External Serial Source 14"},
+    { EPIC_SR_INT15_VEC_REG, "External Serial Source 15"},
+
+    { EPIC_I2C_INT_VEC_REG,  "Internal I2C Source"},
+    { EPIC_DMA0_INT_VEC_REG, "Internal DMA0 Source"},
+    { EPIC_DMA1_INT_VEC_REG, "Internal DMA1 Source"},
+    { EPIC_MSG_INT_VEC_REG,  "Internal Message Source"},
+    };
+
+VOIDFUNCPTR intVecTbl[MAXVEC];    /* Interrupt vector table */
+
+
+/****************************************************************************
+*  epicInit - Initialize the EPIC registers
+*
+*  This routine resets the Global Configuration Register, thus it:
+*     -  Disables all interrupts
+*     -  Sets epic registers to reset values
+*     -  Sets the value of the Processor Current Task Priority to the
+*        highest priority (0xF).
+*  epicInit then sets the EPIC operation mode to Mixed Mode (vs. Pass
+*  Through or 8259 compatible mode).
+*
+*  If IRQType (input) is Direct IRQs:
+*     - IRQType is written to the SIE bit of the EPIC Interrupt
+*       Configuration register (ICR).
+*     - clkRatio is ignored.
+*  If IRQType is Serial IRQs:
+*     - both IRQType and clkRatio will be written to the ICR register
+*/
+
+void epicInit
+    (
+    unsigned int IRQType,      /* Direct or Serial */
+    unsigned int clkRatio      /* Clk Ratio for Serial IRQs */
+    )
+    {
+    ULONG tmp;
+
+    tmp = sysEUMBBARRead(EPIC_GLOBAL_REG);
+    tmp |= 0xa0000000;                  /* Set the Global Conf. register */
+    sysEUMBBARWrite(EPIC_GLOBAL_REG, tmp);
+    sysEUMBBARWrite(EPIC_GLOBAL_REG, 0x20000000);
+    tmp = sysEUMBBARRead(EPIC_INT_CONF_REG);    /* Read interrupt conf. reg */
+
+    if (IRQType == EPIC_DIRECT_IRQ)             /* direct mode */
+        sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp & 0xf7ffffff);
+    else                                        /* Serial mode */
+        {
+        tmp = (clkRatio << 28) | 0x08000000;    /* Set clock ratio */
+        sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp);
+        }
+
+    while (epicIntAck() != 0xff);       /* Clear all pending interrupts */
+}
+
+/****************************************************************************
+ *  epicIntEnable - Enable an interrupt source
+ *
+ *  This routine clears the mask bit of an external, an internal or
+ *  a Timer register to enable the interrupt.
+ *
+ *  RETURNS:  None
+ */
+void epicIntEnable
+    (
+    int intVec        /* Interrupt Vector Number */
+    )
+    {
+    ULONG tmp;
+    ULONG srAddr;
+
+    srAddr = SrcVecTable[intVec].srcAddr;  /* Retrieve src Vec/Prio register */
+    tmp = sysEUMBBARRead(srAddr);
+    tmp &= 0x7fffffff;             /* Clear the mask bit */
+    sysEUMBBARWrite(srAddr, tmp);
+    return;
+    }
+
+/****************************************************************************
+ *  epicIntDisable - Disable an interrupt source
+ *
+ *  This routine sets the mask bit of an external, an internal or
+ *  a Timer register to disable the interrupt.
+ *
+ *  RETURNS:  OK or ERROR
+ *
+ */
+
+void epicIntDisable
+    (
+    int intVec        /* Interrupt vector number */
+    )
+    {
+
+    ULONG tmp, srAddr;
+
+    srAddr = SrcVecTable[intVec].srcAddr;
+    tmp = sysEUMBBARRead(srAddr);
+    tmp |= 0x80000000;                      /* Set the mask bit */
+    sysEUMBBARWrite(srAddr, tmp);
+    return;
+    }
+
+/****************************************************************************
+ * epicIntSourceConfig - Set properties of an interrupt source
+ *
+ * This function sets interrupt properites (Polarity, Sense, Interrupt
+ * Prority, and Interrupt Vector) of an Interrupt Source.  The properties
+ * can be set when the current source is not in-request or in-service,
+ * which is determined by the Activity bit.  This routine return ERROR
+ * if the the Activity bit is 1 (in-request or in-service).
+ *
+ * This function assumes that the Source Vector/Priority register (input)
+ * is a valid address.
+ *
+ * RETURNS:  OK or ERROR
+ */
+
+int epicIntSourceConfig
+    (
+    int   Vect,                         /* interrupt source vector number */
+    int   Polarity,                     /* interrupt source polarity */
+    int   Sense,                        /* interrupt source Sense */
+    int   Prio                          /* interrupt source priority */
+    )
+
+    {
+    ULONG tmp, newVal;
+    ULONG actBit, srAddr;
+
+    srAddr = SrcVecTable[Vect].srcAddr;
+    tmp = sysEUMBBARRead(srAddr);
+    actBit = (tmp & 40000000) >> 30;    /* retrieve activity bit - bit 30 */
+    if (actBit == 1)
+        return ERROR;
+
+    tmp &= 0xff30ff00;     /* Erase previously set P,S,Prio,Vector bits */
+    newVal = (Polarity << 23) | (Sense << 22) | (Prio << 16) | Vect;
+    sysEUMBBARWrite(srAddr, tmp | newVal );
+    return (OK);
+    }
+
+/****************************************************************************
+ * epicIntAck - acknowledge an interrupt
+ *
+ * This function reads the Interrupt acknowldge register and return
+ * the vector number of the highest pending interrupt.
+ *
+ * RETURNS: Interrupt Vector number.
+ */
+
+unsigned int epicIntAck(void)
+{
+    return(sysEUMBBARRead( EPIC_PROC_INT_ACK_REG ));
+}
+
+/****************************************************************************
+ * epicEOI - signal an end of interrupt
+ *
+ * This function writes 0x0 to the EOI register to signal end of interrupt.
+ * It is usually called after an interrupt routine is served.
+ *
+ * RETURNS: None
+ */
+
+void epicEOI(void)
+    {
+    sysEUMBBARWrite(EPIC_PROC_EOI_REG, 0x0);
+    }
+
+/****************************************************************************
+ *  epicCurTaskPrioSet - sets the priority of the Processor Current Task
+ *
+ *  This function should be called after epicInit() to lower the priority
+ *  of the processor current task.
+ *
+ *  RETURNS:  OK or ERROR
+ */
+
+int epicCurTaskPrioSet
+    (
+    int prioNum                 /* New priority value */
+    )
+    {
+
+    if ( (prioNum < 0) || (prioNum > 0xF))
+        return ERROR;
+    sysEUMBBARWrite(EPIC_PROC_CTASK_PRI_REG, prioNum);
+    return OK;
+    }
+
+
+/************************************************************************
+ * function: epicIntTaskGet
+ *
+ * description: Get value of processor current interrupt task priority register
+ *
+ * note:
+ ***********************************************************************/
+unsigned char epicIntTaskGet()
+{
+  /* get the interrupt task priority register */
+    ULONG reg;
+    unsigned char rec;
+
+    reg = sysEUMBBARRead( EPIC_PROC_CTASK_PRI_REG );
+    rec = ( reg & 0x0F );
+    return rec;
+}
+
+
+/**************************************************************
+ * function: epicISR
+ *
+ * description: EPIC service routine called by the core exception
+ *              at 0x500
+ *
+ * note:
+ **************************************************************/
+unsigned int epicISR(void)
+{
+   return 0;
+}
+
+
+/************************************************************
+ * function: epicModeGet
+ *
+ * description: query EPIC mode, return 0 if pass through mode
+ *                               return 1 if mixed mode
+ *
+ * note:
+ *************************************************************/
+unsigned int epicModeGet(void)
+{
+    ULONG val;
+
+    val = sysEUMBBARRead( EPIC_GLOBAL_REG );
+    return (( val & 0x20000000 ) >> 29);
+}
+
+
+/*********************************************
+ * function: epicConfigGet
+ *
+ * description: Get the EPIC interrupt Configuration
+ *              return 0 if not error, otherwise return 1
+ *
+ * note:
+ ********************************************/
+void epicConfigGet( unsigned int *clkRatio, unsigned int *serEnable)
+{
+    ULONG val;
+
+    val = sysEUMBBARRead( EPIC_INT_CONF_REG );
+    *clkRatio = ( val & 0x70000000 ) >> 28;
+    *serEnable = ( val & 0x8000000 ) >> 27;
+}
+
+
+/*******************************************************************
+ *  sysEUMBBARRead - Read a 32-bit EUMBBAR register
+ *
+ *  This routine reads the content of a register in the Embedded
+ *  Utilities Memory Block, and swaps to big endian before returning
+ *  the value.
+ *
+ *  RETURNS:  The content of the specified EUMBBAR register.
+ */
+
+ULONG sysEUMBBARRead
+    (
+    ULONG regNum
+    )
+    {
+    ULONG temp;
+
+    temp = *(ULONG *) (CFG_EUMB_ADDR + regNum);
+    return ( LONGSWAP(temp));
+    }
+
+/*******************************************************************
+ *  sysEUMBBARWrite - Write a 32-bit EUMBBAR register
+ *
+ *  This routine swaps the value to little endian then writes it to
+ *  a register in the Embedded Utilities Memory Block address space.
+ *
+ *  RETURNS: N/A
+ */
+
+void sysEUMBBARWrite
+    (
+    ULONG regNum,               /* EUMBBAR register address */
+    ULONG regVal                /* Value to be written */
+    )
+    {
+
+    *(ULONG *) (EUMBBAR + regNum) = LONGSWAP(regVal);
+    return ;
+    }
+
+
+/********************************************************
+ * function: epicVendorId
+ *
+ * description: return the EPIC Vendor Identification
+ *              register:
+ *
+ *              siliccon version, device id, and vendor id
+ *
+ * note:
+ ********************************************************/
+void epicVendorId
+   (
+    unsigned int *step,
+    unsigned int *devId,
+    unsigned int *venId
+   )
+   {
+    ULONG val;
+    val = sysEUMBBARRead( EPIC_VENDOR_ID_REG );
+    *step  = ( val & 0x00FF0000 ) >> 16;
+    *devId = ( val & 0x0000FF00 ) >> 8;
+    *venId = ( val & 0x000000FF );
+    }
+
+/**************************************************
+ * function: epicFeatures
+ *
+ * description: return the number of IRQ supported,
+ *              number of CPU, and the version of the
+ *              OpenEPIC
+ *
+ * note:
+ *************************************************/
+void epicFeatures
+    (
+    unsigned int *noIRQs,
+    unsigned int *noCPUs,
+    unsigned int *verId
+    )
+    {
+    ULONG val;
+
+    val = sysEUMBBARRead( EPIC_FEATURES_REG );
+    *noIRQs  = ( val & 0x07FF0000 ) >> 16;
+    *noCPUs  = ( val & 0x00001F00 ) >> 8;
+    *verId   = ( val & 0x000000FF );
+}
+
+
+/*********************************************************
+ * function: epciTmFrequncySet
+ *
+ * description: Set the timer frequency reporting register
+ ********************************************************/
+void epicTmFrequencySet( unsigned int frq )
+{
+    sysEUMBBARWrite(EPIC_TM_FREQ_REG, frq);
+}
+
+/*******************************************************
+ * function: epicTmFrequncyGet
+ *
+ * description: Get the current value of the Timer Frequency
+ * Reporting register
+ *
+ ******************************************************/
+unsigned int epicTmFrequencyGet(void)
+{
+    return( sysEUMBBARRead(EPIC_TM_FREQ_REG)) ;
+}
+
+
+/****************************************************
+ * function: epicTmBaseSet
+ *
+ * description: Set the #n global timer base count register
+ *              return 0 if no error, otherwise return 1.
+ *
+ * note:
+ ****************************************************/
+unsigned int epicTmBaseSet
+    (
+    ULONG srcAddr,         /* Address of the Timer Base register */
+    unsigned int cnt,    /* Base count */
+    unsigned int inhibit   /* 1 - count inhibit */
+    )
+{
+
+    unsigned int val = 0x80000000;
+    /* First inhibit counting the timer */
+    sysEUMBBARWrite(srcAddr, val) ;
+
+    /* set the new value */
+    val = (cnt & 0x7fffffff) | ((inhibit & 0x1) << 31);
+    sysEUMBBARWrite(srcAddr, val) ;
+    return 0;
+}
+
+/***********************************************************************
+ * function: epicTmBaseGet
+ *
+ * description: Get the current value of the global timer base count register
+ *              return 0 if no error, otherwise return 1.
+ *
+ * note:
+ ***********************************************************************/
+unsigned int epicTmBaseGet( ULONG srcAddr, unsigned int *val )
+{
+    *val = sysEUMBBARRead( srcAddr );
+    *val = *val & 0x7fffffff;
+    return 0;
+}
+
+/***********************************************************
+ * function: epicTmCountGet
+ *
+ * description: Get the value of a given global timer
+ *              current count register
+ *              return 0 if no error, otherwise return 1
+ * note:
+ **********************************************************/
+unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val )
+{
+    *val = sysEUMBBARRead( srcAddr );
+    *val = *val & 0x7fffffff;
+    return 0;
+}
+
+
+
+/***********************************************************
+ * function: epicTmInhibit
+ *
+ * description: Stop counting of a given global timer
+ *              return 0 if no error, otherwise return 1
+ *
+ * note:
+ ***********************************************************/
+unsigned int epicTmInhibit( unsigned int srcAddr )
+{
+    ULONG val;
+
+    val = sysEUMBBARRead( srcAddr );
+    val |= 0x80000000;
+    sysEUMBBARWrite( srcAddr, val );
+    return 0;
+}
+
+/******************************************************************
+ * function: epicTmEnable
+ *
+ * description: Enable counting of a given global timer
+ *              return 0 if no error, otherwise return 1
+ *
+ * note:
+ *****************************************************************/
+unsigned int epicTmEnable( ULONG srcAddr )
+{
+    ULONG val;
+
+    val = sysEUMBBARRead( srcAddr );
+    val &= 0x7fffffff;
+    sysEUMBBARWrite( srcAddr, val );
+    return 0;
+}
+
+void epicSourcePrint(int Vect)
+    {
+    ULONG srcVal;
+
+    srcVal = sysEUMBBARRead(SrcVecTable[Vect].srcAddr);
+    PRINT("%s\n", SrcVecTable[Vect].srcName);
+    PRINT("Address   = 0x%lx\n", SrcVecTable[Vect].srcAddr);
+    PRINT("Vector    = %ld\n", (srcVal & 0x000000FF) );
+    PRINT("Mask      = %ld\n", srcVal >> 31);
+    PRINT("Activitiy = %ld\n", (srcVal & 40000000) >> 30);
+    PRINT("Polarity  = %ld\n", (srcVal & 0x00800000) >> 23);
+    PRINT("Sense     = %ld\n", (srcVal & 0x00400000) >> 22);
+    PRINT("Priority  = %ld\n", (srcVal & 0x000F0000) >> 16);
+    }
diff --git a/mpc8240/drivers/epic/epic2.S b/mpc8240/drivers/epic/epic2.S
new file mode 100644 (file)
index 0000000..873b95a
--- /dev/null
@@ -0,0 +1,197 @@
+/**************************************
+ * $Id: epic2.S,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+ *
+ * copyright @ Motorola, 1999
+ *
+ **************************************/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/processor.h>
+
+/*********************************************
+ * function: CoreExtIntEnable
+ *
+ * description: Enable 603e core external interrupt
+ *
+ * note: mtmsr is context-synchronization
+ **********************************************/
+               .text
+               .align 2
+        .global CoreExtIntEnable
+CoreExtIntEnable:
+         mfmsr    r3
+
+         ori      r3,r3,0x8000         /* enable external interrupt */
+         mtmsr    r3
+
+         bclr 20, 0
+
+/*******************************************
+ * function: CoreExtIntDisable
+ * 
+ * description: Disable 603e core external interrupt
+ *
+ * note: 
+ *******************************************/
+               .text
+               .align 2
+        .global CoreExtIntDisable
+CoreExtIntDisable:
+        mfmsr    r4
+
+       xor     r3,r3,r3
+       or      r3,r3,r4
+
+       andis.  r4,r4,0xffff
+        andi.   r3,r3,0x7fff         /* disable external interrupt */
+
+       or      r3,r3,r4
+        mtmsr    r3
+
+        bclr 20, 0
+
+/*********************************************************
+ * function: epicEOI
+ *
+ * description: signal the EOI and restore machine status
+ *       Input: r3 - value of eumbbar
+ *       Output: r3 - value of eumbbar
+ *               r4 - ISR vector value
+ * note:
+ ********************************************************/
+               .text
+               .align 2
+        .global epicEOI
+epicEOI:
+       lis     r5,0x0006               /* Build End Of Interrupt Register offset */
+       ori     r5,r5,0x00b0
+       xor     r7,r7,r7                /* Clear r7 */
+       stwbrx  r7,r5,r3            /* Save r7, writing to this register will
+                                            * intidate the end of processing the
+                                            * highest interrupt.
+                             */
+       sync
+
+       /* ---RESTORE MACHINE STATE */
+       mfmsr   r13                     /* Clear Recoverable Interrupt bit in MSR */
+        or      r7,r7,r13
+
+       andis.  r7,r7,0xffff
+       andi.   r13,r13,0x7ffd  /* (and disable interrupts) */
+       or      r13,r13,r7
+       mtmsr   r13
+
+       lwz   r13,0x1c(r1)      /* pull ctr */
+       mtctr r13
+
+       lwz   r13,0x18(r1)      /* pull xer */
+       mtctr r13
+
+       lwz   r13,0x14(r1)      /* pull lr */
+       mtctr r13
+
+       lwz         r13,0x10(r1)        /* Pull SRR1 from stack */
+       mtspr   SRR1,r13            /* Restore SRR1 */
+
+       lwz         r13,0xc(r1)     /* Pull SRR0 from stack */
+       mtspr   SRR0,r13            /* Restore SRR0 */
+
+       lwz         r13,0x8(r1)     /* Pull User stack pointer from stack */
+       mtspr   SPRG1,r13           /* Restore SPRG1 */
+
+       lwz     r4,0x4(r1)          /* vector value */
+       lwz     r3,0x0(r1)          /* eumbbar */
+       sync
+
+       addi    r1,r1,0x20      /* Deallocate stack */
+       mtspr   SPRG0,r1        /* Save updated Supervisor stack pointer */
+       mfspr   r1,SPRG1        /* Restore User stack pointer */
+
+       bclr     20,0
+
+/***********************************************************
+ * function: exception routine called by exception vector 
+ *           at 0x500, external interrupt
+ *
+ * description: Kahlua EPIC controller
+ *
+ * input:  r3 - content of eumbbar
+ * output: r3 - ISR return value
+ *         r4 - Interrupt vector number
+ * note:
+ ***********************************************************/
+
+       .text
+          .align 2
+       .global epic_exception
+
+epic_exception:
+
+       /*---SAVE MACHINE STATE TO A STACK */
+       mtspr   SPRG1,r1        /* Save User stack pointer to SPRG1 */
+       mfspr   r1,SPRG0        /* Load Supervisor stack pointer into r1 */
+
+       stwu    r3,-0x20(r1)    /* Push the value of eumbbar onto stack */
+
+       mfspr   r3,SPRG1        /* Push User stack pointer onto stack */
+       stw         r3,0x8(r1)
+       mfspr   r3,SRR0     /* Push SRR0 onto stack */
+       stw         r1,0xc(r1)
+       mfspr   r3,SRR1     /* Push SRR1 onto stack */
+       stw         r3,0x10(r1)
+       mflr    r3
+       stw     r3,0x14(r1) /* Push LR */
+       mfxer   r3
+       stw     r3,0x18(r1) /* Push Xer */
+       mfctr   r3
+       stw     r3,0x1c(r1) /* Push CTR */
+
+       mtspr   SPRG0,r1        /* Save updated Supervisor stack pointer 
+                                        * value to SPRG0
+                         */
+       mfmsr   r3              
+       ori         r3,r3,0x0002        /* Set Recoverable Interrupt bit in MSR */
+       mtmsr   r3
+
+       /* ---READ IN THE EUMBAR REGISTER */
+    lwz     r6,0(r1)       /* this is eumbbar */
+    sync
+       
+       /* ---READ EPIC REGISTER:       PROCESSOR INTERRUPT ACKNOWLEDGE REGISTER */
+       lis     r5,0x0006               /* Build Interrupt Acknowledge Register 
+                                            * offset
+                             */
+       ori     r5,r5,0x00a0    
+       lwbrx   r7,r5,r6    /* Load interrupt vector into r7 */
+       sync
+
+       /* --MASK OFF ALL BITS EXCEPT THE VECTOR */
+       xor     r3,r3,r3
+    xor r4,r4,r4             
+       or    r3, r3, r6        /*  eumbbar in r3 */
+       andi. r4,r7,0x00ff      /* Mask off bits, vector in r4 */
+
+    stw     r4,0x04(r1)     /* save the vector value */
+
+    lis     r5,epicISR@ha
+       ori     r5,r5,epicISR@l
+       mtlr    r5
+       blrl
+
+    xor   r30,r30,r30
+       or    r30,r30,r3        /* save the r3 which containts the return value from epicISR */
+
+       /* ---READ IN THE EUMBAR REGISTER */
+    lwz     r3,0(r1)
+    sync
+
+    lis     r5,epicEOI@ha
+       ori     r5,r5,epicEOI@l
+       mtlr    r5
+       blrl
+
+    xor  r3,r3,r3
+       or   r3,r3,r30           /* restore the ISR return value  */
+
+       bclr     20,0
diff --git a/mpc8240/drivers/epic/epicutil.S b/mpc8240/drivers/epic/epicutil.S
new file mode 100644 (file)
index 0000000..72787a5
--- /dev/null
@@ -0,0 +1,59 @@
+/**************************************
+ * $Id: epicutil.S,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+ *
+ * copyright @ Motorola, 1999
+ *
+ *
+ * This file contains two commonly used
+ * lower level utility routines.
+ *
+ * The utility routines are also in other 
+ * Kahlua device driver libraries. The 
+ * need to be linked in only once.
+ **************************************/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+/**********************************************************
+ * function: load_runtime_reg
+ *
+ * input:  r3 - value of eumbbar
+ *         r4 - register offset in embedded utility space
+ *
+ * output: r3 - register content
+ **********************************************************/
+      .text
+      .align 2
+      .global load_runtime_reg
+
+load_runtime_reg:
+            
+                 xor r5,r5,r5
+          or  r5,r5,r3       /* save eumbbar */
+
+             lwbrx     r3,r4,r5
+             sync
+
+             bclr 20, 0
+
+/****************************************************************
+ * function: store_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ *        r4 - register offset in embedded utility space
+ *        r5 - new value to be stored 
+ *
+ ****************************************************************/
+           .text
+           .align 2
+           .global store_runtime_reg
+store_runtime_reg:
+
+                 xor r0,r0,r0
+
+             stwbrx r5,  r4, r3
+             sync
+
+                 bclr   20,0
+
diff --git a/mpc8240/drivers/errors.h b/mpc8240/drivers/errors.h
new file mode 100644 (file)
index 0000000..aa707f0
--- /dev/null
@@ -0,0 +1,218 @@
+/*     Copyright Motorola, Inc. 1993, 1994
+       ALL RIGHTS RESERVED
+
+       You are hereby granted a copyright license to use, modify, and 
+       distribute the SOFTWARE so long as this entire notice is retained 
+       without alteration in any modified and/or redistributed versions, 
+       and that such modified versions are clearly identified as such.  
+       No licenses are granted by implication, estoppel or otherwise under 
+       any patents or trademarks of Motorola, Inc.
+
+       The SOFTWARE is provided on an "AS IS" basis and without warranty.  
+       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS 
+       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED 
+       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
+       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH 
+       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS 
+       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. 
+
+       To the maximum extent permitted by applicable law, IN NO EVENT SHALL 
+       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 
+       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF 
+       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS 
+       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR 
+       INABILITY TO USE THE SOFTWARE.   Motorola assumes no responsibility 
+       for the maintenance and support of the SOFTWARE.  
+
+*/
+
+
+#include "config.h"
+
+/*
+         1         2         3         4         5         6         7         8
+01234567890123456789012345678901234567890123456789012345678901234567890123456789
+*/
+/* List define statements here */
+
+/* These are for all the toolboxes and functions to use. These will help
+to standardize the error handling in the current project */
+
+                               /* this is the "data type" for the error
+                               messages in the system */
+#define STATUS unsigned int
+
+                               /* this is a success status code */
+#define SUCCESS 1
+
+                               /* likewise this is failure */
+#define FAILURE 0
+
+#define NUM_ERRORS 47
+
+/* This first section of "defines" are for error codes ONLY.  The called
+   routine will return one of these error codes to the caller.  If the final
+   returned code is "VALID", then everything is a-okay.  However, if one
+   of the functions returns a non-valid status, that error code should be
+   propogated back to all the callers.  At the end, the last caller will
+   call an error_processing function, and send in the status which was
+   returned.  It's up to the error_processing function to determine which
+   error occured (as indicated by the status), and print an appropriate
+   message back to the user.
+*/
+/*----------------------------------------------------------------------*/
+/* these are specifically for the parser routines                      */
+
+#define UNKNOWN_COMMAND                0xfb00 /* "unrecognized command " */
+#define UNKNOWN_REGISTER       0xfb01 /* "unknown register "*/
+#define ILLEGAL_RD_STAGE       0xfb02 /* cannot specify reg. family in range*/
+#define ILLEGAL_REG_FAMILY     0xfb03 /* "cannot specify a range of special
+                                       or miscellaneous registers"*/
+#define RANGE_CROSS_FAMILY     0xfb04 /* "cannot specify a range across
+                                       register families" */
+#define UNIMPLEMENTED_STAGE    0xfb05 /* invalid rd or rmm parameter format */
+#define REG_NOT_WRITEABLE      0xfb06 /* "unknown operator in arguements"*/
+#define INVALID_FILENAME       0xfb07 /* "invalid download filename" */
+#define INVALID_BAUD_RATE      0xfb08  /* invalid baud rate from sb command */
+#define UNSUPPORTED_REGISTER   0xfb09  /* Special register is not supported */
+#define FOR_BOARD_ONLY         0xfb0a  /* "Not available for Unix." */
+
+
+
+/*----------------------------------------------------------------------*/
+/* these are for the error checking toolbox                            */
+
+#define INVALID                        0xfd00 /* NOT valid */
+#define VALID                  0xfd01 /* valid */
+
+                                       /* This error is found in the fcn:
+                                       is_right_size_input() to indicate
+                                       that the input was not 8 characters
+                                       long.  */
+#define INVALID_SIZE           0xfd02
+
+                                       /* This error is found in the fcn:
+                                       is_valid_address_range() to indicate
+                                       that the address given falls outside
+                                       of valid memory defined by MEM_START
+                                       to MEM_END.
+                                       */
+#define OUT_OF_BOUNDS_ADDRESS  0xfd03
+
+                                       /* This error is found in the fcn:
+                                       is_valid_hex_input() to indicate that 
+                                       one of more of the characters entered
+                                       are not valid hex characters.  Valid
+                                       hex characters are 0-9, A-F, a-f.
+                                       */
+#define INVALID_HEX_INPUT      0xfd04
+
+                                       /* This error is found in the fcn:
+                                       is_valid_register_number() to indicate
+                                       that a given register does not exist.
+                                       */
+#define REG_NOT_READABLE       0xfd05
+
+                                       /* This error is found in the fcn:
+                                       is_word_aligned_address() to indicate
+                                       that the given address is not word-
+                                       aligned.  A word-aligned address ends
+                                       in 0x0,0x4,0x8,0xc.
+                                       */
+#define        NOT_WORD_ALIGNED        0xfd07
+
+                                       /* This error is found in the fcn:
+                                       is_valid_address_range() to indicate
+                                       that the starting address is greater
+                                       than the ending address.
+                                       */
+#define REVERSED_ADDRESS       0xfd08
+
+                                       /* this error tells us that the address
+                                       specified as the destination is within 
+                                       the source addresses  */
+#define RANGE_OVERLAP          0xfd09
+                                       
+
+#define        ERROR                   0xfd0a /* An error occured */
+#define INVALID_PARAM          0xfd0b /* "invalid input parameter " */
+
+
+#define INVALID_FLAG           0xfd0c  /* invalid flag */ 
+
+/*----------------------------------------------------------------------*/
+/* these are for the getarg toolbox                                    */
+
+#define INVALID_NUMBER_ARGS    0xFE00 /* invalid number of commd arguements */
+#define UNKNOWN_PARAMETER      0xFE01 /* "unknown type of parameter "*/
+
+
+
+
+
+/*----------------------------------------------------------------------*/
+/* these are for the tokenizer toolbox                                         */
+
+#define ILLEGAL_CHARACTER      0xFF00 /* unrecognized char. in input stream*/
+#define TTL_NOT_SORTED                 0xFF01 /* token translation list not sorted */
+#define TTL_NOT_DEFINED        0xFF02 /* token translation list not assigned*/
+#define INVALID_STRING                 0xFF03 /* unable to extract string from input */
+#define BUFFER_EMPTY           0xFF04 /* "input buffer is empty" */
+#define INVALID_MODE           0xFF05 /* input buf is in an unrecognized mode*/
+#define TOK_INTERNAL_ERROR     0xFF06 /* "internal tokenizer error" */
+#define TOO_MANY_IBS           0xFF07 /* "too many open input buffers" */
+#define NO_OPEN_IBS            0xFF08 /* "no open input buffers" */
+
+
+
+/* these are for the read from screen toolbox */
+
+#define RESERVED_WORD          0xFC00 /* used a reserved word as an arguement*/
+
+
+/* these are for the breakpoint routines */
+
+#define FULL_BPDS              0xFA00 /* breakpoint data structure is full */
+
+
+
+/* THESE are for the downloader */
+
+#define NOT_IN_S_RECORD_FORMAT         0xf900 /* "not in S-Record Format" */
+#define UNREC_RECORD_TYPE      0xf901 /* "unrecognized record type" */
+#define CONVERSION_ERROR       0xf902 /* "ascii to int conversion error" */
+#define INVALID_MEMORY         0xf903 /* "bad s-record memory address " */
+
+
+/* these are for the compression and decompression stuff */
+
+#define COMP_UNK_CHARACTER     0xf800 /* "unknown compressed character " */
+                                       
+#define COMP_UNKNOWN_STATE     0xf801 /* "unknown binary state" */
+       
+#define NOT_IN_COMPRESSED_FORMAT 0xf802 /* not in compressed S-Record format */
+
+
+/* these are for the DUART handling things */
+
+                                       /* "unrecognized serial port configuration" */
+#define UNKNOWN_PORT_STATE     0xf700
+
+
+/* these are for the register toolbox */
+
+                                       /* "cannot find register in special
+                                        purpose register file " */
+#define SPR_NOT_FOUND          0xf600
+
+
+/* these are for the duart specific stuff */
+
+                                       /* "transparent mode needs access to
+                                               two serial ports" */
+#define TM_NEEDS_BOTH_PORTS    0xf500
+
+/*----------------------------------------------------------------------*/
+/* these are specifically for the flash routines                       */
+#define FLASH_ERROR            0xf100          /* general flash error */
diff --git a/mpc8240/drivers/i2c/Makefile b/mpc8240/drivers/i2c/Makefile
new file mode 100644 (file)
index 0000000..faf599b
--- /dev/null
@@ -0,0 +1,134 @@
+##########################################################################
+#
+# $Id: Makefile,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and 
+#       distribute the SOFTWARE so long as this entire notice is retained 
+#       without alteration in any modified and/or redistributed versions, 
+#       and that such modified versions are clearly identified as such.  
+#       No licenses are granted by implication, estoppel or otherwise under 
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.  
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS 
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED 
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH 
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS 
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. 
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL 
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF 
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS 
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR 
+#       INABILITY TO USE THE SOFTWARE. 
+#
+# $Log: Makefile,v $
+# Revision 1.1  2000/11/20 17:22:33  wdenk
+#
+# * Added support for MBX860T (thanks to Rob Taylor)
+#
+# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+#   Work In Progress (TM); current status: boots to command line input.
+#   EPIC code non-functional (interrupts disabled), No net, No IDE.
+#
+# * Add support for Status LED
+#
+# * Optionally panic() to reboot instead of hanging
+#
+# * Misc bug fixes
+#
+# * All frequencies in HZ now (internally)
+#
+# * Add support for BOOTP Domain Name Server Option
+#
+# Revision 1.1.1.1  2000/11/14 16:54:07  robt
+# no message
+#
+# Revision 1.1.1.1  2000/11/14 14:49:39  robt
+# no message
+#
+# Revision 1.4  1999/04/29 13:41:07  charliem
+# Capture first pass at modifications to the I2C interface.  This version is
+# correct, but there are some additional modifications to be implemented.
+# Nothing but I2C should be affected.
+#
+# Revision 1.3  1999/02/11 23:14:58  wyin
+# Added MasterRcvAddress variable to handle master receiver address phase
+#
+# Revision 1.2  1999/02/05 01:55:47  wyin
+# modified to set up soft link for hearder files
+# compilable version with dink
+#
+# Revision 1.1  1999/02/03 18:58:32  wyin
+# Base line
+#
+# Revision 1.12  1998/11/20 01:34:55  wyin
+# Added INTMEM function and data structure.
+# Enabled DCACHE.
+# There is a minor problem with DCACHE, the cache policy had to be write-through.
+# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length.
+# But consequence measurement is fine.
+#
+#
+############################################################################
+TARGET = libi2c.a
+
+#DEBUG  = -g
+DEBUG   = -DI2CDBG
+LST     = -Hanno -S
+OPTIM   = 
+CC      = /risc/tools/pkgs/metaware/bin/hcppc 
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc 
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG = -l -fm
+AS      = /risc/tools/pkgs/metaware/bin/asppc
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -q -Qn -r
+LKCMD   =
+LINK    =  /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = i2c1.o i2c2.o
+
+all: $(TARGET)
+
+objects: $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+clean: 
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+     
+.s.o:  
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:  
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+i2c1.o: i2c_export.h i2c.h i2c1.c
+
+i2c2.o: i2c.h i2c2.s
diff --git a/mpc8240/drivers/i2c/Makefile_pc b/mpc8240/drivers/i2c/Makefile_pc
new file mode 100644 (file)
index 0000000..5fe9f7e
--- /dev/null
@@ -0,0 +1,143 @@
+##########################################################################
+#
+#       makefile_pc for use with PC mksnt tools  dink32/drivers/i2c
+# $Id: Makefile_pc,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and 
+#       distribute the SOFTWARE so long as this entire notice is retained 
+#       without alteration in any modified and/or redistributed versions, 
+#       and that such modified versions are clearly identified as such.  
+#       No licenses are granted by implication, estoppel or otherwise under 
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.  
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS 
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED 
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH 
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS 
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. 
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL 
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF 
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS 
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR 
+#       INABILITY TO USE THE SOFTWARE. 
+#
+# $Log: Makefile_pc,v $
+# Revision 1.1  2000/11/20 17:22:33  wdenk
+#
+# * Added support for MBX860T (thanks to Rob Taylor)
+#
+# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+#   Work In Progress (TM); current status: boots to command line input.
+#   EPIC code non-functional (interrupts disabled), No net, No IDE.
+#
+# * Add support for Status LED
+#
+# * Optionally panic() to reboot instead of hanging
+#
+# * Misc bug fixes
+#
+# * All frequencies in HZ now (internally)
+#
+# * Add support for BOOTP Domain Name Server Option
+#
+# Revision 1.1.1.1  2000/11/14 16:54:07  robt
+# no message
+#
+# Revision 1.1.1.1  2000/11/14 14:49:39  robt
+# no message
+#
+# Revision 1.1  1999/06/11 20:05:13  maurie
+# support for compiling dink on PC
+#
+# Revision 1.4  1999/04/29 13:41:07  charliem
+# Capture first pass at modifications to the I2C interface.  This version is
+# correct, but there are some additional modifications to be implemented.
+# Nothing but I2C should be affected.
+#
+# Revision 1.3  1999/02/11 23:14:58  wyin
+# Added MasterRcvAddress variable to handle master receiver address phase
+#
+# Revision 1.2  1999/02/05 01:55:47  wyin
+# modified to set up soft link for hearder files
+# compilable version with dink
+#
+# Revision 1.1  1999/02/03 18:58:32  wyin
+# Base line
+#
+# Revision 1.12  1998/11/20 01:34:55  wyin
+# Added INTMEM function and data structure.
+# Enabled DCACHE.
+# There is a minor problem with DCACHE, the cache policy had to be write-through.
+# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length.
+# But consequence measurement is fine.
+#
+#
+############################################################################
+TARGET = libi2c.a
+
+#DEBUG  = -g
+DEBUG   = -DI2CDBG
+LST     = -Hanno -S
+OPTIM   = 
+CC      = m:/old_tools/tools/hcppc/bin/hcppc 
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc 
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG = -l -fm
+AS      = m:/old_tools/tools/hcppc/bin/asppc 
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -q -Qn -r
+LKCMD   =
+LINK    = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = i2c1.o i2c2.o
+
+all: $(TARGET)
+
+objects: $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+clean: 
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+     
+.s.o:  
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:  
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+i2c1.o: i2c_export.h i2c.h i2c1.c
+       $(CCobj) $<
+
+
+i2c2.o: i2c.h i2c2.s
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
diff --git a/mpc8240/drivers/i2c/README b/mpc8240/drivers/i2c/README
new file mode 100644 (file)
index 0000000..73e211d
--- /dev/null
@@ -0,0 +1,105 @@
+CONTENT:
+
+   i2c.h
+   i2c1.c
+   i2c2.s
+
+WHAT ARE THESE FILES:
+
+These files contain MPC8240 (Kahlua) I2C 
+driver routines. The driver routines are not 
+written for any specific operating system. 
+They serves the purpose of code sample, and 
+jump-start for using the MPC8240 I2C unit.
+
+For the reason of correctness of C language
+syntax, these files are compiled by Metaware
+C compiler and assembler.
+
+ENDIAN NOTATION:
+
+The algorithm is designed for big-endian mode,
+software is responsible for byte swapping.
+
+USAGE:
+
+1. The host system that is running on MPC8240 
+   shall link the files listed here. The memory 
+   location of driver routines shall take into 
+   account of that driver routines need to run 
+   in supervisor mode and they process I2C 
+   interrupt.
+
+2. The host system is responsible for configuring
+   the MPC8240 including Embedded Utilities Memory 
+   Block. All I2C driver functions require the
+   content of Embedded Utilities Memory Block
+   Base Address Register, EUMBBAR, as the first
+   parameter.
+
+3. Before I2C unit of MPC8240 can be used,
+   initialize I2C unit by calling I2C_Init 
+   with the corresponding parameters.
+
+   Note that the I2CFDR register shall be written
+   once during the initialization. If it is written
+   in the midst of transers, or after I2C STOPs or
+   REPEAT STATRs, depending on the data written,
+   a long reset time may be encountered.
+
+4. After I2C unit has been successfully initialized,
+   use the Application level API to send data or 
+   receive data upon the desired mode, Master or 
+   Slave.
+
+5. If the host system is also using the EPIC unit
+   on MPC8240, the system can register the
+   I2C_ISR with the EPIC including other
+   desired resources.  
+
+   If the host system does not using the EPIC unit
+   on MPC8240, I2C_Timer_Event function can
+   be called for each desired time interval.
+
+   In both cases, the host system is free to provide
+   its own timer event handler and interrupt service 
+   routine.
+
+6. The I2C driver routines contains a set 
+   of utilities, Set and Get, for host system
+   to query and modify the desired I2C registers.
+  
+7. It is the host system's responsibility of
+   queueing the I2C I/O request. The host 
+   system shall check the I2C_ISR return code 
+   for I2C I/O status. If I2C_ISR returns 
+   I2CBUFFEMPTY or I2CBUFFFULL, it means 
+   I2C unit has completed a I/O request 
+   stated by the Application API.
+   
+8. If the host system has more than one master
+   mode I2C unit I/O requests but doesn't want 
+   to be intervented by being addressed as slave, 
+   the host system can use the master mode 
+   Application API with stop_flag set to 0 in 
+   conjunction with is_cnt flag set to 1. 
+   The first API call sets both stop_flag and 
+   is_cnt to 0, indicating a START condition 
+   shall be generated but when the end of 
+   transaction is reached, do not generate a 
+   STOP condition. Once the host system is 
+   informed that the transaction has been 
+   completed, the next Application API call
+   shall set is_cnt flag to 1, indicating a 
+   repeated START condition shall be generated. 
+   The last Application API call shall set 
+   stop_flag
+   to 1.
+
+9. The I2C_Timer_Event function containes
+   a user defined function pointer. It 
+   serves the purpose of providing the 
+   host system a way to use its own event
+   handler instead of the I2C_ISR provided
+   here. 
+   
diff --git a/mpc8240/drivers/i2c/i2c.h b/mpc8240/drivers/i2c/i2c.h
new file mode 100644 (file)
index 0000000..2482033
--- /dev/null
@@ -0,0 +1,364 @@
+#ifndef I2C_H
+#define I2C_H
+
+/****************************************************
+ * $Id: i2c.h,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+ *
+ * Copyright Motrola 1999
+ *
+ * $Log: i2c.h,v $
+ * Revision 1.1  2000/11/20 17:22:33  wdenk
+ *
+ * * Added support for MBX860T (thanks to Rob Taylor)
+ *
+ * * Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+ *   Work In Progress (TM); current status: boots to command line input.
+ *   EPIC code non-functional (interrupts disabled), No net, No IDE.
+ *
+ * * Add support for Status LED
+ *
+ * * Optionally panic() to reboot instead of hanging
+ *
+ * * Misc bug fixes
+ *
+ * * All frequencies in HZ now (internally)
+ *
+ * * Add support for BOOTP Domain Name Server Option
+ *
+ * Revision 1.1.1.1  2000/11/14 16:54:07  robt
+ * no message
+ *
+ * Revision 1.1.1.1  2000/11/14 14:49:39  robt
+ * no message
+ *
+ * Revision 1.7  1999/04/30 16:25:50  charliem
+ * Change the DINK to I2C_do_transaction interface to allow the application
+ * to specify the data address as a parameter to I2C_do_transaction, rather
+ * than putting the data address into the first byte of the buffer.
+ * There is a work-around in I2C_do_transaction in this version, see comments
+ * in the i2c1.c code.
+ *
+ * Revision 1.6  1999/04/29 13:41:03  charliem
+ * Capture first pass at modifications to the I2C interface.  This version is
+ * correct, but there are some additional modifications to be implemented.
+ * Nothing but I2C should be affected.
+ *
+ * Revision 1.5  1999/02/12 20:08:28  wyin
+ * Use I2C's offset as the I2CStatus base value
+ *
+ * Revision 1.4  1999/02/12 15:02:23  wyin
+ * Added I2CADDRESS constant for better information
+ * exchange to apps.
+ *
+ * Revision 1.3  1999/02/10 01:48:27  wyin
+ * Modified the way of Master Rcv generating STOP. Setting TXAK bit to 1 will
+ * not automatically generat STOP. BOOK VI is wrong.
+ *
+ * Revision 1.2  1999/02/05 01:55:44  wyin
+ * modified to set up soft link for hearder files
+ * compilable version with dink
+ *
+ * Revision 1.1  1999/02/03 18:58:30  wyin
+ * Base line
+ *
+ ****************************************************/
+
+#define I2CADR    0x00003000
+#define I2CFDR    0x00003004
+#define I2CCR     0x00003008
+#define I2CSR     0x0000300C
+#define I2CDR     0x00003010
+
+typedef enum _i2cstatus
+{
+ I2CSUCCESS     = 0x3000,
+ I2CADDRESS,
+ I2CERROR,
+ I2CBUFFFULL,
+ I2CBUFFEMPTY,
+ I2CXMITERROR,
+ I2CRCVERROR,
+ I2CBUSBUSY,
+ I2CALOSS,
+ I2CNOEVENT,
+} I2CStatus;
+
+typedef enum i2c_control 
+{
+ MEN  = 0x00000080,
+ MIEN = 0x00000040,
+ MSTA = 0x00000020,
+ MTX  = 0x00000010,
+ TXAK = 0x00000008,
+ RSTA = 0x00000004,
+} I2C_CONTROL;
+
+typedef enum i2c_status
+{
+  MCF   =  0x00000080,
+  MAAS  =  0x00000040,
+  MBB   =  0x00000020,
+  MAL   =  0x00000010,
+  SRW   =  0x00000004,
+  MIF   =  0x00000002,
+  RXAK  =  0x00000001,
+} I2C_STATUS;
+
+typedef struct _i2c_ctrl
+{
+       unsigned int reserved0 : 24;
+       unsigned int men       : 1;
+       unsigned int mien      : 1;
+       unsigned int msta      : 1;
+       unsigned int mtx       : 1;
+       unsigned int txak      : 1;
+       unsigned int rsta      : 1;
+       unsigned int reserved1 : 2;
+} I2C_CTRL;
+
+typedef struct _i2c_stat
+{
+       unsigned int rsrv0    : 24;
+       unsigned int mcf      : 1;
+       unsigned int maas     : 1;
+       unsigned int mbb      : 1;
+       unsigned int mal      : 1;
+       unsigned int rsrv1    : 1;
+       unsigned int srw      : 1;
+       unsigned int mif      : 1;
+       unsigned int rxak     : 1;
+} I2C_STAT;
+
+typedef enum _i2c_mode
+{
+       RCV =  0,
+       XMIT = 1,
+} I2C_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application 
+ * to use the funcitonality provided by I2C driver
+ * 
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we just transfer whatever
+ *       we are given
+ **************************************************/
+/**
+ * Note:
+ *
+ * In all following functions,
+ * the caller shall pass the configured embedded utility memory
+ * block base, EUMBBAR.
+ **/
+
+/* Send a buffer of data to the intended rcv_addr. 
+ * If stop_flag is set, after the whole buffer 
+ * is sent, generate a STOP signal provided that the
+ * receiver doesn't signal the STOP in the middle.
+ * I2C is the master performing transmitting. If
+ * no STOP signal is generated at the end of current
+ * transaction, the master can generate a START signal
+ * to another slave addr.
+ *
+ * return I2CSUCCESS if no error.
+ */
+static I2CStatus I2C_put( unsigned int  eumbbar,
+                                                 unsigned char rcv_addr,    /* receiver's address */
+                             unsigned char *buffer_ptr, /* pointer of data to be sent */
+                                             unsigned int  length,      /* number of byte of in the buffer */
+                                             unsigned int  stop_flag,   /* 1 - signal STOP when buffer is empty
+                                                                         * 0 - no STOP signal when buffer is empty
+                                                                                                 */
+                                                 unsigned int  is_cnt );    /* 1 - this is a restart, don't check MBB
+                                                      * 0 - this is a new start, check MBB
+                                                                                                         */
+                                                
+/* Receive a buffer of data from the desired sender_addr
+ * If stop_flag is set, when the buffer is full and the 
+ * sender does not signal STOP, generate a STOP signal.
+ * I2C is the master performing receiving. If no STOP signal
+ * is generated, the master can generate a START signal
+ * to another slave addr.
+ *
+ * return I2CSUCCESS if no error. 
+ */
+static I2CStatus I2C_get( unsigned int  eumbbar,
+                                                 unsigned char sender_addr, /* sender's address */
+                                             unsigned char *buffer_ptr, /* pointer of receiving buffer */
+                                         unsigned int  length,      /* length of the receiving buffer */
+                                             unsigned int  stop_flag,   /* 1 - signal STOP when buffer is full
+                                                                         * 0 - no STOP signal when buffer is full 
+                                                                                                     */
+                                                 unsigned int  is_cnt );    /* 1 - this is a restart, don't check MBB
+                                                      * 0 - this is a new start, check MBB
+                                                                                                         */
+
+#if 0 /* the I2C_write and I2C_read functions are not active */
+/* Send a buffer of data to the requiring master. 
+ * If stop_flag is set, after the whole buffer is sent,
+ * generate a STOP signal provided that the requiring 
+ * receiver doesn't signal the STOP in the middle.
+ * I2C is the slave performing transmitting.
+ *
+ * return I2CSUCCESS if no error.
+ *
+ * Note: due to the Kahlua design, slave transmitter
+ *       shall not signal STOP since there is no way
+ *       for master to detect it, causing I2C bus hung.
+ *
+ *       For the above reason, the stop_flag is always
+ *       set, i.e., 1.
+ *
+ *       programmer shall use the timer on Kahlua to 
+ *       control the interval of data byte at the 
+ *       master side.
+ */
+static I2CStatus I2C_write( unsigned int eumbbar,
+                                                   unsigned char *buffer_ptr, /* pointer of data to be sent */
+                                               unsigned int  length,      /* number of byte of in the buffer */
+                                               unsigned int  stop_flag ); /* 1 - signal STOP when buffer is empty
+                                                                                       * 0 - no STOP signal when buffer is empty
+                                                                                                   */
+
+ /* Receive a buffer of data from the sending master.
+ * If stop_flag is set, when the buffer is full and the 
+ * sender does not signal STOP, generate a STOP signal.
+ * I2C is the slave performing receiving.
+ *
+ * return I2CSUCCESS if no error. 
+ */
+static I2CStatus I2C_read(unsigned int  eumbbar,
+                                                 unsigned char *buffer_ptr, /* pointer of receiving buffer */
+                                             unsigned int  length,      /* length of the receiving buffer */
+                                         unsigned int  stop_flag ); /* 1 - signal STOP when buffer is full
+                                                                         * 0 - no STOP signal when buffer is full 
+                                                                                                     */
+#endif /* of if0 for turning off I2C_read & I2C_write */
+                                               
+/* if interrupt is not used, this is the timer event handler.
+ * After each fixed time interval, this function can be called
+ * to check the I2C status and call appropriate function to
+ * handle the status event.
+ */
+static I2CStatus I2C_Timer_Event( unsigned int eumbbar, I2CStatus (*handler)( unsigned int ) );
+
+/********************* Kernel API ************************
+ * Kernel APIs are functions I2C driver provides to the
+ * O.S.
+ *********************************************************/
+
+/******************* device I/O function ***************/
+
+/*  Generate a START signal in the desired mode.
+ *  I2C is the master.
+ *
+ * return I2CSUCCESS if no error.
+ *        I2CERROR   if i2c unit is not enabled.
+ *        I2CBUSBUSY if bus cannot be granted
+ */
+static I2CStatus I2C_Start( unsigned int  eumbbar,
+                                                   unsigned char slave_addr, /* address of the receiver */ 
+                               I2C_MODE     mode,       /* XMIT(1) - put (write)
+                                                                                 * RCV(0)  - get (read)
+                                                                                                         */
+                                                   unsigned int is_cnt ); /* 1 - this is a restart, don't check MBB
+                                                                                                       * 0 - this is a new start, check MBB
+                                                    */
+
+/* Generate a STOP signal to terminate the transaction. */
+static I2CStatus I2C_Stop( unsigned int eumbbar );
+
+/*  Do a one-byte master transmit.
+ *
+ *  return I2CBUFFEMPTY if this is the last byte.
+ *  Otherwise return I2CSUCCESS
+ */
+static I2CStatus I2C_Master_Xmit( unsigned int eumbbar );
+                                                              
+/*  Do a one-byte master receive.
+ *
+ *  return I2CBUFFFULL if this is the last byte.
+ *  Otherwise return I2CSUCCESS
+ */
+static I2CStatus I2C_Master_Rcv( unsigned int eumbbar );
+                                                             
+/*  Do a one-byte slave transmit.
+ *
+ *  return I2CBUFFEMPTY if this is the last byte.
+ *  Otherwise return I2CSUCCESS
+ *
+ */
+static I2CStatus I2C_Slave_Xmit( unsigned int eumbbar );
+                                                             
+/* Do a one-byte slave receive.
+ *
+ *  return I2CBUFFFULL if this is the last byte.
+ *  Otherwise return I2CSUCCESS   
+ */
+static I2CStatus I2C_Slave_Rcv( unsigned int eumbbar  );
+                                                           
+/* Process slave address phase.
+ *
+ * return I2CADDRESS if this is slave receiver's address phase
+ * Otherwise return the result of slave xmit one byte.
+ */
+static I2CStatus I2C_Slave_Addr( unsigned int eumbbar );
+
+/******************* Device Control Fucntion ****************/
+/*  Initialize I2C unit with desired frequency divider,
+ *  driver's slave address w/o interrupt enabled.
+ *
+ *  This function must be called before I2C unit can
+ *  be used.
+ */
+static I2CStatus I2C_Init( unsigned int  eumbbar,
+                                                  unsigned char fdr,       /* frequency divider */ 
+                              unsigned char addr,      /* driver's address used for receiving */
+                                          unsigned int en_int);    /* 1 - enable I2C interrupt 
+                                                                        * 0 - disable I2C interrup 
+                                                                                                */
+
+/* I2C interrupt service routine.
+ *
+ * return I2CADDRESS if it is receiver's (either master or slave) address phase.
+ * return the result of xmit or receive one byte
+ */
+static I2CStatus I2C_ISR(unsigned int eumbbar  );
+                                             
+/* Set I2C Status, i.e., write to I2CSR */
+static void I2C_Set_Stat( unsigned int eumbbar, I2C_STAT stat );
+
+/* Query I2C Status, i.e., read I2CSR */
+static I2C_STAT I2C_Get_Stat( unsigned int eumbbar );
+
+/* Change I2C Control bits, i.e., write to I2CCR */
+static void I2C_Set_Ctrl( unsigned int eumbbar, I2C_CTRL ); /* new control value */
+
+/* Query I2C Control bits, i.e., read I2CCR */
+static I2C_CTRL I2C_Get_Ctrl( unsigned int eumbbar );
+
+/* This function performs the work for I2C_do_transaction.  The work is
+ * split into this function to enable I2C_do_transaction to first transmit
+ * the data address to the I2C slave device without putting the data address
+ * into the first byte of the buffer.
+ *
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * i2c_addr is the I2C address of the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+static I2C_Status I2C_do_buffer( I2C_INTERRUPT_MODE en_int,
+                                 I2C_TRANSACTION_MODE act,
+                                 unsigned char i2c_addr,
+                                 int len,
+                                 unsigned char *buffer,
+                                 I2C_STOP_MODE stop,
+                                 int retry,
+                                 I2C_RESTART_MODE rsta);
+#endif
diff --git a/mpc8240/drivers/i2c/i2c1.c b/mpc8240/drivers/i2c/i2c1.c
new file mode 100644 (file)
index 0000000..b63e633
--- /dev/null
@@ -0,0 +1,1140 @@
+/*************************************************************
+ * $Id: i2c1.c,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+ *
+ * Copyright @ Motorola, 1999
+ *
+ ************************************************************/
+#include "i2c_export.h"
+#include "i2c.h"
+
+
+/* Define a macro to use an optional application-layer print function, if
+ * one was passed to the I2C library during initialization.  If there was
+ * no function pointer passed, this protects against calling it.  Also define
+ * the global variable that holds the passed pointer.
+ */
+#define PRINT if ( app_print ) app_print
+static int (*app_print)(char *,...);
+        
+/******************* Internal to I2C Driver *****************/
+static unsigned int ByteToXmit = 0;
+static unsigned int XmitByte = 0;
+static unsigned char *XmitBuf = 0;
+static unsigned int XmitBufEmptyStop =0;
+static unsigned int ByteToRcv = 0;
+static unsigned int RcvByte = 0;
+static unsigned char *RcvBuf = 0;
+static unsigned int RcvBufFulStop = 0;
+static unsigned int MasterRcvAddress = 0;
+
+/* Set by call to get_eumbbar during I2C_Initialize.
+ * This could be globally available to the I2C library, but there is
+ * an advantage to passing it as a parameter: it is already in a register
+ * and doesn't have to be loaded from memory.  Also, that is the way the
+ * I2C library was already implemented and I don't want to change it without
+ * a more detailed analysis.
+ * It is being set as a global variable in I2C_Initialize to hide it from 
+ * the DINK application layer, because it is Kahlua-specific.  I think that 
+ * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in
+ * a Kahlua-specific library dealing with the embedded utilities memory block.
+ * Right now, get_eumbbar is defined in dink32/kahlua.s.  The other two are
+ * defined in dink32/drivers/i2c/i2c2.s.
+ */
+static unsigned int Global_eumbbar = 0;
+extern unsigned int get_eumbbar();
+
+extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
+#pragma Alias( load_runtime_reg, "load_runtime_reg" )
+
+extern unsigned int store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
+#pragma Alias( store_runtime_reg, "store_runtime_reg" )
+
+/************************** API *****************/
+
+/* Application Program Interface (API) are the calls provided by the I2C 
+ * library to upper layer applications (i.e., DINK) to access the Kahlua
+ * I2C bus interface.  The functions and values that are part of this API
+ * are declared in i2c_export.h.
+ */
+
+/*  Initialize I2C unit with the following:
+ *  driver's slave address
+ *  interrupt enabled
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  desired clock rate
+ *  digital filter frequency sampling rate
+ *
+ *  This function must be called before I2C unit can be used.
+ */
+I2C_Status I2C_Initialize(
+        unsigned char addr,
+        I2C_INTERRUPT_MODE en_int,
+        int (*p)(char *,...))
+{
+  I2CStatus status;
+  /* establish the pointer, if there is one, to the application's "printf" */
+  app_print = p;
+
+  /* If this is the first call, get the embedded utilities memory block
+   * base address.  I'm not sure what to do about error handling here:
+   * if a non-zero value is returned, accept it.
+   */
+  if ( Global_eumbbar == 0)
+     Global_eumbbar = get_eumbbar();
+  if ( Global_eumbbar == 0)
+  {
+    PRINT( "I2C_Initialize: can't find EUMBBAR\n" );
+    return I2C_ERROR;
+  }
+
+  /* validate the I2C address */
+  if (addr & 0x80)
+  {
+    PRINT( "I2C_Initialize, I2C address invalid:  %d 0x%x\n", 
+      (unsigned int)addr, (unsigned int)addr ); 
+    return I2C_ERROR;
+  }
+
+  /* Call the internal I2C library function to perform work.
+   * Accept the default frequency sampling rate (no way to set it currently,
+   * via I2C_Init) and set the clock frequency to something reasonable.
+   */
+  status = I2C_Init( Global_eumbbar, (unsigned char)0x31, addr, en_int);
+  if (status != I2CSUCCESS)
+  {
+    PRINT( "I2C_Initialize: error in initiation\n" );
+    return I2C_ERROR;
+  }
+
+  /* all is well */
+  return I2C_SUCCESS;
+}
+
+
+/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV
+ * are implemented.  Both are only in polling mode.
+ *
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * i2c_addr is the I2C address of the slave device
+ * data_addr is the address of the data on the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int,
+                               I2C_TRANSACTION_MODE act,
+                               unsigned char i2c_addr,
+                               unsigned char data_addr,
+                               int len,
+                               char *buffer,
+                               I2C_STOP_MODE stop,
+                               int retry,
+                               I2C_RESTART_MODE rsta)
+{
+  I2C_Status status;
+  unsigned char data_addr_buffer[1];
+
+#if 1
+/* This is a temporary work-around.  The I2C library breaks the protocol
+ * if it attempts to handle a data transmission in more than one
+ * transaction, so the data address and the actual data bytes are put
+ * into a single buffer before sending it to the library internal functions.
+ * The problem is related to being able to restart a transaction without
+ * sending the I2C device address or repeating the data address.  It may take
+ * a day or two to sort it all out, so I'll have to get back to it later.
+ * Look at I2C_Start to see about using some status flags (I'm not sure that
+ * "stop" and "rsta" are enough to reflect the states, maybe so; but the logic
+ * in the library is insufficient) to control correct handling of the protocol.
+ */
+unsigned char dummy_buffer[257];
+if (act == I2C_MASTER_XMIT)
+{
+int i;
+for (i=1;i<=len;i++)dummy_buffer[i]=buffer[i-1];
+dummy_buffer[0]=data_addr;
+  status = I2C_do_buffer(en_int, act, i2c_addr, 1 + len, 
+    dummy_buffer, stop, retry, rsta); 
+  if (status != I2C_SUCCESS)
+  {
+    PRINT( "I2C_do_transaction: can't perform data transfer\n");
+    return I2C_ERROR;
+  }
+return I2C_SUCCESS;
+}
+#endif /* end of temp work-around */
+
+  /* validate requested transaction type */
+  if ((act != I2C_MASTER_XMIT) && (act != I2C_MASTER_RCV))
+  {
+    PRINT( "I2C_do_transaction, invalid transaction request:  %d\n", act);
+    return I2C_ERROR;
+  }
+
+  /* range check the I2C address */
+  if (i2c_addr & 0x80)
+  {
+    PRINT( "I2C_do_transaction, I2C address out of range:  %d 0x%x\n", 
+      (unsigned int)i2c_addr, (unsigned int)i2c_addr ); 
+    return I2C_ERROR;
+  } else {
+    data_addr_buffer[0] = data_addr;
+  }
+
+  /* We first have to contact the slave device and transmit the data address.
+   * Be careful about the STOP and restart stuff.  We don't want to signal STOP 
+   * after sending the data address, but this could be a continuation if the
+   * application didn't release the bus after the previous transaction, by
+   * not sending a STOP after it.
+   */
+  status = I2C_do_buffer(en_int, I2C_MASTER_XMIT, i2c_addr, 1, 
+   data_addr_buffer, I2C_NO_STOP, retry, rsta); 
+  if (status != I2C_SUCCESS)
+  {
+    PRINT( "I2C_do_transaction: can't send data address for read\n");
+    return I2C_ERROR;
+  }
+
+  /* The data transfer will be a continuation. */
+  rsta = I2C_RESTART;
+
+  /* now handle the user data */
+  status = I2C_do_buffer(en_int, act, i2c_addr, len, 
+    buffer, stop, retry, rsta); 
+  if (status != I2C_SUCCESS)
+  {
+    PRINT( "I2C_do_transaction: can't perform data transfer\n");
+    return I2C_ERROR;
+  }
+
+  /* all is well */
+  return I2C_SUCCESS;
+}
+
+/* This function performs the work for I2C_do_transaction.  The work is
+ * split into this function to enable I2C_do_transaction to first transmit
+ * the data address to the I2C slave device without putting the data address
+ * into the first byte of the buffer.
+ *
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * i2c_addr is the I2C address of the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+static I2C_Status I2C_do_buffer( I2C_INTERRUPT_MODE en_int,
+                                 I2C_TRANSACTION_MODE act,
+                                 unsigned char i2c_addr,
+                                 int len,
+                                 unsigned char *buffer,
+                                 I2C_STOP_MODE stop,
+                                 int retry,
+                                 I2C_RESTART_MODE rsta)
+{
+  I2CStatus rval;
+  unsigned int dev_stat;
+  if (act == I2C_MASTER_RCV)
+  {
+    /* set up for master-receive transaction */
+    rval = I2C_get(Global_eumbbar,i2c_addr,buffer,len,stop,rsta);
+  } else {
+    /* set up for master-transmit transaction */
+    rval = I2C_put(Global_eumbbar,i2c_addr,buffer,len,stop,rsta);
+  }
+
+  /* validate the setup */
+  if ( rval != I2CSUCCESS )
+  {
+    dev_stat = load_runtime_reg( Global_eumbbar, I2CSR );
+    PRINT( "Error(I2C_do_buffer): control phase, code(0x%08x), status(0x%08x)\n", rval, dev_stat);
+    I2C_Stop( Global_eumbbar );
+    return I2C_ERROR;
+  }
+
+  if (en_int == 1)
+  {
+    /* this should not happen, no interrupt handling yet */
+    return I2C_SUCCESS;
+  }
+
+  /* this performs the polling action, when the transfer is completed,
+   * the status returned from I2C_Timer_Event will be I2CBUFFFULL or
+   * I2CBUFFEMPTY (rcv or xmit), I2CSUCCESS or I2CADDRESS indicates the
+   * transaction is not yet complete, anything else is an error.
+   */
+  while ( rval == I2CSUCCESS || rval == I2CADDRESS )
+  {
+    /* poll the device until something happens */
+    do
+    {
+      rval = I2C_Timer_Event( Global_eumbbar, 0 );
+    }
+    while ( rval == I2CNOEVENT );
+
+    /* check for error condition */
+    if ( rval == I2CSUCCESS || rval == I2CBUFFFULL ||
+         rval == I2CBUFFEMPTY || rval == I2CADDRESS )
+    { ; /* do nothing */
+    } else {
+      /* report the error condition */
+      dev_stat = load_runtime_reg( Global_eumbbar, I2CSR );
+      PRINT( "Error(I2C_do_buffer):  code(0x%08x), status(0x%08x)\n", rval, dev_stat );
+      return I2C_ERROR;
+    }
+  }
+
+  /* all is well */
+  return I2C_SUCCESS;
+}
+
+/**
+ * Note:
+ *
+ * In all following functions,
+ * the caller shall pass the configured embedded utility memory
+ * block base, EUMBBAR.
+ **/
+
+/***********************************************************
+ * function: I2C_put
+ *
+ * description:
+   Send a buffer of data to the intended rcv_addr. 
+ * If stop_flag is set, after the whole buffer 
+ * is sent, generate a STOP signal provided that the
+ * receiver doesn't signal the STOP in the middle.
+ * I2C is the master performing transmitting. If
+ * no STOP signal is generated at the end of current
+ * transaction, the master can generate a START signal
+ * to another slave addr.
+ *
+ * note: this is master xmit API
+ *********************************************************/
+static I2CStatus I2C_put( unsigned int   eumbbar,
+                   unsigned char  rcv_addr,   /* receiver's address */
+                   unsigned char *buffer_ptr, /* pointer of data to be sent */
+                   unsigned int  length,      /* number of byte of in the buffer */
+                   unsigned int  stop_flag,   /* 1 - signal STOP when buffer is empty
+                                               * 0 - no STOP signal when buffer is empty
+                                               */
+                   unsigned int is_cnt )      /* 1 - this is a restart, don't check MBB
+                                               * 0 - this is a new start, check MBB
+                                               */
+                 
+{
+    if ( buffer_ptr == 0 || length == 0 )
+    {
+      return I2CERROR;
+    }
+
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_put\n", __FILE__, __LINE__ );
+#endif
+       
+    XmitByte = 0;
+    ByteToXmit = length;
+    XmitBuf = buffer_ptr;
+    XmitBufEmptyStop = stop_flag;
+
+    RcvByte = 0;
+    ByteToRcv = 0;
+    RcvBuf = 0;
+
+    /* we are the master, start transaction */
+    return I2C_Start( eumbbar, rcv_addr, XMIT, is_cnt );
+}
+
+/***********************************************************
+ * function: I2C_get
+ *
+ * description:
+ * Receive a buffer of data from the desired sender_addr
+ * If stop_flag is set, when the buffer is full and the 
+ * sender does not signal STOP, generate a STOP signal.
+ * I2C is the master performing receiving. If no STOP signal
+ * is generated, the master can generate a START signal
+ * to another slave addr.
+ *
+ * note: this is master receive API
+ **********************************************************/
+static I2CStatus I2C_get( unsigned int eumbbar,
+                  unsigned char rcv_from,    /* sender's address */
+                  unsigned char *buffer_ptr, /* pointer of receiving buffer */
+                  unsigned int  length,      /* length of the receiving buffer */
+                  unsigned int  stop_flag,   /* 1 - signal STOP when buffer is full
+                                              * 0 - no STOP signal when buffer is full 
+                                              */
+                  unsigned int is_cnt )      /* 1 - this is a restart, don't check MBB
+                                              * 0 - this is a new start, check MBB
+                                               */
+{
+    if ( buffer_ptr == 0 || length == 0 )
+    {
+      return I2CERROR;
+    }
+       
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_get\n", __FILE__, __LINE__ );
+#endif
+
+    RcvByte = 0;
+    ByteToRcv = length;
+    RcvBuf = buffer_ptr;
+    RcvBufFulStop = stop_flag;
+       
+    XmitByte = 0;
+    ByteToXmit = 0;
+    XmitBuf = 0;
+       
+    /* we are the master, start the transaction */
+    return I2C_Start( eumbbar, rcv_from, RCV, is_cnt );
+
+}
+
+#if 0 /* turn off dead code */
+/*********************************************************
+ * function: I2C_write
+ *
+ * description:
+ * Send a buffer of data to the requiring master. 
+ * If stop_flag is set, after the whole buffer is sent,
+ * generate a STOP signal provided that the requiring 
+ * receiver doesn't signal the STOP in the middle.
+ * I2C is the slave performing transmitting.
+ *
+ * Note: this is slave xmit API.
+ *
+ *       due to the current Kahlua design, slave transmitter
+ *       shall not signal STOP since there is no way
+ *       for master to detect it, causing I2C bus hung.
+ *
+ *       For the above reason, the stop_flag is always
+ *       set, i.e., 0.
+ *
+ *       programmer shall use the timer on Kahlua to 
+ *       control the interval of data byte at the 
+ *       master side.
+ *******************************************************/
+static I2CStatus I2C_write( unsigned int eumbbar,
+                    unsigned char *buffer_ptr, /* pointer of data to be sent */
+                    unsigned int  length,      /* number of byte of in the buffer */
+                    unsigned int  stop_flag )  /* 1 - signal STOP when buffer is empty
+                                                * 0 - no STOP signal when buffer is empty
+                                                */
+{
+    if ( buffer_ptr == 0 || length == 0 )
+    {
+      return I2CERROR;
+    }
+
+    XmitByte = 0;
+    ByteToXmit = length;
+    XmitBuf = buffer_ptr;
+    XmitBufEmptyStop = 0; /* in order to avoid bus hung, ignored the user's stop_flag */
+
+    RcvByte = 0;
+    ByteToRcv = 0;
+    RcvBuf = 0;
+       
+    /* we are the slave, just wait for being called, or pull */
+    /* I2C_Timer_Event( eumbbar ); */
+}
+
+/******************************************************
+ * function: I2C_read
+ *
+ * description:
+ * Receive a buffer of data from the sending master.
+ * If stop_flag is set, when the buffer is full and the 
+ * sender does not signal STOP, generate a STOP signal.
+ * I2C is the slave performing receiving.
+ *
+ * note: this is slave receive API
+ ****************************************************/
+static I2CStatus I2C_read(unsigned int eumbbar,
+                   unsigned char *buffer_ptr, /* pointer of receiving buffer */
+                  unsigned int  length,      /* length of the receiving buffer */
+                  unsigned int  stop_flag )  /* 1 - signal STOP when buffer is full
+                                              * 0 - no STOP signal when buffer is full 
+                                              */
+{
+    if ( buffer_ptr == 0 || length == 0 )
+    {
+      return I2CERROR;
+    }
+
+    RcvByte = 0;
+    ByteToRcv = length;
+    RcvBuf = buffer_ptr;
+    RcvBufFulStop = stop_flag;
+
+    XmitByte = 0;
+    ByteToXmit = 0;
+    XmitBuf = 0;
+       
+    /* wait for master to call us, or poll */
+    /* I2C_Timer_Event( eumbbar ); */
+}
+#endif /* turn off dead code */
+
+/*********************************************************
+ * function: I2c_Timer_Event
+ *
+ * description:
+ * if interrupt is not used, this is the timer event handler.
+ * After each fixed time interval, this function can be called
+ * to check the I2C status and call appropriate function to
+ * handle the status event.
+ ********************************************************/
+static I2CStatus I2C_Timer_Event( unsigned int eumbbar, I2CStatus (*handler)( unsigned int ) )
+{
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_Timer_Event\n", __FILE__, __LINE__ );
+#endif
+       
+    I2C_STAT stat = I2C_Get_Stat( eumbbar );
+
+    if ( stat.mif == 1 )
+    {
+       if ( handler == 0 )
+       {
+          return I2C_ISR( eumbbar );
+       }
+       else
+       {
+          return (*handler)( eumbbar );
+       }
+    }
+
+    return I2CNOEVENT;
+}
+
+
+/****************** Device I/O function *****************/
+
+/******************************************************
+ * function: I2C_Start
+ *
+ * description: Generate a START signal in the desired mode.
+ *              I2C is the master.
+ *
+ *              Return I2CSUCCESS if no error.
+ *
+ * note:
+ ****************************************************/
+static I2CStatus I2C_Start( unsigned int  eumbbar,
+                     unsigned char slave_addr, /* address of the receiver */ 
+                        I2C_MODE      mode,       /* XMIT(1) - put (write)
+                                                           * RCV(0)  - get (read)
+                                                                   */
+                            unsigned int is_cnt )    /* 1 - this is a restart, don't check MBB
+                                                                  * 0 - this is a new start
+                                                                  */
+{
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_Start addr 0x%x mode %d cnt %d\n", __FILE__, __LINE__ ,
+      slave_addr,mode,is_cnt);
+#endif
+       unsigned int tmp = 0;
+    I2C_STAT stat;
+    I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar );
+
+    /* first make sure I2C has been initialized */
+    if ( ctrl.men == 0 )
+    {
+          return I2CERROR;
+    }
+
+    /* next make sure bus is idle */
+    stat = I2C_Get_Stat( eumbbar );
+       
+    if ( is_cnt == 0 && stat.mbb == 1 )
+    {
+          /* sorry, we lost */
+          return I2CBUSBUSY;
+    }
+    else if ( is_cnt == 1 && stat.mif == 1 && stat.mal == 0 )
+    {
+       /* sorry, we lost the bus */
+        return I2CALOSS;
+    }
+            
+
+    /* OK, I2C is enabled and we have the bus */
+
+    /* prepare to write the slave address */
+    ctrl.msta = 1;
+    ctrl.mtx  = 1;
+    ctrl.txak = 0;     
+    ctrl.rsta = is_cnt;   /* set the repeat start bit */
+    I2C_Set_Ctrl( eumbbar, ctrl );
+       
+    /* write the slave address and xmit/rcv mode bit */
+    tmp = load_runtime_reg( eumbbar, I2CDR );
+    tmp = ( tmp & 0xffffff00 ) | ((slave_addr & 0x007f)<<1) | ( mode == XMIT ? 0x0 : 0x1 );
+    store_runtime_reg( eumbbar, I2CDR, tmp );
+
+       if ( mode == RCV )
+       {
+               MasterRcvAddress = 1;
+       }
+       else
+       {
+               MasterRcvAddress = 0;
+       }
+       
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_Start exit\n", __FILE__, __LINE__ );
+#endif
+       
+    /* wait for the interrupt or poll  */
+    return I2CSUCCESS;
+}
+
+/***********************************************************
+ * function: I2c_Stop
+ *
+ * description: Generate a STOP signal to terminate the master
+ *              transaction.
+ *              return I2CSUCCESS
+ *
+ **********************************************************/
+static I2CStatus I2C_Stop( unsigned int eumbbar )
+{
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_Stop enter\n", __FILE__, __LINE__ );
+#endif
+       
+    I2C_CTRL ctrl = I2C_Get_Ctrl(eumbbar );
+    ctrl.msta = 0;
+    I2C_Set_Ctrl( eumbbar, ctrl );
+
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_Stop exit\n", __FILE__, __LINE__ );
+#endif
+       
+    return I2CSUCCESS;
+}
+
+/****************************************************
+ * function: I2C_Master_Xmit
+ *
+ * description: Master sends one byte of data to 
+ *              slave target
+ * 
+ *              return I2CSUCCESS if the byte transmitted.
+ *              Otherwise no-zero
+ *
+ * Note: condition must meet when this function is called:
+ *       I2CSR(MIF) == 1 && I2CSR(MCF)  == 1  && I2CSR(RXAK) == 0
+ *       I2CCR(MSTA) == 1  && I2CCR(MTX) == 1
+ *
+ ***************************************************/ 
+static I2CStatus I2C_Master_Xmit( unsigned int eumbbar )
+{
+       unsigned int val;
+    if ( ByteToXmit > 0 )
+    {
+
+      if ( ByteToXmit == XmitByte )
+      {
+            /* all xmitted */
+            ByteToXmit = 0;
+
+            if ( XmitBufEmptyStop == 1 )
+            {
+              I2C_Stop( eumbbar );
+            }
+
+             return I2CBUFFEMPTY;
+
+      }
+
+#ifdef I2CDBG0
+       PRINT( "%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, *(XmitBuf + XmitByte) );
+#endif
+         
+       val = *(XmitBuf + XmitByte);
+       val &= 0x000000ff;
+       store_runtime_reg( eumbbar, I2CDR, val );
+       XmitByte++;
+       
+       return I2CSUCCESS;
+       
+    }
+
+    return I2CBUFFEMPTY;
+}
+
+/***********************************************
+ * function: I2C_Master_Rcv
+ *
+ * description: master reads one byte data
+ *              from slave source
+ *
+ *              return I2CSUCCESS if no error
+ * 
+ * Note: condition must meet when this function is called:
+ *       I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&
+ *       I2CCR(MSTA) == 1 && I2CCR(MTX) == 0
+ * 
+ ***********************************************/
+static I2CStatus I2C_Master_Rcv( unsigned int eumbbar )
+{
+       I2C_CTRL ctrl;
+       unsigned int val;
+    if ( ByteToRcv > 0 )
+    {
+
+      if ( ByteToRcv - RcvByte == 2 && RcvBufFulStop == 1 )
+      {
+           /* master requests more than or equal to 2 bytes
+            * we are reading 2nd to last byte
+            */
+       
+        /* we need to set I2CCR(TXAK) to generate a STOP */
+          ctrl = I2C_Get_Ctrl( eumbbar );
+             ctrl.txak = 1;
+             I2C_Set_Ctrl( eumbbar, ctrl );
+                 
+                            /* Kahlua will automatically generate a STOP
+                                        * next time a transaction happens
+                                        */
+
+           /* note: the case of master requesting one byte is
+            *       handled in I2C_ISR
+            */
+      }
+       
+         /* generat a STOP before reading the last byte */
+         if ( RcvByte + 1 == ByteToRcv && RcvBufFulStop == 1 )
+         {
+                 I2C_Stop( eumbbar );
+         }
+
+      val = load_runtime_reg( eumbbar, I2CDR );
+      *(RcvBuf + RcvByte) = val & 0xFF;
+
+#ifdef I2CDBG0
+       PRINT( "%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, *(RcvBuf + RcvByte) );
+#endif
+      
+      RcvByte++;
+
+         if ( ByteToRcv == RcvByte )
+      {
+           ByteToRcv = 0;
+
+        return I2CBUFFFULL;            
+      }
+         
+      return I2CSUCCESS;
+   }
+      
+   return I2CBUFFFULL;
+   
+}
+
+/****************************************************
+ * function: I2C_Slave_Xmit
+ *
+ * description: Slave sends one byte of data to 
+ *              requesting destination
+ * 
+ *        return SUCCESS if the byte transmitted. Otherwise
+ *        No-zero
+ *
+ * Note: condition must meet when this function is called:
+ *       I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&  I2CSR(RXAK) = 0
+ *       I2CCR(MSTA) == 0  && I2CCR(MTX) == 1
+ *
+ ***************************************************/
+static I2CStatus I2C_Slave_Xmit( unsigned int eumbbar )
+{
+    unsigned int val;  
+    if ( ByteToXmit > 0 )
+    {
+
+          if ( ByteToXmit == XmitByte )
+          {
+           /* no more data to send */      
+           ByteToXmit = 0;
+               
+           /* do not toggle I2CCR(MTX). Doing so will cause bus-hung
+            * since current Kahlua design does not give master a way
+            * to detect slave stop. It is always a good idea for
+            * master to use timer to prevent the long long delays
+            */
+
+             return I2CBUFFEMPTY;              
+          }
+
+#ifdef I2CDBG
+       PRINT( "%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, *(XmitBuf + XmitByte) ); 
+#endif
+          
+        val = *(XmitBuf + XmitByte);
+        val &= 0x000000ff;
+        store_runtime_reg( eumbbar, I2CDR, val );
+        XmitByte++;
+               
+
+       return I2CSUCCESS;
+    }
+
+    return I2CBUFFEMPTY;
+}
+
+/***********************************************
+ * function: I2C_Slave_Rcv
+ *
+ * description: slave reads one byte data
+ *              from master source
+ *
+ *              return I2CSUCCESS if no error otherwise non-zero
+ * 
+ * Note: condition must meet when this function is called:
+ *       I2CSR(MIF) == 1 && I2CSR(MCF) == 1 &&
+ *       I2CCR(MSTA) == 0 && I2CCR(MTX)  = 0
+ * 
+ ***********************************************/
+static I2CStatus I2C_Slave_Rcv(unsigned int eumbbar )
+{
+       unsigned int val;
+    I2C_CTRL ctrl;
+    if ( ByteToRcv > 0 )
+    {
+         val = load_runtime_reg( eumbbar, I2CDR );
+         *( RcvBuf + RcvByte ) = val & 0xff;
+#ifdef I2CDBG
+       PRINT( "%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, *(RcvBuf + RcvByte) );
+#endif   
+         RcvByte++;
+
+        if ( ByteToRcv == RcvByte )
+        {
+             if ( RcvBufFulStop == 1 )
+             {
+               /* all done */
+               ctrl = I2C_Get_Ctrl( eumbbar );
+               ctrl.txak = 1;
+               I2C_Set_Ctrl( eumbbar, ctrl );
+             }
+
+             ByteToRcv = 0;
+          return I2CBUFFFULL;            
+        }
+
+           return I2CSUCCESS;
+    }
+
+    return I2CBUFFFULL;
+}
+
+/****************** Device Control Function *************/
+
+/*********************************************************
+ * function: I2C_Init
+ *
+ * description: Initialize I2C unit with desired frequency divider,
+ *              master's listening address, with interrupt enabled
+ *              or disabled.
+ *
+ * note:
+ ********************************************************/
+static I2CStatus I2C_Init( unsigned int eumbbar,
+                   unsigned char fdr,        /* frequency divider */ 
+                   unsigned char slave_addr, /* driver's address used for receiving */
+                   unsigned int en_int)     /* 1 - enable I2C interrupt 
+                                             * 0 - disable I2C interrup 
+                                             */
+{
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_Init enter\n", __FILE__, __LINE__ );
+#endif
+       
+    I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar );
+    unsigned int tmp;
+    /* disable the I2C module before we change everything */
+    ctrl.men = 0;
+    I2C_Set_Ctrl( eumbbar, ctrl );
+
+    /* set the frequency diver */
+    tmp = load_runtime_reg( eumbbar, I2CFDR );
+    tmp = ( tmp & 0xffffffc0 ) | ( fdr & 0x3f );
+    store_runtime_reg( eumbbar, I2CFDR, tmp );
+
+    /* Set our listening (slave) address */
+    tmp = load_runtime_reg( eumbbar, I2CADR );
+    tmp = ( tmp & 0xffffff01 ) | ( ( slave_addr & 0x7f) << 1 );
+    store_runtime_reg( eumbbar, I2CADR, tmp );
+
+    /* enable I2C with desired interrupt setting */
+    ctrl.men = 1;
+    ctrl.mien = en_int & 0x1;
+    I2C_Set_Ctrl( eumbbar, ctrl );
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_Init exit\n", __FILE__, __LINE__ );
+#endif
+       
+    return I2CSUCCESS;
+    
+}
+
+/*****************************************
+ * function I2c_Get_Stat
+ *
+ * description: Query I2C Status, i.e., read I2CSR
+ *
+ ****************************************/
+static I2C_STAT I2C_Get_Stat( unsigned int eumbbar )
+{
+    unsigned int temp = load_runtime_reg( eumbbar, I2CSR );
+#ifdef I2CDBG0
+       PRINT( "%s(%d): get stat = 0x%08x\n", __FILE__, __LINE__, temp );
+#endif 
+       
+    I2C_STAT stat;
+    stat.rsrv0 = ( temp & 0xffffff00 ) >> 8;
+    stat.mcf   = ( temp & 0x00000080 ) >> 7;
+    stat.maas  = ( temp & 0x00000040 ) >> 6;
+    stat.mbb   = ( temp & 0x00000020 ) >> 5;
+    stat.mal   = ( temp & 0x00000010 ) >> 4;
+    stat.rsrv1 = ( temp & 0x00000008 ) >> 3;
+    stat.srw   = ( temp & 0x00000004 ) >> 2;
+    stat.mif   = ( temp & 0x00000002 ) >> 1;
+    stat.rxak  = ( temp & 0x00000001 );
+    return stat;
+}
+
+/*********************************************
+ * function: I2c_Set_Ctrl
+ *
+ * description: Change I2C Control bits,
+ *              i.e., write to I2CCR
+ *
+ ********************************************/
+static void I2C_Set_Ctrl( unsigned int eumbbar, I2C_CTRL ctrl ) /* new control value */
+{
+    unsigned int temp = load_runtime_reg( eumbbar, I2CCR );
+    temp &= 0xffffff03;
+    temp |= ( ( ctrl.men  & 0x1 ) << 7 );
+    temp |= ( ( ctrl.mien & 0x1 ) << 6 );
+    temp |= ( ( ctrl.msta & 0x1 ) << 5 );
+    temp |= ( ( ctrl.mtx  & 0x1 ) << 4 );
+    temp |= ( ( ctrl.txak & 0x1 ) << 3 );
+    temp |= ( ( ctrl.rsta & 0x1 ) << 2 );
+#ifdef I2CDBG0
+       PRINT( "%s(%d): set ctrl = 0x%08x\n", __FILE__, __LINE__, temp );
+#endif 
+    store_runtime_reg( eumbbar, I2CCR, temp );
+
+}
+
+/*****************************************
+ * function: I2C_Get_Ctrl
+ *
+ * description: Query I2C Control bits,
+ *              i.e., read I2CCR
+ *****************************************/
+static I2C_CTRL I2C_Get_Ctrl( unsigned int eumbbar )
+{
+    union {
+        I2C_CTRL ctrl ;
+        unsigned int temp;
+    } s;
+    s.temp = load_runtime_reg( eumbbar, I2CCR );
+#ifdef I2CDBG0
+    PRINT( "%s(%d): get ctrl = 0x%08x\n", __FILE__, __LINE__, s.temp );
+#endif
+
+    return s.ctrl;
+}
+
+
+/****************************************
+ * function: I2C_Slave_Addr
+ *
+ * description: Process slave address phase.
+ *              return I2CSUCCESS if no error
+ *
+ * note: Precondition for calling this function:
+ *       I2CSR(MIF) == 1 &&
+ *       I2CSR(MAAS) == 1
+ ****************************************/
+static I2CStatus I2C_Slave_Addr( unsigned int eumbbar )
+{
+    I2C_STAT stat = I2C_Get_Stat( eumbbar );
+    I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar );
+    
+    if ( stat.srw == 1 )
+    {
+          /* we are asked to xmit */
+          ctrl.mtx = 1;
+          I2C_Set_Ctrl( eumbbar, ctrl );    /* set MTX */
+          return I2C_Slave_Xmit( eumbbar );
+    }
+
+   /* we are asked to receive data */
+   ctrl.mtx = 0;
+   I2C_Set_Ctrl(eumbbar, ctrl );
+   (void)load_runtime_reg( eumbbar, I2CDR ); /* do a fake read to start */
+
+    return I2CADDRESS;
+}
+
+/***********************************************
+ * function: I2C_ISR
+ *
+ * description: I2C Interrupt service routine
+ *
+ * note: Precondition:
+ *      I2CSR(MIF) == 1
+ **********************************************/
+static I2CStatus I2C_ISR( unsigned int eumbbar )
+{
+#ifdef I2CDBG0
+       PRINT( "%s(%d): I2C_ISR\n", __FILE__, __LINE__ );
+#endif
+       
+    I2C_STAT stat = I2C_Get_Stat( eumbbar );
+    I2C_CTRL ctrl = I2C_Get_Ctrl( eumbbar );
+
+    /* clear MIF */
+    stat.mif = 0;
+
+    /* Now let see what kind of event this is */    
+    if ( stat.mcf == 1 )
+    {
+       /* transfer compete */
+
+       /* clear the MIF bit */
+       I2C_Set_Stat( eumbbar, stat );
+
+       if ( ctrl.msta == 1 )
+       {
+           /* master */
+           if ( ctrl.mtx == 1 )
+           {
+                       /* check if this is the address phase for master receive */
+            if ( MasterRcvAddress == 1 )
+                       {
+                               /* Yes, it is the address phase of master receive */
+                ctrl.mtx = 0;
+                /* now check how much we want to receive */
+                if ( ByteToRcv == 1 && RcvBufFulStop == 1 )
+                {
+                    ctrl.txak = 1;
+                }
+                               
+                I2C_Set_Ctrl( eumbbar, ctrl );
+               (void)load_runtime_reg( eumbbar, I2CDR );  /* fake read first */
+
+                               MasterRcvAddress = 0;
+                               return I2CADDRESS;
+                               
+                       }
+
+            /* master xmit */          
+            if ( stat.rxak == 0 )
+            {
+                         /* slave has acknowledged */
+                         return I2C_Master_Xmit( eumbbar );
+            }
+
+            /* slave has not acknowledged yet, generate a STOP */
+            if ( XmitBufEmptyStop == 1 )
+            {
+                   ctrl.msta = 0;
+                   I2C_Set_Ctrl( eumbbar, ctrl );
+                       }
+                       
+            return I2CSUCCESS;
+           }
+           
+           /* master receive */
+           return I2C_Master_Rcv( eumbbar );
+       }
+
+       /* slave */
+       if ( ctrl.mtx == 1 )
+       {
+           /* slave xmit */
+           if ( stat.rxak == 0 )
+           {
+               /* master has acknowledged */
+               return I2C_Slave_Xmit( eumbbar );
+           }
+
+           /* master has not acknowledged, wait for STOP */
+           /* do nothing for preventing bus from hung */
+           return I2CSUCCESS;
+       }
+
+       /* slave rcv */
+       return I2C_Slave_Rcv( eumbbar );
+       
+    }
+    else if ( stat.maas == 1 )
+    {
+       /* received a call from master */
+       
+       /* clear the MIF bit */
+       I2C_Set_Stat(eumbbar, stat );
+       
+    /* master is calling us, process the address phase */
+       return I2C_Slave_Addr( eumbbar );
+    }
+    else
+    {
+       /* has to be arbitration lost */
+       stat.mal = 0;
+       I2C_Set_Stat( eumbbar, stat );
+
+       ctrl.msta = 0; /* return to receive mode */
+       I2C_Set_Ctrl( eumbbar, ctrl );
+    }
+
+    return I2CSUCCESS;
+
+}
+
+/******************************************************
+ * function: I2C_Set_Stat
+ *
+ * description: modify the I2CSR
+ *
+ *****************************************************/
+static void I2C_Set_Stat( unsigned int eumbbar, I2C_STAT stat )
+{
+    union {
+      unsigned int val;
+      I2C_STAT stat;
+    } s_tmp;
+    union {
+      unsigned int val;
+      I2C_STAT stat;
+    } s;
+    s.val = load_runtime_reg( eumbbar, I2CSR );
+    s.val &= 0xffffff08;
+    s_tmp.stat = stat;
+    s.val |= (s_tmp.val & 0xf7);
+
+#ifdef I2CDBG0
+    PRINT( "%s(%d): set stat = 0x%08x\n", __FILE__, __LINE__, s.val );
+#endif 
+       
+    store_runtime_reg( eumbbar, I2CSR, s.val );
+    
+}
diff --git a/mpc8240/drivers/i2c/i2c2.S b/mpc8240/drivers/i2c/i2c2.S
new file mode 100644 (file)
index 0000000..fce84df
--- /dev/null
@@ -0,0 +1,50 @@
+/**************************************
+ * $Id: i2c2.S,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+ *
+ * copyright @ Motorola, 1999
+ *
+ **************************************/
+
+/**********************************************************
+ * function: load_runtime_reg
+ *
+ * input:  r3 - value of eumbbar
+ *         r4 - register offset in embedded utility space
+ *
+ * output: r3 - register content
+ **********************************************************/
+      .text
+      .align 2
+      .global load_runtime_reg
+load_runtime_reg:
+            
+/*               xor r5,r5,r5
+*         or  r5,r5,r3
+*
+*            lwbrx     r3,r4,r5
+*/
+             lwbrx r3,r4,r3
+             sync
+          
+             bclr 20, 0
+
+/****************************************************************
+ * function: store_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ *        r4 - register offset in embedded utility space
+ *        r5 - new value to be stored 
+ *
+ ****************************************************************/
+           .text
+           .align 2
+           .global store_runtime_reg
+store_runtime_reg:
+
+             stwbrx r5,  r4, r3
+             sync
+
+              bclr   20,0
+
+
+
diff --git a/mpc8240/drivers/i2c/i2c_export.h b/mpc8240/drivers/i2c/i2c_export.h
new file mode 100644 (file)
index 0000000..14a6f09
--- /dev/null
@@ -0,0 +1,148 @@
+#ifndef I2C_EXPORT_H
+#define I2C_EXPORT_H
+
+/****************************************************
+ * $Id: i2c_export.h,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+ *
+ * Copyright Motrola 1999
+ *
+ * $Log: i2c_export.h,v $
+ * Revision 1.1  2000/11/20 17:22:33  wdenk
+ *
+ * * Added support for MBX860T (thanks to Rob Taylor)
+ *
+ * * Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+ *   Work In Progress (TM); current status: boots to command line input.
+ *   EPIC code non-functional (interrupts disabled), No net, No IDE.
+ *
+ * * Add support for Status LED
+ *
+ * * Optionally panic() to reboot instead of hanging
+ *
+ * * Misc bug fixes
+ *
+ * * All frequencies in HZ now (internally)
+ *
+ * * Add support for BOOTP Domain Name Server Option
+ *
+ * Revision 1.1.1.1  2000/11/14 16:54:07  robt
+ * no message
+ *
+ * Revision 1.1.1.1  2000/11/14 14:49:39  robt
+ * no message
+ *
+ * Revision 1.3  1999/05/03 14:57:54  charliem
+ * Decouple the I2C library from DINK application source by making the PRINT
+ * function an optional parameter that is passed to I2C_Inititalize.  If the
+ * function pointer is passed, it is used by the library; otherwise, no print
+ * output is performed.
+ *
+ * Revision 1.2  1999/04/30 16:25:53  charliem
+ * Change the DINK to I2C_do_transaction interface to allow the application
+ * to specify the data address as a parameter to I2C_do_transaction, rather
+ * than putting the data address into the first byte of the buffer.
+ * There is a work-around in I2C_do_transaction in this version, see comments
+ * in the i2c1.c code.
+ *
+ * Revision 1.1  1999/04/29 13:41:07  charliem
+ * Capture first pass at modifications to the I2C interface.  This version is
+ * correct, but there are some additional modifications to be implemented.
+ * Nothing but I2C should be affected.
+ *
+ *
+ ****************************************************/
+
+/* These are the defined return values for the I2C_do_transaction function.
+ * Any non-zero value indicates failure.  Failure modes can be added for 
+ * more detailed error reporting.
+ */
+typedef enum _i2c_status
+{
+ I2C_SUCCESS     = 0,
+ I2C_ERROR,
+} I2C_Status;
+
+/* These are the defined tasks for I2C_do_transaction.
+ * Modes for SLAVE_RCV and SLAVE_XMIT will be added.
+ */
+typedef enum _i2c_transaction_mode
+{
+       I2C_MASTER_RCV =  0,
+       I2C_MASTER_XMIT = 1,
+} I2C_TRANSACTION_MODE;
+
+typedef enum _i2c_interrupt_mode
+{
+       I2C_INT_DISABLE =  0,
+       I2C_INT_ENABLE = 1,
+} I2C_INTERRUPT_MODE;
+
+typedef enum _i2c_stop
+{
+       I2C_NO_STOP =  0,
+       I2C_STOP = 1,
+} I2C_STOP_MODE;
+
+typedef enum _i2c_restart
+{
+       I2C_NO_RESTART =  0,
+       I2C_RESTART = 1,
+} I2C_RESTART_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application 
+ * to use the functionality provided by I2C driver.
+ * This is a "generic" I2C interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ * 
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we just transfer whatever
+ *       we are given
+ **************************************************/
+
+
+/*  Initialize I2C unit with the following:
+ *  driver's slave address 
+ *  interrupt enabled
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  desired clock rate
+ *  digital filter frequency sampling rate
+ *
+ *  This function must be called before I2C unit can be used.
+ */
+extern I2C_Status I2C_Initialize( 
+       unsigned char addr,            /* driver's I2C slave address */
+       I2C_INTERRUPT_MODE en_int,     /* 1 - enable I2C interrupt 
+                                       * 0 - disable I2C interrupt
+                                       */
+        int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+                                                 * provided by application
+                                                 */
+
+/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV
+ * are implemented.  Both are only in polling mode.
+ * 
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * addr is the I2C address of the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int,
+                                      I2C_TRANSACTION_MODE act,
+                                      unsigned char i2c_addr,
+                                      unsigned char data_addr,
+                                      int len,
+                                      char *buffer,
+                                      I2C_STOP_MODE stop,
+                                      int retry,
+                                      I2C_RESTART_MODE rsta);
+#endif
diff --git a/mpc8240/drivers/i2c_export.h b/mpc8240/drivers/i2c_export.h
new file mode 100644 (file)
index 0000000..93a4e9d
--- /dev/null
@@ -0,0 +1,148 @@
+#ifndef I2C_EXPORT_H
+#define I2C_EXPORT_H
+
+/****************************************************
+ * $Id: i2c_export.h,v 1.1 2000/11/20 17:22:32 wdenk Exp $
+ *
+ * Copyright Motrola 1999
+ *
+ * $Log: i2c_export.h,v $
+ * Revision 1.1  2000/11/20 17:22:32  wdenk
+ *
+ * * Added support for MBX860T (thanks to Rob Taylor)
+ *
+ * * Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+ *   Work In Progress (TM); current status: boots to command line input.
+ *   EPIC code non-functional (interrupts disabled), No net, No IDE.
+ *
+ * * Add support for Status LED
+ *
+ * * Optionally panic() to reboot instead of hanging
+ *
+ * * Misc bug fixes
+ *
+ * * All frequencies in HZ now (internally)
+ *
+ * * Add support for BOOTP Domain Name Server Option
+ *
+ * Revision 1.1.1.1  2000/11/14 16:54:07  robt
+ * no message
+ *
+ * Revision 1.1.1.1  2000/11/14 14:49:39  robt
+ * no message
+ *
+ * Revision 1.3  1999/05/03 14:57:54  charliem
+ * Decouple the I2C library from DINK application source by making the PRINT
+ * function an optional parameter that is passed to I2C_Inititalize.  If the
+ * function pointer is passed, it is used by the library; otherwise, no print
+ * output is performed.
+ *
+ * Revision 1.2  1999/04/30 16:25:53  charliem
+ * Change the DINK to I2C_do_transaction interface to allow the application
+ * to specify the data address as a parameter to I2C_do_transaction, rather
+ * than putting the data address into the first byte of the buffer.
+ * There is a work-around in I2C_do_transaction in this version, see comments
+ * in the i2c1.c code.
+ *
+ * Revision 1.1  1999/04/29 13:41:07  charliem
+ * Capture first pass at modifications to the I2C interface.  This version is
+ * correct, but there are some additional modifications to be implemented.
+ * Nothing but I2C should be affected.
+ *
+ *
+ ****************************************************/
+
+/* These are the defined return values for the I2C_do_transaction function.
+ * Any non-zero value indicates failure.  Failure modes can be added for 
+ * more detailed error reporting.
+ */
+typedef enum _i2c_status
+{
+ I2C_SUCCESS     = 0,
+ I2C_ERROR,
+} I2C_Status;
+
+/* These are the defined tasks for I2C_do_transaction.
+ * Modes for SLAVE_RCV and SLAVE_XMIT will be added.
+ */
+typedef enum _i2c_transaction_mode
+{
+       I2C_MASTER_RCV =  0,
+       I2C_MASTER_XMIT = 1,
+} I2C_TRANSACTION_MODE;
+
+typedef enum _i2c_interrupt_mode
+{
+       I2C_INT_DISABLE =  0,
+       I2C_INT_ENABLE = 1,
+} I2C_INTERRUPT_MODE;
+
+typedef enum _i2c_stop
+{
+       I2C_NO_STOP =  0,
+       I2C_STOP = 1,
+} I2C_STOP_MODE;
+
+typedef enum _i2c_restart
+{
+       I2C_NO_RESTART =  0,
+       I2C_RESTART = 1,
+} I2C_RESTART_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application 
+ * to use the functionality provided by I2C driver.
+ * This is a "generic" I2C interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ * 
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we just transfer whatever
+ *       we are given
+ **************************************************/
+
+
+/*  Initialize I2C unit with the following:
+ *  driver's slave address 
+ *  interrupt enabled
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  desired clock rate
+ *  digital filter frequency sampling rate
+ *
+ *  This function must be called before I2C unit can be used.
+ */
+extern I2C_Status I2C_Initialize( 
+       unsigned char addr,            /* driver's I2C slave address */
+       I2C_INTERRUPT_MODE en_int,     /* 1 - enable I2C interrupt 
+                                       * 0 - disable I2C interrupt
+                                       */
+        int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+                                                 * provided by application
+                                                 */
+
+/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV
+ * are implemented.  Both are only in polling mode.
+ * 
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * addr is the I2C address of the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int,
+                                      I2C_TRANSACTION_MODE act,
+                                      unsigned char i2c_addr,
+                                      unsigned char data_addr,
+                                      int len,
+                                      char *buffer,
+                                      I2C_STOP_MODE stop,
+                                      int retry,
+                                      I2C_RESTART_MODE rsta);
+#endif
diff --git a/mpc8240/drivers/i2o.h b/mpc8240/drivers/i2o.h
new file mode 100644 (file)
index 0000000..8b46156
--- /dev/null
@@ -0,0 +1,345 @@
+#ifndef I2O_H
+#define I2O_H
+/*********************************************************
+ * $Id: i2o.h,v 1.1 2000/11/20 17:22:32 wdenk Exp $
+ *
+ * copyright @ Motorola, 1999
+ *********************************************************/
+
+#define I2O_REG_OFFSET 0x0004
+
+#define PCI_CFG_CLA    0x0B
+#define PCI_CFG_SCL    0x0A
+#define PCI_CFG_PIC    0x09
+
+#define I2O_IMR0 0x0050
+#define I2O_IMR1 0x0054
+#define I2O_OMR0 0x0058
+#define I2O_OMR1 0x005C
+
+#define I2O_ODBR 0x0060
+#define I2O_IDBR 0x0068
+
+#define I2O_OMISR  0x0030
+#define I2O_OMIMR  0x0034
+#define I2O_IMISR  0x0100
+#define I2O_IMIMR  0x0104
+
+/* accessable to PCI master but local processor */
+#define I2O_IFQPR  0x0040
+#define I2O_OFQPR  0x0044
+
+/* accessable to local processor */
+#define I2O_IFHPR  0x0120
+#define I2O_IFTPR  0x0128
+#define I2O_IPHPR  0x0130
+#define I2O_IPTPR  0x0138
+#define I2O_OFHPR  0x0140
+#define I2O_OFTPR  0x0148
+#define I2O_OPHPR  0x0150
+#define I2O_OPTPR  0x0158
+#define I2O_MUCR   0x0164
+#define I2O_QBAR   0x0170
+
+#define I2O_NUM_MSG 2
+
+typedef enum _i2o_status
+{
+       I2OSUCCESS = 0,
+       I2OINVALID,
+       I2OMSGINVALID,
+       I2ODBINVALID,
+       I2OQUEINVALID,
+       I2OQUEEMPTY,
+       I2OQUEFULL,
+       I2ONOEVENT,
+} I2OSTATUS;
+
+typedef enum _queue_size
+{
+    QSIZE_4K = 0x02,
+    QSIZE_8K = 0x04,
+    QSIZE_16K = 0x08,
+    QSIZE_32K = 0x10,
+    QSIZe_64K = 0x20,
+} QUEUE_SIZE;
+
+typedef enum _location
+{
+    LOCAL = 0,     /* used by local processor to access its own on board device,
+                     local processor's eumbbar is required */
+    REMOTE,        /* used by PCI master to access the devices on its PCI device,
+                     device's pcsrbar is required */
+} LOCATION;
+
+/* door bell */
+typedef enum _i2o_in_db
+{
+  IN_DB = 1,
+  MC,         /* machine check */
+} I2O_IN_DB;
+
+/* I2O PCI configuration identification */
+typedef struct _i2o_iop
+{
+       unsigned int base_class : 8;
+       unsigned int sub_class  : 8;
+       unsigned int prg_code   : 8;
+} I2OIOP;
+
+/* I2O Outbound Message Interrupt Status Register */
+typedef struct _i2o_om_stat
+{
+       unsigned int rsvd0 : 26;
+       unsigned int opqi  : 1;
+       unsigned int rsvd1 : 1;
+       unsigned int odi   : 1;
+       unsigned int rsvd2 : 1;
+       unsigned int om1i  : 1;
+       unsigned int om0i  : 1;
+} I2OOMSTAT;
+
+/* I2O inbound Message Interrupt Status Register */
+typedef struct _i2o_im_stat
+{
+       unsigned int rsvd0 : 23;
+       unsigned int ofoi  : 1;
+       unsigned int ipoi  : 1;
+       unsigned int rsvd1 : 1;
+       unsigned int ipqi  : 1;
+       unsigned int mci   : 1;
+       unsigned int idi   : 1;
+       unsigned int rsvd2 : 1;
+       unsigned int im1i  : 1;
+       unsigned int im0i  : 1;
+} I2OIMSTAT;
+
+/**
+ Enable the interrupt associated with in/out bound msg
+
+ Inbound message interrupt generated by PCI master and serviced by local processor
+ local processor needs to enable its inbound interrupts it wants to handle (LOCAL)
+
+ Outbound message interrupt generated by local processor and serviced by PCI master
+ PCI master needs to enable the devices' outbound interrupts it wants to handle (REMOTE)
+ **/
+extern I2OSTATUS I2OMsgEnable( LOCATION,            /*  REMOTE/LOCAL   */
+                               unsigned int base,   /* pcsrbar/eumbbar */
+                               unsigned char n );   /* b'1' - msg 0
+                                                                            * b'10'- msg 1
+                                                                            * b'11'- both
+                                                                            */
+
+/**
+ Disable the interrupt associated with in/out bound msg
+
+ local processor needs to disable its inbound interrupts it is not interested (LOCAL)
+
+ PCI master needs to disable outbound interrupts of devices it is not interested (REMOTE)
+ **/
+extern I2OSTATUS I2OMsgDisable( LOCATION,          /*  REMOTE/LOCAL   */
+                                unsigned int base, /* pcsrbar/eumbbar */
+                                unsigned char n ); /* b'1' - msg 0
+                                                                           * b'10'- msg 1
+                                                                           * b'11'- both
+                                                                           */
+
+/**
+ Read the msg register either from local inbound msg 0/1,
+ or an outbound msg 0/1 of devices.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, outbound msg of the device is read.
+ Otherwise local inbound msg is read.
+ **/
+extern I2OSTATUS I2OMsgGet ( LOCATION,                 /* REMOTE/LOCAL */
+                             unsigned int base,        /*pcsrbar/eumbbar */
+                             unsigned int n,           /* 0 or 1 */
+                             unsigned int *msg );
+
+/**
+ Write to nth Msg register either on local outbound msg 0/1,
+ or aninbound msg 0/1 of devices
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, inbound msg on the device is written.
+ Otherwise local outbound msg is written.
+ **/
+extern I2OSTATUS I2OMsgPost( LOCATION,                 /* REMOTE/LOCAL */
+                                unsigned int base,        /*pcsrbar/eumbbar */
+                                unsigned int n,           /* 0 or 1 */
+                                unsigned int msg );
+
+/**
+ Enable the In/Out DoorBell Interrupt
+
+ InDoorBell interrupt is generated by PCI master and serviced by local processor
+ local processor needs to enable its inbound doorbell interrupts it wants to handle
+ OutDoorbell interrupt is generated by local processor and serviced by PCI master
+ PCI master needs to enable outbound doorbell interrupts of the devices it wants to handle
+ **/
+extern I2OSTATUS I2ODBEnable( LOCATION,            /*  REMOTE/LOCAL   */
+                              unsigned int base,   /* pcsrbar/eumbbar */
+                              unsigned int in_db );/* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+
+/**
+ Disable the In/Out DoorBell Interrupt
+
+ local processor needs to disable its inbound doorbell interrupts it is not interested
+
+ PCI master needs to disable outbound doorbell interrupts of devices it is not interested
+
+ **/
+extern I2OSTATUS I2ODBDisable( LOCATION,              /*  REMOTE/LOCAL   */
+                               unsigned int base,     /* pcsrbar/eumbbar */
+                               unsigned int in_db );  /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+
+/**
+ Read a local indoorbell register, or an outdoorbell of devices.
+ Reading a doorbell register, the register will be cleared.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, outdoorbell register on the device is read.
+ Otherwise local in doorbell is read
+ **/
+extern unsigned int I2ODBGet( LOCATION,             /*  REMOTE/LOCAL   */
+                              unsigned int base);   /* pcsrbar/eumbbar */
+
+/**
+ Write to a local outdoorbell register, or an indoorbell register of devices.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, in doorbell register on the device is written.
+ Otherwise local out doorbell is written
+ **/
+extern void I2ODBPost( LOCATION,                 /*  REMOTE/LOCAL   */
+                       unsigned int base,        /* pcsrbar/eumbbar */
+                       unsigned int msg );       /*   in   / out    */
+
+/**
+ Read the outbound msg unit interrupt status of devices. Reading an interrupt status register,
+ the register will be cleared.
+
+ The outbound interrupt status is AND with the outbound
+ interrupt mask. The result is returned.
+ PCI master must pass the pcsrbar to the function.
+ **/
+extern I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT * );
+
+/**
+ Read the inbound msg unit interrupt status. Reading an interrupt status register,
+ the register will be cleared.
+
+ The inbound interrupt status is AND with the inbound
+ interrupt mask. The result is returned.
+ Local process must pass its eumbbar to the function.
+**/
+extern I2OSTATUS I2OInMsgStatGet( unsigned int eumbbar, I2OIMSTAT * );
+
+/**
+ Configure the I2O FIFO, including QBAR, IFHPR/IFTPR,IPHPR/IPTPR,OFHPR/OFTPR, OPHPR/OPTPR,
+ MUCR.
+ **/
+extern I2OSTATUS I2OFIFOInit( unsigned int eumbbar,
+                                             QUEUE_SIZE,
+                                             unsigned int qba);/* queue base address that must be aligned at 1M */
+/**
+ Enable the circular queue
+ **/
+extern I2OSTATUS I2OFIFOEnable( unsigned int eumbbar );
+
+/**
+ Disable the circular queue
+ **/
+extern void I2OFIFODisable( unsigned int eumbbar );
+
+/**
+ Enable the circular queue interrupt
+ PCI master enables outbound FIFO interrupt of device
+ Device enables its inbound FIFO interrupt
+ **/
+extern void I2OFIFOIntEnable( LOCATION, unsigned int base  );
+
+/**
+ Disable the circular queue interrupt
+ PCI master disables outbound FIFO interrupt of device
+ Device disables its inbound FIFO interrupt
+ **/
+extern void I2OFIFOIntDisable( LOCATION, unsigned int base );
+
+/**
+ Enable the circular queue overflow interrupt
+ **/
+extern void I2OFIFOOverflowIntEnable( unsigned int eumbbar );
+
+/**
+ Disable the circular queue overflow interrupt
+ **/
+extern void I2OFIFOOverflowIntDisable( unsigned int eumbbar );
+
+/**
+ Allocate a free msg frame from free FIFO. 
+
+ PCI Master allocates a free msg frame through inbound queue port of device(IFQPR)
+ while local processor allocates a free msg frame from outbound free queue(OFTPR)
+
+ Unless both free queues are initialized, allocating a free MF will return 0xffffffff
+ **/
+extern I2OSTATUS I2OFIFOAlloc( LOCATION,
+                                              unsigned int base,
+                                              void         **pMsg);
+/**
+ Free a used msg frame back to free queue
+ PCI Master frees a MFA through outbound queue port of device(OFQPR)
+ while local processor frees a MFA into its inbound free queue(IFHPR)
+
+ Used msg frame does not need to be recycled in the order they
+ read
+
+ This function has to be called by PCI master to initialize Inbound free queue
+ and by device to initialize Outbound free queue before I2OFIFOAlloc can be used.
+ **/
+extern I2OSTATUS I2OFIFOFree( LOCATION,
+                                         unsigned int base,
+                                         void        *pMsg );
+
+/**
+ Post a msg into FIFO
+ PCI Master posts a msg through inbound queue port of device(IFQPR)
+ while local processor post a msg into its outbound post queue(OPHPR)
+
+ The total number of msg must be less than the max size of the queue
+ Otherwise queue overflow interrupt will assert.
+ **/
+extern I2OSTATUS I2OFIFOPost( LOCATION,
+                                     unsigned int base,
+                                     void         *pMsg );
+
+/**
+ Read a msg from FIFO
+ PCI Master reads a msg through outbound queue port of device(OFQPR)
+ while local processor reads a msg from its inbound post queue(IPTPR)
+ **/
+extern I2OSTATUS I2OFIFOGet( LOCATION,
+                                         unsigned int base,
+                                                         void     **pMsg );
+
+/**
+ Get the I2O PCI configuration identification register
+ **/
+extern I2OSTATUS I2OPCIConfigGet( LOCATION,
+                                          unsigned int base,
+                                                          I2OIOP *);
+
+#endif
diff --git a/mpc8240/drivers/i2o/Makefile b/mpc8240/drivers/i2o/Makefile
new file mode 100644 (file)
index 0000000..b409f0b
--- /dev/null
@@ -0,0 +1,126 @@
+##########################################################################
+#
+# $Id: Makefile,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and 
+#       distribute the SOFTWARE so long as this entire notice is retained 
+#       without alteration in any modified and/or redistributed versions, 
+#       and that such modified versions are clearly identified as such.  
+#       No licenses are granted by implication, estoppel or otherwise under 
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.  
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS 
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED 
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH 
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS 
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. 
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL 
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF 
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS 
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR 
+#       INABILITY TO USE THE SOFTWARE. 
+#
+# $Log: Makefile,v $
+# Revision 1.1  2000/11/20 17:22:33  wdenk
+#
+# * Added support for MBX860T (thanks to Rob Taylor)
+#
+# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+#   Work In Progress (TM); current status: boots to command line input.
+#   EPIC code non-functional (interrupts disabled), No net, No IDE.
+#
+# * Add support for Status LED
+#
+# * Optionally panic() to reboot instead of hanging
+#
+# * Misc bug fixes
+#
+# * All frequencies in HZ now (internally)
+#
+# * Add support for BOOTP Domain Name Server Option
+#
+# Revision 1.1.1.1  2000/11/14 16:54:07  robt
+# no message
+#
+# Revision 1.1.1.1  2000/11/14 14:49:39  robt
+# no message
+#
+# Revision 1.2  1999/02/05 01:55:54  wyin
+# modified to set up soft link for hearder files
+# compilable version with dink
+#
+# Revision 1.1  1999/02/03 18:57:23  wyin
+# Base line
+#
+# Revision 1.12  1998/11/20 01:34:55  wyin
+# Added INTMEM function and data structure.
+# Enabled DCACHE.
+# There is a minor problem with DCACHE, the cache policy had to be write-through.
+# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length.
+# But consequence measurement is fine.
+#
+#
+############################################################################
+TARGET = libi2o.a
+
+#DEBUG  = -g
+DEBUG   = 
+LST     = -Hanno -S
+OPTIM   = 
+CC      = /risc/tools/pkgs/metaware/bin/hcppc 
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc 
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG  = -l -fm
+AS      = /risc/tools/pkgs/metaware/bin/asppc
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -Qn -q -r
+LKCMD    =
+LINK    =  /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = i2o1.o i2o2.o
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+objects: i2o1.o
+
+clean: 
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+     
+.s.o:  
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:  
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+i2o1.o: i2o.h i2o1.c
+
+i2o2.o: i2o.h i2o2.s
diff --git a/mpc8240/drivers/i2o/Makefile_pc b/mpc8240/drivers/i2o/Makefile_pc
new file mode 100644 (file)
index 0000000..5fd13b6
--- /dev/null
@@ -0,0 +1,134 @@
+##########################################################################
+#
+#      makefile_pc for use with PC mksnt tools   dink32/drivers/i2o
+# $Id: Makefile_pc,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and 
+#       distribute the SOFTWARE so long as this entire notice is retained 
+#       without alteration in any modified and/or redistributed versions, 
+#       and that such modified versions are clearly identified as such.  
+#       No licenses are granted by implication, estoppel or otherwise under 
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.  
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS 
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED 
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH 
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS 
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. 
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL 
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER 
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF 
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS 
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR 
+#       INABILITY TO USE THE SOFTWARE. 
+#
+# $Log: Makefile_pc,v $
+# Revision 1.1  2000/11/20 17:22:33  wdenk
+#
+# * Added support for MBX860T (thanks to Rob Taylor)
+#
+# * Added support for Sandpoint8240 (thanks to Rob Taylor); this is
+#   Work In Progress (TM); current status: boots to command line input.
+#   EPIC code non-functional (interrupts disabled), No net, No IDE.
+#
+# * Add support for Status LED
+#
+# * Optionally panic() to reboot instead of hanging
+#
+# * Misc bug fixes
+#
+# * All frequencies in HZ now (internally)
+#
+# * Add support for BOOTP Domain Name Server Option
+#
+# Revision 1.1.1.1  2000/11/14 16:54:07  robt
+# no message
+#
+# Revision 1.1.1.1  2000/11/14 14:49:39  robt
+# no message
+#
+# Revision 1.1  1999/06/11 20:05:26  maurie
+# support for compiling dink on PC
+#
+# Revision 1.2  1999/02/05 01:55:54  wyin
+# modified to set up soft link for hearder files
+# compilable version with dink
+#
+# Revision 1.1  1999/02/03 18:57:23  wyin
+# Base line
+#
+# Revision 1.12  1998/11/20 01:34:55  wyin
+# Added INTMEM function and data structure.
+# Enabled DCACHE.
+# There is a minor problem with DCACHE, the cache policy had to be write-through.
+# Otherwise, when power-on-reset, BlackBox cannot measure the scan chain length.
+# But consequence measurement is fine.
+#
+#
+############################################################################
+TARGET = libi2o.a
+
+#DEBUG  = -g
+DEBUG   = 
+LST     = -Hanno -S
+OPTIM   = 
+CC      = m:/old_tools/tools/hcppc/bin/hcppc 
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc 
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG  = -l -fm
+AS      = m:/old_tools/tools/hcppc/bin/asppc 
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -Qn -q -r
+LKCMD    =
+LINK    = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = i2o1.o i2o2.o
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+objects: i2o1.o
+
+clean: 
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+     
+.s.o:  
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:  
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+i2o1.o: i2o.h i2o1.c
+       $(CCobj) $<
+
+i2o2.o: i2o.h i2o2.s
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
diff --git a/mpc8240/drivers/i2o/i2o.h b/mpc8240/drivers/i2o/i2o.h
new file mode 100644 (file)
index 0000000..e82c723
--- /dev/null
@@ -0,0 +1,345 @@
+#ifndef I2O_H
+#define I2O_H
+/*********************************************************
+ * $Id: i2o.h,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+ *
+ * copyright @ Motorola, 1999
+ *********************************************************/
+
+#define I2O_REG_OFFSET 0x0004
+
+#define PCI_CFG_CLA    0x0B
+#define PCI_CFG_SCL    0x0A
+#define PCI_CFG_PIC    0x09
+
+#define I2O_IMR0 0x0050
+#define I2O_IMR1 0x0054
+#define I2O_OMR0 0x0058
+#define I2O_OMR1 0x005C
+
+#define I2O_ODBR 0x0060
+#define I2O_IDBR 0x0068
+
+#define I2O_OMISR  0x0030
+#define I2O_OMIMR  0x0034
+#define I2O_IMISR  0x0100
+#define I2O_IMIMR  0x0104
+
+/* accessable to PCI master but local processor */
+#define I2O_IFQPR  0x0040
+#define I2O_OFQPR  0x0044
+
+/* accessable to local processor */
+#define I2O_IFHPR  0x0120
+#define I2O_IFTPR  0x0128
+#define I2O_IPHPR  0x0130
+#define I2O_IPTPR  0x0138
+#define I2O_OFHPR  0x0140
+#define I2O_OFTPR  0x0148
+#define I2O_OPHPR  0x0150
+#define I2O_OPTPR  0x0158
+#define I2O_MUCR   0x0164
+#define I2O_QBAR   0x0170
+
+#define I2O_NUM_MSG 2
+
+typedef enum _i2o_status
+{
+       I2OSUCCESS = 0,
+       I2OINVALID,
+       I2OMSGINVALID,
+       I2ODBINVALID,
+       I2OQUEINVALID,
+       I2OQUEEMPTY,
+       I2OQUEFULL,
+       I2ONOEVENT,
+} I2OSTATUS;
+
+typedef enum _queue_size
+{
+    QSIZE_4K = 0x02,
+    QSIZE_8K = 0x04,
+    QSIZE_16K = 0x08,
+    QSIZE_32K = 0x10,
+    QSIZe_64K = 0x20,
+} QUEUE_SIZE;
+
+typedef enum _location
+{
+    LOCAL = 0,     /* used by local processor to access its own on board device,
+                     local processor's eumbbar is required */
+    REMOTE,        /* used by PCI master to access the devices on its PCI device,
+                     device's pcsrbar is required */
+} LOCATION;
+
+/* door bell */
+typedef enum _i2o_in_db
+{
+  IN_DB = 1,
+  MC,         /* machine check */
+} I2O_IN_DB;
+
+/* I2O PCI configuration identification */
+typedef struct _i2o_iop
+{
+       unsigned int base_class : 8;
+       unsigned int sub_class  : 8;
+       unsigned int prg_code   : 8;
+} I2OIOP;
+
+/* I2O Outbound Message Interrupt Status Register */
+typedef struct _i2o_om_stat
+{
+       unsigned int rsvd0 : 26;
+       unsigned int opqi  : 1;
+       unsigned int rsvd1 : 1;
+       unsigned int odi   : 1;
+       unsigned int rsvd2 : 1;
+       unsigned int om1i  : 1;
+       unsigned int om0i  : 1;
+} I2OOMSTAT;
+
+/* I2O inbound Message Interrupt Status Register */
+typedef struct _i2o_im_stat
+{
+       unsigned int rsvd0 : 23;
+       unsigned int ofoi  : 1;
+       unsigned int ipoi  : 1;
+       unsigned int rsvd1 : 1;
+       unsigned int ipqi  : 1;
+       unsigned int mci   : 1;
+       unsigned int idi   : 1;
+       unsigned int rsvd2 : 1;
+       unsigned int im1i  : 1;
+       unsigned int im0i  : 1;
+} I2OIMSTAT;
+
+/**
+ Enable the interrupt associated with in/out bound msg
+
+ Inbound message interrupt generated by PCI master and serviced by local processor
+ local processor needs to enable its inbound interrupts it wants to handle (LOCAL)
+
+ Outbound message interrupt generated by local processor and serviced by PCI master
+ PCI master needs to enable the devices' outbound interrupts it wants to handle (REMOTE)
+ **/
+extern I2OSTATUS I2OMsgEnable( LOCATION,            /*  REMOTE/LOCAL   */
+                               unsigned int base,   /* pcsrbar/eumbbar */
+                               unsigned char n );   /* b'1' - msg 0
+                                                                            * b'10'- msg 1
+                                                                            * b'11'- both
+                                                                            */
+
+/**
+ Disable the interrupt associated with in/out bound msg
+
+ local processor needs to disable its inbound interrupts it is not interested (LOCAL)
+
+ PCI master needs to disable outbound interrupts of devices it is not interested (REMOTE)
+ **/
+extern I2OSTATUS I2OMsgDisable( LOCATION,          /*  REMOTE/LOCAL   */
+                                unsigned int base, /* pcsrbar/eumbbar */
+                                unsigned char n ); /* b'1' - msg 0
+                                                                           * b'10'- msg 1
+                                                                           * b'11'- both
+                                                                           */
+
+/**
+ Read the msg register either from local inbound msg 0/1,
+ or an outbound msg 0/1 of devices.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, outbound msg of the device is read.
+ Otherwise local inbound msg is read.
+ **/
+extern I2OSTATUS I2OMsgGet ( LOCATION,                 /* REMOTE/LOCAL */
+                             unsigned int base,        /*pcsrbar/eumbbar */
+                             unsigned int n,           /* 0 or 1 */
+                             unsigned int *msg );
+
+/**
+ Write to nth Msg register either on local outbound msg 0/1,
+ or aninbound msg 0/1 of devices
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, inbound msg on the device is written.
+ Otherwise local outbound msg is written.
+ **/
+extern I2OSTATUS I2OMsgPost( LOCATION,                 /* REMOTE/LOCAL */
+                                unsigned int base,        /*pcsrbar/eumbbar */
+                                unsigned int n,           /* 0 or 1 */
+                                unsigned int msg );
+
+/**
+ Enable the In/Out DoorBell Interrupt
+
+ InDoorBell interrupt is generated by PCI master and serviced by local processor
+ local processor needs to enable its inbound doorbell interrupts it wants to handle
+ OutDoorbell interrupt is generated by local processor and serviced by PCI master
+ PCI master needs to enable outbound doorbell interrupts of the devices it wants to handle
+ **/
+extern I2OSTATUS I2ODBEnable( LOCATION,            /*  REMOTE/LOCAL   */
+                              unsigned int base,   /* pcsrbar/eumbbar */
+                              unsigned int in_db );/* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+
+/**
+ Disable the In/Out DoorBell Interrupt
+
+ local processor needs to disable its inbound doorbell interrupts it is not interested
+
+ PCI master needs to disable outbound doorbell interrupts of devices it is not interested
+
+ **/
+extern I2OSTATUS I2ODBDisable( LOCATION,              /*  REMOTE/LOCAL   */
+                               unsigned int base,     /* pcsrbar/eumbbar */
+                               unsigned int in_db );  /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+
+/**
+ Read a local indoorbell register, or an outdoorbell of devices.
+ Reading a doorbell register, the register will be cleared.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, outdoorbell register on the device is read.
+ Otherwise local in doorbell is read
+ **/
+extern unsigned int I2ODBGet( LOCATION,             /*  REMOTE/LOCAL   */
+                              unsigned int base);   /* pcsrbar/eumbbar */
+
+/**
+ Write to a local outdoorbell register, or an indoorbell register of devices.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, in doorbell register on the device is written.
+ Otherwise local out doorbell is written
+ **/
+extern void I2ODBPost( LOCATION,                 /*  REMOTE/LOCAL   */
+                       unsigned int base,        /* pcsrbar/eumbbar */
+                       unsigned int msg );       /*   in   / out    */
+
+/**
+ Read the outbound msg unit interrupt status of devices. Reading an interrupt status register,
+ the register will be cleared.
+
+ The outbound interrupt status is AND with the outbound
+ interrupt mask. The result is returned.
+ PCI master must pass the pcsrbar to the function.
+ **/
+extern I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT * );
+
+/**
+ Read the inbound msg unit interrupt status. Reading an interrupt status register,
+ the register will be cleared.
+
+ The inbound interrupt status is AND with the inbound
+ interrupt mask. The result is returned.
+ Local process must pass its eumbbar to the function.
+**/
+extern I2OSTATUS I2OInMsgStatGet( unsigned int eumbbar, I2OIMSTAT * );
+
+/**
+ Configure the I2O FIFO, including QBAR, IFHPR/IFTPR,IPHPR/IPTPR,OFHPR/OFTPR, OPHPR/OPTPR,
+ MUCR.
+ **/
+extern I2OSTATUS I2OFIFOInit( unsigned int eumbbar,
+                                             QUEUE_SIZE,
+                                             unsigned int qba);/* queue base address that must be aligned at 1M */
+/**
+ Enable the circular queue
+ **/
+extern I2OSTATUS I2OFIFOEnable( unsigned int eumbbar );
+
+/**
+ Disable the circular queue
+ **/
+extern void I2OFIFODisable( unsigned int eumbbar );
+
+/**
+ Enable the circular queue interrupt
+ PCI master enables outbound FIFO interrupt of device
+ Device enables its inbound FIFO interrupt
+ **/
+extern void I2OFIFOIntEnable( LOCATION, unsigned int base  );
+
+/**
+ Disable the circular queue interrupt
+ PCI master disables outbound FIFO interrupt of device
+ Device disables its inbound FIFO interrupt
+ **/
+extern void I2OFIFOIntDisable( LOCATION, unsigned int base );
+
+/**
+ Enable the circular queue overflow interrupt
+ **/
+extern void I2OFIFOOverflowIntEnable( unsigned int eumbbar );
+
+/**
+ Disable the circular queue overflow interrupt
+ **/
+extern void I2OFIFOOverflowIntDisable( unsigned int eumbbar );
+
+/**
+ Allocate a free msg frame from free FIFO. 
+
+ PCI Master allocates a free msg frame through inbound queue port of device(IFQPR)
+ while local processor allocates a free msg frame from outbound free queue(OFTPR)
+
+ Unless both free queues are initialized, allocating a free MF will return 0xffffffff
+ **/
+extern I2OSTATUS I2OFIFOAlloc( LOCATION,
+                                              unsigned int base,
+                                              void         **pMsg);
+/**
+ Free a used msg frame back to free queue
+ PCI Master frees a MFA through outbound queue port of device(OFQPR)
+ while local processor frees a MFA into its inbound free queue(IFHPR)
+
+ Used msg frame does not need to be recycled in the order they
+ read
+
+ This function has to be called by PCI master to initialize Inbound free queue
+ and by device to initialize Outbound free queue before I2OFIFOAlloc can be used.
+ **/
+extern I2OSTATUS I2OFIFOFree( LOCATION,
+                                         unsigned int base,
+                                         void        *pMsg );
+
+/**
+ Post a msg into FIFO
+ PCI Master posts a msg through inbound queue port of device(IFQPR)
+ while local processor post a msg into its outbound post queue(OPHPR)
+
+ The total number of msg must be less than the max size of the queue
+ Otherwise queue overflow interrupt will assert.
+ **/
+extern I2OSTATUS I2OFIFOPost( LOCATION,
+                                     unsigned int base,
+                                     void         *pMsg );
+
+/**
+ Read a msg from FIFO
+ PCI Master reads a msg through outbound queue port of device(OFQPR)
+ while local processor reads a msg from its inbound post queue(IPTPR)
+ **/
+extern I2OSTATUS I2OFIFOGet( LOCATION,
+                                         unsigned int base,
+                                                         void     **pMsg );
+
+/**
+ Get the I2O PCI configuration identification register
+ **/
+extern I2OSTATUS I2OPCIConfigGet( LOCATION,
+                                          unsigned int base,
+                                                          I2OIOP *);
+
+#endif
diff --git a/mpc8240/drivers/i2o/i2o1.c b/mpc8240/drivers/i2o/i2o1.c
new file mode 100644 (file)
index 0000000..355aa19
--- /dev/null
@@ -0,0 +1,890 @@
+/*********************************************************
+ * $Id
+ *
+ * copyright @ Motorola, 1999
+ *********************************************************/
+#include "i2o.h"
+
+extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
+#pragma Alias( load_runtime_reg, "load_runtime_reg" );
+
+extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
+#pragma Alias( store_runtime_reg, "store_runtime_reg" );
+
+typedef struct _fifo_stat
+{
+    QUEUE_SIZE   qsz;
+    unsigned int qba;
+} FIFOSTAT;
+
+FIFOSTAT fifo_stat = { QSIZE_4K, 0xffffffff };
+
+/**********************************************************************************
+ * function: I2OMsgEnable
+ *
+ * description: Enable the interrupt associated with in/out bound msg
+ *              return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
+ *
+ *              All previously enabled interrupts are preserved.
+ * note:
+ * Inbound message interrupt generated by PCI master and serviced by local processor
+ * Outbound message interrupt generated by local processor and serviced by PCI master
+ *
+ * local processor needs to enable its inbound interrupts it wants to handle(LOCAL)
+ * PCI master needs to enable the outbound interrupts of devices it wants to handle(REMOTE)
+ ************************************************************************************/
+I2OSTATUS I2OMsgEnable ( LOCATION loc,        /*  REMOTE/LOCAL   */
+                         unsigned int base,   /* pcsrbar/eumbbar */
+                         unsigned char n )    /* b'1' - msg 0
+                                              * b'10'- msg 1
+                                              * b'11'- both
+                                              */
+{
+    unsigned int reg, val;
+    if ( ( n & 0x3 ) == 0 )
+    {
+       /* neither msg 0, nor msg 1 */
+       return I2OMSGINVALID;
+    }
+
+    n = (~n) & 0x3;
+    /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base
+     *            LOCAL  : enable local inbound message, eumbbar as base
+     */
+    reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
+    val = load_runtime_reg( base, reg );
+
+    val &= 0xfffffffc; /* masked out the msg interrupt bits */
+    val |= n;          /* LSB are the one we want */
+    store_runtime_reg( base, reg, val );
+
+    return I2OSUCCESS;
+}
+
+/*********************************************************************************
+ * function: I2OMsgDisable
+ *
+ * description: Disable the interrupt associated with in/out bound msg
+ *              Other previously enabled interrupts are preserved.
+ *              return I2OSUCCESS if no error otherwise return I2OMSGINVALID
+ *
+ * note:
+ *  local processor needs to disable its inbound interrupts it is not interested(LOCAL)
+ *  PCI master needs to disable outbound interrupts of devices it is not interested(REMOTE)
+ *********************************************************************************/
+I2OSTATUS I2OMsgDisable( LOCATION loc,      /*  REMOTE/LOCAL   */
+                         unsigned int base, /* pcsrbar/eumbbar */
+                         unsigned char n )  /* b'1' - msg 0
+                                            * b'10'- msg 1
+                                            * b'11'- both
+                                            */
+{
+    unsigned int reg, val;
+    
+    if ( ( n & 0x3 ) == 0 )
+    {
+       /* neither msg 0, nor msg 1 */
+       return I2OMSGINVALID;
+    }
+
+    /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base
+     *            LOCAL  : disable local inbound message interrupt, eumbbar as base
+     */
+    reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
+    val = load_runtime_reg( base, reg );
+
+    val &= 0xfffffffc; /* masked out the msg interrupt bits */
+    val |= ( n & 0x3 );
+    store_runtime_reg( base, reg, val );
+
+    return I2OSUCCESS;
+    
+}
+
+/**************************************************************************
+ * function: I2OMsgGet
+ *
+ * description: Local processor reads the nth Msg register from its inbound msg,
+ *              or a PCI Master reads nth outbound msg from device
+ *
+ *              return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
+ *
+ * note:
+ * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed.
+ * If it is remote, outbound msg on the device is read; otherwise local inbound msg is read
+ *************************************************************************/
+I2OSTATUS I2OMsgGet ( LOCATION loc,             /* REMOTE/LOCAL */
+                         unsigned int base,        /*pcsrbar/eumbbar */
+                         unsigned int n,           /* 0 or 1 */
+                         unsigned int *msg )
+{
+    if ( n >= I2O_NUM_MSG || msg == 0 )
+    {
+       return I2OMSGINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* read the outbound msg of the device, pcsrbar as base */
+       *msg = load_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET );
+    }
+    else
+    {
+       /* read the inbound msg sent by PCI master, eumbbar as base */
+       *msg = load_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET );
+    }
+           
+    return I2OSUCCESS;
+}
+
+/***************************************************************
+ * function: I2OMsgPost
+ *
+ * description: Kahlua  writes to its nth outbound msg register
+ *              PCI master writes to nth inbound msg register of device
+ *
+ *              return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
+ *
+ * note:
+ * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed.
+ *
+ * If it is remote, inbound msg on the device is written; otherwise local outbound msg is written
+ ***************************************************************/
+I2OSTATUS I2OMsgPost( LOCATION loc,             /* REMOTE/LOCAL */
+                      unsigned int base,        /*pcsrbar/eumbbar */
+                      unsigned int n,           /* 0 or 1 */
+                      unsigned int msg )
+{
+    if ( n >= I2O_NUM_MSG )
+    {
+       return I2OMSGINVALID;
+    }
+    
+    if ( loc == REMOTE )
+    {
+       /* write to the inbound msg register of the device, pcsrbar as base  */
+       store_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET, msg );
+    }
+    else
+    {
+       /* write to the outbound msg register for PCI master to read, eumbbar as base */
+       store_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET, msg );      
+    }
+    
+    return I2OSUCCESS;
+}
+
+/***********************************************************************
+ * function: I2ODBEnable
+ *
+ * description: Local processor enables it's inbound doorbell interrupt
+ *              PCI master enables outbound doorbell interrupt of devices
+ *              Other previously enabled interrupts are preserved.
+ *              Return I2OSUCCESS if no error otherwise return I2ODBINVALID
+ *
+ * note:
+ * In DoorBell interrupt is generated by PCI master and serviced by local processor
+ * Out Doorbell interrupt is generated by local processor and serviced by PCI master
+ *
+ * Out Doorbell interrupt is generated by local processor and serviced by PCI master
+ * PCI master needs to enable the outbound doorbell interrupts of device it wants to handle
+ **********************************************************************/
+I2OSTATUS I2ODBEnable( LOCATION loc,        /*  REMOTE/LOCAL   */
+                  unsigned int base,   /* pcsrbar/eumbbar */
+                  unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+{
+
+    /* LOCATION - REMOTE : PCI master initializes outbound doorbell message of device
+     *            LOCAL  : Kahlua initializes its inbound doorbell message
+     */
+    unsigned int val;
+
+    if ( loc == LOCAL && ( in_db & 0x3 ) == 0 )
+    {
+       return I2ODBINVALID;
+    }
+    
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is base */
+       val = load_runtime_reg( base, I2O_OMIMR );
+       val &= 0xfffffff7;
+        store_runtime_reg( base, I2O_OMIMR , val );        
+    }
+    else
+    {
+       /* eumbbar is base */
+       val = load_runtime_reg( base, I2O_IMIMR);
+        in_db = ( (~in_db) & 0x3 ) << 3;
+        val = ( val & 0xffffffe7) | in_db;
+        store_runtime_reg( base,  I2O_IMIMR, val );        
+    }
+
+    return I2OSUCCESS;
+}
+
+/**********************************************************************************
+ * function: I2ODBDisable
+ *
+ * description: local processor disables its inbound DoorBell Interrupt
+ *              PCI master disables outbound DoorBell interrupt of device
+ *              Other previously enabled interrupts are preserved.
+ *              return I2OSUCCESS if no error.Otherwise return I2ODBINVALID
+ *
+ * note:
+ * local processor needs to disable its inbound doorbell interrupts it is not interested
+ *
+ * PCI master needs to disable outbound doorbell interrupts of device it is not interested
+ ************************************************************************************/
+I2OSTATUS I2ODBDisable( LOCATION loc,          /*  REMOTE/LOCAL   */
+                        unsigned int base,     /* pcsrbar/eumbbar */
+                        unsigned int in_db )   /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+{
+    /* LOCATION - REMOTE : handle device's out bound message initialization
+     *            LOCAL  : handle local in bound message initialization
+     */
+    unsigned int val;
+
+    if ( loc == LOCAL && ( in_db & 0x3 ) == 0 )
+    {
+           return I2ODBINVALID;
+    }
+    
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base */
+       val = load_runtime_reg( base, I2O_OMIMR );
+       val |= 0x8;
+        store_runtime_reg( base, I2O_OMIMR, val );         
+    }
+    else
+    {
+           val = load_runtime_reg( base, I2O_IMIMR);
+            in_db = ( in_db & 0x3 ) << 3;
+            val |= in_db;
+            store_runtime_reg( base, I2O_IMIMR, val );             
+    }
+
+    return I2OSUCCESS;
+}
+
+/**********************************************************************************
+ * function: I2ODBGet
+ *
+ * description: Local processor reads its in doorbell register,
+ *              PCI master reads the outdoorbell register of device.
+ *              After a doorbell register is read, the whole register will be cleared.
+ *              Otherwise, HW keeps generating interrupt.
+ *
+ * note:
+ * If it is not local, pcsrbar must be passed to the function.
+ * Otherwise eumbbar is passed.
+ *
+ * If it is remote, out doorbell register on the device is read.
+ * Otherwise local in doorbell is read
+ *
+ * If the register is not cleared by write to it, any remaining bit of b'1's
+ * will cause interrupt pending.
+ *********************************************************************************/
+unsigned int I2ODBGet( LOCATION loc,         /*  REMOTE/LOCAL   */
+                       unsigned int base)    /* pcsrbar/eumbbar */
+{
+    unsigned int msg, val;
+
+    if ( loc == REMOTE )
+    {
+       /* read outbound doorbell register of device, pcsrbar is the base */
+        val = load_runtime_reg( base, I2O_ODBR );      
+        msg = val & 0xe0000000;
+        store_runtime_reg( base, I2O_ODBR, val ); /* clear the register */
+    }
+    else
+    {
+       /* read the inbound doorbell register, eumbbar is the base */
+        val = load_runtime_reg( base, I2O_IDBR );
+        store_runtime_reg( base, I2O_IDBR, val ); /* clear the register */
+       msg = val;
+    }
+
+    return msg;
+}
+
+/**********************************************************************
+ * function: I2ODBPost
+ *
+ * description: local processor writes to a outbound doorbell register,
+ *              PCI master writes to the inbound doorbell register of device
+ *
+ * note:
+ * If it is not local, pcsrbar must be passed to the function.
+ * Otherwise eumbbar is passed.
+ *
+ * If it is remote, in doorbell register on the device is written.
+ * Otherwise local out doorbell is written
+ *********************************************************************/
+void I2ODBPost( LOCATION loc,             /*  REMOTE/LOCAL   */
+                unsigned int base,        /* pcsrbar/eumbbar */
+                unsigned int msg )        /*   in   / out    */
+{
+    if ( loc == REMOTE )
+    {
+       /* write to inbound doorbell register of device, pcsrbar is the base */
+       store_runtime_reg( base, I2O_IDBR, msg );
+    }
+    else
+    {
+       /* write to local outbound doorbell register, eumbbar is the base */
+       store_runtime_reg( base, I2O_ODBR, msg & 0x1fffffff );
+    }
+
+}
+
+/********************************************************************
+ * function: I2OOutMsgStatGet
+ *
+ * description: PCI master reads device's outbound msg unit interrupt status.
+ *              Reading an interrupt status register,
+ *              the register will be cleared.
+ *
+ *              The value of the status register is AND with the outbound
+ *              interrupt mask and result is returned.
+ *
+ * note:
+ * pcsrbar must be passed to the function.
+ ********************************************************************/
+I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT *val )
+{
+    unsigned int stat;
+    unsigned int mask;
+
+    if ( val == 0 )
+    {
+           return I2OINVALID;
+    }
+    
+    /* read device's outbound status */
+    stat = load_runtime_reg( pcsrbar, I2O_OMISR );
+    mask = load_runtime_reg( pcsrbar, I2O_OMIMR );
+    store_runtime_reg( pcsrbar, I2O_OMISR, stat & 0xffffffd7);
+    
+    stat &= mask;
+    val->rsvd0 = ( stat & 0xffffffc0 ) >> 6;
+    val->opqi  = ( stat & 0x00000020 ) >> 5;
+    val->rsvd1 = ( stat & 0x00000010 ) >> 4;
+    val->odi   = ( stat & 0x00000008 ) >> 3;
+    val->rsvd2 = ( stat & 0x00000004 ) >> 2;
+    val->om1i  = ( stat & 0x00000002 ) >> 1;
+    val->om0i  = ( stat & 0x00000001 );
+
+    return I2OSUCCESS;   
+}
+
+/********************************************************************
+ * function: I2OInMsgStatGet
+ *
+ * description: Local processor reads its inbound msg unit interrupt status.
+ *              Reading an interrupt status register,
+ *              the register will be cleared.
+ *
+ *              The inbound msg interrupt status is AND with the inbound
+ *              msg interrupt mask and result is returned.
+ *
+ * note:
+ * eumbbar must be passed to the function.
+ ********************************************************************/
+I2OSTATUS I2OInMsgStatGet(unsigned int eumbbar, I2OIMSTAT *val)
+{
+    unsigned int stat;
+    unsigned int mask;
+
+    if ( val == 0 )
+    {
+           return I2OINVALID;
+    }
+    
+    /* read device's outbound status */
+    stat = load_runtime_reg( eumbbar, I2O_OMISR );
+    mask = load_runtime_reg( eumbbar, I2O_OMIMR );
+    store_runtime_reg( eumbbar, I2O_OMISR, stat & 0xffffffe7 );
+
+    stat &= mask;
+    val->rsvd0 = ( stat & 0xfffffe00 ) >> 9;
+    val->ofoi  = ( stat & 0x00000100 ) >> 8;
+    val->ipoi  = ( stat & 0x00000080 ) >> 7;
+    val->rsvd1 = ( stat & 0x00000040 ) >> 6;
+    val->ipqi  = ( stat & 0x00000020 ) >> 5;
+    val->mci   = ( stat & 0x00000010 ) >> 4;
+    val->idi   = ( stat & 0x00000008 ) >> 3;
+    val->rsvd2 = ( stat & 0x00000004 ) >> 2;
+    val->im1i  = ( stat & 0x00000002 ) >> 1;
+    val->im0i  = ( stat & 0x00000001 );
+    
+    return I2OSUCCESS;
+          
+}
+
+/***********************************************************
+ * function: I2OFIFOInit
+ *
+ * description: Configure the I2O FIFO, including QBAR,
+ *              IFHPR/IFTPR, IPHPR/IPTPR, OFHPR/OFTPR,
+ *              OPHPR/OPTPR, MUCR.
+ *
+ *              return I2OSUCCESS if no error,
+ *              otherwise return I2OQUEINVALID
+ *
+ * note: It is NOT this driver's responsibility of initializing
+ *       MFA blocks, i.e., FIFO queue itself. The MFA blocks
+ *       must be initialized before I2O unit can be used.
+ ***********************************************************/
+I2OSTATUS I2OFIFOInit( unsigned int eumbbar,
+                      QUEUE_SIZE   sz,      /* value of CQS of MUCR */
+                      unsigned int qba)     /* queue base address that must be aligned at 1M */
+{
+    
+    if ( ( qba & 0xfffff ) != 0 )
+    {
+       /* QBA must be aligned at 1Mbyte boundary */
+       return I2OQUEINVALID;
+    }
+
+    store_runtime_reg( eumbbar, I2O_QBAR, qba );
+    store_runtime_reg( eumbbar, I2O_MUCR, (unsigned int)sz );
+    store_runtime_reg( eumbbar, I2O_IFHPR, qba );
+    store_runtime_reg( eumbbar, I2O_IFTPR, qba );
+    store_runtime_reg( eumbbar, I2O_IPHPR, qba + 1 * ( sz << 11 ));
+    store_runtime_reg( eumbbar, I2O_IPTPR, qba + 1 * ( sz << 11 ));
+    store_runtime_reg( eumbbar, I2O_OFHPR, qba + 2 * ( sz << 11 ));
+    store_runtime_reg( eumbbar, I2O_OFTPR, qba + 2 * ( sz << 11 ));    
+    store_runtime_reg( eumbbar, I2O_OPHPR, qba + 3 * ( sz << 11 ));
+    store_runtime_reg( eumbbar, I2O_OPTPR, qba + 3 * ( sz << 11 ));
+
+    fifo_stat.qsz = sz;
+    fifo_stat.qba = qba;
+
+    return I2OSUCCESS;
+}
+
+/**************************************************
+ * function: I2OFIFOEnable
+ *
+ * description: Enable the circular queue
+ *              return I2OSUCCESS if no error.
+ *              Otherwise I2OQUEINVALID is returned.
+ *
+ * note:
+ *************************************************/
+I2OSTATUS I2OFIFOEnable( unsigned int eumbbar )
+{
+    unsigned int val;
+
+    if ( fifo_stat.qba == 0xfffffff )
+    {
+       return I2OQUEINVALID;
+    }
+           
+    val = load_runtime_reg( eumbbar, I2O_MUCR );
+    store_runtime_reg( eumbbar, I2O_MUCR, val | 0x1 );
+
+    return I2OSUCCESS;
+}
+
+/**************************************************
+ * function: I2OFIFODisable
+ *
+ * description: Disable the circular queue
+ *
+ * note:
+ *************************************************/
+void I2OFIFODisable( unsigned int eumbbar )
+{
+    if ( fifo_stat.qba == 0xffffffff )
+    {
+       /* not enabled */
+       return;
+    }
+    
+    unsigned int val = load_runtime_reg( eumbbar, I2O_MUCR );
+    store_runtime_reg( eumbbar, I2O_MUCR, val & 0xfffffffe );
+}
+
+/****************************************************
+ * function: I2OFIFOAlloc
+ *
+ * description: Allocate a free MFA from free FIFO.
+ *              return I2OSUCCESS if no error.
+ *              return I2OQUEEMPTY if no more free MFA.
+ *              return I2OINVALID on other errors.
+ *
+ *              A free MFA must be allocated before a
+ *              message can be posted.
+ *
+ * note:
+ * PCI Master allocates a free MFA from inbound queue of device
+ * (pcsrbar is the base,) through the inbound queue port of device
+ * while local processor allocates a free MFA from its outbound
+ * queue (eumbbar is the base.)
+ *
+ ****************************************************/
+I2OSTATUS I2OFIFOAlloc( LOCATION loc,
+                       unsigned int base,
+                       void         **pMsg )
+{
+    I2OSTATUS stat = I2OSUCCESS;
+    void *pHdr, *pTil;
+    
+    if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff )
+    {
+       /* not configured */
+       return I2OQUEINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base and read the inbound free tail ptr */
+       pTil = (void *)load_runtime_reg( base, I2O_IFQPR );
+        if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF )
+        {
+           stat = I2OQUEEMPTY;
+        }
+       else
+        {
+           *pMsg = pTil;
+       }
+    }
+    else
+    {
+       /* eumbbar is the base and read the outbound free tail ptr */
+       pHdr = (void *)load_runtime_reg( base, I2O_OFHPR ); /* queue head */
+       pTil = (void *)load_runtime_reg( base, I2O_OFTPR ); /* queue tail */
+
+       /* check underflow */
+       if ( pHdr == pTil )
+       {
+           /* hdr and til point to the same fifo item, no free MFA */
+            stat = I2OQUEEMPTY;
+       }
+       else
+       {
+         /* update OFTPR */
+         *pMsg = (void *)(*(unsigned char *)pTil);
+         pTil = (void *)((unsigned int)pTil + 4);
+         if ( (unsigned int)pTil == fifo_stat.qba + ( 4 * ( fifo_stat.qsz << 11 ) ) )
+         {
+               /* reach the upper limit */
+               pTil = (void *)(fifo_stat.qba + ( 3 * (fifo_stat.qsz << 11) ));
+         }
+         store_runtime_reg( base, I2O_OFTPR, (unsigned int)pTil );
+       }
+    }
+    
+    return stat;
+}
+
+/******************************************************
+ * function: I2OFIFOFree
+ *
+ * description: Free a used MFA back to free queue after
+ *              use.
+ *              return I2OSUCCESS if no error.
+ *              return I2OQUEFULL if inbound free queue
+ *              overflow
+ *
+ * note: PCI Master frees a MFA into device's outbound queue
+ *       (OFQPR) while local processor frees a MFA into its
+ *       inbound queue (IFHPR). 
+ *****************************************************/
+I2OSTATUS I2OFIFOFree( LOCATION loc,
+                 unsigned int base,
+                 void *pMsg )
+{
+    void **pHdr, **pTil;
+    I2OSTATUS stat = I2OSUCCESS;
+    
+    if ( fifo_stat.qba == 0xffffffff || pMsg == 0 )
+    {
+           return I2OQUEINVALID;
+    }
+    
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base */       
+       store_runtime_reg( base, I2O_OFQPR, (unsigned int)pMsg );
+    }
+    else
+    {
+       /* eumbbar is the base */
+       pHdr = (void **)load_runtime_reg( base, I2O_IFHPR );
+        pTil = (void **)load_runtime_reg( base, I2O_IFTPR );
+       
+       /* store MFA */
+       *pHdr = pMsg;
+
+       /* update IFHPR */
+       pHdr += 4;
+
+       if ( (unsigned int)pHdr == fifo_stat.qba + ( fifo_stat.qsz << 11 ) )
+       {
+         /* reach the upper limit */
+         pHdr = (void **)fifo_stat.qba;
+       }
+
+       /* check inbound free queue overflow */
+       if ( pHdr != pTil )
+       {
+          store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr);
+        }
+       else
+       {
+           stat = I2OQUEFULL;
+       }
+
+    }
+
+    return stat;
+    
+}
+
+/*********************************************
+ * function: I2OFIFOPost
+ *
+ * description: Post a msg into FIFO post queue
+ *              the value of msg must be the one
+ *              returned by I2OFIFOAlloc
+ *
+ * note: PCI Master posts a msg into device's inbound queue
+ *       (IFQPR) while local processor post a msg into device's
+ *       outbound queue (OPHPR)
+ *********************************************/
+I2OSTATUS I2OFIFOPost( LOCATION loc,
+                      unsigned int base,
+                      void *pMsg )
+{
+    void **pHdr, **pTil;
+    I2OSTATUS stat = I2OSUCCESS;
+    
+    if ( fifo_stat.qba == 0xffffffff || pMsg == 0 )
+    {
+       return I2OQUEINVALID;
+    }
+    
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base */
+       store_runtime_reg( base, I2O_IFQPR, (unsigned int)pMsg );
+    }
+    else
+    {
+       /* eumbbar is the base */
+       pHdr = (void **)load_runtime_reg( base, I2O_OPHPR );
+        pTil = (void **)load_runtime_reg( base, I2O_OPTPR );
+       
+       /* store MFA */
+       *pHdr = pMsg;
+
+       /* update IFHPR */
+       pHdr += 4;
+
+       if ( (unsigned int)pHdr == fifo_stat.qba + 3 * ( fifo_stat.qsz << 11 ) )
+       {
+         /* reach the upper limit */
+         pHdr = (void **)(fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) );
+       }
+
+       /* check post queue overflow */
+       if ( pHdr != pTil )
+       {
+          store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr);
+        }
+       else
+       {
+           stat = I2OQUEFULL;
+       }
+    }
+
+    return stat;
+}
+
+/************************************************
+ * function: I2OFIFOGet
+ *
+ * description:  Read a msg from FIFO
+ *               This function should be called
+ *               only when there is a corresponding
+ *               msg interrupt.
+ *
+ * note: PCI Master reads a msg from device's outbound queue
+ *       (OFQPR) while local processor reads a msg from device's
+ *       inbound queue (IPTPR)
+ ************************************************/
+I2OSTATUS I2OFIFOGet( LOCATION loc,
+                      unsigned int base,
+                      void **pMsg )
+{
+    I2OSTATUS stat = I2OSUCCESS;    
+    void *pHdr, *pTil;
+
+    if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff )
+    {
+       /* not configured */
+       return I2OQUEINVALID;
+    }
+    
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base */
+       pTil = (void *)load_runtime_reg( base, I2O_OFQPR );
+        if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF )
+        {
+           stat = I2OQUEEMPTY;
+        }
+       else
+        {
+           *pMsg = pTil;
+       }
+    }
+    else
+    {
+       /* eumbbar is the base and read the outbound free tail ptr */
+       pHdr = (void *)load_runtime_reg( base, I2O_IPHPR ); /* queue head */
+       pTil = (void *)load_runtime_reg( base, I2O_IPTPR ); /* queue tail */
+
+       /* check underflow */
+       if ( pHdr == pTil )
+       {
+           /* no free MFA */
+            stat = I2OQUEEMPTY;
+       }
+       else
+       {
+         /* update OFTPR */
+         *pMsg = (void *)(*(unsigned char *)pTil);
+         pTil = (void *)((unsigned int)pTil + 4);
+         if ( (unsigned int)pTil == fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) )
+         {
+               /* reach the upper limit */
+               pTil = (void *)(fifo_stat.qba + 1 * (fifo_stat.qsz << 11) );
+         }
+         
+         store_runtime_reg( base, I2O_IPTPR, (unsigned int)pTil );
+       }
+    }
+
+    return stat;
+}
+
+/********************************************************
+ * function: I2OIOP
+ *
+ * description: Get the I2O PCI configuration identification
+ *              register.
+ *
+ * note: PCI master should pass pcsrbar while local processor
+ *       should pass eumbbar.
+ *********************************************************/
+I2OSTATUS I2OPCIConfigGet( LOCATION loc,
+                       unsigned int base,
+                       I2OIOP * val)
+{
+    unsigned int tmp;
+    if ( val == 0 )
+    {
+           return I2OINVALID;
+    }
+    tmp = load_runtime_reg( base, PCI_CFG_CLA );
+    val->base_class = ( tmp & 0xFF) << 16;
+    tmp = load_runtime_reg( base, PCI_CFG_SCL );
+    val->sub_class= ( (tmp & 0xFF) << 8 );
+    tmp = load_runtime_reg( base, PCI_CFG_PIC );
+    val->prg_code = (tmp & 0xFF);
+    return I2OSUCCESS;
+}
+
+/*********************************************************
+ * function: I2OFIFOIntEnable
+ *
+ * description: Enable the circular post queue interrupt
+ *
+ * note:
+ * PCI master enables outbound FIFO interrupt of device
+ * pscrbar is the base
+ * Device enables its inbound FIFO interrupt
+ * eumbbar is the base
+ *******************************************************/
+void I2OFIFOIntEnable( LOCATION loc, unsigned int base  )
+{
+    unsigned int reg, val;
+
+    /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base
+     *            LOCAL  : enable local inbound message, eumbbar as base
+     */
+    reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
+    val = load_runtime_reg( base, reg );
+
+    val &= 0xffffffdf; /* clear the msg interrupt bits */
+    store_runtime_reg( base, reg, val );
+
+}
+
+/****************************************************
+ * function: I2OFIFOIntDisable
+ *
+ * description: Disable the circular post queue interrupt
+ *
+ * note:
+ * PCI master disables outbound FIFO interrupt of device
+ * (pscrbar is the base)
+ * Device disables its inbound FIFO interrupt
+ * (eumbbar is the base)
+ *****************************************************/
+void I2OFIFOIntDisable( LOCATION loc, unsigned int base )
+{
+
+    /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base
+     *            LOCAL  : disable local inbound message interrupt, eumbbar as base
+     */
+    unsigned int reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
+    unsigned int val = load_runtime_reg( base, reg );
+
+    val |= 0x00000020; /* masked out the msg interrupt bits */
+    store_runtime_reg( base, reg, val );
+
+}
+
+/*********************************************************
+ * function: I2OFIFOOverflowIntEnable
+ *
+ * description: Enable the circular queue overflow interrupt
+ *
+ * note:
+ * Device enables its inbound FIFO post overflow interrupt
+ * and outbound free overflow interrupt.
+ * eumbbar is the base
+ *******************************************************/
+void I2OFIFOOverflowIntEnable( unsigned int eumbbar  )
+{
+    unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR );
+
+    val &= 0xfffffe7f; /* clear the two overflow interrupt bits */
+    store_runtime_reg( eumbbar, I2O_IMIMR, val );
+
+}
+
+/****************************************************
+ * function: I2OFIFOOverflowIntDisable
+ *
+ * description: Disable the circular queue overflow interrupt
+ *
+ * note:
+ * Device disables its inbound post FIFO overflow interrupt
+ * and outbound free FIFO overflow interrupt
+ * (eumbbar is the base)
+ *****************************************************/
+void I2OFIFOOverflowIntDisable( unsigned int eumbbar )
+{
+
+    unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR );
+
+    val |= 0x00000180; /* masked out the msg overflow interrupt bits */
+    store_runtime_reg( eumbbar, I2O_IMIMR, val );
+}
diff --git a/mpc8240/drivers/i2o/i2o2.S b/mpc8240/drivers/i2o/i2o2.S
new file mode 100644 (file)
index 0000000..f9d9287
--- /dev/null
@@ -0,0 +1,49 @@
+/**************************************
+ * $Id: i2o2.S,v 1.1 2000/11/20 17:22:33 wdenk Exp $
+ *
+ * copyright @ Motorola, 1999
+ *
+ **************************************/
+
+/**********************************************************
+ * function: load_runtime_reg
+ *
+ * input:  r3 - value of eumbbar
+ *         r4 - register offset in embedded utility space
+ *
+ * output: r3 - register content
+ **********************************************************/
+      .text
+      .align 2
+      .global load_runtime_reg
+
+load_runtime_reg:
+            
+                 xor r5,r5,r5
+          or  r5,r5,r3       /* save eumbbar */
+
+             lwbrx     r3,r4,r5
+             sync
+
+             bclr 20, 0
+
+/****************************************************************
+ * function: store_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ *        r4 - register offset in embedded utility space
+ *        r5 - new value to be stored 
+ *
+ ****************************************************************/
+           .text
+           .align 2
+           .global store_runtime_reg
+store_runtime_reg:
+
+                 xor r0,r0,r0
+
+             stwbrx r5,  r4, r3
+             sync
+
+                 bclr   20,0
+
diff --git a/mpc8240/interrupts.c b/mpc8240/interrupts.c
new file mode 100644 (file)
index 0000000..f405461
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <mpc8240.h>
+#include <asm/processor.h>
+#include <asm/pci_io.h>
+#include <commproc.h>
+#include "drivers/epic.h"
+
+/****************************************************************************/
+
+static __inline__ unsigned long get_msr(void)
+{
+    unsigned long msr;
+
+    asm volatile("mfmsr %0" : "=r" (msr) :);
+    return msr;
+}
+
+static __inline__ void set_msr(unsigned long msr)
+{
+    asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+static __inline__ unsigned long get_dec(void)
+{
+    unsigned long val;
+
+    asm volatile("mfdec %0" : "=r" (val) :);
+    return val;
+}
+
+
+static __inline__ void set_dec(unsigned long val)
+{
+    asm volatile("mtdec %0" : : "r" (val));
+}
+
+
+void enable_interrupts (void)
+{
+    set_msr (get_msr() | MSR_EE);
+}
+
+/* returns flag if MSR_EE was set before */
+int disable_interrupts (void)
+{
+    ulong msr = get_msr();
+    set_msr (msr & ~MSR_EE);
+    return ((msr & MSR_EE) != 0);
+}
+
+/****************************************************************************/
+
+void
+interrupt_init (bd_t *bd)
+{
+  /* it's all broken at the moment and I currently don't need interrupts
+     if you want to fix it, have a look at the epic drivers in dink32 v12
+     they do everthing and motorola said I could use the dink source in this project
+     as long as copyright notices remain intact.
+    epicInit(EPIC_DIRECT_IRQ,0);
+    set_msr (get_msr() | MSR_EE);
+    */
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+  register unsigned long temp;
+  pci_readl(CFG_EUMB_ADDR + EPIC_PROC_INT_ACK_REG, temp);
+  sync();                 /* i'm not convinced this is needed, but dink source has it */
+  temp &= 0xff;   /*get vector*/
+
+  /*TODO: handle them -...*/
+  epicEOI();
+}
+
+/****************************************************************************/
+
+/*
+ * blank int handlers.
+ */
+
+void
+irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+}
+
+void
+irq_free_handler(int vec)
+{
+
+}
+
+/*TODO: some handlers for winbond and 87308 interrupts
+ and what about generic pci inteerupts?
+ vga?
+ */
+
+volatile ulong timestamp = 0;
+
+ void timer_interrupt(struct pt_regs *regs)
+ {
+ }
+
+ void reset_timer (void)
+ {
+  timestamp = 0;
+ }
+
+ ulong get_timer (ulong base)
+ {
+  return (timestamp - base);
+ }
+
+ void set_timer (ulong t)
+ {
+  timestamp = t;
+ }
diff --git a/mpc8240/start.S b/mpc8240/start.S
new file mode 100644 (file)
index 0000000..8fd23da
--- /dev/null
@@ -0,0 +1,653 @@
+/*                             
+ *  Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ *  Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *  Copyright (C) 2000 Wolfgang Denk <wd@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*  ppcboot - Startup Code for PowerPC based Embedded Boards
+ *
+ *
+ *  The processor starts at 0x00000100 and the code is executed
+ *  from flash. The code is organized to be at an other address
+ *  in memory, but as long we don't jump around before relocating.
+ *  board_init lies at a quite high address and when the cpu has
+ *  jumped there, everything is ok.
+ *  This works because the cpu gives the FLASH (CS0) the whole
+ *  address space at startup, and board_init lies as a echo of
+ *  the flash somewhere up there in the memorymap.
+ *
+ *  board_init will change CS0 to be positioned at the correct
+ *  address and (s)dram will be positioned at address 0
+ */
+#include <config.h>
+#include <mpc8240.h>
+#include "version.h"
+
+#define _LINUX_CONFIG_H 1      /* avoid reading Linux autoconf.h file  */
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+
+/* We don't want the  MMU yet.
+*/
+#undef MSR_KERNEL
+#define MSR_KERNEL ( MSR_ME | MSR_RI ) /* Machine Check and Recoverable Interr. */
+
+/*
+ * Set up GOT: Global Offset Table
+ *
+ * Use r14 to access the GOT
+ */
+       START_GOT
+       GOT_ENTRY(_GOT2_TABLE_)
+       GOT_ENTRY(_FIXUP_TABLE_)
+
+       GOT_ENTRY(_start)
+       GOT_ENTRY(_start_of_vectors)
+       GOT_ENTRY(_end_of_vectors)
+       GOT_ENTRY(transfer_to_handler)
+
+       GOT_ENTRY(_end)
+       GOT_ENTRY(.bss)
+#if defined(CONFIG_FADS)
+       GOT_ENTRY(environment)
+#endif
+       END_GOT
+
+/*
+ * r3 - 1st arg to board_init(): IMMP pointer
+ * r4 - 2nd arg to board_init(): boot flag
+ */
+       .text
+       .long   0x27051956              /* PPCBOOT Magic Number                 */
+       .globl  version_string
+version_string:
+       .ascii PPCBOOT_VERSION, " (", __DATE__, " - ", __TIME__, ")\0"
+
+       . = EXC_OFF_SYS_RESET
+       .globl  _start
+_start:
+       li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH     */
+       b       boot_cold
+
+       . = EXC_OFF_SYS_RESET + 0x10
+
+       .globl  _start_warm
+_start_warm:
+       li      r21, BOOTFLAG_WARM      /* Software reboot                      */
+       b       boot_warm
+
+boot_cold:
+boot_warm:
+
+       /* Initialize machine status; enable machine check interrupt            */
+       /*----------------------------------------------------------------------*/
+       li      r3, MSR_KERNEL          /* Set ME, RI flags */
+       mtmsr   r3
+       mtspr   SRR1, r3                /* Make SRR1 match MSR */
+
+       mfspr   r3, ICR                 /* clear Interrupt Cause Register */
+
+       addis   r0,0,0x0000             //  lets make sure that r0 is really 0 
+
+       mfmsr   r3                      //  turn off address translation
+       addis   r4,0,0xffff
+       ori     r4,r4,0xffcf
+       and     r3,r3,r4
+       mtmsr   r3
+       isync
+       sync                            //   the MMU should be off...
+
+
+
+       /*
+        * Calculate absolute address in FLASH and jump there
+        *----------------------------------------------------------------------*/
+#ifndef DEBUG
+       lis     r3, CFG_FLASH_BASE@h
+       ori     r3, r3, CFG_FLASH_BASE@l
+       addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
+       mtlr    r3
+       blr
+#endif
+in_flash:
+
+
+       /* thisk the stack pointer *somewhere* sensible. doesnt matter much where as we'll
+        move it when we relocate*/
+        
+        lis    r1, (CFG_MEMTEST_END - 0x3000)@h
+        ori    r1, r1, (CFG_MEMTEST_END - 0x3000)@l
+        
+        
+       /* let the C-code set up the rest                                       */
+       /*                                                                      */
+       /* Be careful to keep code relocatable !                                */
+       /*----------------------------------------------------------------------*/
+
+       GET_GOT                 /* initialize GOT access                        */
+
+       /* r3: IMMR */
+       bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
+
+       mr      r3, r21
+       /* r3: BOOTFLAG */
+       bl      board_init_f    /* run 1st part of board init code (from Flash) */
+
+
+
+       .globl  _start_of_vectors
+_start_of_vectors:
+
+/* Machine check */
+       STD_EXCEPTION(EXC_OFF_MACH_CHCK, MachineCheck, MachineCheckException)
+
+/* Data Storage exception.  "Never" generated on the 860. */
+       STD_EXCEPTION(EXC_OFF_DATA_STOR, DataStorage, UnknownException)
+
+/* Instruction Storage exception.  "Never" generated on the 860. */
+       STD_EXCEPTION(EXC_OFF_INS_STOR, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+       STD_EXCEPTION(EXC_OFF_EXTERNAL, ExtInterrupt, external_interrupt)
+
+/* Alignment exception. */
+       . = EXC_OFF_ALIGN
+Alignment:
+       EXCEPTION_PROLOG
+       mfspr   r4,DAR
+       stw     r4,_DAR(r21)
+       mfspr   r5,DSISR
+       stw     r5,_DSISR(r21)
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r20,MSR_KERNEL
+       rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
+       lwz     r6,GOT(transfer_to_handler)
+       mtlr    r6
+       blrl
+.L_Alignment:
+       .long   AlignmentException - _start + EXC_OFF_SYS_RESET
+       .long   int_return - _start + EXC_OFF_SYS_RESET
+
+/* Program check exception */
+       . = EXC_OFF_PROGRAM
+ProgramCheck:
+       EXCEPTION_PROLOG
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r20,MSR_KERNEL
+       rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
+       lwz     r6,GOT(transfer_to_handler)
+       mtlr    r6
+       blrl
+.L_ProgramCheck:
+       .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
+       .long   int_return - _start + EXC_OFF_SYS_RESET
+
+       /* No FPU on MPC8xx.  This exception is not supposed to happen.
+       */
+       STD_EXCEPTION(EXC_OFF_FPUNAVAIL, FPUnavailable, UnknownException)
+
+       /* I guess we could implement decrementer, and may have
+        * to someday for timekeeping.
+        */
+       STD_EXCEPTION(EXC_OFF_DECR, Decrementer, timer_interrupt)
+       STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+       STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+
+       STD_EXCEPTION(EXC_OFF_SYS_CALL, SystemCall, UnknownException)
+       STD_EXCEPTION(EXC_OFF_TRACE, SingleStep, UnknownException)
+
+       STD_EXCEPTION(EXC_OFF_FPUNASSIST, Trap_0e, UnknownException)
+       STD_EXCEPTION(EXC_OFF_PMI, Trap_0f, UnknownException)
+
+       STD_EXCEPTION(EXC_OFF_ITME, InstructionTransMiss, UnknownException)
+       STD_EXCEPTION(EXC_OFF_DLTME, DataLoadTransMiss, UnknownException)
+       STD_EXCEPTION(EXC_OFF_DSTME, DataStoreTransMiss, UnknownException)
+       STD_EXCEPTION(EXC_OFF_IABE, InstructionBreakpoint, UnknownException)
+       STD_EXCEPTION(EXC_OFF_SMIE, SysManageInt, UnknownException)
+       STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+       STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+       STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+       STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+       STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+       STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+       STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+       STD_EXCEPTION(0x1c00, ReservedC, UnknownException)
+       STD_EXCEPTION(0x1d00, ReservedD, UnknownException)
+       STD_EXCEPTION(0x1e00, ReservedE, UnknownException)
+       STD_EXCEPTION(0x1f00, ReservedF, UnknownException)
+
+       STD_EXCEPTION(EXC_OFF_RMTE, RunModeTrace, UnknownException)
+
+       .globl  _end_of_vectors
+_end_of_vectors:
+
+
+       . = 0x3000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+       .globl  transfer_to_handler
+transfer_to_handler:
+       stw     r22,_NIP(r21)
+       lis     r22,MSR_POW@h
+       andc    r23,r23,r22
+       stw     r23,_MSR(r21)
+       SAVE_GPR(7, r21)
+       SAVE_4GPRS(8, r21)
+       SAVE_8GPRS(12, r21)
+       SAVE_8GPRS(24, r21)
+#if 0
+       andi.   r23,r23,MSR_PR
+       mfspr   r23,SPRG3               /* if from user, fix up tss.regs */
+       beq     2f
+       addi    r24,r1,STACK_FRAME_OVERHEAD
+       stw     r24,PT_REGS(r23)
+2:     addi    r2,r23,-TSS             /* set r2 to current */
+       tovirt(r2,r2,r23)
+#endif
+       mflr    r23
+       andi.   r24,r23,0x3f00          /* get vector offset */
+       stw     r24,TRAP(r21)
+       li      r22,0
+       stw     r22,RESULT(r21)
+       mtspr   SPRG2,r22               /* r1 is now kernel sp */
+#if 0
+       addi    r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
+       cmplw   0,r1,r2
+       cmplw   1,r1,r24
+       crand   1,1,4
+       bgt     stack_ovf               /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
+#endif
+       lwz     r24,0(r23)              /* virtual address of handler */
+       lwz     r23,4(r23)              /* where to go when done */
+       mtspr   SRR0,r24
+       mtspr   SRR1,r20
+       mtlr    r23
+       SYNC
+       rfi                             /* jump to handler, enable MMU */
+
+int_return:
+       mfmsr   r29             /* Disable interrupts */
+       li      r4,0
+       ori     r4,r4,MSR_EE
+       andc    r29,r29,r4
+       SYNC                    /* Some chip revs need this... */
+       mtmsr   r29
+       SYNC
+       lwz     r2,_CTR(r1)
+       lwz     r0,_LINK(r1)
+       mtctr   r2
+       mtlr    r0
+       lwz     r2,_XER(r1)
+       lwz     r0,_CCR(r1)
+       mtspr   XER,r2
+       mtcrf   0xFF,r0
+       REST_10GPRS(3, r1)
+       REST_10GPRS(13, r1)
+       REST_8GPRS(23, r1)
+       REST_GPR(31, r1)
+       lwz     r2,_NIP(r1)     /* Restore environment */
+       lwz     r0,_MSR(r1)
+       mtspr   SRR0,r2
+       mtspr   SRR1,r0
+       lwz     r0,GPR0(r1)
+       lwz     r2,GPR2(r1)
+       lwz     r1,GPR1(r1)
+       SYNC
+       rfi
+
+/* Cache functions.
+*/
+       .globl  icache_enable
+icache_enable:
+       mfspr   r5,HID0         //  turn on the I cache.
+       ori     r5,r5,0x8800    //  Instruction cache only//!
+       addis   r6,0,0xFFFF
+       ori     r6,r6,0xF7FF
+       and     r6,r5,r6        //  clear the invalidate bit
+       sync
+       mtspr   HID0,r5
+       mtspr   HID0,r6
+       isync
+       sync
+       blr
+
+       .globl  icache_disable
+icache_disable:
+       mfspr   r5,HID0
+       addis   r6,0,0xFFFF
+       ori     r6,r6,0x7FFF
+       and     r5,r5,r6
+       sync
+       mtspr   HID0,r5
+       isync
+       sync
+       blr
+
+       .globl  icache_status
+icache_status:
+       mfspr   r3, HID0
+       srwi    r3, r3, 15      /* >>15 & 1=> select bit 16 */
+       andi.   r3, r3, 1       
+       blr
+
+       .globl  dcache_enable
+dcache_enable:
+       mfspr   r5,HID0         //  turn on the D cache.
+       ori     r5,r5,0x4400    //  Data cache only//!
+       mfspr r4, PVR                   //  read PVR 
+       srawi r3, r4, 16                //  shift off the least 16 bits
+        cmpi  0, 0, r3, 0xC     // Check for Max pvr
+        bne   NotMax
+       ori     r5,r5,0x0040    //  setting the DCFA bit, for Max rev 1 errata 
+NotMax:
+       addis   r6,0,0xFFFF
+       ori     r6,r6,0xFBFF
+       and     r6,r5,r6        //  clear the invalidate bit
+       sync
+       mtspr   HID0,r5
+       mtspr   HID0,r6
+       isync
+       sync
+       blr
+
+       .globl  dcache_disable
+dcache_disable:
+       mfspr   r5,HID0
+       addis   r6,0,0xFFFF
+       ori     r6,r6,0xBFFF
+       and     r5,r5,r6
+       sync
+       mtspr   HID0,r5
+       isync
+       sync
+       blr
+
+       .globl  dcache_status
+dcache_status:
+       mfspr   r3, HID0
+       srwi    r3, r3, 14      /* >>14 & 1=> select bit 17 */
+       andi.   r3, r3, 1       
+       blr
+
+       .globl  dc_read
+dc_read:
+/*TODO : who uses this, what should it do?
+*/
+       blr
+
+
+       .globl get_pvr
+get_pvr:
+       mfspr   r3, PVR
+       blr
+
+
+/*------------------------------------------------------------------------------*/
+
+/*
+ * void relocate_code (addr_sp, bd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
+ *
+ * r3 = dest
+ * r4 = src
+ * r5 = length in bytes
+ * r6 = cachelinesize
+ */
+       .globl  relocate_code
+relocate_code:
+
+       mr      r1,  r3         /* Set new stack pointer                */
+       mr      r9,  r4         /* Save copy of Board Info pointer      */
+       mr      r10, r5         /* Save copy of Destination Address     */
+
+       mr      r3,  r5                         /* Destination Address  */
+#ifdef DEBUG
+       lis     r4, CFG_SDRAM_BASE@h            /* Source      Address  */
+       ori     r4, r4, CFG_SDRAM_BASE@l
+#else
+       lis     r4, CFG_FLASH_BASE@h            /* Source      Address  */
+       ori     r4, r4, CFG_FLASH_BASE@l
+#endif
+       lis     r5, CFG_MONITOR_LEN@h           /* Length in Bytes      */
+       ori     r5, r5, CFG_MONITOR_LEN@l
+       li      r6, CFG_CACHELINE_SIZE          /* Cache Line Size      */
+
+       /*
+        * Fix GOT pointer:
+        *
+        * New GOT-PTR = (old GOT-PTR - CFG_FLASH_BASE) + Destination Address
+        *
+        * Offset:
+        */
+       sub     r15, r10, r4
+
+       /* First our own GOT */
+       add     r14, r14, r15
+       /* the the one used by the C code */
+       add     r30, r30, r15
+
+       /*
+        * Now relocate code
+        */
+       
+       cmplw   cr1,r3,r4
+       addi    r0,r5,3
+       srwi.   r0,r0,2
+       beq     cr1,4f          /* In place copy is not necessary       */
+       beq     7f              /* Protect against 0 count              */
+       mtctr   r0
+       bge     cr1,2f
+
+       la      r8,-4(r4)
+       la      r7,-4(r3)
+1:     lwzu    r0,4(r8)
+       stwu    r0,4(r7)
+       bdnz    1b
+       b       4f
+
+2:     slwi    r0,r0,2
+       add     r8,r4,r0
+       add     r7,r3,r0
+3:     lwzu    r0,-4(r8)
+       stwu    r0,-4(r7)
+       bdnz    3b
+
+/*
+ * Now flush the cache: note that we must start from a cache aligned
+ * address. Otherwise we might miss one cache line.
+ */
+4:     cmpwi   r6,0
+       add     r5,r3,r5
+       beq     7f              /* Always flush prefetch queue in any case */
+       subi    r0,r6,1
+       andc    r3,r3,r0
+       mr      r4,r3
+5:     cmplw   r4,r5
+       dcbst   0,r4
+       add     r4,r4,r6
+       blt     5b
+       sync                    /* Wait for all dcbst to complete on bus */
+       mr      r4,r3
+6:     cmplw   r4,r5
+       icbi    0,r4
+       add     r4,r4,r6
+       blt     6b
+7:     sync                    /* Wait for all icbi to complete on bus */
+       isync
+
+/*
+ * We are done. Do not return, instead branch to second part of board
+ * initialization, now running from RAM.
+ */
+
+       addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
+       mtlr    r0
+       blr
+
+in_ram:
+
+       /*
+        * Relocation Function, r14 point to got2+0x8000
+        *
+         * Adjust got2 pointers, no need to check for 0, this code
+         * already puts a few entries in the table.
+        */
+       li      r0,__got2_entries@sectoff@l
+       la      r3,GOT(_GOT2_TABLE_)
+       lwz     r11,GOT(_GOT2_TABLE_)
+       mtctr   r0
+       sub     r11,r3,r11
+       addi    r3,r3,-4
+1:     lwzu    r0,4(r3)
+       add     r0,r0,r11
+       stw     r0,0(r3)
+       bdnz    1b
+       
+       /*
+         * Now adjust the fixups and the pointers to the fixups
+        * in case we need to move ourselves again.
+        */     
+2:     li      r0,__fixup_entries@sectoff@l
+       lwz     r3,GOT(_FIXUP_TABLE_)
+       cmpwi   r0,0
+       mtctr   r0
+       addi    r3,r3,-4
+       beq     4f
+3:     lwzu    r4,4(r3)
+       lwzux   r0,r4,r11
+       add     r0,r0,r11
+       stw     r10,0(r3)
+       stw     r0,0(r4)
+       bdnz    3b
+4:
+clear_bss:
+       /*
+        * Now clear BSS segment
+        */
+       lwz     r3,GOT(.bss)
+#if defined(CONFIG_FADS)
+       /*
+        * For the FADS - the environment is the very last item in flash.
+        * The real .bss stops just before environment starts, so only
+        * clear up to that point.
+        */
+       lwz r4,GOT(environment)
+#else
+       lwz     r4,GOT(_end)
+#endif
+
+       cmplw   0, r3, r4
+       beq     6f
+
+       li      r0, 0
+5:
+       stw     r0, 0(r3)
+       addi    r3, r3, 4
+       cmplw   0, r3, r4
+       blt     5b
+6:
+
+       mr      r3, r9          /* Board Info pointer           */
+       mr      r4, r10         /* Destination Address          */
+       bl      board_init_r
+
+       /* Problems accessing "end" in C, so do it here */
+       .globl  get_endaddr
+get_endaddr:
+       lwz     r3,GOT(_end)
+       blr
+
+       /*
+        * Copy exception vector code to low memory
+        *
+        * r3: dest_addr
+        * r7: source address, r8: end address, r9: target address
+        */
+       .globl  trap_init
+trap_init:
+       lwz     r7, GOT(_start)
+       lwz     r8, GOT(_end_of_vectors)
+
+       rlwinm  r9, r7, 0, 18, 31       /* _start & 0x3FFF      */
+
+       cmplw   0, r7, r8
+       bgelr                           /* return if r7>=r8 - just in case */
+
+       mflr    r4                      /* save link register           */
+1:
+       lwz     r0, 0(r7)
+       stw     r0, 0(r9)
+       addi    r7, r7, 4
+       addi    r9, r9, 4
+       cmplw   0, r7, r8
+       bne     1b
+
+       /*
+        * relocate `hdlr' and `int_return' entries
+        */
+       li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
+       li      r8, Alignment - _start + EXC_OFF_SYS_RESET
+2:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     2b
+
+       li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
+       bl      trap_reloc
+
+       li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
+       bl      trap_reloc
+
+       li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
+       li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
+3:
+       bl      trap_reloc
+       addi    r7, r7, 0x100           /* next exception vector        */
+       cmplw   0, r7, r8
+       blt     3b
+
+       mtlr    r4                      /* restore link register        */
+       blr
+
+       /*
+        * Function: relocate entries for one exception vector
+        */
+trap_reloc:
+       lwz     r0, 0(r7)               /* hdlr ...                     */
+       add     r0, r0, r3              /*  ... += dest_addr            */
+       stw     r0, 0(r7)
+
+       lwz     r0, 4(r7)               /* int_return ...               */
+       add     r0, r0, r3              /*  ... += dest_addr            */
+       stw     r0, 4(r7)
+
+       blr
diff --git a/mpc8240/start1.S b/mpc8240/start1.S
new file mode 100644 (file)
index 0000000..f81cd68
--- /dev/null
@@ -0,0 +1,1812 @@
+Analyzing: d:\ppcboot\mpc8240\start1.o
+Header idenfication: 0x7f, ELF, 32 bit MSB v1
+    type:           1, machine:         20
+    version: 00000001, entry:     00000000, phoff:  00000000
+    shoff:   00003410, flags:     00000000, ehsize:       52, phentsize:  0
+    phnum:          0, shentsize:       40, shnum:        10, shstrndx:  7
+
+
+==> .shstrtab
+    [  1]      .symtab
+    [  9]      .strtab
+    [ 17]      .shstrtab
+    [ 27]      .text
+    [ 33]      .rela.text
+    [ 44]      .data
+    [ 50]      .bss
+    [ 55]      .got2
+    [ 61]      .rela.got2
+
+==> .text [1]: Section Header
+    type:    00000001, flags:  00000006
+    address: 00000000, offset: 00000034, size: 00003374
+    link:    00000000, info:   00000000, alignment: 1, entry size: 0
+
+
+==> .rela.text [2]: Section Header
+    type:    00000004, flags:  00000000
+    address: 00000000, offset: 0000416c, size: 000001a4
+    link:    00000008, info:   00000001, alignment: 4, entry size: 12
+
+
+==> .data [3]: Section Header
+    type:    00000001, flags:  00000003
+    address: 00000000, offset: 000033a8, size: 00000000
+    link:    00000000, info:   00000000, alignment: 1, entry size: 0
+
+
+==> .bss [4]: Section Header
+    type:    00000008, flags:  00000003
+    address: 00000000, offset: 000033a8, size: 00000000
+    link:    00000000, info:   00000000, alignment: 1, entry size: 0
+
+
+==> .got2 [5]: Section Header
+    type:    00000001, flags:  00000003
+    address: 00000000, offset: 000033a8, size: 00000020
+    link:    00000000, info:   00000000, alignment: 1, entry size: 0
+
+
+==> .rela.got2 [6]: Section Header
+    type:    00000004, flags:  00000000
+    address: 00000000, offset: 00004310, size: 00000060
+    link:    00000008, info:   00000005, alignment: 4, entry size: 12
+
+
+==> .shstrtab [7]: Section Header
+    type:    00000003, flags:  00000000
+    address: 00000000, offset: 000033c8, size: 00000048
+    link:    00000000, info:   00000000, alignment: 1, entry size: 0
+
+
+==> .symtab [8]: Section Header
+    type:    00000002, flags:  00000000
+    address: 00000000, offset: 000035a0, size: 00000680
+    link:    00000009, info:   0000004a, alignment: 4, entry size: 16
+
+
+==> .strtab [9]: Section Header
+    type:    00000003, flags:  00000000
+    address: 00000000, offset: 00003c20, size: 00000549
+    link:    00000000, info:   00000000, alignment: 1, entry size: 0
+
+
+==> .strtab
+    [  1]      start.S
+    [  9]      /cygdrive/d/ppcboot/include/asm/mmu.h
+    [ 47]      /cygdrive/d/ppcboot/include/linux/config.h
+    [ 90]      /cygdrive/d/ppcboot/include/asm/cache.h
+    [ 130]     /cygdrive/d/ppcboot/include/asm/processor.h
+    [ 174]     /cygdrive/d/ppcboot/include/asm/types.h
+    [ 214]     /cygdrive/d/ppcboot/include/asm/ptrace.h
+    [ 255]     /cygdrive/d/ppcboot/include/ppc_defs.h
+    [ 294]     /cygdrive/d/ppcboot/include/ppc_asm.tmpl
+    [ 335]     /cygdrive/d/ppcboot/include/version.h
+    [ 373]     /cygdrive/d/ppcboot/include/mpc8240.h
+    [ 411]     /cygdrive/d/ppcboot/include/config.h
+    [ 448]     /cygdrive/d/ppcboot/include/config_Sandpoint8240.h
+    [ 499]     boot_cold
+    [ 509]     boot_warm
+    [ 519]     in_flash
+    [ 528]     MachineCheck
+    [ 541]     int_return
+    [ 552]     DataStorage
+    [ 564]     InstStorage
+    [ 576]     ExtInterrupt
+    [ 589]     Alignment
+    [ 599]     ProgramCheck
+    [ 612]     FPUnavailable
+    [ 626]     Decrementer
+    [ 638]     Trap_0a
+    [ 646]     Trap_0b
+    [ 654]     SystemCall
+    [ 665]     SingleStep
+    [ 676]     Trap_0e
+    [ 684]     Trap_0f
+    [ 692]     InstructionTransMiss
+    [ 713]     DataLoadTransMiss
+    [ 731]     DataStoreTransMiss
+    [ 750]     InstructionBreakpoint
+    [ 772]     SysManageInt
+    [ 785]     Reserved5
+    [ 795]     Reserved6
+    [ 805]     Reserved7
+    [ 815]     Reserved8
+    [ 825]     Reserved9
+    [ 835]     ReservedA
+    [ 845]     ReservedB
+    [ 855]     ReservedC
+    [ 865]     ReservedD
+    [ 875]     ReservedE
+    [ 885]     ReservedF
+    [ 895]     RunModeTrace
+    [ 908]     NotMax
+    [ 915]     clear_bss
+    [ 925]     trap_reloc
+    [ 936]     _GOT2_TABLE_
+    [ 949]     _FIXUP_TABLE_
+    [ 963]     _start
+    [ 970]     _start_of_vectors
+    [ 988]     _end_of_vectors
+    [ 1004]    transfer_to_handler
+    [ 1024]    _end
+    [ 1029]    version_string
+    [ 1044]    _start_warm
+    [ 1056]    cpu_init_f
+    [ 1067]    board_init_f
+    [ 1080]    MachineCheckException
+    [ 1102]    UnknownException
+    [ 1119]    external_interrupt
+    [ 1138]    AlignmentException
+    [ 1157]    ProgramCheckException
+    [ 1179]    timer_interrupt
+    [ 1195]    icache_enable
+    [ 1209]    icache_disable
+    [ 1224]    icache_status
+    [ 1238]    dcache_enable
+    [ 1252]    dcache_disable
+    [ 1267]    dcache_status
+    [ 1281]    dc_read
+    [ 1289]    get_pvr
+    [ 1297]    udelay
+    [ 1304]    relocate_code
+    [ 1318]    board_init_r
+    [ 1331]    get_endaddr
+    [ 1343]    trap_init
+
+==> .symtab
+    entry  spndx   value      size   bind   type  other    shndx         name
+    [   0]     0   00000000      0   LOC    NULL      0    UND           
+    [   1]     1   00000000      0   LOC    FILE      0    ABS           start.S
+    [   2]     9   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/mmu.h
+    [   3]    47   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/linux/config.h
+    [   4]     9   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/mmu.h
+    [   5]     1   00000000      0   LOC    FILE      0    ABS           start.S
+    [   6]    90   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/cache.h
+    [   7]   130   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/processor.h
+    [   8]   174   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/types.h
+    [   9]   130   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/processor.h
+    [  10]   214   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/ptrace.h
+    [  11]    47   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/linux/config.h
+    [  12]   214   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/ptrace.h
+    [  13]   130   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/processor.h
+    [  14]    47   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/linux/config.h
+    [  15]   130   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/processor.h
+    [  16]    90   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/cache.h
+    [  17]    47   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/linux/config.h
+    [  18]    90   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/asm/cache.h
+    [  19]     1   00000000      0   LOC    FILE      0    ABS           start.S
+    [  20]   255   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/ppc_defs.h
+    [  21]     1   00000000      0   LOC    FILE      0    ABS           start.S
+    [  22]   294   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/ppc_asm.tmpl
+    [  23]     1   00000000      0   LOC    FILE      0    ABS           start.S
+    [  24]   335   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/version.h
+    [  25]     1   00000000      0   LOC    FILE      0    ABS           start.S
+    [  26]   373   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/mpc8240.h
+    [  27]     1   00000000      0   LOC    FILE      0    ABS           start.S
+    [  28]   411   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/config.h
+    [  29]   448   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/config_Sandpoint8240.h
+    [  30]   411   00000000      0   LOC    FILE      0    ABS           /cygdrive/d/ppcboot/include/config.h
+    [  31]     1   00000000      0   LOC    FILE      0    ABS           start.S
+    [  32]     0   00000000      0   LOC    SECT      0    .text         .text
+    [  33]     0   00000000      0   LOC    SECT      0    .data         .data
+    [  34]     0   00000000      0   LOC    SECT      0    .bss          .bss
+    [  35]     0   00000000      0   LOC    SECT      0    .got2         .got2
+    [  36]   499   00000118      0   LOC    NULL      0    .text         boot_cold
+    [  37]   509   00000118      0   LOC    NULL      0    .text         boot_warm
+    [  38]   519   00000148      0   LOC    NULL      0    .text         in_flash
+    [  39]   528   00000200      0   LOC    NULL      0    .text         MachineCheck
+    [  40]   541   0000309c      0   LOC    NULL      0    .text         int_return
+    [  41]   552   00000300      0   LOC    NULL      0    .text         DataStorage
+    [  42]   564   00000400      0   LOC    NULL      0    .text         InstStorage
+    [  43]   576   00000500      0   LOC    NULL      0    .text         ExtInterrupt
+    [  44]   589   00000600      0   LOC    NULL      0    .text         Alignment
+    [  45]   599   00000700      0   LOC    NULL      0    .text         ProgramCheck
+    [  46]   612   00000800      0   LOC    NULL      0    .text         FPUnavailable
+    [  47]   626   00000900      0   LOC    NULL      0    .text         Decrementer
+    [  48]   638   00000a00      0   LOC    NULL      0    .text         Trap_0a
+    [  49]   646   00000b00      0   LOC    NULL      0    .text         Trap_0b
+    [  50]   654   00000c00      0   LOC    NULL      0    .text         SystemCall
+    [  51]   665   00000d00      0   LOC    NULL      0    .text         SingleStep
+    [  52]   676   00000e00      0   LOC    NULL      0    .text         Trap_0e
+    [  53]   684   00000f00      0   LOC    NULL      0    .text         Trap_0f
+    [  54]   692   00001000      0   LOC    NULL      0    .text         InstructionTransMiss
+    [  55]   713   00001100      0   LOC    NULL      0    .text         DataLoadTransMiss
+    [  56]   731   00001200      0   LOC    NULL      0    .text         DataStoreTransMiss
+    [  57]   750   00001300      0   LOC    NULL      0    .text         InstructionBreakpoint
+    [  58]   772   00001400      0   LOC    NULL      0    .text         SysManageInt
+    [  59]   785   00001500      0   LOC    NULL      0    .text         Reserved5
+    [  60]   795   00001600      0   LOC    NULL      0    .text         Reserved6
+    [  61]   805   00001700      0   LOC    NULL      0    .text         Reserved7
+    [  62]   815   00001800      0   LOC    NULL      0    .text         Reserved8
+    [  63]   825   00001900      0   LOC    NULL      0    .text         Reserved9
+    [  64]   835   00001a00      0   LOC    NULL      0    .text         ReservedA
+    [  65]   845   00001b00      0   LOC    NULL      0    .text         ReservedB
+    [  66]   855   00001c00      0   LOC    NULL      0    .text         ReservedC
+    [  67]   865   00001d00      0   LOC    NULL      0    .text         ReservedD
+    [  68]   875   00001e00      0   LOC    NULL      0    .text         ReservedE
+    [  69]   885   00001f00      0   LOC    NULL      0    .text         ReservedF
+    [  70]   895   00002000      0   LOC    NULL      0    .text         RunModeTrace
+    [  71]   908   000031f8      0   LOC    NULL      0    .text         NotMax
+    [  72]   915   000032a4      0   LOC    NULL      0    .text         clear_bss
+    [  73]   925   00003354      0   LOC    NULL      0    .text         trap_reloc
+    [  74]   936   00000000      0   GLOB   NULL      0    UND           _GOT2_TABLE_
+    [  75]   949   00000000      0   GLOB   NULL      0    UND           _FIXUP_TABLE_
+    [  76]   963   00000100      0   GLOB   NULL      0    .text         _start
+    [  77]   970   0000016c      0   GLOB   NULL      0    .text         _start_of_vectors
+    [  78]   988   00002090      0   GLOB   NULL      0    .text         _end_of_vectors
+    [  79]   1004   00003000      0   GLOB   NULL      0    .text         transfer_to_handler
+    [  80]   1024   00000000      0   GLOB   NULL      0    UND           _end
+    [  81]   1029   00000004      0   GLOB   NULL      0    .text         version_string
+    [  82]   1044   00000110      0   GLOB   NULL      0    .text         _start_warm
+    [  83]   1056   00000000      0   GLOB   NULL      0    UND           cpu_init_f
+    [  84]   1067   00000000      0   GLOB   NULL      0    UND           board_init_f
+    [  85]   1080   00000000      0   GLOB   NULL      0    UND           MachineCheckException
+    [  86]   1102   00000000      0   GLOB   NULL      0    UND           UnknownException
+    [  87]   1119   00000000      0   GLOB   NULL      0    UND           external_interrupt
+    [  88]   1138   00000000      0   GLOB   NULL      0    UND           AlignmentException
+    [  89]   1157   00000000      0   GLOB   NULL      0    UND           ProgramCheckException
+    [  90]   1179   00000000      0   GLOB   NULL      0    UND           timer_interrupt
+    [  91]   1195   0000317c      0   GLOB   NULL      0    .text         icache_enable
+    [  92]   1209   000031a8      0   GLOB   NULL      0    .text         icache_disable
+    [  93]   1224   000031cc      0   GLOB   NULL      0    .text         icache_status
+    [  94]   1238   000031dc      0   GLOB   NULL      0    .text         dcache_enable
+    [  95]   1252   0000321c      0   GLOB   NULL      0    .text         dcache_disable
+    [  96]   1267   00003240      0   GLOB   NULL      0    .text         dcache_status
+    [  97]   1281   00003250      0   GLOB   NULL      0    .text         dc_read
+    [  98]   1289   00003254      0   GLOB   NULL      0    .text         get_pvr
+    [  99]   1297   0000325c      0   GLOB   NULL      0    .text         udelay
+    [ 100]   1304   000032a4      0   GLOB   NULL      0    .text         relocate_code
+    [ 101]   1318   00000000      0   GLOB   NULL      0    UND           board_init_r
+    [ 102]   1331   000032d4      0   GLOB   NULL      0    .text         get_endaddr
+    [ 103]   1343   000032dc      0   GLOB   NULL      0    .text         trap_init
+
+==> .rela.text
+    entry  offset   addend   type name(symbol id)
+    [   0] 00000160 00000000   10 cpu_init_f(83)
+    [   1] 00000168 00000000   10 board_init_f(84)
+    [   2] 00000288 00000288   26 MachineCheckException(85)
+    [   3] 00000388 00000388   26 UnknownException(86)
+    [   4] 00000488 00000488   26 UnknownException(86)
+    [   5] 00000588 00000588   26 external_interrupt(87)
+    [   6] 0000069c 0000069c   26 AlignmentException(88)
+    [   7] 0000078c 0000078c   26 ProgramCheckException(89)
+    [   8] 00000888 00000888   26 UnknownException(86)
+    [   9] 00000988 00000988   26 timer_interrupt(90)
+    [  10] 00000a88 00000a88   26 UnknownException(86)
+    [  11] 00000b88 00000b88   26 UnknownException(86)
+    [  12] 00000c88 00000c88   26 UnknownException(86)
+    [  13] 00000d88 00000d88   26 UnknownException(86)
+    [  14] 00000e88 00000e88   26 UnknownException(86)
+    [  15] 00000f88 00000f88   26 UnknownException(86)
+    [  16] 00001088 00001088   26 UnknownException(86)
+    [  17] 00001188 00001188   26 UnknownException(86)
+    [  18] 00001288 00001288   26 UnknownException(86)
+    [  19] 00001388 00001388   26 UnknownException(86)
+    [  20] 00001488 00001488   26 UnknownException(86)
+    [  21] 00001588 00001588   26 UnknownException(86)
+    [  22] 00001688 00001688   26 UnknownException(86)
+    [  23] 00001788 00001788   26 UnknownException(86)
+    [  24] 00001888 00001888   26 UnknownException(86)
+    [  25] 00001988 00001988   26 UnknownException(86)
+    [  26] 00001a88 00001a88   26 UnknownException(86)
+    [  27] 00001b88 00001b88   26 UnknownException(86)
+    [  28] 00001c88 00001c88   26 UnknownException(86)
+    [  29] 00001d88 00001d88   26 UnknownException(86)
+    [  30] 00001e88 00001e88   26 UnknownException(86)
+    [  31] 00001f88 00001f88   26 UnknownException(86)
+    [  32] 00002088 00002088   26 UnknownException(86)
+    [  33] 000032d0 00000000   10 board_init_r(101)
+    [  34] 00003370 0000b21c   26 .got2(35)
+
+==> .text
+00000000: 27051956  dc.l     0x27051956              ; Invalid opcode ''..V'
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="version_string"  Size=0
+00000004: 70706362  andi.    r16,r3,0x6362
+00000008: 6F6F7420  xoris    r15,r27,0x7420
+0000000C: 302E352E  addic    rsp,r14,13614
+00000010: 3020284F  addic    rsp,r0,10319
+00000014: 63742031  ori      r20,r27,0x2031
+00000018: 31203230  addic    r9,r0,12848
+0000001C: 3030202D  addic    rsp,r16,8237
+00000020: 2031363A  subfic   rsp,r17,13882
+00000024: 35353A34  addic.   r9,r21,14900
+00000028: 38290000  addi     rsp,r9,0
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="_start"  Size=0
+00000100: 3AA00001  li       r21,1
+00000104: 48000014  b        *+20                    ; 0x00000118
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="_start_warm"  Size=0
+00000110: 3AA00002  li       r21,2
+00000114: 48000004  b        *+4                     ; 0x00000118
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="boot_warm"  Size=0
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="boot_cold"  Size=0
+00000118: 38601002  li       r3,4098
+0000011C: 7C600124  mtmsr    r3
+00000120: 7C7B03A6  mtsrr1   r3
+00000124: 7C7422A6  mfspr    r3,ECR
+00000128: 3C000000  lis      r0,0
+0000012C: 7C6000A6  mfmsr    r3
+00000130: 3C80FFFF  lis      r4,-1
+00000134: 6084FFCF  ori      r4,r4,0xffcf
+00000138: 7C632038  and      r3,r3,r4
+0000013C: 7C600124  mtmsr    r3
+00000140: 4C00012C  isync
+00000144: 7C0004AC  sync
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="in_flash"  Size=0
+00000148: 3C20007F  lis      rsp,127
+0000014C: 6021D000  ori      rsp,rsp,0xd000
+00000150: 48000005  bl       *+4                     ; 0x00000154
+00000154: 7DC802A6  mflr     r14
+00000158: 800E321C  lwz      r0,12828(r14)
+0000015C: 7DC07214  add      r14,r0,r14
+00000160: 48000001  bl       cpu_init_f
+00000164: 7EA3AB78  mr       r3,r21
+00000168: 48000001  bl       board_init_f
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="_start_of_vectors"  Size=0
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="MachineCheck"  Size=0
+00000200: 7E9043A6  mtsprg0  r20
+00000204: 7EB143A6  mtsprg1  r21
+00000208: 7E800026  mfcr     r20
+0000020C: 7C350B78  mr       r21,rsp
+00000210: 3AB5FF00  subi     r21,r21,256
+00000214: 929500A8  stw      r20,168(r21)
+00000218: 92D50068  stw      r22,104(r21)
+0000021C: 92F5006C  stw      r23,108(r21)
+00000220: 7E9042A6  mfsprg0  r20
+00000224: 92950060  stw      r20,96(r21)
+00000228: 7ED142A6  mfsprg1  r22
+0000022C: 92D50064  stw      r22,100(r21)
+00000230: 7E8802A6  mflr     r20
+00000234: 929500A0  stw      r20,160(r21)
+00000238: 7EC902A6  mfctr    r22
+0000023C: 92D5009C  stw      r22,156(r21)
+00000240: 7E8102A6  mfxer    r20
+00000244: 929500A4  stw      r20,164(r21)
+00000248: 7EDA02A6  mfsrr0   r22
+0000024C: 7EFB02A6  mfsrr1   r23
+00000250: 90150010  stw      r0,16(r21)
+00000254: 90350014  stw      rsp,20(r21)
+00000258: 90550018  stw      r2,24(r21)
+0000025C: 90350000  stw      rsp,0(r21)
+00000260: 7EA1AB78  mr       rsp,r21
+00000264: 9075001C  stw      r3,28(r21)
+00000268: 90950020  stw      r4,32(r21)
+0000026C: 90B50024  stw      r5,36(r21)
+00000270: 90D50028  stw      r6,40(r21)
+00000274: 806E8014  lwz      r3,-32748(r14)
+00000278: 7C6803A6  mtlr     r3
+0000027C: 38610010  addi     r3,rsp,16
+00000280: 3A801002  li       r20,4098
+00000284: 4E800021  blrl
+00000288: 00000288  dc.l     0x00000288              ; Invalid opcode '....'
+0000028C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="DataStorage"  Size=0
+00000300: 7E9043A6  mtsprg0  r20
+00000304: 7EB143A6  mtsprg1  r21
+00000308: 7E800026  mfcr     r20
+0000030C: 7C350B78  mr       r21,rsp
+00000310: 3AB5FF00  subi     r21,r21,256
+00000314: 929500A8  stw      r20,168(r21)
+00000318: 92D50068  stw      r22,104(r21)
+0000031C: 92F5006C  stw      r23,108(r21)
+00000320: 7E9042A6  mfsprg0  r20
+00000324: 92950060  stw      r20,96(r21)
+00000328: 7ED142A6  mfsprg1  r22
+0000032C: 92D50064  stw      r22,100(r21)
+00000330: 7E8802A6  mflr     r20
+00000334: 929500A0  stw      r20,160(r21)
+00000338: 7EC902A6  mfctr    r22
+0000033C: 92D5009C  stw      r22,156(r21)
+00000340: 7E8102A6  mfxer    r20
+00000344: 929500A4  stw      r20,164(r21)
+00000348: 7EDA02A6  mfsrr0   r22
+0000034C: 7EFB02A6  mfsrr1   r23
+00000350: 90150010  stw      r0,16(r21)
+00000354: 90350014  stw      rsp,20(r21)
+00000358: 90550018  stw      r2,24(r21)
+0000035C: 90350000  stw      rsp,0(r21)
+00000360: 7EA1AB78  mr       rsp,r21
+00000364: 9075001C  stw      r3,28(r21)
+00000368: 90950020  stw      r4,32(r21)
+0000036C: 90B50024  stw      r5,36(r21)
+00000370: 90D50028  stw      r6,40(r21)
+00000374: 806E8014  lwz      r3,-32748(r14)
+00000378: 7C6803A6  mtlr     r3
+0000037C: 38610010  addi     r3,rsp,16
+00000380: 3A801002  li       r20,4098
+00000384: 4E800021  blrl
+00000388: 00000388  dc.l     0x00000388              ; Invalid opcode '....'
+0000038C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="InstStorage"  Size=0
+00000400: 7E9043A6  mtsprg0  r20
+00000404: 7EB143A6  mtsprg1  r21
+00000408: 7E800026  mfcr     r20
+0000040C: 7C350B78  mr       r21,rsp
+00000410: 3AB5FF00  subi     r21,r21,256
+00000414: 929500A8  stw      r20,168(r21)
+00000418: 92D50068  stw      r22,104(r21)
+0000041C: 92F5006C  stw      r23,108(r21)
+00000420: 7E9042A6  mfsprg0  r20
+00000424: 92950060  stw      r20,96(r21)
+00000428: 7ED142A6  mfsprg1  r22
+0000042C: 92D50064  stw      r22,100(r21)
+00000430: 7E8802A6  mflr     r20
+00000434: 929500A0  stw      r20,160(r21)
+00000438: 7EC902A6  mfctr    r22
+0000043C: 92D5009C  stw      r22,156(r21)
+00000440: 7E8102A6  mfxer    r20
+00000444: 929500A4  stw      r20,164(r21)
+00000448: 7EDA02A6  mfsrr0   r22
+0000044C: 7EFB02A6  mfsrr1   r23
+00000450: 90150010  stw      r0,16(r21)
+00000454: 90350014  stw      rsp,20(r21)
+00000458: 90550018  stw      r2,24(r21)
+0000045C: 90350000  stw      rsp,0(r21)
+00000460: 7EA1AB78  mr       rsp,r21
+00000464: 9075001C  stw      r3,28(r21)
+00000468: 90950020  stw      r4,32(r21)
+0000046C: 90B50024  stw      r5,36(r21)
+00000470: 90D50028  stw      r6,40(r21)
+00000474: 806E8014  lwz      r3,-32748(r14)
+00000478: 7C6803A6  mtlr     r3
+0000047C: 38610010  addi     r3,rsp,16
+00000480: 3A801002  li       r20,4098
+00000484: 4E800021  blrl
+00000488: 00000488  dc.l     0x00000488              ; Invalid opcode '....'
+0000048C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="ExtInterrupt"  Size=0
+00000500: 7E9043A6  mtsprg0  r20
+00000504: 7EB143A6  mtsprg1  r21
+00000508: 7E800026  mfcr     r20
+0000050C: 7C350B78  mr       r21,rsp
+00000510: 3AB5FF00  subi     r21,r21,256
+00000514: 929500A8  stw      r20,168(r21)
+00000518: 92D50068  stw      r22,104(r21)
+0000051C: 92F5006C  stw      r23,108(r21)
+00000520: 7E9042A6  mfsprg0  r20
+00000524: 92950060  stw      r20,96(r21)
+00000528: 7ED142A6  mfsprg1  r22
+0000052C: 92D50064  stw      r22,100(r21)
+00000530: 7E8802A6  mflr     r20
+00000534: 929500A0  stw      r20,160(r21)
+00000538: 7EC902A6  mfctr    r22
+0000053C: 92D5009C  stw      r22,156(r21)
+00000540: 7E8102A6  mfxer    r20
+00000544: 929500A4  stw      r20,164(r21)
+00000548: 7EDA02A6  mfsrr0   r22
+0000054C: 7EFB02A6  mfsrr1   r23
+00000550: 90150010  stw      r0,16(r21)
+00000554: 90350014  stw      rsp,20(r21)
+00000558: 90550018  stw      r2,24(r21)
+0000055C: 90350000  stw      rsp,0(r21)
+00000560: 7EA1AB78  mr       rsp,r21
+00000564: 9075001C  stw      r3,28(r21)
+00000568: 90950020  stw      r4,32(r21)
+0000056C: 90B50024  stw      r5,36(r21)
+00000570: 90D50028  stw      r6,40(r21)
+00000574: 806E8014  lwz      r3,-32748(r14)
+00000578: 7C6803A6  mtlr     r3
+0000057C: 38610010  addi     r3,rsp,16
+00000580: 3A801002  li       r20,4098
+00000584: 4E800021  blrl
+00000588: 00000588  dc.l     0x00000588              ; Invalid opcode '....'
+0000058C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Alignment"  Size=0
+00000600: 7E9043A6  mtsprg0  r20
+00000604: 7EB143A6  mtsprg1  r21
+00000608: 7E800026  mfcr     r20
+0000060C: 7C350B78  mr       r21,rsp
+00000610: 3AB5FF00  subi     r21,r21,256
+00000614: 929500A8  stw      r20,168(r21)
+00000618: 92D50068  stw      r22,104(r21)
+0000061C: 92F5006C  stw      r23,108(r21)
+00000620: 7E9042A6  mfsprg0  r20
+00000624: 92950060  stw      r20,96(r21)
+00000628: 7ED142A6  mfsprg1  r22
+0000062C: 92D50064  stw      r22,100(r21)
+00000630: 7E8802A6  mflr     r20
+00000634: 929500A0  stw      r20,160(r21)
+00000638: 7EC902A6  mfctr    r22
+0000063C: 92D5009C  stw      r22,156(r21)
+00000640: 7E8102A6  mfxer    r20
+00000644: 929500A4  stw      r20,164(r21)
+00000648: 7EDA02A6  mfsrr0   r22
+0000064C: 7EFB02A6  mfsrr1   r23
+00000650: 90150010  stw      r0,16(r21)
+00000654: 90350014  stw      rsp,20(r21)
+00000658: 90550018  stw      r2,24(r21)
+0000065C: 90350000  stw      rsp,0(r21)
+00000660: 7EA1AB78  mr       rsp,r21
+00000664: 9075001C  stw      r3,28(r21)
+00000668: 90950020  stw      r4,32(r21)
+0000066C: 90B50024  stw      r5,36(r21)
+00000670: 90D50028  stw      r6,40(r21)
+00000674: 7C9302A6  mfspr    r4,DAR
+00000678: 909500B4  stw      r4,180(r21)
+0000067C: 7CB202A6  mfspr    r5,DSISR
+00000680: 90B500B8  stw      r5,184(r21)
+00000684: 38610010  addi     r3,rsp,16
+00000688: 3A801002  li       r20,4098
+0000068C: 52F40420  rlwimi   r20,r23,0,16,16
+00000690: 80CE8014  lwz      r6,-32748(r14)
+00000694: 7CC803A6  mtlr     r6
+00000698: 4E800021  blrl
+0000069C: 0000069C  dc.l     0x0000069c              ; Invalid opcode '....'
+000006A0: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="ProgramCheck"  Size=0
+00000700: 7E9043A6  mtsprg0  r20
+00000704: 7EB143A6  mtsprg1  r21
+00000708: 7E800026  mfcr     r20
+0000070C: 7C350B78  mr       r21,rsp
+00000710: 3AB5FF00  subi     r21,r21,256
+00000714: 929500A8  stw      r20,168(r21)
+00000718: 92D50068  stw      r22,104(r21)
+0000071C: 92F5006C  stw      r23,108(r21)
+00000720: 7E9042A6  mfsprg0  r20
+00000724: 92950060  stw      r20,96(r21)
+00000728: 7ED142A6  mfsprg1  r22
+0000072C: 92D50064  stw      r22,100(r21)
+00000730: 7E8802A6  mflr     r20
+00000734: 929500A0  stw      r20,160(r21)
+00000738: 7EC902A6  mfctr    r22
+0000073C: 92D5009C  stw      r22,156(r21)
+00000740: 7E8102A6  mfxer    r20
+00000744: 929500A4  stw      r20,164(r21)
+00000748: 7EDA02A6  mfsrr0   r22
+0000074C: 7EFB02A6  mfsrr1   r23
+00000750: 90150010  stw      r0,16(r21)
+00000754: 90350014  stw      rsp,20(r21)
+00000758: 90550018  stw      r2,24(r21)
+0000075C: 90350000  stw      rsp,0(r21)
+00000760: 7EA1AB78  mr       rsp,r21
+00000764: 9075001C  stw      r3,28(r21)
+00000768: 90950020  stw      r4,32(r21)
+0000076C: 90B50024  stw      r5,36(r21)
+00000770: 90D50028  stw      r6,40(r21)
+00000774: 38610010  addi     r3,rsp,16
+00000778: 3A801002  li       r20,4098
+0000077C: 52F40420  rlwimi   r20,r23,0,16,16
+00000780: 80CE8014  lwz      r6,-32748(r14)
+00000784: 7CC803A6  mtlr     r6
+00000788: 4E800021  blrl
+0000078C: 0000078C  dc.l     0x0000078c              ; Invalid opcode '....'
+00000790: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="FPUnavailable"  Size=0
+00000800: 7E9043A6  mtsprg0  r20
+00000804: 7EB143A6  mtsprg1  r21
+00000808: 7E800026  mfcr     r20
+0000080C: 7C350B78  mr       r21,rsp
+00000810: 3AB5FF00  subi     r21,r21,256
+00000814: 929500A8  stw      r20,168(r21)
+00000818: 92D50068  stw      r22,104(r21)
+0000081C: 92F5006C  stw      r23,108(r21)
+00000820: 7E9042A6  mfsprg0  r20
+00000824: 92950060  stw      r20,96(r21)
+00000828: 7ED142A6  mfsprg1  r22
+0000082C: 92D50064  stw      r22,100(r21)
+00000830: 7E8802A6  mflr     r20
+00000834: 929500A0  stw      r20,160(r21)
+00000838: 7EC902A6  mfctr    r22
+0000083C: 92D5009C  stw      r22,156(r21)
+00000840: 7E8102A6  mfxer    r20
+00000844: 929500A4  stw      r20,164(r21)
+00000848: 7EDA02A6  mfsrr0   r22
+0000084C: 7EFB02A6  mfsrr1   r23
+00000850: 90150010  stw      r0,16(r21)
+00000854: 90350014  stw      rsp,20(r21)
+00000858: 90550018  stw      r2,24(r21)
+0000085C: 90350000  stw      rsp,0(r21)
+00000860: 7EA1AB78  mr       rsp,r21
+00000864: 9075001C  stw      r3,28(r21)
+00000868: 90950020  stw      r4,32(r21)
+0000086C: 90B50024  stw      r5,36(r21)
+00000870: 90D50028  stw      r6,40(r21)
+00000874: 806E8014  lwz      r3,-32748(r14)
+00000878: 7C6803A6  mtlr     r3
+0000087C: 38610010  addi     r3,rsp,16
+00000880: 3A801002  li       r20,4098
+00000884: 4E800021  blrl
+00000888: 00000888  dc.l     0x00000888              ; Invalid opcode '....'
+0000088C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Decrementer"  Size=0
+00000900: 7E9043A6  mtsprg0  r20
+00000904: 7EB143A6  mtsprg1  r21
+00000908: 7E800026  mfcr     r20
+0000090C: 7C350B78  mr       r21,rsp
+00000910: 3AB5FF00  subi     r21,r21,256
+00000914: 929500A8  stw      r20,168(r21)
+00000918: 92D50068  stw      r22,104(r21)
+0000091C: 92F5006C  stw      r23,108(r21)
+00000920: 7E9042A6  mfsprg0  r20
+00000924: 92950060  stw      r20,96(r21)
+00000928: 7ED142A6  mfsprg1  r22
+0000092C: 92D50064  stw      r22,100(r21)
+00000930: 7E8802A6  mflr     r20
+00000934: 929500A0  stw      r20,160(r21)
+00000938: 7EC902A6  mfctr    r22
+0000093C: 92D5009C  stw      r22,156(r21)
+00000940: 7E8102A6  mfxer    r20
+00000944: 929500A4  stw      r20,164(r21)
+00000948: 7EDA02A6  mfsrr0   r22
+0000094C: 7EFB02A6  mfsrr1   r23
+00000950: 90150010  stw      r0,16(r21)
+00000954: 90350014  stw      rsp,20(r21)
+00000958: 90550018  stw      r2,24(r21)
+0000095C: 90350000  stw      rsp,0(r21)
+00000960: 7EA1AB78  mr       rsp,r21
+00000964: 9075001C  stw      r3,28(r21)
+00000968: 90950020  stw      r4,32(r21)
+0000096C: 90B50024  stw      r5,36(r21)
+00000970: 90D50028  stw      r6,40(r21)
+00000974: 806E8014  lwz      r3,-32748(r14)
+00000978: 7C6803A6  mtlr     r3
+0000097C: 38610010  addi     r3,rsp,16
+00000980: 3A801002  li       r20,4098
+00000984: 4E800021  blrl
+00000988: 00000988  dc.l     0x00000988              ; Invalid opcode '....'
+0000098C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Trap_0a"  Size=0
+00000A00: 7E9043A6  mtsprg0  r20
+00000A04: 7EB143A6  mtsprg1  r21
+00000A08: 7E800026  mfcr     r20
+00000A0C: 7C350B78  mr       r21,rsp
+00000A10: 3AB5FF00  subi     r21,r21,256
+00000A14: 929500A8  stw      r20,168(r21)
+00000A18: 92D50068  stw      r22,104(r21)
+00000A1C: 92F5006C  stw      r23,108(r21)
+00000A20: 7E9042A6  mfsprg0  r20
+00000A24: 92950060  stw      r20,96(r21)
+00000A28: 7ED142A6  mfsprg1  r22
+00000A2C: 92D50064  stw      r22,100(r21)
+00000A30: 7E8802A6  mflr     r20
+00000A34: 929500A0  stw      r20,160(r21)
+00000A38: 7EC902A6  mfctr    r22
+00000A3C: 92D5009C  stw      r22,156(r21)
+00000A40: 7E8102A6  mfxer    r20
+00000A44: 929500A4  stw      r20,164(r21)
+00000A48: 7EDA02A6  mfsrr0   r22
+00000A4C: 7EFB02A6  mfsrr1   r23
+00000A50: 90150010  stw      r0,16(r21)
+00000A54: 90350014  stw      rsp,20(r21)
+00000A58: 90550018  stw      r2,24(r21)
+00000A5C: 90350000  stw      rsp,0(r21)
+00000A60: 7EA1AB78  mr       rsp,r21
+00000A64: 9075001C  stw      r3,28(r21)
+00000A68: 90950020  stw      r4,32(r21)
+00000A6C: 90B50024  stw      r5,36(r21)
+00000A70: 90D50028  stw      r6,40(r21)
+00000A74: 806E8014  lwz      r3,-32748(r14)
+00000A78: 7C6803A6  mtlr     r3
+00000A7C: 38610010  addi     r3,rsp,16
+00000A80: 3A801002  li       r20,4098
+00000A84: 4E800021  blrl
+00000A88: 00000A88  dc.l     0x00000a88              ; Invalid opcode '....'
+00000A8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Trap_0b"  Size=0
+00000B00: 7E9043A6  mtsprg0  r20
+00000B04: 7EB143A6  mtsprg1  r21
+00000B08: 7E800026  mfcr     r20
+00000B0C: 7C350B78  mr       r21,rsp
+00000B10: 3AB5FF00  subi     r21,r21,256
+00000B14: 929500A8  stw      r20,168(r21)
+00000B18: 92D50068  stw      r22,104(r21)
+00000B1C: 92F5006C  stw      r23,108(r21)
+00000B20: 7E9042A6  mfsprg0  r20
+00000B24: 92950060  stw      r20,96(r21)
+00000B28: 7ED142A6  mfsprg1  r22
+00000B2C: 92D50064  stw      r22,100(r21)
+00000B30: 7E8802A6  mflr     r20
+00000B34: 929500A0  stw      r20,160(r21)
+00000B38: 7EC902A6  mfctr    r22
+00000B3C: 92D5009C  stw      r22,156(r21)
+00000B40: 7E8102A6  mfxer    r20
+00000B44: 929500A4  stw      r20,164(r21)
+00000B48: 7EDA02A6  mfsrr0   r22
+00000B4C: 7EFB02A6  mfsrr1   r23
+00000B50: 90150010  stw      r0,16(r21)
+00000B54: 90350014  stw      rsp,20(r21)
+00000B58: 90550018  stw      r2,24(r21)
+00000B5C: 90350000  stw      rsp,0(r21)
+00000B60: 7EA1AB78  mr       rsp,r21
+00000B64: 9075001C  stw      r3,28(r21)
+00000B68: 90950020  stw      r4,32(r21)
+00000B6C: 90B50024  stw      r5,36(r21)
+00000B70: 90D50028  stw      r6,40(r21)
+00000B74: 806E8014  lwz      r3,-32748(r14)
+00000B78: 7C6803A6  mtlr     r3
+00000B7C: 38610010  addi     r3,rsp,16
+00000B80: 3A801002  li       r20,4098
+00000B84: 4E800021  blrl
+00000B88: 00000B88  dc.l     0x00000b88              ; Invalid opcode '....'
+00000B8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="SystemCall"  Size=0
+00000C00: 7E9043A6  mtsprg0  r20
+00000C04: 7EB143A6  mtsprg1  r21
+00000C08: 7E800026  mfcr     r20
+00000C0C: 7C350B78  mr       r21,rsp
+00000C10: 3AB5FF00  subi     r21,r21,256
+00000C14: 929500A8  stw      r20,168(r21)
+00000C18: 92D50068  stw      r22,104(r21)
+00000C1C: 92F5006C  stw      r23,108(r21)
+00000C20: 7E9042A6  mfsprg0  r20
+00000C24: 92950060  stw      r20,96(r21)
+00000C28: 7ED142A6  mfsprg1  r22
+00000C2C: 92D50064  stw      r22,100(r21)
+00000C30: 7E8802A6  mflr     r20
+00000C34: 929500A0  stw      r20,160(r21)
+00000C38: 7EC902A6  mfctr    r22
+00000C3C: 92D5009C  stw      r22,156(r21)
+00000C40: 7E8102A6  mfxer    r20
+00000C44: 929500A4  stw      r20,164(r21)
+00000C48: 7EDA02A6  mfsrr0   r22
+00000C4C: 7EFB02A6  mfsrr1   r23
+00000C50: 90150010  stw      r0,16(r21)
+00000C54: 90350014  stw      rsp,20(r21)
+00000C58: 90550018  stw      r2,24(r21)
+00000C5C: 90350000  stw      rsp,0(r21)
+00000C60: 7EA1AB78  mr       rsp,r21
+00000C64: 9075001C  stw      r3,28(r21)
+00000C68: 90950020  stw      r4,32(r21)
+00000C6C: 90B50024  stw      r5,36(r21)
+00000C70: 90D50028  stw      r6,40(r21)
+00000C74: 806E8014  lwz      r3,-32748(r14)
+00000C78: 7C6803A6  mtlr     r3
+00000C7C: 38610010  addi     r3,rsp,16
+00000C80: 3A801002  li       r20,4098
+00000C84: 4E800021  blrl
+00000C88: 00000C88  dc.l     0x00000c88              ; Invalid opcode '....'
+00000C8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="SingleStep"  Size=0
+00000D00: 7E9043A6  mtsprg0  r20
+00000D04: 7EB143A6  mtsprg1  r21
+00000D08: 7E800026  mfcr     r20
+00000D0C: 7C350B78  mr       r21,rsp
+00000D10: 3AB5FF00  subi     r21,r21,256
+00000D14: 929500A8  stw      r20,168(r21)
+00000D18: 92D50068  stw      r22,104(r21)
+00000D1C: 92F5006C  stw      r23,108(r21)
+00000D20: 7E9042A6  mfsprg0  r20
+00000D24: 92950060  stw      r20,96(r21)
+00000D28: 7ED142A6  mfsprg1  r22
+00000D2C: 92D50064  stw      r22,100(r21)
+00000D30: 7E8802A6  mflr     r20
+00000D34: 929500A0  stw      r20,160(r21)
+00000D38: 7EC902A6  mfctr    r22
+00000D3C: 92D5009C  stw      r22,156(r21)
+00000D40: 7E8102A6  mfxer    r20
+00000D44: 929500A4  stw      r20,164(r21)
+00000D48: 7EDA02A6  mfsrr0   r22
+00000D4C: 7EFB02A6  mfsrr1   r23
+00000D50: 90150010  stw      r0,16(r21)
+00000D54: 90350014  stw      rsp,20(r21)
+00000D58: 90550018  stw      r2,24(r21)
+00000D5C: 90350000  stw      rsp,0(r21)
+00000D60: 7EA1AB78  mr       rsp,r21
+00000D64: 9075001C  stw      r3,28(r21)
+00000D68: 90950020  stw      r4,32(r21)
+00000D6C: 90B50024  stw      r5,36(r21)
+00000D70: 90D50028  stw      r6,40(r21)
+00000D74: 806E8014  lwz      r3,-32748(r14)
+00000D78: 7C6803A6  mtlr     r3
+00000D7C: 38610010  addi     r3,rsp,16
+00000D80: 3A801002  li       r20,4098
+00000D84: 4E800021  blrl
+00000D88: 00000D88  dc.l     0x00000d88              ; Invalid opcode '....'
+00000D8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Trap_0e"  Size=0
+00000E00: 7E9043A6  mtsprg0  r20
+00000E04: 7EB143A6  mtsprg1  r21
+00000E08: 7E800026  mfcr     r20
+00000E0C: 7C350B78  mr       r21,rsp
+00000E10: 3AB5FF00  subi     r21,r21,256
+00000E14: 929500A8  stw      r20,168(r21)
+00000E18: 92D50068  stw      r22,104(r21)
+00000E1C: 92F5006C  stw      r23,108(r21)
+00000E20: 7E9042A6  mfsprg0  r20
+00000E24: 92950060  stw      r20,96(r21)
+00000E28: 7ED142A6  mfsprg1  r22
+00000E2C: 92D50064  stw      r22,100(r21)
+00000E30: 7E8802A6  mflr     r20
+00000E34: 929500A0  stw      r20,160(r21)
+00000E38: 7EC902A6  mfctr    r22
+00000E3C: 92D5009C  stw      r22,156(r21)
+00000E40: 7E8102A6  mfxer    r20
+00000E44: 929500A4  stw      r20,164(r21)
+00000E48: 7EDA02A6  mfsrr0   r22
+00000E4C: 7EFB02A6  mfsrr1   r23
+00000E50: 90150010  stw      r0,16(r21)
+00000E54: 90350014  stw      rsp,20(r21)
+00000E58: 90550018  stw      r2,24(r21)
+00000E5C: 90350000  stw      rsp,0(r21)
+00000E60: 7EA1AB78  mr       rsp,r21
+00000E64: 9075001C  stw      r3,28(r21)
+00000E68: 90950020  stw      r4,32(r21)
+00000E6C: 90B50024  stw      r5,36(r21)
+00000E70: 90D50028  stw      r6,40(r21)
+00000E74: 806E8014  lwz      r3,-32748(r14)
+00000E78: 7C6803A6  mtlr     r3
+00000E7C: 38610010  addi     r3,rsp,16
+00000E80: 3A801002  li       r20,4098
+00000E84: 4E800021  blrl
+00000E88: 00000E88  dc.l     0x00000e88              ; Invalid opcode '....'
+00000E8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Trap_0f"  Size=0
+00000F00: 7E9043A6  mtsprg0  r20
+00000F04: 7EB143A6  mtsprg1  r21
+00000F08: 7E800026  mfcr     r20
+00000F0C: 7C350B78  mr       r21,rsp
+00000F10: 3AB5FF00  subi     r21,r21,256
+00000F14: 929500A8  stw      r20,168(r21)
+00000F18: 92D50068  stw      r22,104(r21)
+00000F1C: 92F5006C  stw      r23,108(r21)
+00000F20: 7E9042A6  mfsprg0  r20
+00000F24: 92950060  stw      r20,96(r21)
+00000F28: 7ED142A6  mfsprg1  r22
+00000F2C: 92D50064  stw      r22,100(r21)
+00000F30: 7E8802A6  mflr     r20
+00000F34: 929500A0  stw      r20,160(r21)
+00000F38: 7EC902A6  mfctr    r22
+00000F3C: 92D5009C  stw      r22,156(r21)
+00000F40: 7E8102A6  mfxer    r20
+00000F44: 929500A4  stw      r20,164(r21)
+00000F48: 7EDA02A6  mfsrr0   r22
+00000F4C: 7EFB02A6  mfsrr1   r23
+00000F50: 90150010  stw      r0,16(r21)
+00000F54: 90350014  stw      rsp,20(r21)
+00000F58: 90550018  stw      r2,24(r21)
+00000F5C: 90350000  stw      rsp,0(r21)
+00000F60: 7EA1AB78  mr       rsp,r21
+00000F64: 9075001C  stw      r3,28(r21)
+00000F68: 90950020  stw      r4,32(r21)
+00000F6C: 90B50024  stw      r5,36(r21)
+00000F70: 90D50028  stw      r6,40(r21)
+00000F74: 806E8014  lwz      r3,-32748(r14)
+00000F78: 7C6803A6  mtlr     r3
+00000F7C: 38610010  addi     r3,rsp,16
+00000F80: 3A801002  li       r20,4098
+00000F84: 4E800021  blrl
+00000F88: 00000F88  dc.l     0x00000f88              ; Invalid opcode '....'
+00000F8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="InstructionTransMiss"  Size=0
+00001000: 7E9043A6  mtsprg0  r20
+00001004: 7EB143A6  mtsprg1  r21
+00001008: 7E800026  mfcr     r20
+0000100C: 7C350B78  mr       r21,rsp
+00001010: 3AB5FF00  subi     r21,r21,256
+00001014: 929500A8  stw      r20,168(r21)
+00001018: 92D50068  stw      r22,104(r21)
+0000101C: 92F5006C  stw      r23,108(r21)
+00001020: 7E9042A6  mfsprg0  r20
+00001024: 92950060  stw      r20,96(r21)
+00001028: 7ED142A6  mfsprg1  r22
+0000102C: 92D50064  stw      r22,100(r21)
+00001030: 7E8802A6  mflr     r20
+00001034: 929500A0  stw      r20,160(r21)
+00001038: 7EC902A6  mfctr    r22
+0000103C: 92D5009C  stw      r22,156(r21)
+00001040: 7E8102A6  mfxer    r20
+00001044: 929500A4  stw      r20,164(r21)
+00001048: 7EDA02A6  mfsrr0   r22
+0000104C: 7EFB02A6  mfsrr1   r23
+00001050: 90150010  stw      r0,16(r21)
+00001054: 90350014  stw      rsp,20(r21)
+00001058: 90550018  stw      r2,24(r21)
+0000105C: 90350000  stw      rsp,0(r21)
+00001060: 7EA1AB78  mr       rsp,r21
+00001064: 9075001C  stw      r3,28(r21)
+00001068: 90950020  stw      r4,32(r21)
+0000106C: 90B50024  stw      r5,36(r21)
+00001070: 90D50028  stw      r6,40(r21)
+00001074: 806E8014  lwz      r3,-32748(r14)
+00001078: 7C6803A6  mtlr     r3
+0000107C: 38610010  addi     r3,rsp,16
+00001080: 3A801002  li       r20,4098
+00001084: 4E800021  blrl
+00001088: 00001088  dc.l     0x00001088              ; Invalid opcode '....'
+0000108C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="DataLoadTransMiss"  Size=0
+00001100: 7E9043A6  mtsprg0  r20
+00001104: 7EB143A6  mtsprg1  r21
+00001108: 7E800026  mfcr     r20
+0000110C: 7C350B78  mr       r21,rsp
+00001110: 3AB5FF00  subi     r21,r21,256
+00001114: 929500A8  stw      r20,168(r21)
+00001118: 92D50068  stw      r22,104(r21)
+0000111C: 92F5006C  stw      r23,108(r21)
+00001120: 7E9042A6  mfsprg0  r20
+00001124: 92950060  stw      r20,96(r21)
+00001128: 7ED142A6  mfsprg1  r22
+0000112C: 92D50064  stw      r22,100(r21)
+00001130: 7E8802A6  mflr     r20
+00001134: 929500A0  stw      r20,160(r21)
+00001138: 7EC902A6  mfctr    r22
+0000113C: 92D5009C  stw      r22,156(r21)
+00001140: 7E8102A6  mfxer    r20
+00001144: 929500A4  stw      r20,164(r21)
+00001148: 7EDA02A6  mfsrr0   r22
+0000114C: 7EFB02A6  mfsrr1   r23
+00001150: 90150010  stw      r0,16(r21)
+00001154: 90350014  stw      rsp,20(r21)
+00001158: 90550018  stw      r2,24(r21)
+0000115C: 90350000  stw      rsp,0(r21)
+00001160: 7EA1AB78  mr       rsp,r21
+00001164: 9075001C  stw      r3,28(r21)
+00001168: 90950020  stw      r4,32(r21)
+0000116C: 90B50024  stw      r5,36(r21)
+00001170: 90D50028  stw      r6,40(r21)
+00001174: 806E8014  lwz      r3,-32748(r14)
+00001178: 7C6803A6  mtlr     r3
+0000117C: 38610010  addi     r3,rsp,16
+00001180: 3A801002  li       r20,4098
+00001184: 4E800021  blrl
+00001188: 00001188  dc.l     0x00001188              ; Invalid opcode '....'
+0000118C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="DataStoreTransMiss"  Size=0
+00001200: 7E9043A6  mtsprg0  r20
+00001204: 7EB143A6  mtsprg1  r21
+00001208: 7E800026  mfcr     r20
+0000120C: 7C350B78  mr       r21,rsp
+00001210: 3AB5FF00  subi     r21,r21,256
+00001214: 929500A8  stw      r20,168(r21)
+00001218: 92D50068  stw      r22,104(r21)
+0000121C: 92F5006C  stw      r23,108(r21)
+00001220: 7E9042A6  mfsprg0  r20
+00001224: 92950060  stw      r20,96(r21)
+00001228: 7ED142A6  mfsprg1  r22
+0000122C: 92D50064  stw      r22,100(r21)
+00001230: 7E8802A6  mflr     r20
+00001234: 929500A0  stw      r20,160(r21)
+00001238: 7EC902A6  mfctr    r22
+0000123C: 92D5009C  stw      r22,156(r21)
+00001240: 7E8102A6  mfxer    r20
+00001244: 929500A4  stw      r20,164(r21)
+00001248: 7EDA02A6  mfsrr0   r22
+0000124C: 7EFB02A6  mfsrr1   r23
+00001250: 90150010  stw      r0,16(r21)
+00001254: 90350014  stw      rsp,20(r21)
+00001258: 90550018  stw      r2,24(r21)
+0000125C: 90350000  stw      rsp,0(r21)
+00001260: 7EA1AB78  mr       rsp,r21
+00001264: 9075001C  stw      r3,28(r21)
+00001268: 90950020  stw      r4,32(r21)
+0000126C: 90B50024  stw      r5,36(r21)
+00001270: 90D50028  stw      r6,40(r21)
+00001274: 806E8014  lwz      r3,-32748(r14)
+00001278: 7C6803A6  mtlr     r3
+0000127C: 38610010  addi     r3,rsp,16
+00001280: 3A801002  li       r20,4098
+00001284: 4E800021  blrl
+00001288: 00001288  dc.l     0x00001288              ; Invalid opcode '....'
+0000128C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="InstructionBreakpoint"  Size=0
+00001300: 7E9043A6  mtsprg0  r20
+00001304: 7EB143A6  mtsprg1  r21
+00001308: 7E800026  mfcr     r20
+0000130C: 7C350B78  mr       r21,rsp
+00001310: 3AB5FF00  subi     r21,r21,256
+00001314: 929500A8  stw      r20,168(r21)
+00001318: 92D50068  stw      r22,104(r21)
+0000131C: 92F5006C  stw      r23,108(r21)
+00001320: 7E9042A6  mfsprg0  r20
+00001324: 92950060  stw      r20,96(r21)
+00001328: 7ED142A6  mfsprg1  r22
+0000132C: 92D50064  stw      r22,100(r21)
+00001330: 7E8802A6  mflr     r20
+00001334: 929500A0  stw      r20,160(r21)
+00001338: 7EC902A6  mfctr    r22
+0000133C: 92D5009C  stw      r22,156(r21)
+00001340: 7E8102A6  mfxer    r20
+00001344: 929500A4  stw      r20,164(r21)
+00001348: 7EDA02A6  mfsrr0   r22
+0000134C: 7EFB02A6  mfsrr1   r23
+00001350: 90150010  stw      r0,16(r21)
+00001354: 90350014  stw      rsp,20(r21)
+00001358: 90550018  stw      r2,24(r21)
+0000135C: 90350000  stw      rsp,0(r21)
+00001360: 7EA1AB78  mr       rsp,r21
+00001364: 9075001C  stw      r3,28(r21)
+00001368: 90950020  stw      r4,32(r21)
+0000136C: 90B50024  stw      r5,36(r21)
+00001370: 90D50028  stw      r6,40(r21)
+00001374: 806E8014  lwz      r3,-32748(r14)
+00001378: 7C6803A6  mtlr     r3
+0000137C: 38610010  addi     r3,rsp,16
+00001380: 3A801002  li       r20,4098
+00001384: 4E800021  blrl
+00001388: 00001388  dc.l     0x00001388              ; Invalid opcode '....'
+0000138C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="SysManageInt"  Size=0
+00001400: 7E9043A6  mtsprg0  r20
+00001404: 7EB143A6  mtsprg1  r21
+00001408: 7E800026  mfcr     r20
+0000140C: 7C350B78  mr       r21,rsp
+00001410: 3AB5FF00  subi     r21,r21,256
+00001414: 929500A8  stw      r20,168(r21)
+00001418: 92D50068  stw      r22,104(r21)
+0000141C: 92F5006C  stw      r23,108(r21)
+00001420: 7E9042A6  mfsprg0  r20
+00001424: 92950060  stw      r20,96(r21)
+00001428: 7ED142A6  mfsprg1  r22
+0000142C: 92D50064  stw      r22,100(r21)
+00001430: 7E8802A6  mflr     r20
+00001434: 929500A0  stw      r20,160(r21)
+00001438: 7EC902A6  mfctr    r22
+0000143C: 92D5009C  stw      r22,156(r21)
+00001440: 7E8102A6  mfxer    r20
+00001444: 929500A4  stw      r20,164(r21)
+00001448: 7EDA02A6  mfsrr0   r22
+0000144C: 7EFB02A6  mfsrr1   r23
+00001450: 90150010  stw      r0,16(r21)
+00001454: 90350014  stw      rsp,20(r21)
+00001458: 90550018  stw      r2,24(r21)
+0000145C: 90350000  stw      rsp,0(r21)
+00001460: 7EA1AB78  mr       rsp,r21
+00001464: 9075001C  stw      r3,28(r21)
+00001468: 90950020  stw      r4,32(r21)
+0000146C: 90B50024  stw      r5,36(r21)
+00001470: 90D50028  stw      r6,40(r21)
+00001474: 806E8014  lwz      r3,-32748(r14)
+00001478: 7C6803A6  mtlr     r3
+0000147C: 38610010  addi     r3,rsp,16
+00001480: 3A801002  li       r20,4098
+00001484: 4E800021  blrl
+00001488: 00001488  dc.l     0x00001488              ; Invalid opcode '....'
+0000148C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Reserved5"  Size=0
+00001500: 7E9043A6  mtsprg0  r20
+00001504: 7EB143A6  mtsprg1  r21
+00001508: 7E800026  mfcr     r20
+0000150C: 7C350B78  mr       r21,rsp
+00001510: 3AB5FF00  subi     r21,r21,256
+00001514: 929500A8  stw      r20,168(r21)
+00001518: 92D50068  stw      r22,104(r21)
+0000151C: 92F5006C  stw      r23,108(r21)
+00001520: 7E9042A6  mfsprg0  r20
+00001524: 92950060  stw      r20,96(r21)
+00001528: 7ED142A6  mfsprg1  r22
+0000152C: 92D50064  stw      r22,100(r21)
+00001530: 7E8802A6  mflr     r20
+00001534: 929500A0  stw      r20,160(r21)
+00001538: 7EC902A6  mfctr    r22
+0000153C: 92D5009C  stw      r22,156(r21)
+00001540: 7E8102A6  mfxer    r20
+00001544: 929500A4  stw      r20,164(r21)
+00001548: 7EDA02A6  mfsrr0   r22
+0000154C: 7EFB02A6  mfsrr1   r23
+00001550: 90150010  stw      r0,16(r21)
+00001554: 90350014  stw      rsp,20(r21)
+00001558: 90550018  stw      r2,24(r21)
+0000155C: 90350000  stw      rsp,0(r21)
+00001560: 7EA1AB78  mr       rsp,r21
+00001564: 9075001C  stw      r3,28(r21)
+00001568: 90950020  stw      r4,32(r21)
+0000156C: 90B50024  stw      r5,36(r21)
+00001570: 90D50028  stw      r6,40(r21)
+00001574: 806E8014  lwz      r3,-32748(r14)
+00001578: 7C6803A6  mtlr     r3
+0000157C: 38610010  addi     r3,rsp,16
+00001580: 3A801002  li       r20,4098
+00001584: 4E800021  blrl
+00001588: 00001588  dc.l     0x00001588              ; Invalid opcode '....'
+0000158C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Reserved6"  Size=0
+00001600: 7E9043A6  mtsprg0  r20
+00001604: 7EB143A6  mtsprg1  r21
+00001608: 7E800026  mfcr     r20
+0000160C: 7C350B78  mr       r21,rsp
+00001610: 3AB5FF00  subi     r21,r21,256
+00001614: 929500A8  stw      r20,168(r21)
+00001618: 92D50068  stw      r22,104(r21)
+0000161C: 92F5006C  stw      r23,108(r21)
+00001620: 7E9042A6  mfsprg0  r20
+00001624: 92950060  stw      r20,96(r21)
+00001628: 7ED142A6  mfsprg1  r22
+0000162C: 92D50064  stw      r22,100(r21)
+00001630: 7E8802A6  mflr     r20
+00001634: 929500A0  stw      r20,160(r21)
+00001638: 7EC902A6  mfctr    r22
+0000163C: 92D5009C  stw      r22,156(r21)
+00001640: 7E8102A6  mfxer    r20
+00001644: 929500A4  stw      r20,164(r21)
+00001648: 7EDA02A6  mfsrr0   r22
+0000164C: 7EFB02A6  mfsrr1   r23
+00001650: 90150010  stw      r0,16(r21)
+00001654: 90350014  stw      rsp,20(r21)
+00001658: 90550018  stw      r2,24(r21)
+0000165C: 90350000  stw      rsp,0(r21)
+00001660: 7EA1AB78  mr       rsp,r21
+00001664: 9075001C  stw      r3,28(r21)
+00001668: 90950020  stw      r4,32(r21)
+0000166C: 90B50024  stw      r5,36(r21)
+00001670: 90D50028  stw      r6,40(r21)
+00001674: 806E8014  lwz      r3,-32748(r14)
+00001678: 7C6803A6  mtlr     r3
+0000167C: 38610010  addi     r3,rsp,16
+00001680: 3A801002  li       r20,4098
+00001684: 4E800021  blrl
+00001688: 00001688  dc.l     0x00001688              ; Invalid opcode '....'
+0000168C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Reserved7"  Size=0
+00001700: 7E9043A6  mtsprg0  r20
+00001704: 7EB143A6  mtsprg1  r21
+00001708: 7E800026  mfcr     r20
+0000170C: 7C350B78  mr       r21,rsp
+00001710: 3AB5FF00  subi     r21,r21,256
+00001714: 929500A8  stw      r20,168(r21)
+00001718: 92D50068  stw      r22,104(r21)
+0000171C: 92F5006C  stw      r23,108(r21)
+00001720: 7E9042A6  mfsprg0  r20
+00001724: 92950060  stw      r20,96(r21)
+00001728: 7ED142A6  mfsprg1  r22
+0000172C: 92D50064  stw      r22,100(r21)
+00001730: 7E8802A6  mflr     r20
+00001734: 929500A0  stw      r20,160(r21)
+00001738: 7EC902A6  mfctr    r22
+0000173C: 92D5009C  stw      r22,156(r21)
+00001740: 7E8102A6  mfxer    r20
+00001744: 929500A4  stw      r20,164(r21)
+00001748: 7EDA02A6  mfsrr0   r22
+0000174C: 7EFB02A6  mfsrr1   r23
+00001750: 90150010  stw      r0,16(r21)
+00001754: 90350014  stw      rsp,20(r21)
+00001758: 90550018  stw      r2,24(r21)
+0000175C: 90350000  stw      rsp,0(r21)
+00001760: 7EA1AB78  mr       rsp,r21
+00001764: 9075001C  stw      r3,28(r21)
+00001768: 90950020  stw      r4,32(r21)
+0000176C: 90B50024  stw      r5,36(r21)
+00001770: 90D50028  stw      r6,40(r21)
+00001774: 806E8014  lwz      r3,-32748(r14)
+00001778: 7C6803A6  mtlr     r3
+0000177C: 38610010  addi     r3,rsp,16
+00001780: 3A801002  li       r20,4098
+00001784: 4E800021  blrl
+00001788: 00001788  dc.l     0x00001788              ; Invalid opcode '....'
+0000178C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Reserved8"  Size=0
+00001800: 7E9043A6  mtsprg0  r20
+00001804: 7EB143A6  mtsprg1  r21
+00001808: 7E800026  mfcr     r20
+0000180C: 7C350B78  mr       r21,rsp
+00001810: 3AB5FF00  subi     r21,r21,256
+00001814: 929500A8  stw      r20,168(r21)
+00001818: 92D50068  stw      r22,104(r21)
+0000181C: 92F5006C  stw      r23,108(r21)
+00001820: 7E9042A6  mfsprg0  r20
+00001824: 92950060  stw      r20,96(r21)
+00001828: 7ED142A6  mfsprg1  r22
+0000182C: 92D50064  stw      r22,100(r21)
+00001830: 7E8802A6  mflr     r20
+00001834: 929500A0  stw      r20,160(r21)
+00001838: 7EC902A6  mfctr    r22
+0000183C: 92D5009C  stw      r22,156(r21)
+00001840: 7E8102A6  mfxer    r20
+00001844: 929500A4  stw      r20,164(r21)
+00001848: 7EDA02A6  mfsrr0   r22
+0000184C: 7EFB02A6  mfsrr1   r23
+00001850: 90150010  stw      r0,16(r21)
+00001854: 90350014  stw      rsp,20(r21)
+00001858: 90550018  stw      r2,24(r21)
+0000185C: 90350000  stw      rsp,0(r21)
+00001860: 7EA1AB78  mr       rsp,r21
+00001864: 9075001C  stw      r3,28(r21)
+00001868: 90950020  stw      r4,32(r21)
+0000186C: 90B50024  stw      r5,36(r21)
+00001870: 90D50028  stw      r6,40(r21)
+00001874: 806E8014  lwz      r3,-32748(r14)
+00001878: 7C6803A6  mtlr     r3
+0000187C: 38610010  addi     r3,rsp,16
+00001880: 3A801002  li       r20,4098
+00001884: 4E800021  blrl
+00001888: 00001888  dc.l     0x00001888              ; Invalid opcode '....'
+0000188C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="Reserved9"  Size=0
+00001900: 7E9043A6  mtsprg0  r20
+00001904: 7EB143A6  mtsprg1  r21
+00001908: 7E800026  mfcr     r20
+0000190C: 7C350B78  mr       r21,rsp
+00001910: 3AB5FF00  subi     r21,r21,256
+00001914: 929500A8  stw      r20,168(r21)
+00001918: 92D50068  stw      r22,104(r21)
+0000191C: 92F5006C  stw      r23,108(r21)
+00001920: 7E9042A6  mfsprg0  r20
+00001924: 92950060  stw      r20,96(r21)
+00001928: 7ED142A6  mfsprg1  r22
+0000192C: 92D50064  stw      r22,100(r21)
+00001930: 7E8802A6  mflr     r20
+00001934: 929500A0  stw      r20,160(r21)
+00001938: 7EC902A6  mfctr    r22
+0000193C: 92D5009C  stw      r22,156(r21)
+00001940: 7E8102A6  mfxer    r20
+00001944: 929500A4  stw      r20,164(r21)
+00001948: 7EDA02A6  mfsrr0   r22
+0000194C: 7EFB02A6  mfsrr1   r23
+00001950: 90150010  stw      r0,16(r21)
+00001954: 90350014  stw      rsp,20(r21)
+00001958: 90550018  stw      r2,24(r21)
+0000195C: 90350000  stw      rsp,0(r21)
+00001960: 7EA1AB78  mr       rsp,r21
+00001964: 9075001C  stw      r3,28(r21)
+00001968: 90950020  stw      r4,32(r21)
+0000196C: 90B50024  stw      r5,36(r21)
+00001970: 90D50028  stw      r6,40(r21)
+00001974: 806E8014  lwz      r3,-32748(r14)
+00001978: 7C6803A6  mtlr     r3
+0000197C: 38610010  addi     r3,rsp,16
+00001980: 3A801002  li       r20,4098
+00001984: 4E800021  blrl
+00001988: 00001988  dc.l     0x00001988              ; Invalid opcode '....'
+0000198C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="ReservedA"  Size=0
+00001A00: 7E9043A6  mtsprg0  r20
+00001A04: 7EB143A6  mtsprg1  r21
+00001A08: 7E800026  mfcr     r20
+00001A0C: 7C350B78  mr       r21,rsp
+00001A10: 3AB5FF00  subi     r21,r21,256
+00001A14: 929500A8  stw      r20,168(r21)
+00001A18: 92D50068  stw      r22,104(r21)
+00001A1C: 92F5006C  stw      r23,108(r21)
+00001A20: 7E9042A6  mfsprg0  r20
+00001A24: 92950060  stw      r20,96(r21)
+00001A28: 7ED142A6  mfsprg1  r22
+00001A2C: 92D50064  stw      r22,100(r21)
+00001A30: 7E8802A6  mflr     r20
+00001A34: 929500A0  stw      r20,160(r21)
+00001A38: 7EC902A6  mfctr    r22
+00001A3C: 92D5009C  stw      r22,156(r21)
+00001A40: 7E8102A6  mfxer    r20
+00001A44: 929500A4  stw      r20,164(r21)
+00001A48: 7EDA02A6  mfsrr0   r22
+00001A4C: 7EFB02A6  mfsrr1   r23
+00001A50: 90150010  stw      r0,16(r21)
+00001A54: 90350014  stw      rsp,20(r21)
+00001A58: 90550018  stw      r2,24(r21)
+00001A5C: 90350000  stw      rsp,0(r21)
+00001A60: 7EA1AB78  mr       rsp,r21
+00001A64: 9075001C  stw      r3,28(r21)
+00001A68: 90950020  stw      r4,32(r21)
+00001A6C: 90B50024  stw      r5,36(r21)
+00001A70: 90D50028  stw      r6,40(r21)
+00001A74: 806E8014  lwz      r3,-32748(r14)
+00001A78: 7C6803A6  mtlr     r3
+00001A7C: 38610010  addi     r3,rsp,16
+00001A80: 3A801002  li       r20,4098
+00001A84: 4E800021  blrl
+00001A88: 00001A88  dc.l     0x00001a88              ; Invalid opcode '....'
+00001A8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="ReservedB"  Size=0
+00001B00: 7E9043A6  mtsprg0  r20
+00001B04: 7EB143A6  mtsprg1  r21
+00001B08: 7E800026  mfcr     r20
+00001B0C: 7C350B78  mr       r21,rsp
+00001B10: 3AB5FF00  subi     r21,r21,256
+00001B14: 929500A8  stw      r20,168(r21)
+00001B18: 92D50068  stw      r22,104(r21)
+00001B1C: 92F5006C  stw      r23,108(r21)
+00001B20: 7E9042A6  mfsprg0  r20
+00001B24: 92950060  stw      r20,96(r21)
+00001B28: 7ED142A6  mfsprg1  r22
+00001B2C: 92D50064  stw      r22,100(r21)
+00001B30: 7E8802A6  mflr     r20
+00001B34: 929500A0  stw      r20,160(r21)
+00001B38: 7EC902A6  mfctr    r22
+00001B3C: 92D5009C  stw      r22,156(r21)
+00001B40: 7E8102A6  mfxer    r20
+00001B44: 929500A4  stw      r20,164(r21)
+00001B48: 7EDA02A6  mfsrr0   r22
+00001B4C: 7EFB02A6  mfsrr1   r23
+00001B50: 90150010  stw      r0,16(r21)
+00001B54: 90350014  stw      rsp,20(r21)
+00001B58: 90550018  stw      r2,24(r21)
+00001B5C: 90350000  stw      rsp,0(r21)
+00001B60: 7EA1AB78  mr       rsp,r21
+00001B64: 9075001C  stw      r3,28(r21)
+00001B68: 90950020  stw      r4,32(r21)
+00001B6C: 90B50024  stw      r5,36(r21)
+00001B70: 90D50028  stw      r6,40(r21)
+00001B74: 806E8014  lwz      r3,-32748(r14)
+00001B78: 7C6803A6  mtlr     r3
+00001B7C: 38610010  addi     r3,rsp,16
+00001B80: 3A801002  li       r20,4098
+00001B84: 4E800021  blrl
+00001B88: 00001B88  dc.l     0x00001b88              ; Invalid opcode '....'
+00001B8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="ReservedC"  Size=0
+00001C00: 7E9043A6  mtsprg0  r20
+00001C04: 7EB143A6  mtsprg1  r21
+00001C08: 7E800026  mfcr     r20
+00001C0C: 7C350B78  mr       r21,rsp
+00001C10: 3AB5FF00  subi     r21,r21,256
+00001C14: 929500A8  stw      r20,168(r21)
+00001C18: 92D50068  stw      r22,104(r21)
+00001C1C: 92F5006C  stw      r23,108(r21)
+00001C20: 7E9042A6  mfsprg0  r20
+00001C24: 92950060  stw      r20,96(r21)
+00001C28: 7ED142A6  mfsprg1  r22
+00001C2C: 92D50064  stw      r22,100(r21)
+00001C30: 7E8802A6  mflr     r20
+00001C34: 929500A0  stw      r20,160(r21)
+00001C38: 7EC902A6  mfctr    r22
+00001C3C: 92D5009C  stw      r22,156(r21)
+00001C40: 7E8102A6  mfxer    r20
+00001C44: 929500A4  stw      r20,164(r21)
+00001C48: 7EDA02A6  mfsrr0   r22
+00001C4C: 7EFB02A6  mfsrr1   r23
+00001C50: 90150010  stw      r0,16(r21)
+00001C54: 90350014  stw      rsp,20(r21)
+00001C58: 90550018  stw      r2,24(r21)
+00001C5C: 90350000  stw      rsp,0(r21)
+00001C60: 7EA1AB78  mr       rsp,r21
+00001C64: 9075001C  stw      r3,28(r21)
+00001C68: 90950020  stw      r4,32(r21)
+00001C6C: 90B50024  stw      r5,36(r21)
+00001C70: 90D50028  stw      r6,40(r21)
+00001C74: 806E8014  lwz      r3,-32748(r14)
+00001C78: 7C6803A6  mtlr     r3
+00001C7C: 38610010  addi     r3,rsp,16
+00001C80: 3A801002  li       r20,4098
+00001C84: 4E800021  blrl
+00001C88: 00001C88  dc.l     0x00001c88              ; Invalid opcode '....'
+00001C8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="ReservedD"  Size=0
+00001D00: 7E9043A6  mtsprg0  r20
+00001D04: 7EB143A6  mtsprg1  r21
+00001D08: 7E800026  mfcr     r20
+00001D0C: 7C350B78  mr       r21,rsp
+00001D10: 3AB5FF00  subi     r21,r21,256
+00001D14: 929500A8  stw      r20,168(r21)
+00001D18: 92D50068  stw      r22,104(r21)
+00001D1C: 92F5006C  stw      r23,108(r21)
+00001D20: 7E9042A6  mfsprg0  r20
+00001D24: 92950060  stw      r20,96(r21)
+00001D28: 7ED142A6  mfsprg1  r22
+00001D2C: 92D50064  stw      r22,100(r21)
+00001D30: 7E8802A6  mflr     r20
+00001D34: 929500A0  stw      r20,160(r21)
+00001D38: 7EC902A6  mfctr    r22
+00001D3C: 92D5009C  stw      r22,156(r21)
+00001D40: 7E8102A6  mfxer    r20
+00001D44: 929500A4  stw      r20,164(r21)
+00001D48: 7EDA02A6  mfsrr0   r22
+00001D4C: 7EFB02A6  mfsrr1   r23
+00001D50: 90150010  stw      r0,16(r21)
+00001D54: 90350014  stw      rsp,20(r21)
+00001D58: 90550018  stw      r2,24(r21)
+00001D5C: 90350000  stw      rsp,0(r21)
+00001D60: 7EA1AB78  mr       rsp,r21
+00001D64: 9075001C  stw      r3,28(r21)
+00001D68: 90950020  stw      r4,32(r21)
+00001D6C: 90B50024  stw      r5,36(r21)
+00001D70: 90D50028  stw      r6,40(r21)
+00001D74: 806E8014  lwz      r3,-32748(r14)
+00001D78: 7C6803A6  mtlr     r3
+00001D7C: 38610010  addi     r3,rsp,16
+00001D80: 3A801002  li       r20,4098
+00001D84: 4E800021  blrl
+00001D88: 00001D88  dc.l     0x00001d88              ; Invalid opcode '....'
+00001D8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="ReservedE"  Size=0
+00001E00: 7E9043A6  mtsprg0  r20
+00001E04: 7EB143A6  mtsprg1  r21
+00001E08: 7E800026  mfcr     r20
+00001E0C: 7C350B78  mr       r21,rsp
+00001E10: 3AB5FF00  subi     r21,r21,256
+00001E14: 929500A8  stw      r20,168(r21)
+00001E18: 92D50068  stw      r22,104(r21)
+00001E1C: 92F5006C  stw      r23,108(r21)
+00001E20: 7E9042A6  mfsprg0  r20
+00001E24: 92950060  stw      r20,96(r21)
+00001E28: 7ED142A6  mfsprg1  r22
+00001E2C: 92D50064  stw      r22,100(r21)
+00001E30: 7E8802A6  mflr     r20
+00001E34: 929500A0  stw      r20,160(r21)
+00001E38: 7EC902A6  mfctr    r22
+00001E3C: 92D5009C  stw      r22,156(r21)
+00001E40: 7E8102A6  mfxer    r20
+00001E44: 929500A4  stw      r20,164(r21)
+00001E48: 7EDA02A6  mfsrr0   r22
+00001E4C: 7EFB02A6  mfsrr1   r23
+00001E50: 90150010  stw      r0,16(r21)
+00001E54: 90350014  stw      rsp,20(r21)
+00001E58: 90550018  stw      r2,24(r21)
+00001E5C: 90350000  stw      rsp,0(r21)
+00001E60: 7EA1AB78  mr       rsp,r21
+00001E64: 9075001C  stw      r3,28(r21)
+00001E68: 90950020  stw      r4,32(r21)
+00001E6C: 90B50024  stw      r5,36(r21)
+00001E70: 90D50028  stw      r6,40(r21)
+00001E74: 806E8014  lwz      r3,-32748(r14)
+00001E78: 7C6803A6  mtlr     r3
+00001E7C: 38610010  addi     r3,rsp,16
+00001E80: 3A801002  li       r20,4098
+00001E84: 4E800021  blrl
+00001E88: 00001E88  dc.l     0x00001e88              ; Invalid opcode '....'
+00001E8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="ReservedF"  Size=0
+00001F00: 7E9043A6  mtsprg0  r20
+00001F04: 7EB143A6  mtsprg1  r21
+00001F08: 7E800026  mfcr     r20
+00001F0C: 7C350B78  mr       r21,rsp
+00001F10: 3AB5FF00  subi     r21,r21,256
+00001F14: 929500A8  stw      r20,168(r21)
+00001F18: 92D50068  stw      r22,104(r21)
+00001F1C: 92F5006C  stw      r23,108(r21)
+00001F20: 7E9042A6  mfsprg0  r20
+00001F24: 92950060  stw      r20,96(r21)
+00001F28: 7ED142A6  mfsprg1  r22
+00001F2C: 92D50064  stw      r22,100(r21)
+00001F30: 7E8802A6  mflr     r20
+00001F34: 929500A0  stw      r20,160(r21)
+00001F38: 7EC902A6  mfctr    r22
+00001F3C: 92D5009C  stw      r22,156(r21)
+00001F40: 7E8102A6  mfxer    r20
+00001F44: 929500A4  stw      r20,164(r21)
+00001F48: 7EDA02A6  mfsrr0   r22
+00001F4C: 7EFB02A6  mfsrr1   r23
+00001F50: 90150010  stw      r0,16(r21)
+00001F54: 90350014  stw      rsp,20(r21)
+00001F58: 90550018  stw      r2,24(r21)
+00001F5C: 90350000  stw      rsp,0(r21)
+00001F60: 7EA1AB78  mr       rsp,r21
+00001F64: 9075001C  stw      r3,28(r21)
+00001F68: 90950020  stw      r4,32(r21)
+00001F6C: 90B50024  stw      r5,36(r21)
+00001F70: 90D50028  stw      r6,40(r21)
+00001F74: 806E8014  lwz      r3,-32748(r14)
+00001F78: 7C6803A6  mtlr     r3
+00001F7C: 38610010  addi     r3,rsp,16
+00001F80: 3A801002  li       r20,4098
+00001F84: 4E800021  blrl
+00001F88: 00001F88  dc.l     0x00001f88              ; Invalid opcode '....'
+00001F8C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="RunModeTrace"  Size=0
+00002000: 7E9043A6  mtsprg0  r20
+00002004: 7EB143A6  mtsprg1  r21
+00002008: 7E800026  mfcr     r20
+0000200C: 7C350B78  mr       r21,rsp
+00002010: 3AB5FF00  subi     r21,r21,256
+00002014: 929500A8  stw      r20,168(r21)
+00002018: 92D50068  stw      r22,104(r21)
+0000201C: 92F5006C  stw      r23,108(r21)
+00002020: 7E9042A6  mfsprg0  r20
+00002024: 92950060  stw      r20,96(r21)
+00002028: 7ED142A6  mfsprg1  r22
+0000202C: 92D50064  stw      r22,100(r21)
+00002030: 7E8802A6  mflr     r20
+00002034: 929500A0  stw      r20,160(r21)
+00002038: 7EC902A6  mfctr    r22
+0000203C: 92D5009C  stw      r22,156(r21)
+00002040: 7E8102A6  mfxer    r20
+00002044: 929500A4  stw      r20,164(r21)
+00002048: 7EDA02A6  mfsrr0   r22
+0000204C: 7EFB02A6  mfsrr1   r23
+00002050: 90150010  stw      r0,16(r21)
+00002054: 90350014  stw      rsp,20(r21)
+00002058: 90550018  stw      r2,24(r21)
+0000205C: 90350000  stw      rsp,0(r21)
+00002060: 7EA1AB78  mr       rsp,r21
+00002064: 9075001C  stw      r3,28(r21)
+00002068: 90950020  stw      r4,32(r21)
+0000206C: 90B50024  stw      r5,36(r21)
+00002070: 90D50028  stw      r6,40(r21)
+00002074: 806E8014  lwz      r3,-32748(r14)
+00002078: 7C6803A6  mtlr     r3
+0000207C: 38610010  addi     r3,rsp,16
+00002080: 3A801002  li       r20,4098
+00002084: 4E800021  blrl
+00002088: 00002088  dc.l     0x00002088              ; Invalid opcode '.. .'
+0000208C: 0000309C  dc.l     0x0000309c              ; Invalid opcode '..0.'
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="_end_of_vectors"  Size=0
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="transfer_to_handler"  Size=0
+00003000: 92D50090  stw      r22,144(r21)
+00003004: 3EC00004  lis      r22,4
+00003008: 7EF7B078  andc     r23,r23,r22
+0000300C: 92F50094  stw      r23,148(r21)
+00003010: 90F5002C  stw      r7,44(r21)
+00003014: 91150030  stw      r8,48(r21)
+00003018: 91350034  stw      r9,52(r21)
+0000301C: 91550038  stw      r10,56(r21)
+00003020: 9175003C  stw      r11,60(r21)
+00003024: 91950040  stw      r12,64(r21)
+00003028: 91B50044  stw      r13,68(r21)
+0000302C: 91D50048  stw      r14,72(r21)
+00003030: 91F5004C  stw      r15,76(r21)
+00003034: 92150050  stw      r16,80(r21)
+00003038: 92350054  stw      r17,84(r21)
+0000303C: 92550058  stw      r18,88(r21)
+00003040: 9275005C  stw      r19,92(r21)
+00003044: 93150070  stw      r24,112(r21)
+00003048: 93350074  stw      r25,116(r21)
+0000304C: 93550078  stw      r26,120(r21)
+00003050: 9375007C  stw      r27,124(r21)
+00003054: 93950080  stw      r28,128(r21)
+00003058: 93B50084  stw      r29,132(r21)
+0000305C: 93D50088  stw      r30,136(r21)
+00003060: 93F5008C  stw      r31,140(r21)
+00003064: 7EE802A6  mflr     r23
+00003068: 72F83F00  andi.    r24,r23,0x3f00
+0000306C: 931500B0  stw      r24,176(r21)
+00003070: 3AC00000  li       r22,0
+00003074: 92D500BC  stw      r22,188(r21)
+00003078: 7ED243A6  mtsprg2  r22
+0000307C: 83170000  lwz      r24,0(r23)
+00003080: 82F70004  lwz      r23,4(r23)
+00003084: 7F1A03A6  mtsrr0   r24
+00003088: 7E9B03A6  mtsrr1   r20
+0000308C: 7EE803A6  mtlr     r23
+00003090: 7C0004AC  sync
+00003094: 4C00012C  isync
+00003098: 4C000064  rfi
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="int_return"  Size=0
+0000309C: 7FA000A6  mfmsr    r29
+000030A0: 38800000  li       r4,0
+000030A4: 60848000  ori      r4,r4,0x8000
+000030A8: 7FBD2078  andc     r29,r29,r4
+000030AC: 7C0004AC  sync
+000030B0: 4C00012C  isync
+000030B4: 7FA00124  mtmsr    r29
+000030B8: 7C0004AC  sync
+000030BC: 4C00012C  isync
+000030C0: 8041009C  lwz      r2,156(rsp)
+000030C4: 800100A0  lwz      r0,160(rsp)
+000030C8: 7C4903A6  mtctr    r2
+000030CC: 7C0803A6  mtlr     r0
+000030D0: 804100A4  lwz      r2,164(rsp)
+000030D4: 800100A8  lwz      r0,168(rsp)
+000030D8: 7C4103A6  mtxer    r2
+000030DC: 7C0FF120  mtcrf    0xff,r0
+000030E0: 8061001C  lwz      r3,28(rsp)
+000030E4: 80810020  lwz      r4,32(rsp)
+000030E8: 80A10024  lwz      r5,36(rsp)
+000030EC: 80C10028  lwz      r6,40(rsp)
+000030F0: 80E1002C  lwz      r7,44(rsp)
+000030F4: 81010030  lwz      r8,48(rsp)
+000030F8: 81210034  lwz      r9,52(rsp)
+000030FC: 81410038  lwz      r10,56(rsp)
+00003100: 8161003C  lwz      r11,60(rsp)
+00003104: 81810040  lwz      r12,64(rsp)
+00003108: 81A10044  lwz      r13,68(rsp)
+0000310C: 81C10048  lwz      r14,72(rsp)
+00003110: 81E1004C  lwz      r15,76(rsp)
+00003114: 82010050  lwz      r16,80(rsp)
+00003118: 82210054  lwz      r17,84(rsp)
+0000311C: 82410058  lwz      r18,88(rsp)
+00003120: 8261005C  lwz      r19,92(rsp)
+00003124: 82810060  lwz      r20,96(rsp)
+00003128: 82A10064  lwz      r21,100(rsp)
+0000312C: 82C10068  lwz      r22,104(rsp)
+00003130: 82E1006C  lwz      r23,108(rsp)
+00003134: 83010070  lwz      r24,112(rsp)
+00003138: 83210074  lwz      r25,116(rsp)
+0000313C: 83410078  lwz      r26,120(rsp)
+00003140: 8361007C  lwz      r27,124(rsp)
+00003144: 83810080  lwz      r28,128(rsp)
+00003148: 83A10084  lwz      r29,132(rsp)
+0000314C: 83C10088  lwz      r30,136(rsp)
+00003150: 83E1008C  lwz      r31,140(rsp)
+00003154: 80410090  lwz      r2,144(rsp)
+00003158: 80010094  lwz      r0,148(rsp)
+0000315C: 7C5A03A6  mtsrr0   r2
+00003160: 7C1B03A6  mtsrr1   r0
+00003164: 80010010  lwz      r0,16(rsp)
+00003168: 80410018  lwz      r2,24(rsp)
+0000316C: 80210014  lwz      rsp,20(rsp)
+00003170: 7C0004AC  sync
+00003174: 4C00012C  isync
+00003178: 4C000064  rfi
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="icache_enable"  Size=0
+0000317C: 7CB0FAA6  mfdbsr   r5
+00003180: 60A58800  ori      r5,r5,0x8800
+00003184: 3CC0FFFF  lis      r6,-1
+00003188: 60C6F7FF  ori      r6,r6,0xf7ff
+0000318C: 7CA63038  and      r6,r5,r6
+00003190: 7C0004AC  sync
+00003194: 7CB0FBA6  mtdbsr   r5
+00003198: 7CD0FBA6  mtdbsr   r6
+0000319C: 4C00012C  isync
+000031A0: 7C0004AC  sync
+000031A4: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="icache_disable"  Size=0
+000031A8: 7CB0FAA6  mfdbsr   r5
+000031AC: 3CC0FFFF  lis      r6,-1
+000031B0: 60C67FFF  ori      r6,r6,0x7fff
+000031B4: 7CA53038  and      r5,r5,r6
+000031B8: 7C0004AC  sync
+000031BC: 7CB0FBA6  mtdbsr   r5
+000031C0: 4C00012C  isync
+000031C4: 7C0004AC  sync
+000031C8: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="icache_status"  Size=0
+000031CC: 7C70FAA6  mfdbsr   r3
+000031D0: 54638BFE  srwi     r3,r3,15
+000031D4: 70630001  andi.    r3,r3,0x0001
+000031D8: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="dcache_enable"  Size=0
+000031DC: 7CB0FAA6  mfdbsr   r5
+000031E0: 60A54400  ori      r5,r5,0x4400
+000031E4: 7C9F42A6  mfpvr    r4
+000031E8: 7C838670  srawi    r3,r4,16
+000031EC: 2C03000C  cmpwi    r3,0x000c
+000031F0: 40820008  bne      *+8                     ; 0x000031F8
+000031F4: 60A50040  ori      r5,r5,0x0040
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="NotMax"  Size=0
+000031F8: 3CC0FFFF  lis      r6,-1
+000031FC: 60C6FBFF  ori      r6,r6,0xfbff
+00003200: 7CA63038  and      r6,r5,r6
+00003204: 7C0004AC  sync
+00003208: 7CB0FBA6  mtdbsr   r5
+0000320C: 7CD0FBA6  mtdbsr   r6
+00003210: 4C00012C  isync
+00003214: 7C0004AC  sync
+00003218: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="dcache_disable"  Size=0
+0000321C: 7CB0FAA6  mfdbsr   r5
+00003220: 3CC0FFFF  lis      r6,-1
+00003224: 60C6BFFF  ori      r6,r6,0xbfff
+00003228: 7CA53038  and      r5,r5,r6
+0000322C: 7C0004AC  sync
+00003230: 7CB0FBA6  mtdbsr   r5
+00003234: 4C00012C  isync
+00003238: 7C0004AC  sync
+0000323C: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="dcache_status"  Size=0
+00003240: 7C70FAA6  mfdbsr   r3
+00003244: 546393BE  srwi     r3,r3,14
+00003248: 70630001  andi.    r3,r3,0x0001
+0000324C: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="dc_read"  Size=0
+00003250: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="get_pvr"  Size=0
+00003254: 7C7F42A6  mfpvr    r3
+00003258: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="udelay"  Size=0
+0000325C: 1C832710  mulli    r4,r3,10000
+00003260: 38A00C35  li       r5,3125
+00003264: 7C842BD6  divw     r4,r4,r5
+00003268: 7CAD42E6  mftbu    r5
+0000326C: 7CCC42E6  mftb     r6
+00003270: 7CED42E6  mftbu    r7
+00003274: 7C053800  cmpw     r5,r7
+00003278: 4082FFF0  bne      *-16                    ; 0x00003268
+0000327C: 7D262014  addc     r9,r6,r4
+00003280: 7D050194  addze    r8,r5
+00003284: 7CAD42E6  mftbu    r5
+00003288: 7C054000  cmpw     r5,r8
+0000328C: 4180FFF8  blt      *-8                     ; 0x00003284
+00003290: 41810010  bgt      *+16                    ; 0x000032A0
+00003294: 7CCC42E6  mftb     r6
+00003298: 7C064800  cmpw     r6,r9
+0000329C: 4180FFE8  blt      *-24                    ; 0x00003284
+000032A0: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="relocate_code"  Size=0
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="clear_bss"  Size=0
+000032A4: 806E801C  lwz      r3,-32740(r14)
+000032A8: 808E8018  lwz      r4,-32744(r14)
+000032AC: 7C032040  cmplw    r3,r4
+000032B0: 41820018  beq      *+24                    ; 0x000032C8
+000032B4: 38000000  li       r0,0
+000032B8: 90030000  stw      r0,0(r3)
+000032BC: 38630004  addi     r3,r3,4
+000032C0: 7C032040  cmplw    r3,r4
+000032C4: 4082FFF4  bne      *-12                    ; 0x000032B8
+000032C8: 7D234B78  mr       r3,r9
+000032CC: 7D445378  mr       r4,r10
+000032D0: 48000001  bl       *+0                     ; 0x000032D0
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="get_endaddr"  Size=0
+000032D4: 806E8018  lwz      r3,-32744(r14)
+000032D8: 4E800020  blr
+
+Hunk:  Kind=HUNK_GLOBAL_CODE     Name="trap_init"  Size=0
+000032DC: 80EE8008  lwz      r7,-32760(r14)
+000032E0: 810E8010  lwz      r8,-32752(r14)
+000032E4: 54E904BE  clrlwi   r9,r7,18
+000032E8: 7C074040  cmplw    r7,r8
+000032EC: 4C800020  bgelr
+000032F0: 7C8802A6  mflr     r4
+000032F4: 80070000  lwz      r0,0(r7)
+000032F8: 90090000  stw      r0,0(r9)
+000032FC: 38E70004  addi     r7,r7,4
+00003300: 39290004  addi     r9,r9,4
+00003304: 7C074040  cmplw    r7,r8
+00003308: 4082FFEC  bne      *-20                    ; 0x000032F4
+0000330C: 38E00288  li       r7,648
+00003310: 39000600  li       r8,1536
+00003314: 48000041  bl       *+64                    ; 0x00003354
+00003318: 38E70100  addi     r7,r7,256
+0000331C: 7C074040  cmplw    r7,r8
+00003320: 4180FFF4  blt      *-12                    ; 0x00003314
+00003324: 38E0069C  li       r7,1692
+00003328: 4800002D  bl       *+44                    ; 0x00003354
+0000332C: 38E0078C  li       r7,1932
+00003330: 48000025  bl       *+36                    ; 0x00003354
+00003334: 38E00888  li       r7,2184
+00003338: 39002090  li       r8,8336
+0000333C: 48000019  bl       *+24                    ; 0x00003354
+00003340: 38E70100  addi     r7,r7,256
+00003344: 7C074040  cmplw    r7,r8
+00003348: 4180FFF4  blt      *-12                    ; 0x0000333C
+0000334C: 7C8803A6  mtlr     r4
+00003350: 4E800020  blr
+
+Hunk:  Kind=HUNK_LOCAL_CODE     Name="trap_reloc"  Size=0
+00003354: 80070000  lwz      r0,0(r7)
+00003358: 7C001A14  add      r0,r0,r3
+0000335C: 90070000  stw      r0,0(r7)
+00003360: 80070004  lwz      r0,4(r7)
+00003364: 7C001A14  add      r0,r0,r3
+00003368: 90070004  stw      r0,4(r7)
+0000336C: 4E800020  blr
+00003370: 0000B21C  dc.l     0x0000b21c              ; Invalid opcode '....'
+
+==> .data
+
+==> .bss
+
+==> .rela.got2
+    entry  offset   addend   type name(symbol id)
+    [   0] 00000000 00000000    1 _GOT2_TABLE_(74)
+    [   1] 00000004 00000000    1 _FIXUP_TABLE_(75)
+    [   2] 00000008 00000000    1 _start(76)
+    [   3] 0000000c 00000000    1 _start_of_vectors(77)
+    [   4] 00000010 00000000    1 _end_of_vectors(78)
+    [   5] 00000014 00000000    1 transfer_to_handler(79)
+    [   6] 00000018 00000000    1 _end(80)
+    [   7] 0000001c 00000000    1 .bss(34)
+
+==> .got2
+00000000: 00000000  00000000  00000000  00000000 '................'
+00000010: 00000000  00000000  00000000  00000000 '................'
diff --git a/mpc8240/traps.c b/mpc8240/traps.c
new file mode 100644 (file)
index 0000000..227b41d
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * linux/arch/ppc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include <ppcboot.h>
+#include <asm/processor.h>
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM     0x00400000
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+       int cnt = 0;
+       unsigned long i;
+
+       printf("Call backtrace: ");
+       while (sp) {
+               if ((uint)sp > END_OF_MEM)
+                       break;
+
+               i = sp[1];
+               if (cnt++ % 7 == 0)
+                       printf("\n");
+               printf("%08lX ", i);
+               if (cnt > 32) break;
+               sp = (unsigned long *)*sp;
+       }
+       printf("\n");
+}
+
+void show_regs(struct pt_regs * regs)
+{
+       int i;
+
+       printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
+              regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
+       printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+              regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+              regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+              regs->msr&MSR_IR ? 1 : 0,
+              regs->msr&MSR_DR ? 1 : 0);
+
+       printf("\n");
+       for (i = 0;  i < 32;  i++) {
+               if ((i % 8) == 0)
+               {
+                       printf("GPR%02d: ", i);
+               }
+
+               printf("%08lX ", regs->gpr[i]);
+               if ((i % 8) == 7)
+               {
+                       printf("\n");
+               }
+       }
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+       show_regs(regs);
+       print_backtrace((unsigned long *)regs->gpr[1]);
+       panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+       unsigned long fixup;
+
+       /* Probing PCI using config cycles cause this exception
+        * when a device is not present.  Catch it and return to
+        * the PCI exception handler.
+        */
+       if ((fixup = search_exception_table(regs->nip)) != 0) {
+               regs->nip = fixup;
+               return;
+       }
+
+       printf("Machine check in kernel mode.\n");
+       printf("Caused by (from msr): ");
+       printf("regs %p ",regs);
+       switch( regs->msr & 0x0000F000)
+       {
+       case (1<<12) :
+               printf("Machine check signal - probably due to mm fault\n"
+                       "with mmu off\n");
+               break;
+       case (1<<13) :
+               printf("Transfer error ack signal\n");
+               break;
+       case (1<<14) :
+               printf("Data parity signal\n");
+               break;
+       case (1<<15) :
+               printf("Address parity signal\n");
+               break;
+       default:
+               printf("Unknown values in msr\n");
+       }
+       show_regs(regs);
+       print_backtrace((unsigned long *)regs->gpr[1]);
+       panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+       show_regs(regs);
+       print_backtrace((unsigned long *)regs->gpr[1]);
+       panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+       show_regs(regs);
+       print_backtrace((unsigned long *)regs->gpr[1]);
+       panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+       show_regs(regs);
+       print_backtrace((unsigned long *)regs->gpr[1]);
+       panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+       printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+              regs->nip, regs->msr, regs->trap);
+       _exception(0, regs);
+}
+
+/* Probe an address by reading.  If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+       int     retval;
+
+       __asm__ __volatile__(                   \
+               "1:     lwz %0,0(%1)\n"         \
+               "       eieio\n"                \
+               "       li %0,0\n"              \
+               "2:\n"                          \
+               ".section .fixup,\"ax\"\n"      \
+               "3:     li %0,-1\n"             \
+               "       b 2b\n"                 \
+               ".section __ex_table,\"a\"\n"   \
+               "       .align 2\n"             \
+               "       .long 1b,3b\n"          \
+               ".text"                         \
+               : "=r" (retval) : "r"(addr));
+
+       return (retval);
+#endif
+       return 0;
+}
index a011d81edaa70e6ad5edc6dbb0ef3afd9372dfcc..14de409dd1ffb499db7490459dcd8650d749e860 100644 (file)
@@ -29,7 +29,8 @@ LIB   = lib$(CPU).a
 
 START  = start.o kgdb.o
 OBJS   = traps.o serial.o cpu.o cpu_init.o speed.o \
-         commproc.o interrupts.o scc.o i2c.o video.o wlkbd.o
+         commproc.o interrupts.o fec.o scc.o \
+         i2c.o video.o wlkbd.o status_led.o
 
 all:   .depend $(START) $(LIB)
 
index a38e10225bf8af238db0b94f86e2bfc9b950daa0..36de2e9f196a49cf74310b88f5350f4d4f5fcdb3 100644 (file)
@@ -26,7 +26,9 @@
 #include <net.h>
 #include <command.h>
 
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#define        ET_DEBUG
+
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET)
 
 #define BD_OFFSET 0x860 /* offset to begin of DPRAM + allocation for serial IF*/
 
 
 #define TX_BUF_CNT 2
 
-#define TOUT_LOOP 1000000
+#define TOUT_LOOP 100000
+
+#define PKT_MAXBUF_SIZE         1518
+#define PKT_MINBUF_SIZE         64
+#define PKT_MAXBLR_SIZE         1520
+
 
 /* static char rxbuf[PKTBUFSRX][ DBUF_LENGTH ]; */
 static char txbuf[TX_BUF_CNT][ DBUF_LENGTH ];
@@ -60,6 +67,8 @@ static RTXBD *rtx;
 int eth_send(volatile void *packet, int length)
 {
        int i, j=0;
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+       volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
 #if 0
        volatile char *in, *out;
 #endif
@@ -79,7 +88,8 @@ int eth_send(volatile void *packet, int length)
        while (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) j++;
 
 #ifdef ET_DEBUG
-       printf("cycles: %d    status: %x\n", j, rtx->txbd[txIdx].cbd_sc);
+       printf("%s[%d] %s: cycles: %d    status: %x\n",
+       __FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc);
 #endif
        i = (rtx->txbd[txIdx++].cbd_sc & BD_ENET_TX_STATS) /* return only status bits */;
 
@@ -87,23 +97,57 @@ int eth_send(volatile void *packet, int length)
        if (txIdx >= TX_BUF_CNT) txIdx = 0;
 #endif
 
-       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) j++;
-       if (j>=TOUT_LOOP) printf("TX not ready\n");
+       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+               udelay(1);
+               j++;
+       }
+       if (j>=TOUT_LOOP) {
+               printf("TX not ready\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_HB) printf("- No heartbeat\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_LC) printf("- Late collision\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_RL) printf("- Retrans limit\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_UN) printf("- Underrun\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_CSL) printf("- Carrier lost\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_DEF) printf("- Deferred\n");
+       }
        rtx->txbd[txIdx].cbd_bufaddr = (uint)packet;
        rtx->txbd[txIdx].cbd_datlen = length;
        rtx->txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |BD_ENET_TX_WRAP);
-       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) j++;
-       if (j>=TOUT_LOOP) printf("TX timeout\n");
+
+       /* Activate transmit Buffer Descriptor polling */
+       fecp->fec_x_des_active = 0x01000000;    /* Descriptor polling active    */
+
+       while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) {
+               udelay(1);
+               j++;
+       }
+       if (j>=TOUT_LOOP) {
+               printf("TX timeout\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_HB) printf("- No heartbeat\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_LC) printf("- Late collision\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_RL) printf("- Retrans limit\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_UN) printf("- Underrun\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_CSL) printf("- Carrier lost\n");
+if (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_DEF) printf("- Deferred\n");
+       }
 #ifdef ET_DEBUG
-       printf("cycles: %d    status: %x\n", j, rtx->txbd[txIdx].cbd_sc);
+       printf("%s[%d] %s: cycles: %d    status: %x\n",
+       __FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc);
 #endif
        i = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS) /* return only status bits */;
+
+printf("%s[%d] %s: return 0x%x\n",__FILE__,__LINE__,__FUNCTION__,i);
        return i;
 }
 
 int eth_rx(void)
 {
        int length;
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+       volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
+
+    /* Try to fill Buffer Descriptors */
+    fecp->fec_r_des_active = 0x01000000;       /* Descriptor polling active    */
 
    for (;;)
    {
@@ -115,14 +159,12 @@ int eth_rx(void)
 
        length = rtx->rxbd[rxIdx].cbd_datlen;
 
-       if (rtx->rxbd[rxIdx].cbd_sc & 0x003f)
-       {
+       if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) {
 #ifdef ET_DEBUG
-               printf("err: %x\n", rtx->rxbd[rxIdx].cbd_sc);
+               printf("%s[%d] %s: err: %x\n",
+               __FILE__,__LINE__,__FUNCTION__,rtx->rxbd[rxIdx].cbd_sc);
 #endif
-       }
-       else
-       {
+       } else {
                /* Pass the packet up to the protocol layers. */
                NetReceive(NetRxPackets[rxIdx], length - 4);
        }
@@ -135,338 +177,170 @@ int eth_rx(void)
        if ((rxIdx + 1) >= PKTBUFSRX) {
            rtx->rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
           rxIdx = 0;
-       }
-       else {
+       } else {
            rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
           rxIdx++;
        }
    }
+
+    /* Try to fill Buffer Descriptors */
+    fecp->fec_r_des_active = 0x01000000;       /* Descriptor polling active    */
+printf("%s[%d] %s: len=%d\n",__FILE__,__LINE__,__FUNCTION__,length);
    return length;
 }
 
 /**************************************************************
-  *
-  * FEC Ethernet Initialization Routine
-  *
-  *************************************************************/
+ *
+ * FEC Ethernet Initialization Routine
+ *
+ *************************************************************/
+
+#define        FEC_ECNTRL_PINMUX       0x00000004
+#define FEC_ECNTRL_ETHER_EN    0x00000002
+#define FEC_ECNTRL_RESET       0x00000001
+
+#define        FEC_RESET_DELAY         50
 
-int eth_init(bd_t *bis)
+int eth_init (bd_t * bd)
 {
 
-    int i;
-    volatile immap_t *immr = (immap_t *)CFG_IMMR;
-    volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
-
-    /* Whack a reset.
-     * A delay is required between a reset of the FEC block and
-     * initialization of other FEC registers because the reset takes
-     * some time to complete. If you don't delay, subsequent writes
-     * to FEC registers might get killed by the reset routinewhich is
-     * still in progress.
-     */
-    fecp->fec_ecntrl = 1;
-    udelay (20);
-
-    /* We use striclty polling mode only
-     */
-    fecp->fec_imask = 0;
-
-    /* Clear any outstanding interrupt.
-     */
-    fecp->fec_ievent = 0xffc0;
-
-    /* Reset all multicast.
-     */
-    fecp->fec_hash_table_high = 0;
-    fecp->fec_hash_table_low  = 0;
-
-    /* Set maximum receive buffer size.
-     */
-    fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
-    fecp->fec_r_hash = PKT_MAXBUF_SIZE;
-
-    /* Configure all of port D for MII.
-     */
-    immr->im_ioport.iop_pdpar = 0x1fff;
-
-    /* Bits moved from Rev. D onward */
-    if ((_get_IMMR() & 0xffff) < 0x0501) {
-       immr->im_ioport.iop_pddir = 0x1c58;     /* Pre rev. D */
-    } else {
-       immr->im_ioport.iop_pddir = 0x1fff;     /* Rev. D and later */
-    }
-
-    /* Set MII speed to 2.5 MHz
-     */
-    fecp->fec_mii_speed = fep->phy_speed =
-       ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e;
-
-    
-    rxIdx = 0;
-    txIdx = 0;
-
-    /* assign static pointer to BD area */
-    rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + BD_OFFSET);
-
-    /* Set receive and transmit descriptor base
-     */
-    fecp->fec_r_des_start = (unsigned int)(&rtx->rxbd[0]);
-    fecp->fec_x_des_start = (unsigned int)(&rtx->txbd[0]);
-
-
-#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD))
-    /* Configure port A pins for Txd and Rxd.
-    */
-    immr->im_ioport.iop_papar |=  (PA_ENET_RXD | PA_ENET_TXD);
-    immr->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD);
-    immr->im_ioport.iop_paodr &=                ~PA_ENET_TXD;
-#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD))
-    /* Configure port B pins for Txd and Rxd.
-    */
-    immr->im_cpm.cp_pbpar |=  (PB_ENET_RXD | PB_ENET_TXD);
-    immr->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD);
-    immr->im_cpm.cp_pbodr &=                ~PB_ENET_TXD;
-#else
-#error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined
-#endif
+       int i;
+       volatile immap_t *immr = (immap_t *) CFG_IMMR;
+       volatile fec_t *fecp = &(immr->im_cpm.cp_fec);
+
+printf ("Start FEC init\n");
+       /* Whack a reset.
+        * A delay is required between a reset of the FEC block and
+        * initialization of other FEC registers because the reset takes
+        * some time to complete. If you don't delay, subsequent writes
+        * to FEC registers might get killed by the reset routine which is
+        * still in progress.
+        */
+       fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET;
+       for (i = 0;
+            (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY);
+            ++i) {
+               udelay (1);
+       }
+       if (i == FEC_RESET_DELAY) {
+               printf ("FEC_RESET_DELAY timeout\n");
+               return 0;
+       }
+
+       /* We use strictly polling mode only
+        */
+       fecp->fec_imask = 0;
+
+       /* Clear any pending interrupt
+        */
+       fecp->fec_ievent = 0xffc0;
 
-#if defined(PC_ENET_LBK)
-    /* Configure port C pins to disable External Loopback
-     */
-    immr->im_ioport.iop_pcpar &= ~PC_ENET_LBK;
-    immr->im_ioport.iop_pcdir |=  PC_ENET_LBK;
-    immr->im_ioport.iop_pcso  &= ~PC_ENET_LBK;
-    immr->im_ioport.iop_pcdat &= ~PC_ENET_LBK; /* Disable Loopback */
-#endif /* PC_ENET_LBK */
-
-    /* Configure port C pins to enable CLSN and RENA.
-    */
-    immr->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA);
-    immr->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA);
-    immr->im_ioport.iop_pcso  |=  (PC_ENET_CLSN | PC_ENET_RENA);
-
-    /* Configure port A for TCLK and RCLK.
-    */
-    immr->im_ioport.iop_papar |=  (PA_ENET_TCLK | PA_ENET_RCLK);
-    immr->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK);
-
-    /*
-     * Configure Serial Interface clock routing -- see section 16.7.5.3
-     * First, clear all FEC bits to zero, then set the ones we want.
-     */
-
-    immr->im_cpm.cp_sicr &= ~SICR_ENET_MASK;
-    immr->im_cpm.cp_sicr |= SICR_ENET_CLKRT;
-
-
-    /*
-     * Initialize SDCR -- see section 16.9.23.7
-     * SDMA configuration register
-     */
-    immr->im_siu_conf.sc_sdcr = 0x01;
-
-
-    /*
-     * Setup FEC Ethernet Parameter RAM
-     */
-
-    pram_ptr->sen_genscc.scc_rfcr = 0x18;  /* Normal Operation and Mot byte ordering */
-    pram_ptr->sen_genscc.scc_tfcr = 0x18;  /* Mot byte ordering, Normal access */
-
-    pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH;      /* max. ET package len 1520 */
-
-
-    /*
-     * Setup Receiver Buffer Descriptors (13.14.24.18)
-     * Settings:
-     *     Empty, Wrap
-     */
-
-    for (i = 0; i < PKTBUFSRX; i++)
-    {
-      rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
-      rtx->rxbd[i].cbd_datlen = 0;                                 /* Reset */
-      rtx->rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
-    }
-
-    rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
-
-    /*
-     * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
-     * Settings:
-     *    Add PADs to Short FRAMES, Wrap, Last, Tx CRC
-     */
-
-    for (i = 0; i < TX_BUF_CNT; i++)
-    {
-      rtx->txbd[i].cbd_sc = (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
-      rtx->txbd[i].cbd_datlen = 0;                                 /* Reset */
-      rtx->txbd[i].cbd_bufaddr = (uint)&txbuf[i][0];
-    }
-
-    rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
-
-    /*
-     * Enter Command:  Initialize Rx Params for FEC
-     */
-
-    do {                               /* Spin until ready to issue command    */
-       __asm__ ("eieio");
-    } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
-    /* Issue command */
-    immr->im_cpm.cp_cpcr = ((CPM_CR_INIT_RX << 8) | (CPM_CR_ENET << 4) | CPM_CR_FLG);
-    do {                               /* Spin until command processed         */
-       __asm__ ("eieio");
-    } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
-
-    /*
-     * Ethernet Specific Parameter RAM
-     *     see table 13-16, pg. 660,
-     *     pg. 681 (example with suggested settings)
-     */
-
-    pram_ptr->sen_cpres  = ~(0x0);     /* Preset CRC */
-    pram_ptr->sen_cmask  = 0xdebb20e3; /* Constant Mask for CRC */
-    pram_ptr->sen_crcec  = 0x0;                /* Error Counter CRC (unused) */
-    pram_ptr->sen_alec   = 0x0;                /* Alignment Error Counter (unused) */
-    pram_ptr->sen_disfc  = 0x0;                /* Discard Frame Counter (unused) */
-    pram_ptr->sen_pads   = 0x8888;     /* Short Frame PAD Characters */
-
-    pram_ptr->sen_retlim = 15;         /* Retry Limit Threshold */
-    pram_ptr->sen_maxflr = 1518;       /* MAX Frame Length Register */
-    pram_ptr->sen_minflr = 64;         /* MIN Frame Length Register */
-
-    pram_ptr->sen_maxd1  = DBUF_LENGTH;        /* MAX DMA1 Length Register */
-    pram_ptr->sen_maxd2  = DBUF_LENGTH;        /* MAX DMA2 Length Register */
-
-    pram_ptr->sen_gaddr1 = 0x0;                /* Group Address Filter 1 (unused) */
-    pram_ptr->sen_gaddr2 = 0x0;                /* Group Address Filter 2 (unused) */
-    pram_ptr->sen_gaddr3 = 0x0;                /* Group Address Filter 3 (unused) */
-    pram_ptr->sen_gaddr4 = 0x0;                /* Group Address Filter 4 (unused) */
-
-#define ea bis->bi_enetaddr
-    pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4];
-    pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2];
-    pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0];
+       /* No need to set the IVEC register */
+
+       /* Set station address
+        */
+#define ea bd->bi_enetaddr
+       fecp->fec_addr_low   =  (ea[0] << 24) | (ea[1] << 16) |
+                               (ea[2] <<  8) | (ea[3]      ) ;
+       fecp->fec_addr_high  =  (ea[4] << 24) | (ea[5] << 16) ;
 #undef ea
 
-    pram_ptr->sen_pper   = 0x0;                /* Persistence (unused) */
-    pram_ptr->sen_iaddr1 = 0x0;                /* Individual Address Filter 1 (unused) */
-    pram_ptr->sen_iaddr2 = 0x0;                /* Individual Address Filter 2 (unused) */
-    pram_ptr->sen_iaddr3 = 0x0;                /* Individual Address Filter 3 (unused) */
-    pram_ptr->sen_iaddr4 = 0x0;                /* Individual Address Filter 4 (unused) */
-    pram_ptr->sen_taddrh = 0x0;                /* Tmp Address (MSB) (unused) */
-    pram_ptr->sen_taddrm = 0x0;                /* Tmp Address (unused) */
-    pram_ptr->sen_taddrl = 0x0;                /* Tmp Address (LSB) (unused) */
-
-    /*
-     * Enter Command:  Initialize Tx Params for FEC
-     */
-
-    do {                               /* Spin until ready to issue command    */
-       __asm__ ("eieio");
-    } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
-    /* Issue command */
-    immr->im_cpm.cp_cpcr = ((CPM_CR_INIT_TX << 8) | (CPM_CR_ENET << 4) | CPM_CR_FLG);
-    do {                               /* Spin until command processed         */
-       __asm__ ("eieio");
-    } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG);
-
-    /*
-     * Mask all Events in SCCM - we use polling mode
-     */
-    immr->im_cpm.cp_scc[SCC_ENET].scc_sccm = 0;
-
-    /*
-     * Clear Events in SCCE -- Clear bits by writing 1's
-     */
-
-    immr->im_cpm.cp_scc[SCC_ENET].scc_scce = ~(0x0);
-
-
-    /*
-     * Initialize GSMR High 32-Bits
-     * Settings:  Normal Mode
-     */
-
-    immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrh = 0;
-
-    /*
-     * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive
-     * Settings:
-     *     TCI = Invert
-     *     TPL =  48 bits
-     *     TPP = Repeating 10's
-     *     MODE = Ethernet
-     */
-
-    immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl = (        SCC_GSMRL_TCI    |      \
-                                               SCC_GSMRL_TPL_48 |      \
-                                               SCC_GSMRL_TPP_10 |      \
-                                               SCC_GSMRL_MODE_ENET);
-
-    /*
-     * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4
-     */
-
-    immr->im_cpm.cp_scc[SCC_ENET].scc_dsr = 0xd555;
-
-    /*
-     * Initialize the PSMR
-     * Settings:
-     *      CRC = 32-Bit CCITT
-     *      NIB = Begin searching for SFD 22 bits after RENA
-     *      BRO = Reject broadcast packets
-     *      PROMISCOUS = Catch all packets regardless of dest. MAC adress
-     */
-    immr->im_cpm.cp_scc[SCC_ENET].scc_pmsr = (SCC_PMSR_ENCRC | SCC_PMSR_NIB22
-                                     /* | SCC_PMSR_BRO | SCC_PMSR_PRO */);
-
-    /*
-     * Configure Ethernet TENA Signal
-     */
-
-#if (defined(PC_ENET_TENA) && !defined(PB_ENET_TENA))
-    immr->im_ioport.iop_pcpar |=  PC_ENET_TENA;
-    immr->im_ioport.iop_pcdir &= ~PC_ENET_TENA;
-#elif (defined(PB_ENET_TENA) && !defined(PC_ENET_TENA))
-    immr->im_cpm.cp_pbpar |= PB_ENET_TENA;
-    immr->im_cpm.cp_pbdir |= PB_ENET_TENA;
-#else
-#error Configuration Error: exactly ONE of PB_ENET_TENA, PC_ENET_TENA must be defined
-#endif
+       rxIdx = 0;
+       txIdx = 0;
+
+       rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + m8xx_cpm_dpbase_align(8));
+       /*
+        * Setup Receiver Buffer Descriptors (13.14.24.18)
+        * Settings:
+        *     Empty, Wrap
+        */
+       for (i = 0; i < PKTBUFSRX; i++) {
+               rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+               rtx->rxbd[i].cbd_datlen = 0;    /* Reset */
+               rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i];
+       }
+       rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+       /*
+        * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19)
+        * Settings:
+        *    Add PADs to Short FRAMES, Wrap, Last, Tx CRC
+        */
+       for (i = 0; i < TX_BUF_CNT; i++) {
+               rtx->txbd[i].cbd_sc =
+                               (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+               rtx->txbd[i].cbd_datlen = 0;    /* Reset */
+               rtx->txbd[i].cbd_bufaddr = (uint) & txbuf[i][0];
+       }
+       rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
 
-#if defined(CONFIG_FADS) && defined(CONFIG_MPC860T)
-    /*
-     * Port C is used to control the PHY,MC68160.
-     */
-    immr->im_ioport.iop_pcdir |=
-       (PC_ENET_ETHLOOP | PC_ENET_TPFLDL | PC_ENET_TPSQEL);
+       /* Clear multicast address hash table
+        */
+       fecp->fec_hash_table_high = 0;
+       fecp->fec_hash_table_low  = 0;
 
-    immr->im_ioport.iop_pcdat |= PC_ENET_TPFLDL;
-    immr->im_ioport.iop_pcdat &= ~(PC_ENET_ETHLOOP | PC_ENET_TPSQEL);
-    *((uint *) BCSR1) &= ~BCSR1_ETHEN;
-#endif /* FADS860T */
+       /* Set maximum receive buffer size.
+        */
+       fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
 
-#ifdef CONFIG_MBX
-    board_ether_init();
+       /* Set receive and transmit descriptor base
+        */
+       fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]);
+       fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]);
+
+       /* Set maximum frame length
+        */
+       fecp->fec_r_hash = PKT_MAXBUF_SIZE;
+
+       /* Enable MII mode
+        */
+#if 0  /* Full duplex mode */
+       fecp->fec_r_cntrl = 0x04;       /* MII enable */
+       fecp->fec_x_cntrl = 0x04;       /* FD enable */
+#else  /* Half duplex mode */
+       fecp->fec_r_cntrl = 0x06;       /* MII enable | No Rcv on Xmit */
+       fecp->fec_x_cntrl = 0x00;
 #endif
 
-    /*
-     * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive
-     */
+       /* Enable big endian and don't care about SDMA FC.
+        */
+       fecp->fec_fun_code = 0x78000000;
 
-    immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       /* Configure all of port D for MII.
+        */
+       immr->im_ioport.iop_pdpar = 0x1fff;
 
-    return 1;
+       /* Bits moved from Rev. D onward */
+       if ((get_immr (0) & 0xffff) < 0x0501) {
+               immr->im_ioport.iop_pddir = 0x1c58;     /* Pre rev. D */
+       } else {
+               immr->im_ioport.iop_pddir = 0x1fff;     /* Rev. D and later */
+       }
+
+       /* Set MII speed to 2.5 MHz
+        */
+       fecp->fec_mii_speed = ((bd->bi_busfreq * 1000000) / 2500000) & 0x7e;
+
+       rxIdx = 0;
+       txIdx = 0;
+
+       /* And last, enable the transmit and receive processing
+        */
+       fecp->fec_ecntrl = 6;
+       fecp->fec_r_des_active = 0x01000000;
+
+printf ("FEC init done\n");
+       return 1;
 }
 
 
 
 void eth_halt(void)
 {
+#if 0
     volatile immap_t *immr = (immap_t *)CFG_IMMR;
     immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+#endif
 }
 
 #if 0
diff --git a/mpc8xx/fec.h b/mpc8xx/fec.h
new file mode 100644 (file)
index 0000000..a49417c
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef        _FEC_H_
+#define        _FEC_H_
+
+
+#endif /* _FEC_H_ */
index ff6c32f9d30bc18df40c039b96c8a9d0214e025f..0d12cb9ee97878ad1a9a0912f52d504f44484042 100644 (file)
@@ -285,6 +285,9 @@ volatile ulong timestamp = 0;
 void timer_interrupt(struct pt_regs *regs)
 {
        volatile immap_t *immr = (immap_t *)CFG_IMMR;
+#ifdef CONFIG_STATUS_LED
+       extern void status_led_tick (ulong);
+#endif
 #if 0
        printf ("*** Timer Interrupt *** ");
 #endif
@@ -298,13 +301,15 @@ void timer_interrupt(struct pt_regs *regs)
 
        timestamp++;
 
+#ifdef CONFIG_STATUS_LED
+       status_led_tick (timestamp);
+#endif /* CONFIG_STATUS_LED */
+
 #if defined(CONFIG_WATCHDOG) || defined(CFG_CMA_LCD_HEARTBEAT)
 
        if ((timestamp % 1000) == 0) {
-
 #if defined(CFG_CMA_LCD_HEARTBEAT)
                extern void lcd_heartbeat(void);
-
                lcd_heartbeat();
 #endif /* CFG_CMA_LCD_HEARTBEAT */
 
index 374eb58482d14da875d1a2da2bc36bafee70bf04..e3b94d36c7a21622620d62dbb4896faefd2d9f7d 100644 (file)
@@ -45,7 +45,7 @@
 #include <net.h>
 #include <command.h>
 
-#if (CONFIG_COMMANDS & CFG_CMD_NET)
+#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(SCC_ENET)
 
 #if 0
 #define BD_OFFSET 0x860 /* offset to begin of DPRAM + allocation for serial IF*/
@@ -466,4 +466,4 @@ void restart(void)
 }
 #endif
 
-#endif /* CFG_CMD_NET */
+#endif /* CFG_CMD_NET, SCC_ENET */
diff --git a/mpc8xx/status_led.c b/mpc8xx/status_led.c
new file mode 100644 (file)
index 0000000..6b8d88a
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include "mpc8xx.h"
+#include <status_led.h>
+
+/*
+ * The purpose of this code is to signal the operational status of a
+ * target which usually boots over the network; while running in
+ * PCBoot, a status LED is blinking. As soon as a valid BOOTP reply
+ * message has been received, the LED is turned off. The Linux
+ * kernel, once it is running, will start blinking the LED again,
+ * with another frequency.
+ */
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_STATUS_LED
+
+static int status_led_state;
+static int status_led_init_done = 0;
+
+static void status_led_init (void)
+{
+    volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+    immr->STATUS_LED_PAR &= ~(STATUS_LED_BIT);
+#ifdef STATUS_LED_ODR
+    immr->STATUS_LED_ODR &= ~(STATUS_LED_BIT);
+#endif
+    immr->STATUS_LED_DAT &= ~(STATUS_LED_BIT); /* start with off */
+    immr->STATUS_LED_DIR |=   STATUS_LED_BIT ;
+    status_led_state     = STATUS_LED_BLINKING;
+    status_led_init_done  = 1;
+}
+
+void status_led_tick (ulong timestamp)
+{
+    volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+    if (status_led_state != STATUS_LED_BLINKING)
+       return;
+
+    if (!status_led_init_done)
+       status_led_init();
+
+    if ((timestamp % STATUS_LED_PERIOD) == 0) {
+       immr->STATUS_LED_DAT ^= STATUS_LED_BIT;
+    }
+}
+
+void status_led_set (int state)
+{
+    volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+    if (!status_led_init_done)
+       status_led_init();
+
+    switch (state) {
+    default:
+       return;
+    case STATUS_LED_BLINKING:
+       break;
+    case STATUS_LED_ON:
+       immr->STATUS_LED_DAT |= STATUS_LED_BIT;
+       break;
+    case STATUS_LED_OFF:
+       immr->STATUS_LED_DAT &= ~(STATUS_LED_BIT);
+       break;
+    }
+    status_led_state = state;
+}
+
+#endif /* CONFIG_STATUS_LED */
index 6e7f1aa826e15ecfa693a70acf9a9cc9180d45b2..7711c96c7e471175cf5a6ed975ecae061453699b 100644 (file)
@@ -14,6 +14,9 @@
 #include "net.h"
 #include "bootp.h"
 #include "tftp.h"
+#ifdef CONFIG_STATUS_LED
+#include <status_led.h>
+#endif
 
 #define        BOOTP_VENDOR_MAGIC      0x63825363      /* RFC1048 Magic Cookie         */
 
@@ -199,6 +202,9 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
        /*
         *      Got a good BOOTP reply.  Copy the data into our variables.
         */
+#ifdef CONFIG_STATUS_LED
+       status_led_set (STATUS_LED_OFF);
+#endif
        NetOurIP = bp->bp_yiaddr;
        NetServerIP = bp->bp_siaddr;
        NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
index d42b362abc1d7c7b21ffc6127650df83fc442e82..898c7c5a5caef665a693e960e8dff65244269b04 100644 (file)
@@ -324,8 +324,12 @@ void panic(const char *fmt, ...)
        va_list args;
        va_start(args, fmt);
        printf(fmt);
+       putc('\n');
        va_end(args);
-
-       /* Hang */
-       for(;;);
+#if 1
+       hang();
+#else
+       udelay (100000);        /* allow messages to go out */
+       do_reset (NULL, NULL, 0, 0, NULL);
+#endif
 }
index bb7f437696d5e74f00104627134398a794f17af3..a5aec1d3fb83e5a9988331bd9282a1373f15f381 100644 (file)
@@ -220,12 +220,12 @@ int eth_init (bd_t *bis)
   out32 (EMAC_M0, in32 (EMAC_M0) & ~EMAC_M0_SRST);
 
   speed = miiphy_speed();
-  printf("ENET Speed is %d Mbs... \n\r", (int)speed);
+  printf("ENET Speed is %d Mbs... \n", (int)speed);
   duplex = miiphy_duplex();
   if( duplex == HALF)
-    printf("HALF duplex connection\n\r");
+    printf("HALF duplex connection\n");
   else
-    printf("FULL duplex connection\n\r");
+    printf("FULL duplex connection\n");
 
   /* set the Mal configuration reg */
   mtdcr(malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT);
@@ -535,7 +535,7 @@ void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef,
               unsigned long mal_errr)
 {
   mtdcr(malesr, isr); /* clear interrupt */
-  printf ("MAL error occured.... ISR = %lx UIC = = %lx  MAL_DEF = %lx  MAL_ERR= %lx \n\r",
+  printf ("MAL error occured.... ISR = %lx UIC = = %lx  MAL_DEF = %lx  MAL_ERR= %lx \n",
           isr, uic, maldef, mal_errr);
 
 #if 0
@@ -556,7 +556,7 @@ void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef,
 +-----------------------------------------------------------------------------*/
 void emac_err (unsigned long isr)
 {
-  printf ("EMAC error occured.... ISR = %lx\n\r", isr);
+  printf ("EMAC error occured.... ISR = %lx\n", isr);
   out32(EMAC_ISR, isr);
 }
 
index 0f60337e565591e82e405a0aa8152a2af79d0b48..72a82961312048dc41f286e113be6210f39d5342 100644 (file)
@@ -65,10 +65,10 @@ void miiphy_dump(void)
     { 
       if(miiphy_read(i, &data))
         {
-          printf("read error for reg %lx\n\r",i);
+          printf("read error for reg %lx\n",i);
           return;
         }  
-      printf("Phy reg %lx ==> %4x\n\r", i, data); 
+      printf("Phy reg %lx ==> %4x\n", i, data); 
     
       /* jump to the next set of regs */
       if(i==0x07)
@@ -96,7 +96,7 @@ int miiphy_read(unsigned char reg, unsigned short * value)
     {
       udelay(7);
       if(i > 5)
-        { printf("read err 1\n\r");
+        { printf("read err 1\n");
         return -1;
         }
       i++;
@@ -117,14 +117,14 @@ int miiphy_read(unsigned char reg, unsigned short * value)
     {
       udelay(7);
       if(i > 5)
-        { printf("read err 2\n\r");
+        { printf("read err 2\n");
         return -1;
         }
       i++;
       sta_reg = in32(EMAC_STACR);
     }
   if ((sta_reg & EMAC_STACR_PHYE) !=0)
-    { printf("read err 3\n\r");
+    { printf("read err 3\n");
     printf("a2: read: EMAC_STACR=0x%0lx, i=%d\n", sta_reg, (int)i); /* test-only */
     return -1;
     }
@@ -191,7 +191,7 @@ int miiphy_speed()
   unsigned short bmcr = 0x0;
 
   if (miiphy_read(PHY_ANLPAR,&bmcr)) {
-    printf("phy speed1 read failed \n\r");
+    printf("phy speed1 read failed \n");
     miiphy_dump();
   }
 
@@ -211,7 +211,7 @@ int miiphy_duplex()
 
   if (miiphy_read(PHY_ANLPAR,&bmcr)) 
     {
-      printf("phy duplex read failed \n\r");
+      printf("phy duplex read failed \n");
       miiphy_dump();
     }
 
diff --git a/sandpoint/Makefile b/sandpoint/Makefile
new file mode 100644 (file)
index 0000000..6c8a6c2
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB    = lib$(BOARD).a
+
+OBJS   = $(BOARD).o flash.o board_init.o ns16550.o ns87308.o serial.o speed.o 
+#eepro100.o
+
+$(LIB):        .depend $(OBJS)
+       $(AR) crv $@ $^
+
+#########################################################################
+
+.depend:       Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+       
+sinclude .depend
+
+#########################################################################
diff --git a/sandpoint/board_init.c b/sandpoint/board_init.c
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sandpoint/config.mk b/sandpoint/config.mk
new file mode 100644 (file)
index 0000000..ccf6830
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# (C) Copyright 2000
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# Sandpoint boards
+#
+
+TEXT_BASE = 0xFE000000
+
+PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
diff --git a/sandpoint/flash.c b/sandpoint/flash.c
new file mode 100644 (file)
index 0000000..f2de593
--- /dev/null
@@ -0,0 +1,760 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <mpc8240.h>
+#include <asm/processor.h>
+#include <asm/pci_io.h>
+#include "w83c553f.h"
+
+flash_info_t    flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips    */
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+ulong flash_get_size (vu_long *addr, flash_info_t *info);
+
+int flash_write (uchar *, ulong, ulong);
+flash_info_t *addr2info (ulong);
+
+static int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+static int  flash_protect (int flag, ulong from, ulong to, flash_info_t *info);
+
+/*-----------------------------------------------------------------------
+ * Protection Flags:
+ */
+#define FLAG_PROTECT_SET    0x01
+#define FLAG_PROTECT_CLEAR  0x02
+
+/*flash command address offsets*/
+
+#define ADDR0           (0x555)
+#define ADDR1           (0x2AA)
+#define ADDR3           (0x001)
+
+#define FLASH_WORD_SIZE unsigned char
+
+/*-----------------------------------------------------------------------
+ */
+
+unsigned long flash_init (void)
+{
+    unsigned long size;
+    int i;
+    unsigned long base;
+    register unsigned long temp;
+
+    /* Init: no FLASHes known */
+    for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+        flash_info[i].flash_id = FLASH_UNKNOWN;
+    }
+
+    /* Static FLASH Bank configuration here - FIXME XXX */
+
+    /*Enable writes to Sandpoint flash*/
+    printf("setting flash write enable\n");
+    CONFIG_READ_BYTE(CFG_WINBOND_ISA_CFG_ADDR + WINBOND_CSCR, temp);
+    temp &= 0xDF; /* clear BIOSWP bit */
+    CONFIG_WRITE_BYTE(CFG_WINBOND_ISA_CFG_ADDR + WINBOND_CSCR, temp);
+
+    size = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+    if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+        printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+            size, size<<20);
+    }
+
+
+    flash_get_offsets (base, &flash_info[0]);
+
+    /* monitor protection ON by default */
+    (void)flash_protect(FLAG_PROTECT_SET,
+                base + size-CFG_MONITOR_LEN,
+                base + size - 1,
+                &flash_info[0]);
+
+
+    flash_info[1].flash_id = FLASH_UNKNOWN;
+    flash_info[1].sector_count = -1;
+
+    flash_info[0].size = size;
+
+    return (size);
+}
+
+/*-----------------------------------------------------------------------
+ * Check or set protection status for monitor sectors
+ *
+ * The monitor always occupies the _first_ part of the _first_ Flash bank.
+ */
+static int  flash_protect (int flag, ulong from, ulong to, flash_info_t *info)
+{
+    ulong b_end = info->start[0] + info->size - 1;  /* bank end address */
+    int rc    =  0;
+    int first = -1;
+    int last  = -1;
+    int i;
+
+    if (to < info->start[0]) {
+        return (0);
+    }
+
+    for (i=0; i<info->sector_count; ++i) {
+        ulong end;      /* last address in current sect */
+        short s_end;
+
+        s_end = info->sector_count - 1;
+
+        end = (i == s_end) ? b_end : info->start[i + 1] - 1;
+
+        if (from > end) {
+            continue;
+        }
+        if (to < info->start[i]) {
+            continue;
+        }
+
+        if (from == info->start[i]) {
+            first = i;
+            if (last < 0) {
+                last = s_end;
+            }
+        }
+        if (to  == end) {
+            last  = i;
+            if (first < 0) {
+                first = 0;
+            }
+        }
+    }
+
+    for (i=first; i<=last; ++i) {
+        if (flag & FLAG_PROTECT_CLEAR) {
+            info->protect[i] = 0;
+        } else if (flag & FLAG_PROTECT_SET) {
+            info->protect[i] = 1;
+        }
+        if (info->protect[i]) {
+            rc = 1;
+        }
+    }
+    return (rc);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+    int i;
+
+    /* set up sector start adress table */
+        if (info->flash_id & FLASH_MAN_SST)
+          {
+            for (i = 0; i < info->sector_count; i++)
+              info->start[i] = base + (i * 0x00010000);
+          }
+        else
+    if (info->flash_id & FLASH_BTYPE) {
+        /* set sector offsets for bottom boot block type    */
+        info->start[0] = base + 0x00000000;
+        info->start[1] = base + 0x00004000;
+        info->start[2] = base + 0x00006000;
+        info->start[3] = base + 0x00008000;
+        for (i = 4; i < info->sector_count; i++) {
+            info->start[i] = base + (i * 0x00010000) - 0x00030000;
+        }
+    } else {
+        /* set sector offsets for top boot block type       */
+        i = info->sector_count - 1;
+        info->start[i--] = base + info->size - 0x00004000;
+        info->start[i--] = base + info->size - 0x00006000;
+        info->start[i--] = base + info->size - 0x00008000;
+        for (; i >= 0; i--) {
+            info->start[i] = base + i * 0x00010000;
+        }
+    }
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+    int i;
+        int k;
+        int size;
+        int erased;
+        volatile unsigned long *flash;
+
+    if (info->flash_id == FLASH_UNKNOWN) {
+        printf ("missing or unknown FLASH type\n");
+        return;
+    }
+
+    switch (info->flash_id & FLASH_VENDMASK) {
+    case FLASH_MAN_AMD: printf ("AMD ");        break;
+    case FLASH_MAN_FUJ: printf ("FUJITSU ");        break;
+    case FLASH_MAN_SST: printf ("SST ");        break;
+    default:        printf ("Unknown Vendor "); break;
+    }
+
+    switch (info->flash_id & FLASH_TYPEMASK) {
+    case FLASH_AM400B:  printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+                break;
+    case FLASH_AM400T:  printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+                break;
+    case FLASH_AM800B:  printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+                break;
+    case FLASH_AM800T:  printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+                break;
+    case FLASH_AM160B:  printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+                break;
+    case FLASH_AM160T:  printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+                break;
+    case FLASH_AM320B:  printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+                break;
+    case FLASH_AM320T:  printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+                break;
+    case FLASH_SST800A: printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
+                break;
+    case FLASH_SST160A: printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
+                break;
+    default:        printf ("Unknown Chip Type\n");
+                break;
+    }
+
+    printf ("  Size: %ld MB in %d Sectors\n",
+        info->size >> 20, info->sector_count);
+
+    printf ("  Sector Start Addresses:");
+    for (i=0; i<info->sector_count; ++i) {
+                /*
+                 * Check if whole sector is erased
+                 */
+                if (i != (info->sector_count-1))
+                  size = info->start[i+1] - info->start[i];
+                else
+                  size = info->start[0] + info->size - info->start[i];
+                erased = 1;
+                flash = (volatile unsigned long *)info->start[i];
+                size = size >> 2;        /* divide by 4 for longword access */
+                for (k=0; k<size; k++)
+                  {
+                    if (*flash++ != 0xffffffff)
+                      {
+                        erased = 0;
+                        break;
+                      }
+                  }
+
+        if ((i % 5) == 0)
+            printf ("\n   ");
+#if 0 /* test-only */
+        printf (" %08lX%s",
+            info->start[i],
+            info->protect[i] ? " (RO)" : "     "
+#else
+        printf (" %08lX%s%s",
+            info->start[i],
+            erased ? " E" : "  ",
+            info->protect[i] ? "RO " : "   "
+#endif
+        );
+    }
+    printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+   short i;
+    FLASH_WORD_SIZE value;
+    ulong base = (ulong)addr;
+        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
+
+    printf("flash_get_size: \n");
+    /* Write auto select command: read Manufacturer ID */
+    eieio();
+    addr2[ADDR0] = (FLASH_WORD_SIZE)0xAA;
+    addr2[ADDR1] = (FLASH_WORD_SIZE)0x55;
+    addr2[ADDR0] = (FLASH_WORD_SIZE)0x90;
+    value = addr2[0];
+
+    switch (value) {
+    case (FLASH_WORD_SIZE)AMD_MANUFACT:
+        info->flash_id = FLASH_MAN_AMD;
+        break;
+    case (FLASH_WORD_SIZE)FUJ_MANUFACT:
+        info->flash_id = FLASH_MAN_FUJ;
+        break;
+    case (FLASH_WORD_SIZE)SST_MANUFACT:
+        info->flash_id = FLASH_MAN_SST;
+        break;
+    default:
+        info->flash_id = FLASH_UNKNOWN;
+        info->sector_count = 0;
+        info->size = 0;
+        return (0);         /* no or unknown flash  */
+    }
+    printf("recognised manufacturer");
+
+    value = addr2[ADDR3];          /* device ID        */
+        //        printf("\ndev_code=%x\n", value);
+
+    switch (value) {
+    case (FLASH_WORD_SIZE)AMD_ID_LV400T:
+        info->flash_id += FLASH_AM400T;
+        info->sector_count = 11;
+        info->size = 0x00080000;
+        break;              /* => 0.5 MB        */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV400B:
+        info->flash_id += FLASH_AM400B;
+        info->sector_count = 11;
+        info->size = 0x00080000;
+        break;              /* => 0.5 MB        */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV800T:
+        info->flash_id += FLASH_AM800T;
+        info->sector_count = 19;
+        info->size = 0x00100000;
+        break;              /* => 1 MB      */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV800B:
+        info->flash_id += FLASH_AM800B;
+        info->sector_count = 19;
+        info->size = 0x00100000;
+        break;              /* => 1 MB      */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV160T:
+        info->flash_id += FLASH_AM160T;
+        info->sector_count = 35;
+        info->size = 0x00200000;
+        break;              /* => 2 MB      */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV160B:
+        info->flash_id += FLASH_AM160B;
+        info->sector_count = 35;
+        info->size = 0x00200000;
+        break;              /* => 2 MB      */
+#if 0   /* enable when device IDs are available */
+    case (FLASH_WORD_SIZE)AMD_ID_LV320T:
+        info->flash_id += FLASH_AM320T;
+        info->sector_count = 67;
+        info->size = 0x00400000;
+        break;              /* => 4 MB      */
+
+    case (FLASH_WORD_SIZE)AMD_ID_LV320B:
+        info->flash_id += FLASH_AM320B;
+        info->sector_count = 67;
+        info->size = 0x00400000;
+        break;              /* => 4 MB      */
+#endif
+    case (FLASH_WORD_SIZE)SST_ID_xF800A:
+        info->flash_id += FLASH_SST800A;
+        info->sector_count = 16;
+        info->size = 0x00100000;
+        break;              /* => 1 MB      */
+
+    case (FLASH_WORD_SIZE)SST_ID_xF160A:
+        info->flash_id += FLASH_SST160A;
+        info->sector_count = 32;
+        info->size = 0x00200000;
+        break;              /* => 2 MB      */
+
+    case (FLASH_WORD_SIZE)AMD_ID_F040B:
+        info->flash_id += FLASH_AM040B;
+        info->sector_count = 8;
+        info->size = 0x00080000;
+        break;              /* => 0.5 MB      */
+
+    default:
+        info->flash_id = FLASH_UNKNOWN;
+        return (0);         /* => no or unknown flash */
+
+    }
+
+    printf("flash id %lx; sector count %x, size %lx\n", info->flash_id,info->sector_count,info->size);
+    /* set up sector start adress table */
+        if (info->flash_id & FLASH_MAN_SST)
+          {
+            for (i = 0; i < info->sector_count; i++)
+              info->start[i] = base + (i * 0x00010000);
+          }
+        else
+    if (info->flash_id & FLASH_BTYPE) {
+        /* set sector offsets for bottom boot block type    */
+        info->start[0] = base + 0x00000000;
+        info->start[1] = base + 0x00004000;
+        info->start[2] = base + 0x00006000;
+        info->start[3] = base + 0x00008000;
+        for (i = 4; i < info->sector_count; i++) {
+            info->start[i] = base + (i * 0x00010000) - 0x00030000;
+        }
+    } else {
+        /* set sector offsets for top boot block type       */
+        i = info->sector_count - 1;
+        info->start[i--] = base + info->size - 0x00004000;
+        info->start[i--] = base + info->size - 0x00006000;
+        info->start[i--] = base + info->size - 0x00008000;
+        for (; i >= 0; i--) {
+            info->start[i] = base + i * 0x00010000;
+        }
+    }
+
+    /* check for protected sectors */
+    for (i = 0; i < info->sector_count; i++) {
+        /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+        /* D0 = 1 if protected */
+        addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
+                if (info->flash_id & FLASH_MAN_SST)
+                  info->protect[i] = 0;
+                else
+                  info->protect[i] = addr2[2] & 1;
+    }
+
+    /*
+     * Prevent writes to uninitialized FLASH.
+     */
+    if (info->flash_id != FLASH_UNKNOWN) {
+       addr2 = (FLASH_WORD_SIZE *)info->start[0];
+        *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
+    }
+
+    return (info->size);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+
+void    flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+    volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
+    int flag, prot, sect, l_sect;
+    ulong start, now, last;
+
+    if ((s_first < 0) || (s_first > s_last)) {
+        if (info->flash_id == FLASH_UNKNOWN) {
+            printf ("- missing\n");
+        } else {
+            printf ("- no sectors to erase\n");
+        }
+        return;
+    }
+
+    if ((info->flash_id == FLASH_UNKNOWN) ||
+        (info->flash_id > FLASH_AMD_COMP)) {
+        printf ("Can't erase unknown flash type - aborted\n");
+        return;
+    }
+
+    prot = 0;
+    for (sect=s_first; sect<=s_last; ++sect) {
+        if (info->protect[sect]) {
+            prot++;
+        }
+    }
+
+    if (prot) {
+        printf ("- Warning: %d protected sectors will not be erased!\n",
+            prot);
+    } else {
+        printf ("\n");
+    }
+
+    l_sect = -1;
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+    addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+    addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
+    addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+    addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+
+    /* Start erase on unprotected sectors */
+    for (sect = s_first; sect<=s_last; sect++) {
+        if (info->protect[sect] == 0) { /* not protected */
+            addr = (FLASH_WORD_SIZE *)(info->start[sect]);
+                        if (info->flash_id & FLASH_MAN_SST)
+                          {
+                            addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+                            addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+                            addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
+                            addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+                            addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+                            addr[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
+                            udelay(30000);  /* wait 30 ms */
+                          }
+                        else
+                          addr[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
+            l_sect = sect;
+        }
+    }
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+        enable_interrupts();
+
+    /* wait at least 80us - let's wait 1 ms */
+    udelay (1000);
+
+    /*
+     * We wait for the last triggered sector
+     */
+    if (l_sect < 0)
+        goto DONE;
+
+    start = get_timer (0);
+    last  = start;
+    addr = (FLASH_WORD_SIZE *)(info->start[l_sect]);
+    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
+        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+            printf ("Timeout\n");
+            return;
+        }
+        /* show that we're waiting */
+        if ((now - last) > 1000) {  /* every second */
+            serial_putc ('.');
+            last = now;
+        }
+    }
+
+DONE:
+    /* reset to read mode */
+    addr = (FLASH_WORD_SIZE *)info->start[0];
+    addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
+
+    printf (" done\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+flash_info_t *addr2info (ulong addr)
+{
+    flash_info_t *info;
+    int i;
+
+    for (i=0, info=&flash_info[0]; i<CFG_MAX_FLASH_BANKS; ++i, ++info) {
+        if ((addr >= info->start[0]) &&
+            (addr <= (info->start[0] + info->size - 1)) ) {
+            return (info);
+        }
+    }
+
+    return (NULL);
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash.
+ * Make sure all target addresses are within Flash bounds,
+ * and no protected sectors are hit.
+ * Returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ * 4 - target range includes protected sectors
+ * 8 - target address not in Flash memory
+ */
+int flash_write (uchar *src, ulong addr, ulong cnt)
+{
+    int i;
+    ulong         end        = addr + cnt - 1;
+    flash_info_t *info_first = addr2info (addr);
+    flash_info_t *info_last  = addr2info (end );
+    flash_info_t *info;
+
+    if (cnt == 0) {
+        return (0);
+    }
+
+    if (!info_first || !info_last) {
+        return (8);
+    }
+
+    for (info = info_first; info <= info_last; ++info) {
+        ulong b_end = info->start[0] + info->size;  /* bank end addr */
+        short s_end = info->sector_count - 1;
+        for (i=0; i<info->sector_count; ++i) {
+            ulong e_addr = (i == s_end) ? b_end : info->start[i + 1];
+
+            if ((end >= info->start[i]) && (addr < e_addr) &&
+                (info->protect[i] != 0) ) {
+                return (4);
+            }
+        }
+    }
+
+    /* finally write data to flash */
+    for (info = info_first; info <= info_last && cnt>0; ++info) {
+        ulong len;
+
+        len = info->start[0] + info->size - addr;
+        if (len > cnt)
+            len = cnt;
+        if ((i = write_buff(info, src, addr, len)) != 0) {
+            return (i);
+        }
+        cnt  -= len;
+        addr += len;
+        src  += len;
+    }
+    return (0);
+}
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+static int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    ulong cp, wp, data;
+    int i, l, rc;
+
+    wp = (addr & ~3);   /* get lower word aligned address */
+
+    /*
+     * handle unaligned start bytes
+     */
+    if ((l = addr - wp) != 0) {
+        data = 0;
+        for (i=0, cp=wp; i<l; ++i, ++cp) {
+            data = (data << 8) | (*(uchar *)cp);
+        }
+        for (; i<4 && cnt>0; ++i) {
+            data = (data << 8) | *src++;
+            --cnt;
+            ++cp;
+        }
+        for (; cnt==0 && i<4; ++i, ++cp) {
+            data = (data << 8) | (*(uchar *)cp);
+        }
+
+        if ((rc = write_word(info, wp, data)) != 0) {
+            return (rc);
+        }
+        wp += 4;
+    }
+
+    /*
+     * handle word aligned part
+     */
+    while (cnt >= 4) {
+        data = 0;
+        for (i=0; i<4; ++i) {
+            data = (data << 8) | *src++;
+        }
+        if ((rc = write_word(info, wp, data)) != 0) {
+            return (rc);
+        }
+        wp  += 4;
+        cnt -= 4;
+    }
+
+    if (cnt == 0) {
+        return (0);
+    }
+
+    /*
+     * handle unaligned tail bytes
+     */
+    data = 0;
+    for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+        data = (data << 8) | *src++;
+        --cnt;
+    }
+    for (; i<4; ++i, ++cp) {
+        data = (data << 8) | (*(uchar *)cp);
+    }
+
+    return (write_word(info, wp, data));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+        volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]);
+        volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest;
+        volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
+    ulong start;
+    int flag;
+        int i;
+
+    /* Check if Flash is (sufficiently) erased */
+    if ((*((volatile FLASH_WORD_SIZE *)dest) &
+             (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
+        return (2);
+    }
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+        for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
+          {
+            addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+            addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+            addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0;
+
+            dest2[i] = data2[i];
+
+            /* re-enable interrupts if necessary */
+            if (flag)
+              enable_interrupts();
+
+            /* data polling for D7 */
+            start = get_timer (0);
+            while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) !=
+                   (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
+              if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+                return (1);
+              }
+            }
+          }
+
+    return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/sandpoint/interrupts.c b/sandpoint/interrupts.c
new file mode 100644 (file)
index 0000000..8a3e8b1
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <mpc8240.h>
+#include <asm/processor.h>
+
+
+/****************************************************************************/
+
+static __inline__ unsigned long get_msr(void)
+{
+    unsigned long msr;
+
+    asm volatile("mfmsr %0" : "=r" (msr) :);
+    return msr;
+}
+
+static __inline__ void set_msr(unsigned long msr)
+{
+    asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+static __inline__ unsigned long get_dec(void)
+{
+    unsigned long val;
+
+    asm volatile("mfdec %0" : "=r" (val) :);
+    return val;
+}
+
+
+static __inline__ void set_dec(unsigned long val)
+{
+    asm volatile("mtdec %0" : : "r" (val));
+}
+
+
+void enable_interrupts (void)
+{
+    set_msr (get_msr() | MSR_EE);
+}
+
+/* returns flag if MSR_EE was set before */
+int disable_interrupts (void)
+{
+    ulong msr = get_msr();
+    set_msr (msr & ~MSR_EE);
+    return ((msr & MSR_EE) != 0);
+}
+
+/****************************************************************************/
+
+void
+interrupt_init (bd_t *bd)
+{
+
+    set_msr (get_msr() | MSR_EE);
+}
+
+/****************************************************************************/
+
+/*
+ * Handle external interrupts
+ */
+void external_interrupt(struct pt_regs *regs)
+{
+
+}
+
+/****************************************************************************/
+
+/*
+ * blank int handlers.
+ */
+
+void
+irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+}
+
+void
+irq_free_handler(int vec)
+{
+
+}
+
+/*TODO: some handlers for winbond and 87308 interrupts
+ and what about generic pci inteerupts?
+ vga?
+ */
+
+volatile ulong timestamp = 0;
+
+void timer_interrupt(struct pt_regs *regs)
+{
+        timestamp++;
+}
+
+void reset_timer (void)
+{
+    timestamp = 0;
+}
+
+ulong get_timer (ulong base)
+{
+    return (timestamp - base);
+}
+
+void set_timer (ulong t)
+{
+    timestamp = t;
+}
diff --git a/sandpoint/interrupts.h b/sandpoint/interrupts.h
new file mode 100644 (file)
index 0000000..316d04c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _INTERRUPTS_H_
+#define _INTERRUPTS_H_
+
+void irq_install_handler(int vec, interrupt_handler_t *handler, void *arg);
+
+void irq_free_handler(int vec);
+
+#endif
diff --git a/sandpoint/ns16550.c b/sandpoint/ns16550.c
new file mode 100644 (file)
index 0000000..1fb9779
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * COM1 NS16550 support
+ * originally from linux source (arch/ppc/boot/ns16550.c)
+ * modified to use CFG_ISA_MEM and new defines
+ */
+
+#include <config.h>
+#include "ns16550.h"
+
+typedef struct NS16550 *NS16550_t;
+
+const NS16550_t COM_PORTS[] = { (NS16550_t) (CFG_ISA_IO + COM1),
+    (NS16550_t) (CFG_ISA_IO + COM2) };
+
+volatile struct NS16550 *
+NS16550_init(int chan, int baud_divisor)
+{
+ volatile struct NS16550 *com_port;
+ com_port = (struct NS16550 *) COM_PORTS[chan];
+ com_port->ier = 0x00;
+ com_port->lcr = LCR_BKSE;              /* Access baud rate */
+ com_port->dll = baud_divisor & 0xff;   /* 9600 baud */
+ com_port->dlm = (baud_divisor >> 8) & 0xff;
+ com_port->lcr = LCR_8N1;               /* 8 data, 1 stop, no parity */
+ com_port->mcr = MCR_DTR | MCR_RTS;     /* RTS/DTR */
+ com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR;                  /* Clear & enable FIFOs */
+ return (com_port);
+}
+
+void
+NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor)
+{
+ com_port->ier = 0x00;
+ com_port->lcr = LCR_BKSE;              /* Access baud rate */
+ com_port->dll = baud_divisor & 0xff;   /* 9600 baud */
+ com_port->dlm = (baud_divisor >> 8) & 0xff;
+ com_port->lcr = LCR_8N1;               /* 8 data, 1 stop, no parity */
+ com_port->mcr = MCR_DTR | MCR_RTS;     /* RTS/DTR */
+ com_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR;                  /* Clear & enable FIFOs */
+}
+
+void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
+{
+ while ((com_port->lsr & LSR_THRE) == 0) ;
+ com_port->thr = c;
+}
+
+unsigned char
+NS16550_getc(volatile struct NS16550 *com_port)
+{
+ while ((com_port->lsr & LSR_DR) == 0) ;
+ return (com_port->rbr);
+}
+
+int NS16550_tstc(volatile struct NS16550 *com_port)
+{
+ return ((com_port->lsr & LSR_DR) != 0);
+}
+
+
+
diff --git a/sandpoint/ns16550.h b/sandpoint/ns16550.h
new file mode 100644 (file)
index 0000000..3a28d9d
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * NS16550 Serial Port
+ * originally from linux source (arch/ppc/boot/ns16550.h)
+ * modified slightly to
+ * have addresses as offsets from CFG_ISA_BASE
+ * added a few more definitions
+ * added prototypes for ns16550.c
+ * reduced no of com ports to 2
+ * modifications (c) Rob Taylor, Flying Pig Systems. 2000.
+ */
+
+
+struct NS16550
+ {
+  unsigned char rbr;  /* 0 */
+  unsigned char ier;  /* 1 */
+  unsigned char fcr;  /* 2 */
+  unsigned char lcr;  /* 3 */
+  unsigned char mcr;  /* 4 */
+  unsigned char lsr;  /* 5 */
+  unsigned char msr;  /* 6 */
+  unsigned char scr;  /* 7 */
+ };
+
+#define thr rbr
+#define iir fcr
+#define dll rbr
+#define dlm ier
+
+#define FCR_FIFO_EN     0x01    /*fifo enable*/
+#define FCR_RXSR        0x02    /*reciever soft reset*/
+#define FCR_TXSR        0x04    /*transmitter soft reset*/
+
+
+#define MCR_DTR         0x01
+#define MCR_RTS         0x02
+#define MCR_DMA_EN      0x04
+#define MCR_TX_DFR      0x08
+
+
+#define LCR_WLS_MSK 0x03    /* character length slect mask*/
+#define LCR_WLS_5   0x00    /* 5 bit character length */
+#define LCR_WLS_6   0x01    /* 6 bit character length */
+#define LCR_WLS_7   0x02    /* 7 bit character length */
+#define LCR_WLS_8   0x03    /* 8 bit character length */
+#define LCR_STB     0x04    /* Number of stop Bits, off = 1, on = 1.5 or 2) */
+#define LCR_PEN     0x08    /* Parity eneble*/
+#define LCR_EPS     0x10    /* Even Parity Select*/
+#define LCR_STKP    0x20    /* Stick Parity*/
+#define LCR_SBRK    0x40    /* Set Break*/
+#define LCR_BKSE    0x80    /* Bank select enable*/
+
+#define LSR_DR      0x01    /* Data ready */
+#define LSR_OE      0x02    /* Overrun */
+#define LSR_PE      0x04    /* Parity error */
+#define LSR_FE      0x08    /* Framing error */
+#define LSR_BI      0x10    /* Break */
+#define LSR_THRE    0x20    /* Xmit holding register empty */
+#define LSR_TEMT    0x40    /* Xmitter empty */
+#define LSR_ERR     0x80    /* Error */
+
+/* useful defaults for LCR*/
+#define LCR_8N1     0x03
+
+
+#define COM1 0x03F8
+#define COM2 0x02F8
+
+volatile struct NS16550 * NS16550_init(int chan, int baud_divisor);
+void NS16550_putc(volatile struct NS16550 *com_port, unsigned char c);
+unsigned char NS16550_getc(volatile struct NS16550 *com_port);
+int NS16550_tstc(volatile struct NS16550 *com_port);
+void NS16550_reinit(volatile struct NS16550 *com_port, int baud_divisor);
+
diff --git a/sandpoint/ns87308.c b/sandpoint/ns87308.c
new file mode 100644 (file)
index 0000000..ad00a46
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+
+#include <mpc8240.h>
+#include "ns87308.h"
+#include "ns16550.h"   /*to configure the 87308's internal 16550's*/
+#include <asm/mc146818rtc.h>  /* to configure 87308's RTC*/
+
+void initialise_ns87308 (void)
+{
+    PNP_SET_DEVICE_BASE(LDEV_UART1, COM1);
+    PNP_SET_DEVICE_BASE(LDEV_UART2, COM2);
+
+    PNP_SET_DEVICE_BASE(LDEV_RTC_APC, RTC_PORT(0));
+    PNP_ACTIVATE_DEVICE(LDEV_POWRMAN);
+
+    /* set up the NVRAM access registers
+    NVRAM's controlled by the configurable CS line from the 87308*/
+
+    PNP_PGCS_CSLINE_BASE(0, 0x76);
+    PNP_PGCS_CSLINE_CONF(0, 0x30);
+    PNP_PGCS_CSLINE_BASE(1, 0x75);
+    PNP_PGCS_CSLINE_CONF(1, 0x30);
+    PNP_PGCS_CSLINE_BASE(2, 0x74);
+    PNP_PGCS_CSLINE_CONF(2, 0x30);
+}
+/*
+void write_pnp_config(unsigned char index, unsigned char data)
+{
+    unsigned char *io_index = (unsigned char *) IO_INDEX;
+    unsigned char *io_data = (unsigned char *) IO_DATA;
+    *io_index = index;
+    *io_data = data;
+}
+
+void pnp_set_device(unsigned char dev)
+{
+    write_pnp_config(LOGICAL_DEVICE, dev);
+}
+*/
diff --git a/sandpoint/ns87308.h b/sandpoint/ns87308.h
new file mode 100644 (file)
index 0000000..14b9f5c
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _NS87308_H_
+#define _NS87308_H_
+
+#include <asm/pci_io.h>
+
+/* Note: I couldn't find a full data sheet for the ns87308, but the ns87307 seems to be pretty
+   functionally- (and pin-) equivalent to the 87308, but the 308 has better ir support. */
+
+/*PNP config registers:
+ * these depend on the stated of BADDR1 and BADDR0 on startup
+ * so there's three versions here with the last two digits indicating
+ * for which configuration their valid
+ * the 1st of the two digits indicates the state of BADDR1
+ * the 2st of the two digits indicates the state of BADDR0
+ */
+
+
+#define IO_INDEX_OFFSET_0x 0x0279  /* full PnP isa Mode */
+#define IO_INDEX_OFFSET_10 0x015C  /* PnP motherboard mode */
+#define IO_INDEX_OFFSET_11 0x002E  /* PnP motherboard mode */
+#define IO_DATA_OFFSET_0x  0x0A79  /* full PnP isa Mode */
+#define IO_DATA_OFFSET_10  0x015D  /* PnP motherboard mode */
+#define IO_DATA_OFFSET_11  0x002F  /* PnP motherboard mode */
+
+#if defined(CFG_NS87308_BADDR_0x)
+#define IO_INDEX (CFG_ISA_IO + IO_INDEX_OFFSET_0x)
+#define IO_DATA  (CFG_ISA_IO + IO_DATA_OFFSET_0x)
+#elif defined(CFG_NS87308_BADDR_10)
+#define IO_INDEX (CFG_ISA_IO + IO_INDEX_OFFSET_10)
+#define IO_DATA  (CFG_ISA_IO + IO_DATA_OFFSET_10)
+#elif defined(CFG_NS87308_BADDR_11)
+#define IO_INDEX (CFG_ISA_IO + IO_INDEX_OFFSET_11)
+#define IO_DATA  (CFG_ISA_IO + IO_DATA_OFFSET_11)
+#endif
+
+/* PnP register definitions */
+
+#define SET_RD_DATA_PORT    0x00
+#define SERIAL_ISOLATION    0x01
+#define CONFIG_CONTROL      0x02
+#define WAKE_CSN            0x03
+#define RES_DATA            0x04
+#define STATUS              0x05
+#define SET_CSN             0x06
+#define LOGICAL_DEVICE      0x07
+/*vendor defined values */
+#define SID_REG             0x20
+#define SUPOERIO_CONF1      0x21
+#define SUPOERIO_CONF2      0x21
+#define PGCS_INDEX          0x22
+#define PGCS_DATA           0x22
+
+/* values above 30 are different for each logical device
+   but I can't be arsed to enter them all. the ones here
+   are pretty consistent between all logical devices
+   feel free to correct the situation if you want.. ;)
+   */
+#define ACTIVATE            0x30
+#define ACTIVATE_OFF        0x00
+#define ACTIVATE_ON         0x01
+
+#define BASE_ADDR_HIGH      0x60
+#define BASE_ADDR_LOW       0x61
+
+/* the logical devices*/
+#define LDEV_KBC1           0x00   /* 2 devices for keyboard and mouse controller*/
+#define LDEV_KBC2           0x01
+#define LDEV_RTC_APC        0x02  /*Real Time Clock and Advanced Power Control*/
+#define LDEV_FDC            0x03   /*floppy disk controller*/
+#define LDEV_PARP           0x04   /*Parallel port*/
+#define LDEV_UART1          0x05
+#define LDEV_UART2          0x06
+#define LDEV_GPIO           0x07    /*Gennerla Purpose IO and chip select output signals*/
+#define LDEV_POWRMAN        0x08    /*Power Managment*/
+
+/*some functions and macro's for doing configuration */
+
+static inline void write_pnp_config(unsigned char index, unsigned char data)
+{
+    pci_writeb(index,IO_INDEX);
+    pci_writeb(data, IO_DATA);
+}
+
+static inline void pnp_set_device(unsigned char dev)
+{
+    write_pnp_config(LOGICAL_DEVICE, dev);
+}
+
+
+/*void write_pnp_config(unsigned char index, unsigned char data);
+void pnp_set_device(unsigned char dev);
+*/
+
+#define PNP_SET_DEVICE_BASE(dev,base) \
+   pnp_set_device(dev); \
+   write_pnp_config(ACTIVATE, ACTIVATE_OFF); \
+   write_pnp_config(BASE_ADDR_HIGH, ((base) >> 8) & 0xff ); \
+   write_pnp_config(BASE_ADDR_LOW, (base) &0xff); \
+   write_pnp_config(ACTIVATE, ACTIVATE_ON);
+
+#define PNP_ACTIVATE_DEVICE(dev) \
+   pnp_set_device(dev); \
+   write_pnp_config(ACTIVATE, ACTIVATE_ON);
+
+#define PNP_DEACTIVATE_DEVICE(dev) \
+   pnp_set_device(dev); \
+   write_pnp_config(ACTIVATE, ACTIVATE_OFF);
+
+
+static inline void write_pgcs_config(unsigned char index, unsigned char data)
+{
+    write_pnp_config(PGCS_INDEX, index);
+    write_pnp_config(PGCS_DATA, data);
+}
+
+/* these macrose configure the 3 CS lines
+   on the sandpoint board these controll NVRAM
+   CS0 is connected to NVRAMCS
+   CS1 is connected to NVRAMAS0
+   CS2 is connected to NVRAMAS1
+   */
+#define PGCS_CS_ASSERT_ON_WRITE 0x10
+#define PGCS_CS_ASSERT_ON_READ  0x20
+
+#define PNP_PGCS_CSLINE_BASE(cs, base) \
+  write_pgcs_config((cs) << 2, ((base) >> 8) & 0xff ); \
+  write_pgcs_config(((cs) << 2) + 1, (base) & 0xff );
+
+#define PNP_PGCS_CSLINE_CONF(cs, conf) \
+  write_pgcs_config(((cs) << 2) + 2, (conf) );
+
+
+/* The following sections are for 87308 extensions to the standard compoents it emulates */
+
+/* extensions to 16550*/
+
+#define MCR_MDSL_MSK    0xe0 /*mode select mask*/
+#define MCR_MDSL_UART   0x00 /*uart, default*/
+#define MCR_MDSL_SHRPIR 0x02 /*Sharp IR*/
+#define MCR_MDSL_SIR    0x03 /*SIR*/
+#define MCR_MDSL_CIR    0x06 /*Consumer IR*/
+
+#define FCR_TXFTH0      0x10    /* these bits control threshod of data level in fifo */
+#define FCR_TXFTH1      0x20    /* for interrupt trigger */
+
+
+#endif /*_NS87308_H_*/
diff --git a/sandpoint/ppcboot.lds b/sandpoint/ppcboot.lds
new file mode 100644 (file)
index 0000000..9754ffa
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems Ltd. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+
+MEMORY {
+       ram  (!rx) : org = 0x00000000 , LENGTH = 8M
+       code (!rx) : org = 0x00002000 , LENGTH = (4M - 0x2000)
+       rom   (rx) : org = 0xfe000000 , LENGTH = (0x100000000 - 0xfe000000)
+}
+
+SECTIONS
+{
+  _f_init = .;
+  PROVIDE(_f_init = .);
+  _f_init_rom = .;
+  PROVIDE(_f_init_rom = .);
+  
+  .init : { 
+      mpc8240/start.o  (.text)
+      *(.init)
+  } > ram
+  _init_size = SIZEOF(.init);
+  PROVIDE(_init_size = SIZEOF(.init));
+  
+  ENTRY(_start)
+
+/*  _ftext = .;
+  _ftext_rom = .;
+  _text_size = SIZEOF(.text);
+ */ 
+  .text : { 
+      *(.text)
+      *(.got1)
+      } > ram
+  .rodata : { *(.rodata) } > ram
+  .dtors : { *(.dtors) } > ram
+  .data : { *(.data) } > ram
+  .sdata : { *(.sdata) } > ram
+  .sdata2 : { *(.sdata2) 
+      *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+    } > ram
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+  
+  .sbss : { *(.sbss) } > ram
+  .sbss2 : { *(.sbss2) } > ram
+  .bss : { *(.bss) } > ram
+  .debug : { *(.debug) } > ram
+  .line : { *(.line) } > ram
+  .symtab : { *(.symtab) } > ram
+  .shrstrtab : { *(.shstrtab) } > ram
+  .strtab : { *(.strtab) } > ram
+ /* .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  } > ram
+  */
+   __start___ex_table = .;
+    __ex_table : { *(__ex_table) } > ram
+    __stop___ex_table = .;
+
+
+  .ppcenv      :
+  {
+    common/environment.o (.ppcenv)
+  } > ram
+
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/sandpoint/ppcboot.lds.mw.debug b/sandpoint/ppcboot.lds.mw.debug
new file mode 100644 (file)
index 0000000..9754ffa
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems Ltd. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+
+MEMORY {
+       ram  (!rx) : org = 0x00000000 , LENGTH = 8M
+       code (!rx) : org = 0x00002000 , LENGTH = (4M - 0x2000)
+       rom   (rx) : org = 0xfe000000 , LENGTH = (0x100000000 - 0xfe000000)
+}
+
+SECTIONS
+{
+  _f_init = .;
+  PROVIDE(_f_init = .);
+  _f_init_rom = .;
+  PROVIDE(_f_init_rom = .);
+  
+  .init : { 
+      mpc8240/start.o  (.text)
+      *(.init)
+  } > ram
+  _init_size = SIZEOF(.init);
+  PROVIDE(_init_size = SIZEOF(.init));
+  
+  ENTRY(_start)
+
+/*  _ftext = .;
+  _ftext_rom = .;
+  _text_size = SIZEOF(.text);
+ */ 
+  .text : { 
+      *(.text)
+      *(.got1)
+      } > ram
+  .rodata : { *(.rodata) } > ram
+  .dtors : { *(.dtors) } > ram
+  .data : { *(.data) } > ram
+  .sdata : { *(.sdata) } > ram
+  .sdata2 : { *(.sdata2) 
+      *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+    } > ram
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+  
+  .sbss : { *(.sbss) } > ram
+  .sbss2 : { *(.sbss2) } > ram
+  .bss : { *(.bss) } > ram
+  .debug : { *(.debug) } > ram
+  .line : { *(.line) } > ram
+  .symtab : { *(.symtab) } > ram
+  .shrstrtab : { *(.shstrtab) } > ram
+  .strtab : { *(.strtab) } > ram
+ /* .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  } > ram
+  */
+   __start___ex_table = .;
+    __ex_table : { *(__ex_table) } > ram
+    __stop___ex_table = .;
+
+
+  .ppcenv      :
+  {
+    common/environment.o (.ppcenv)
+  } > ram
+
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/sandpoint/sandpoint.c b/sandpoint/sandpoint.c
new file mode 100644 (file)
index 0000000..b1a3fb9
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+
+int checkboard (void)
+{
+    printf("Sandpoint ");
+    /*TODO: Check processor type*/
+    printf("8240 Unity ##Test not implemented yet##\n");
+    return 0;
+}
+
+int checkflash (void)
+{
+    /* TODO: XXX XXX XXX */
+    printf ("8 MB ## Test not implemented yet ##\n");
+
+    return (0);
+}
+
+long int dram_size (int board_type)
+{
+    /* No actual initialisation to do - done when setting up PICRs MCCRs ME/SARs etc
+     * in cpu_init.c - done there to keep init sequence same as Dink. May be able to move some of
+     * it here and refine the configuration defines to be more high-level, but I haven't had time
+     * to investigate that yet
+     */
+     #if defined(CFG_MEM_TEST)
+
+     register unsigned long reg;
+
+     //write each mem addr with it's address
+     for (reg = CFG_MEM_TEST_START; reg < CGF_MEM_TEST_END; reg+=4
+         *reg = reg;
+
+     for (reg = CFG_MEM_TEST_START; reg < CGF_MEM_TEST_END; reg+=4
+     {
+         if (*reg != reg)
+           return -1;
+     }
+     #endif
+
+     //TODO: calculate amount of dram..for now just return MEMTEST_END
+     return CFG_MEMTEST_END;
+
+}
+
+long int initdram(int board_type)
+{
+return dram_size(board_type);
+}
+
+
+
+/*temporarlyily here: to be removed:*/
+
+
+int eth_init(bd_t *bis)
+{
+  /* Initialize the device  */
+  return 0;
+}
+
+int eth_send(volatile void *packet, int length)
+{
+  /* Send a packet */
+  return 0;
+}
+
+int eth_rx(void)
+{
+  /* Check for received packets */
+  return 0;
+}
+
+void eth_halt(void)
+{
+  /* stop ethernet     */
+}
diff --git a/sandpoint/serial.c b/sandpoint/serial.c
new file mode 100644 (file)
index 0000000..ec7afa0
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "ns16550.h"
+
+void initialise_ns87308(void);
+
+/*
+ * Minimal serial functions needed to use one87308's UARTs
+ * as serial console interface.
+ */
+
+volatile struct NS16550 *console;
+
+void
+serial_init (unsigned long dummy, int baudrate)
+{
+    int clock_divisor = 115200/baudrate;
+    initialise_ns87308();
+    console = NS16550_init(0, clock_divisor);
+}
+
+void
+serial_putc(const char c)
+{
+    NS16550_putc(console, c);
+}
+
+void
+serial_puts (const char *s)
+{
+    while (*s) {
+        serial_putc (*s++);
+    }
+}
+
+
+int
+serial_getc(void)
+{
+    return NS16550_getc(console);
+}
+
+int
+serial_tstc(void)
+{
+    return NS16550_tstc(console);
+}
+
+void
+serial_setbrg (unsigned long dummy, int baudrate)
+{
+   int clock_divisor = 115200/baudrate;
+   NS16550_reinit(console, clock_divisor);
+}
diff --git a/sandpoint/serial.h b/sandpoint/serial.h
new file mode 100644 (file)
index 0000000..94ab81e
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
diff --git a/sandpoint/speed.c b/sandpoint/speed.c
new file mode 100644 (file)
index 0000000..c44297c
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <mpc8240.h>
+#include <asm/processor.h>
+#include "speed.h"
+
+/*use UART2 to measure bus speed*/
+#include "ns16550.h"
+
+
+/* Access functions for the Machine State Register */
+static __inline__ unsigned long get_msr(void)
+{
+    unsigned long msr;
+
+    asm volatile("mfmsr %0" : "=r" (msr) :);
+    return msr;
+}
+
+static __inline__ void set_msr(unsigned long msr)
+{
+    asm volatile("mtmsr %0" : : "r" (msr));
+}
+
+/* ------------------------------------------------------------------------- */
+
+ulong get_bus_freq (ulong ignore)
+{
+    /* measure the bus frequency using UART2 */
+    /* 1st initilise it to run at 9600
+       it takes approx 10*(1/9600) us to sens an 8N1 character at 9600bps
+       but due to chrystal inaccuracies on sandpoint we use 1145us */
+
+    int count=0, start, end;
+    int i;
+    volatile struct NS16550 *uart2;
+
+    uart2=NS16550_init(1,115200/9600);
+
+
+    for (i =0; i< 10 ; i++)
+    {
+       NS16550_putc(uart2,0); /*send NUL*/
+       start=mfspr(DEC);
+       NS16550_putc(uart2,0); /*send NUL*/
+       end=mfspr(DEC);
+       count +=(start-end);
+    }
+
+    count /=10; /*average number of decrements per char send*/
+    count *=4;  /*1 decrement per 4 bus cycles*/
+
+    /*time taken to do count cycles = 1145 us
+      therefore number of cycles per second is (1/(1145*10-6))*count
+      */
+    return (1000000/1145)*count;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Measure CPU clock speed
+ */
+
+/*table to convert pllratio to actual processor clock scaling factor (*10)*/
+/* if you are using a a different processor with your sandpoint,
+   have a look at pmc.c in the dink source for values, or
+   figure it out from the hardware book*/
+
+#ifdef CONFIG_MPC8240
+short pllratio_to_factor[] = {
+    00, 00, 00, 10, 20, 20, 25, 00, 00, 00, 00, 00, 00, 00, 00, 00,
+    00, 00, 00, 10, 00, 00, 00, 45, 30, 00, 40, 00, 00, 00, 35, 00,
+};
+#endif
+
+ulong get_gclk_freq (void)
+{
+   uint hid1;
+   hid1=mfspr(HID1);
+   #ifdef CONFIG_MPC8240
+   hid1=(hid1 >> (32-5)) & 0x1f; /* 5 bits for PLL ration on 8240*/
+   #else
+   hid1=(hid1 >> (32-4)) & 0xf; /* 4 bits on everythings else*/
+   #endif
+
+   return (pllratio_to_factor[hid1] * get_bus_freq(0))/10;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
diff --git a/sandpoint/speed.h b/sandpoint/speed.h
new file mode 100644 (file)
index 0000000..204f7ec
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*-----------------------------------------------------------------------
+ * Timer value for timer 2, ICLK = 10
+ * 
+ * SPEED_FCOUNT2 =  GCLK / (16 * (TIMER_TMR_PS + 1))
+ * SPEED_TMR3_PS = (GCLK / (16 * SPEED_FCOUNT3)) - 1 
+ *
+ * SPEED_FCOUNT2       timer 2 counting frequency
+ * GCLK                        CPU clock
+ * SPEED_TMR2_PS       prescaler
+ */
+#define SPEED_TMR2_PS          (250 - 1)       /* divide by 250        */
+
+/*-----------------------------------------------------------------------
+ * Timer value for PIT
+ * 
+ * PIT_TIME = SPEED_PITC / PITRTCLK
+ * PITRTCLK = 8192 
+ */
+#define SPEED_PITC     (82 << 16)      /* start counting from 82       */
+
+/*
+ * The new value for PTA is calculated from
+ *
+ *     PTA = (gclk * Trefresh) / (2 ^ (2 * DFBRG) * PTP * NCS)
+ * 
+ * gclk                CPU clock (not bus clock !) 
+ * Trefresh    Refresh cycle * 4 (four word bursts used)
+ * DFBRG       For normal mode (no clock reduction) always 0
+ * PTP         Prescaler (already adjusted for no. of banks and 4K / 8K refresh)
+ * NCS         Number of SDRAM banks (chip selects) on this UPM.
+ */
diff --git a/sandpoint/w83c553f.c b/sandpoint/w83c553f.c
new file mode 100644 (file)
index 0000000..aac06e1
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "w83c553f.h"
diff --git a/sandpoint/w83c553f.h b/sandpoint/w83c553f.h
new file mode 100644 (file)
index 0000000..79fe669
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems. robt@flyingpig.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+ /* winbond access routines and defines*/
+
+/* from the winbond data sheet -
+ The W83C553F SIO controller with PCI arbiter is a multi-function PCI device.
+ Function 0 is the ISA bridge, and Function 1 is the bus master IDE controller.
+*/
+
+/*ISA bridge configuration space*/
+
+#define WINBOND_PCICONTR  0x40  /*pci control reg*/
+#define WINBOND_SGBAR     0x41  /*scatter/gather base address reg*/
+#define WINBOND_LBCR      0x42  /*Line Buffer Control reg*/
+#define WINBOND_IDEIRCR   0x43  /*IDE Interrupt Routing Control  Reg*/
+#define WINBOND_PCIIRCR   0x44  /*PCI Interrupt Routing Control Reg*/
+#define WINBOND_BTBAR     0x46  /*BIOS Timer Base Address Register*/
+#define WINBOND_IPADCR    0x48  /*ISA to PCI Address Decoder Control Register*/
+#define WINBOND_IRADCR    0x49  /*ISA ROM Address Decoder Control Register*/
+#define WINBOND_IPMHSAR   0x4a  /*ISA to PCI Memory Hole STart Address Register*/
+#define WINBOND_IPMHSR    0x4b  /*ISA to PCI Memory Hols Size Register*/
+#define WINBOND_CDR       0x4c  /*Clock Divisor Register*/
+#define WINBOND_CSCR      0x4d  /*Chip Select Control Register*/
+#define WINBOND_ATSCR     0x4e  /*AT System Control register*/
+#define WINBOND_ATBCR     0x4f  /*AT Bus ControL Register*/
+#define WINBOND_IRQBEE0R  0x60  /*IRQ Break Event Enable 0 Register*/
+#define WINBOND_IRQBEE1R  0x61  /*IRQ Break Event Enable 1 Register*/
+#define WINBOND_ABEER     0x62  /*Additional Break Event Enable Register*/
+#define WINBOND_DMABEER   0x63  /*DMA Break Event Enable Register*/
+
+
index 68e68ac91cba32b11463233f2732f2067e2d5f97..670d3cadd2b53c2027ed8e32f2d8720aa65a5779 100644 (file)
@@ -35,6 +35,10 @@ CFLAGS     = $(CPPFLAGS)
 CC        = $(HOSTCC)
 MAKEDEPEND = makedepend
 
+ifeq ($(OSTYPE),cygwin)
+all:
+.depend:
+else
 all:   $(BINS)
 
 gdbsend:       gdbsend.o error.o remote.o serial.o
@@ -60,3 +64,5 @@ distclean:    clean
 -include .depend
 
 #########################################################################
+
+endif  # cygwin
index d736c65b3d98afe9f3e3ad8ff4b64d6096308969..5e33c0a76120d6fe0ab57ef3953a77ff5d7709ed 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+
+/*nicked from gcc..*/
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
 #include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc.  */
+#endif /* not GNU C.  */
+extern "C" {
+    void* alloca(size_t);
+}
+#endif /* alloca not defined.  */
+
+
 #include "serial.h"
 #include "error.h"
 #include "remote.h"
index b153d0de57d534cd2dd1b4eb48670cc8860bf317..330ae02ecfc043fadf9dec8606eeb6f748090fd3 100644 (file)
@@ -59,6 +59,7 @@
 #include <string.h>
 #include <elf.h>
 #include <unistd.h>
+#include <errno.h>
 
 extern int errno;
 
index 9c1a2f3f490164a4102753f6e413fff3ad7efa5e..5bf890220561185242910c461bdaed1d8c486c77 100644 (file)
@@ -4,8 +4,8 @@
  * Wolfgang Denk, wd@denx.de
  * All rights reserved.
  *     
- * $Date: 2000/10/25 10:46:51 $
- * $Revision: 1.9 $
+ * $Date: 2000/11/16 20:16:58 $
+ * $Revision: 1.10 $
  */
 
 #include <errno.h>
 
 extern int errno;
 
+#ifndef MAP_FAILED
+#define MAP_FAILED -1
+#endif
+
 char *cmdname;
 
 extern unsigned long crc32 (unsigned long crc, const char *buf, unsigned int len);
@@ -309,7 +313,7 @@ NXTARG:             ;
 
        if (opt_type == IH_TYPE_MULTI) {
                char *file = datafile;
-               ulong size;
+               unsigned long size;
 
                for (;;) {
                        char *sep = NULL;
@@ -515,7 +519,9 @@ print_header (image_header_t *hdr)
 
        if (hdr->ih_type == IH_TYPE_MULTI) {
                int i;
-               ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t));
+               unsigned long *len_ptr = (unsigned long *) (
+                                       (unsigned long)hdr + sizeof(image_header_t)
+                               );
 
                printf ("Contents:\n");
                for (i=0; *len_ptr; ++i, ++len_ptr) {