]> www.infradead.org Git - users/rw/ppcboot.git/commitdiff
* Added bedbug (http://www.mindspring.com/~wlp/bedbug.html) embedded
authorwdenk <wdenk>
Fri, 1 Jun 2001 23:57:50 +0000 (23:57 +0000)
committerwdenk <wdenk>
Fri, 1 Jun 2001 23:57:50 +0000 (23:57 +0000)
  disasssembler/debugger/...
  Patch by Bill Pitts: 08 May 2001

* Added TQM8260 Configuration

* Patch for ERIC configuration and embedded flash environment
  by Swen Anderson: 30 May 2001

* Fixed some DHCP problems

48 files changed:
CHANGELOG
CREDITS
MAKEALL
Makefile
board/eric/flash.c
board/tqm8260/Makefile [new file with mode: 0644]
board/tqm8260/config.mk [new file with mode: 0644]
board/tqm8260/flash.c [new file with mode: 0644]
board/tqm8260/ppcboot.lds [new file with mode: 0644]
board/tqm8260/tqm8260.c [new file with mode: 0644]
common/Makefile
common/bedbug.c [new file with mode: 0644]
common/board.c
common/cmd_bedbug.c [new file with mode: 0644]
common/cmd_i2c.c
common/cmd_nvedit.c
common/command.c
cpu/mpc8260/Makefile
cpu/mpc8260/ether_fcc.c
cpu/mpc8260/ether_scc.c
cpu/mpc8260/soft_i2c.c [new file with mode: 0644]
cpu/mpc8260/start.S
cpu/ppc4xx/Makefile
cpu/ppc4xx/bedbug_405.c [new file with mode: 0644]
cpu/ppc4xx/start.S
cpu/ppc4xx/traps.c
doc/README.bedbug [new file with mode: 0644]
include/bedbug/bedbug.h [new file with mode: 0644]
include/bedbug/elf.h [new file with mode: 0644]
include/bedbug/ppc.h [new file with mode: 0644]
include/bedbug/regs.h [new file with mode: 0644]
include/bedbug/tables.h [new file with mode: 0644]
include/cmd_bedbug.h [new file with mode: 0644]
include/cmd_confdefs.h
include/config_ERIC.h
include/config_LANTEC.h
include/config_TQM823L.h
include/config_TQM8260.h [new file with mode: 0644]
include/config_WALNUT405.h
include/config_hymod.h
include/config_lwmon.h
include/flash.h
include/i2c.h
include/ppc_asm.tmpl
include/ppcboot.h
include/version.h
net/bootp.c
net/net.c

index d391e0a085dc39e78b7b2c45ba6832c83a4009c5..5403252d8597a6a8ee6fd59afe125f35a8fbf685 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -56,6 +56,12 @@ To do:
 Modifications for 1.0.0:
 ======================================================================
 
+* Added bedbug (http://www.mindspring.com/~wlp/bedbug.html) embedded
+  disasssembler/debugger/...
+  Patch by Bill Pitts: 08 May 2001
+
+* Added TQM8260 Configuration
+
 * Patch for ERIC configuration and embedded flash environment
   by Swen Anderson: 30 May 2001
 
diff --git a/CREDITS b/CREDITS
index 076b1d05aac41a9fe76f45fda16e32ca5df9c010..f803ac81596e3e66f4d9209e91a3a116d7de4efa 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -104,6 +104,10 @@ N: Frank Morauf
 E: frank.morauf@salzbrenner.com
 D: Support for Embedded Planet RPX Super Board
 
+N: Bill Pitts
+D: wlp@mindspring.com
+D: BedBug embedded debugger code
+
 N: Stefan Roese
 E: stefan.roese@esd-electronics.com
 D: IBM PPC401/403/405GP Support; Windows environment support
diff --git a/MAKEALL b/MAKEALL
index ef98a3d7b23335ff5aa013fa2df482f7d875f753..ed07af7c79502baba6492fd7fb00af4a493e02c0 100755 (executable)
--- a/MAKEALL
+++ b/MAKEALL
@@ -53,6 +53,7 @@ LIST="$LIST   \
 #########################################################################
 
 LIST="$LIST    \
+       TQM8260                         \
        hymod                           \
        cogent_mpc8260                  \
        rsdproto                        \
index d8bcc95295efea565d6fd469cbd5d4f97ac1b0a4..14fcb0b0e4f7d0287370c46c5b654a3b23a47d20 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -422,6 +422,14 @@ RPXsuper_config:   unconfig
        echo "CPU   = mpc8260"  >>config.mk ;   \
        echo "#include <config_$(@:_config=).h>" >config.h
 
+TQM8260_config: unconfig
+       @echo "Configuring for $(@:_config=) Board..." ; \
+       cd include ;                            \
+       echo "ARCH  = ppc"      > config.mk ;   \
+       echo "BOARD = tqm8260"  >>config.mk ;   \
+       echo "CPU   = mpc8260"  >>config.mk ;   \
+       echo "#include <config_$(@:_config=).h>" >config.h
+
 #########################################################################
 
 clean:
index deae93a84f2dcd8e85944879be88c49f640725cf..f688a29fd453df418923decee6cf8acfc4745beb 100644 (file)
@@ -81,10 +81,17 @@ unsigned long flash_init (void)
            flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
              
            /* Monitor protection ON by default */
+#if 0      /* sand: */
            (void)flash_protect(FLAG_PROTECT_SET, 
                                FLASH_BASE0_PRELIM-CFG_MONITOR_LEN+size_b0,
                                FLASH_BASE0_PRELIM-1+size_b0,
                                &flash_info[0]);
+#else
+           (void)flash_protect(FLAG_PROTECT_SET,
+                               CFG_MONITOR_BASE,
+                               CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+                               &flash_info[0]);
+#endif
            size_b1 = 0 ;
            flash_info[0].size = size_b0;
          }
@@ -123,11 +130,18 @@ unsigned long flash_init (void)
            flash_get_offsets (base_b0, &flash_info[0]);
            
            /* monitor protection ON by default */
-           (void)flash_protect(FLAG_PROTECT_SET,
-                               base_b0+size_b0-CFG_MONITOR_LEN+size_b1,
-                               base_b0+size_b0-1+size_b1,
+#if 0      /* sand: */
+           (void)flash_protect(FLAG_PROTECT_SET, 
+                               FLASH_BASE0_PRELIM-CFG_MONITOR_LEN+size_b0,
+                               FLASH_BASE0_PRELIM-1+size_b0,
                                &flash_info[0]);
-           
+#else
+           (void)flash_protect(FLAG_PROTECT_SET,
+                               CFG_MONITOR_BASE,
+                               CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+                               &flash_info[0]);
+#endif
+
            if (size_b1) {
              /* Re-do sizing to get full correct info */
              size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b1, &flash_info[1]);
diff --git a/board/tqm8260/Makefile b/board/tqm8260/Makefile
new file mode 100644 (file)
index 0000000..35b8428
--- /dev/null
@@ -0,0 +1,40 @@
+#
+# (C) Copyright 2001
+# 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
+
+$(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/board/tqm8260/config.mk b/board/tqm8260/config.mk
new file mode 100644 (file)
index 0000000..673f622
--- /dev/null
@@ -0,0 +1,34 @@
+#
+# (C) Copyright 2001
+# 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
+#
+
+#
+# TQM8260 boards
+#
+
+# This should be equal to the CFG_FLASH_BASE define in config_TQM8260.h
+# for the "final" configuration, with ppcboot in flash, or the address
+# in RAM where ppcboot is loaded at for debugging.
+#
+TEXT_BASE = 0x40000000
+
+PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)
diff --git a/board/tqm8260/flash.c b/board/tqm8260/flash.c
new file mode 100644 (file)
index 0000000..50c2559
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for AM29LV640U devices
+ *
+ *--------------------------------------------------------------------
+ * 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>
+
+#define V_ULONG(a)     (*(volatile unsigned long *)( a ))
+#define V_BYTE(a)      (*(volatile unsigned char *)( a ))
+
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+/*-----------------------------------------------------------------------
+ */
+void flash_reset(void)
+{
+  if( flash_info[0].flash_id != FLASH_UNKNOWN )
+  {
+    V_ULONG( flash_info[0].start[0] ) = 0x00F000F0;
+    V_ULONG( flash_info[0].start[0] + 4 ) = 0x00F000F0;
+  }
+}
+
+/*-----------------------------------------------------------------------
+ */
+ulong flash_get_size( ulong baseaddr, flash_info_t *info )
+{
+  short i;
+  unsigned long flashtest_h, flashtest_l;
+
+  /* Write auto select command sequence and test FLASH answer */
+  V_ULONG( baseaddr + ((ulong)0x0555 << 3)) = 0x00AA00AA;
+  V_ULONG( baseaddr + ((ulong)0x02AA << 3)) = 0x00550055;
+  V_ULONG( baseaddr + ((ulong)0x0555 << 3)) = 0x00900090;
+  V_ULONG( baseaddr + 4 + ((ulong)0x0555 << 3)) = 0x00AA00AA;
+  V_ULONG( baseaddr + 4 + ((ulong)0x02AA << 3)) = 0x00550055;
+  V_ULONG( baseaddr + 4 + ((ulong)0x0555 << 3)) = 0x00900090;
+
+  flashtest_h = V_ULONG( baseaddr );           /* manufacturer ID         */
+  flashtest_l = V_ULONG( baseaddr + 4 );
+  if (flashtest_h != AMD_MANUFACT)
+  {
+    info->flash_id = FLASH_UNKNOWN;
+    info->sector_count = 0;
+    info->size = 0;
+    return( 0 );                               /* no or unknown flash     */
+  }
+
+  info->flash_id = AMD_MANUFACT << 16;         /* set manufacturer offset */
+
+  flashtest_h = V_ULONG( baseaddr + 8 );       /* device ID               */
+  flashtest_l = V_ULONG( baseaddr + 12 );
+  if( flashtest_h != flashtest_l )
+    info->flash_id = FLASH_UNKNOWN;
+  else
+    switch( flashtest_h )
+    {
+      case AMD_ID_LV640U:
+        info->flash_id += FLASH_AM640U;
+        info->sector_count = 128;
+        info->size = 0x02000000;  break;       /* 4 * 8 MB = 32 MB        */
+      default:
+        info->flash_id = FLASH_UNKNOWN;
+        return( 0 );                           /* no or unknown flash     */
+    }
+
+  /* set up sector start adress table (uniform sector type!) */
+  for( i = 0; i < info->sector_count; i++ )
+    info->start[i] = baseaddr + (i * 0x00040000);
+
+  /* check for protected sectors */
+  for( i = 0; i < info->sector_count; i++ )
+  {
+    /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+    if( (V_ULONG( info->start[i] + 16 ) & 0x00010001) ||
+        (V_ULONG( info->start[i] + 20 ) & 0x00010001) )
+      info->protect[i] = 1;            /* D0 = 1 if protected */
+    else info->protect[i] = 0;
+  }
+
+  flash_reset();
+  return( info->size );
+}
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+    unsigned long size_b0 = 0;
+    int i;
+
+    /* 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 (only one bank) */
+
+    size_b0 = flash_get_size(CFG_FLASH0_BASE, &flash_info[0]);
+    if (flash_info[0].flash_id == FLASH_UNKNOWN)
+    {
+       printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+               size_b0, size_b0>>20);
+    }
+    if (flash_info[0].size != (CFG_FLASH0_SIZE<<20))
+    {
+       printf ("## FLASH size on Bank 0 does not match CFG_FLASH0_SIZE: "
+               "0x%lx != 0x%x\n", flash_info[0].size,
+                                 CFG_FLASH0_SIZE<<20);
+    }
+
+    /*
+     * protect monitor and environment sectors
+     */
+
+#if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
+    flash_protect(FLAG_PROTECT_SET,
+                 CFG_MONITOR_BASE,
+                 CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+                 &flash_info[0]);
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef  CFG_ENV_SIZE
+#  define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
+# endif
+    flash_protect(FLAG_PROTECT_SET,
+                 CFG_ENV_ADDR,
+                 CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+                 &flash_info[0]);
+#endif
+
+    return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+    int i;
+
+    if (info->flash_id == FLASH_UNKNOWN)
+    {
+       printf ("missing or unknown FLASH type\n");
+       return;
+    }
+
+    switch ((info->flash_id >> 16) & 0xff)
+    {
+    case 0x1:
+       printf ("AMD ");
+       break;
+    default:
+       printf ("Unknown Vendor ");
+       break;
+    }
+
+    switch (info->flash_id & FLASH_TYPEMASK)
+    {
+    case FLASH_AM640U:
+       printf ("29LV640D (64 M, uniform sector)\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)
+    {
+       if ((i % 5) == 0)
+         printf ("\n   ");
+       printf (" %08lX%s",
+               info->start[i],
+               info->protect[i] ? " (RO)" : "     "
+               );
+    }
+    printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+    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;
+    }
+
+    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();
+
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00800080;
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00800080;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
+    udelay (1000);
+
+    /* Start erase on unprotected sectors */
+    for (sect = s_first; sect<=s_last; sect++)
+    {
+       if (info->protect[sect] == 0)
+        {      /* not protected */
+           V_ULONG( info->start[sect] ) = 0x00300030;
+           V_ULONG( info->start[sect] + 4 ) = 0x00300030;
+           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;
+    while ((V_ULONG( info->start[l_sect] ) & 0x00800080) != 0x00800080 ||
+          (V_ULONG( info->start[l_sect] + 4 ) & 0x00800080) != 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 */
+    flash_reset ();
+
+    printf (" done\n");
+}
+
+static int write_dword (flash_info_t *, ulong, unsigned char *);
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+    ulong dp;
+    static unsigned char bb[8];
+    int i, l, rc, cc = cnt;
+
+    dp = (addr & ~7);  /* get lower dword aligned address */
+
+    /*
+     * handle unaligned start bytes
+     */
+    if ((l = addr - dp) != 0)
+    {
+       for (i = 0; i < 8; i++)
+           bb[i] = (i < l || (i-l) >= cc) ? V_BYTE(dp+i) : *src++;
+       if ((rc = write_dword(info, dp, bb)) != 0)
+       {
+           return (rc);
+       }
+       dp += 8;
+       cc -= 8 - l;
+    }
+
+    /*
+     * handle word aligned part
+     */
+    while (cc >= 8)
+    {
+       if ((rc = write_dword(info, dp, src)) != 0)
+       {
+           return (rc);
+       }
+       dp  += 8;
+       src += 8;
+       cc -= 8;
+    }
+
+    if (cc <= 0)
+    {
+       return (0);
+    }
+
+    /*
+     * handle unaligned tail bytes
+     */
+    for (i = 0; i < 8; i++)
+    {
+       bb[i] = (i < cc) ? *src++ : V_BYTE(dp+i);
+    }
+    return (write_dword(info, dp, bb));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a dword to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_dword (flash_info_t *info, ulong dest, unsigned char * pdata)
+{
+    ulong start, cl, ch;
+    int flag, i;
+
+    for (i = 0; i < 4; i++)
+       ch = (ch << 8) + *pdata++;      /* high word    */
+    for (i = 0; i < 4; i++)
+       cl = (cl << 8) + *pdata++;      /* low word     */
+
+    /* Check if Flash is (sufficiently) erased */
+    if ((*((vu_long *)dest) & ch)      != ch
+      ||(*((vu_long *)(dest + 4)) & cl)        != cl)
+    {
+       return (2);
+    }
+
+    /* Disable interrupts which might cause a timeout here */
+    flag = disable_interrupts();
+
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00A000A0;
+    V_ULONG( dest ) = ch;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
+    V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
+    V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00A000A0;
+    V_ULONG( dest + 4 ) = cl;
+
+    /* re-enable interrupts if necessary */
+    if (flag)
+      enable_interrupts();
+
+    /* data polling for D7 */
+    start = get_timer (0);
+    while( ((V_ULONG( dest ) & 0x00800080) != (ch & 0x00800080)) ||
+           ((V_ULONG( dest + 4 ) & 0x00800080) != (cl & 0x00800080)) )
+    {
+       if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
+       {
+           return (1);
+       }
+    }
+    return (0);
+}
+
diff --git a/board/tqm8260/ppcboot.lds b/board/tqm8260/ppcboot.lds
new file mode 100644 (file)
index 0000000..5df4cdb
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * (C) Copyright 2001
+ * 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
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)          }
+  .dynsym        : { *(.dynsym)                }
+  .dynstr        : { *(.dynstr)                }
+  .rel.text      : { *(.rel.text)              }
+  .rela.text     : { *(.rela.text)     }
+  .rel.data      : { *(.rel.data)              }
+  .rela.data     : { *(.rela.data)     }
+  .rel.rodata    : { *(.rel.rodata)    }
+  .rela.rodata   : { *(.rela.rodata)   }
+  .rel.got       : { *(.rel.got)               }
+  .rela.got      : { *(.rela.got)              }
+  .rel.ctors     : { *(.rel.ctors)     }
+  .rela.ctors    : { *(.rela.ctors)    }
+  .rel.dtors     : { *(.rel.dtors)     }
+  .rela.dtors    : { *(.rela.dtors)    }
+  .rel.bss       : { *(.rel.bss)               }
+  .rela.bss      : { *(.rela.bss)              }
+  .rel.plt       : { *(.rel.plt)               }
+  .rela.plt      : { *(.rela.plt)              }
+  .init          : { *(.init)  }
+  .plt : { *(.plt) }
+  .text      :
+  {
+    cpu/mpc8260/start.o        (.text)
+    *(.text)
+    common/environment.o(.text)
+    *(.fixup)
+    *(.got1)
+    . = ALIGN(16);
+    *(.rodata)
+    *(.rodata1)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  _erotext = .;
+  PROVIDE (erotext = .);
+  .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  }
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+  __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(4096);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
+
diff --git a/board/tqm8260/tqm8260.c b/board/tqm8260/tqm8260.c
new file mode 100644 (file)
index 0000000..4574df3
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * (C) Copyright 2001
+ * 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 <ioports.h>
+#include <mpc8260.h>
+
+/*
+ * I/O Port configuration table
+ *
+ * if conf is 1, then that port pin will be configured at boot time
+ * according to the five values podr/pdir/ppar/psor/pdat for that entry
+ */
+
+const iop_conf_t iop_conf_tab[4][32] = {
+
+    /* Port A configuration */
+    {  /*            conf ppar psor pdir podr pdat */
+       /* PA31 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 *ATMTXEN */
+       /* PA30 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTCA   */
+       /* PA29 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTSOC  */
+       /* PA28 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 *ATMRXEN */
+       /* PA27 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRSOC */
+       /* PA26 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRCA */
+       /* PA25 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTXD[0] */
+       /* PA24 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTXD[1] */
+       /* PA23 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTXD[2] */
+       /* PA22 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTXD[3] */
+       /* PA21 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTXD[4] */
+       /* PA20 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTXD[5] */
+       /* PA19 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTXD[6] */
+       /* PA18 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMTXD[7] */
+       /* PA17 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRXD[7] */
+       /* PA16 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRXD[6] */
+       /* PA15 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRXD[5] */
+       /* PA14 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRXD[4] */
+       /* PA13 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRXD[3] */
+       /* PA12 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRXD[2] */
+       /* PA11 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRXD[1] */
+       /* PA10 */ {   0,   0,   0,   1,   0,   0   }, /* FCC1 ATMRXD[0] */
+       /* PA9  */ {   1,   1,   0,   1,   0,   0   }, /* SMC2 TXD */
+       /* PA8  */ {   1,   1,   0,   0,   0,   0   }, /* SMC2 RXD */
+       /* PA7  */ {   0,   0,   0,   1,   0,   0   }, /* PA7 */
+       /* PA6  */ {   0,   0,   0,   1,   0,   0   }, /* PA6 */
+       /* PA5  */ {   0,   0,   0,   1,   0,   0   }, /* PA5 */
+       /* PA4  */ {   0,   0,   0,   1,   0,   0   }, /* PA4 */
+       /* PA3  */ {   0,   0,   0,   1,   0,   0   }, /* PA3 */
+       /* PA2  */ {   0,   0,   0,   1,   0,   0   }, /* PA2 */
+       /* PA1  */ {   0,   0,   0,   1,   0,   0   }, /* PA1 */
+       /* PA0  */ {   0,   0,   0,   1,   0,   0   }  /* PA0 */
+    },
+
+    /* Port B configuration */
+    {   /*           conf ppar psor pdir podr pdat */
+       /* PB31 */ {   1,   1,   0,   1,   0,   0   }, /* FCC2 MII TX_ER */
+       /* PB30 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII RX_DV */
+       /* PB29 */ {   1,   1,   1,   1,   0,   0   }, /* FCC2 MII TX_EN */
+       /* PB28 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII RX_ER */
+       /* PB27 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII COL */
+       /* PB26 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII CRS */
+       /* PB25 */ {   1,   1,   0,   1,   0,   0   }, /* FCC2 MII TxD[3] */
+       /* PB24 */ {   1,   1,   0,   1,   0,   0   }, /* FCC2 MII TxD[2] */
+       /* PB23 */ {   1,   1,   0,   1,   0,   0   }, /* FCC2 MII TxD[1] */
+       /* PB22 */ {   1,   1,   0,   1,   0,   0   }, /* FCC2 MII TxD[0] */
+       /* PB21 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII RxD[0] */
+       /* PB20 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII RxD[1] */
+       /* PB19 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII RxD[2] */
+       /* PB18 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII RxD[3] */
+       /* PB17 */ {   0,   0,   0,   0,   0,   0   }, /* PB17 */
+       /* PB16 */ {   0,   0,   0,   0,   0,   0   }, /* PB16 */
+       /* PB15 */ {   0,   0,   0,   0,   0,   0   }, /* PB15 */
+       /* PB14 */ {   0,   0,   0,   0,   0,   0   }, /* PB14 */
+       /* PB13 */ {   0,   0,   0,   0,   0,   0   }, /* PB13 */
+       /* PB12 */ {   0,   0,   0,   0,   0,   0   }, /* PB12 */
+       /* PB11 */ {   0,   0,   0,   0,   0,   0   }, /* PB11 */
+       /* PB10 */ {   0,   0,   0,   0,   0,   0   }, /* PB10 */
+       /* PB9  */ {   0,   0,   0,   0,   0,   0   }, /* PB9 */
+       /* PB8  */ {   0,   0,   0,   0,   0,   0   }, /* PB8 */
+       /* PB7  */ {   0,   0,   0,   0,   0,   0   }, /* PB7 */
+       /* PB6  */ {   0,   0,   0,   0,   0,   0   }, /* PB6 */
+       /* PB5  */ {   0,   0,   0,   0,   0,   0   }, /* PB5 */
+       /* PB4  */ {   0,   0,   0,   0,   0,   0   }, /* PB4 */
+       /* PB3  */ {   0,   0,   0,   0,   0,   0   }, /* pin doesn't exist */
+       /* PB2  */ {   0,   0,   0,   0,   0,   0   }, /* pin doesn't exist */
+       /* PB1  */ {   0,   0,   0,   0,   0,   0   }, /* pin doesn't exist */
+       /* PB0  */ {   0,   0,   0,   0,   0,   0   }  /* pin doesn't exist */
+    },
+
+    /* Port C */
+    {   /*           conf ppar psor pdir podr pdat */
+       /* PC31 */ {   0,   0,   0,   1,   0,   0   }, /* PC31 */
+       /* PC30 */ {   0,   0,   0,   1,   0,   0   }, /* PC30 */
+       /* PC29 */ {   1,   1,   1,   0,   0,   0   }, /* SCC1 EN *CLSN */
+       /* PC28 */ {   0,   0,   0,   1,   0,   0   }, /* PC28 */
+       /* PC27 */ {   0,   0,   0,   1,   0,   0   }, /* PC27 */
+       /* PC26 */ {   0,   0,   0,   1,   0,   0   }, /* PC26 */
+       /* PC25 */ {   0,   0,   0,   1,   0,   0   }, /* PC25 */
+       /* PC24 */ {   0,   0,   0,   1,   0,   0   }, /* PC24 */
+       /* PC23 */ {   0,   1,   0,   1,   0,   0   }, /* ATMTFCLK */
+       /* PC22 */ {   0,   1,   0,   0,   0,   0   }, /* ATMRFCLK */
+       /* PC21 */ {   1,   1,   0,   0,   0,   0   }, /* SCC1 EN RXCLK */
+       /* PC20 */ {   1,   1,   0,   0,   0,   0   }, /* SCC1 EN TXCLK */
+       /* PC19 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII RX_CLK */
+       /* PC18 */ {   1,   1,   0,   0,   0,   0   }, /* FCC2 MII TX_CLK */
+       /* PC17 */ {   0,   0,   0,   1,   0,   0   }, /* PC17 */
+       /* PC16 */ {   0,   0,   0,   1,   0,   0   }, /* PC16 */
+       /* PC15 */ {   0,   0,   0,   1,   0,   0   }, /* PC15 */
+       /* PC14 */ {   1,   1,   0,   0,   0,   0   }, /* SCC1 EN *CD */
+       /* PC13 */ {   0,   0,   0,   1,   0,   0   }, /* PC13 */
+       /* PC12 */ {   0,   0,   0,   1,   0,   0   }, /* PC12 */
+       /* PC11 */ {   0,   0,   0,   1,   0,   0   }, /* PC11 */
+       /* PC10 */ {   0,   0,   0,   1,   0,   0   }, /* FCC2 MDC */
+       /* PC9  */ {   0,   0,   0,   1,   0,   0   }, /* FCC2 MDIO */
+       /* PC8  */ {   0,   0,   0,   1,   0,   0   }, /* PC8 */
+       /* PC7  */ {   0,   0,   0,   1,   0,   0   }, /* PC7 */
+       /* PC6  */ {   0,   0,   0,   1,   0,   0   }, /* PC6 */
+       /* PC5  */ {   0,   0,   0,   1,   0,   0   }, /* PC5 */
+       /* PC4  */ {   0,   0,   0,   1,   0,   0   }, /* PC4 */
+       /* PC3  */ {   0,   0,   0,   1,   0,   0   }, /* PC3 */
+       /* PC2  */ {   0,   0,   0,   1,   0,   1   }, /* ENET FDE */
+       /* PC1  */ {   0,   0,   0,   1,   0,   0   }, /* ENET DSQE */
+       /* PC0  */ {   0,   0,   0,   1,   0,   0   }, /* ENET LBK */
+    },
+
+    /* Port D */
+    {   /*           conf ppar psor pdir podr pdat */
+       /* PD31 */ {   1,   1,   0,   0,   0,   0   }, /* SCC1 EN RxD */
+       /* PD30 */ {   1,   1,   1,   1,   0,   0   }, /* SCC1 EN TxD */
+       /* PD29 */ {   1,   1,   0,   1,   0,   0   }, /* SCC1 EN TENA */
+       /* PD28 */ {   0,   0,   0,   1,   0,   0   }, /* PD28 */
+       /* PD27 */ {   0,   0,   0,   1,   0,   0   }, /* PD27 */
+       /* PD26 */ {   0,   0,   0,   1,   0,   0   }, /* PD26 */
+       /* PD25 */ {   0,   0,   0,   1,   0,   0   }, /* PD25 */
+       /* PD24 */ {   0,   0,   0,   1,   0,   0   }, /* PD24 */
+       /* PD23 */ {   0,   0,   0,   1,   0,   0   }, /* PD23 */
+       /* PD22 */ {   0,   0,   0,   1,   0,   0   }, /* PD22 */
+       /* PD21 */ {   0,   0,   0,   1,   0,   0   }, /* PD21 */
+       /* PD20 */ {   0,   0,   0,   1,   0,   0   }, /* PD20 */
+       /* PD19 */ {   0,   0,   0,   1,   0,   0   }, /* PD19 */
+       /* PD18 */ {   0,   0,   0,   1,   0,   0   }, /* PD19 */
+       /* PD17 */ {   0,   1,   0,   0,   0,   0   }, /* FCC1 ATMRXPRTY */
+       /* PD16 */ {   0,   1,   0,   1,   0,   0   }, /* FCC1 ATMTXPRTY */
+       /* PD15 */ {   0,   1,   1,   0,   1,   0   }, /* I2C SDA */
+       /* PD14 */ {   0,   1,   1,   0,   1,   0   }, /* I2C SCL */
+       /* PD13 */ {   0,   0,   0,   0,   0,   0   }, /* PD13 */
+       /* PD12 */ {   0,   0,   0,   0,   0,   0   }, /* PD12 */
+       /* PD11 */ {   0,   0,   0,   0,   0,   0   }, /* PD11 */
+       /* PD10 */ {   0,   0,   0,   0,   0,   0   }, /* PD10 */
+       /* PD9  */ {   1,   1,   0,   1,   0,   0   }, /* SMC1 TXD */
+       /* PD8  */ {   1,   1,   0,   0,   0,   0   }, /* SMC1 RXD */
+       /* PD7  */ {   0,   0,   0,   1,   0,   1   }, /* PD7 */
+       /* PD6  */ {   0,   0,   0,   1,   0,   1   }, /* PD6 */
+       /* PD5  */ {   0,   0,   0,   1,   0,   1   }, /* PD5 */
+       /* PD4  */ {   0,   0,   0,   1,   0,   1   }, /* PD4 */
+       /* PD3  */ {   0,   0,   0,   0,   0,   0   }, /* pin doesn't exist */
+       /* PD2  */ {   0,   0,   0,   0,   0,   0   }, /* pin doesn't exist */
+       /* PD1  */ {   0,   0,   0,   0,   0,   0   }, /* pin doesn't exist */
+       /* PD0  */ {   0,   0,   0,   0,   0,   0   }  /* pin doesn't exist */
+    }
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Check Board Identity:
+ */
+int checkboard(void)
+{
+    printf ("TQM8260\n");
+    return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Try SDRAM initialization with P/LSDMR=sdmr and ORx=orx
+ *
+ * This routine performs standard 8260 initialization sequence
+ * and calculates the available memory size. It may be called
+ * several times to try different SDRAM configurations on both
+ * 60x and local buses.
+ */
+long int try_init(volatile memctl8260_t *memctl, ulong sdmr, ulong orx,
+                 volatile uchar * base)
+{
+    volatile uchar     c = 0xff;
+    ulong              cnt, val;
+    volatile ulong *   addr;
+    volatile uint *    sdmr_ptr;
+    volatile uint *    orx_ptr;
+    int                        i;
+
+    /* Since CFG_SDRAM_BASE is always 0 (??), we assume that
+     * we are configuring CS1 if base != 0
+     */
+    sdmr_ptr = base ? &memctl->memc_lsdmr : &memctl->memc_psdmr;
+    orx_ptr = base ? &memctl->memc_or2 : &memctl->memc_or1;
+
+    *orx_ptr = orx;
+
+    /*
+     * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35):
+     *
+     * "At system reset, initialization software must set up the
+     *  programmable parameters in the memory controller banks registers
+     *  (ORx, BRx, P/LSDMR). After all memory parameters are configured,
+     *  system software should execute the following initialization sequence
+     *  for each SDRAM device.
+     *
+     *  1. Issue a PRECHARGE-ALL-BANKS command
+     *  2. Issue eight CBR REFRESH commands
+     *  3. Issue a MODE-SET command to initialize the mode register
+     *
+     *  The initial commands are executed by setting P/LSDMR[OP] and
+     *  accessing the SDRAM with a single-byte transaction."
+     *
+     * The appropriate BRx/ORx registers have already been set when we
+     * get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE.
+     */
+
+    *sdmr_ptr = sdmr | PSDMR_OP_PREA;
+    *base = c;
+
+    *sdmr_ptr = sdmr | PSDMR_OP_CBRR;
+    for (i = 0; i < 8; i++)
+       *base = c;
+
+    *sdmr_ptr = sdmr | PSDMR_OP_MRW;
+    *(base + CFG_MRS_OFFS) = c;                /* setting MR on address lines */
+
+    *sdmr_ptr = sdmr | PSDMR_OP_NORM | PSDMR_RFEN;
+    *base = c;
+
+    /*
+     * Check memory range for valid RAM. A simple memory test determines
+     * the actually available RAM size between addresses `base' and
+     * `base + maxsize'. Some (not all) hardware errors are detected:
+     * - short between address lines
+     * - short between data lines
+     */
+    for (cnt = 0x04000000/sizeof(long); cnt > 0; cnt >>= 1)
+    {
+       addr = (volatile ulong *)base + cnt;    /* pointer arith! */
+       *addr = ~cnt;
+    }
+
+    addr = (volatile ulong *)base;
+    *addr = 0;
+
+    if ((val = *addr) != 0)
+    {
+       return (0);
+    }
+
+    for (cnt = 1; ; cnt <<=1)
+    {
+        addr = (volatile ulong *)base + cnt;   /* pointer arith! */
+       val = *addr;
+       if (val != ~cnt)
+       {
+           /* Write the actual size to ORx
+            */
+           *orx_ptr = orx | ~(cnt * sizeof(long) - 1);
+           return (cnt * sizeof(long));
+       }
+    }
+    /* NOTREACHED */
+}
+
+long int initdram(int board_type)
+{
+    volatile immap_t *immap  = (immap_t *)CFG_IMMR;
+    volatile memctl8260_t *memctl = &immap->im_memctl;
+#ifndef CFG_RAMBOOT
+    long size8, size9;
+#endif
+    long psize, lsize;
+
+    psize = 16 * 1024 * 1024;
+    lsize = 0;
+
+    memctl->memc_psrt = CFG_PSRT;
+    memctl->memc_mptpr = CFG_MPTPR;
+
+#ifndef CFG_RAMBOOT
+    /* 60x SDRAM setup:
+     */
+    size8 = try_init(memctl, CFG_PSDMR_8COL, CFG_OR1_8COL,
+               (uchar *) CFG_SDRAM_BASE);
+    size9 = try_init(memctl, CFG_PSDMR_9COL, CFG_OR1_9COL,
+               (uchar *) CFG_SDRAM_BASE);
+
+    if (size8 < size9)
+    {
+       psize = size9;
+       printf("(60x:9COL - %ld MB, ", psize >> 20);
+    }
+    else
+    {
+       psize = try_init(memctl, CFG_PSDMR_8COL, CFG_OR1_8COL,
+               (uchar *) CFG_SDRAM_BASE);
+       printf("(60x:8COL - %ld MB, ", psize >> 20);
+    }
+
+    /* Local SDRAM setup:
+     */
+#ifdef CFG_INIT_LOCAL_SDRAM
+    memctl->memc_lsrt = CFG_LSRT;
+    size8 = try_init(memctl, CFG_LSDMR_8COL, CFG_OR2_8COL,
+               (uchar *) SDRAM_BASE2_PRELIM);
+    size9 = try_init(memctl, CFG_LSDMR_9COL, CFG_OR2_9COL,
+               (uchar *) SDRAM_BASE2_PRELIM);
+
+    if (size8 < size9)
+    {
+       lsize = size9;
+       printf("Local:9COL - %ld MB) using ", lsize >> 20);
+    }
+    else
+    {
+       lsize = try_init(memctl, CFG_LSDMR_8COL, CFG_OR2_8COL,
+               (uchar *) SDRAM_BASE2_PRELIM);
+       printf("Local:8COL - %ld MB) using ", lsize >> 20);
+    }
+
+#if 0
+    /* Set up BR2 so that the local SDRAM goes
+     * right after the 60x SDRAM
+     */
+    memctl->memc_br2 = (CFG_BR2_PRELIM & ~BRx_BA_MSK) |
+                      (CFG_SDRAM_BASE + psize);
+#endif
+#endif /* CFG_INIT_LOCAL_SDRAM */
+#endif /* CFG_RAMBOOT */
+
+    return (psize);
+}
+
index 52b29896652b2a1024bb8942d6765db038fc3108..e8f80158a9a04cb86deec063973bf00a2b041326 100644 (file)
@@ -33,7 +33,7 @@ COBJS = board.o main.o command.o \
          cmd_console.o cmd_date.o cmd_eeprom.o \
          cmd_flash.o cmd_ide.o cmd_mem.o cmd_net.o \
          cmd_nvedit.o cmd_pcmcia.o cmd_reginfo.o \
-         s_record.o dlmalloc.o \
+         cmd_bedbug.o bedbug.o s_record.o dlmalloc.o \
          kgdb.o console.o lists.o devices.o flash.o cmd_i2c.o cmd_immap.o
 
 OBJS   = $(AOBJS) $(COBJS)
diff --git a/common/bedbug.c b/common/bedbug.c
new file mode 100644 (file)
index 0000000..1158a08
--- /dev/null
@@ -0,0 +1,1291 @@
+/* $Id: bedbug.c,v 1.1 2001/05/31 22:12:25 wd Exp $ */
+
+#include <ppcboot.h>
+#include <linux/ctype.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/ppc.h>
+#include <bedbug/regs.h>
+#include <bedbug/tables.h>
+
+#define Elf32_Word     unsigned long
+
+/* USE_SOURCE_CODE enables some symbolic debugging functions of this
+   code.  This is only useful if the program will have access to the
+   source code for the binary being examined.
+*/
+
+/* #define USE_SOURCE_CODE 1 */
+
+#ifdef USE_SOURCE_CODE
+extern int line_info_from_addr __P((Elf32_Word, char *, char *, int *));
+extern struct symreflist *symByAddr;
+extern char *symbol_name_from_addr __P((Elf32_Word,int,int *));
+#endif /* USE_SOURCE_CODE */
+
+int            print_operands __P((struct ppc_ctx *));
+int            get_operand_value __P(( struct opcode *, unsigned long,
+                                       enum OP_FIELD, unsigned long * ));
+struct opcode *        find_opcode __P((unsigned long));
+struct opcode * find_opcode_by_name __P((char *));
+char *         spr_name __P((int));
+int            spr_value __P((char *));
+char *         tbr_name __P((int));
+int            tbr_value __P((char *));
+int            parse_operand __P((unsigned long,struct opcode *,
+                                  struct operand *,char *,int *));
+int            get_word __P((char**,char*));
+long           read_number __P((char *));
+int            downstring __P((char*));
+
+\f
+/*======================================================================
+ * Entry point for the PPC disassembler.
+ *
+ * Arguments:
+ *     memaddr         The address to start disassembling from.
+ *
+ *     virtual         If this value is non-zero, then this will be 
+ *                     used as the base address for the output and
+ *                     symbol lookups.  If this value is zero then
+ *                     memaddr is used as the absolute address.
+ *
+ *     num_instr       The number of instructions to disassemble.  Since
+ *                     each instruction is 32 bits long, this can be
+ *                     computed if you know the total size of the region.
+ *
+ *     pfunc           The address of a function that is called to print
+ *                     each line of output.  The function should take a
+ *                     single character pointer as its parameters a la puts.
+ *
+ *     flags           Sets options for the output.  This is a
+ *                     bitwise-inclusive-OR of the following
+ *                     values.  Note that only one of the radix
+ *                     options may be set.
+ *
+ *                     F_RADOCTAL      - output radix is unsigned base 8.
+ *                     F_RADUDECIMAL   - output radix is unsigned base 10.
+ *                     F_RADSDECIMAL   - output radix is signed base 10.
+ *                     F_RADHEX        - output radix is unsigned base 16.
+ *                     F_SIMPLE        - use simplified mnemonics.
+ *                     F_SYMBOL        - lookup symbols for addresses.
+ *                     F_INSTR         - output raw instruction.
+ *                     F_LINENO        - show line # info if available.
+ *
+ * Returns TRUE if the area was successfully disassembled or FALSE if
+ * a problem was encountered with accessing the memory.
+ */
+
+int disppc( unsigned char *memaddr, unsigned char *virtual, int num_instr,
+           int (*pfunc)(const char *), unsigned long flags )
+{
+  int                  i;
+  struct ppc_ctx       ctx;
+#ifdef USE_SOURCE_CODE
+  int                  line_no = 0;
+  int                  last_line_no = 0;
+  char                 funcname[ 128 ] = {0};
+  char                 filename[ 256 ] = {0};
+  char                 last_funcname[ 128 ] = {0};
+  int                  symoffset;
+  char *               symname;
+  char *               cursym = (char *)0;
+#endif /* USE_SOURCE_CODE */
+  /*------------------------------------------------------------*/
+
+  ctx.flags   = flags;
+  ctx.virtual = virtual;
+  
+  /* Figure out the output radix before we go any further */
+  
+  if( ctx.flags & F_RADOCTAL )
+    {
+      /* Unsigned octal output */
+      strcpy( ctx.radix_fmt, "O%o" );
+    }
+  else if( ctx.flags & F_RADUDECIMAL )
+    {
+      /* Unsigned decimal output */
+      strcpy( ctx.radix_fmt, "%u" );
+    }
+  else if( ctx.flags & F_RADSDECIMAL )
+    {
+      /* Signed decimal output */
+      strcpy( ctx.radix_fmt, "%d" );
+    }
+  else
+    {
+      /* Unsigned hex output */
+      strcpy( ctx.radix_fmt, "0x%x" );
+    }
+
+  if( ctx.virtual == 0 )
+    {
+      ctx.virtual = memaddr;
+    }
+
+#ifdef USE_SOURCE_CODE
+  if( ctx.flags & F_SYMBOL )
+    {
+      if( symByAddr == 0 )     /* no symbols loaded */
+       ctx.flags &= ~F_SYMBOL;
+      else
+       {
+         cursym = (char *)0;
+         symoffset = 0;
+       }
+    }
+#endif /* USE_SOURCE_CODE */
+         
+  /* format each line as "XXXXXXXX: <symbol> IIIIIIII  disassembly" where,
+     XXXXXXXX is the memory address in hex,
+     <symbol> is the symbolic location if F_SYMBOL is set.
+     IIIIIIII is the raw machine code in hex if F_INSTR is set,
+     and disassembly is the disassembled machine code with numbers
+     formatted according to the 'radix' parameter */
+  
+  for( i = 0; i < num_instr; ++i, memaddr += 4, ctx.virtual += 4 )
+    {
+#ifdef USE_SOURCE_CODE
+      if( ctx.flags & F_LINENO )
+       {
+         if(( line_info_from_addr( (Elf32_Word) ctx.virtual, filename,
+                                   funcname, &line_no ) == TRUE ) &&
+            (( line_no != last_line_no ) ||
+             ( strcmp( last_funcname, funcname ) != 0 )))
+           {
+             print_source_line( filename, funcname, line_no, pfunc );
+           }
+         last_line_no = line_no;
+         strcpy( last_funcname, funcname );
+       }
+#endif /* USE_SOURCE_CODE */
+
+      sprintf( ctx.data, "%08lx: ", (unsigned long)ctx.virtual );
+      ctx.datalen = 10;
+
+#ifdef USE_SOURCE_CODE
+      if( ctx.flags & F_SYMBOL )
+       {
+         if(( symname =
+              symbol_name_from_addr( (Elf32_Word)ctx.virtual,
+                                     TRUE, 0 )) != 0 )
+           {
+             cursym = symname;
+             symoffset = 0;
+           }
+         else
+           {
+             if( (cursym == 0) &&
+                 ((symname =
+                   symbol_name_from_addr( (Elf32_Word)ctx.virtual,
+                                          FALSE, &symoffset )) != 0 ))
+               {
+                 cursym = symname;
+               }
+             else
+               {
+                 symoffset += 4;
+               }
+           }
+         
+         if( cursym != 0 )
+           {
+             sprintf( &ctx.data[ ctx.datalen ], "<%s+", cursym );
+             ctx.datalen = strlen( ctx.data );
+             sprintf( &ctx.data[ ctx.datalen ], ctx.radix_fmt, symoffset );
+             strcat( ctx.data, ">" );
+             ctx.datalen = strlen( ctx.data );
+           }
+       }
+#endif /* USE_SOURCE_CODE */
+      
+      ctx.instr = INSTRUCTION( memaddr );
+
+      if( ctx.flags & F_INSTR )
+       {
+         /* Find the opcode structure for this opcode.  If one is not found
+            then it must be an illegal instruction */
+         sprintf( &ctx.data[ ctx.datalen ], "   %02lx %02lx %02lx %02lx    ",
+                  ((ctx.instr >> 24) & 0xff), ((ctx.instr >> 16) & 0xff),
+                  ((ctx.instr >> 8) & 0xff), (ctx.instr & 0xff));
+         ctx.datalen += 18;
+       }
+      else
+       {
+         strcat( ctx.data, "   " );
+         ctx.datalen += 3;
+       }
+
+      if(( ctx.op = find_opcode( ctx.instr )) == 0 )
+       {
+         /* Illegal Opcode */
+         sprintf( &ctx.data[ ctx.datalen ], "        .long 0x%08lx",
+                  ctx.instr );
+         ctx.datalen += 24;
+         (*pfunc)( ctx.data );
+         continue;
+       }
+
+      if((( ctx.flags & F_SIMPLE ) == 0 ) ||
+        ( ctx.op->hfunc == 0 ) ||
+        ((*ctx.op->hfunc)( &ctx ) == FALSE ))
+       {
+         sprintf( &ctx.data[ ctx.datalen ], "%-7s ", ctx.op->name );
+         ctx.datalen += 8;
+         print_operands( &ctx );
+       }
+
+      (*pfunc)( ctx.data );
+    }
+
+  return TRUE;
+} /* disppc */
+
+
+\f
+/*======================================================================
+ * Called by the disassembler to print the operands for an instruction.
+ *
+ * Arguments:
+ *     ctx             A pointer to the disassembler context record.
+ *
+ * always returns 0.
+ */
+
+int print_operands( struct ppc_ctx *ctx )
+{
+  int                  open_parens = 0;
+  int                  field;
+  unsigned long        operand;
+  struct operand *     opr;
+#ifdef USE_SOURCE_CODE
+  char *               symname;
+  int                  offset;
+#endif /* USE_SOURCE_CODE */
+  /*------------------------------------------------------------*/
+
+  /* Walk through the operands and list each in order */
+  for( field = 0; ctx->op->fields[ field ] != 0; ++field )
+    {
+      if( ctx->op->fields[ field ] > n_operands )
+       {
+         continue;     /* bad operand ?! */
+       }
+         
+      opr = &operands[ ctx->op->fields[ field ] - 1 ];
+
+      if( opr->hint & OH_SILENT )
+       {
+         continue;
+       }
+
+      if(( field > 0 ) && !open_parens )
+       {
+         strcat( ctx->data, "," );
+         ctx->datalen++;
+       }
+
+      operand = (ctx->instr >> opr->shift) & ((1 << opr->bits)-1);
+
+      if( opr->hint & OH_ADDR )
+       {
+         if(( operand & (1 << (opr->bits-1))) != 0 )
+           {
+             operand = operand - (1 << opr->bits);
+           }
+
+         if( ctx->op->hint & H_RELATIVE )
+           operand = (operand << 2) + (unsigned long)ctx->virtual;
+         else
+           operand = (operand << 2);
+           
+
+         sprintf( &ctx->data[ ctx->datalen ], "0x%lx", operand );
+         ctx->datalen = strlen( ctx->data );
+
+#ifdef USE_SOURCE_CODE
+         if(( ctx->flags & F_SYMBOL ) &&
+            (( symname = symbol_name_from_addr( operand, 0, &offset )) != 0 ))
+           {
+             sprintf( &ctx->data[ ctx->datalen ], " <%s", symname );
+             if( offset != 0 )
+               {
+                 strcat( ctx->data, "+" );
+                 ctx->datalen = strlen( ctx->data );
+                 sprintf( &ctx->data[ ctx->datalen ], ctx->radix_fmt,
+                          offset );
+               }
+             strcat( ctx->data, ">" );
+           }
+#endif /* USE_SOURCE_CODE */
+       }
+
+      else if( opr->hint & OH_REG )
+       {
+         if(( operand == 0 )       &&
+            ( opr->field == O_rA ) &&
+            ( ctx->op->hint & H_RA0_IS_0 ))
+           {
+             strcat( ctx->data, "0" );
+           }
+         else
+           {
+             sprintf( &ctx->data[ ctx->datalen ], "r%d", (short)operand );
+           }
+
+         if( open_parens )
+           {
+             strcat( ctx->data, ")" );
+             open_parens--;
+           }
+       }
+
+      else if( opr->hint & OH_SPR )
+       {
+         strcat( ctx->data, spr_name( operand ));
+       }
+
+      else if( opr->hint & OH_TBR )
+       {
+         strcat( ctx->data, tbr_name( operand ));
+       }
+
+      else if( opr->hint & OH_LITERAL )
+       {
+         switch( opr->field )
+           {
+           case O_cr2:
+             strcat( ctx->data, "cr2" );
+             ctx->datalen += 3;
+             break;
+
+           default:
+             break;
+           }
+       }
+      
+      else
+       {
+         sprintf( &ctx->data[ ctx->datalen ], ctx->radix_fmt,
+                  (unsigned short)operand );
+
+         if( open_parens )
+           {
+             strcat( ctx->data, ")" );
+             open_parens--;
+           }
+
+         else if( opr->hint & OH_OFFSET )
+           {
+             strcat( ctx->data, "(" );
+             open_parens++;
+           }
+       }
+
+      ctx->datalen = strlen( ctx->data );
+    }
+
+  return 0;
+} /* print_operands */
+
+
+\f
+/*======================================================================
+ * Called to get the value of an arbitrary operand with in an instruction.
+ *
+ * Arguments:
+ *     op              The pointer to the opcode structure to which
+ *                     the operands belong.
+ *
+ *     instr           The instruction (32 bits) containing the opcode
+ *                     and the operands to print.  By the time that
+ *                     this routine is called the operand has already
+ *                     been added to the output.
+ *
+ *     field           The field (operand) to get the value of.
+ *
+ *     value           The address of an unsigned long to be filled in
+ *                     with the value of the operand if it is found.  This
+ *                     will only be filled in if the function returns
+ *                     TRUE.  This may be passed as 0 if the value is
+ *                     not required.
+ *
+ * Returns TRUE if the operand was found or FALSE if it was not.
+ */
+
+int get_operand_value( struct opcode *op, unsigned long instr,
+                      enum OP_FIELD field, unsigned long *value )
+{
+  int                  i;
+  struct operand *     opr;
+  /*------------------------------------------------------------*/
+
+  if( field > n_operands )
+    {
+      return FALSE;    /* bad operand ?! */
+    }
+
+  /* Walk through the operands and list each in order */
+  for( i = 0; op->fields[ i ] != 0; ++i )
+    {
+      if( op->fields[ i ] != field )
+       {
+         continue;
+       }
+
+      opr = &operands[ op->fields[ i ] - 1 ];
+
+      if( value )
+       {
+         *value = (instr >> opr->shift) & ((1 << opr->bits)-1);
+       }
+      return TRUE;
+    }
+
+  return FALSE;
+} /* operand_value */
+
+
+\f
+/*======================================================================
+ * Called by the disassembler to match an opcode value to an opcode structure.
+ *
+ * Arguments:
+ *     instr           The instruction (32 bits) to match.  This value
+ *                     may contain operand values as well as the opcode
+ *                     since they will be masked out anyway for this
+ *                     search.
+ *
+ * Returns the address of an opcode struct (from the opcode table) if the
+ * operand successfully matched an entry, or 0 if no match was found.
+ */
+
+struct opcode *find_opcode( unsigned long instr )
+{
+  struct opcode *      ptr;
+  int                  top = 0;
+  int                  bottom = n_opcodes - 1;
+  int                  idx;
+  /*------------------------------------------------------------*/
+
+  while( top <= bottom )
+    {
+      idx = (top + bottom) >> 1;
+      ptr = &opcodes[ idx ];
+      
+      if(( instr & ptr->mask ) < ptr->opcode )
+       {
+         bottom = idx - 1;
+       }
+      else if(( instr & ptr->mask ) > ptr->opcode )
+       {
+         top = idx + 1;
+       }
+      else
+       {
+         return ptr;
+       }
+    }
+
+  return (struct opcode *)0;
+} /* find_opcode */
+
+
+\f
+/*======================================================================
+ * Called by the assembler to match an opcode name to an opcode structure.
+ *
+ * Arguments:
+ *     name            The text name of the opcode, e.g. "b", "mtspr", etc.
+ *
+ * The opcodes are sorted numerically by their instruction binary code
+ * so a search for the name cannot use the binary search used by the
+ * other find routine.
+ *
+ * Returns the address of an opcode struct (from the opcode table) if the
+ * name successfully matched an entry, or 0 if no match was found.
+ */
+
+struct opcode *find_opcode_by_name( char *name )
+{
+  int                  idx;
+  /*------------------------------------------------------------*/
+
+  downstring( name );
+
+  for( idx = 0; idx < n_opcodes; ++idx )
+    {
+      if( !strcmp( name, opcodes[ idx ].name ))
+       return &opcodes[ idx ];
+    }
+
+  return (struct opcode *)0;
+} /* find_opcode_by_name */
+
+
+\f
+/*======================================================================
+ * Convert the 'spr' operand from its numeric value to its symbolic name.
+ *
+ * Arguments:
+ *     value           The value of the 'spr' operand.  This value should
+ *                     be unmodified from its encoding in the instruction.
+ *                     the split-field computations will be performed
+ *                     here before the switch.
+ *
+ * Returns the address of a character array containing the name of the
+ * special purpose register defined by the 'value' parameter, or the
+ * address of a character array containing "???" if no match was found.
+ */
+
+char *spr_name( int value )
+{
+  unsigned short       spr;
+  static char          other[ 10 ];
+  int                  i;
+  /*------------------------------------------------------------*/
+  
+  /* spr is a 10 bit field whose interpretation has the high and low
+     five-bit fields reversed from their encoding in the operand */
+  
+  spr = (( value >> 5 ) & 0x1f ) | (( value & 0x1f ) << 5 );
+
+  for( i = 0; i < n_sprs; ++i ){
+    if( spr == spr_map[ i ].spr_val )
+      return spr_map[ i ].spr_name;
+  }
+  
+  sprintf( other, "%d", spr );
+  return other;
+} /* spr_name */
+     
+
+\f
+/*======================================================================
+ * Convert the 'spr' operand from its symbolic name to its numeric value
+ *
+ * Arguments:
+ *     name            The symbolic name of the 'spr' operand.  The
+ *                     split-field encoding will be done by this routine.
+ *                     NOTE: name can be a number.
+ *
+ * Returns the numeric value for the spr appropriate for encoding a machine
+ * instruction.  Returns 0 if unable to find the SPR.
+ */
+
+int spr_value( char *name )
+{
+  struct spr_info *    sprp;
+  int                  spr;
+  int                  i;
+  /*------------------------------------------------------------*/
+
+  if( !name || !*name )
+    return 0;
+  
+  if( isdigit((int)name[ 0 ])) {
+    i = htonl( read_number( name ));
+    spr = (( i >> 5 ) & 0x1f ) | (( i & 0x1f ) << 5 );
+    return spr;
+  }
+
+  downstring( name );
+  
+  for( i = 0; i < n_sprs; ++i ) {
+    sprp = &spr_map[ i ];
+    
+    if( strcmp( name, sprp->spr_name ) == 0 ) {
+      /* spr is a 10 bit field whose interpretation has the high and low
+        five-bit fields reversed from their encoding in the operand */
+      i = htonl( sprp->spr_val );
+      spr = (( i >> 5 ) & 0x1f ) | (( i & 0x1f ) << 5 );
+
+      return spr;
+    }
+  }
+
+  return 0;
+} /* spr_value */
+     
+
+\f
+/*======================================================================
+ * Convert the 'tbr' operand from its numeric value to its symbolic name.
+ *
+ * Arguments:
+ *     value           The value of the 'tbr' operand.  This value should
+ *                     be unmodified from its encoding in the instruction.
+ *                     the split-field computations will be performed
+ *                     here before the switch.
+ *
+ * Returns the address of a character array containing the name of the
+ * time base register defined by the 'value' parameter, or the address
+ * of a character array containing "???" if no match was found.
+ */
+
+char *tbr_name( int value )
+{
+  unsigned short       tbr;
+  /*------------------------------------------------------------*/
+  
+  /* tbr is a 10 bit field whose interpretation has the high and low
+     five-bit fields reversed from their encoding in the operand */
+  
+  tbr = (( value >> 5 ) & 0x1f ) | (( value & 0x1f ) << 5 );
+
+  if( tbr == 268 )
+    return "TBL";
+  
+  else if( tbr == 269 )
+    return "TBU";
+  
+
+  return "???";
+} /* tbr_name */
+
+
+\f
+/*======================================================================
+ * Convert the 'tbr' operand from its symbolic name to its numeric value.
+ *
+ * Arguments:
+ *     name            The symbolic name of the 'tbr' operand.  The
+ *                     split-field encoding will be done by this routine.
+ *
+ * Returns the numeric value for the spr appropriate for encoding a machine
+ * instruction.  Returns 0 if unable to find the TBR.
+ */
+
+int tbr_value( char *name )
+{
+  int  tbr;
+  int  val;
+  /*------------------------------------------------------------*/
+
+  if( !name || !*name )
+    return 0;
+
+  downstring( name );
+  
+  if( isdigit((int)name[ 0 ])) {
+    val = read_number( name );
+
+    if( val != 268 && val != 269 )
+      return 0;
+  }
+  else if( strcmp( name, "tbl" ) == 0 )
+    val = 268;
+  else if( strcmp( name, "tbu" ) == 0 )
+    val = 269;
+  else
+    return 0;
+  
+  /* tbr is a 10 bit field whose interpretation has the high and low
+     five-bit fields reversed from their encoding in the operand */
+
+  val = htonl( val );
+  tbr = (( val >> 5 ) & 0x1f ) | (( val & 0x1f ) << 5 );
+  return tbr;
+} /* tbr_name */
+
+
+\f
+/*======================================================================
+ * The next several functions (handle_xxx) are the routines that handle
+ * disassembling the opcodes with simplified mnemonics.
+ *
+ * Arguments:
+ *     ctx             A pointer to the disassembler context record.
+ *
+ * Returns TRUE if the simpler form was printed or FALSE if it was not.
+ */
+
+int handle_bc( struct ppc_ctx *ctx )
+{
+  unsigned long        bo;
+  unsigned long        bi;
+  struct opcode        blt  = {B_OPCODE(16,0,0), B_MASK, {O_BD, 0},
+                       0, "blt", H_RELATIVE};
+  struct opcode        bne  = {B_OPCODE(16,0,0), B_MASK, {O_cr2, O_BD, 0},
+                       0, "bne", H_RELATIVE};
+  struct opcode        bdnz = {B_OPCODE(16,0,0), B_MASK, {O_BD, 0},
+                       0, "bdnz", H_RELATIVE};
+  /*------------------------------------------------------------*/
+
+  if( get_operand_value( ctx->op, ctx->instr, O_BO, &bo ) == FALSE )
+    return FALSE;
+  
+  if( get_operand_value( ctx->op, ctx->instr, O_BI, &bi ) == FALSE )
+    return FALSE;
+
+  if(( bo == 12 ) && ( bi == 0 ))
+    {
+      ctx->op = &blt;
+      sprintf( &ctx->data[ ctx->datalen ], "%-7s ", ctx->op->name );
+      ctx->datalen += 8;
+      print_operands( ctx );
+      return TRUE;
+    }
+  else if(( bo == 4 ) && ( bi == 10 ))
+    {
+      ctx->op = &bne;
+      sprintf( &ctx->data[ ctx->datalen ], "%-7s ", ctx->op->name );
+      ctx->datalen += 8;
+      print_operands( ctx );
+      return TRUE;
+    }
+  else if(( bo == 16 ) && ( bi == 0 ))
+    {
+      ctx->op = &bdnz;
+      sprintf( &ctx->data[ ctx->datalen ], "%-7s ", ctx->op->name );
+      ctx->datalen += 8;
+      print_operands( ctx );
+      return TRUE;
+    }
+  
+  return FALSE;
+} /* handle_blt */
+
+
+\f
+/*======================================================================
+ * Outputs source line information for the disassembler.  This should
+ * be modified in the future to lookup the actual line of source code
+ * from the file, but for now this will do.
+ *
+ * Arguments:
+ *     filename        The address of a character array containing the
+ *                     absolute path and file name of the source file.
+ *
+ *     funcname        The address of a character array containing the
+ *                     name of the function (not C++ demangled (yet))
+ *                     to which this code belongs.
+ *
+ *     line_no         An integer specifying the source line number that
+ *                     generated this code.
+ *
+ *     pfunc           The address of a function to call to print the output.
+ *     
+ *
+ * Returns TRUE if it was able to output the line info, or false if it was
+ * not.
+ */
+
+int print_source_line( char *filename, char *funcname,
+                      int line_no, int (*pfunc)(const char *))
+{
+  char out_buf[ 256 ];
+  /*------------------------------------------------------------*/
+  
+  (*pfunc)( "" ); /* output a newline */
+  sprintf( out_buf, "%s %s(): line %d", filename, funcname, line_no );
+  (*pfunc)( out_buf );
+  
+  return TRUE;
+} /* print_source_line */
+
+
+\f
+/*======================================================================
+ * Entry point for the PPC assembler.
+ *
+ * Arguments:
+ *     asm_buf         An array of characters containing the assembly opcode
+ *                     and operands to convert to a POWERPC machine
+ *                     instruction.
+ *
+ * Returns the machine instruction or zero.
+ */
+
+unsigned long asmppc( unsigned long memaddr, char *asm_buf, int *err )
+{
+  struct opcode *      opc;
+  struct operand *     oper[ MAX_OPERANDS ];
+  unsigned long                instr;
+  unsigned long                param;
+  char *               ptr = asm_buf;
+  char                 scratch[ 20 ];
+  int                  i;
+  int                  w_operands = 0; /* wanted # of operands */
+  int                  n_operands = 0; /* # of operands read */
+  int                  asm_debug = 0;
+  /*------------------------------------------------------------*/
+
+  if( err )
+    *err = 0;
+  
+  if( get_word( &ptr, scratch ) == 0 )
+    return 0;
+
+  /* Lookup the opcode structure based on the opcode name */
+  if(( opc = find_opcode_by_name( scratch )) == (struct opcode *)0 ) {
+    if( err ) *err = E_ASM_BAD_OPCODE;
+    return 0;
+  }
+
+  if( asm_debug ) {
+    printf( "asmppc: Opcode = \"%s\"\n", opc->name );
+  }
+    
+  for( i = 0; i < 8; ++i ) {
+    if( opc->fields[ i ] == 0 )
+      break;
+    ++w_operands;
+  }
+
+  if( asm_debug ) {
+    printf( "asmppc: Expecting %d operands\n", w_operands );
+  }
+    
+  instr = opc->opcode;
+  
+  /* read each operand */
+  while( n_operands < w_operands ) {
+
+    oper[ n_operands ] = &operands[ opc->fields[ n_operands ] - 1 ];
+
+    if( oper[ n_operands ]->hint & OH_SILENT ) {
+      /* Skip silent operands, they are covered in opc->opcode */
+
+      if( asm_debug ) {
+       printf( "asmppc: Operand %d \"%s\" SILENT\n", n_operands,
+               oper[ n_operands ]->name );
+      }
+
+      ++n_operands;
+      continue;
+    }
+    
+    if( get_word( &ptr, scratch ) == 0 )
+      break;
+
+    if( asm_debug ) {
+      printf( "asmppc: Operand %d \"%s\" : \"%s\"\n", n_operands,
+             oper[ n_operands ]->name, scratch );
+    }
+
+    if(( param = parse_operand( memaddr, opc, oper[ n_operands ],
+                               scratch, err )) == 0 )
+      return 0;
+
+    instr |= param;
+    ++n_operands;
+  }
+
+  if( n_operands < w_operands ) {
+    if( err ) *err = E_ASM_NUM_OPERANDS;
+    return 0;
+  }
+
+  if( asm_debug ) {
+    printf( "asmppc: Instruction = 0x%08lx\n", instr );
+  }
+
+  return instr;
+} /* asmppc */
+
+
+\f
+/*======================================================================
+ * Called by the assembler to interpret a single operand
+ *
+ * Arguments:
+ *     ctx             A pointer to the disassembler context record.
+ *
+ * Returns 0 if the operand is ok, or -1 if it is bad.
+ */
+
+int parse_operand( unsigned long memaddr, struct opcode *opc,
+                  struct operand *oper, char *txt, int *err )
+{
+  long data;
+  long mask;
+  int  is_neg = 0;
+  /*------------------------------------------------------------*/
+
+  mask = (1 << oper->bits) - 1;
+
+  if( oper->hint & OH_ADDR ) {
+    data = read_number( txt );
+
+    if( opc->hint & H_RELATIVE )
+      data = data - memaddr;
+
+    if( data < 0 )
+      is_neg = 1;
+    
+    data >>= 2;
+    data &= (mask >> 1);
+
+    if( is_neg )
+      data |= 1 << (oper->bits - 1);
+  }
+
+  else if( oper->hint & OH_REG ) {
+    if( txt[ 0 ] == 'r' || txt[ 0 ] == 'R' )
+      txt++;
+    else if( txt[ 0 ] == '%' && ( txt[ 1 ] == 'r' || txt[ 1 ] == 'R' ))
+      txt += 2;
+
+    data = read_number( txt );
+    if( data > 31 ) {
+      if( err ) *err = E_ASM_BAD_REGISTER;
+      return 0;
+    }
+
+    data = htonl( data );
+  }
+
+  else if( oper->hint & OH_SPR ) {
+    if(( data = spr_value( txt )) == 0 ) {
+      if( err ) *err = E_ASM_BAD_SPR;
+      return 0;
+    }
+  }
+
+  else if( oper->hint & OH_TBR ) {
+    if(( data = tbr_value( txt )) == 0 ) {
+      if( err ) *err = E_ASM_BAD_TBR;
+      return 0;
+    }
+  }
+
+  else {
+    data = htonl( read_number( txt ));
+  }
+
+  return (data & mask) << oper->shift;
+} /* parse_operand */
+
+
+char *asm_error_str( int err )
+{
+  switch( err ) {
+  case E_ASM_BAD_OPCODE:       return "Bad opcode";
+  case E_ASM_NUM_OPERANDS:     return "Bad number of operands";
+  case E_ASM_BAD_REGISTER:     return "Bad register number";
+  case E_ASM_BAD_SPR:          return "Bad SPR name or number";
+  case E_ASM_BAD_TBR:          return "Bad TBR name or number";
+  }
+
+  return "";
+} /* asm_error_str */
+
+
+\f
+/*======================================================================
+ * Copy a word from one buffer to another, ignores leading white spaces.
+ *
+ * Arguments:
+ *     src             The address of a character pointer to the
+ *                     source buffer.
+ *     dest            A pointer to a character buffer to write the word
+ *                     into.
+ *
+ * Returns the number of non-white space characters copied, or zero.
+ */
+
+int get_word( char **src, char *dest )
+{
+  char *       ptr = *src;
+  int          nchars = 0;
+  /*------------------------------------------------------------*/
+
+  /* Eat white spaces */
+  while( *ptr && isblank( *ptr ))
+    ptr++;
+
+  if( *ptr == 0 ) {
+    *src = ptr;
+    return 0;
+  }
+  
+  /* Find the text of the word */
+  while( *ptr && !isblank( *ptr ))
+    dest[ nchars++ ] = *ptr++;
+  dest[ nchars ] = 0;
+
+  *src = ptr;
+  return nchars;
+} /* get_word */
+
+
+\f
+/*======================================================================
+ * Convert a numeric string to a number, be aware of base notations.
+ *
+ * Arguments:
+ *     txt             The numeric string.
+ *
+ * Returns the converted numeric value.
+ */
+
+long read_number( char *txt )
+{ 
+  long val;
+  int  is_neg = 0;
+  /*------------------------------------------------------------*/
+
+  if( txt == 0 || *txt == 0 )
+    return 0;
+
+  if( *txt == '-' ){
+    is_neg = 1;
+    ++txt;
+  }
+
+  if( txt[ 0 ] == '0' && ( txt[ 1 ] == 'x' || txt[ 1 ] == 'X' )) /* hex */
+    val = simple_strtoul( &txt[2], NULL, 16 );
+  else                                         /* decimal */
+    val = simple_strtoul( txt, NULL, 10 );
+
+  if( is_neg )
+    val = -val;
+  
+  return val;
+} /* read_number */
+
+
+int downstring( char *s )
+{
+  if( !s || !*s )
+    return 0;
+  
+  while( *s ) {
+    if( isupper( *s ))
+      *s = tolower( *s );
+    s++;
+  }
+
+  return 0;
+} /* downstring */
+
+
+\f
+/*======================================================================
+ * Examines the instruction at the current address and determines the
+ * next address to be executed.  This will take into account branches
+ * of different types so that a "step" and "next" operations can be
+ * supported.
+ *
+ * Arguments:
+ *     nextaddr        The address (to be filled in) of the next
+ *                     instruction to execute.  This will only be a valid
+ *                     address if TRUE is returned.
+ * 
+ *     step_over       A flag indicating how to compute addresses for
+ *                     branch statements:
+ *                      TRUE  = Step over the branch (next)
+ *                      FALSE = step into the branch (step)
+ *     
+ * Returns TRUE if it was able to compute the address.  Returns FALSE if
+ * it has a problem reading the current instruction or one of the registers.
+ */
+
+int find_next_address( unsigned char *nextaddr, int step_over,
+                       struct pt_regs *regs )
+{
+  unsigned long                pc;     /* SRR0 register from PPC */
+  unsigned long                ctr;    /* CTR register from PPC */
+  unsigned long                cr;     /* CR register from PPC */
+  unsigned long                lr;     /* LR register from PPC */
+  unsigned long                instr;  /* instruction at SRR0 */
+  unsigned long                next;   /* computed instruction for 'next' */
+  unsigned long                step;   /* computed instruction for 'step' */
+  unsigned long                addr = 0; /* target address operand */
+  unsigned long                aa = 0; /* AA operand */
+  unsigned long                lk = 0; /* LK operand */
+  unsigned long                bo = 0; /* BO operand */
+  unsigned long                bi = 0; /* BI operand */
+  struct opcode *      op = 0; /* opcode structure for 'instr' */
+  int                  ctr_ok = 0;
+  int                  cond_ok = 0;
+  int                  conditional = 0;
+  int                  branch = 0;
+  /*------------------------------------------------------------*/
+
+  if( nextaddr == 0 || regs == 0 )
+  {
+    printf( "find_next_address: bad args" );
+    return FALSE;
+  }
+  
+  pc = regs->nip & 0xfffffffc;
+  instr = INSTRUCTION( pc );
+
+  if(( op = find_opcode( instr )) == (struct opcode *)0 )
+  {
+    printf( "find_next_address: can't parse opcode 0x%lx", instr );
+    return FALSE;
+  }
+  
+  ctr = regs->ctr;
+  cr  = regs->ccr;
+  lr  = regs->link;
+  
+  switch( op->opcode )
+  {
+  case B_OPCODE(16,0,0):       /* bc */
+  case B_OPCODE(16,0,1):       /* bcl */
+  case B_OPCODE(16,1,0):       /* bca */
+  case B_OPCODE(16,1,1):       /* bcla */
+    if( !get_operand_value( op, instr, O_BD, &addr ) ||
+        !get_operand_value( op, instr, O_BO, &bo )   ||
+        !get_operand_value( op, instr, O_BI, &bi )   ||
+        !get_operand_value( op, instr, O_AA, &aa )   ||
+        !get_operand_value( op, instr, O_LK, &lk ))
+      return FALSE;
+
+    if(( addr & (1 << 13)) != 0 )
+      addr = addr - (1 << 14);
+    addr <<= 2;
+    conditional = 1;
+    branch = 1;
+    break;
+      
+  case I_OPCODE(18,0,0):       /* b */
+  case I_OPCODE(18,0,1):       /* bl */
+  case I_OPCODE(18,1,0):       /* ba */
+  case I_OPCODE(18,1,1):       /* bla */
+    if( !get_operand_value( op, instr, O_LI, &addr ) ||
+        !get_operand_value( op, instr, O_AA, &aa )   ||
+        !get_operand_value( op, instr, O_LK, &lk ))
+      return FALSE;
+
+    if(( addr & (1 << 23)) != 0 )
+      addr = addr - (1 << 24);
+    addr <<= 2;
+    conditional = 0;
+    branch = 1;
+    break;
+      
+  case XL_OPCODE(19,528,0):    /* bcctr */
+  case XL_OPCODE(19,528,1):    /* bcctrl */
+    if( !get_operand_value( op, instr, O_BO, &bo )   ||
+        !get_operand_value( op, instr, O_BI, &bi )   ||
+        !get_operand_value( op, instr, O_LK, &lk ))
+      return FALSE;
+
+    addr = ctr;
+    aa   = 1;
+    conditional = 1;
+    branch = 1;
+    break;
+      
+  case XL_OPCODE(19,16,0):     /* bclr */
+  case XL_OPCODE(19,16,1):     /* bclrl */
+    if( !get_operand_value( op, instr, O_BO, &bo )   ||
+        !get_operand_value( op, instr, O_BI, &bi )   ||
+        !get_operand_value( op, instr, O_LK, &lk ))
+      return FALSE;
+
+    addr = lr;
+    aa   = 1;
+    conditional = 1;
+    branch = 1;
+    break;
+      
+  default:
+    conditional = 0;
+    branch = 0;
+    break;
+  }
+
+  if( conditional )
+  {
+    switch((bo & 0x1e) >> 1 )
+    {
+    case 0:    /* 0000y */
+      if( --ctr != 0 )
+        ctr_ok = 1;
+
+      cond_ok = !(cr & (1 << (31 - bi)));
+      break;
+         
+    case 1: /* 0001y */
+      if( --ctr == 0 )
+        ctr_ok = 1;
+
+      cond_ok = !(cr & (1 << (31 - bi)));
+      break;
+         
+    case 2: /* 001zy */
+      ctr_ok = 1;
+      cond_ok = !(cr & (1 << (31 - bi)));
+      break;
+         
+    case 4: /* 0100y */
+      if( --ctr != 0 )
+        ctr_ok = 1;
+
+      cond_ok = cr & (1 << (31 - bi));
+      break;
+         
+    case 5: /* 0101y */
+      if( --ctr == 0 )
+        ctr_ok = 1;
+
+      cond_ok = cr & (1 << (31 - bi));
+      break;
+         
+    case 6: /* 011zy */
+      ctr_ok = 1;
+      cond_ok = cr & (1 << (31 - bi));
+      break;
+         
+    case 8: /* 1z00y */
+      if( --ctr != 0 )
+        ctr_ok = cond_ok = 1;
+      break;
+         
+    case 9: /* 1z01y */
+      if( --ctr == 0 )
+        ctr_ok = cond_ok = 1;
+      break;
+         
+    case 10: /* 1z1zz */
+      ctr_ok = cond_ok = 1;
+      break;
+    }
+  }
+  
+  if( branch && (!conditional || (ctr_ok && cond_ok)))
+  {
+    if( aa )
+      step = addr;
+    else
+      step = addr + pc;
+
+    if( lk )
+      next = pc + 4;
+    else
+      next = step;
+  }
+  else
+  {
+    step = next = pc + 4;
+  }
+
+  if( step_over == TRUE )
+    *(unsigned long *)nextaddr = next;
+  else
+    *(unsigned long *)nextaddr = step;
+
+  return TRUE;
+} /* find_next_address */
+
+
+/*
+ * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ * 
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
index 3ff007cb00f6d72ad99fb8bc916d2597d8477bc9..96e1941a5b14036526548282871ee96dbf078cd3 100644 (file)
@@ -40,6 +40,9 @@
 #if (CONFIG_COMMANDS & CFG_CMD_NET)
 #include <net.h>
 #endif
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#include <cmd_bedbug.h>
+#endif
 #ifdef CFG_ALLOC_DPRAM
 #include <commproc.h>
 #endif
@@ -600,6 +603,10 @@ void    board_init_r  (bd_t *bd, ulong dest_addr)
     ide_init(bd);
 #endif /* CFG_CMD_IDE */
 
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+    bedbug_init();
+#endif
+
 /** LEAVE THIS HERE **/
     /* Initialize devices */
     devices_init (reloc_off);
diff --git a/common/cmd_bedbug.c b/common/cmd_bedbug.c
new file mode 100644 (file)
index 0000000..ad1ac45
--- /dev/null
@@ -0,0 +1,653 @@
+/*
+ * BedBug Functions
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <net.h>
+
+#include <cmd_bedbug.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+#include <bedbug/elf.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+extern void show_regs __P((struct pt_regs*));
+extern int  run_command __P((const char*,bd_t*,int));
+extern char console_buffer[];
+
+ulong        dis_last_addr = 0;        /* Last address disassembled   */
+ulong        dis_last_len = 20;        /* Default disassembler length */
+CPU_DEBUG_CTX bug_ctx;                  /* Bedbug context structure    */
+
+\f
+/* ======================================================================
+ * PPCBOOT's puts function does not append a newline, so the bedbug stuff
+ * will use this for the output of the dis/assembler.                    
+ * ====================================================================== */
+
+int bedbug_puts(const char *str)
+{
+  /* -------------------------------------------------- */
+
+  printf( "%s\r\n", str );
+  return 0;
+} /* bedbug_puts */
+
+
+\f
+/* ======================================================================
+ * Initialize the bug_ctx structure used by the bedbug debugger.  This is
+ * specific to the CPU since each has different debug registers and
+ * settings.
+ * ====================================================================== */
+
+void bedbug_init( void )
+{
+  /* -------------------------------------------------- */
+
+#if defined(CONFIG_PPC405)
+  void bedbug405_init( void );
+  
+  bedbug405_init();
+#endif
+
+  return;
+} /* bedbug_init */
+
+
+\f
+/* ======================================================================
+ * Entry point from the interpreter to the disassembler.  Repeated calls
+ * will resume from the last disassembled address.
+ * ====================================================================== */
+
+void do_bedbug_dis (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+                   char *argv[])
+{
+  ulong        addr;   /* Address to start disassembly from    */
+  ulong        len;    /* # of instructions to disassemble     */
+  /* -------------------------------------------------- */
+
+  /* Setup to go from the last address if none is given */
+  addr = dis_last_addr;
+  len  = dis_last_len;
+    
+  if (argc < 2)
+  {
+    printf ("Usage:\n%s\n", cmdtp->usage);
+    return;
+  }
+    
+  if(( flag & CMD_FLAG_REPEAT ) == 0 )
+  {
+    /* New command */
+    addr = simple_strtoul( argv[1], NULL, 16 );
+
+    /* If an extra param is given then it is the length */
+    if( argc > 2 )
+      len = simple_strtoul( argv[2], NULL, 16 );
+  }
+
+  /* Run the disassembler */
+  disppc( (unsigned char *)addr, 0, len, bedbug_puts, F_RADHEX );
+
+  dis_last_addr = addr + (len * 4);
+  dis_last_len = len;
+} /* do_bedbug_dis */
+
+
+\f
+/* ======================================================================
+ * Entry point from the interpreter to the assembler.  Assembles
+ * instructions in consecutive memory locations until a '.' (period) is
+ * entered on a line by itself.
+ * ====================================================================== */
+
+void do_bedbug_asm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+                   char *argv[])
+{
+  long         mem_addr;               /* Address to assemble into     */
+  unsigned long instr;                  /* Machine code for text        */
+  char         prompt[ 15 ];           /* Prompt string for user input */
+  int          asm_err;                /* Error code from the assembler*/
+  /* -------------------------------------------------- */
+               
+  if (argc < 2)
+  {
+    printf ("Usage:\n%s\n", cmdtp->usage);
+    return;
+  }
+    
+  printf( "\nEnter '.' when done\n" );
+  mem_addr = simple_strtoul( argv[ 1 ], NULL, 16 );
+
+  while( 1 )
+  {
+    putc( '\n' );
+    disppc( (unsigned char *)mem_addr, 0, 1, bedbug_puts, F_RADHEX );
+
+    sprintf( prompt, "%08lx:    ", mem_addr );
+    readline( prompt );
+
+    if( console_buffer[ 0 ] && strcmp( console_buffer, "." ))
+    {
+      if(( instr = asmppc( mem_addr, console_buffer, &asm_err )) != 0 )
+      {
+       *(unsigned long *)mem_addr = instr;
+       mem_addr += 4;
+      }
+      else
+      {
+       printf( "*** Error: %s ***\n", asm_error_str( asm_err ));
+      }
+    }
+    else
+    {
+      break;
+    }
+  }
+} /* do_bedbug_asm */
+
+
+\f
+/* ======================================================================
+ * Used to set a break point from the interpreter.  Simply calls into the
+ * CPU-specific break point set routine.
+ * ====================================================================== */
+
+void do_bedbug_break (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+                      char *argv[])
+{
+  /* -------------------------------------------------- */
+
+  if( bug_ctx.do_break )
+    (*bug_ctx.do_break)( cmdtp, bd, flag, argc, argv );
+} /* do_bedbug_break */
+
+
+\f
+/* ======================================================================
+ * Called from the debug interrupt routine.  Simply calls the CPU-specific
+ * breakpoint handling routine.
+ * ====================================================================== */
+
+void do_bedbug_breakpoint( struct pt_regs *regs )
+{
+  /* -------------------------------------------------- */
+
+  if( bug_ctx.break_isr )
+    (*bug_ctx.break_isr)( regs );
+} /* do_bedbug_breakpoint */
+
+
+\f
+/* ======================================================================
+ * Called from the CPU-specific breakpoint handling routine.  Enter a
+ * mini main loop until the stopped flag is cleared from the breakpoint
+ * context.
+ *
+ * This handles the parts of the debugger that are common to all CPU's.
+ * ====================================================================== */
+
+void bedbug_main_loop( unsigned long addr, struct pt_regs *regs )
+{
+  int          len;                    /* Length of command line */
+  int           flag;                   /* Command flags          */
+  int           rc;                     /* Result from run_command*/
+  char          prompt_str[ 20 ];       /* Prompt string          */
+  static char   lastcommand[ CFG_CBSIZE ] = {0}; /* previous command */
+  /* -------------------------------------------------- */
+
+  if( bug_ctx.clear )
+    (*bug_ctx.clear)( bug_ctx.current_bp );
+  
+  printf( "Breakpoint %d: ", bug_ctx.current_bp );
+  disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+
+  bug_ctx.stopped = 1;
+  bug_ctx.regs = regs;
+
+  sprintf( prompt_str, "BEDBUG.%d =>", bug_ctx.current_bp );
+
+  /* A miniature main loop */
+  while( bug_ctx.stopped )
+  {
+    len = readline( prompt_str );
+    
+    flag = 0;  /* assume no special flags for now */
+
+    if (len > 0)
+      strcpy( lastcommand, console_buffer );
+    else if( len == 0 )
+      flag |= CMD_FLAG_REPEAT;
+
+    if (len == -1)
+      printf ("<INTERRUPT>\n");
+    else
+      rc = run_command( lastcommand, bug_ctx.bd, flag );
+
+    if (rc <= 0) {
+      /* invalid command or not repeatable, forget it */
+      lastcommand[0] = 0;
+    }
+  }
+
+  bug_ctx.regs = NULL;
+  bug_ctx.current_bp = 0;
+
+  return;
+} /* bedbug_main_loop */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to continue from a breakpoint.  Just clears the
+ * stopped flag in the context so that the breakpoint routine will
+ * return.
+ * ====================================================================== */
+
+void do_bedbug_continue (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+                         char *argv[])
+{
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return;
+  }
+  
+  bug_ctx.stopped = 0;
+  return;
+} /* do_bedbug_continue */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to continue to the next instruction, stepping into
+ * subroutines.  Works by calling the find_next_addr() routine to compute
+ * the address passes control to the CPU-specific set breakpoint routine
+ * for the current breakpoint number.
+ * ====================================================================== */
+
+void do_bedbug_step (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+                     char *argv[])
+{
+  unsigned long addr;   /* Address to stop at */
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return;
+  }
+
+  if( !find_next_address( (unsigned char *)&addr, FALSE, bug_ctx.regs ))
+    return;
+
+  if( bug_ctx.set )
+    (*bug_ctx.set)( bug_ctx.current_bp, addr );
+  
+  bug_ctx.stopped = 0;
+  return;
+} /* do_bedbug_step */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to continue to the next instruction, stepping over
+ * subroutines.  Works by calling the find_next_addr() routine to compute
+ * the address passes control to the CPU-specific set breakpoint routine
+ * for the current breakpoint number.
+ * ====================================================================== */
+
+void do_bedbug_next (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+                     char *argv[])
+{
+  unsigned long addr;   /* Address to stop at */
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return;
+  }
+
+  if( !find_next_address( (unsigned char *)&addr, TRUE, bug_ctx.regs ))
+    return;
+
+  if( bug_ctx.set )
+    (*bug_ctx.set)( bug_ctx.current_bp, addr );
+
+  bug_ctx.stopped = 0;
+  return;
+} /* do_bedbug_next */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to print the current stack.  This assumes an EABI
+ * architecture, so it starts with GPR R1 and works back up the stack.
+ * ====================================================================== */
+
+void do_bedbug_stack (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+                      char *argv[])
+{
+  unsigned long sp;             /* Stack pointer                */
+  unsigned long func;           /* LR from stack                */
+  int           depth;          /* Stack iteration level        */
+  int           skip = 1;       /* Flag to skip the first entry */
+  unsigned long top;            /* Top of memory address        */
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return;
+  }
+
+  top = bd->bi_memstart + bd->bi_memsize;
+  depth = 0;
+
+  printf( "Depth     PC\n" );
+  printf( "-----  --------\n" );
+  printf( "%5d  %08lx\n", depth++, bug_ctx.regs->nip );
+
+  sp = bug_ctx.regs->gpr[ 1 ];
+  func = *(unsigned long *)(sp+4);
+
+  while(( func < top ) && ( sp < top ))
+  {
+    if( !skip )
+      printf( "%5d  %08lx\n", depth++, func );
+    else
+      --skip;
+    
+    sp = *(unsigned long *)sp;
+    func = *(unsigned long *)(sp+4);
+  }
+
+  return;
+} /* do_bedbug_stack */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to dump the registers.  Calls the CPU-specific
+ * show registers routine.
+ * ====================================================================== */
+
+void do_bedbug_rdump (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+                      char *argv[])
+{
+  /* -------------------------------------------------- */
+
+  if( ! bug_ctx.stopped )
+  {
+    printf( "Not at a breakpoint\n" );
+    return;
+  }
+
+  show_regs( bug_ctx.regs );
+  return;
+} /* do_bedbug_rdump */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to boot an arbitrary ELF image from memory.
+ * ====================================================================== */
+
+void do_bootelf( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
+{
+  unsigned long        addr;   /* Address of the ELF image     */
+  unsigned long        rc;     /* Return value from user code  */
+  /* -------------------------------------------------- */
+
+  if (argc < 2)
+    addr = load_addr;
+  else
+    addr = simple_strtoul( argv[ 1 ], NULL, 16 );
+
+  if( ! valid_elf_image( addr ))
+    return;
+  
+  addr = load_elf_image( addr );
+
+  printf ("## Starting application at 0x%08lx ...\n", addr);
+
+  /*
+   * pass address parameter as argv[0] (aka command name),
+   * and all remaining args
+   */
+  rc = ((ulong (*)(bd_t *, int, char *[]))addr) (bd, --argc, &argv[1]);
+
+  printf ("## Application terminated, rc = 0x%lx\n", rc);
+} /* do_bootelf */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to boot VxWorks from a memory image.  The image can
+ * be either an ELF image or a raw binary.  Will attempt to setup the
+ * bootline and other parameters correctly.
+ * ====================================================================== */
+
+void do_bootvx( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
+{
+  unsigned long        addr;                   /* Address of image            */
+  unsigned long        bootaddr;               /* Address to put the bootline */
+  char *       bootline;               /* Text of the bootline        */
+  char *       tmp;                    /* Temporary char pointer      */
+#if defined(CONFIG_PPC405)
+  char          build_buf[ 80 ];        /* Buffer for building the bootline */
+#endif
+  /* -------------------------------------------------- */
+
+  /* Check the loadaddr variable.  If we don't know where the image is
+     then we're done. */
+  
+  if(( tmp = getenv( "loadaddr" )) != NULL )
+  {
+    addr = simple_strtoul( tmp, NULL, 16 );
+  }
+  else
+  {
+    printf( "No load address provided\n" );
+    return;
+  }
+
+  /* Check to see if we need to tftp the image ourselves before starting */
+  
+  if(( argc == 2 ) && ( strcmp( argv[ 1 ], "tftp" ) == 0 ))
+  {
+    if( NetLoop( bd, TFTP ) == 0 )
+      return;
+
+    printf( "Automatic boot of VxWorks image at address 0x%08lx ... \n",
+            addr );
+  }
+
+  /* This should equate to NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
+     from the VxWorks BSP header files.  This will vary from board to board */
+
+#if defined(CONFIG_WALNUT405)
+  tmp = (char *)CFG_NVRAM_BASE_ADDR + 0x500;
+  memcpy( (char *)tmp, (char *)&bd->bi_enetaddr[3], 3 );
+#else
+  printf( "## Ethernet MAC address not copied to NV RAM\n" );
+#endif
+  
+  /* Use bootaddr to find the location in memory that VxWorks will
+     look for the bootline string.  The default value for PowerPC
+     is LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET which defaults
+     to 0x4200 */
+  
+  if(( tmp = getenv( "bootaddr" )) == NULL )
+    bootaddr = 0x4200;
+  else
+    bootaddr = simple_strtoul( tmp, NULL, 16 );
+
+  /* Check to see if the bootline is defined in the 'bootargs' parameter.
+     If it is not defined, we may be able to construct the info */
+  
+  if(( bootline = getenv( "bootargs" )) != NULL )
+  {
+    memcpy( (void *)bootaddr, bootline, MAX( strlen( bootline ), 255 ));
+  }
+  else
+  {
+#if defined(CONFIG_PPC405)
+    sprintf( build_buf, "ibmEmac(0,0)" );
+
+    if(( tmp = getenv( "hostname" )) != NULL )
+    {
+      sprintf( &build_buf[ strlen( build_buf - 1 ) ], "host:%s ", tmp );
+    }
+    else
+    {
+      sprintf( &build_buf[ strlen( build_buf - 1 ) ], ": " );
+    }
+
+    if(( tmp = getenv( "ipaddr" )) != NULL )
+    {
+      sprintf( &build_buf[ strlen( build_buf - 1 ) ], "e=%s ", tmp );
+    }
+#else
+
+    /* I'm not sure what the device should be for other
+       PPC flavors, the hostname and ipaddr should be ok to just copy */
+    
+    printf( "No bootargs defined\n" );
+    return;
+#endif
+  }
+
+  /* If the data at the load address is an elf image, then treat it like
+     an elf image.  Otherwise, assume that it is a binary image */
+  
+  if( valid_elf_image( addr ))
+  {
+    addr = load_elf_image( addr );
+  }
+  else
+  {
+    printf( "## Not an ELF image, assuming binary\n" );
+    /* leave addr as load_addr */
+  }
+
+  printf ("## Starting vxWorks at 0x%08lx ...\n", addr);
+
+  ((void (*)(void))addr)();
+
+  printf ("## vxWorks terminated\n" );
+} /* do_bootvx */
+
+
+\f
+/* ======================================================================
+ * Determine if a valid ELF image exists at the given memory location.
+ * First looks at the ELF header magic field, the makes sure that it is
+ * executable and makes sure that it is for a PowerPC.
+ * ====================================================================== */
+
+int valid_elf_image( unsigned long addr )
+{
+  Elf32_Ehdr * ehdr;   /* Elf header structure pointer */
+  /* -------------------------------------------------- */
+
+  ehdr = (Elf32_Ehdr *)addr;
+
+  if( ! IS_ELF( *ehdr )) {
+    printf( "## No elf image at address 0x%08lx\n", addr );
+    return 0;
+  }
+
+  if( ehdr->e_type != ET_EXEC ) {
+    printf( "## Not a 32-bit elf image at address 0x%08lx\n", addr );
+    return 0;
+  }
+
+  if( ehdr->e_machine != EM_PPC ) {
+    printf( "## Not a PowerPC elf image at address 0x%08lx\n", addr );
+    return 0;
+  }
+
+  return 1;
+} /* valid_elf_image */
+
+
+\f
+/* ======================================================================
+ * A very simple elf loader, assumes the image is valid, returns the
+ * entry point address.
+ * ====================================================================== */
+
+unsigned long load_elf_image( unsigned long addr )
+{
+  Elf32_Ehdr *         ehdr;           /* Elf header structure pointer     */
+  Elf32_Shdr *         shdr;           /* Section header structure pointer */
+  unsigned char *      strtab = 0;     /* String table pointer             */
+  unsigned char *      image;          /* Binary image pointer             */
+  int                  i;              /* Loop counter                     */
+  /* -------------------------------------------------- */
+  
+  ehdr = (Elf32_Ehdr *)addr;
+
+  /* Find the section header string table for output info */
+  shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
+                       (ehdr->e_shstrndx * sizeof( Elf32_Shdr )));
+  
+  if( shdr->sh_type == SHT_STRTAB )
+    strtab = ( unsigned char *)(addr + shdr->sh_offset);
+
+  /* Load each appropriate section */
+  for( i = 0; i < ehdr->e_shnum; ++i ) {
+    shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + (i * sizeof( Elf32_Shdr )));
+
+    if( !( shdr->sh_flags & SHF_ALLOC )
+       || shdr->sh_type == SHT_NOBITS
+       || shdr->sh_addr == 0
+       || shdr->sh_size == 0 )
+      continue;
+
+    if( strtab ) {
+      printf( "Loading %s @ 0x%08lx (%ld bytes)\n",
+             &strtab[ shdr->sh_name ], (unsigned long)shdr->sh_addr,
+              (long)shdr->sh_size );
+    }
+    
+    image = (unsigned char *)addr + shdr->sh_offset;
+    memcpy( (void *)shdr->sh_addr, (const void *)image, shdr->sh_size );
+  }
+
+  return ehdr->e_entry;
+} /* load_elf_image */
+
+
+/* ====================================================================== */
+#endif /* CFG_CMD_BEDBUG */
+
+
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ * 
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
index 10c36750678105419b8f3cc0b4cf0757e626628b..78260666aeb00bbc63daa0ea6185f3c833075f04 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000
+ * (C) Copyright 2000, 2001
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * See file CREDITS for list of people who contributed to this
@@ -49,7 +49,15 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
     unsigned char i2c_addr, sec_addr, *data_addr;
     unsigned short size;
     int speed;
+    
+    
+
+#if !defined(CONFIG_CPCI405) && !defined(CONFIG_AR405) && \
+    !defined (CONFIG_WALNUT405) && !defined (CONFIG_ERIC)
+
     i2c_state_t state;
+#endif
+
     int rc;
 
     switch (argc) {
@@ -61,7 +69,12 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
     case 2:
        if (strncmp (argv[1], "res", 3) == 0) {
            printf ("I2C reset 50kHz ... ");
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+           i2c_init ();
+#else
            i2c_init (50000, 0xfe);     /* use all one's as slave address */
+#endif
            printf ("DONE\n");
            return;
        }
@@ -74,7 +87,12 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                printf ("I2C reset %d.%03dkHz ... ", speed/1000, speed%1000);
            else
                printf ("I2C reset %dkHz ... ", speed/1000);
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+           i2c_init ();
+#else
            i2c_init (speed, 0xfe);     /* use all one's as slave address */
+#endif
            printf ("DONE\n");
            return;
        }
@@ -84,7 +102,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
        break;
 
     case 5:
-       if (strcmp(argv[1], "recv") == 0) {
+       if (strncmp(argv[1], "recv", 4) == 0) {
                i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
                data_addr = (unsigned char *)simple_strtoul(argv[3], NULL, 16);
                size = (unsigned short)simple_strtoul(argv[4], NULL, 16);
@@ -96,17 +114,39 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 #endif
                        , i2c_addr, (ulong)data_addr, size);
 
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
                i2c_newio (&state);
+#endif
+
+
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+               rc = i2c_receive (i2c_addr, size, data_addr);
+#else
 
                rc = i2c_receive (&state, i2c_addr, 0,
                                  I2CF_START_COND|I2CF_STOP_COND,
                                  size, data_addr);
+#endif
+
+
                if (rc) {
                    printf ("i2c_receive FAILED rc=%d\n", rc);
                    return;
                }
 
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
+
                rc = i2c_doio (&state);
+#endif
+
                if (rc) {
                    printf ("i2c_doio FAILED rc=%d\n", rc);
                    return;
@@ -114,7 +154,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 
                printf ("DONE\n");
                return;
-       } else if (strcmp(argv[1], "send") == 0) {
+       } else if (strncmp(argv[1], "send",4) == 0) {
                i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
                data_addr = (unsigned char *)simple_strtoul(argv[3], NULL, 16);
                size = (unsigned short)simple_strtoul(argv[4], NULL, 16);
@@ -122,16 +162,36 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                printf ("I2C send: i2c_addr 0x%02x, data_addr 0x%08lx, "
                        "size %u ... ", i2c_addr, (ulong)data_addr, size);
 
+
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
                i2c_newio (&state);
+#endif
+
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+               rc = i2c_send (i2c_addr, size, data_addr);
+#else
 
                rc = i2c_send (&state, i2c_addr, 0,
                    I2CF_START_COND|I2CF_STOP_COND, size, data_addr);
+#endif
                if (rc) {
                    printf ("i2c_receive FAILED rc=%d\n", rc);
                    return;
                }
 
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
+
                rc = i2c_doio (&state);
+#endif
+
                if (rc) {
                    printf ("i2c_doio FAILED rc=%d\n", rc);
                    return;
@@ -143,7 +203,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
        break;
 
     case 6:
-       if (strcmp(argv[1], "rcvs") == 0) {
+       if (strncmp(argv[1], "rcvs", 4) == 0) {
                i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
                sec_addr = (unsigned char)simple_strtoul(argv[3], NULL, 16);
                data_addr = (unsigned char *)simple_strtoul(argv[4], NULL, 16);
@@ -153,17 +213,37 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                        "data_addr 0x%08lx, size %u ... ",
                        i2c_addr, sec_addr, (ulong)data_addr, size);
 
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
                i2c_newio (&state);
+#endif
+
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+               rc = i2c_receive (i2c_addr, size, data_addr);
+#else
 
                rc = i2c_receive (&state, i2c_addr, sec_addr,
                    I2CF_ENABLE_SECONDARY|I2CF_START_COND|I2CF_STOP_COND,
                    size, data_addr);
+#endif
+
                if (rc) {
                    printf ("i2c_receive FAILED rc=%d\n", rc);
                    return;
                }
 
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
+
                rc = i2c_doio (&state);
+#endif
+
                if (rc) {
                    printf ("i2c_doio FAILED rc=%d\n", rc);
                    return;
@@ -172,7 +252,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                printf ("DONE\n");
                return;
        }
-       else if (strcmp(argv[1], "snds") == 0) {
+       else if (strncmp(argv[1], "snds",4) == 0) {
                i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
                sec_addr = (unsigned char)simple_strtoul(argv[3], NULL, 16);
                data_addr = (unsigned char *)simple_strtoul(argv[4], NULL, 16);
@@ -182,17 +262,36 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                        "data_addr 0x%08lx, size %u ... ",
                        i2c_addr, sec_addr, (ulong)data_addr, size);
 
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
                i2c_newio (&state);
+#endif
 
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+               rc = i2c_send (i2c_addr, size, data_addr);
+#else
                rc = i2c_send (&state, i2c_addr, sec_addr,
                    I2CF_ENABLE_SECONDARY|I2CF_START_COND|I2CF_STOP_COND,
                    size, data_addr);
+#endif
+
                if (rc) {
                    printf ("i2c_send FAILED rc=%d\n", rc);
                    return;
                }
 
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
+
                rc = i2c_doio (&state);
+#endif
+
                if (rc) {
                    printf ("i2c_doio FAILED rc=%d\n", rc);
                    return;
index 6e2e277e39144d39acc88c34c13ae812c226b504..ca902c05bb92605c0010d1d6f817b7be66dff6d8 100644 (file)
@@ -728,27 +728,30 @@ void do_saveenv  (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 {
        int len, rc;
        ulong end_addr;
-       uchar *flash_offset;
        uchar *flash_sect_addr;
 #if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
-
-       uchar env_buffer[CFG_ENV_SECT_SIZE];
+       uchar *flash_offset;
+       uchar  env_buffer[CFG_ENV_SECT_SIZE];
 #else
        uchar *env_buffer = (char *)env_ptr;
 #endif /* CFG_ENV_SECT_SIZE */
 
-       flash_offset = (uchar *)(((unsigned long)flash_addr) & (CFG_ENV_SECT_SIZE-1));
-       flash_sect_addr = (uchar *)(((unsigned long)flash_addr) & ~(CFG_ENV_SECT_SIZE-1));
 #if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
 
+       flash_offset    = (uchar *)(((ulong)flash_addr) &  (CFG_ENV_SECT_SIZE-1));
+       flash_sect_addr = (uchar *)(((ulong)flash_addr) & ~(CFG_ENV_SECT_SIZE-1));
+
        /* copy old contents to temporary buffer */
-       memcpy(env_buffer, flash_sect_addr, CFG_ENV_SECT_SIZE);
+       memcpy (env_buffer, flash_sect_addr, CFG_ENV_SECT_SIZE);
 
        /* copy current environment to temporary buffer */
-       memcpy((uchar *)((unsigned long)env_buffer + (unsigned long)flash_offset), env_ptr, CFG_ENV_SIZE);
+       memcpy ((uchar *)((unsigned long)env_buffer + (unsigned long)flash_offset),
+               env_ptr,
+               CFG_ENV_SIZE);
 
        len      = CFG_ENV_SECT_SIZE;
 #else
+       flash_sect_addr = flash_addr;
        len      = CFG_ENV_SIZE;
 # endif        /* CFG_ENV_SECT_SIZE */
 
index 5c10a9070754a7d610505db803616c56a1102303..544768641bce37405ad4c65569ff422d0c834b7e 100644 (file)
@@ -53,6 +53,8 @@
 #include <board/hymod/cmd_fpga.h>
 #endif
 
+#include <cmd_bedbug.h>
+
 /*
  * HELP command
  */
@@ -188,6 +190,10 @@ cmd_tbl_t *find_cmd(const char *cmd)
 cmd_tbl_t cmd_tbl[] = {
        CMD_TBL_GO
        CMD_TBL_RUN
+
+        CMD_TBL_BOOTELF
+        CMD_TBL_BOOTVX
+
        CMD_TBL_BOOTM
        CMD_TBL_BOOTP
        CMD_TBL_TFTPB
@@ -258,6 +264,15 @@ cmd_tbl_t cmd_tbl[] = {
        CMD_TBL_HELP
        CMD_TBL_QUES
 
+        CMD_TBL_DIS
+        CMD_TBL_ASM
+        CMD_TBL_BREAK
+        CMD_TBL_STACK
+        CMD_TBL_CONTINUE
+        CMD_TBL_STEP
+        CMD_TBL_NEXT
+        CMD_TBL_RDUMP
+        
        /* the following entry terminates this table */
        MK_CMD_TBL_ENTRY( NULL, 0, 0, 0, NULL, NULL, NULL )
 };
index b013d571381b6861366f81277833a63749d38314..5be5f993094299fab6babaea07429d13b0c341ef 100644 (file)
@@ -27,7 +27,7 @@ LIB   = lib$(CPU).a
 
 START  = start.o kgdb.o
 OBJS   = traps.o serial_smc.o serial_scc.o cpu.o cpu_init.o speed.o \
-         interrupts.o ether_scc.o ether_fcc.o i2c.o commproc.o
+         interrupts.o ether_scc.o ether_fcc.o i2c.o commproc.o soft_i2c.o
 
 all:   .depend $(START) $(LIB)
 
index 9b5f67b96d24938412575d75e86b0f2fb114164b..492b67f3b771ee0b57a6c145b747a9c584843851 100644 (file)
@@ -70,7 +70,6 @@
 #if defined(CONFIG_RPXSUPER)
 #error "on RPX Super ethernet must be FCC3"
 #endif
-
 #elif (CONFIG_ETHER_INDEX == 2)
 
 #define PROFF_ENET             PROFF_FCC2
 #if defined(CONFIG_RPXSUPER)
 #error "on RPX Super ethernet must be FCC3"
 #endif
+#if defined(CONFIG_TQM8260)
+/* 
+ * Attention: this is board-specific
+ * - Rx-CLK is CLK13
+ * - Tx-CLK is CLK14
+ * - RAM for BD/Buffers is on the 60x Bus (see 28-13)
+ * - Enable Full Duplex in FSMR
+ */
+#define CMXFCR_MASK            (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK)
+#define CMXFCR_VALUE           (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14)
+#define CPMFCR_RAMTYPE         0
+#define FCC_PSMR               (FCC_PSMR_FDE|FCC_PSMR_LPB)
+#endif
 
 #elif (CONFIG_ETHER_INDEX == 3)
 
index ef47605ad5713a3fe12978c71030010d85c338e7..55129991a89769e198bd78497d0f85fa384693c9 100644 (file)
                                 CMXSCR_TS1CS_CLK12)
 #  endif
 
+#  if defined(CONFIG_TQM8260)
+/*
+ *  Attention: This is board specific
+ *  - RX clk is CLK11
+ *  - TX clk is CLK12
+ */
+#    define CMXSCR_VALUE       (CMXSCR_RS1CS_CLK11  |\
+                                CMXSCR_TS1CS_CLK12)
+#  endif
+
 #elif (CONFIG_ETHER_INDEX == 2)
 #  define PROFF_ENET            PROFF_SCC2
 #  define CPM_CR_ENET_PAGE      CPM_CR_SCC2_PAGE
@@ -208,7 +218,7 @@ int eth_init(bd_t *bis)
 
     /* 24.21 - (4,5): connect SCC's tx and rx clocks, use NMSI for SCC */
     immr->im_cpmux.cmx_uar = 0;
-    immr->im_cpmux.cmx_scr = ( (immr->im_cpmux.cmx_fcr & ~CMXSCR_MASK) |
+    immr->im_cpmux.cmx_scr = ( (immr->im_cpmux.cmx_scr & ~CMXSCR_MASK) |
                                CMXSCR_VALUE);
 
 
diff --git a/cpu/mpc8260/soft_i2c.c b/cpu/mpc8260/soft_i2c.c
new file mode 100644 (file)
index 0000000..882483b
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * (C) Copyright 2001
+ * 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 <asm/cpm_8260.h>
+#include <i2c.h>
+
+#if defined(CONFIG_SOFT_I2C)
+
+/*-----------------------------------------------------------------------
+ * Set default values
+ */
+#ifndef        CFG_I2C_SPEED
+#define        CFG_I2C_SPEED   50000
+#endif
+
+#ifndef        CFG_I2C_SLAVE
+#define        CFG_I2C_SLAVE   0xFE
+#endif
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+/* TQM8260 Rev.100 has the clock and data pins swapped (!!!) on EEPROM
+ */
+#if CONFIG_TQM8260<=100
+#define        PD_SCL          0x00010000      /* PD 15 */
+#define PD_SDA         0x00020000      /* PD 14 */
+#else
+#define        PD_SCL          0x00020000      /* PD 14 */
+#define PD_SDA         0x00010000      /* PD 15 */
+#endif
+
+#define I2C_ACK                0               /* PD_SDA level to ack a byte */
+#define I2C_NOACK      1               /* PD_SDA level to noack a byte */
+
+#define        SET_PD_BIT(bit) do {                                            \
+                       immr->im_ioport.iop_pdird |=  bit;/* output */  \
+                       immr->im_ioport.iop_pdatd |=  bit;/* set  1 */  \
+                       udelay (5);                                     \
+               } while (0)
+
+#define RESET_PD_BIT(bit) do {                                         \
+                       immr->im_ioport.iop_pdird |=  bit;/* output */  \
+                       immr->im_ioport.iop_pdatd &= ~bit;/* set  0 */  \
+                       udelay (5);                                     \
+               } while (0)
+
+#define RESET_PD_BIT1(bit) do {                                                \
+                       immr->im_ioport.iop_pdird |=  bit;/* output */  \
+                       immr->im_ioport.iop_pdatd &= ~bit;/* set  0 */  \
+                       udelay (1);                                     \
+               } while (0)
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static void send_start (void);
+static void send_stop  (void);
+static void send_ack   (int);
+static void rcv_ack    (void);
+static void send_data_1        (void);
+static void send_data_0        (void);
+static void read_addr  (uchar addr);
+static void write_addr (uchar addr);
+static int  read_bit   (void);
+static uchar read_byte (int);
+static void write_byte (uchar byte);
+
+/*-----------------------------------------------------------------------
+ * START: High -> Low on SDA while SCL is High
+ */
+static void send_start (void)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+       SET_PD_BIT   (PD_SCL);
+       RESET_PD_BIT (PD_SDA);
+}
+
+/*-----------------------------------------------------------------------
+ * STOP: Low -> High on SDA while SCL is High
+ */
+static void send_stop (void)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+       RESET_PD_BIT (PD_SDA);
+       SET_PD_BIT   (PD_SCL);
+       SET_PD_BIT   (PD_SDA);
+       udelay (5);
+}
+
+/*-----------------------------------------------------------------------
+ * ack should be I2C_ACK or I2C_NOACK
+ */
+static void send_ack (int ack)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+       RESET_PD_BIT (PD_SCL);
+       if (ack == I2C_ACK)
+               RESET_PD_BIT (PD_SDA);
+       else
+               SET_PD_BIT   (PD_SDA);
+       SET_PD_BIT   (PD_SCL);
+       udelay (5);
+       RESET_PD_BIT (PD_SCL);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void rcv_ack (void)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+       RESET_PD_BIT (PD_SCL);
+
+       immr->im_ioport.iop_pdird &= ~PD_SDA;   /* input */
+       udelay (10);
+       while (immr->im_ioport.iop_pdatd & PD_SDA)
+               ;
+       udelay (5);
+       SET_PD_BIT   (PD_SCL);
+       RESET_PD_BIT (PD_SCL);
+       SET_PD_BIT   (PD_SDA);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void send_data_1 (void)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+       RESET_PD_BIT1(PD_SCL);
+       SET_PD_BIT   (PD_SDA);
+       SET_PD_BIT   (PD_SCL);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void send_data_0 (void)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+       RESET_PD_BIT1(PD_SCL);
+       RESET_PD_BIT (PD_SDA);
+       SET_PD_BIT   (PD_SCL);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+static void read_addr (uchar addr)
+{
+       int i;
+
+       addr = (addr << 1) | 0x01;
+
+       for (i=0; i<8; ++i) {
+               if (addr & 0x80) {
+                       send_data_1 ();
+               } else {
+                       send_data_0 ();
+               }
+               addr <<= 1;
+       }
+
+       rcv_ack ();
+}
+
+/*-----------------------------------------------------------------------
+ * addr & 0xF0 -> Device Identifier
+ * addr & 0x0E -> bank_num or device address << 1
+ * addr & 0x01 -> 1 = read, 0 = write
+ */
+static void write_addr (uchar addr)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+       addr <<= 1;
+
+       for (;;) {
+               uchar a = addr;
+               uint i;
+
+               send_start ();
+
+               for (i=0; i<8; ++i) {
+                       if (a & 0x80) {
+                               send_data_1 ();
+                       } else {
+                               send_data_0 ();
+                       }
+                       a <<= 1;
+               }
+
+               RESET_PD_BIT (PD_SCL);
+
+               immr->im_ioport.iop_pdird &= ~PD_SDA;   /* input */
+               udelay (10);
+
+               i = immr->im_ioport.iop_pdatd;
+               udelay (5);
+               SET_PD_BIT   (PD_SCL);
+               RESET_PD_BIT (PD_SCL);
+               SET_PD_BIT   (PD_SDA);
+
+               if ((i & PD_SDA) == 0)
+                       break;
+               
+               send_stop();
+       }
+}
+
+/*-----------------------------------------------------------------------
+ */
+static int read_bit (void)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+       int bit;
+
+       RESET_PD_BIT (PD_SCL);
+       SET_PD_BIT   (PD_SCL);
+       bit = (immr->im_ioport.iop_pdatd & PD_SDA) ? 1 : 0;
+       return (bit);
+}
+
+/*-----------------------------------------------------------------------
+ * if last == 0, ACK the byte so can continue reading
+ * else NO ACK to end the read
+ */
+static uchar read_byte (int last)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+       uchar byte = 0;
+       int i;
+
+       immr->im_ioport.iop_pdird &= ~PD_SDA;           /* input */
+       udelay (5);
+
+       for (i=0; i<8; ++i) {
+               byte = (byte << 1) | read_bit();
+       }
+       send_ack (last ? I2C_NOACK : I2C_ACK);
+
+       return byte;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void write_byte (uchar byte)
+{
+       int i;
+       for (i=0; i<8; ++i) {
+               if (byte & 0x80) {
+                       send_data_1 ();
+               } else {
+                       send_data_0 ();
+               }
+               byte <<= 1;
+       }
+       rcv_ack();
+}
+
+/*=====================================================================*/
+/*=====================================================================*/
+
+/*-----------------------------------------------------------------------
+ * `speed' and `slaveaddr' not implemented
+ */
+void i2c_init (int speed, int slaveaddr)
+{
+       volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+       immr->im_ioport.iop_ppard &= ~(PD_SCL | PD_SDA);/* GPIO */
+       immr->im_ioport.iop_podrd |=  (PD_SCL | PD_SDA);/* Open Drain Output */
+
+       RESET_PD_BIT (PD_SCL);
+       RESET_PD_BIT (PD_SDA);
+       SET_PD_BIT   (PD_SCL);
+       SET_PD_BIT   (PD_SDA);          /* stop condition */
+       udelay (25);
+}
+
+/*-----------------------------------------------------------------------
+ *
+ * addr:       Array of address bytes; for instance, to read from
+ *              EEPROM with 8 bit page addresses you have to write 2
+ *              address bytes: the block number, and the block
+ *              offset.
+ * alen:       Number of address bytes in "addr"
+ * buffer:     where to store the read data in
+ * len:                number of bytes to read
+ *              Warning: it is expected that the device is really
+ *              capable of reading `len' sequential bytes; no
+ *              checking is doen here
+ */
+void i2c_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+       uchar *ap = addr;
+
+       write_addr (*ap);
+       while (--alen > 0) {
+               write_byte (*++ap);
+       }
+       send_start ();
+
+       read_addr  (*addr);
+       while (len-- > 0) {
+               *buffer++ = read_byte (len==0);
+       }
+       send_stop  ();
+}
+
+void i2c_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+       uchar *ap = addr;
+
+       write_addr (*ap);
+       while (--alen > 0) {
+               write_byte (*++ap);
+       }
+
+       while (len-- > 0) {
+               write_byte (*buffer++);
+       }
+       send_stop  ();
+}
+
+uchar i2c_reg_read (uchar i2c_addr, uchar reg)
+{
+       char addr[2];
+       char buf [1];
+
+       i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+
+       addr[0] = i2c_addr;
+       addr[1] = reg;
+
+       i2c_read (addr, 2, buf, 1);
+
+       return (buf[0]);
+}
+
+void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
+{
+       char addr[2];
+
+       i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+
+       addr[0] = i2c_addr;
+       addr[1] = reg;
+
+       i2c_write (addr, 2, &val, 1);
+}
+
+#endif /* CONFIG_SOFT_I2C */
+/*-----------------------------------------------------------------------
+ */
index 2c45fd6d9ce5cc2b18f694baaf3ec0bcc9638a12..29e4a81e4a573d0b07b05f85a8ddd44b27989218 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  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>
+ *  Copyright (C) 2000, 2001   Wolfgang Denk <wd@denx.de>
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -95,7 +95,7 @@ version_string:
  *  boot ROM appears in memory, the memory controller setup when access
  *  boot ROM, etc. The HRCW is *extremely* important.
  *
- *  The HRCW is read from the bus during reset. One CPU on the bus will be
+ *  The HRCW is read from the bus during reset. One CPU on the bus will
  *  be a hard reset configuration master, any others will be hard reset
  *  configuration slaves. The master reads eight HRCWs from flash during
  *  reset - the first it uses for itself, the other 7 it communicates to
index ea73eb343b7284d18037c7e246dff0603ef1a94c..db81d2b4b7c667089eaa84ba67c1ab23ecead0dc 100644 (file)
@@ -27,7 +27,7 @@ LIB   = lib$(CPU).a
 
 START  = start.o resetvec.o kgdb.o
 OBJS   = traps.o serial.o cpu.o cpu_init.o speed.o interrupts.o \
-         405gp_pci.o 405gp_enet.o miiphy.o i2c.o
+         405gp_pci.o 405gp_enet.o miiphy.o i2c.o bedbug_405.o
 
 all:   .depend $(START) $(LIB)
 
diff --git a/cpu/ppc4xx/bedbug_405.c b/cpu/ppc4xx/bedbug_405.c
new file mode 100644 (file)
index 0000000..5fb939f
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * Bedbug Functions specific to the PPC405 chip
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <linux/ctype.h>
+
+#include <cmd_bedbug.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) && defined(CONFIG_PPC405)
+
+#define MAX_BREAK_POINTS 4
+
+extern CPU_DEBUG_CTX bug_ctx;
+
+void bedbug405_init __P((void));
+void bedbug405_do_break __P((cmd_tbl_t*,bd_t*,int,int,char*[]));
+void bedbug405_break_isr __P((struct pt_regs*));
+int  bedbug405_find_empty __P((void));
+int  bedbug405_set __P((int,unsigned long));
+int  bedbug405_clear __P((int));
+
+\f
+/* ======================================================================
+ * Initialize the global bug_ctx structure for the IBM PPC405.  Clear all
+ * of the breakpoints.
+ * ====================================================================== */
+
+void bedbug405_init( void )
+{
+  int  i;
+  /* -------------------------------------------------- */
+  
+  bug_ctx.hw_debug_enabled = 0;
+  bug_ctx.stopped = 0;
+  bug_ctx.current_bp = 0;
+  bug_ctx.regs = NULL;
+  
+  bug_ctx.do_break   = bedbug405_do_break;
+  bug_ctx.break_isr  = bedbug405_break_isr;
+  bug_ctx.find_empty = bedbug405_find_empty;
+  bug_ctx.set        = bedbug405_set;
+  bug_ctx.clear      = bedbug405_clear;
+
+  for( i = 1; i <= MAX_BREAK_POINTS; ++i )
+    (*bug_ctx.clear)( i );
+
+  printf( "  BEDBUG Ready\n" );
+  return;
+} /* bedbug_init_breakpoints */
+
+
+\f
+/* ======================================================================
+ * Set/clear/show one of the hardware breakpoints for the 405.  The "off"
+ * string will disable a specific breakpoint.  The "show" string will
+ * display the current breakpoints.  Otherwise an address will set a
+ * breakpoint at that address.  Setting a breakpoint uses the CPU-specific
+ * set routine which will assign a breakpoint number.
+ * ====================================================================== */
+
+void bedbug405_do_break (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+                         char *argv[])
+{
+  long         addr;           /* Address to break at  */
+  int          which_bp;       /* Breakpoint number    */
+  /* -------------------------------------------------- */
+    
+  if (argc < 2)
+  {
+    printf ("Usage:\n%s\n", cmdtp->usage);
+    return;
+  }
+
+  /* Turn off a breakpoint */
+  
+  if( strcmp( argv[ 1 ], "off" ) == 0 )
+  {
+    if( bug_ctx.hw_debug_enabled == 0 )
+    {
+      printf( "No breakpoints enabled\n" );
+      return;
+    }
+
+    which_bp = simple_strtoul( argv[ 2 ], NULL, 10 );
+
+    if( bug_ctx.clear )
+      (*bug_ctx.clear)( which_bp );
+    
+    printf( "Breakpoint %d removed\n", which_bp );
+    return;
+  }
+
+  /* Show a list of breakpoints */
+
+  if( strcmp( argv[ 1 ], "show" ) == 0 )
+  {
+    for( which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp )
+    {
+
+      switch( which_bp )
+      {
+      case 1: addr = GET_IAC1(); break;
+      case 2: addr = GET_IAC2(); break;
+      case 3: addr = GET_IAC3(); break;
+      case 4: addr = GET_IAC4(); break;
+      }
+
+      printf( "Breakpoint [%d]: ", which_bp );
+      if( addr == 0 )
+       printf( "NOT SET\n" );
+      else
+       disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+    }
+    return;
+  }
+
+  /* Set a breakpoint at the address */
+  
+  if( !isdigit( argv[ 1 ][ 0 ]))
+  {
+    printf ("Usage:\n%s\n", cmdtp->usage);
+    return;
+  }
+  
+  addr = simple_strtoul( argv[ 1 ], NULL, 16 ) & 0xfffffffc;
+
+  if(( bug_ctx.set ) && ( which_bp = (*bug_ctx.set)( 0, addr )) > 0 )
+  {
+    printf( "Breakpoint [%d]: ", which_bp );
+    disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+  }
+
+  bug_ctx.bd = bd;
+  return;
+} /* bedbug405_do_break */
+
+
+\f
+/* ======================================================================
+ * Handle a breakpoint.  First determine which breakpoint was hit by
+ * looking at the DeBug Status Register (DBSR), clear the breakpoint
+ * and enter a mini main loop.  Stay in the loop until the stopped flag
+ * in the debug context is cleared.
+ * ====================================================================== */
+
+void bedbug405_break_isr( struct pt_regs *regs )
+{
+  unsigned long        dbsr_val;       /* Value of the DBSR    */
+  unsigned long        addr;           /* Address stopped at   */
+  /* -------------------------------------------------- */
+  
+  dbsr_val = GET_DBSR();
+
+  if( dbsr_val & DBSR_IA1 )
+  {
+    bug_ctx.current_bp = 1;
+    addr = GET_IAC1();
+    SET_DBSR( DBSR_IA1 );      /* Write a 1 to clear */
+  }
+  else if( dbsr_val & DBSR_IA2 )
+  {
+    bug_ctx.current_bp = 2;
+    addr = GET_IAC2();
+    SET_DBSR( DBSR_IA2 );      /* Write a 1 to clear */
+  }
+  else if( dbsr_val & DBSR_IA3 )
+  {
+    bug_ctx.current_bp = 3;
+    addr = GET_IAC3();
+    SET_DBSR( DBSR_IA3 );      /* Write a 1 to clear */
+  }
+  else if( dbsr_val & DBSR_IA4 )
+  {
+    bug_ctx.current_bp = 4;
+    addr = GET_IAC4();
+    SET_DBSR( DBSR_IA4 );      /* Write a 1 to clear */
+  }
+
+  bedbug_main_loop( addr, regs );
+  return;
+} /* bedbug405_break_isr */
+
+
+\f
+/* ======================================================================
+ * Look through all of the hardware breakpoints available to see if one
+ * is unused.
+ * ====================================================================== */
+
+int bedbug405_find_empty( void )
+{
+  /* -------------------------------------------------- */
+
+  if( GET_IAC1() == 0 )
+    return 1;
+
+  if( GET_IAC2() == 0 )
+    return 2;
+
+  if( GET_IAC3() == 0 )
+    return 3;
+
+  if( GET_IAC4() == 0 )
+    return 4;
+
+  return 0;
+} /* bedbug405_find_empty */
+
+
+\f
+/* ======================================================================
+ * Set a breakpoint.  If 'which_bp' is zero then find an unused breakpoint
+ * number, otherwise reassign the given breakpoint.  If hardware debugging
+ * is not enabled, then turn it on via the MSR and DBCR0.  Set the break
+ * address in the appropriate IACx register and enable proper address
+ * beakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug405_set( int which_bp, unsigned long addr )
+{
+  /* -------------------------------------------------- */
+
+  /* Only look if which_bp == 0, else use which_bp */
+  if(( bug_ctx.find_empty ) && ( !which_bp ) &&
+     ( which_bp = (*bug_ctx.find_empty)()) == 0 )
+  {
+    printf( "All breakpoints in use\n" );
+    return 0;
+  }
+
+  if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+  {
+    printf( "Invalid break point # %d\n", which_bp );
+    return 0;
+  }
+  
+  if( ! bug_ctx.hw_debug_enabled )
+  {
+    SET_MSR( GET_MSR() | 0x200 );              /* set MSR[ DE ] */
+    SET_DBCR0( GET_DBCR0() | DBCR0_IDM );
+    bug_ctx.hw_debug_enabled = 1;
+  }
+
+  switch( which_bp )
+  {
+  case 1:
+    SET_IAC1( addr );
+    SET_DBCR0( GET_DBCR0() | DBCR0_IA1 );
+    break;
+
+  case 2:
+    SET_IAC2( addr );
+    SET_DBCR0( GET_DBCR0() | DBCR0_IA2 );
+    break;
+
+  case 3:
+    SET_IAC3( addr );
+    SET_DBCR0( GET_DBCR0() | DBCR0_IA3 );
+    break;
+
+  case 4:
+    SET_IAC4( addr );
+    SET_DBCR0( GET_DBCR0() | DBCR0_IA4 );
+    break;
+  }
+
+  return which_bp;
+} /* bedbug405_set */
+
+
+\f
+/* ======================================================================
+ * Disable a specific breakoint by setting the appropriate IACx register
+ * to zero and claring the instruction address breakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug405_clear( int which_bp )
+{
+  /* -------------------------------------------------- */
+
+  if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+  {
+    printf( "Invalid break point # (%d)\n", which_bp );
+    return -1;
+  }
+
+  switch( which_bp )
+  {
+  case 1:
+    SET_IAC1( 0 );
+    SET_DBCR0( GET_DBCR0() & ~DBCR0_IA1 );
+    break;
+
+  case 2:
+    SET_IAC2( 0 );
+    SET_DBCR0( GET_DBCR0() & ~DBCR0_IA2 );
+    break;
+
+  case 3:
+    SET_IAC3( 0 );
+    SET_DBCR0( GET_DBCR0() & ~DBCR0_IA3 );
+    break;
+
+  case 4:
+    SET_IAC4( 0 );
+    SET_DBCR0( GET_DBCR0() & ~DBCR0_IA4 );
+    break;
+  }
+
+  return 0;
+} /* bedbug405_clear */
+
+
+/* ====================================================================== */
+#endif
+
index c454dc1bbe15da28246383d98040cf218f34af88..80e8fe261d23ef5f5eeb0eac153f781b71519dd2 100644 (file)
@@ -371,12 +371,13 @@ ProgramCheck:
        STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
        STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
 
+        CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
 
        .globl  _end_of_vectors
 _end_of_vectors:
 
 
-       . = 0x2000
+       . = 0x2100
 
 /*
  * This code finishes saving the registers to the exception frame
@@ -453,6 +454,36 @@ int_return:
        SYNC
        rfi
 
+crit_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   990,r2          /* SRR2 */
+        mtspr   991,r0          /* SRR3 */
+        lwz     r0,GPR0(r1)
+        lwz     r2,GPR2(r1)
+        lwz     r1,GPR1(r1)
+        SYNC
+        rfci
+
 /* Cache functions.
 */
 invalidate_icache:
index c4fc6af08f2eb226487bb2d9a9cdaab09da93cbb..538022cb9540b018d4a35ca4e089334e4438a940 100644 (file)
@@ -53,6 +53,23 @@ static __inline__ void set_tsr(unsigned long val)
     asm volatile("mttsr %0" : : "r" (val));
 }
 
+static __inline__ unsigned long get_esr(void)
+{
+    unsigned long val;
+
+    asm volatile("mfesr %0" : "=r" (val) :);
+    return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+extern void do_bedbug_breakpoint(struct pt_regs *);
 
 /*
  * Trap & Exception support
@@ -176,12 +193,23 @@ AlignmentException(struct pt_regs *regs)
 void
 ProgramCheckException(struct pt_regs *regs)
 {
+        long esr_val;
+  
 #if (CONFIG_COMMANDS & CFG_CMD_KGDB)
        if (debugger_exception_handler && (*debugger_exception_handler)(regs))
                return;
 #endif
 
        show_regs(regs);
+
+        esr_val = get_esr();
+        if( esr_val & ESR_PIL )
+          printf( "** Illegal Instruction **\n" );
+        else if( esr_val & ESR_PPR )
+          printf( "** Privileged Instruction **\n" );
+        else if( esr_val & ESR_PTR )
+          printf( "** Trap Instruction **\n" );
+
        print_backtrace((unsigned long *)regs->gpr[1]);
        panic("Program Check Exception");
 }
@@ -214,6 +242,16 @@ UnknownException(struct pt_regs *regs)
        _exception(0, regs);
 }
 
+void
+DebugException(struct pt_regs *regs)
+{
+  printf("Debugger trap at @ %lx\n", regs->nip );
+  show_regs(regs);
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+  do_bedbug_breakpoint( regs );
+#endif
+}
+
 /* Probe an address by reading.  If not present, return -1, otherwise
  * return 0.
  */
diff --git a/doc/README.bedbug b/doc/README.bedbug
new file mode 100644 (file)
index 0000000..109e8cb
--- /dev/null
@@ -0,0 +1,62 @@
+BEDBUG Support for PPCBoot
+--------------------------
+
+These changes implement the bedbug (emBEDded deBUGger) debugger in ppcboot.
+A specific implementation is made for the IBM405 processor but other flavors
+can be easily implemented.
+
+#####################
+### Modifications ###
+#####################
+
+./common/Makefile
+       Included cmd_bedbug.c and bedbug.c in the Makefile.
+
+./common/command.c
+       Added bedbug commands to command table.
+
+./common/board.c
+       Added call to initialize debugger on startup.
+
+./cpu/ppc4xx/Makefile
+       Added bedbug_405.c to the Makefile.
+
+./cpu/ppc4xx/start.S
+       Added code to handle the debug exception (0x2000) on the 405.
+       Also added code to handle critical exceptions since the debug
+       is treated as critical on the 405.
+
+./cpu/ppc4xx/traps.c
+       Added more detailed output for the program exception to tell
+       if it is an illegal instruction, privileged instruction or 
+       a trap. Also added debug trap handler.
+
+./include/cmd_confdefs.h
+       Added definition of CFG_CMD_BEDBUG.
+
+./include/config_WALNUT405.h
+       Added CFG_CMD_BEDBUG to the CONFIG_COMMANDS for the WALNUT.
+              
+./include/ppc_asm.tmpl
+       Added code to handle critical exceptions
+
+#################
+### New Stuff ###
+#################
+
+./include/bedbug/ppc.h
+./include/bedbug/regs.h
+./include/bedbug/bedbug.h
+./include/bedbug/elf.h
+./include/bedbug/tables.h
+./include/cmd_bedbug.h
+./common/cmd_bedbug.c
+./common/bedbug.c
+       Bedbug library includes code for assembling and disassembling
+       PowerPC instructions to/from memory as well as handling 
+       hardware breakpoints and stepping through code.  These 
+       routines are common to all PowerPC processors.
+
+./cpu/ppc4xx/bedbug_405.c
+       IBM PPC405 specific debugger routines.
+
diff --git a/include/bedbug/bedbug.h b/include/bedbug/bedbug.h
new file mode 100644 (file)
index 0000000..10c4102
--- /dev/null
@@ -0,0 +1,42 @@
+/* $Id: bedbug.h,v 1.1 2001/05/31 22:12:27 wd Exp $ */
+
+#ifndef _BEDBUG_H
+#define _BEDBUG_H
+
+#ifndef NULL
+#define NULL   0
+#endif
+
+#define _USE_PROTOTYPES
+
+#ifndef isblank
+#define isblank(c) isspace((int)(c))
+#endif
+
+#ifndef __P
+#if defined(_USE_PROTOTYPES) && (defined(__STDC__) || defined(__cplusplus))
+#define __P(protos)    protos          /* full-blown ANSI C */
+#else
+#define __P(protos)    ()              /* traditional C preprocessor */
+#endif
+#endif
+
+#define assert( condition ) if( (condition) ) _exit(0)
+
+#endif /* _BEDBUG_H */
+
+
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ * 
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
diff --git a/include/bedbug/elf.h b/include/bedbug/elf.h
new file mode 100644 (file)
index 0000000..a6e3d20
--- /dev/null
@@ -0,0 +1,582 @@
+/*     $OpenBSD: exec_elf.h,v 1.27 2001/01/23 16:58:06 drahn Exp $     */
+/*
+ * Copyright (c) 1995, 1996 Erik Theisen.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This is the ELF ABI header file
+ * formerly known as "elf_abi.h".
+ */
+
+#ifndef _SYS_EXEC_ELF_H_
+#define _SYS_EXEC_ELF_H_
+
+/* #include <machine/types.h> */
+/* #include <machine/exec.h> */
+
+typedef u_int8_t       Elf_Byte;
+
+typedef u_int32_t      Elf32_Addr;     /* Unsigned program address */
+typedef u_int32_t      Elf32_Off;      /* Unsigned file offset */
+typedef int32_t                Elf32_Sword;    /* Signed large integer */
+typedef u_int32_t      Elf32_Word;     /* Unsigned large integer */
+typedef u_int16_t      Elf32_Half;     /* Unsigned medium integer */
+
+typedef u_int64_t      Elf64_Addr;
+typedef u_int64_t      Elf64_Off;
+typedef int64_t                Elf64_Sword;
+typedef int32_t                Elf64_Shalf;
+typedef u_int64_t      Elf64_Word;
+typedef u_int32_t      Elf64_Half;
+typedef u_int16_t      Elf64_Quarter;
+
+/* e_ident[] identification indexes */
+#define EI_MAG0                0               /* file ID */
+#define EI_MAG1                1               /* file ID */
+#define EI_MAG2                2               /* file ID */
+#define EI_MAG3                3               /* file ID */
+#define EI_CLASS       4               /* file class */
+#define EI_DATA                5               /* data encoding */
+#define EI_VERSION     6               /* ELF header version */
+#define EI_PAD         7               /* start of pad bytes */
+#define EI_BRAND       8               /* brand */ 
+#define EI_NIDENT      16              /* Size of e_ident[] */
+
+/* e_ident[] magic number */
+#define        ELFMAG0         0x7f            /* e_ident[EI_MAG0] */
+#define        ELFMAG1         'E'             /* e_ident[EI_MAG1] */
+#define        ELFMAG2         'L'             /* e_ident[EI_MAG2] */
+#define        ELFMAG3         'F'             /* e_ident[EI_MAG3] */
+#define        ELFMAG          "\177ELF"       /* magic */
+#define        SELFMAG         4               /* size of magic */
+
+/* e_ident[] file class */
+#define        ELFCLASSNONE    0               /* invalid */
+#define        ELFCLASS32      1               /* 32-bit objs */
+#define        ELFCLASS64      2               /* 64-bit objs */
+#define        ELFCLASSNUM     3               /* number of classes */
+
+/* e_ident[] data encoding */
+#define ELFDATANONE    0               /* invalid */
+#define ELFDATA2LSB    1               /* Little-Endian */
+#define ELFDATA2MSB    2               /* Big-Endian */
+#define ELFDATANUM     3               /* number of data encode defines */
+
+/* e_ident */
+#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
+                      (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
+                      (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
+                      (ehdr).e_ident[EI_MAG3] == ELFMAG3)
+
+/* ELF Header */
+typedef struct elfhdr{
+       unsigned char   e_ident[EI_NIDENT]; /* ELF Identification */
+       Elf32_Half      e_type;         /* object file type */
+       Elf32_Half      e_machine;      /* machine */
+       Elf32_Word      e_version;      /* object file version */
+       Elf32_Addr      e_entry;        /* virtual entry point */
+       Elf32_Off       e_phoff;        /* program header table offset */
+       Elf32_Off       e_shoff;        /* section header table offset */
+       Elf32_Word      e_flags;        /* processor-specific flags */
+       Elf32_Half      e_ehsize;       /* ELF header size */
+       Elf32_Half      e_phentsize;    /* program header entry size */
+       Elf32_Half      e_phnum;        /* number of program header entries */
+       Elf32_Half      e_shentsize;    /* section header entry size */
+       Elf32_Half      e_shnum;        /* number of section header entries */
+       Elf32_Half      e_shstrndx;     /* section header table's "section 
+                                          header string table" entry offset */
+} Elf32_Ehdr;
+
+typedef struct {
+       unsigned char   e_ident[EI_NIDENT];     /* Id bytes */
+       Elf64_Quarter   e_type;                 /* file type */
+       Elf64_Quarter   e_machine;              /* machine type */
+       Elf64_Half      e_version;              /* version number */
+       Elf64_Addr      e_entry;                /* entry point */
+       Elf64_Off       e_phoff;                /* Program hdr offset */
+       Elf64_Off       e_shoff;                /* Section hdr offset */
+       Elf64_Half      e_flags;                /* Processor flags */
+       Elf64_Quarter   e_ehsize;               /* sizeof ehdr */
+       Elf64_Quarter   e_phentsize;            /* Program header entry size */
+       Elf64_Quarter   e_phnum;                /* Number of program headers */
+       Elf64_Quarter   e_shentsize;            /* Section header entry size */
+       Elf64_Quarter   e_shnum;                /* Number of section headers */
+       Elf64_Quarter   e_shstrndx;             /* String table index */
+} Elf64_Ehdr;
+
+/* e_type */
+#define ET_NONE                0               /* No file type */
+#define ET_REL         1               /* relocatable file */
+#define ET_EXEC                2               /* executable file */
+#define ET_DYN         3               /* shared object file */
+#define ET_CORE                4               /* core file */
+#define ET_NUM         5               /* number of types */
+#define ET_LOPROC      0xff00          /* reserved range for processor */
+#define ET_HIPROC      0xffff          /*  specific e_type */
+
+/* e_machine */
+#define EM_NONE                0               /* No Machine */
+#define EM_M32         1               /* AT&T WE 32100 */
+#define EM_SPARC       2               /* SPARC */
+#define EM_386         3               /* Intel 80386 */
+#define EM_68K         4               /* Motorola 68000 */
+#define EM_88K         5               /* Motorola 88000 */
+#define EM_486         6               /* Intel 80486 - unused? */
+#define EM_860         7               /* Intel 80860 */
+#define EM_MIPS                8               /* MIPS R3000 Big-Endian only */
+
+/* 
+ * Don't know if EM_MIPS_RS4_BE,
+ * EM_SPARC64, EM_PARISC,
+ * or EM_PPC are ABI compliant
+ */
+#define EM_MIPS_RS4_BE 10              /* MIPS R4000 Big-Endian */
+#define EM_SPARC64     11              /* SPARC v9 64-bit unoffical */
+#define EM_PARISC      15              /* HPPA */
+#define EM_PPC         20              /* PowerPC */
+#define EM_ALPHA       41              /* DEC ALPHA */
+#define EM_ALPHA_EXP   0x9026          /* DEC ALPHA */
+#define EM_NUM         15              /* number of machine types */
+
+/* Version */
+#define EV_NONE                0               /* Invalid */
+#define EV_CURRENT     1               /* Current */
+#define EV_NUM         2               /* number of versions */
+
+/* Section Header */
+typedef struct {
+       Elf32_Word      sh_name;        /* name - index into section header
+                                          string table section */
+       Elf32_Word      sh_type;        /* type */
+       Elf32_Word      sh_flags;       /* flags */
+       Elf32_Addr      sh_addr;        /* address */
+       Elf32_Off       sh_offset;      /* file offset */
+       Elf32_Word      sh_size;        /* section size */
+       Elf32_Word      sh_link;        /* section header table index link */
+       Elf32_Word      sh_info;        /* extra information */
+       Elf32_Word      sh_addralign;   /* address alignment */
+       Elf32_Word      sh_entsize;     /* section entry size */
+} Elf32_Shdr;
+
+typedef struct {
+       Elf64_Half      sh_name;        /* section name */
+       Elf64_Half      sh_type;        /* section type */
+       Elf64_Word      sh_flags;       /* section flags */
+       Elf64_Addr      sh_addr;        /* virtual address */
+       Elf64_Off       sh_offset;      /* file offset */
+       Elf64_Word      sh_size;        /* section size */
+       Elf64_Half      sh_link;        /* link to another */
+       Elf64_Half      sh_info;        /* misc info */
+       Elf64_Word      sh_addralign;   /* memory alignment */
+       Elf64_Word      sh_entsize;     /* table entry size */
+} Elf64_Shdr;
+
+/* Special Section Indexes */
+#define SHN_UNDEF      0               /* undefined */
+#define SHN_LORESERVE  0xff00          /* lower bounds of reserved indexes */
+#define SHN_LOPROC     0xff00          /* reserved range for processor */
+#define SHN_HIPROC     0xff1f          /*   specific section indexes */
+#define SHN_ABS                0xfff1          /* absolute value */
+#define SHN_COMMON     0xfff2          /* common symbol */
+#define SHN_HIRESERVE  0xffff          /* upper bounds of reserved indexes */
+
+/* sh_type */
+#define SHT_NULL       0               /* inactive */
+#define SHT_PROGBITS   1               /* program defined information */
+#define SHT_SYMTAB     2               /* symbol table section */
+#define SHT_STRTAB     3               /* string table section */
+#define SHT_RELA       4               /* relocation section with addends*/
+#define SHT_HASH       5               /* symbol hash table section */
+#define SHT_DYNAMIC    6               /* dynamic section */
+#define SHT_NOTE       7               /* note section */
+#define SHT_NOBITS     8               /* no space section */
+#define SHT_REL                9               /* relation section without addends */
+#define SHT_SHLIB      10              /* reserved - purpose unknown */
+#define SHT_DYNSYM     11              /* dynamic symbol table section */
+#define SHT_NUM                12              /* number of section types */
+#define SHT_LOPROC     0x70000000      /* reserved range for processor */
+#define SHT_HIPROC     0x7fffffff      /*  specific section header types */
+#define SHT_LOUSER     0x80000000      /* reserved range for application */
+#define SHT_HIUSER     0xffffffff      /*  specific indexes */
+
+/* Section names */
+#define ELF_BSS         ".bss"         /* uninitialized data */
+#define ELF_DATA        ".data"                /* initialized data */
+#define ELF_DEBUG       ".debug"       /* debug */
+#define ELF_DYNAMIC     ".dynamic"     /* dynamic linking information */
+#define ELF_DYNSTR      ".dynstr"      /* dynamic string table */
+#define ELF_DYNSYM      ".dynsym"      /* dynamic symbol table */
+#define ELF_FINI        ".fini"                /* termination code */
+#define ELF_GOT         ".got"         /* global offset table */
+#define ELF_HASH        ".hash"                /* symbol hash table */
+#define ELF_INIT        ".init"                /* initialization code */
+#define ELF_REL_DATA    ".rel.data"    /* relocation data */
+#define ELF_REL_FINI    ".rel.fini"    /* relocation termination code */
+#define ELF_REL_INIT    ".rel.init"    /* relocation initialization code */
+#define ELF_REL_DYN     ".rel.dyn"     /* relocaltion dynamic link info */
+#define ELF_REL_RODATA  ".rel.rodata"  /* relocation read-only data */
+#define ELF_REL_TEXT    ".rel.text"    /* relocation code */
+#define ELF_RODATA      ".rodata"      /* read-only data */
+#define ELF_SHSTRTAB    ".shstrtab"    /* section header string table */
+#define ELF_STRTAB      ".strtab"      /* string table */
+#define ELF_SYMTAB      ".symtab"      /* symbol table */
+#define ELF_TEXT        ".text"                /* code */
+
+
+/* Section Attribute Flags - sh_flags */
+#define SHF_WRITE      0x1             /* Writable */
+#define SHF_ALLOC      0x2             /* occupies memory */
+#define SHF_EXECINSTR  0x4             /* executable */
+#define SHF_MASKPROC   0xf0000000      /* reserved bits for processor */
+                                       /*  specific section attributes */
+
+/* Symbol Table Entry */
+typedef struct elf32_sym {
+       Elf32_Word      st_name;        /* name - index into string table */
+       Elf32_Addr      st_value;       /* symbol value */
+       Elf32_Word      st_size;        /* symbol size */
+       unsigned char   st_info;        /* type and binding */
+       unsigned char   st_other;       /* 0 - no defined meaning */
+       Elf32_Half      st_shndx;       /* section header index */
+} Elf32_Sym;
+
+typedef struct {
+       Elf64_Half      st_name;        /* Symbol name index in str table */
+       Elf_Byte        st_info;        /* type / binding attrs */
+       Elf_Byte        st_other;       /* unused */
+       Elf64_Quarter   st_shndx;       /* section index of symbol */
+       Elf64_Word      st_value;       /* value of symbol */
+       Elf64_Word      st_size;        /* size of symbol */
+} Elf64_Sym;
+
+/* Symbol table index */
+#define STN_UNDEF      0               /* undefined */
+
+/* Extract symbol info - st_info */
+#define ELF32_ST_BIND(x)       ((x) >> 4)
+#define ELF32_ST_TYPE(x)       (((unsigned int) x) & 0xf)
+#define ELF32_ST_INFO(b,t)     (((b) << 4) + ((t) & 0xf))
+
+#define ELF64_ST_BIND(x)       ((x) >> 4)
+#define ELF64_ST_TYPE(x)       (((unsigned int) x) & 0xf)
+#define ELF64_ST_INFO(b,t)     (((b) << 4) + ((t) & 0xf))
+
+/* Symbol Binding - ELF32_ST_BIND - st_info */
+#define STB_LOCAL      0               /* Local symbol */
+#define STB_GLOBAL     1               /* Global symbol */
+#define STB_WEAK       2               /* like global - lower precedence */
+#define STB_NUM                3               /* number of symbol bindings */
+#define STB_LOPROC     13              /* reserved range for processor */
+#define STB_HIPROC     15              /*  specific symbol bindings */
+
+/* Symbol type - ELF32_ST_TYPE - st_info */
+#define STT_NOTYPE     0               /* not specified */
+#define STT_OBJECT     1               /* data object */
+#define STT_FUNC       2               /* function */
+#define STT_SECTION    3               /* section */
+#define STT_FILE       4               /* file */
+#define STT_NUM                5               /* number of symbol types */
+#define STT_LOPROC     13              /* reserved range for processor */
+#define STT_HIPROC     15              /*  specific symbol types */
+
+/* Relocation entry with implicit addend */
+typedef struct 
+{
+       Elf32_Addr      r_offset;       /* offset of relocation */
+       Elf32_Word      r_info;         /* symbol table index and type */
+} Elf32_Rel;
+
+/* Relocation entry with explicit addend */
+typedef struct 
+{
+       Elf32_Addr      r_offset;       /* offset of relocation */
+       Elf32_Word      r_info;         /* symbol table index and type */
+       Elf32_Sword     r_addend;
+} Elf32_Rela;
+
+/* Extract relocation info - r_info */
+#define ELF32_R_SYM(i)         ((i) >> 8)
+#define ELF32_R_TYPE(i)                ((unsigned char) (i))
+#define ELF32_R_INFO(s,t)      (((s) << 8) + (unsigned char)(t))
+
+typedef struct {
+       Elf64_Word      r_offset;       /* where to do it */
+       Elf64_Word      r_info;         /* index & type of relocation */
+} Elf64_Rel;
+
+typedef struct {
+       Elf64_Word      r_offset;       /* where to do it */
+       Elf64_Word      r_info;         /* index & type of relocation */
+       Elf64_Word      r_addend;       /* adjustment value */
+} Elf64_Rela;
+
+#define        ELF64_R_SYM(info)       ((info) >> 32)
+#define        ELF64_R_TYPE(info)      ((info) & 0xFFFFFFFF)
+#define ELF64_R_INFO(s,t)      (((s) << 32) + (u_int32_t)(t))
+
+/* Program Header */
+typedef struct {
+       Elf32_Word      p_type;         /* segment type */
+       Elf32_Off       p_offset;       /* segment offset */
+       Elf32_Addr      p_vaddr;        /* virtual address of segment */
+       Elf32_Addr      p_paddr;        /* physical address - ignored? */
+       Elf32_Word      p_filesz;       /* number of bytes in file for seg. */
+       Elf32_Word      p_memsz;        /* number of bytes in mem. for seg. */
+       Elf32_Word      p_flags;        /* flags */
+       Elf32_Word      p_align;        /* memory alignment */
+} Elf32_Phdr;
+
+typedef struct {
+       Elf64_Half      p_type;         /* entry type */
+       Elf64_Half      p_flags;        /* flags */
+       Elf64_Off       p_offset;       /* offset */
+       Elf64_Addr      p_vaddr;        /* virtual address */
+       Elf64_Addr      p_paddr;        /* physical address */
+       Elf64_Word      p_filesz;       /* file size */
+       Elf64_Word      p_memsz;        /* memory size */
+       Elf64_Word      p_align;        /* memory & file alignment */
+} Elf64_Phdr;
+
+/* Segment types - p_type */
+#define PT_NULL                0               /* unused */
+#define PT_LOAD                1               /* loadable segment */
+#define PT_DYNAMIC     2               /* dynamic linking section */
+#define PT_INTERP      3               /* the RTLD */
+#define PT_NOTE                4               /* auxiliary information */
+#define PT_SHLIB       5               /* reserved - purpose undefined */
+#define PT_PHDR                6               /* program header */
+#define PT_NUM         7               /* Number of segment types */
+#define PT_LOPROC      0x70000000      /* reserved range for processor */
+#define PT_HIPROC      0x7fffffff      /*  specific segment types */
+
+/* Segment flags - p_flags */
+#define PF_X           0x1             /* Executable */
+#define PF_W           0x2             /* Writable */
+#define PF_R           0x4             /* Readable */
+#define PF_MASKPROC    0xf0000000      /* reserved bits for processor */
+                                       /*  specific segment flags */
+
+/* Dynamic structure */
+typedef struct {
+       Elf32_Sword     d_tag;          /* controls meaning of d_val */
+       union {
+               Elf32_Word      d_val;  /* Multiple meanings - see d_tag */
+               Elf32_Addr      d_ptr;  /* program virtual address */
+       } d_un;
+} Elf32_Dyn;
+
+extern Elf32_Dyn       _DYNAMIC[];     /* XXX not 64-bit clean */
+
+typedef struct {
+       Elf64_Word      d_tag;          /* controls meaning of d_val */
+       union {
+               Elf64_Addr      d_ptr;
+               Elf64_Word      d_val;
+       } d_un;
+} Elf64_Dyn;
+
+/* Dynamic Array Tags - d_tag */
+#define DT_NULL                0               /* marks end of _DYNAMIC array */
+#define DT_NEEDED      1               /* string table offset of needed lib */
+#define DT_PLTRELSZ    2               /* size of relocation entries in PLT */
+#define DT_PLTGOT      3               /* address PLT/GOT */
+#define DT_HASH                4               /* address of symbol hash table */
+#define DT_STRTAB      5               /* address of string table */
+#define DT_SYMTAB      6               /* address of symbol table */
+#define DT_RELA                7               /* address of relocation table */
+#define DT_RELASZ      8               /* size of relocation table */
+#define DT_RELAENT     9               /* size of relocation entry */
+#define DT_STRSZ       10              /* size of string table */
+#define DT_SYMENT      11              /* size of symbol table entry */
+#define DT_INIT                12              /* address of initialization func. */
+#define DT_FINI                13              /* address of termination function */
+#define DT_SONAME      14              /* string table offset of shared obj */
+#define DT_RPATH       15              /* string table offset of library
+                                          search path */
+#define DT_SYMBOLIC    16              /* start sym search in shared obj. */
+#define DT_REL         17              /* address of rel. tbl. w addends */
+#define DT_RELSZ       18              /* size of DT_REL relocation table */
+#define DT_RELENT      19              /* size of DT_REL relocation entry */
+#define DT_PLTREL      20              /* PLT referenced relocation entry */
+#define DT_DEBUG       21              /* bugger */
+#define DT_TEXTREL     22              /* Allow rel. mod. to unwritable seg */
+#define DT_JMPREL      23              /* add. of PLT's relocation entries */
+#define DT_BIND_NOW    24              /* Bind now regardless of env setting */
+#define DT_NUM         25              /* Number used. */
+#define DT_LOPROC      0x70000000      /* reserved range for processor */
+#define DT_HIPROC      0x7fffffff      /*  specific dynamic array tags */
+       
+/* Standard ELF hashing function */
+unsigned int elf_hash(const unsigned char *name);
+
+/*
+ * Note Definitions
+ */
+typedef struct {
+       Elf32_Word namesz;
+       Elf32_Word descsz;
+       Elf32_Word type;
+} Elf32_Note;
+
+typedef struct {
+       Elf64_Half namesz;
+       Elf64_Half descsz;
+       Elf64_Half type;
+} Elf64_Note;
+
+/*
+ * XXX - these _KERNEL items aren't part of the ABI!
+ */
+#if defined(_KERNEL) || defined(_DYN_LOADER)
+
+#define ELF32_NO_ADDR  ((u_long) ~0)   /* Indicates addr. not yet filled in */
+#define ELF_AUX_ENTRIES        8               /* Size of aux array passed to loader */
+
+typedef struct {
+       Elf32_Sword     au_id;                          /* 32-bit id */
+       Elf32_Word      au_v;                           /* 32-bit value */
+} Aux32Info;
+
+#define ELF64_NO_ADDR  ((u_int64_t) ~0)/* Indicates addr. not yet filled in */
+#define ELF64_AUX_ENTRIES      8       /* Size of aux array passed to loader */
+
+typedef struct {
+       Elf64_Shalf     au_id;                          /* 32-bit id */
+       Elf64_Word      au_v;                           /* 64-bit id */
+} Aux64Info;
+
+enum AuxID {
+       AUX_null = 0,
+       AUX_ignore = 1,
+       AUX_execfd = 2,
+       AUX_phdr = 3,                   /* &phdr[0] */
+       AUX_phent = 4,                  /* sizeof(phdr[0]) */
+       AUX_phnum = 5,                  /* # phdr entries */
+       AUX_pagesz = 6,                 /* PAGESIZE */
+       AUX_base = 7,                   /* ld.so base addr */
+       AUX_flags = 8,                  /* processor flags */
+       AUX_entry = 9,                  /* a.out entry */
+       AUX_sun_uid = 2000,             /* euid */
+       AUX_sun_ruid = 2001,            /* ruid */
+       AUX_sun_gid = 2002,             /* egid */
+       AUX_sun_rgid = 2003             /* rgid */
+};
+
+struct elf_args {
+        u_long  arg_entry;             /* progran entry point */
+        u_long  arg_interp;            /* Interpreter load address */
+        u_long  arg_phaddr;            /* program header address */
+        u_long  arg_phentsize;         /* Size of program header */
+        u_long  arg_phnum;             /* Number of program headers */
+        u_long  arg_os;                        /* OS tag */
+};
+
+#endif
+
+#if !defined(ELFSIZE) && defined(ARCH_ELFSIZE)
+#define ELFSIZE ARCH_ELFSIZE
+#endif
+
+#if defined(ELFSIZE)
+#define CONCAT(x,y)    __CONCAT(x,y)
+#define ELFNAME(x)     CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
+#define ELFNAME2(x,y)  CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
+#define ELFNAMEEND(x)  CONCAT(x,CONCAT(_elf,ELFSIZE))
+#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
+#endif
+
+#if defined(ELFSIZE) && (ELFSIZE == 32)
+#define Elf_Ehdr       Elf32_Ehdr
+#define Elf_Phdr       Elf32_Phdr
+#define Elf_Shdr       Elf32_Shdr
+#define Elf_Sym                Elf32_Sym
+#define Elf_Rel                Elf32_Rel
+#define Elf_RelA       Elf32_Rela
+#define Elf_Dyn                Elf32_Dyn
+#define Elf_Word       Elf32_Word
+#define Elf_Sword      Elf32_Sword
+#define Elf_Addr       Elf32_Addr
+#define Elf_Off                Elf32_Off
+#define Elf_Nhdr       Elf32_Nhdr
+
+#define ELF_R_SYM      ELF32_R_SYM
+#define ELF_R_TYPE     ELF32_R_TYPE
+#define ELF_R_INFO     ELF32_R_INFO
+#define ELFCLASS       ELFCLASS32
+
+#define ELF_ST_BIND    ELF32_ST_BIND
+#define ELF_ST_TYPE    ELF32_ST_TYPE
+#define ELF_ST_INFO    ELF32_ST_INFO
+
+#define AuxInfo                Aux32Info
+#elif defined(ELFSIZE) && (ELFSIZE == 64)
+#define Elf_Ehdr       Elf64_Ehdr
+#define Elf_Phdr       Elf64_Phdr
+#define Elf_Shdr       Elf64_Shdr
+#define Elf_Sym                Elf64_Sym
+#define Elf_Rel                Elf64_Rel
+#define Elf_RelA       Elf64_Rela
+#define Elf_Dyn                Elf64_Dyn
+#define Elf_Word       Elf64_Word
+#define Elf_Sword      Elf64_Sword
+#define Elf_Addr       Elf64_Addr
+#define Elf_Off                Elf64_Off
+#define Elf_Nhdr       Elf64_Nhdr
+
+#define ELF_R_SYM      ELF64_R_SYM
+#define ELF_R_TYPE     ELF64_R_TYPE
+#define ELF_R_INFO     ELF64_R_INFO
+#define ELFCLASS       ELFCLASS64
+
+#define ELF_ST_BIND    ELF64_ST_BIND
+#define ELF_ST_TYPE    ELF64_ST_TYPE
+#define ELF_ST_INFO    ELF64_ST_INFO
+
+#define AuxInfo                Aux64Info
+#endif
+
+#ifdef _KERNEL
+#ifdef _KERN_DO_ELF64
+int exec_elf64_makecmds __P((struct proc *, struct exec_package *));
+void *elf64_copyargs __P((struct exec_package *, struct ps_strings *,
+        void *, void *));
+int exec_elf64_fixup __P((struct proc *, struct exec_package *));
+char *elf64_check_brand __P((Elf64_Ehdr *));
+int elf64_os_pt_note __P((struct proc *, struct exec_package *, Elf64_Ehdr *,
+       char *, size_t, size_t));
+#endif
+#ifdef _KERN_DO_ELF
+int exec_elf_makecmds __P((struct proc *, struct exec_package *));
+void *elf_copyargs __P((struct exec_package *, struct ps_strings *,
+        void *, void *));
+int exec_elf_fixup __P((struct proc *, struct exec_package *));
+char *elf_check_brand __P((Elf32_Ehdr *));
+#endif
+
+#endif /* _KERNEL */
+
+#define ELF_TARG_VER   1       /* The ver for which this code is intended */
+
+#endif /* _SYS_EXEC_ELF_H_ */
diff --git a/include/bedbug/ppc.h b/include/bedbug/ppc.h
new file mode 100644 (file)
index 0000000..29fa840
--- /dev/null
@@ -0,0 +1,413 @@
+/* $Id: ppc.h,v 1.1 2001/05/31 22:12:27 wd Exp $ */
+
+#ifndef _PPC_H
+#define _PPC_H
+
+/*======================================================================
+ *
+ *  OPERANDS
+ *
+ *======================================================================*/
+
+enum OP_FIELD {
+  O_AA = 1, O_BD, O_BI, O_BO, O_crbD, O_crbA, O_crbB, O_CRM, O_d, O_frC, O_frD,
+  O_frS, O_IMM, O_LI, O_LK, O_MB, O_ME, O_NB, O_OE, O_rA, O_rB, O_Rc, O_rD,
+  O_rS, O_SH, O_SIMM, O_SR, O_TO, O_UIMM, O_crfD, O_crfS, O_L, O_spr, O_tbr,
+  O_cr2 };
+
+struct operand {
+  enum OP_FIELD        field;          /* The operand identifier from the
+                                  enum above */
+
+  char *       name;           /* Symbolic name of this operand */
+  
+  unsigned int bits;           /* The number of bits used by this
+                                  operand */
+
+  unsigned int shift;          /* How far to the right the operand
+                                  should be shifted so that it is
+                                  aligned at the beginning of the
+                                  word */
+
+  unsigned int hint;           /* A bitwise-inclusive-OR of the
+                                  values shown below.  These are used
+                                  tell the disassembler how to print
+                                  this operand */
+};
+
+/* Values for operand hint */
+#define OH_SILENT      0x01    /* dont print this operand */
+#define OH_ADDR                0x02    /* this operand is an address */
+#define OH_REG         0x04    /* this operand is a register */
+#define OH_SPR         0x08    /* this operand is an SPR */
+#define OH_TBR         0x10    /* this operand is a TBR */
+#define OH_OFFSET      0x20    /* this operand is an offset */
+#define OH_LITERAL      0x40    /* a literal string */
+
+\f
+/*======================================================================
+ *
+ *  OPCODES
+ *
+ *======================================================================*/
+
+/* From the MPCxxx instruction set documentation, all instructions are 
+ * 32 bits long and word aligned.  Bits 0-5 always specify the primary 
+ * opcode.  Many instructions also have an extended opcode.
+ */
+
+#define GET_OPCD(i) (((unsigned long)(i) >> 26) & 0x3f)
+#define MAKE_OPCODE(i) ((((unsigned long)(i)) & 0x3f) << 26)
+
+/* The MPC860 User's Manual, Appendix D.4 contains the definitions of the
+ * instruction forms
+ */
+
+
+/*-------------------------------------------------
+ *              I-Form Instructions:               
+ * bX                                              
+ *-------------------------------------------------
+ * OPCD |           LI                       |AA|LK 
+ *-------------------------------------------------*/
+
+#define I_OPCODE(i,aa,lk) (MAKE_OPCODE(i) | (((aa) & 0x1) << 1) | ((lk) & 0x1))
+#define I_MASK I_OPCODE(0x3f,0x1,0x1)
+
+
+/*-------------------------------------------------
+ *              B-Form Instructions:               
+ * bcX                                             
+ *-------------------------------------------------
+ * OPCD |    BO   |  BI  |   BD              |AA|LK 
+ *-------------------------------------------------*/
+
+#define B_OPCODE(i,aa,lk) (MAKE_OPCODE(i) | (((aa) & 0x1) << 1) | ((lk) & 0x1))
+#define B_MASK B_OPCODE(0x3f,0x1,0x1)
+
+
+/*-------------------------------------------------
+ *             SC-Form Instructions:               
+ * sc                                              
+ *-------------------------------------------------
+ * OPCD | 00000 | 00000 | 00000000000000       |1|0 
+ *-------------------------------------------------*/
+
+#define SC_OPCODE(i) (MAKE_OPCODE(i) | 0x2)
+#define SC_MASK SC_OPCODE(0x3f)
+
+
+/*-------------------------------------------------
+ *             D-Form Instructions:                
+ * addi addic addic. addis andi. andis. cmpi cmpli 
+ * lbz lbzu lha lhau lhz lhzu lmw lwz lwzu mulli   
+ * ori oris stb stbu sth sthu stmw stw stwu subfic 
+ * twi xori xoris                                  
+ *-------------------------------------------------
+ * OPCD |   D    |   A   |            d            
+ * OPCD |   D    |   A   |           SIMM          
+ * OPCD |   S    |   A   |            d            
+ * OPCD |   S    |   A   |           UIMM          
+ * OPCD |crfD|0|L|   A   |           SIMM          
+ * OPCD |crfD|0|L|   A   |           UIMM          
+ * OPCD |   TO   |   A   |           SIMM          
+ *-------------------------------------------------*/
+
+#define D_OPCODE(i) MAKE_OPCODE(i)
+#define D_MASK MAKE_OPCODE(0x3f)
+
+
+/*-------------------------------------------------
+ *            DS-Form Instructions:                
+ * (none supported by MPC860)                      
+ *-------------------------------------------------
+ * OPCD |   D    |   A   |          ds          |XO 
+ * OPCD |   S    |   A   |          ds          |XO 
+ *-------------------------------------------------*/
+
+#define DS_OPCODE(i,xo) (MAKE_OPCODE(i) | ((xo) & 0x3))
+#define DS_MASK DS_OPCODE(0x3f,0x1)
+
+
+/*---------------------------------------------------
+ *            X-Form Instructions:                   
+ * andX andcX cmp cmpl cntlzwX dcbf dcbi dcbst dcbt  
+ * dcbtst dcbz eciwx ecowx eieio eqvX extsbX extshX  
+ * icbi lbzux lbxz lhaux lhax lhbrx lhzux lhxz lswi  
+ * lswx lwarx lwbrx lwzux lwxz mcrfs mcrxr mfcr      
+ * mfmsr mfsr mfsrin mtmsr mtsr mtsrin nandX norX    
+ * orX orcX slwX srawX srawiX srwX stbux stbx        
+ * sthbrx sthuxsthx stswi stswx stwbrx stwcx. stwux  
+ * stwx sync tlbie tlbld tlbli tlbsync tw xorX       
+ *---------------------------------------------------
+ * OPCD |   D    |    A   |    B   |      XO      |0  
+ * OPCD |   D    |    A   |   NB   |      XO      |0  
+ * OPCD |   D    |  00000 |    B   |      XO      |0  
+ * OPCD |   D    |  00000 |  00000 |      XO      |0  
+ * OPCD |   D    |0|  SR  |  00000 |      XO      |0  
+ * OPCD |   S    |    A   |    B   |      XO      |Rc 
+ * OPCD |   S    |    A   |    B   |      XO      |1  
+ * OPCD |   S    |    A   |    B   |      XO      |0  
+ * OPCD |   S    |    A   |   NB   |      XO      |0  
+ * OPCD |   S    |    A   |  00000 |      XO      |Rc 
+ * OPCD |   S    |  00000 |    B   |      XO      |0  
+ * OPCD |   S    |  00000 |  00000 |      XO      |0  
+ * OPCD |   S    |0|  SR  |  00000 |      XO      |0  
+ * OPCD |   S    |    A   |   SH   |      XO      |Rc 
+ * OPCD |crfD|0|L|    A   |   SH   |      XO      |0  
+ * OPCD |crfD |00|    A   |    B   |      XO      |0  
+ * OPCD |crfD |00|crfS |00|  00000 |      XO      |0  
+ * OPCD |crfD |00|  00000 |  00000 |      XO      |0  
+ * OPCD |crfD |00|  00000 | IMM  |0|      XO      |Rc 
+ * OPCD |   TO   |    A   |    B   |      XO      |0  
+ * OPCD |   D    |  00000 |    B   |      XO      |Rc 
+ * OPCD |   D    |  00000 |  00000 |      XO      |Rc 
+ * OPCD |  crbD  |  00000 |  00000 |      XO      |Rc 
+ * OPCD |  00000 |    A   |    B   |      XO      |0  
+ * OPCD |  00000 |  00000 |    B   |      XO      |0  
+ * OPCD |  00000 |  00000 |  00000 |      XO      |0  
+ *---------------------------------------------------*/
+
+#define X_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x3ff) << 1) | \
+                          ((rc) & 0x1))
+#define X_MASK X_OPCODE(0x3f,0x3ff,0x1)
+     
+
+/*---------------------------------------------------
+ *            XL-Form Instructions:                  
+ * bcctrX bclrX crand crandc creqv crnand crnor cror 
+ * croc crxorisync mcrf rfi                          
+ *---------------------------------------------------
+ * OPCD |   BO   |  BI    |  00000 |      XO      |LK 
+ * OPCD |  crbD  | crbA   |  crbB  |      XO      |0  
+ * OPCD |crfD |00|crfS |00|  00000 |      XO      |0  
+ * OPCD |  00000 |  00000 |  00000 |      XO      |0  
+ *---------------------------------------------------*/
+
+#define XL_OPCODE(i,xo,lk) (MAKE_OPCODE(i) | (((xo) & 0x3ff) << 1) | \
+                           ((lk) & 0x1))
+#define XL_MASK XL_OPCODE(0x3f,0x3ff,0x1)
+
+
+/*---------------------------------------------------
+ *            XFX-Form Instructions:                  
+ * mfspr mftb mtcrf mtspr                            
+ *---------------------------------------------------
+ * OPCD |   D    |      spr        |      XO       |0
+ * OPCD |   D    |0|    CRM      |0|      XO       |0
+ * OPCD |   S    |      spr        |      XO       |0
+ * OPCD |   D    |      tbr        |      XO       |0
+ *---------------------------------------------------*/
+
+#define XFX_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x3ff) << 1) | \
+                            ((rc) & 0x1))
+#define XFX_MASK XFX_OPCODE(0x3f,0x3ff,0x1)
+
+
+/*---------------------------------------------------
+ *            XFL-Form Instructions:                  
+ * (none supported by MPC860)                      
+ *---------------------------------------------------
+ * OPCD |0|      FM     |0|   B    |      XO       |0
+ *---------------------------------------------------*/
+
+#define XFL_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x3ff) << 1) | \
+                            ((rc) & 0x1))
+#define XFL_MASK XFL_OPCODE(0x3f,0x3ff,0x1)
+
+
+/*---------------------------------------------------
+ *            XS-Form Instructions:                  
+ * (none supported by MPC860)                      
+ *---------------------------------------------------
+ * OPCD |    S   |   A    |   sh   |      XO   |sh|LK
+ *---------------------------------------------------*/
+
+#define XS_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x1ff) << 2) | \
+                            ((rc) & 0x1))
+#define XS_MASK XS_OPCODE(0x3f,0x1ff,0x1)
+
+
+/*---------------------------------------------------
+ *            XO-Form Instructions:                  
+ * addX addcXaddeX addmeX addzeX divwX divwuX mulhwX
+ * mulhwuX mullwX negX subfX subfcX subfeX subfmeX
+ * subfzeX
+ *---------------------------------------------------
+ * OPCD |    D   |   A    |    B   |OE|     XO    |Rc
+ * OPCD |    D   |   A    |    B   |0 |     XO    |Rc
+ * OPCD |    D   |   A    |  00000 |OE|     XO    |Rc
+ *---------------------------------------------------*/
+
+#define XO_OPCODE(i,xo,oe,rc) (MAKE_OPCODE(i) | (((oe) & 0x1) << 10) | \
+                              (((xo) & 0x1ff) << 1) | ((rc) & 0x1))
+#define XO_MASK XO_OPCODE(0x3f,0x1ff,0x1,0x1)
+
+
+/*---------------------------------------------------
+ *            A-Form Instructions:                  
+ * (none supported by MPC860)                      
+ *---------------------------------------------------
+ * OPCD |    D   |   A    |    B   |00000|  XO    |Rc
+ * OPCD |    D   |   A    |    B   |  C  |  XO    |Rc
+ * OPCD |    D   |   A    |  00000 |  C  |  XO    |Rc
+ * OPCD |    D   |  00000 |    B   |00000|  XO    |Rc
+ *---------------------------------------------------*/
+
+#define A_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x1f) << 1) | \
+                          ((rc) & 0x1))
+#define A_MASK A_OPCODE(0x3f,0x1f,0x1)
+
+
+/*---------------------------------------------------
+ *            M-Form Instructions:
+ * rlwimiX rlwinmX rlwnmX
+ *---------------------------------------------------
+ * OPCD |    S   |   A    |    SH   |  MB |  ME   |Rc
+ * OPCD |    S   |   A    |     B   |  MB |  ME   |Rc
+ *---------------------------------------------------*/
+
+#define M_OPCODE(i,rc) (MAKE_OPCODE(i) | ((rc) & 0x1))
+#define M_MASK M_OPCODE(0x3f,0x1)
+
+
+/*---------------------------------------------------
+ *            MD-Form Instructions:
+ * (none supported by MPC860)                      
+ *---------------------------------------------------
+ * OPCD |    S   |   A    |    sh   |  mb | XO |sh|Rc
+ * OPCD |    S   |   A    |    sh   |  me | XO |sh|Rc
+ *---------------------------------------------------*/
+
+#define MD_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x7) << 2) | \
+                          ((rc) & 0x1))
+#define MD_MASK MD_OPCODE(0x3f,0x7,0x1)
+
+
+/*---------------------------------------------------
+ *            MDS-Form Instructions:
+ * (none supported by MPC860)                      
+ *---------------------------------------------------
+ * OPCD |    S   |   A    |    B    |  mb | XO    |Rc
+ * OPCD |    S   |   A    |    B    |  me | XO    |Rc
+ *---------------------------------------------------*/
+
+#define MDS_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0xf) << 1) | \
+                          ((rc) & 0x1))
+#define MDS_MASK MDS_OPCODE(0x3f,0xf,0x1)
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+#define INSTRUCTION( memaddr ) ntohl(*(unsigned long *)(memaddr))
+
+#define MAX_OPERANDS  8
+
+struct ppc_ctx;
+
+struct opcode {
+  unsigned long        opcode;         /* The complete opcode as produced by
+                                  one of the XXX_OPCODE macros above */
+
+  unsigned long        mask;           /* The mask to use on an instruction
+                                  before comparing with the opcode
+                                  field to see if it matches */
+
+  enum OP_FIELD        fields[MAX_OPERANDS];
+                               /* An array defining the operands for
+                                  this opcode.  The values of the
+                                  array are the operand identifiers */
+
+  int (*hfunc)(struct ppc_ctx *);
+                               /* Address of a function to handle the given
+                                  mnemonic */
+
+  char *       name;           /* The symbolic name of this opcode */
+
+  unsigned int hint;           /* A bitwise-inclusive-OR of the
+                                  values shown below.  These are used
+                                  tell the disassembler how to print
+                                  some operands for this opcode */
+};
+
+/* values for opcode hints */
+#define H_RELATIVE     0x1     /* The address operand is relative */
+#define H_IMM_HIGH     0x2     /* [U|S]IMM field shifted high */
+#define H_RA0_IS_0     0x4     /* If rA = 0 then treat as literal 0 */
+
+struct ppc_ctx {
+  struct opcode *      op;
+  unsigned long                instr;
+  unsigned int         flags;
+  int                  datalen;
+  char                 data[ 256 ];
+  char                 radix_fmt[ 8 ];
+  unsigned char *      virtual;
+};
+
+
+/*======================================================================
+ *
+ *  FUNCTIONS
+ *
+ *======================================================================*/
+
+/* Values for flags as passed to various ppc routines */
+#define F_RADOCTAL     0x1     /* output radix = unsigned octal */
+#define F_RADUDECIMAL  0x2     /* output radix = unsigned decimal */
+#define F_RADSDECIMAL  0x4     /* output radix = signed decimal */
+#define F_RADHEX       0x8     /* output radix = unsigned hex */
+#define F_SIMPLE       0x10    /* use simplified mnemonics */
+#define F_SYMBOL       0x20    /* use symbol lookups for addresses */
+#define F_INSTR                0x40    /* output the raw instruction */
+#define F_LOCALMEM     0x80    /* retrieve opcodes from local memory
+                                  rather than from the HMI */
+#define F_LINENO       0x100   /* show line number info if available */
+#define F_VALIDONLY    0x200   /* cache: valid entries only */
+
+/* Values for assembler error codes */
+#define E_ASM_BAD_OPCODE       1
+#define E_ASM_NUM_OPERANDS     2
+#define E_ASM_BAD_REGISTER     3
+#define E_ASM_BAD_SPR          4
+#define E_ASM_BAD_TBR          5
+
+extern int disppc __P((unsigned char *,unsigned char *,int,
+                      int (*)(const char *), unsigned long));
+extern int print_source_line __P((char *,char *,int,
+                                 int (*pfunc)(const char *)));
+extern int find_next_address __P((unsigned char *,int,struct pt_regs *));
+extern int handle_bc __P((struct ppc_ctx *));
+extern unsigned long asmppc __P((unsigned long,char*,int*));
+extern char *asm_error_str __P((int));
+
+/*======================================================================
+ *
+ *  GLOBAL VARIABLES
+ *
+ *======================================================================*/
+
+extern struct operand operands[];
+extern const unsigned int n_operands;
+extern struct opcode opcodes[];
+extern const unsigned int n_opcodes;
+
+#endif /* _PPC_H */
+
+
+/*
+ * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ * 
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
diff --git a/include/bedbug/regs.h b/include/bedbug/regs.h
new file mode 100644 (file)
index 0000000..93c7e0c
--- /dev/null
@@ -0,0 +1,397 @@
+/* $Id: regs.h,v 1.1 2001/05/31 22:12:27 wd Exp $ */
+
+#ifndef _REGS_H
+#define _REGS_H
+
+/* Special Purpose Registers */
+
+#define SPR_CR         -1
+#define SPR_MSR                -2
+
+#define SPR_XER                1
+#define SPR_LR         8
+#define SPR_CTR                9
+#define SPR_DSISR      18
+#define SPR_DAR                19
+#define SPR_DEC                22
+#define SPR_SRR0       26
+#define SPR_SRR1       27
+#define SPR_EIE                80
+#define SPR_EID                81
+#define SPR_CMPA       144
+#define SPR_CMPB       145
+#define SPR_CMPC       146
+#define SPR_CMPD       147
+#define SPR_ICR                148
+#define SPR_DER                149
+#define SPR_COUNTA     150
+#define SPR_COUNTB     151
+#define SPR_CMPE       152
+#define SPR_CMPF       153
+#define SPR_CMPG       154
+#define SPR_CMPH       155
+#define SPR_LCTRL1     156
+#define SPR_LCTRL2     157
+#define SPR_ICTRL      158
+#define SPR_BAR                159
+#define SPR_USPRG0      256
+#define SPR_SPRG4_RO    260
+#define SPR_SPRG5_RO    261
+#define SPR_SPRG6_RO    262
+#define SPR_SPRG7_RO    263
+#define SPR_SPRG0      272
+#define SPR_SPRG1      273
+#define SPR_SPRG2      274
+#define SPR_SPRG3      275
+#define SPR_SPRG4       276
+#define SPR_SPRG5       277
+#define SPR_SPRG6       278
+#define SPR_SPRG7       279
+#define SPR_TBL         284
+#define SPR_TBU         285
+#define SPR_PVR                287
+#define SPR_IC_CST     560
+#define SPR_IC_ADR     561
+#define SPR_IC_DAT     562
+#define SPR_DC_CST     568
+#define SPR_DC_ADR     569
+#define SPR_DC_DAT     570
+#define SPR_DPDR       630
+#define SPR_IMMR       638
+#define SPR_MI_CTR     784
+#define SPR_MI_AP      786
+#define SPR_MI_EPN     787
+#define SPR_MI_TWC     789
+#define SPR_MI_RPN     790
+#define SPR_MD_CTR     792
+#define SPR_M_CASID    793
+#define SPR_MD_AP      794
+#define SPR_MD_EPN     795
+#define SPR_M_TWB      796
+#define SPR_MD_TWC     797
+#define SPR_MD_RPN     798
+#define SPR_M_TW       799
+#define SPR_MI_DBCAM   816
+#define SPR_MI_DBRAM0  817
+#define SPR_MI_DBRAM1  818
+#define SPR_MD_DBCAM   824
+#define SPR_MD_DBRAM0  825
+#define SPR_MD_DBRAM1  826
+#define SPR_ZPR         944
+#define SPR_PID         945
+#define SPR_CCR0        947
+#define SPR_IAC3        948
+#define SPR_IAC4        949
+#define SPR_DVC1        950
+#define SPR_DVC2        951
+#define SPR_SGR         953
+#define SPR_DCWR        954
+#define SPR_SLER        955
+#define SPR_SU0R        956
+#define SPR_DBCR1       957
+#define SPR_ICDBDR      979
+#define SPR_ESR         980
+#define SPR_DEAR        981
+#define SPR_EVPR        982
+#define SPR_TSR         984
+#define SPR_TCR         986
+#define SPR_PIT         987
+#define SPR_SRR2        990
+#define SPR_SRR3        991
+#define SPR_DBSR        1008
+#define SPR_DBCR0       1010
+#define SPR_IAC1        1012
+#define SPR_IAC2        1013
+#define SPR_DAC1        1014
+#define SPR_DAC2        1015
+#define SPR_DCCR        1018
+#define SPR_ICCR        1019
+
+/* Bits for the DBCR0 register */
+#define DBCR0_EDM      0x80000000
+#define DBCR0_IDM      0x40000000
+#define DBCR0_RST      0x30000000
+#define DBCR0_IC       0x08000000
+#define DBCR0_BT       0x04000000
+#define DBCR0_EDE      0x02000000
+#define DBCR0_TDE      0x01000000
+#define DBCR0_IA1      0x00800000
+#define DBCR0_IA2      0x00400000
+#define DBCR0_IA12     0x00200000
+#define DBCR0_IA12X    0x00100000
+#define DBCR0_IA3      0x00080000
+#define DBCR0_IA4      0x00040000
+#define DBCR0_IA34     0x00020000
+#define DBCR0_IA34X    0x00010000
+#define DBCR0_IA12T    0x00008000
+#define DBCR0_IA34T    0x00004000
+#define DBCR0_FT       0x00000001
+
+/* Bits for the DBCR1 register */
+#define DBCR1_D1R      0x80000000
+#define DBCR1_D2R      0x40000000
+#define DBCR1_D1W      0x20000000
+#define DBCR1_D2W      0x10000000
+#define DBCR1_D1S      0x0C000000
+#define DBCR1_D2S      0x03000000
+#define DBCR1_DA12     0x00800000
+#define DBCR1_DA12X    0x00400000
+#define DBCR1_DV1M     0x000C0000
+#define DBCR1_DV2M     0x00030000
+#define DBCR1_DV1BE    0x0000F000
+#define DBCR1_DV2BE    0x00000F00
+
+/* Bits for the DBSR register */
+#define DBSR_IC                0x80000000
+#define DBSR_BT                0x40000000
+#define DBSR_EDE       0x20000000
+#define DBSR_TIE       0x10000000
+#define DBSR_UDE       0x08000000
+#define DBSR_IA1       0x04000000
+#define DBSR_IA2       0x02000000
+#define DBSR_DR1       0x01000000
+#define DBSR_DW1       0x00800000
+#define DBSR_DR2       0x00400000
+#define DBSR_DW2       0x00200000
+#define DBSR_IDE       0x00100000
+#define DBSR_IA3       0x00080000
+#define DBSR_IA4       0x00040000
+#define DBSR_MRR       0x00000300
+
+struct spr_info {
+  int  spr_val;
+  char spr_name[ 10 ];
+};
+
+extern struct spr_info spr_map[];
+extern const unsigned int n_sprs;
+
+
+#define SET_REGISTER( str, val ) \
+({ unsigned long __value = (val); \
+  asm volatile( str : : "r" (__value)); \
+  __value; })
+
+#define        GET_REGISTER( str ) \
+({ unsigned long __value; \
+  asm volatile( str : "=r" (__value) : ); \
+  __value; })
+
+#define         GET_CR()            GET_REGISTER( "mfcr %0" )
+#define         SET_CR(val)         SET_REGISTER( "mtcr %0", val )
+#define         GET_MSR()           GET_REGISTER( "mfmsr %0" )
+#define         SET_MSR(val)        SET_REGISTER( "mtmsr %0", val )
+#define         GET_XER()           GET_REGISTER( "mfspr %0,1" )
+#define         SET_XER(val)        SET_REGISTER( "mtspr 1,%0", val )
+#define         GET_LR()            GET_REGISTER( "mfspr %0,8" )
+#define         SET_LR(val)         SET_REGISTER( "mtspr 8,%0", val )
+#define         GET_CTR()           GET_REGISTER( "mfspr %0,9" )
+#define         SET_CTR(val)        SET_REGISTER( "mtspr 9,%0", val )
+#define         GET_DSISR()         GET_REGISTER( "mfspr %0,18" )
+#define         SET_DSISR(val)      SET_REGISTER( "mtspr 18,%0", val )
+#define         GET_DAR()           GET_REGISTER( "mfspr %0,19" )
+#define         SET_DAR(val)        SET_REGISTER( "mtspr 19,%0", val )
+#define         GET_DEC()           GET_REGISTER( "mfspr %0,22" )
+#define         SET_DEC(val)        SET_REGISTER( "mtspr 22,%0", val )
+#define         GET_SRR0()          GET_REGISTER( "mfspr %0,26" )
+#define         SET_SRR0(val)       SET_REGISTER( "mtspr 26,%0", val )
+#define         GET_SRR1()          GET_REGISTER( "mfspr %0,27" )
+#define         SET_SRR1(val)       SET_REGISTER( "mtspr 27,%0", val )
+#define         GET_EIE()           GET_REGISTER( "mfspr %0,80" )
+#define         SET_EIE(val)        SET_REGISTER( "mtspr 80,%0", val )
+#define         GET_EID()           GET_REGISTER( "mfspr %0,81" )
+#define         SET_EID(val)        SET_REGISTER( "mtspr 81,%0", val )
+#define         GET_CMPA()          GET_REGISTER( "mfspr %0,144" )
+#define         SET_CMPA(val)       SET_REGISTER( "mtspr 144,%0", val )
+#define         GET_CMPB()          GET_REGISTER( "mfspr %0,145" )
+#define         SET_CMPB(val)       SET_REGISTER( "mtspr 145,%0", val )
+#define         GET_CMPC()          GET_REGISTER( "mfspr %0,146" )
+#define         SET_CMPC(val)       SET_REGISTER( "mtspr 146,%0", val )
+#define         GET_CMPD()          GET_REGISTER( "mfspr %0,147" )
+#define         SET_CMPD(val)       SET_REGISTER( "mtspr 147,%0", val )
+#define         GET_ICR()           GET_REGISTER( "mfspr %0,148" )
+#define         SET_ICR(val)        SET_REGISTER( "mtspr 148,%0", val )
+#define         GET_DER()           GET_REGISTER( "mfspr %0,149" )
+#define         SET_DER(val)        SET_REGISTER( "mtspr 149,%0", val )
+#define         GET_COUNTA()        GET_REGISTER( "mfspr %0,150" )
+#define         SET_COUNTA(val)     SET_REGISTER( "mtspr 150,%0", val )
+#define         GET_COUNTB()        GET_REGISTER( "mfspr %0,151" )
+#define         SET_COUNTB(val)     SET_REGISTER( "mtspr 151,%0", val )
+#define         GET_CMPE()          GET_REGISTER( "mfspr %0,152" )
+#define         SET_CMPE(val)       SET_REGISTER( "mtspr 152,%0", val )
+#define         GET_CMPF()          GET_REGISTER( "mfspr %0,153" )
+#define         SET_CMPF(val)       SET_REGISTER( "mtspr 153,%0", val )
+#define         GET_CMPG()          GET_REGISTER( "mfspr %0,154" )
+#define         SET_CMPG(val)       SET_REGISTER( "mtspr 154,%0", val )
+#define         GET_CMPH()          GET_REGISTER( "mfspr %0,155" )
+#define         SET_CMPH(val)       SET_REGISTER( "mtspr 155,%0", val )
+#define  GET_LCTRL1()       GET_REGISTER( "mfspr %0,156" )
+#define         SET_LCTRL1(val)     SET_REGISTER( "mtspr 156,%0", val )
+#define  GET_LCTRL2()       GET_REGISTER( "mfspr %0,157" )
+#define         SET_LCTRL2(val)     SET_REGISTER( "mtspr 157,%0", val )
+#define  GET_ICTRL()        GET_REGISTER( "mfspr %0,158" )
+#define         SET_ICTRL(val)      SET_REGISTER( "mtspr 158,%0", val )
+#define  GET_BAR()          GET_REGISTER( "mfspr %0,159" )
+#define         SET_BAR(val)        SET_REGISTER( "mtspr 159,%0", val )
+#define  GET_USPRG0()       GET_REGISTER( "mfspr %0,256" )
+#define         SET_USPRG0(val)     SET_REGISTER( "mtspr 256,%0", val )
+#define  GET_SPRG4_RO()             GET_REGISTER( "mfspr %0,260" )
+#define         SET_SPRG4_RO(val)   SET_REGISTER( "mtspr 260,%0", val )
+#define  GET_SPRG5_RO()             GET_REGISTER( "mfspr %0,261" )
+#define         SET_SPRG5_RO(val)   SET_REGISTER( "mtspr 261,%0", val )
+#define  GET_SPRG6_RO()             GET_REGISTER( "mfspr %0,262" )
+#define         SET_SPRG6_RO(val)   SET_REGISTER( "mtspr 262,%0", val )
+#define  GET_SPRG7_RO()             GET_REGISTER( "mfspr %0,263" )
+#define         SET_SPRG7_RO(val)   SET_REGISTER( "mtspr 263,%0", val )
+#define  GET_SPRG0()        GET_REGISTER( "mfspr %0,272" )
+#define         SET_SPRG0(val)      SET_REGISTER( "mtspr 272,%0", val )
+#define  GET_SPRG1()        GET_REGISTER( "mfspr %0,273" )
+#define         SET_SPRG1(val)      SET_REGISTER( "mtspr 273,%0", val )
+#define  GET_SPRG2()        GET_REGISTER( "mfspr %0,274" )
+#define         SET_SPRG2(val)      SET_REGISTER( "mtspr 274,%0", val )
+#define  GET_SPRG3()        GET_REGISTER( "mfspr %0,275" )
+#define         SET_SPRG3(val)      SET_REGISTER( "mtspr 275,%0", val )
+#define  GET_SPRG4()        GET_REGISTER( "mfspr %0,276" )
+#define         SET_SPRG4(val)      SET_REGISTER( "mtspr 276,%0", val )
+#define  GET_SPRG5()        GET_REGISTER( "mfspr %0,277" )
+#define         SET_SPRG5(val)      SET_REGISTER( "mtspr 277,%0", val )
+#define  GET_SPRG6()        GET_REGISTER( "mfspr %0,278" )
+#define         SET_SPRG6(val)      SET_REGISTER( "mtspr 278,%0", val )
+#define  GET_SPRG7()        GET_REGISTER( "mfspr %0,279" )
+#define         SET_SPRG7(val)      SET_REGISTER( "mtspr 279,%0", val )
+#define  GET_TBL()          GET_REGISTER( "mfspr %0,284" )
+#define         SET_TBL(val)        SET_REGISTER( "mtspr 284,%0", val )
+#define  GET_TBU()          GET_REGISTER( "mfspr %0,285" )
+#define         SET_TBU(val)        SET_REGISTER( "mtspr 285,%0", val )
+#define  GET_PVR()          GET_REGISTER( "mfspr %0,287" )
+#define         SET_PVR(val)        SET_REGISTER( "mtspr 287,%0", val )
+#define  GET_IC_CST()       GET_REGISTER( "mfspr %0,560" )
+#define         SET_IC_CST(val)     SET_REGISTER( "mtspr 560,%0", val )
+#define  GET_IC_ADR()       GET_REGISTER( "mfspr %0,561" )
+#define         SET_IC_ADR(val)     SET_REGISTER( "mtspr 561,%0", val )
+#define  GET_IC_DAT()       GET_REGISTER( "mfspr %0,562" )
+#define         SET_IC_DAT(val)     SET_REGISTER( "mtspr 562,%0", val )
+#define  GET_DC_CST()       GET_REGISTER( "mfspr %0,568" )
+#define         SET_DC_CST(val)     SET_REGISTER( "mtspr 568,%0", val )
+#define  GET_DC_ADR()       GET_REGISTER( "mfspr %0,569" )
+#define         SET_DC_ADR(val)     SET_REGISTER( "mtspr 569,%0", val )
+#define  GET_DC_DAT()       GET_REGISTER( "mfspr %0,570" )
+#define         SET_DC_DAT(val)     SET_REGISTER( "mtspr 570,%0", val )
+#define  GET_DPDR()         GET_REGISTER( "mfspr %0,630" )
+#define         SET_DPDR(val)       SET_REGISTER( "mtspr 630,%0", val )
+#define  GET_IMMR()         GET_REGISTER( "mfspr %0,638" )
+#define         SET_IMMR(val)       SET_REGISTER( "mtspr 638,%0", val )
+#define  GET_MI_CTR()       GET_REGISTER( "mfspr %0,784" )
+#define         SET_MI_CTR(val)     SET_REGISTER( "mtspr 784,%0", val )
+#define  GET_MI_AP()        GET_REGISTER( "mfspr %0,786" )
+#define         SET_MI_AP(val)      SET_REGISTER( "mtspr 786,%0", val )
+#define  GET_MI_EPN()       GET_REGISTER( "mfspr %0,787" )
+#define         SET_MI_EPN(val)     SET_REGISTER( "mtspr 787,%0", val )
+#define  GET_MI_TWC()       GET_REGISTER( "mfspr %0,789" )
+#define         SET_MI_TWC(val)     SET_REGISTER( "mtspr 789,%0", val )
+#define  GET_MI_RPN()       GET_REGISTER( "mfspr %0,790" )
+#define         SET_MI_RPN(val)     SET_REGISTER( "mtspr 790,%0", val )
+#define  GET_MD_CTR()       GET_REGISTER( "mfspr %0,792" )
+#define         SET_MD_CTR(val)     SET_REGISTER( "mtspr 792,%0", val )
+#define  GET_M_CASID()      GET_REGISTER( "mfspr %0,793" )
+#define         SET_M_CASID(val)    SET_REGISTER( "mtspr 793,%0", val )
+#define  GET_MD_AP()        GET_REGISTER( "mfspr %0,794" )
+#define         SET_MD_AP(val)      SET_REGISTER( "mtspr ,794%0", val )
+#define  GET_MD_EPN()       GET_REGISTER( "mfspr %0,795" )
+#define         SET_MD_EPN(val)     SET_REGISTER( "mtspr 795,%0", val )
+#define  GET_M_TWB()        GET_REGISTER( "mfspr %0,796" )
+#define         SET_M_TWB(val)      SET_REGISTER( "mtspr 796,%0", val )
+#define  GET_MD_TWC()       GET_REGISTER( "mfspr %0,797" )
+#define         SET_MD_TWC(val)     SET_REGISTER( "mtspr 797,%0", val )
+#define  GET_MD_RPN()       GET_REGISTER( "mfspr %0,798" )
+#define         SET_MD_RPN(val)     SET_REGISTER( "mtspr 798,%0", val )
+#define  GET_M_TW()         GET_REGISTER( "mfspr %0,799" )
+#define         SET_M_TW(val)       SET_REGISTER( "mtspr 799,%0", val )
+#define  GET_MI_DBCAM()      GET_REGISTER( "mfspr %0,816" )
+#define         SET_MI_DBCAM(val)   SET_REGISTER( "mtspr 816,%0", val )
+#define  GET_MI_DBRAM0()     GET_REGISTER( "mfspr %0,817" )
+#define         SET_MI_DBRAM0(val)  SET_REGISTER( "mtspr 817,%0", val )
+#define  GET_MI_DBRAM1()     GET_REGISTER( "mfspr %0,818" )
+#define         SET_MI_DBRAM1(val)  SET_REGISTER( "mtspr 818,%0", val )
+#define  GET_MD_DBCAM()      GET_REGISTER( "mfspr %0,824" )
+#define         SET_MD_DBCA(val)    SET_REGISTER( "mtspr 824,%0", val )
+#define  GET_MD_DBRAM0()     GET_REGISTER( "mfspr %0,825" )
+#define         SET_MD_DBRAM0(val)  SET_REGISTER( "mtspr 825,%0", val )
+#define  GET_MD_DBRAM1()     GET_REGISTER( "mfspr %0,826" )
+#define         SET_MD_DBRAM1(val)  SET_REGISTER( "mtspr 826,%0", val )
+#define  GET_ZPR()           GET_REGISTER( "mfspr %0,944" )
+#define         SET_ZPR(val)        SET_REGISTER( "mtspr 944,%0", val )
+#define  GET_PID()          GET_REGISTER( "mfspr %0,945" )
+#define         SET_PID(val)        SET_REGISTER( "mtspr 945,%0", val )
+#define  GET_CCR0()         GET_REGISTER( "mfspr %0,947" )
+#define         SET_CCR0(val)       SET_REGISTER( "mtspr 947,%0", val )
+#define         GET_IAC3()          GET_REGISTER( "mfspr %0,948" )
+#define         SET_IAC3(val)       SET_REGISTER( "mtspr 948,%0", val )
+#define         GET_IAC4()          GET_REGISTER( "mfspr %0,949" )
+#define         SET_IAC4(val)       SET_REGISTER( "mtspr 949,%0", val )
+#define         GET_DVC1()          GET_REGISTER( "mfspr %0,950" )
+#define         SET_DVC1(val)       SET_REGISTER( "mtspr 950,%0", val )
+#define         GET_DVC2()          GET_REGISTER( "mfspr %0,951" )
+#define         SET_DVC2(val)       SET_REGISTER( "mtspr 951,%0", val )
+#define         GET_SGR()           GET_REGISTER( "mfspr %0,953" )
+#define         SET_SGR(val)        SET_REGISTER( "mtspr 953,%0", val )
+#define         GET_DCWR()          GET_REGISTER( "mfspr %0,954" )
+#define         SET_DCWR(val)       SET_REGISTER( "mtspr 954,%0", val )
+#define         GET_SLER()          GET_REGISTER( "mfspr %0,955" )
+#define         SET_SLER(val)       SET_REGISTER( "mtspr 955,%0", val )
+#define         GET_SU0R()          GET_REGISTER( "mfspr %0,956" )
+#define         SET_SU0R(val)       SET_REGISTER( "mtspr 956,%0", val )
+#define         GET_DBCR1()         GET_REGISTER( "mfspr %0,957" )
+#define         SET_DBCR1(val)      SET_REGISTER( "mtspr 957,%0", val )
+#define         GET_ICDBDR()        GET_REGISTER( "mfspr %0,979" )
+#define         SET_ICDBDR(val)     SET_REGISTER( "mtspr 979,%0", val )
+#define         GET_ESR()           GET_REGISTER( "mfspr %0,980" )
+#define         SET_ESR(val)        SET_REGISTER( "mtspr 980,%0", val )
+#define         GET_DEAR()          GET_REGISTER( "mfspr %0,981" )
+#define         SET_DEAR(val)       SET_REGISTER( "mtspr 981,%0", val )
+#define         GET_EVPR()          GET_REGISTER( "mfspr %0,982" )
+#define         SET_EVPR(val)       SET_REGISTER( "mtspr 982,%0", val )
+#define         GET_TSR()           GET_REGISTER( "mfspr %0,984" )
+#define         SET_TSR(val)        SET_REGISTER( "mtspr 984,%0", val )
+#define         GET_TCR()           GET_REGISTER( "mfspr %0,986" )
+#define         SET_TCR(val)        SET_REGISTER( "mtspr 986,%0", val )
+#define         GET_PIT()           GET_REGISTER( "mfspr %0,987" )
+#define         SET_PIT(val)        SET_REGISTER( "mtspr 987,%0", val )
+#define         GET_SRR2()          GET_REGISTER( "mfspr %0,990" )
+#define         SET_SRR2(val)       SET_REGISTER( "mtspr 990,%0", val )
+#define         GET_SRR3()          GET_REGISTER( "mfspr %0,991" )
+#define         SET_SRR3(val)       SET_REGISTER( "mtspr 991,%0", val )
+#define         GET_DBSR()          GET_REGISTER( "mfspr %0,1008" )
+#define         SET_DBSR(val)       SET_REGISTER( "mtspr 1008,%0", val )
+#define         GET_DBCR0()         GET_REGISTER( "mfspr %0,1010" )
+#define         SET_DBCR0(val)      SET_REGISTER( "mtspr 1010,%0", val )
+#define         GET_IAC1()          GET_REGISTER( "mfspr %0,1012" )
+#define         SET_IAC1(val)       SET_REGISTER( "mtspr 1012,%0", val )
+#define         GET_IAC2()          GET_REGISTER( "mfspr %0,1013" )
+#define         SET_IAC2(val)       SET_REGISTER( "mtspr 1013,%0", val )
+#define         GET_DAC1()          GET_REGISTER( "mfspr %0,1014" )
+#define         SET_DAC1(val)       SET_REGISTER( "mtspr 1014,%0", val )
+#define         GET_DAC2()          GET_REGISTER( "mfspr %0,1015" )
+#define         SET_DAC2(val)       SET_REGISTER( "mtspr 1015,%0", val )
+#define         GET_DCCR()          GET_REGISTER( "mfspr %0,1018" )
+#define         SET_DCCR(val)       SET_REGISTER( "mtspr 1018,%0", val )
+#define         GET_ICCR()          GET_REGISTER( "mfspr %0,1019" )
+#define         SET_ICCR(val)       SET_REGISTER( "mtspr 1019,%0", val )
+
+#endif /* _REGS_H */
+
+
+/*
+ * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ * 
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
diff --git a/include/bedbug/tables.h b/include/bedbug/tables.h
new file mode 100644 (file)
index 0000000..f04c6c8
--- /dev/null
@@ -0,0 +1,601 @@
+/* $Id: tables.h,v 1.1 2001/05/31 22:12:27 wd Exp $ */
+
+#ifndef TABLES_H
+#define TABLES_H
+
+/* This is only included by common/bedbug.c, and depends on the following
+ * files to already be included
+ *   ppcboot.h
+ *   bedbug/bedbug.h
+ *   bedbug/ppc.h
+ *   bedbug/regs.h
+ */
+
+struct operand operands[] = {
+  /*Field    Name     Bits  Shift  Hint                   Position     */
+  /*-----    ------   ----- -----  ----                   ------------ */
+  { O_AA,    "O_AA",    1,     1,  OH_SILENT },                /*   30         */
+  { O_BD,    "O_BD",   14,     2,  OH_ADDR },          /* 16-29        */
+  { O_BI,    "O_BI",    5,    16,  0 },                        /* 11-15        */
+  { O_BO,    "O_BO",    5,    21,  0 },                        /*  6-10        */
+  { O_crbD,  "O_crbD",  5,    21,  0 },                        /*  6-10        */
+  { O_crbA,  "O_crbA",  5,    16,  0 },                        /* 11-15        */
+  { O_crbB,  "O_crbB",  5,    11,  0 },                        /* 16-20        */
+  { O_CRM,   "O_CRM",   8,    12,  0 },                        /* 12-19        */
+  { O_d,     "O_d",    15,     0,  OH_OFFSET },                /* 16-31        */
+  { O_frC,   "O_frC",   5,     6,  0 },                        /* 21-25        */
+  { O_frD,   "O_frD",   5,    21,  0 },                        /*  6-10        */
+  { O_frS,   "O_frS",   5,    21,  0 },                        /*  6-10        */
+  { O_IMM,   "O_IMM",   4,    12,  0 },                        /* 16-19        */
+  { O_LI,    "O_LI",   24,     2,  OH_ADDR },          /*  6-29        */
+  { O_LK,    "O_LK",    1,     0,  OH_SILENT },                /*   31         */
+  { O_MB,    "O_MB",    5,     6,  0 },                        /* 21-25        */
+  { O_ME,    "O_ME",    5,     1,  0 },                        /* 26-30        */
+  { O_NB,    "O_NB",    5,    11,  0 },                        /* 16-20        */
+  { O_OE,    "O_OE",    1,    10,  OH_SILENT },                /*   21         */
+  { O_rA,    "O_rA",    5,    16,  OH_REG },           /* 11-15        */
+  { O_rB,    "O_rB",    5,    11,  OH_REG },           /* 16-20        */
+  { O_Rc,    "O_Rc",    1,     0,  OH_SILENT },                /*   31         */
+  { O_rD,    "O_rD",    5,    21,  OH_REG },           /*  6-10        */
+  { O_rS,    "O_rS",    5,    21,  OH_REG },           /*  6-10        */
+  { O_SH,    "O_SH",    5,    11,  0 },                        /* 16-20        */
+  { O_SIMM,  "O_SIMM", 16,     0,  0 },                        /* 16-31        */
+  { O_SR,    "O_SR",    4,    16,  0 },                        /* 12-15        */
+  { O_TO,    "O_TO",    5,    21,  0 },                        /*  6-10        */
+  { O_UIMM,  "O_UIMM", 16,     0,  0 },                        /* 16-31        */
+  { O_crfD,  "O_crfD",  3,    23,  0 },                        /*  6- 8        */
+  { O_crfS,  "O_crfS",  3,    18,  0 },                        /* 11-13        */
+  { O_L,     "O_L",     1,    21,  0 },                        /*   10         */
+  { O_spr,   "O_spr",  10,    11,  OH_SPR },           /* 11-20        */
+  { O_tbr,   "O_tbr",  10,    11,  OH_TBR },           /* 11-20        */
+  { O_cr2,   "O_cr2",   0,     0,  OH_LITERAL },        /* "cr2"        */
+};
+
+const unsigned int n_operands = sizeof(operands) / sizeof(operands[0]);
+
+/* A note about the fields array in the opcodes structure:
+   The operands are listed in the order they appear in the output.
+
+   This table is arranged in numeric order of the opcode.  Note that some
+   opcodes have defined bits in odd places so not all forms of a command
+   will be in the same place.  This is done so that a binary search can be
+   done to find the opcodes.  Note that table D.2 in the MPC860 User's
+   Manual "Instructions Sorted by Opcode" does not account for these
+   bit locations */
+
+struct opcode opcodes[] = {
+  { D_OPCODE(3),           D_MASK,   {O_TO, O_rA, O_SIMM, 0},
+    0,               "twi",          0 },
+  { D_OPCODE(7),           D_MASK,   {O_rD, O_rA, O_SIMM, 0},
+    0,               "mulli",        0 },
+  { D_OPCODE(8),           D_MASK,   {O_rD, O_rA, O_SIMM, 0},
+    0,               "subfic",       0 },
+  { D_OPCODE(10),          D_MASK,   {O_crfD, O_L, O_rA, O_UIMM, 0},
+    0,               "cmpli",        0 },
+  { D_OPCODE(11),          D_MASK,   {O_crfD, O_L, O_rA, O_SIMM, 0},
+    0,               "cmpi",         0 },
+  { D_OPCODE(12),          D_MASK,   {O_rD, O_rA, O_SIMM, 0},
+    0,               "addic",        0 },
+  { D_OPCODE(13),          D_MASK,   {O_rD, O_rA, O_SIMM, 0},
+    0,               "addic.",       0 },
+  { D_OPCODE(14),          D_MASK,   {O_rD, O_rA, O_SIMM, 0},
+    0,               "addi",         H_RA0_IS_0 },
+  { D_OPCODE(15),          D_MASK,   {O_rD, O_rA, O_SIMM, 0},
+    0,               "addis",        H_RA0_IS_0|H_IMM_HIGH },
+  { B_OPCODE(16,0,0),      B_MASK,   {O_BO, O_BI, O_BD, O_AA, O_LK, 0},
+    handle_bc,       "bc",           H_RELATIVE },
+  { B_OPCODE(16,0,1),      B_MASK,   {O_BO, O_BI, O_BD, O_AA, O_LK, 0},
+    0,               "bcl",          H_RELATIVE },
+  { B_OPCODE(16,1,0),      B_MASK,   {O_BO, O_BI, O_BD, O_AA, O_LK, 0},
+    0,               "bca",          0 },
+  { B_OPCODE(16,1,1),      B_MASK,   {O_BO, O_BI, O_BD, O_AA, O_LK, 0},
+    0,               "bcla",         0 },
+  { SC_OPCODE(17),         SC_MASK,  {0},
+    0,               "sc",           0 },
+  { I_OPCODE(18,0,0),      I_MASK,   {O_LI, O_AA, O_LK, 0},
+    0,               "b",            H_RELATIVE },
+  { I_OPCODE(18,0,1),      I_MASK,   {O_LI, O_AA, O_LK, 0},
+    0,               "bl",           H_RELATIVE },
+  { I_OPCODE(18,1,0),      I_MASK,   {O_LI, O_AA, O_LK, 0},
+    0,               "ba",           0 },
+  { I_OPCODE(18,1,1),      I_MASK,   {O_LI, O_AA, O_LK, 0},
+    0,               "bla",          0 },
+  { XL_OPCODE(19,0,0),     XL_MASK,  {O_crfD, O_crfS},
+    0,               "mcrf",         0 },
+  { XL_OPCODE(19,16,0),    XL_MASK,  {O_BO, O_BI, O_LK, 0},
+    0,               "bclr",         0 },
+  { XL_OPCODE(19,16,1),    XL_MASK,  {O_BO, O_BI, O_LK, 0},
+    0,               "bclrl",        0 },
+  { XL_OPCODE(19,33,0),    XL_MASK,  {O_crbD, O_crbA, O_crbB, 0},
+    0,               "crnor",        0 },
+  { XL_OPCODE(19,50,0),    XL_MASK,  {0},
+    0,               "rfi",          0 },
+  { XL_OPCODE(19,129,0),   XL_MASK,  {O_crbD, O_crbA, O_crbB, 0},
+    0,               "crandc",       0 },
+  { XL_OPCODE(19,150,0),   XL_MASK,  {0},
+    0,               "isync",        0 },
+  { XL_OPCODE(19,193,0),   XL_MASK,  {O_crbD, O_crbA, O_crbB, 0},
+    0,               "crxor",        0 },
+  { XL_OPCODE(19,225,0),   XL_MASK,  {O_crbD, O_crbA, O_crbB, 0},
+    0,               "crnand",       0 },
+  { XL_OPCODE(19,257,0),   XL_MASK,  {O_crbD, O_crbA, O_crbB, 0},
+    0,               "crand",        0 },
+  { XL_OPCODE(19,289,0),   XL_MASK,  {O_crbD, O_crbA, O_crbB, 0},
+    0,               "creqv",        0 },
+  { XL_OPCODE(19,417,0),   XL_MASK,  {O_crbD, O_crbA, O_crbB, 0},
+    0,               "crorc",        0 },
+  { XL_OPCODE(19,449,0),   XL_MASK,  {O_crbD, O_crbA, O_crbB, 0},
+    0,               "cror",         0 },
+  { XL_OPCODE(19,528,0),   XL_MASK,  {O_BO, O_BI, O_LK, 0},
+    0,               "bcctr",        0 },
+  { XL_OPCODE(19,528,1),   XL_MASK,  {O_BO, O_BI, O_LK, 0},
+    0,               "bcctrl",       0 },
+  { M_OPCODE(20,0),        M_MASK,   {O_rA, O_rS, O_SH, O_MB, O_ME, O_Rc, 0},
+    0,               "rlwimi",       0 },
+  { M_OPCODE(20,1),        M_MASK,   {O_rA, O_rS, O_SH, O_MB, O_ME, O_Rc, 0},
+    0,               "rlwimi.",      0 },
+  { M_OPCODE(21,0),        M_MASK,   {O_rA, O_rS, O_SH, O_MB, O_ME, O_Rc, 0},
+    0,               "rlwinm",       0 },
+  { M_OPCODE(21,1),        M_MASK,   {O_rA, O_rS, O_SH, O_MB, O_ME, O_Rc, 0},
+    0,               "rlwinm.",      0 },
+  { M_OPCODE(23,0),        M_MASK,   {O_rA, O_rS, O_rB, O_MB, O_ME, O_Rc, 0},
+    0,               "rlwnm",        0 },
+  { M_OPCODE(23,1),        M_MASK,   {O_rA, O_rS, O_rB, O_MB, O_ME, O_Rc, 0},
+    0,               "rlwnm.",       0 },
+  { D_OPCODE(24),          D_MASK,   {O_rA, O_rS, O_UIMM, 0},
+    0,               "ori",          0 },
+  { D_OPCODE(25),          D_MASK,   {O_rA, O_rS, O_UIMM, 0},
+    0,               "oris",         H_IMM_HIGH },
+  { D_OPCODE(26),          D_MASK,   {O_rA, O_rS, O_UIMM, 0},
+    0,               "xori",         0 },
+  { D_OPCODE(27),          D_MASK,   {O_rA, O_rS, O_UIMM, 0},
+    0,               "xoris",        H_IMM_HIGH },
+  { D_OPCODE(28),          D_MASK,   {O_rA, O_rS, O_UIMM, 0},
+    0,               "andi.",        0 },
+  { D_OPCODE(29),          D_MASK,   {O_rA, O_rS, O_UIMM, 0},
+    0,               "andis.",       H_IMM_HIGH },
+  { X_OPCODE(31,0,0),      X_MASK,   {O_crfD, O_L, O_rA, O_rB, 0},
+    0,               "cmp",          0 },
+  { X_OPCODE(31,4,0),      X_MASK,   {O_TO, O_rA, O_rB, 0},
+    0,               "tw",           0 },
+  { XO_OPCODE(31,8,0,0),   XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfc",        0 },
+  { XO_OPCODE(31,8,0,1),   XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfc.",       0 },
+  { XO_OPCODE(31,10,0,0),  XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "addc",         0 },
+  { XO_OPCODE(31,10,0,1),  XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "addc.",        0 },
+  { XO_OPCODE(31,11,0,0),  XO_MASK,  {O_rD, O_rA, O_rB, O_Rc, 0},
+    0,               "mulhwu",       0 },
+  { XO_OPCODE(31,11,0,1),  XO_MASK,  {O_rD, O_rA, O_rB, O_Rc, 0},
+    0,               "mulhwu.",      0 },
+  { X_OPCODE(31,19,0),     X_MASK,   {O_rD, 0},
+    0,               "mfcr",         0 },
+  { X_OPCODE(31,20,0),     X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lwarx",        H_RA0_IS_0 },
+  { X_OPCODE(31,23,0),     X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lwzx",         H_RA0_IS_0 },
+  { X_OPCODE(31,24,0),     X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "slw",          0 },
+  { X_OPCODE(31,24,1),     X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "slw.",         0 },
+  { X_OPCODE(31,26,0),     X_MASK,   {O_rA, O_rS, O_Rc, 0 },
+    0,               "cntlzw",       0 },
+  { X_OPCODE(31,26,1),     X_MASK,   {O_rA, O_rS, O_Rc, 0},
+    0,               "cntlzw.",      0 },
+  { X_OPCODE(31,28,0),     X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "and",          0 },
+  { X_OPCODE(31,28,1),     X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "and.",         0 },
+  { X_OPCODE(31,32,0),     X_MASK,   {O_crfD, O_L, O_rA, O_rB, 0},
+    0,               "cmpl",         0 },
+  { XO_OPCODE(31,40,0,0),  XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subf",         0 },
+  { XO_OPCODE(31,40,0,1),  XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subf.",        0 },
+  { X_OPCODE(31,54,0),     X_MASK,   {O_rA, O_rB, 0},
+    0,               "dcbst",        H_RA0_IS_0 },
+  { X_OPCODE(31,55,0),     X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lwzux",        0 },
+  { X_OPCODE(31,60,0),     X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "andc",         0 },
+  { X_OPCODE(31,60,1),     X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "andc.",        0 },
+  { XO_OPCODE(31,75,0,0),  XO_MASK,  {O_rD, O_rA, O_rB, O_Rc, 0},
+    0,               "mulhw",        0 },
+  { XO_OPCODE(31,75,0,1),  XO_MASK,  {O_rD, O_rA, O_rB, O_Rc, 0},
+    0,               "mulhw.",       0 },
+  { X_OPCODE(31,83,0),     X_MASK,   {O_rD, 0},
+    0,               "mfmsr",        0 },
+  { X_OPCODE(31,86,0),     X_MASK,   {O_rA, O_rB, 0},
+    0,               "dcbf",         H_RA0_IS_0 },
+  { X_OPCODE(31,87,0),     X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lbzx",         H_RA0_IS_0 },
+  { XO_OPCODE(31,104,0,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "neg",          0 },
+  { XO_OPCODE(31,104,0,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "neg.",         0 },
+  { X_OPCODE(31,119,0),    X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lbzux",        0 },
+  { X_OPCODE(31,124,0),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "nor",          0 },
+  { X_OPCODE(31,124,1),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "nor.",         0 },
+  { XO_OPCODE(31,136,0,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfe",        0 },
+  { XO_OPCODE(31,136,0,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfe.",       0 },
+  { XO_OPCODE(31,138,0,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "adde",         0 },
+  { XO_OPCODE(31,138,0,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "adde.",        0 },
+  { XFX_OPCODE(31,144,0),  XFX_MASK, {O_CRM, O_rS, 0},
+    0,               "mtcrf",        0 },
+  { X_OPCODE(31,146,0),    X_MASK,   {O_rS, 0},
+    0,               "mtmsr",        0 },
+  { X_OPCODE(31,150,1),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "stwcx.",       0 },
+  { X_OPCODE(31,151,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "stwx",         0 },
+  { X_OPCODE(31,183,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "stwux",        0 },
+  { XO_OPCODE(31,200,0,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "subfze",       0 },
+  { XO_OPCODE(31,200,0,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "subfze.",      0 },
+  { XO_OPCODE(31,202,0,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "addze",        0 },
+  { XO_OPCODE(31,202,0,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "addze.",       0 },
+  { X_OPCODE(31,210,0),    X_MASK,   {O_SR, O_rS, 0},
+    0,               "mtsr",         0 },
+  { X_OPCODE(31,215,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "stbx",         H_RA0_IS_0 },
+  { XO_OPCODE(31,232,0,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "subfme",       0 },
+  { XO_OPCODE(31,232,0,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "subfme.",      0 },
+  { XO_OPCODE(31,234,0,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "addme",        0 },
+  { XO_OPCODE(31,234,0,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "addme.",       0 },
+  { XO_OPCODE(31,235,0,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "mullw",        0 },
+  { XO_OPCODE(31,235,0,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "mullw.",       0 },
+  { X_OPCODE(31,242,0),    X_MASK,   {O_rS, O_rB, 0},
+    0,               "mtsrin",       0 },
+  { X_OPCODE(31,246,0),    X_MASK,   {O_rA, O_rB, 0},
+    0,               "dcbtst",       H_RA0_IS_0 },
+  { X_OPCODE(31,247,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "stbux",        0 },
+  { XO_OPCODE(31,266,0,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "add",          0 },
+  { XO_OPCODE(31,266,0,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "add.",         0 },
+  { X_OPCODE(31,278,0),    X_MASK,   {O_rA, O_rB, 0},
+    0,               "dcbt",         H_RA0_IS_0 },
+  { X_OPCODE(31,279,0),    X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lhzx",         H_RA0_IS_0 },
+  { X_OPCODE(31,284,0),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "eqv",          0 },
+  { X_OPCODE(31,284,1),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "eqv.",         0 },
+  { X_OPCODE(31,306,0),    X_MASK,   {O_rB, 0},
+    0,               "tlbie",        0 },
+  { X_OPCODE(31,310,0),    X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "eciwx",        H_RA0_IS_0 },
+  { X_OPCODE(31,311,0),    X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lhzux",        0 },
+  { X_OPCODE(31,316,0),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "xor",          0 },
+  { X_OPCODE(31,316,1),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "xor.",         0 },
+  { XFX_OPCODE(31,339,0),  XFX_MASK, {O_rD, O_spr, 0},
+    0,               "mfspr",        0 },
+  { X_OPCODE(31,343,0),    X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lhax",         H_RA0_IS_0 },
+  { X_OPCODE(31,370,0),    X_MASK,   {0},
+    0,               "tlbia",        0 },
+  { XFX_OPCODE(31,371,0),  XFX_MASK, {O_rD, O_tbr, 0},
+    0,               "mftb",         0 },
+  { X_OPCODE(31,375,0),    X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lhaux",        0 },
+  { X_OPCODE(31,407,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "sthx",         H_RA0_IS_0 },
+  { X_OPCODE(31,412,0),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "orc",          0 },
+  { X_OPCODE(31,412,1),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "orc.",         0 },
+  { X_OPCODE(31,438,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "ecowx",        H_RA0_IS_0 },
+  { X_OPCODE(31,439,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "sthux",        0 },
+  { X_OPCODE(31,444,0),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "or",           0 },
+  { X_OPCODE(31,444,1),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "or.",          0 },
+  { XO_OPCODE(31,459,0,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "divwu",        0 },
+  { XO_OPCODE(31,459,0,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "divwu.",       0 },
+  { XFX_OPCODE(31,467,0),  XFX_MASK, {O_spr, O_rS, 0},
+    0,               "mtspr",        0 },
+  { X_OPCODE(31,470,0),    X_MASK,   {O_rA, O_rB, 0},
+    0,               "dcbi",         H_RA0_IS_0 },
+  { X_OPCODE(31,476,0),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "nand",         0 },
+  { X_OPCODE(31,476,1),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc,0},
+    0,               "nand.",        0 },
+  { XO_OPCODE(31,491,0,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "divw",         0 },
+  { XO_OPCODE(31,491,0,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "divw.",        0 },
+  { X_OPCODE(31,512,0),    X_MASK,   {O_crfD, 0},
+    0,               "mcrxr",        0 },
+  { XO_OPCODE(31,8,1,0),   XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfco",       0 },
+  { XO_OPCODE(31,8,1,1),   XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfco.",      0 },
+  { XO_OPCODE(31,10,1,0),  XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "addco",        0 },
+  { XO_OPCODE(31,10,1,1),  XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "addco.",       0 },
+  { X_OPCODE(31,533,0),    X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lswx",         H_RA0_IS_0 },
+  { X_OPCODE(31,534,0),    X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lwbrx",        H_RA0_IS_0 },
+  { X_OPCODE(31,536,0),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "srw",          0 },
+  { X_OPCODE(31,536,1),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "srw.",         0 },
+  { XO_OPCODE(31,40,1,0),  XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfo",        0 },
+  { XO_OPCODE(31,40,1,1),  XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfo.",       0 },
+  { X_OPCODE(31,566,0),    X_MASK,   {0},
+    0,               "tlbsync",      0 },
+  { X_OPCODE(31,595,0),    X_MASK,   {O_rD, O_SR, 0},
+    0,               "mfsr",         0 },
+  { X_OPCODE(31,597,0),    X_MASK,   {O_rD, O_rA, O_NB, 0},
+    0,               "lswi",         H_RA0_IS_0 },
+  { X_OPCODE(31,598,0),    X_MASK,   {0},
+    0,               "sync",         0 },
+  { XO_OPCODE(31,104,1,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "nego",         0 },
+  { XO_OPCODE(31,104,1,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "nego.",        0 },
+  { XO_OPCODE(31,136,1,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfeo",       0 },
+  { XO_OPCODE(31,136,1,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "subfeo.",      0 },
+  { XO_OPCODE(31,138,1,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "addeo",        0 },
+  { XO_OPCODE(31,138,1,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "addeo.",       0 },
+  { X_OPCODE(31,659,0),    X_MASK,   {O_rD, O_rB, 0},
+    0,               "mfsrin",       0 },
+  { X_OPCODE(31,661,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "stswx",        H_RA0_IS_0 },
+  { X_OPCODE(31,662,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "stwbrx",       H_RA0_IS_0 },
+  { XO_OPCODE(31,200,1,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "subfzeo",      0 },
+  { XO_OPCODE(31,200,1,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "subfzeo.",     0 },
+  { XO_OPCODE(31,202,1,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "addzeo",       0 },
+  { XO_OPCODE(31,202,1,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "addzeo.",      0 },
+  { X_OPCODE(31,725,0),    X_MASK,   {O_rS, O_rA, O_NB, 0},
+    0,               "stswi",        H_RA0_IS_0 },
+  { XO_OPCODE(31,232,1,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "subfmeo",      0 },
+  { XO_OPCODE(31,232,1,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "subfmeo.",     0 },
+  { XO_OPCODE(31,234,1,0), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "addmeo",       0 },
+  { XO_OPCODE(31,234,1,1), XO_MASK,  {O_rD, O_rA, O_OE, O_Rc, 0},
+    0,               "addmeo.",      0 },
+  { XO_OPCODE(31,235,1,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "mullwo",       0 },
+  { XO_OPCODE(31,235,1,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "mullwo.",      0 },
+  { XO_OPCODE(31,266,1,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "addo",         0 },
+  { XO_OPCODE(31,266,1,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "addo.",        0 },
+  { X_OPCODE(31,790,0),    X_MASK,   {O_rD, O_rA, O_rB, 0},
+    0,               "lhbrx",        H_RA0_IS_0 },
+  { X_OPCODE(31,792,0),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "sraw",         0 },
+  { X_OPCODE(31,792,1),    X_MASK,   {O_rA, O_rS, O_rB, O_Rc, 0},
+    0,               "sraw.",        0 },
+  { X_OPCODE(31,824,0),    X_MASK,   {O_rA, O_rS, O_SH, O_Rc, 0},
+    0,               "srawi",        0 },
+  { X_OPCODE(31,824,1),    X_MASK,   {O_rA, O_rS, O_SH, O_Rc, 0},
+    0,               "srawi.",       0 },
+  { X_OPCODE(31,854,0),    X_MASK,   {0},
+    0,               "eieio",        0 },
+  { X_OPCODE(31,918,0),    X_MASK,   {O_rS, O_rA, O_rB, 0},
+    0,               "sthbrx",       H_RA0_IS_0 },
+  { X_OPCODE(31,922,0),    X_MASK,   {O_rA, O_rS, O_Rc, 0},
+    0,               "extsh",        0 },
+  { X_OPCODE(31,922,1),    X_MASK,   {O_rA, O_rS, O_Rc, 0},
+    0,               "extsh.",       0 },
+  { X_OPCODE(31,954,0),    X_MASK,   {O_rA, O_rS, O_Rc, 0},
+    0,               "extsb",        0 },
+  { X_OPCODE(31,954,1),    X_MASK,   {O_rA, O_rS, O_Rc, 0},
+    0,               "extsb.",       0 },
+  { XO_OPCODE(31,459,1,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "divwuo",       0 },
+  { XO_OPCODE(31,459,1,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "divwuo.",      0 },
+  { X_OPCODE(31,978,0),    X_MASK,   {O_rB, 0},
+    0,               "tlbld",        0 },
+  { X_OPCODE(31,982,0),    X_MASK,   {O_rA, O_rB, 0},
+    0,               "icbi",         H_RA0_IS_0 },
+  { XO_OPCODE(31,491,1,0), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "divwo",        0 },
+  { XO_OPCODE(31,491,1,1), XO_MASK,  {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+    0,               "divwo.",       0 },
+  { X_OPCODE(31,1010,0),   X_MASK,   {O_rB, 0},
+    0,               "tlbli",        0 },
+  { X_OPCODE(31,1014,0),   X_MASK,   {O_rA, O_rB, 0},
+    0,               "dcbz",         H_RA0_IS_0 },
+  { D_OPCODE(32),          D_MASK,   {O_rD, O_d, O_rA, 0},
+    0,               "lwz",          H_RA0_IS_0 },
+  { D_OPCODE(33),          D_MASK,   {O_rD, O_d, O_rA, 0},
+    0,               "lwzu",         0 },
+  { D_OPCODE(34),          D_MASK,   {O_rD, O_d, O_rA, 0},
+    0,               "lbz",          H_RA0_IS_0 },
+  { D_OPCODE(35),          D_MASK,   {O_rD, O_d, O_rA, 0},
+    0,               "lbzu",         0 },
+  { D_OPCODE(36),          D_MASK,   {O_rS, O_d, O_rA, 0},
+    0,               "stw",          H_RA0_IS_0 },
+  { D_OPCODE(37),          D_MASK,   {O_rS, O_d, O_rA, 0},
+    0,               "stwu",         0 },
+  { D_OPCODE(38),          D_MASK,   {O_rS, O_d, O_rA, 0},
+    0,               "stb",          H_RA0_IS_0 },
+  { D_OPCODE(39),          D_MASK,   {O_rS, O_d, O_rA, 0},
+    0,               "stbu",         0 },
+  { D_OPCODE(40),          D_MASK,   {O_rD, O_d, O_rA, 0},
+    0,               "lhz",          H_RA0_IS_0 },
+  { D_OPCODE(41),          D_MASK,   {O_rD, O_d, O_rA, 0},
+    0,               "lhzu",         0 },
+  { D_OPCODE(42),          D_MASK,   {O_rD, O_d, O_rA, 0},
+    0,               "lha",          H_RA0_IS_0 },
+  { D_OPCODE(43),          D_MASK,   {O_rD, O_d, O_rA, 0},
+    0,               "lhau",         0 },
+  { D_OPCODE(44),          D_MASK,   {O_rS, O_d, O_rA, 0},
+    0,               "sth",          H_RA0_IS_0 },
+  { D_OPCODE(45),          D_MASK,   {O_rS, O_d, O_rA, 0},
+    0,               "sthu",         0 },
+  { D_OPCODE(46),          D_MASK,   {O_rD, O_d, O_rA, 0},
+    0,               "lmw",          H_RA0_IS_0 },
+  { D_OPCODE(47),          D_MASK,   {O_rS, O_d, O_rA, 0},
+    0,               "stmw",         H_RA0_IS_0 },
+};
+
+const unsigned int n_opcodes = sizeof(opcodes) / sizeof(opcodes[0]);
+
+struct spr_info spr_map[] = {
+  { SPR_XER,   "XER" },
+  { SPR_LR,    "LR" },
+  { SPR_CTR,   "CTR" },
+  { SPR_DSISR, "DSISR" },
+  { SPR_DAR,   "DAR" },
+  { SPR_DEC,   "DEC" },
+  { SPR_SRR0,  "SRR0" },
+  { SPR_SRR1,  "SRR1" },
+  { SPR_EIE,   "EIE" },
+  { SPR_EID,   "EID" },
+  { SPR_CMPA,  "CMPA" },
+  { SPR_CMPB,  "CMPB" },
+  { SPR_CMPC,  "CMPC" },
+  { SPR_CMPD,  "CMPD" },
+  { SPR_ICR,   "ICR" },
+  { SPR_DER,   "DER" },
+  { SPR_COUNTA,        "COUNTA" },
+  { SPR_COUNTB,        "COUNTB" },
+  { SPR_CMPE,  "CMPE" },
+  { SPR_CMPF,  "CMPF" },
+  { SPR_CMPG,  "CMPG" },
+  { SPR_CMPH,  "CMPH" },
+  { SPR_LCTRL1,        "LCTRL1" },
+  { SPR_LCTRL2,        "LCTRL2" },
+  { SPR_ICTRL, "ICTRL" },
+  { SPR_BAR,   "BAR" },
+  { SPR_USPRG0,        "USPRG0" },
+  { SPR_SPRG4_RO,      "SPRG4_RO" },
+  { SPR_SPRG5_RO,      "SPRG5_RO" },
+  { SPR_SPRG6_RO,      "SPRG6_RO" },
+  { SPR_SPRG7_RO,      "SPRG7_RO" },
+  { SPR_SPRG0, "SPRG0" },
+  { SPR_SPRG1, "SPRG1" },
+  { SPR_SPRG2, "SPRG2" },
+  { SPR_SPRG3, "SPRG3" },
+  { SPR_SPRG4, "SPRG4" },
+  { SPR_SPRG5, "SPRG5" },
+  { SPR_SPRG6, "SPRG6" },
+  { SPR_SPRG7, "SPRG7" },
+  { SPR_TBL,   "TBL" },
+  { SPR_TBU,   "TBU" },
+  { SPR_IC_CST,        "IC_CST" },
+  { SPR_IC_ADR,        "IC_ADR" },
+  { SPR_IC_DAT,        "IC_DAT" },
+  { SPR_DC_CST,        "DC_CST" },
+  { SPR_DC_ADR,        "DC_ADR" },
+  { SPR_DC_DAT,        "DC_DAT" },
+  { SPR_DPDR,  "DPDR" },
+  { SPR_IMMR,  "IMMR" },
+  { SPR_MI_CTR,        "MI_CTR" },
+  { SPR_MI_AP, "MI_AP" },
+  { SPR_MI_EPN,        "MI_EPN" },
+  { SPR_MI_TWC,        "MI_TWC" },
+  { SPR_MI_RPN,        "MI_RPN" },
+  { SPR_MD_CTR,        "MD_CTR" },
+  { SPR_M_CASID,       "M_CASID" },
+  { SPR_MD_AP, "MD_AP" },
+  { SPR_MD_EPN,        "MD_EPN" },
+  { SPR_M_TWB, "M_TWB" },
+  { SPR_MD_TWC,        "MD_TWC" },
+  { SPR_MD_RPN,        "MD_RPN" },
+  { SPR_M_TW,  "M_TW" },
+  { SPR_MI_DBCAM,      "MI_DBCAM" },
+  { SPR_MI_DBRAM0,     "MI_DBRAM0" },
+  { SPR_MI_DBRAM1,     "MI_DBRAM1" },
+  { SPR_MD_DBCAM,      "MD_DBCAM" },
+  { SPR_MD_DBRAM0,     "MD_DBRAM0" },
+  { SPR_MD_DBRAM1,     "MD_DBRAM1" },
+  { SPR_ZPR,   "ZPR" },
+  { SPR_PID,   "PID" },
+  { SPR_CCR0,  "CCR0" },
+  { SPR_IAC3,  "IAC3" },
+  { SPR_IAC4,  "IAC4" },
+  { SPR_DVC1,  "DVC1" },
+  { SPR_DVC2,  "DVC2" },
+  { SPR_SGR,   "SGR" },
+  { SPR_DCWR,  "DCWR" },
+  { SPR_SLER,  "SLER" },
+  { SPR_SU0R,  "SU0R" },
+  { SPR_DBCR1, "DBCR1" },
+  { SPR_ICDBDR,        "ICDBDR" },
+  { SPR_ESR,   "ESR" },
+  { SPR_DEAR,  "DEAR" },
+  { SPR_EVPR,  "EVPR" },
+  { SPR_TSR,   "TSR" },
+  { SPR_TCR,   "TCR" },
+  { SPR_PIT,   "PIT" },
+  { SPR_SRR2,  "SRR2" },
+  { SPR_SRR3,  "SRR3" },
+  { SPR_DBSR,  "DBSR" },
+  { SPR_DBCR0, "DBCR0" },
+  { SPR_IAC1,  "IAC1" },
+  { SPR_IAC2,  "IAC2" },
+  { SPR_DAC1,  "DAC1" },
+  { SPR_DAC2,  "DAC2" },
+  { SPR_DCCR,  "DCCR" },
+  { SPR_ICCR,  "ICCR" },
+};
+
+const unsigned int n_sprs = sizeof(spr_map) / sizeof(spr_map[0]);
+
+#endif
+
+/*
+ * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ * 
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+
diff --git a/include/cmd_bedbug.h b/include/cmd_bedbug.h
new file mode 100644 (file)
index 0000000..8ab502e
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * BedBug Functions
+ */
+#ifndef        _CMD_BEDBUG_H
+#define _CMD_BEDBUG_H
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+
+#define CMD_TBL_DIS    MK_CMD_TBL_ENTRY(                               \
+       "ds",           2,      3,      1,      do_bedbug_dis,          \
+       "ds      - disassemble memory\n",                               \
+       "ds <address> [# instructions]\n"                               \
+        ),
+
+#define CMD_TBL_ASM    MK_CMD_TBL_ENTRY(                               \
+       "as",           2,      2,      0,      do_bedbug_asm,          \
+       "as      - assemble memory\n",                                  \
+       "as <address>\n"                                                \
+        ),
+
+#define CMD_TBL_BREAK  MK_CMD_TBL_ENTRY(                               \
+       "break",        2,      3,      0,      do_bedbug_break,        \
+       "break   - set or clear a breakpoint\n",                        \
+       " - Set or clear a breakpoint\n"                                \
+       "break <address> - Break at an address\n"                       \
+       "break off <bp#> - Disable breakpoint.\n"                       \
+       "break show      - List breakpoints.\n"                         \
+        ),
+
+#define CMD_TBL_CONTINUE        MK_CMD_TBL_ENTRY(                      \
+       "continue",     4,      1,      0,      do_bedbug_continue,     \
+       "break   - continue from a breakpoint\n",                       \
+       " - continue from a breakpoint.\n"                              \
+        ),
+
+#define CMD_TBL_STEP        MK_CMD_TBL_ENTRY(                           \
+       "step", 1,      1,      1,      do_bedbug_step,                 \
+       "step    - single step execution.\n",                           \
+       " - single step execution.\n"                                   \
+        ),
+
+#define CMD_TBL_NEXT        MK_CMD_TBL_ENTRY(                           \
+       "next", 1,      1,      1,      do_bedbug_next,                 \
+       "next    - single step execution, stepping over subroutines.\n",\
+       " - single step execution, stepping over subroutines.\n"        \
+        ),
+
+#define CMD_TBL_STACK        MK_CMD_TBL_ENTRY(                          \
+       "where", 2,     1,      1,      do_bedbug_stack,                \
+       "where   - Print the running stack.\n",                         \
+       " - Print the running stack.\n"                                 \
+        ),
+
+#define CMD_TBL_RDUMP        MK_CMD_TBL_ENTRY(                          \
+       "rdump", 2,     1,      1,      do_bedbug_rdump,                \
+       "rdump   - Show registers.\n",                                  \
+       " - Show registers.\n"                                          \
+        ),
+
+#define CMD_TBL_BOOTELF MK_CMD_TBL_ENTRY(                               \
+        "bootelf",      7,      2,      0,      do_bootelf,             \
+        "bootelf - Boot from an ELF image in memory\n",                 \
+        " [address] - load address of ELF image.\n"                     \
+        ),
+
+#define CMD_TBL_BOOTVX  MK_CMD_TBL_ENTRY(                               \
+        "bootvx",       6,      2,      0,      do_bootvx,              \
+        "bootvx  - Boot vxWorks from an ELF image\n",                   \
+        " [address] - load address of vxWorks ELF image.\n"             \
+        ),
+
+extern void do_bedbug_dis (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_asm (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_break (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_continue (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_step (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_next (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_stack (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_rdump (cmd_tbl_t *, bd_t *, int, int, char *[]);
+
+extern void do_bootelf (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bootvx (cmd_tbl_t *, bd_t *, int, int, char *[]);
+
+/* Supporting routines */
+extern int           bedbug_puts (const char *);
+extern void          bedbug_init (void);
+extern void          do_bedbug_breakpoint (struct pt_regs*);
+extern void          bedbug_main_loop (unsigned long,struct pt_regs *);
+extern int           valid_elf_image (unsigned long);
+extern unsigned long load_elf_image (unsigned long);
+
+
+typedef struct {
+  int               hw_debug_enabled;
+  int               stopped;
+  int               current_bp;
+  struct pt_regs *  regs;
+  bd_t *            bd;
+  
+  void              (*do_break)(cmd_tbl_t*,bd_t*,int,int,char *[]);
+  void              (*break_isr)(struct pt_regs *);
+  int               (*find_empty)(void);
+  int               (*set)(int,unsigned long);
+  int               (*clear)(int);
+} CPU_DEBUG_CTX;
+
+
+#else   /* ! CFG_CMD_BEDBUG */
+
+#define CMD_TBL_DIS
+#define CMD_TBL_ASM
+#define CMD_TBL_BREAK
+#define CMD_TBL_CONTINUE
+#define CMD_TBL_STEP
+#define CMD_TBL_NEXT
+#define CMD_TBL_STACK
+#define CMD_TBL_RDUMP
+#define CMD_TBL_BOOTELF
+#define CMD_TBL_BOOTVX
+
+#endif /* CFG_CMD_BEDBUG */
+#endif /* _CMD_BEDBUG_H */
+
+
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ * 
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
index 8c0a56ab3cf8a972befd9c2b720ea851d899f941..d25a134694e4861d725f97b770a7c21411d4b9ed 100644 (file)
@@ -56,7 +56,8 @@
 #define        CFG_CMD_IMMAP   0x00400000      /* IMMR dump support            */
 #define        CFG_CMD_DATE    0x00800000      /* support for RTC, date/time...*/
 #define CFG_CMD_DHCP   0x01000000      /* DHCP Support                 */
-#define        CFG_CMD_BSP     0x02000000      /* Board SPecific functions     */
+#define CFG_CMD_BEDBUG  0x02000000      /* Include BedBug Debugger      */
+#define        CFG_CMD_BSP     0x04000000      /* Board SPecific functions     */
 
 #define CFG_CMD_ALL    0xFFFFFFFF      /* ALL commands                 */
 
@@ -76,6 +77,7 @@
                        CFG_CMD_REGINFO | \
                        CFG_CMD_IMMAP   | \
                        CFG_CMD_DATE    | \
+                       CFG_CMD_BEDBUG  | \
                        CFG_CMD_BSP     )
 
 /* Default configuration
index 65571ca258cc1d2c6e7ef82c4f1028ccf1a1ac3c..fb4a3d950f6e69d38634d7730284784c75b6b87b 100644 (file)
 #else  /* force ENV to be embedded */
 #define        CFG_ENV_SIZE            (2 * 1024) /* Total Size of Environment Sector 2k */
 #define CFG_ENV_ADDR            (CFG_MONITOR_BASE + CFG_MONITOR_LEN - CFG_ENV_SIZE - 0x10) /* let space for reset vector */
-/* #define CFG_ENV_ADDR            (CFG_MONITOR_BASE)*/ /* let space for reset vector */
+/* #define CFG_ENV_ADDR            (CFG_MONITOR_BASE)*/ 
 #define CFG_ENV_OFFSET          (CFG_ENV_ADDR - CFG_FLASH_BASE)
 #endif
 
index 6867962e196cf9a8c3c72d14843ca48798af056c..baf4e10c95fec73dedf0ff75131e54b1574629f3 100644 (file)
@@ -87,7 +87,8 @@
                                             & ~CFG_CMD_PCI     \
                                             & ~CFG_CMD_EEPROM  \
                                             & ~CFG_CMD_I2C     \
-                                            & ~CFG_CMD_IRQ)
+                                            & ~CFG_CMD_IRQ     \
+                                            & ~CFG_CMD_BEDBUG  )
 
 #if CONFIG_LANTEC >= 2
 #define        CONFIG_RTC_MPC8xx               /* use internal RTC of MPC8xx   */
index 2d146d111774d0d6d4894fb07613eed2d95b8537..9779a9e1f9f213fef0f838734aa18f381c37d09a 100644 (file)
@@ -74,6 +74,7 @@
 #define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
                                CFG_CMD_DHCP    | \
                                CFG_CMD_IDE     | \
+                               CFG_CMD_DHCP    | \
                                CFG_CMD_DATE    )
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
diff --git a/include/config_TQM8260.h b/include/config_TQM8260.h
new file mode 100644 (file)
index 0000000..3b773ce
--- /dev/null
@@ -0,0 +1,494 @@
+/*
+ * (C) Copyright 2001
+ * 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
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC8260         1       /* This is a MPC8260 CPU                */
+#define CONFIG_TQM8260         100     /* ...on a TQM8260 module Rev.100       */
+#define CONFIG_82xx_CONS_SMC1  1       /* console on SMC1                      */
+
+#if 0
+#define CONFIG_BOOTDELAY       -1      /* autoboot disabled            */
+#else
+#define CONFIG_BOOTDELAY       5       /* autoboot after 5 seconds     */
+#endif
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_BOOTCOMMAND                                                     \
+       "bootp; "                                                               \
+       "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) "     \
+       "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; "   \
+       "bootm"
+
+#define CONFIG_SOFT_I2C                1       /* I2C support                          */
+#define CONFIG_I2C_X           1       /* extended EEPROM addressing           */
+
+# define CFG_I2C_EEPROM_ADDR   0x50
+# define CFG_EEPROM_PAGE_WRITE_BITS 5
+
+/*
+ * select serial console configuration
+ *
+ * if either CONFIG_CONS_ON_SMC or CONFIG_CONS_ON_SCC is selected, then
+ * CONFIG_CONS_INDEX must be set to the channel number (1-2 for SMC, 1-4
+ * for SCC).
+ *
+ * if CONFIG_CONS_NONE is defined, then the serial console routines must
+ * defined elsewhere (for example, on the cogent platform, there are serial
+ * ports on the motherboard which are used for the serial console - see
+ * cogent/cma101/serial.[ch]).
+ */
+#define CONFIG_CONS_ON_SMC             /* define if console on SMC */
+#undef  CONFIG_CONS_ON_SCC             /* define if console on SCC */
+#undef  CONFIG_CONS_NONE               /* define if console on something else*/
+#ifdef CONFIG_82xx_CONS_SMC1
+#define CONFIG_CONS_INDEX      1       /* which serial channel for console */
+#endif
+#ifdef CONFIG_82xx_CONS_SMC2
+#define CONFIG_CONS_INDEX      2       /* which serial channel for console */
+#endif
+
+#undef  CONFIG_CONS_USE_EXTC           /* SMC/SCC use ext clock not brg_clk */
+#define CONFIG_CONS_EXTC_RATE  3686400 /* SMC/SCC ext clk rate in Hz */
+#define CONFIG_CONS_EXTC_PINSEL        0       /* pin select 0=CLK3/CLK9 */
+
+/*
+ * select ethernet configuration
+ *
+ * if either CONFIG_ETHER_ON_SCC or CONFIG_ETHER_ON_FCC is selected, then
+ * CONFIG_ETHER_INDEX must be set to the channel number (1-4 for SCC, 1-3
+ * for FCC)
+ *
+ * if CONFIG_ETHER_NONE is defined, then either the ethernet routines must be
+ * defined elsewhere (as for the console), or CFG_CMD_NET must be removed
+ * from CONFIG_COMMANDS to remove support for networking.
+ *
+ * (On TQM8260 either SCC1 or FCC2 may be chosen: SCC1 is hardwired to the
+ * X.29 connector, and FCC2 is hardwired to the X.1 connector)
+ */
+#undef CONFIG_ETHER_ON_SCC             /* define if ether on SCC       */
+#define        CONFIG_ETHER_ON_FCC             /* define if ether on FCC       */
+#undef CONFIG_ETHER_NONE               /* define if ether on something else */
+#define        CONFIG_ETHER_INDEX    2         /* which SCC/FCC channel for ethernet */
+
+/* system clock rate (CLKIN) - equal to the 60x and local bus speed */
+#define CONFIG_8260_CLKIN      66666666        /* in Hz */
+
+#if defined(CONFIG_CONS_NONE) || defined(CONFIG_CONS_USE_EXTC)
+#define CONFIG_BAUDRATE                230400
+#else
+#define CONFIG_BAUDRATE                9600
+#endif
+
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#undef CFG_LOADS_BAUD_CHANGE           /* don't allow baudrate change  */
+
+#undef CONFIG_WATCHDOG                 /* watchdog disabled            */
+
+#define CONFIG_BOOTP_MASK      (CONFIG_BOOTP_DEFAULT|CONFIG_BOOTP_BOOTFILESIZE)
+
+#define CONFIG_COMMANDS                (CONFIG_CMD_DFL | CFG_CMD_EEPROM)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define        CFG_LONGHELP                    /* undef to save memory         */
+#define        CFG_PROMPT      "=> "           /* Monitor Command Prompt       */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define        CFG_CBSIZE      1024            /* Console I/O Buffer Size      */
+#else
+#define        CFG_CBSIZE      256             /* Console I/O Buffer Size      */
+#endif
+#define        CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define        CFG_MAXARGS     16              /* max number of command args   */
+#define CFG_BARGSIZE   CFG_CBSIZE      /* Boot Argument Buffer Size    */
+
+#define CFG_MEMTEST_START      0x0400000       /* memtest works on     */
+#define CFG_MEMTEST_END        0x0C00000       /* 4 ... 12 MB in DRAM  */
+
+#define        CFG_LOAD_ADDR   0x100000        /* default load address */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+#define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * 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 */
+
+
+/* What should the base address of the main FLASH be and how big is
+ * it (in MBytes)? This must contain TEXT_BASE from board/tqm8260/config.mk
+ * The main FLASH is whichever is connected to *CS0.
+ */
+#define CFG_FLASH0_BASE 0x40000000
+#define CFG_FLASH1_BASE 0x60000000
+#define CFG_FLASH0_SIZE 32
+#define CFG_FLASH1_SIZE 32
+
+/* Flash bank size (for preliminary settings)
+ */
+#define CFG_FLASH_SIZE CFG_FLASH0_SIZE
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    1       /* max num of memory banks      */
+#define CFG_MAX_FLASH_SECT     128     /* max num of sects on one chip */
+
+#define CFG_FLASH_ERASE_TOUT   240000  /* Flash Erase Timeout (in ms)  */
+#define CFG_FLASH_WRITE_TOUT   500     /* Flash Write Timeout (in ms)  */
+
+#if 0
+/* Start port with environment in flash; switch to EEPROM later */
+#define CFG_ENV_IS_IN_FLASH    1
+#define CFG_ENV_ADDR           (CFG_FLASH_BASE+0x40000)
+#define CFG_ENV_SIZE           0x40000
+#define CFG_ENV_SECT_SIZE      0x40000
+#else
+/* Final version: environment in EEPROM */
+#define CFG_ENV_IS_IN_EEPROM   1
+#define CFG_ENV_OFFSET         0
+#define CFG_ENV_SIZE           1024
+#endif
+
+/*-----------------------------------------------------------------------
+ * Hard Reset Configuration Words
+ *
+ * if you change bits in the HRCW, you must also change the CFG_*
+ * defines for the various registers affected by the HRCW e.g. changing
+ * HRCW_DPPCxx requires you to also change CFG_SIUMCR.
+ */
+#define CFG_HRCW_MASTER                (HRCW_CIP | HRCW_ISB111 | HRCW_BMS)
+
+/* no slaves so just fill with zeros */
+#define CFG_HRCW_SLAVE1                0
+#define CFG_HRCW_SLAVE2                0
+#define CFG_HRCW_SLAVE3                0
+#define CFG_HRCW_SLAVE4                0
+#define CFG_HRCW_SLAVE5                0
+#define CFG_HRCW_SLAVE6                0
+#define CFG_HRCW_SLAVE7                0
+
+/*-----------------------------------------------------------------------
+ * Internal Memory Mapped Register
+ */
+#define CFG_IMMR               0xFFF00000
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR      CFG_IMMR
+#define CFG_INIT_RAM_END       0x4000  /* End of used area in DPRAM    */
+#define CFG_INIT_DATA_SIZE     128 /* 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
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ *
+ * 60x SDRAM is mapped at CFG_SDRAM_BASE, local SDRAM
+ * is mapped at SDRAM_BASE2_PRELIM.
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         CFG_FLASH0_BASE
+#define CFG_MONITOR_BASE       TEXT_BASE
+#define CFG_MONITOR_LEN                (256 << 10)     /* Reserve 256 kB for Monitor */
+#define CFG_MALLOC_LEN         (128 << 10)     /* Reserve 128 kB for malloc()*/
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD          0x01    /* Normal Power-On: Boot from FLASH*/
+#define BOOTFLAG_WARM          0x02    /* Software reboot                 */
+
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE      32      /* For MPC8260 CPU              */
+
+/*-----------------------------------------------------------------------
+ * HIDx - Hardware Implementation-dependent Registers                    2-11
+ *-----------------------------------------------------------------------
+ * HID0 also contains cache control - initially enable both caches and
+ * invalidate contents, then the final state leaves only the instruction
+ * cache enabled. Note that Power-On and Hard reset invalidate the caches,
+ * but Soft reset does not.
+ *
+ * HID1 has only read-only information - nothing to set.
+ */
+#define CFG_HID0_INIT   (HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI|\
+                                HID0_IFEM|HID0_ABE)
+#define CFG_HID0_FINAL  (HID0_ICE|HID0_IFEM|HID0_ABE)
+#define CFG_HID2        0
+
+/*-----------------------------------------------------------------------
+ * RMR - Reset Mode Register                                     5-5
+ *-----------------------------------------------------------------------
+ * turn on Checkstop Reset Enable
+ */
+#define CFG_RMR         RMR_CSRE
+
+/*-----------------------------------------------------------------------
+ * BCR - Bus Configuration                                       4-25
+ *-----------------------------------------------------------------------
+ */
+#define CFG_BCR         (BCR_EBM|BCR_L2C|BCR_LETM|\
+                        BCR_NPQM0|BCR_NPQM1|BCR_NPQM2)
+
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration                             4-31
+ *-----------------------------------------------------------------------
+ */
+#define CFG_SIUMCR      (SIUMCR_DPPC10|SIUMCR_APPC10)
+
+
+/*-----------------------------------------------------------------------
+ * SYPCR - System Protection Control                             4-35
+ * SYPCR can only be written once after reset!
+ *-----------------------------------------------------------------------
+ * Watchdog & Bus Monitor Timer max, 60x Bus Monitor enable
+ */
+#if defined(CONFIG_WATCHDOG)
+#define CFG_SYPCR       (SYPCR_SWTC|SYPCR_BMT|SYPCR_PBME|SYPCR_LBME|\
+                         SYPCR_SWRI|SYPCR_SWP|SYPCR_SWE)
+#else
+#define CFG_SYPCR       (SYPCR_SWTC|SYPCR_BMT|SYPCR_PBME|SYPCR_LBME|\
+                         SYPCR_SWRI|SYPCR_SWP)
+#endif /* CONFIG_WATCHDOG */
+
+/*-----------------------------------------------------------------------
+ * TMCNTSC - Time Counter Status and Control                     4-40
+ *-----------------------------------------------------------------------
+ * Clear once per Second and Alarm Interrupt Status, Set 32KHz timersclk,
+ * and enable Time Counter
+ */
+#define CFG_TMCNTSC     (TMCNTSC_SEC|TMCNTSC_ALR|TMCNTSC_TCF|TMCNTSC_TCE)
+
+/*-----------------------------------------------------------------------
+ * PISCR - Periodic Interrupt Status and Control                 4-42
+ *-----------------------------------------------------------------------
+ * Clear Periodic Interrupt Status, Set 32KHz timersclk, and enable
+ * Periodic timer
+ */
+#define CFG_PISCR       (PISCR_PS|PISCR_PTF|PISCR_PTE)
+
+/*-----------------------------------------------------------------------
+ * SCCR - System Clock Control                                   9-8
+ *-----------------------------------------------------------------------
+ * Ensure DFBRG is Divide by 16
+ */
+#define CFG_SCCR        0
+
+/*-----------------------------------------------------------------------
+ * RCCR - RISC Controller Configuration                         13-7
+ *-----------------------------------------------------------------------
+ */
+#define CFG_RCCR        0
+
+/*
+ * Init Memory Controller:
+ *
+ * Bank Bus     Machine PortSz  Device
+ * ---- ---     ------- ------  ------
+ *  0   60x     GPCM    64 bit  FLASH
+ *  1   60x     SDRAM   64 bit  SDRAM
+ *  2   Local   SDRAM   32 bit  SDRAM
+ *
+ */
+
+       /* Initialize SDRAM on local bus
+        */
+#define CFG_INIT_LOCAL_SDRAM
+
+
+/* Minimum mask to separate preliminary
+ * address ranges for CS[0:2]
+ */
+#define CFG_MIN_AM_MASK        0xC0000000
+
+#define CFG_MPTPR       0x4000
+
+/*-----------------------------------------------------------------------------
+ * Address for Mode Register Set (MRS) command
+ *-----------------------------------------------------------------------------
+ * In fact, the address is rather configuration data presented to the SDRAM on
+ * its address lines. Because the address lines may be mux'ed externally either
+ * for 8 column or 9 column devices, some bits appear twice in the 8260's
+ * address:
+ *
+ * |   (RFU)   |   (RFU)   | WBL |    TM    |     CL    |  BT | Burst Length |
+ * | BA1   BA0 | A12 : A10 |  A9 |  A8   A7 |  A6 : A4  |  A3 |   A2 :  A0   |
+ *  8 columns mux'ing:     |  A9 | A10  A21 | A22 : A24 | A25 |  A26 : A28   |
+ *  9 columns mux'ing:     |  A8 | A20  A21 | A22 : A24 | A25 |  A26 : A28   |
+ *  Settings:              |  0  |  0    0  |  0  1  0  |  0  |   0  1  0    |
+ *-----------------------------------------------------------------------------
+ */
+#define CFG_MRS_OFFS   0x00000110
+
+
+/* Bank 0 - FLASH
+ */
+#define CFG_BR0_PRELIM  ((CFG_FLASH_BASE & BRx_BA_MSK)  |\
+                         BRx_PS_64                      |\
+                         BRx_MS_GPCM_P                  |\
+                         BRx_V)
+
+#define CFG_OR0_PRELIM  (MEG_TO_AM(CFG_FLASH_SIZE)      |\
+                         ORxG_CSNT                      |\
+                         ORxG_ACS_DIV1                  |\
+                         ORxG_SCY_3_CLK                 |\
+                         ORxG_EHTR                      |\
+                         ORxG_TRLX)
+
+       /* SDRAM on TQM8260 can have either 8 or 9 columns.
+        * The number affects configuration values.
+        */
+
+/* Bank 1 - 60x bus SDRAM
+ */
+#define CFG_PSRT        0x20
+#define CFG_LSRT        0x20
+#ifndef CFG_RAMBOOT
+#define CFG_BR1_PRELIM  ((CFG_SDRAM_BASE & BRx_BA_MSK)  |\
+                         BRx_PS_64                      |\
+                         BRx_MS_SDRAM_P                 |\
+                         BRx_V)
+
+#define CFG_OR1_PRELIM CFG_OR1_8COL
+
+
+       /* SDRAM initialization values for 8-column chips
+        */
+#define CFG_OR1_8COL    (CFG_MIN_AM_MASK               |\
+                         ORxS_BPD_4                     |\
+                         ORxS_ROWST_PBI1_A7             |\
+                         ORxS_NUMR_12)
+
+#define CFG_PSDMR_8COL  (PSDMR_PBI                      |\
+                         PSDMR_SDAM_A15_IS_A5           |\
+                         PSDMR_BSMA_A12_A14             |\
+                         PSDMR_SDA10_PBI1_A8            |\
+                         PSDMR_RFRC_7_CLK               |\
+                         PSDMR_PRETOACT_2W              |\
+                         PSDMR_ACTTORW_2W               |\
+                         PSDMR_LDOTOPRE_1C              |\
+                         PSDMR_WRC_2C                   |\
+                         PSDMR_EAMUX                    |\
+                         PSDMR_CL_2)
+
+       /* SDRAM initialization values for 9-column chips
+        */
+#define CFG_OR1_9COL    (CFG_MIN_AM_MASK               |\
+                         ORxS_BPD_4                     |\
+                         ORxS_ROWST_PBI1_A5             |\
+                         ORxS_NUMR_13)
+
+#define CFG_PSDMR_9COL  (PSDMR_PBI                      |\
+                         PSDMR_SDAM_A16_IS_A5           |\
+                         PSDMR_BSMA_A12_A14             |\
+                         PSDMR_SDA10_PBI1_A7            |\
+                         PSDMR_RFRC_7_CLK               |\
+                         PSDMR_PRETOACT_2W              |\
+                         PSDMR_ACTTORW_2W               |\
+                         PSDMR_LDOTOPRE_1C              |\
+                         PSDMR_WRC_2C                   |\
+                         PSDMR_EAMUX                    |\
+                         PSDMR_CL_2)
+
+/* Bank 2 - Local bus SDRAM
+ */
+#ifdef CFG_INIT_LOCAL_SDRAM
+#define CFG_BR2_PRELIM  ((SDRAM_BASE2_PRELIM & BRx_BA_MSK) |\
+                         BRx_PS_32                      |\
+                         BRx_MS_SDRAM_L                 |\
+                         BRx_V)
+
+#define CFG_OR2_PRELIM CFG_OR2_8COL
+
+#define SDRAM_BASE2_PRELIM     0x80000000
+
+       /* SDRAM initialization values for 8-column chips
+        */
+#define CFG_OR2_8COL    (CFG_MIN_AM_MASK               |\
+                         ORxS_BPD_4                     |\
+                         ORxS_ROWST_PBI1_A8             |\
+                         ORxS_NUMR_12)
+
+#define CFG_LSDMR_8COL  (PSDMR_PBI                      |\
+                         PSDMR_SDAM_A15_IS_A5           |\
+                         PSDMR_BSMA_A13_A15             |\
+                         PSDMR_SDA10_PBI1_A9            |\
+                         PSDMR_RFRC_7_CLK               |\
+                         PSDMR_PRETOACT_2W              |\
+                         PSDMR_ACTTORW_2W               |\
+                         PSDMR_BL                       |\
+                         PSDMR_LDOTOPRE_1C              |\
+                         PSDMR_WRC_2C                   |\
+                         PSDMR_CL_2)
+
+       /* SDRAM initialization values for 9-column chips
+        */
+#define CFG_OR2_9COL    (CFG_MIN_AM_MASK               |\
+                         ORxS_BPD_4                     |\
+                         ORxS_ROWST_PBI1_A6             |\
+                         ORxS_NUMR_13)
+
+#define CFG_LSDMR_9COL  (PSDMR_PBI                      |\
+                         PSDMR_SDAM_A16_IS_A5           |\
+                         PSDMR_BSMA_A13_A15             |\
+                         PSDMR_SDA10_PBI1_A8            |\
+                         PSDMR_RFRC_7_CLK               |\
+                         PSDMR_PRETOACT_2W              |\
+                         PSDMR_ACTTORW_2W               |\
+                         PSDMR_BL                       |\
+                         PSDMR_LDOTOPRE_1C              |\
+                         PSDMR_WRC_2C                   |\
+                         PSDMR_CL_2)
+
+#endif /* CFG_INIT_LOCAL_SDRAM */
+
+#endif /* CFG_RAMBOOT */
+
+#endif /* __CONFIG_H */
index 540627fe51e3bed9105760b80456e36feb8539ac..bd0d168a59b299be7a9d6b5524a61cdb13a6cf11 100644 (file)
@@ -78,7 +78,8 @@
                                CFG_CMD_PCI     | \
                                CFG_CMD_IRQ     | \
                                CFG_CMD_KGDB    | \
-                               CFG_CMD_DHCP)
+                               CFG_CMD_DHCP    | \
+                               CFG_CMD_BEDBUG  )
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
index 9f5fb57ff15ecbb8e2345f8a5ae3d49b737af9ed..8b7cf7a69d1dd5d0cc0472a0f3d229680cd770f7 100644 (file)
@@ -93,7 +93,8 @@
                                        CFG_CMD_PCMCIA  | \
                                        CFG_CMD_PCI     | \
                                        CFG_CMD_DATE    | \
-                                       CFG_CMD_EEPROM  ))
+                                       CFG_CMD_BEDBUG  | \
+                                       CFG_CMD_EEPROM  ) )
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
 #include <cmd_confdefs.h>
index 44d068067c42fff6564221dd61dc1bfc93e22c0c..25c6a3bdf9a5807b0803367b26e798e1bc979a85 100644 (file)
 #else
 #define CONFIG_COMMANDS              ( CONFIG_CMD_DFL  | \
                                CFG_CMD_EEPROM  | \
+                               CFG_CMD_DHCP    | \
                                CFG_CMD_DATE    | \
                                CFG_CMD_IDE     | \
                                CFG_CMD_BSP     )
-/* CFG_CMD_DHCP        */
 #endif
 #define CONFIG_MAC_PARTITION
 #define CONFIG_DOS_PARTITION
index 98a5d225c8e7773072e43cda8aeaea5f7ebc6c9e..9510e4c03fd126b6cde49194aa7cb3cde4485a4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Copyright 2000
+ * (C) Copyright 2000, 2001
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  *
  * See file CREDITS for list of people who contributed to this
@@ -112,6 +112,7 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt);
 #define AMD_ID_DL324B  0x225F225F      /* 29DL324B ID (32 M, bottom boot sect) */
 
 #define AMD_ID_DL640   0x227E227E      /* 29DL640D ID (64 M, dual boot sectors)*/
+#define AMD_ID_LV640U  0x22D722D7      /* 29LV640U ID (64 M, uniform sectors)  */
 
 #define SST_ID_xF200A  0x27892789      /* 39xF200A ID ( 2M = 128K x 16 )       */
 #define SST_ID_xF400A  0x27802780      /* 39xF400A ID ( 4M = 256K x 16 )       */
@@ -198,6 +199,7 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt);
 #define FLASH_28F160S3 0x0086          /* Intel 28F160S3  ( 16M = 512K x 32 )  */
 #define FLASH_28F320S3 0x0088          /* Intel 28F320S3  ( 32M = 512K x 64 )  */
 #define FLASH_28F320C3 0x0089          /* Intel 28F320C3  ( 32M = 64Kx8 + 512x64)*/
+#define FLASH_AM640U   0x0090          /* AMD Am29LV640U  ( 64M = 4M x 16 )    */
 
 #define FLASH_UNKNOWN  0xFFFF          /* unknown flash type                   */
 
index d554c1d90869039b1a0a123616950a0647b3049d..953fc62cf8537463e7abd312af76a2b6fa6c7cad 100644 (file)
@@ -21,14 +21,16 @@ void  i2c_write (uchar *addr, int alen, uchar *buffer, int len);
 #endif
 
 
-#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || defined (CONFIG_WALNUT405)
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+    defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
-void i2c_receive(unsigned char address,
+void i2c_init(void);
+int  i2c_receive(unsigned char address,
                 unsigned short size_to_expect, unsigned char datain[] );
-void i2c_send(unsigned char address,
+int  i2c_send(unsigned char address,
                 unsigned short size_to_send, unsigned char dataout[] );
 
-#else  /* !CPCI405, !AR405, !WALNUT405 */
+#else  /* !CPCI405, !AR405, !WALNUT405, !ERIC */
 
 #define I2C_RXTX_LEN   128     /* maximum tx/rx buffer length */
 
index f939b384dd7d15711908d4ee524d3cd047f54e4c..29b1cda0d8e77e405f9af9240102da71f7895801 100644 (file)
  * r21, r22 (SRR0), and r23 (SRR1).
  */
 
+/*
+ * Critical exception entry code.  This is just like the other exception
+ * code except that it uses SRR2 and SRR3 instead of SRR0 and SRR1.
+ */
+#define CRITICAL_EXCEPTION_PROLOG       \
+        mtspr   SPRG0,r20;      \
+        mtspr   SPRG1,r21;      \
+        mfcr    r20;            \
+        subi    r21,r1,INT_FRAME_SIZE+STACK_UNDERHEAD;  /* alloc exc. frame */\
+        stw     r20,_CCR(r21);          /* save registers */ \
+        stw     r22,GPR22(r21); \
+        stw     r23,GPR23(r21); \
+        mfspr   r20,SPRG0;      \
+        stw     r20,GPR20(r21); \
+        mfspr   r22,SPRG1;      \
+        stw     r22,GPR21(r21); \
+        mflr    r20;            \
+        stw     r20,_LINK(r21); \
+        mfctr   r22;            \
+        stw     r22,_CTR(r21);  \
+        mfspr   r20,XER;        \
+        stw     r20,_XER(r21);  \
+        mfspr   r22,990;        /* SRR2 */      \
+        mfspr   r23,991;        /* SRR3 */      \
+        stw     r0,GPR0(r21);   \
+        stw     r1,GPR1(r21);   \
+        stw     r2,GPR2(r21);   \
+        stw     r1,0(r21);      \
+        mr      r1,r21;                 /* set new kernel sp */ \
+        SAVE_4GPRS(3, r21);
+/*
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r21, r22 (SRR2), and r23 (SRR3).
+ */
+
 /*
  * Exception vectors.
  *
@@ -253,4 +288,18 @@ label:                                                     \
        .long   int_return - _start + EXC_OFF_SYS_RESET
 
 
+#define CRIT_EXCEPTION(n, label, hdlr)                  \
+        . = n;                                          \
+label:                                                  \
+        CRITICAL_EXCEPTION_PROLOG;                      \
+        lwz     r3,GOT(transfer_to_handler);            \
+        mtlr    r3;                                     \
+        addi    r3,r1,STACK_FRAME_OVERHEAD;             \
+        li      r20,MSR_KERNEL;                         \
+        rlwimi  r20,r23,0,25,25;                        \
+        blrl    ;                                       \
+.L_ ## label :                                          \
+        .long   hdlr - _start + EXC_OFF_SYS_RESET;      \
+        .long   crit_return - _start + EXC_OFF_SYS_RESET
+
 #endif /* __PPC_ASM_TMPL__ */
index 0e866b09c56da244a86d07be473ffc8251c76442..46889c259565c6381d04de220362693013b7a5ac 100644 (file)
@@ -183,7 +183,8 @@ void inline         setenv (char *, char *);
 #if defined(CONFIG_CPCI405)    || \
     defined(CONFIG_AR405)      || \
     defined (CONFIG_WALNUT405) || \
-    defined (CONFIG_CPCIISER4)
+    defined (CONFIG_CPCIISER4) || \
+    defined (CONFIG_ERIC)
 /* $(CPU)/405gp_pci.c */
 void    pci_init      (void);
 void    pciinfo       (int);
@@ -217,7 +218,8 @@ void        reset_phy     (void);
     defined(CONFIG_CANBT)      || \
     defined(CONFIG_WALNUT405)  || \
     defined(CONFIG_CPCIISER4)  || \
-    defined(CONFIG_LWMON)
+    defined(CONFIG_LWMON)      || \
+    defined(CONFIG_TQM8260)
 /* $(BOARD)/eeprom.c */
 void eeprom_init  (void);
 void eeprom_read  (unsigned offset, uchar *buffer, unsigned cnt);
index bb68a352c6ece40bce2a040eb9c0398e13640f70..1f74ebe539f4233200369ee8e5d8e8687a6d9e73 100644 (file)
@@ -24,6 +24,6 @@
 #ifndef        __VERSION_H__
 #define        __VERSION_H__
 
-#define        PPCBOOT_VERSION "PPCBoot 0.9.3"
+#define        PPCBOOT_VERSION "PPCBoot 1.0.0-pre1"
 
 #endif /* __VERSION_H__ */
index de4cbc205a09b7f54e8bde838d5b7f7496030ce4..8ad82c73c7f0f4395609729fc9fecbd18f74e1bf 100644 (file)
 #define DEBUG_BOOTP_EXT        1       /* Debug received vendor fields */
 #endif
 
+#ifdef DEBUG_BOOTP_EXT
+#define debug_ext(fmt,args...) printf (fmt ,##args)
+#else
+#define debug_ext(fmt,args...)
+#endif
+
 #include <ppcboot.h>
 #include <command.h>
 #include "net.h"
@@ -81,9 +87,8 @@ static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len)
        if (bp->bp_id != BootpID)
                retval = -6;
 
-#ifdef DEBUG
-       printf("Filtering pkt = %d\n", retval);
-#endif
+       debug ("Filtering pkt = %d\n", retval);
+
        return retval;
 }
 
@@ -96,9 +101,8 @@ void BootpCopyNetParams(Bootp_t *bp)
        NetServerIP = bp->bp_siaddr;
        NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
        copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
-#ifdef DEBUG
-       printf("Bootfile: %s\n", BootFile);
-#endif
+
+       debug ("Bootfile: %s\n", BootFile);
 
        /* Propagate to environment */
        setenv ("bootfile", BootFile);
@@ -109,9 +113,7 @@ static void BootpVendorFieldProcess(u8 *ext)
 {
     int size = *(ext+1) ;
 
-#ifdef DEBUG_BOOTP_EXT
-    printf("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
-#endif
+    debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
 
     NetBootFileSize = 0;
 
@@ -197,9 +199,9 @@ static void BootpVendorFieldProcess(u8 *ext)
 static void BootpVendorProcess(u8 *ext, int size)
 {
     u8 *end = ext + size ;
-#ifdef DEBUG_BOOTP_EXT
-    printf("[BOOTP] Checking extension (%d bytes)...\n", size);
-#endif
+
+    debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);
+
     while ((ext < end) && (*ext != 0xff)) {
        if (*ext == 0) {
            ext ++ ;
@@ -252,14 +254,12 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
        Bootp_t *bp;
        char    *s;
 
-#ifdef DEBUG
-       printf("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
+       debug ("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
                src, dest, len, sizeof (Bootp_t));
-#endif /* DEBUG */
 
        bp = (Bootp_t *)pkt;
 
-       if ( BootpCheckPkt(pkt, dest, src, len) )       /* Filter out pkts we don't want */
+       if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
                return;
 
        /*
@@ -277,9 +277,7 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
 
        NetSetTimeout(0, (thand_f *)0);
 
-#ifdef DEBUG
-       printf("Got good BOOTP\n");
-#endif /* DEBUG */
+       debug ("Got good BOOTP\n");
 
        if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
                /*
@@ -596,14 +594,31 @@ void DhcpOptionsProcess(char *popt)
                        case  3:
                                NetOurGatewayIP = *(IPaddr_t *)(popt + 2);
                                break;
-                       case 53:
-                               break;          /* Ignore Message Type Option */
-                       case 54:
-                               NetServerIP = *(IPaddr_t *)(popt+2);
+                       case  6:
+                               NetOurDNSIP = *(IPaddr_t *)(popt +2);
+                               break;
+                       case 12:
+                               memcpy(&NetOurHostName, popt+2, oplen);
+                               NetOurHostName[oplen] = 0 ;
+                               break;
+                       case 15:                /* Ignore Domain Name Option */
+                               break;
+                       case 17:
+                               memcpy(&NetOurRootPath, popt+2, oplen);
+                               NetOurRootPath[oplen] = 0 ;
                                break;
                        case 51:
                                dhcp_leasetime = *(unsigned int *)(popt + 2);
                                break;
+                       case 53:                /* Ignore Message Type Option */
+                               break;
+                       case 54:
+                               NetServerIP = *(IPaddr_t *)(popt+2);
+                               break;
+                       case 58:                /* Ignore Renewal Time Option */
+                               break;
+                       case 59:                /* Ignore Rebinding Time Option */
+                               break;
                        default:
                                printf("*** Unhandled DHCP Option in OFFER/ACK: %d\n",
                                        *popt);
@@ -633,9 +648,7 @@ void DhcpSendRequestPkt(Bootp_t *bp_offer)
        Bootp_t *bp;
        int pktlen, iplen, extlen;
 
-#ifdef DEBUG
-       printf("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
-#endif
+       debug ("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
        pkt = NetTxPacket;
        memset ((void*)pkt, 0, PKTSIZE);
 
@@ -651,7 +664,7 @@ void DhcpSendRequestPkt(Bootp_t *bp_offer)
        bp->bp_hlen = HWL_ETHER;
        bp->bp_hops = 0;
        bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
-       bp->bp_ciaddr = bp_offer->bp_ciaddr;
+       bp->bp_ciaddr =  bp_offer->bp_ciaddr;
        bp->bp_yiaddr =  bp_offer->bp_yiaddr;
        bp->bp_siaddr =  bp_offer->bp_siaddr;
        bp->bp_giaddr =  bp_offer->bp_giaddr;
@@ -672,7 +685,7 @@ void DhcpSendRequestPkt(Bootp_t *bp_offer)
        iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
        NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
 
-       printf("Transmitting packet: len = %d\n", pktlen);
+       debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
        NetSendPacket(NetTxPacket, pktlen);
 }
 
@@ -683,13 +696,15 @@ static void
 DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
 {
        Bootp_t *bp = (Bootp_t *)pkt;
+
+       debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
+               src, dest, len, dhcp_state);
+
        if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
                return;
 
-#ifdef DEBUG
-       printf("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
+       debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
                src, dest, len, dhcp_state);
-#endif /* DEBUG */
 
        switch (dhcp_state) {
        case SELECTING:
@@ -699,22 +714,20 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
                 * If filename is in format we recognize, assume it is a valid
                 * OFFER from a server we want.
                 */
-#ifdef DEBUG
-               printf("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
-#endif
+               debug ("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
 #ifdef CFG_BOOTFILE_PREFIX
                if (strncmp(bp->bp_file,
                            CFG_BOOTFILE_PREFIX,
                            strlen(CFG_BOOTFILE_PREFIX)) == 0 ) {
 #endif /* CFG_BOOTFILE_PREFIX */
 
-#ifdef DEBUG
-                       printf("TRANSITIONING TO REQUESTING STATE\n");
-#endif
+                       debug ("TRANSITIONING TO REQUESTING STATE\n");
                        dhcp_state = REQUESTING;
+#if 0
                        if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
                                DhcpOptionsProcess(&bp->bp_vend[4]);
 
+#endif
                        BootpCopyNetParams(bp); /* Store net params from reply */
 
                        NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
@@ -726,12 +739,14 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
                return;
                break;
        case REQUESTING:
-#ifdef DEBUG
-               printf("DHCP State: REQUESTING\n");
-#endif
+               debug ("DHCP State: REQUESTING\n");
+
                if ( DhcpMessageType(bp->bp_vend) == DHCP_ACK ) {
+                       if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
+                               DhcpOptionsProcess(&bp->bp_vend[4]);
+                       BootpCopyNetParams(bp); /* Store net params from reply */
                        dhcp_state = BOUND;
-                       printf("DhcpHandler: Client BOUND to address ");
+                       printf("DHCP client bound to address ");
                        print_IPaddr(NetOurIP);
                        printf("\n");
 #if 0  /* Not much point in configuring PPCBoot w/o loading boot file - CLH */
@@ -746,7 +761,7 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
                }
                break;
        default:
-               printf("DHCP State: INVALID STATE\n");
+               printf("DHCP: INVALID STATE\n");
                break;
        }
 
index 0e03cce920eb0e67804474c9d327af71d4d7da46..443e208a7d0bd4510f20034f3321149703cd46f8 100644 (file)
--- a/net/net.c
+++ b/net/net.c
@@ -68,7 +68,9 @@
 
 #if (CONFIG_COMMANDS & CFG_CMD_NET)
 
-#undef ET_DEBUG
+#if 0
+#define ET_DEBUG
+#endif
 
 /** BOOTP EXTENTIONS **/
 
@@ -440,8 +442,10 @@ NetReceive(volatile uchar * pkt, int len)
 #ifdef ET_DEBUG
                printf("Got IP\n");
 #endif
-               if (len < IP_HDR_SIZE)
+               if (len < IP_HDR_SIZE) {
+                       debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
                        return;
+               }
                if (len < SWAP16(ip->ip_len)) {
                        printf("len bad %d < %d\n", len, SWAP16(ip->ip_len));
                        return;
@@ -450,16 +454,21 @@ NetReceive(volatile uchar * pkt, int len)
 #ifdef ET_DEBUG
                printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
 #endif
-               if ((ip->ip_hl_v & 0xf0) != 0x40)
+               if ((ip->ip_hl_v & 0xf0) != 0x40) {
                        return;
-               if (ip->ip_off & SWAP16c(0x1fff)) /* Can't deal w/ fragments */
+               }
+               if (ip->ip_off & SWAP16c(0x1fff)) { /* Can't deal w/ fragments */
                        return;
+               }
                if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
                        printf("checksum bad\n");
                        return;
                }
-               if (NetOurIP && ip->ip_dst != NetOurIP)
+               if (NetOurIP &&
+                   ip->ip_dst != NetOurIP &&
+                   ip->ip_dst != 0xFFFFFFFF) {
                        return;
+               }
                /*
                 * watch for ICMP host redirects
                 *