]> www.infradead.org Git - users/rw/ppcboot.git/commitdiff
* Patch by Denis Peter, 5 Dec 2001
authorwdenk <wdenk>
Fri, 7 Dec 2001 01:21:34 +0000 (01:21 +0000)
committerwdenk <wdenk>
Fri, 7 Dec 2001 01:21:34 +0000 (01:21 +0000)
  - add USB support for 40x
  - add support for MIP405 board
  - Move PIP405 into new manufacturer's directory,
    separate out common stuff
  - changed scsi_init in file common/board.c to make it common to IDE
    init
  - added last_stage_init in common/board.c (#ifdef
    CONFIG_LAST_STAGE_INIT) for parts which needs working interrupts
    (ISA Keyboard etc)
  - replaced "defined(CONFIG_PIP405)" in common/cmd_i2c.c with
    "defined(CONFIG_I2C405)" which is also defined for MIP405. Other
    405 based boards may also change to this define. (CONFIG_W70
    CONFIG_CPCI405, CONFIG_AR405, CONFIG_WALNUT405 and CONFIG_ERIC).
  - add "device_deregister()" in common/devices.c. Used to
    deregister the USB keyboard.
  - removed drv_isa_kbd_init() in common/devices.c because it will
    not work when initializing before setting up the interrupts.
  - changed type of TimeOut from int to ulong and the sequence how
    the TimeOut value is calculated (to prevent an overflow for a CPU
    frequency of 266MHz) in file cpu/ppc4xx/i2c.c.
  - fix size rounding in disc/part.c

66 files changed:
CHANGELOG
CREDITS
MAKEALL
Makefile
README
board/mpl/common/flash.c [new file with mode: 0644]
board/mpl/common/isa.c [new file with mode: 0644]
board/mpl/common/isa.h [new file with mode: 0644]
board/mpl/common/kbd.c [new file with mode: 0644]
board/mpl/common/kbd.h [new file with mode: 0644]
board/mpl/common/memtst.c [new file with mode: 0644]
board/mpl/common/pci.c [new file with mode: 0644]
board/mpl/common/pci.h [new file with mode: 0644]
board/mpl/common/pci_parts.h [new file with mode: 0644]
board/mpl/common/sym53c8xx.c [new file with mode: 0644]
board/mpl/common/sym53c8xx_defs.h [new file with mode: 0644]
board/mpl/common/usb_uhci.c [new file with mode: 0644]
board/mpl/common/usb_uhci.h [new file with mode: 0644]
board/mpl/common/vga_table.h [new file with mode: 0644]
board/mpl/common/video.c [new file with mode: 0644]
board/mpl/common/video.h [new file with mode: 0644]
board/mpl/mip405/Makefile [new file with mode: 0644]
board/mpl/mip405/cmd_mip405.c [new file with mode: 0644]
board/mpl/mip405/config.mk [new file with mode: 0644]
board/mpl/mip405/init.S [new file with mode: 0644]
board/mpl/mip405/mip405.c [new file with mode: 0644]
board/mpl/mip405/mip405.h [new file with mode: 0644]
board/mpl/mip405/ppcboot.lds [new file with mode: 0644]
board/mpl/pip405/Makefile [new file with mode: 0644]
board/mpl/pip405/cmd_pip405.c [new file with mode: 0644]
board/mpl/pip405/config.mk [new file with mode: 0644]
board/mpl/pip405/init.S [new file with mode: 0644]
board/mpl/pip405/pip405.c [new file with mode: 0644]
board/mpl/pip405/pip405.h [new file with mode: 0644]
board/mpl/pip405/ppcboot.lds [new file with mode: 0644]
board/mpl/pip405/ppcboot.lds.debug [new file with mode: 0644]
common/Makefile
common/board.c
common/cmd_i2c.c
common/cmd_pcmcia.c
common/cmd_scsi.c
common/cmd_usb.c [new file with mode: 0644]
common/command.c
common/devices.c
common/lists.c
common/usb.c [new file with mode: 0644]
common/usb_kbd.c [new file with mode: 0644]
common/usb_storage.c [new file with mode: 0644]
cpu/ppc4xx/405gp_pci.c
cpu/ppc4xx/i2c.c
disk/part.c
doc/README.commands
doc/README.usb [new file with mode: 0644]
include/cmd_bsp.h
include/cmd_confdefs.h
include/cmd_usb.h [new file with mode: 0644]
include/config_LANTEC.h
include/config_MIP405.h [new file with mode: 0644]
include/config_MPC8260ADS.h
include/config_PIP405.h
include/config_hymod.h
include/devices.h
include/lists.h
include/ppcboot.h
include/usb.h [new file with mode: 0644]
include/usb_defs.h [new file with mode: 0644]

index 771578a3adc48c718d4b4229fe95781856de9bab..7cafdd7e38164dd783b56a5d7559769436ec45f1 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -56,6 +56,33 @@ To do:
 Modifications for 1.1.2:
 ======================================================================
 
+* Patch by Denis Peter, 5 Dec 2001
+  - add USB support for 40x
+  - add support for MIP405 board
+  - Move PIP405 into new manufacturer's directory,
+    separate out common stuff
+  - changed scsi_init in file common/board.c to make it common to IDE
+    init
+  - added last_stage_init in common/board.c (#ifdef
+    CONFIG_LAST_STAGE_INIT) for parts which needs working interrupts
+    (ISA Keyboard etc)
+  - replaced "defined(CONFIG_PIP405)" in common/cmd_i2c.c with
+    "defined(CONFIG_I2C405)" which is also defined for MIP405. Other
+    405 based boards may also change to this define. (CONFIG_W70
+    CONFIG_CPCI405, CONFIG_AR405, CONFIG_WALNUT405 and CONFIG_ERIC).
+  - add "device_deregister()" in common/devices.c. Used to
+    deregister the USB keyboard.
+  - removed drv_isa_kbd_init() in common/devices.c because it will
+    not work when initializing before setting up the interrupts.
+  - changed type of TimeOut from int to ulong and the sequence how
+    the TimeOut value is calculated (to prevent an overflow for a CPU
+    frequency of 266MHz) in file cpu/ppc4xx/i2c.c.
+  - fix size rounding in disc/part.c
+
+* Fix for broken SanDisk which spuriously set high bit in function ID
+  CIS tuple
+  Patch by Peter Desnoyers, 05 Dec 2001
+
 * Add new 8260 mask revision support
 
 * Add support for TTTech C2MON board
diff --git a/CREDITS b/CREDITS
index 86c6d64f61893ba67db6a37e95f3ebf0e5868b6f..d3e2975b9c541015dcaef523ad5b9d40ad338ead 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -99,7 +99,8 @@ D: Port to MPC8260ADS board
 
 N: Murray Jensen
 E: Murray.Jensen@cmst.csiro.au
-D: Initial 8260 support; GDB support; Port to Cogent+Hymod boards; Hymod Board Database
+D: Initial 8260 support; GDB support
+D: Port to Cogent+Hymod boards; Hymod Board Database
 W: http://www.msa.cmst.csiro.au/ourstaff/MurrayJensen/mjj.html
 
 N: Yoo. Jonghoon
@@ -132,7 +133,9 @@ D: Support for Embedded Planet RPX Super Board
 
 N: Denis Peter
 E: d.peter@mpl.ch
-D: Port to PIP405 board, support for SCSI, floppy, CDROM, CT69000 video, ...
+D: Support for 4xx SCSI, floppy, CDROM, CT69000 video, ...
+D: Support for PIP405 board
+D: Support for MIP405 board
 
 N: Bill Pitts
 E: wlp@mindspring.com
diff --git a/MAKEALL b/MAKEALL
index 27399d9e2755cc0f8e7eb1670f7198accaf55267..6c0b8f690bae1cac8f1ec50a986bdc1226c82bae 100755 (executable)
--- a/MAKEALL
+++ b/MAKEALL
@@ -36,9 +36,9 @@ LIST_4xx="    \
        CANBT           CPCI405         \
        CPCIISER4       CRAYL1          \
        DASA_SIM        ERIC            \
-       OCRTC           PIP405          \
-       W7OLMC          W7OLMG          \
-       WALNUT405                       \
+       MIP405          OCRTC           \
+       PIP405          W7OLMC          \
+       W7OLMG          WALNUT405       \
 "
 
 #########################################################################
index e8b10f221d0cad002548c75c3b52356acda55e75..eb80451271e5dccf4a09418628f20eb4e2772d7a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -459,6 +459,15 @@ ERIC_config:unconfig
        echo "CPU   = ppc4xx"   >>config.mk ;   \
        echo "#include <config_$(@:_config=).h>" >config.h
 
+MIP405_config:unconfig
+       @echo "Configuring for $(@:_config=) Board..." ; \
+       cd ./include ;                          \
+       echo "ARCH  = ppc"      > config.mk ;   \
+       echo "BOARD = mip405"   >>config.mk ;   \
+       echo "CPU   = ppc4xx"   >>config.mk ;   \
+       echo "VENDOR = mpl"     >>config.mk ;   \
+       echo "#include <config_$(@:_config=).h>" >config.h
+
 OCRTC_config:  unconfig
        @echo "Configuring for $(@:_config=) Board..." ; \
        cd ./include ;                          \
@@ -474,6 +483,7 @@ PIP405_config:unconfig
        echo "ARCH  = ppc"      > config.mk ;   \
        echo "BOARD = pip405"   >>config.mk ;   \
        echo "CPU   = ppc4xx"   >>config.mk ;   \
+       echo "VENDOR = mpl"     >>config.mk ;   \
        echo "#include <config_$(@:_config=).h>" >config.h
 
 W7OLMC_config  \
diff --git a/README b/README
index 8c951f86f256592c4d5dc01f70141b93a36279cd..059a1ebae4c1d3ac7ac39e4f8a638c7911c6e72a 100644 (file)
--- a/README
+++ b/README
@@ -128,7 +128,9 @@ Directory Hierarchy:
 - board/lantec Files specific to LANTEC     boards
 - board/lwmon  Files specific to LWMON      boards
 - board/mbx8xx Files specific to MBX        boards
-- board/pip405 Files specific to PIP405     boards
+- board/mpl/common     Common files for MPL boards
+- board/mpl/pip405     Files specific to PIP405     boards
+- board/mpl/mip405     Files specific to MIP405     boards
 - board/RPXlite Files specific to RPXlite    boards
 - board/rpxsuper
                Files specific to RPXsuper   boards
@@ -211,18 +213,18 @@ The following options need to be configured:
 
 - Board Type:  Define exactly one of
 
-               CONFIG_ADCIOP,      CONFIG_FADS,        CONFIG_RPXSUPER,
-               CONFIG_ADS,         CONFIG_FPS850L,     CONFIG_SANDPOINT,
-               CONFIG_BSEIP,       CONFIG_HERMES,      CONFIG_SBC8260,
-               CONFIG_COGENT,      CONFIG_HYMOD,       CONFIG_SM850,
-               CONFIG_COGENT,      CONFIG_IP860,       CONFIG_SPD823TS,
-               CONFIG_CPCI405,     CONFIG_IVMS8,       CONFIG_SXNI855T,
-               CONFIG_CU824,       CONFIG_MBX,         CONFIG_TQM823L,
-               CONFIG_ERIC,        CONFIG_PIP405,      CONFIG_TQM8260,
-               CONFIG_ETX094,      CONFIG_RDSPROTO,    CONFIG_TQM850L,
-               CONFIG_EVB64260,    CONFIG_RPXCLASSIC,  CONFIG_TQM855L,
-               CONFIG_EVB64260,    CONFIG_RPXLITE,     CONFIG_TQM860L,
-               CONFIG_PCU_E,       CONFIG_CCM
+               CONFIG_ADCIOP,      CONFIG_FADS,        CONFIG_RPXLITE,
+               CONFIG_ADS,         CONFIG_FPS850L,     CONFIG_RPXSUPER,
+               CONFIG_BSEIP,       CONFIG_HERMES,      CONFIG_SANDPOINT,
+               CONFIG_CCM,         CONFIG_HYMOD,       CONFIG_SBC8260,
+               CONFIG_COGENT,      CONFIG_IP860,       CONFIG_SM850,
+               CONFIG_COGENT,      CONFIG_IVMS8,       CONFIG_SPD823TS,
+               CONFIG_CPCI405,     CONFIG_MBX,         CONFIG_SXNI855T,
+               CONFIG_CU824,       CONFIG_MIP405,      CONFIG_TQM823L,
+               CONFIG_ERIC,        CONFIG_PCU_E,       CONFIG_TQM8260,
+               CONFIG_ETX094,      CONFIG_PIP405,      CONFIG_TQM850L,
+               CONFIG_EVB64260,    CONFIG_RDSPROTO,    CONFIG_TQM855L,
+               CONFIG_EVB64260,    CONFIG_RPXCLASSIC,  CONFIG_TQM860L
 
 - CPU Module Type: (if CONFIG_COGENT is defined)
                Define exactly one of
@@ -395,10 +397,11 @@ The following options need to be configured:
                CFG_CMD_DHCP      DHCP support
                CFG_CMD_BEDBUG    Include BedBug Debugger
                CFG_CMD_ELF       bootelf, bootvx
-               CFG_CMD_FDC       Floppy Disk Support
-               CFG_CMD_SCSI      SCSI Support
+               CFG_CMD_FDC     * Floppy Disk Support
+               CFG_CMD_SCSI    * SCSI Support
                CFG_CMD_SETGETDCR Support for DCR Register access (4xx only)
-               CFG_CMD_BSP     * Board SPecific functions
+                CFG_CMD_USB     * USB support
+                CFG_CMD_BSP    * Board SPecific functions
                -----------------------------------------------
                CFG_CMD_ALL     all
 
@@ -465,6 +468,17 @@ The following options need to be configured:
                 maximum numbers of LUNs, SCSI ID's and target
                 devices.
 
+- USB Support:
+                At the moment only the UHCI host controller is
+                supported (PIP405, MIP405); define
+               CONFIG_USB_UHCI to enable it.
+                define CONFIG_USB_KEYBOARD to enable the USB Keyboard
+                end define CONFIG_USB_STORAGE to enable the USB
+                storage devices.
+                Note:
+                Supported are USB Keyboards and USB Floppy drives
+                (TEAC FD-05PUB).
+
 - Keyboard Support:
                CONFIG_ISA_KEYBOARD
 
diff --git a/board/mpl/common/flash.c b/board/mpl/common/flash.c
new file mode 100644 (file)
index 0000000..6f2eef6
--- /dev/null
@@ -0,0 +1,886 @@
+/*
+ * (C) Copyright 2000, 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
+ */
+
+/*
+ * Modified 4/5/2001
+ * Wait for completion of each sector erase command issued
+ * 4/5/2001
+ * Chris Hallinan - DS4.COM, Inc. - clh@net1plus.com
+ */
+
+/*
+ * Modified 3/7/2001
+ * - adopted for pip405, Denis Peter, MPL AG Switzerland
+ * TODO:
+ * clean-up
+ */
+
+#include <ppcboot.h>
+#include <ppc4xx.h>
+#include <asm/processor.h>
+#ifdef CONFIG_PIP405
+#include "../pip405/pip405.h"
+#endif
+#ifdef CONFIG_MIP405
+#include "../mip405/mip405.h"
+#endif
+
+flash_info_t   flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips        */
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info);
+static int write_word (flash_info_t *info, ulong dest, ulong data);
+static void flash_get_offsets (ulong base, flash_info_t *info);
+
+void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt);
+
+
+#ifdef CONFIG_ADCIOP
+#define ADDR0           0x0aa9
+#define ADDR1           0x0556
+#define FLASH_WORD_SIZE unsigned char
+#endif
+
+#ifdef CONFIG_CPCI405
+#define ADDR0           0x5555
+#define ADDR1           0x2aaa
+#define FLASH_WORD_SIZE unsigned short
+#endif
+
+#ifdef CONFIG_PIP405
+#define ADDR0           0x5555
+#define ADDR1           0x2aaa
+#define FLASH_WORD_SIZE unsigned short
+#endif
+
+#ifdef CONFIG_MIP405
+#define ADDR0           0x5555
+#define ADDR1           0x2aaa
+#define FLASH_WORD_SIZE unsigned short
+#endif
+
+#define FALSE           0
+#define TRUE            1
+
+/*-----------------------------------------------------------------------
+ */
+
+
+unsigned long flash_init (void)
+{
+       unsigned long size_b0, size_b1;
+       int i;
+  unsigned long pbcr;
+  unsigned long base_b0, base_b1;
+  unsigned char rc;
+  
+  rc=switch_cs(FALSE); /* map Flash High */
+
+       if(rc) 
+               printf("(MPS Boot) ");
+       else
+               printf("(Flash Boot) ");
+       /* Init: no FLASHes known */
+       for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) {
+               flash_info[i].flash_id = FLASH_UNKNOWN;
+       }
+
+       /* Static FLASH Bank configuration here - FIXME XXX */
+
+       size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]);
+
+       if (flash_info[0].flash_id == FLASH_UNKNOWN) {
+               printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+                       size_b0, size_b0<<20);
+       }
+       /* Only one bank */
+       if (CFG_MAX_FLASH_BANKS == 1)
+         {
+           /* Setup offsets */
+                       /*  flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]); */
+           /* Monitor protection ON by default */
+#if CFG_MONITOR_BASE >= CFG_FLASH_BASE
+                   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;
+         }
+
+       /* 2 banks */
+       else
+         {
+           size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]);
+           
+           /* Re-do sizing to get full correct info */
+           
+           if (size_b1)
+             {
+               mtdcr(ebccfga, pb0cr);
+               pbcr = mfdcr(ebccfgd);
+               mtdcr(ebccfga, pb0cr);
+               base_b1 = -size_b1;
+               pbcr = (pbcr & 0x0001ffff) | base_b1 | (((size_b1/1024/1024)-1)<<17);
+               mtdcr(ebccfgd, pbcr);
+               /*          printf("pb1cr = %x\n", pbcr); */
+             }
+           
+           if (size_b0)
+             {
+               mtdcr(ebccfga, pb1cr);
+               pbcr = mfdcr(ebccfgd);
+               mtdcr(ebccfga, pb1cr);
+               base_b0 = base_b1 - size_b0;
+               pbcr = (pbcr & 0x0001ffff) | base_b0 | (((size_b0/1024/1024)-1)<<17);
+               mtdcr(ebccfgd, pbcr);
+               /*            printf("pb0cr = %x\n", pbcr); */
+             }
+           
+           size_b0 = flash_get_size((vu_long *)base_b0, &flash_info[0]);
+           
+           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,
+                               base_b0+size_b0-1,
+                               &flash_info[0]);
+           
+           if (size_b1) {
+             /* Re-do sizing to get full correct info */
+             size_b1 = flash_get_size((vu_long *)base_b1, &flash_info[1]);
+             
+             flash_get_offsets (base_b1, &flash_info[1]);
+             
+             /* monitor protection ON by default */
+             (void)flash_protect(FLAG_PROTECT_SET,
+                                 base_b1+size_b1-CFG_MONITOR_LEN,
+                                 base_b1+size_b1-1,
+                                 &flash_info[1]);
+             /* monitor protection OFF by default (one is enough) */
+             (void)flash_protect(FLAG_PROTECT_CLEAR,
+                                 base_b0+size_b0-CFG_MONITOR_LEN,
+                                 base_b0+size_b0-1,
+                                 &flash_info[0]);
+           } else {
+             flash_info[1].flash_id = FLASH_UNKNOWN;
+             flash_info[1].sector_count = -1;
+           }
+           
+           flash_info[0].size = size_b0;
+           flash_info[1].size = size_b1;
+         }/* else 2 banks */
+       /*      switch_cs(rc); */ /* switch mode back */
+       return (size_b0 + size_b1);
+}
+
+
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+       return;
+}
+#if 0
+/*-----------------------------------------------------------------------
+ */
+static void flash_get_offsets (ulong base, flash_info_t *info)
+{
+       int i;
+
+       /* set up sector start address table */
+  if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) || 
+           (info->flash_id  == FLASH_AM040)){
+               for (i = 0; i < info->sector_count; i++)
+                       info->start[i] = base + (i * 0x00010000);
+  } 
+  else {
+               if (info->flash_id & FLASH_BTYPE) {
+               /* set sector offsets for bottom boot block type        */
+               info->start[0] = base + 0x00000000;
+               info->start[1] = base + 0x00004000;
+               info->start[2] = base + 0x00006000;
+               info->start[3] = base + 0x00008000;
+               for (i = 4; i < info->sector_count; i++) {
+                       info->start[i] = base + (i * 0x00010000) - 0x00030000;
+               }
+           } else {
+               /* set sector offsets for top boot block type           */
+               i = info->sector_count - 1;
+               info->start[i--] = base + info->size - 0x00004000;
+               info->start[i--] = base + info->size - 0x00006000;
+               info->start[i--] = base + info->size - 0x00008000;
+               for (; i >= 0; i--) {
+                       info->start[i] = base + i * 0x00010000;
+               }
+           }
+       }
+}
+
+#endif
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info  (flash_info_t *info)
+{
+       int i;
+    int k;
+       int size;
+    int erased;
+    volatile unsigned long *flash;
+       
+       if (info->flash_id == FLASH_UNKNOWN) {
+               printf ("missing or unknown FLASH type\n");
+               return;
+       }
+
+       switch (info->flash_id & FLASH_VENDMASK) {
+       case FLASH_MAN_AMD:     printf ("AMD ");                break;
+       case FLASH_MAN_FUJ:     printf ("FUJITSU ");            break;
+       case FLASH_MAN_SST:     printf ("SST ");                break;
+       case FLASH_MAN_INTEL:   printf ("Intel ");              break;
+       default:                printf ("Unknown Vendor ");     break;
+       }
+
+       switch (info->flash_id & FLASH_TYPEMASK) {
+       case FLASH_AM040:       printf ("AM29F040 (512 Kbit, uniform sector size)\n");
+                               break;
+       case FLASH_AM400B:      printf ("AM29LV400B (4 Mbit, bottom boot sect)\n");
+                               break;
+       case FLASH_AM400T:      printf ("AM29LV400T (4 Mbit, top boot sector)\n");
+                               break;
+       case FLASH_AM800B:      printf ("AM29LV800B (8 Mbit, bottom boot sect)\n");
+                               break;
+       case FLASH_AM800T:      printf ("AM29LV800T (8 Mbit, top boot sector)\n");
+                               break;
+       case FLASH_AM160B:      printf ("AM29LV160B (16 Mbit, bottom boot sect)\n");
+                               break;
+       case FLASH_AM160T:      printf ("AM29LV160T (16 Mbit, top boot sector)\n");
+                               break;
+       case FLASH_AM320B:      printf ("AM29LV320B (32 Mbit, bottom boot sect)\n");
+                               break;
+       case FLASH_AM320T:      printf ("AM29LV320T (32 Mbit, top boot sector)\n");
+                               break;
+       case FLASH_SST800A:     printf ("SST39LF/VF800 (8 Mbit, uniform sector size)\n");
+                               break;
+       case FLASH_SST160A:     printf ("SST39LF/VF160 (16 Mbit, uniform sector size)\n");
+                               break;
+       case FLASH_INTEL320T:   printf ("TE28F320C3 (32 Mbit, top sector size)\n");
+                               break;
+       default:                printf ("Unknown Chip Type\n");
+                               break;
+       }
+       
+       printf ("  Size: %ld KB in %d Sectors\n",
+               info->size >> 10, info->sector_count);
+
+       printf ("  Sector Start Addresses:");
+       for (i=0; i<info->sector_count; ++i) {
+       /*
+     * Check if whole sector is erased
+     */
+               if (i != (info->sector_count-1))
+       size = info->start[i+1] - info->start[i];
+               else
+      size = info->start[0] + info->size - info->start[i];
+    erased = 1;
+    flash = (volatile unsigned long *)info->start[i];
+    size = size >> 2;        /* divide by 4 for longword access */
+    for (k=0; k<size; k++)
+    {
+       if (*flash++ != 0xffffffff)
+                       {
+                               erased = 0;
+                               break;
+                       }
+               }
+               if ((i % 5) == 0)
+                       printf ("\n   ");
+#if 0 /* test-only */
+               printf (" %08lX%s",
+                       info->start[i],
+                       info->protect[i] ? " (RO)" : "     "
+#else
+               printf (" %08lX%s%s",
+                       info->start[i],
+                       erased ? " E" : "  ",
+                       info->protect[i] ? "RO " : "   "
+#endif
+               );
+       }
+       printf ("\n");
+
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+
+/*-----------------------------------------------------------------------
+ */
+
+/*
+ * The following code cannot be run from FLASH!
+ */
+static ulong flash_get_size (vu_long *addr, flash_info_t *info)
+{
+       short i;
+       FLASH_WORD_SIZE value;
+       ulong base = (ulong)addr;
+       volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr;
+
+       /* Write auto select command: read Manufacturer ID */
+       addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+       addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+       addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090;
+
+       value = addr2[0];
+       /*      printf("flash_get_size value: %x\n",value); */
+       switch (value) {
+       case (FLASH_WORD_SIZE)AMD_MANUFACT:
+               info->flash_id = FLASH_MAN_AMD;
+               break;
+       case (FLASH_WORD_SIZE)FUJ_MANUFACT:
+               info->flash_id = FLASH_MAN_FUJ;
+               break;
+       case (FLASH_WORD_SIZE)INTEL_MANUFACT:
+               info->flash_id = FLASH_MAN_INTEL;
+               break;
+       case (FLASH_WORD_SIZE)SST_MANUFACT:
+               info->flash_id = FLASH_MAN_SST;
+               break;
+       default:
+               info->flash_id = FLASH_UNKNOWN;
+               info->sector_count = 0;
+               info->size = 0;
+               return (0);                     /* no or unknown flash  */
+       }
+       value = addr2[1];                       /* device ID            */
+       /*      printf("Device value %x\n",value); */
+       switch (value) {
+       case (FLASH_WORD_SIZE)AMD_ID_F040B:
+               info->flash_id += FLASH_AM040;
+               info->sector_count = 8;
+               info->size = 0x0080000; /* => 512 ko */
+               break;
+       case (FLASH_WORD_SIZE)AMD_ID_LV400T:
+               info->flash_id += FLASH_AM400T;
+               info->sector_count = 11;
+               info->size = 0x00080000;
+               break;                          /* => 0.5 MB            */
+
+       case (FLASH_WORD_SIZE)AMD_ID_LV400B:
+               info->flash_id += FLASH_AM400B;
+               info->sector_count = 11;
+               info->size = 0x00080000;
+               break;                          /* => 0.5 MB            */
+
+       case (FLASH_WORD_SIZE)AMD_ID_LV800T:
+               info->flash_id += FLASH_AM800T;
+               info->sector_count = 19;
+               info->size = 0x00100000;
+               break;                          /* => 1 MB              */
+
+       case (FLASH_WORD_SIZE)AMD_ID_LV800B:
+               info->flash_id += FLASH_AM800B;
+               info->sector_count = 19;
+               info->size = 0x00100000;
+               break;                          /* => 1 MB              */
+
+       case (FLASH_WORD_SIZE)AMD_ID_LV160T:
+               info->flash_id += FLASH_AM160T;
+               info->sector_count = 35;
+               info->size = 0x00200000;
+               break;                          /* => 2 MB              */
+
+       case (FLASH_WORD_SIZE)AMD_ID_LV160B:
+               info->flash_id += FLASH_AM160B;
+               info->sector_count = 35;
+               info->size = 0x00200000;
+               break;                          /* => 2 MB              */
+#if 0  /* enable when device IDs are available */
+       case (FLASH_WORD_SIZE)AMD_ID_LV320T:
+               info->flash_id += FLASH_AM320T;
+               info->sector_count = 67;
+               info->size = 0x00400000;
+               break;                          /* => 4 MB              */
+
+       case (FLASH_WORD_SIZE)AMD_ID_LV320B:
+               info->flash_id += FLASH_AM320B;
+               info->sector_count = 67;
+               info->size = 0x00400000;
+               break;                          /* => 4 MB              */
+#endif
+       case (FLASH_WORD_SIZE)SST_ID_xF800A:
+               info->flash_id += FLASH_SST800A;
+               info->sector_count = 16;
+               info->size = 0x00100000;
+               break;                          /* => 1 MB              */
+       case (FLASH_WORD_SIZE)INTEL_ID_28F320C3T:
+               info->flash_id += FLASH_INTEL320T;
+               info->sector_count = 71;
+               info->size = 0x00400000;
+               break;                          /* => 4 MB              */
+
+
+       case (FLASH_WORD_SIZE)SST_ID_xF160A:
+               info->flash_id += FLASH_SST160A;
+               info->sector_count = 32;
+               info->size = 0x00200000;
+               break;                          /* => 2 MB              */
+
+       default:
+               info->flash_id = FLASH_UNKNOWN;
+               return (0);                     /* => no or unknown flash */
+
+       }
+
+       /* set up sector start address table */
+  if (((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) ||
+           (info->flash_id  == FLASH_AM040)){
+               for (i = 0; i < info->sector_count; i++)
+                       info->start[i] = base + (i * 0x00010000);
+  } else {
+               if (info->flash_id & FLASH_BTYPE) {
+               /* set sector offsets for bottom boot block type        */
+               info->start[0] = base + 0x00000000;
+               info->start[1] = base + 0x00004000;
+               info->start[2] = base + 0x00006000;
+               info->start[3] = base + 0x00008000;
+               for (i = 4; i < info->sector_count; i++) 
+                       info->start[i] = base + (i * 0x00010000) - 0x00030000;
+         } 
+         else {
+                       /* set sector offsets for top boot block type           */
+                       i = info->sector_count - 1;
+                       if(info->sector_count==71) {
+                               
+                               info->start[i--] = base + info->size - 0x00002000;
+                               info->start[i--] = base + info->size - 0x00004000;
+                               info->start[i--] = base + info->size - 0x00006000;
+                               info->start[i--] = base + info->size - 0x00008000;
+                               info->start[i--] = base + info->size - 0x0000A000;
+                               info->start[i--] = base + info->size - 0x0000C000;
+                               info->start[i--] = base + info->size - 0x0000E000;
+                               for (; i >= 0; i--) 
+                                       info->start[i] = base + i * 0x000010000;
+                       }
+                       else {
+                               info->start[i--] = base + info->size - 0x00004000;
+                               info->start[i--] = base + info->size - 0x00006000;
+                               info->start[i--] = base + info->size - 0x00008000;
+                               for (; i >= 0; i--) 
+                                       info->start[i] = base + i * 0x00010000;
+                       }
+               }
+       }
+
+       /* check for protected sectors */
+       for (i = 0; i < info->sector_count; i++) {
+               /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+               /* D0 = 1 if protected */
+               addr2 = (volatile FLASH_WORD_SIZE *)(info->start[i]);
+       if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL)
+       info->protect[i] = 0;
+      else
+        info->protect[i] = addr2[2] & 1;
+       }
+
+       /*
+        * Prevent writes to uninitialized FLASH.
+        */
+       if (info->flash_id != FLASH_UNKNOWN) {
+#if 0 /* test-only */
+#ifdef CONFIG_ADCIOP
+               addr2 = (volatile unsigned char *)info->start[0];
+                addr2[ADDR0] = 0xAA;
+                addr2[ADDR1] = 0x55;
+                addr2[ADDR0] = 0xF0;  /* reset bank */
+#else
+               addr2 = (FLASH_WORD_SIZE *)info->start[0];
+               *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
+#endif
+#else /* test-only */
+               addr2 = (FLASH_WORD_SIZE *)info->start[0];
+               *addr2 = (FLASH_WORD_SIZE)0x00F000F0;   /* reset bank */
+#endif /* test-only */
+       }
+       return (info->size);
+}
+
+int wait_for_DQ7(flash_info_t *info, int sect)
+{
+       ulong start, now, last;
+       volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
+
+       start = get_timer (0);
+    last  = start;
+    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
+        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+            printf ("Timeout\n");
+            return -1;
+        }
+        /* show that we're waiting */
+        if ((now - last) > 1000) {  /* every second */
+                               putc ('.');
+            last = now;
+        }
+    }
+       return 0;
+}
+
+int intel_wait_for_DQ7(flash_info_t *info, int sect)
+{
+       ulong start, now, last;
+       volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[sect]);
+
+               start = get_timer (0);
+    last  = start;
+    while ((addr[0] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) {
+        if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) {
+            printf ("Timeout\n");
+            return -1;
+        }
+        /* show that we're waiting */
+        if ((now - last) > 1000) {  /* every second */
+                               putc ('.');
+            last = now;
+        }
+    }
+    addr[0]=(FLASH_WORD_SIZE)0x00500050;
+       return 0;
+}
+
+/*-----------------------------------------------------------------------
+ */
+
+int    flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+       volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
+       volatile FLASH_WORD_SIZE *addr2;
+       int flag, prot, sect, l_sect;
+       int i;
+
+
+       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 1;
+       }
+
+       if (info->flash_id == FLASH_UNKNOWN) {
+               printf ("Can't erase unknown flash type - aborted\n");
+               return 1;
+       }
+
+       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();
+
+       /* Start erase on unprotected sectors */
+       for (sect = s_first; sect<=s_last; sect++) {
+               if (info->protect[sect] == 0) { /* not protected */
+                       addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);
+                       /*  printf("Erasing sector %p\n", addr2); */ /* CLH */
+           if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_SST) {
+                               addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+                               addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+                               addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
+                               addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+                               addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+                               addr2[0] = (FLASH_WORD_SIZE)0x00500050;  /* block erase */
+                               for (i=0; i<50; i++)
+                                       udelay(1000);  /* wait 1 ms */
+                   wait_for_DQ7(info, sect);
+                 } 
+                 else {
+                       if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
+                                       addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector */
+                                       addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
+                           intel_wait_for_DQ7(info, sect);
+                                       addr2[0] = (FLASH_WORD_SIZE)0x00200020;  /* sector erase */
+                                       addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* sector erase */
+                           intel_wait_for_DQ7(info, sect);
+                               }
+                               else {
+                                       addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+                                       addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+                                       addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
+                                       addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+                                       addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+                                       addr2[0] = (FLASH_WORD_SIZE)0x00300030;  /* sector erase */
+                           wait_for_DQ7(info, sect);
+                               }
+                }
+                l_sect = sect;
+                   /*
+                    * Wait for each sector to complete, it's more 
+                    * reliable.  According to AMD Spec, you must 
+                    * issue all erase commands within a specified
+                    * timeout.  This has been seen to fail, especially
+                    * if printf()s are included (for debug)!!
+                    */
+                /*   wait_for_DQ7(info, sect); */
+               }
+       }
+
+       /* re-enable interrupts if necessary */
+       if (flag)
+               enable_interrupts();
+
+       /* wait at least 80us - let's wait 1 ms */
+       udelay (1000);
+
+#if 0
+       /*
+        * We wait for the last triggered sector
+        */
+       if (l_sect < 0)
+               goto DONE;
+       wait_for_DQ7(info, l_sect);
+
+DONE:
+#endif
+       /* reset to read mode */
+       addr = (FLASH_WORD_SIZE *)info->start[0];
+       addr[0] = (FLASH_WORD_SIZE)0x00F000F0;  /* reset bank */
+
+       printf (" done\n");
+       return 0;
+}
+
+void unlock_intel_sectors(flash_info_t *info,ulong addr,ulong cnt)
+{
+       int i;
+       volatile FLASH_WORD_SIZE *addr2;
+       long c;
+       c= (long)cnt;
+       for(i=info->sector_count-1;i>0;i--)
+       {
+               if(addr>=info->start[i])
+                       break;
+       }
+       do {
+               addr2 = (FLASH_WORD_SIZE *)(info->start[i]);
+               addr2[0] = (FLASH_WORD_SIZE)0x00600060;  /* unlock sector setup */
+               addr2[0] = (FLASH_WORD_SIZE)0x00D000D0;  /* unlock sector */
+               intel_wait_for_DQ7(info, i);
+               i++;
+               c-=(info->start[i]-info->start[i-1]);
+       }while(c>0);
+               
+
+}
+
+
+/*-----------------------------------------------------------------------
+ * 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 wp, data;
+       int rc;
+       /*      int i, l, rc;  */
+       /* unsigned char sw; */
+       ulong *srcp;
+       
+
+       
+       if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
+               unlock_intel_sectors(info,addr,cnt);
+       }
+       wp=addr;
+       srcp=(ulong *)src;
+       while (cnt >= 4) {
+               data=*srcp++;
+               if ((rc = write_word(info, wp, data)) != 0) {
+                       return (rc);
+               }
+               wp  += 4;
+               if((wp % 0x10000)==0)
+                       printf("."); /* show Progress */
+               cnt -= 4;
+       }
+
+       if (cnt == 0) {
+               return (0);
+       }
+       return -1;
+#if 0  
+       wp = (addr & ~3);       /* get lower word aligned address */
+       /*
+        * handle unaligned start bytes
+        */
+       if ((l = addr - wp) != 0) {
+               data = 0;
+               for (i=0, cp=wp; i<l; ++i, ++cp) {
+                       data = (data << 8) | (*(uchar *)cp);
+               }
+               for (; i<4 && cnt>0; ++i) {
+                       data = (data << 8) | *src++;
+                       --cnt;
+                       ++cp;
+               }
+               for (; cnt==0 && i<4; ++i, ++cp) {
+                       data = (data << 8) | (*(uchar *)cp);
+               }
+
+               if ((rc = write_word(info, wp, data)) != 0) {
+                       return (rc);
+               }
+               wp += 4;
+       }
+
+       /*
+        * handle word aligned part
+        */
+       while (cnt >= 4) {
+               data = 0;
+               for (i=0; i<4; ++i) {
+                       data = (data << 8) | *src++;
+               }
+               if ((rc = write_word(info, wp, data)) != 0) {
+                       return (rc);
+               }
+               wp  += 4;
+               if((wp % 0x10000)==0)
+                       printf("."); /* show Progress */
+               cnt -= 4;
+       }
+
+       if (cnt == 0) {
+               return (0);
+       }
+
+       /*
+        * handle unaligned tail bytes
+        */
+       data = 0;
+       for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) {
+               data = (data << 8) | *src++;
+               --cnt;
+       }
+       for (; i<4; ++i, ++cp) {
+               data = (data << 8) | (*(uchar *)cp);
+       }
+       rc=write_word(info, wp, data);
+       return rc;
+
+#endif
+}      
+
+/*-----------------------------------------------------------------------
+ * Write a word to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static FLASH_WORD_SIZE *read_val = (FLASH_WORD_SIZE *)0x200000;
+
+static int write_word (flash_info_t *info, ulong dest, ulong data)
+{
+       volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)(info->start[0]);
+       volatile FLASH_WORD_SIZE *dest2 = (FLASH_WORD_SIZE *)dest;
+       volatile FLASH_WORD_SIZE *data2 = (FLASH_WORD_SIZE *)&data;
+       ulong start;
+       int flag;
+       int i;
+       
+       /* Check if Flash is (sufficiently) erased */
+       if ((*((volatile FLASH_WORD_SIZE *)dest) &
+               (FLASH_WORD_SIZE)data) != (FLASH_WORD_SIZE)data) {
+               return (2);
+       }
+       /* Disable interrupts which might cause a timeout here */
+       flag = disable_interrupts();
+       for (i=0; i<4/sizeof(FLASH_WORD_SIZE); i++)
+       {
+               if((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){
+                       /* intel style writting */
+                       dest2[i] = (FLASH_WORD_SIZE)0x00500050;
+                       dest2[i] = (FLASH_WORD_SIZE)0x00400040;
+               *read_val++ = data2[i];
+                       dest2[i] = data2[i];
+               if (flag)
+                       enable_interrupts();
+               /* data polling for D7 */
+               start = get_timer (0);
+                       udelay(10);
+               while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) != (FLASH_WORD_SIZE)0x00800080) 
+               {
+                       if (get_timer(start) > CFG_FLASH_WRITE_TOUT) 
+                               return (1);
+                       }
+                       dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
+                       udelay(10);
+                       dest2[i] = (FLASH_WORD_SIZE)0x00FF00FF; /* return to read mode */
+                       if(dest2[i]!=data2[i])
+                               printf("Error at %p 0x%04X != 0x%04X\n",&dest2[i],dest2[i],data2[i]);
+                       
+               }
+               else {
+                       addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+               addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+               addr2[ADDR0] = (FLASH_WORD_SIZE)0x00A000A0;    
+                       dest2[i] = data2[i];
+            /* re-enable interrupts if necessary */
+               if (flag)
+                       enable_interrupts();
+                   /* data polling for D7 */
+               start = get_timer (0);
+               while ((dest2[i] & (FLASH_WORD_SIZE)0x00800080) !=
+                               (data2[i] & (FLASH_WORD_SIZE)0x00800080)) {
+                       if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
+                               return (1);
+                               }
+               }
+               }   
+       }
+       return (0);
+}
+
+/*-----------------------------------------------------------------------
+ */
diff --git a/board/mpl/common/isa.c b/board/mpl/common/isa.c
new file mode 100644 (file)
index 0000000..fff8f88
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ *
+ * TODO: clean-up
+ */
+#include <ppcboot.h>
+#include <asm/processor.h>
+#include <devices.h>
+#include "isa.h"
+#include "pci.h"
+#include "kbd.h"
+#include "video.h"
+
+extern int drv_isa_kbd_init (void);
+
+#undef ISA_DEBUG
+
+#ifdef ISA_DEBUG
+#define        PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#ifndef        TRUE
+#define TRUE            1
+#endif
+#ifndef FALSE
+#define FALSE           0
+#endif
+
+
+
+/* fdc (logical device 0) */
+const SIO_LOGDEV_TABLE sio_fdc[] = {
+       {0x60, 3},                      /* set IO to FDPort (3F0) */
+       {0x61, 0xF0},           /* set IO to FDPort (3F0) */
+       {0x70, 06},                     /* set IRQ 6 for FDPort */
+       {0x74, 02},                     /* set DMA 2 for FDPort */
+       {0xF0, 0x05},           /* set to PS2 type */
+       {0xF1, 0x00},     /* default value */
+       {0x30, 1},                      /* and activate the device */
+       {0xFF, 0}                               /* end of device table */
+};
+/* paralell port (logical device 3) */
+const SIO_LOGDEV_TABLE sio_pport[] = {
+       {0x60, 3},                      /* set IO to PPort (378) */
+       {0x61, 0x78},           /* set IO to PPort (378) */
+       {0x70, 07},                     /* set IRQ 7 for PPort */
+       {0xF1, 00},                     /* set PPort to normal */
+       {0x30, 1},                      /* and activate the device */
+       {0xFF, 0}                               /* end of device table */
+};
+/* paralell port (logical device 3) Floppy assigned to lpt */
+const SIO_LOGDEV_TABLE sio_pport_fdc[] = {
+       {0x60, 3},                      /* set IO to PPort (378) */
+       {0x61, 0x78},           /* set IO to PPort (378) */
+       {0x70, 07},                     /* set IRQ 7 for PPort */
+       {0xF1, 02},                     /* set PPort to Floppy */
+       {0x30, 1},                      /* and activate the device */
+       {0xFF, 0}                               /* end of device table */
+};
+/* uart 1 (logical device 4) */
+const SIO_LOGDEV_TABLE sio_com1[] = {
+       {0x60, 3},                      /* set IO to COM1 (3F8) */
+       {0x61, 0xF8},           /* set IO to COM1 (3F8) */
+       {0x70, 04},                     /* set IRQ 4 for COM1 */
+       {0x30, 1},                      /* and activate the device */
+       {0xFF, 0}                               /* end of device table */
+};
+/* uart 2 (logical device 5) */
+const SIO_LOGDEV_TABLE sio_com2[] = {
+       {0x60, 2},                      /* set IO to COM2 (2F8) */
+       {0x61, 0xF8},           /* set IO to COM2 (2F8) */
+       {0x70, 03},                     /* set IRQ 3 for COM2 */
+       {0x30, 1},                      /* and activate the device */
+       {0xFF, 0}                               /* end of device table */
+};
+
+/* keyboard controller (logical device 7) */
+const SIO_LOGDEV_TABLE sio_keyboard[] = {
+       {0x70, 1},                      /* set IRQ 1 for keyboard */
+       {0x72, 12},                     /* set IRQ 12 for mouse */
+       {0xF0, 0},                      /* disable Port92 (this is a PowerPC!!) */
+       {0x30, 1},                      /* and activate the device */
+       {0xFF, 0}                               /* end of device table */
+};
+
+
+/*******************************************************************************
+* Config SuperIO FDC37C672
+********************************************************************************/
+unsigned char open_cfg_super_IO(int address)
+{
+       out8(CFG_ISA_IO_BASE_ADDRESS | address,0x55); /* open config */
+       out8(CFG_ISA_IO_BASE_ADDRESS | address,0x20); /* set address to DEV ID */
+       if(in8(CFG_ISA_IO_BASE_ADDRESS | address | 0x1)==0x40) /* ok Device ID is correct */
+               return TRUE;
+       else 
+               return FALSE;
+}
+
+void close_cfg_super_IO(int address)
+{
+       out8(CFG_ISA_IO_BASE_ADDRESS | address,0xAA); /* close config */
+}
+
+
+unsigned char read_cfg_super_IO(int address, unsigned char function, unsigned char regaddr)
+{
+       /* assuming config reg is open */
+       out8(CFG_ISA_IO_BASE_ADDRESS | address,0x7); /* points to the function reg */
+       out8(CFG_ISA_IO_BASE_ADDRESS | address | 1,function); /* set the function no */
+       out8(CFG_ISA_IO_BASE_ADDRESS | address,regaddr); /* sets the address in the function */
+       return in8(CFG_ISA_IO_BASE_ADDRESS | address | 1);      
+}
+
+void write_cfg_super_IO(int address, unsigned char function, unsigned char regaddr, unsigned char data)
+{
+       /* assuming config reg is open */
+       out8(CFG_ISA_IO_BASE_ADDRESS | address,0x7); /* points to the function reg */
+       out8(CFG_ISA_IO_BASE_ADDRESS | address | 1,function); /* set the function no */
+       out8(CFG_ISA_IO_BASE_ADDRESS | address,regaddr); /* sets the address in the function */
+       out8(CFG_ISA_IO_BASE_ADDRESS | address | 1,data); /* writes the data */
+}
+
+void isa_write_table(SIO_LOGDEV_TABLE *ldt,unsigned char ldev)
+{
+       while (ldt->index != 0xFF) {
+               write_cfg_super_IO(SIO_CFG_PORT, ldev, ldt->index, ldt->val);
+               ldt++;  
+       } /* endwhile */
+}
+
+void isa_sio_loadtable(void)
+{
+       unsigned char *s = getenv("floppy");
+       /* setup Floppy device 0*/
+       isa_write_table((SIO_LOGDEV_TABLE *)&sio_fdc,0);
+       /* setup parallel port device 3 */
+       if(s && !strncmp(s, "lpt", 3)) {
+               printf("SIO:   Floppy assigned to LPT\n"); 
+               /* floppy is assigned to the LPT */
+               isa_write_table((SIO_LOGDEV_TABLE *)&sio_pport_fdc,3);
+       }
+       else {
+               /*printf("Floppy assigned to internal port\n");*/ 
+               isa_write_table((SIO_LOGDEV_TABLE *)&sio_pport,3);
+       }
+       /* setup Com1 port device 4 */
+       isa_write_table((SIO_LOGDEV_TABLE *)&sio_com1,4);
+       /* setup Com2 port device 5 */
+       isa_write_table((SIO_LOGDEV_TABLE *)&sio_com2,5);
+       /* setup keyboards device 7 */
+       isa_write_table((SIO_LOGDEV_TABLE *)&sio_keyboard,7);
+}
+
+
+void isa_sio_setup(void)
+{
+       if(open_cfg_super_IO(SIO_CFG_PORT)==TRUE)
+       {
+               isa_sio_loadtable();
+               close_cfg_super_IO(0x3F0);      
+       }
+}
+
+
+
+/******************************************************************************
+ * IRQ Controller
+ * we use the Vector mode
+ */
+
+struct isa_irq_action {
+        interrupt_handler_t *handler;
+        void *arg;
+        int count;
+};
+
+static struct isa_irq_action isa_irqs[16];
+
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define cached_imr1    (unsigned char)cached_irq_mask
+#define cached_imr2    (unsigned char)(cached_irq_mask>>8)
+#define IMR_1          CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_OCW1
+#define IMR_2          CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_OCW1
+#define ICW1_1 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_ICW1
+#define ICW1_2 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_ICW1
+#define ICW2_1 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT1_ICW2
+#define ICW2_2 CFG_ISA_IO_BASE_ADDRESS + PIIX4_ISA_INT2_ICW2
+#define ICW3_1 ICW2_1
+#define ICW3_2 ICW2_2
+#define ICW4_1 ICW2_1
+#define ICW4_2 ICW2_2
+#define ISR_1          ICW1_1
+#define ISR_2          ICW1_2
+
+
+void disable_8259A_irq(unsigned int irq)
+{
+       unsigned int mask = 1 << irq;
+
+       cached_irq_mask |= mask;
+       if (irq & 8)
+               out8(IMR_2,cached_imr2);
+       else
+               out8(IMR_1,cached_imr1);
+}
+
+void enable_8259A_irq(unsigned int irq)
+{
+       unsigned int mask = ~(1 << irq);
+
+       cached_irq_mask &= mask;
+       if (irq & 8)
+               out8(IMR_2,cached_imr2);
+       else
+               out8(IMR_1,cached_imr1);
+}
+/*
+int i8259A_irq_pending(unsigned int irq)
+{
+       unsigned int mask = 1<<irq;
+       int ret;
+
+       if (irq < 8)
+               ret = inb(0x20) & mask;
+       else
+               ret = inb(0xA0) & (mask >> 8);
+       spin_unlock_irqrestore(&i8259A_lock, flags);
+
+       return ret;
+}
+*/
+
+/*
+ * This function assumes to be called rarely. Switching between
+ * 8259A registers is slow.
+ */
+int i8259A_irq_real(unsigned int irq)
+{
+       int value;
+       int irqmask = 1<<irq;
+
+       if (irq < 8) {
+               out8(ISR_1,0x0B);               /* ISR register */
+               value = in8(ISR_1) & irqmask;
+               out8(ISR_1,0x0A);               /* back to the IRR register */
+               return value;
+       }
+       out8(ISR_2,0x0B);               /* ISR register */
+       value = in8(ISR_2) & (irqmask >> 8);
+       out8(ISR_2,0x0A);               /* back to the IRR register */
+       return value;
+}
+
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+void mask_and_ack_8259A(unsigned int irq)
+{
+       unsigned int irqmask = 1 << irq;
+       unsigned int temp_irqmask = cached_irq_mask;
+       /*
+        * Lightweight spurious IRQ detection. We do not want
+        * to overdo spurious IRQ handling - it's usually a sign
+        * of hardware problems, so we only do the checks we can
+        * do without slowing down good hardware unnecesserily.
+        *
+        * Note that IRQ7 and IRQ15 (the two spurious IRQs
+        * usually resulting from the 8259A-1|2 PICs) occur
+        * even if the IRQ is masked in the 8259A. Thus we
+        * can check spurious 8259A IRQs without doing the
+        * quite slow i8259A_irq_real() call for every IRQ.
+        * This does not cover 100% of spurious interrupts,
+        * but should be enough to warn the user that there
+        * is something bad going on ...
+        */
+       if (temp_irqmask & irqmask)
+               goto spurious_8259A_irq;
+       temp_irqmask |= irqmask;
+
+handle_real_irq:
+       if (irq & 8) {
+               in8(IMR_2);             /* DUMMY - (do we need this?) */
+               out8(IMR_2,(unsigned char)(temp_irqmask>>8));
+               out8(ISR_2,0x60+(irq&7));/* 'Specific EOI' to slave */
+               out8(ISR_1,0x62);       /* 'Specific EOI' to master-IRQ2 */
+               out8(IMR_2,cached_imr2); /* turn it on again */
+       } else {
+               in8(IMR_1);             /* DUMMY - (do we need this?) */
+               out8(IMR_1,(unsigned char)temp_irqmask);
+               out8(ISR_1,0x60+irq);   /* 'Specific EOI' to master */
+               out8(IMR_1,cached_imr1); /* turn it on again */
+       }
+       
+       return;
+
+spurious_8259A_irq:
+       /*
+        * this is the slow path - should happen rarely.
+        */
+       if (i8259A_irq_real(irq))
+               /*
+                * oops, the IRQ _is_ in service according to the
+                * 8259A - not spurious, go handle it.
+                */
+               goto handle_real_irq;
+
+       {
+               static int spurious_irq_mask;
+               /*
+                * At this point we can be sure the IRQ is spurious,
+                * lets ACK and report it. [once per IRQ]
+                */
+               if (!(spurious_irq_mask & irqmask)) {
+                       PRINTF("spurious 8259A interrupt: IRQ%d.\n", irq);
+                       spurious_irq_mask |= irqmask;
+               }
+               /* irq_err_count++; */
+               /*
+                * Theoretically we do not have to handle this IRQ,
+                * but in Linux this does not cause problems and is
+                * simpler for us.
+                */
+               goto handle_real_irq;
+       }
+}
+
+void init_8259A(void)
+{
+       out8(IMR_1,0xff);       /* mask all of 8259A-1 */
+       out8(IMR_2,0xff);       /* mask all of 8259A-2 */
+
+       out8(ICW1_1,0x11);      /* ICW1: select 8259A-1 init */
+       out8(ICW2_1,0x20 + 0);  /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
+       out8(ICW3_1,0x04);      /* 8259A-1 (the master) has a slave on IR2 */
+       out8(ICW4_1,0x01);      /* master expects normal EOI */
+       out8(ICW1_2,0x11);      /* ICW2: select 8259A-2 init */
+       out8(ICW2_2,0x20 + 8);  /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
+       out8(ICW3_2,0x02);      /* 8259A-2 is a slave on master's IR2 */
+       out8(ICW4_2,0x01);      /* (slave's support for AEOI in flat mode
+                                   is to be investigated) */
+       udelay(10000);          /* wait for 8259A to initialize */
+       out8(IMR_1,cached_imr1);        /* restore master IRQ mask */
+       udelay(10000);          /* wait for 8259A to initialize */
+       out8(IMR_2,cached_imr2);        /* restore slave IRQ mask */
+}
+
+
+#define PCI_INT_ACK_ADDR 0xEED00000
+
+int handle_isa_int(void)
+{
+       unsigned long irqack;
+       unsigned char isr1,isr2,irq;
+       /* first we acknokledge the int via the PCI bus */
+       irqack=in32(PCI_INT_ACK_ADDR);
+       /* now we get the ISRs */
+       isr2=in8(ISR_2);
+       isr1=in8(ISR_1);
+       irq=(unsigned char)irqack;
+       if((irq==7)&&((isr1&0x80)==0)) {
+               PRINTF("IRQ7 detected but not in ISR\n");
+       }
+       else {
+               /* we should handle cascaded interrupts here also */
+               /* printf("ISA Irq %d\n",irq); */
+               isa_irqs[irq].count++;
+       if (isa_irqs[irq].handler != NULL)
+               (*isa_irqs[irq].handler)(isa_irqs[irq].arg);      /* call isr */
+       else
+       {
+       PRINTF ("bogus interrupt vector 0x%x\n", irq);
+       }
+       }
+       /* issue EOI instruction to clear the IRQ */
+       mask_and_ack_8259A(irq);
+       return 0;
+}
+
+
+
+/******************************************************************
+ * Install and free an ISA interrupt handler.
+ */
+
+void isa_irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
+{
+  if (isa_irqs[vec].handler != NULL) {
+   printf ("ISA Interrupt vector %d: handler 0x%x replacing 0x%x\n",
+           vec, (uint)handler, (uint)isa_irqs[vec].handler);
+  }
+  isa_irqs[vec].handler = handler;
+  isa_irqs[vec].arg     = arg;
+  enable_8259A_irq(vec);
+       PRINTF ("Install ISA IRQ %d ==> %p, @ %p mask=%04x\n", vec, handler, &isa_irqs[vec].handler,cached_irq_mask);
+
+}
+
+void isa_irq_free_handler(int vec)
+{
+       disable_8259A_irq(vec);
+  isa_irqs[vec].handler = NULL;
+  isa_irqs[vec].arg     = NULL;
+       printf ("Free ISA IRQ %d mask=%04x\n", vec, cached_irq_mask);
+
+}
+
+/****************************************************************************/
+void isa_init_irq_contr(void)
+{
+       int i;
+       /* disable all Interrupts */
+       /* first write icws controller 1 */
+       for(i=0;i<16;i++)
+       {
+               isa_irqs[i].handler=NULL;
+               isa_irqs[i].arg=NULL;
+               isa_irqs[i].count=0;
+       }
+       init_8259A();
+       out8(IMR_2,0xFF);                               
+}
+
+
+/******************************************************************
+ * Init the ISA bus and devices.
+ */
+int isa_init(void)
+{
+       isa_sio_setup();
+       drv_isa_kbd_init();
+       return 0;
+}
+
diff --git a/board/mpl/common/isa.h b/board/mpl/common/isa.h
new file mode 100644 (file)
index 0000000..1b775fb
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+#ifndef _PIP405_ISA_H_
+#define _PIP405_ISA_H_
+/* Super IO */
+#define SIO_CFG_PORT   0x3F0   /* Config Port Address */
+
+
+
+/* table fore SIO initialization */
+typedef struct {
+       const uchar index;
+       const uchar val;
+} SIO_LOGDEV_TABLE;
+
+typedef struct {
+       const uchar ldev;
+       const SIO_LOGDEV_TABLE *ldev_table;
+} SIO_TABLE;
+
+
+
+
+unsigned char open_cfg_super_IO(int address);
+unsigned char read_cfg_super_IO(int address, unsigned char function, unsigned char regaddr);
+void write_cfg_super_IO(int address, unsigned char function, unsigned char regaddr, unsigned char data);
+void close_cfg_super_IO(int address);
+void isa_sio_setup(void);
+void isa_sio_setup(void);
+void isa_irq_install_handler(int vec, interrupt_handler_t *handler, void *arg);
+void isa_irq_free_handler(int vec);
+int handle_isa_int(void); 
+
+
+#endif
diff --git a/board/mpl/common/kbd.c b/board/mpl/common/kbd.c
new file mode 100644 (file)
index 0000000..d5949fa
--- /dev/null
@@ -0,0 +1,655 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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
+ *
+ *
+ * Source partly derived from:
+ * linux/drivers/char/pc_keyb.c
+ *
+ *
+ */
+#include <ppcboot.h>
+#include <asm/processor.h>
+#include <devices.h>
+#include "isa.h"
+#include "kbd.h"
+
+
+unsigned char kbd_read_status(void);
+unsigned char kbd_read_input(void);
+void kbd_send_data(unsigned char data);
+void disable_8259A_irq(unsigned int irq);
+void enable_8259A_irq(unsigned int irq);
+
+/* used only by send_data - set by keyboard_interrupt */
+
+
+#undef KBG_DEBUG
+
+#ifdef KBG_DEBUG
+#define        PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#define KBD_STAT_KOBF          0x01
+#define KBD_STAT_IBF           0x02
+#define KBD_STAT_SYS           0x04
+#define KBD_STAT_CD                    0x08
+#define KBD_STAT_LOCK          0x10
+#define KBD_STAT_MOBF          0x20
+#define KBD_STAT_TI_OUT        0x40
+#define KBD_STAT_PARERR        0x80
+
+#define KBD_INIT_TIMEOUT 1000          /* Timeout in ms for initializing the keyboard */
+#define KBC_TIMEOUT 250                        /* Timeout in ms for sending to keyboard controller */
+#define KBD_TIMEOUT 2000               /* Timeout in ms for keyboard command acknowledge */
+/*
+ *     Keyboard Controller Commands
+ */
+
+#define KBD_CCMD_READ_MODE                     0x20    /* Read mode bits */
+#define KBD_CCMD_WRITE_MODE                    0x60    /* Write mode bits */
+#define KBD_CCMD_GET_VERSION           0xA1    /* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE 0xA7    /* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE          0xA8    /* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE                    0xA9    /* Mouse interface test */
+#define KBD_CCMD_SELF_TEST                     0xAA    /* Controller self test */
+#define KBD_CCMD_KBD_TEST                              0xAB    /* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE           0xAD    /* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE                    0xAE    /* Keyboard interface enable */
+#define KBD_CCMD_WRITE_AUX_OBUF        0xD3    /* Write to output buffer as if
+                                          initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE           0xD4    /* Write the following byte to the mouse */
+
+/*
+ *     Keyboard Commands
+ */
+
+#define KBD_CMD_SET_LEDS                               0xED    /* Set keyboard leds */
+#define KBD_CMD_SET_RATE                               0xF3    /* Set typematic rate */
+#define KBD_CMD_ENABLE                                 0xF4    /* Enable scanning */
+#define KBD_CMD_DISABLE                                        0xF5    /* Disable scanning */
+#define KBD_CMD_RESET                                          0xFF    /* Reset */
+
+/*
+ *     Keyboard Replies
+ */
+
+#define KBD_REPLY_POR                                          0xAA    /* Power on reset */
+#define KBD_REPLY_ACK                                          0xFA    /* Command ACK */
+#define KBD_REPLY_RESEND                               0xFE    /* Command NACK, send the cmd again */
+
+/*
+ *     Status Register Bits
+ */
+
+#define KBD_STAT_OBF                                           0x01    /* Keyboard output buffer full */
+#define KBD_STAT_IBF                                           0x02    /* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST                              0x04    /* Self test successful */
+#define KBD_STAT_CMD                                           0x08    /* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED                              0x10    /* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF                     0x20    /* Mouse output buffer full */
+#define KBD_STAT_GTO                                           0x40    /* General receive/xmit timeout */
+#define KBD_STAT_PERR                                  0x80    /* Parity error */
+
+#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
+
+/*
+ *     Controller Mode Register Bits
+ */
+
+#define KBD_MODE_KBD_INT                               0x01    /* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT                     0x02    /* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS                                           0x04    /* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK                    0x08    /* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD           0x10    /* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE 0x20    /* Disable mouse interface */
+#define KBD_MODE_KCC                                           0x40    /* Scan code conversion to PC format */
+#define KBD_MODE_RFU                                           0x80
+
+
+#define KDB_DATA_PORT                  0x60
+#define KDB_COMMAND_PORT       0x64
+
+#define        LED_SCR         0x01    /* scroll lock led */
+#define        LED_CAP         0x04    /* caps lock led */
+#define        LED_NUM         0x02    /* num lock led */
+
+#define        KBD_BUFFER_LEN 0x20  /* size of the keyboardbuffer */
+
+
+
+
+static volatile char kbd_buffer[KBD_BUFFER_LEN];
+static volatile int in_pointer = 0;
+static volatile int out_pointer = 0;
+
+
+static unsigned char num_lock = 0;
+static unsigned char caps_lock = 0;
+static unsigned char scroll_lock = 0;
+static unsigned char shift = 0;
+static unsigned char ctrl = 0;
+static unsigned char alt = 0;
+static unsigned char e0 = 0;
+static unsigned char leds = 0;
+
+#define DEVNAME "kbd"
+
+/* Simple translation table for the keys */
+
+static unsigned char kbd_plain_xlate[] = {
+       0xff,0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b','\t',        /* 0x00 - 0x0f */
+        'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',0xff, 'a', 's',        /* 0x10 - 0x1f */
+        'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',0xff,'\\', 'z', 'x', 'c', 'v',        /* 0x20 - 0x2f */
+        'b', 'n', 'm', ',', '.', '/',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff,        /* 0x30 - 0x3f */
+       0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1',        /* 0x40 - 0x4f */
+        '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  /* 0x50 - 0x5F */
+       '\r',0xff,0xff
+       };
+                 
+static unsigned char kbd_shift_xlate[] = {
+       0xff,0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b','\t',        /* 0x00 - 0x0f */
+        'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',0xff, 'A', 'S',        /* 0x10 - 0x1f */
+        'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',0xff, '|', 'Z', 'X', 'C', 'V',        /* 0x20 - 0x2f */
+        'B', 'N', 'M', '<', '>', '?',0xff,0xff,0xff, ' ',0xff,0xff,0xff,0xff,0xff,0xff,        /* 0x30 - 0x3f */
+       0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1',        /* 0x40 - 0x4f */
+        '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  /* 0x50 - 0x5F */
+       '\r',0xff,0xff
+       };
+
+static unsigned char kbd_ctrl_xlate[] = {
+       0xff,0x1b, '1',0x00, '3', '4', '5',0x1E, '7', '8', '9', '0',0x1F, '=','\b','\t',        /* 0x00 - 0x0f */
+       0x11,0x17,0x05,0x12,0x14,0x18,0x15,0x09,0x0f,0x10,0x1b,0x1d,'\n',0xff,0x01,0x13,        /* 0x10 - 0x1f */
+       0x04,0x06,0x08,0x09,0x0a,0x0b,0x0c, ';','\'', '~',0x00,0x1c,0x1a,0x18,0x03,0x16,        /* 0x20 - 0x2f */
+       0x02,0x0e,0x0d, '<', '>', '?',0xff,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff,        /* 0x30 - 0x3f */
+       0xff,0xff,0xff,0xff,0xff,0xff,0xff, '7', '8', '9', '-', '4', '5', '6', '+', '1',        /* 0x40 - 0x4f */
+        '2', '3', '0', '.',0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,  /* 0x50 - 0x5F */
+       '\r',0xff,0xff
+       };
+
+/******************************************************************
+ * Init 
+ ******************************************************************/
+int isa_kbd_init(void)
+{
+       char* result;
+       result=kbd_initialize();
+       if(result==NULL) {
+               PRINTF("AT Keyboard initialized\n");
+               irq_install_handler(25, (interrupt_handler_t *)handle_isa_int, NULL);
+               isa_irq_install_handler(KBD_INTERRUPT, (interrupt_handler_t *)kbd_interrupt, NULL);
+               return (1);
+       }
+       else {
+               printf("%s\n",result);
+               return (-1);
+       }
+}
+
+#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
+extern int overwrite_console (void);
+#else
+int overwrite_console (void)
+{
+       return (0);
+}
+#endif
+
+int drv_isa_kbd_init (void)
+{
+       int error;
+       device_t kbddev ;
+       char *stdinname  = getenv ("stdin");
+
+       if(isa_kbd_init()==-1)
+               return -1;
+       memset (&kbddev, 0, sizeof(kbddev));
+       strcpy(kbddev.name, DEVNAME);
+       kbddev.flags =  DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+       kbddev.putc = NULL ;
+       kbddev.puts = NULL ;
+       kbddev.getc = kbd_getc ;
+       kbddev.tstc = kbd_testc ;
+
+       error = device_register (&kbddev);
+       if(error==0) {
+               /* check if this is the standard input device */
+               if(strcmp(stdinname,DEVNAME)==0) {
+                       /* reassign the console */
+                       if(overwrite_console()) {
+                               return 1;
+                       }
+                       error=console_assign(stdin,DEVNAME);
+                       if(error==0)
+                               return 1;
+                       else 
+                               return error;
+               }
+               return 1;
+       }
+       return error;
+}
+
+/******************************************************************
+ * Queue handling 
+ ******************************************************************/
+/* puts character in the queue and sets up the in and out pointer */
+void kbd_put_queue(char data)
+{
+       if((in_pointer+1)==KBD_BUFFER_LEN) {
+               if(out_pointer==0) {
+                       return; /* buffer full */
+               } else{
+                       in_pointer=0;
+               }
+       } else {
+               if((in_pointer+1)==out_pointer)
+                       return; /* buffer full */
+               in_pointer++;
+       }
+       kbd_buffer[in_pointer]=data;
+       return;
+}
+
+/* test if a character is in the queue */
+int kbd_testc(void)
+{
+       if(in_pointer==out_pointer)
+               return(0); /* no data */
+       else
+               return(1);      
+}
+/* gets the character from the queue */
+int kbd_getc(void)
+{
+       char c;
+       while(in_pointer==out_pointer);
+       if((out_pointer+1)==KBD_BUFFER_LEN) 
+               out_pointer=0;
+       else
+               out_pointer++;
+       c=kbd_buffer[out_pointer];
+       return (int)c;
+       
+}
+
+
+/* set LEDs */
+
+void kbd_set_leds(void)
+{
+       if(caps_lock==0)
+               leds&=~LED_CAP; /* switch caps_lock off */
+       else
+               leds|=LED_CAP; /* switch on LED */
+       if(num_lock==0)
+               leds&=~LED_NUM; /* switch LED off */
+       else
+               leds|=LED_NUM;  /* switch on LED */
+       if(scroll_lock==0)
+               leds&=~LED_SCR; /* switch LED off */
+       else
+               leds|=LED_SCR; /* switch on LED */
+       kbd_send_data(KBD_CMD_SET_LEDS);
+       kbd_send_data(leds);
+}
+       
+
+void handle_keyboard_event(unsigned char scancode)
+{
+       unsigned char keycode;
+
+       /*  Convert scancode to keycode */
+       PRINTF("scancode %x\n",scancode);
+       if(scancode==0xe0) {
+               e0=1; /* special charakters */
+               return;
+       }
+       if(e0==1) {
+               e0=0; /* delete flag */
+               if(!(   ((scancode&0x7F)==0x38)|| /* the right ctrl key */
+                                       ((scancode&0x7F)==0x1D)|| /* the right alt key */
+                                       ((scancode&0x7F)==0x35)||       /* the right '/' key */
+                                       ((scancode&0x7F)==0x1C) ))  /* the right enter key */
+                       /* we swallow unknown e0 codes */
+                       return;
+       }
+       /* special cntrl keys */
+       switch(scancode)
+       {
+               case 0x2A: 
+               case 0x36: /* shift pressed */
+                       shift=1;
+                       return; /* do nothing else */
+               case 0xAA: 
+               case 0xB6: /* shift released */
+                       shift=0;
+                       return; /* do nothing else */
+               case 0x38: /* alt pressed */
+                       alt=1;
+                       return; /* do nothing else */
+               case 0xB8: /* alt released */
+                       alt=0;
+                       return; /* do nothing else */
+               case 0x1d: /* ctrl pressed */
+                       ctrl=1;
+                       return; /* do nothing else */
+               case 0x9d: /* ctrl released */
+                       ctrl=0;
+                       return; /* do nothing else */
+               case 0x46: /* scrollock pressed */
+                       scroll_lock=~scroll_lock;
+                       kbd_set_leds();
+                       return; /* do nothing else */
+               case 0x3A: /* capslock pressed */
+                       caps_lock=~caps_lock;
+                       kbd_set_leds();
+                       return; 
+               case 0x45: /* numlock pressed */
+                       num_lock=~num_lock;
+                       kbd_set_leds();
+                       return; 
+               case 0xC6: /* scroll lock released */
+               case 0xC5: /* num lock released */
+               case 0xBA: /* caps lock released */
+                       return; /* just swallow */ 
+       }
+       if((scancode&0x80)==0x80) /* key released */
+               return;
+       /* now, decide which table we need */
+       if(scancode > (sizeof(kbd_plain_xlate)/sizeof(kbd_plain_xlate[0]))) { /* scancode not in list */
+               PRINTF("unkown scancode %X\n",scancode);
+               return; /* swallow it */
+       }
+       /* setup plain code first */
+       keycode=kbd_plain_xlate[scancode];
+       if(caps_lock==1) { /* caps_lock is pressed, overwrite plain code */
+               if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
+                       PRINTF("unkown caps-locked scancode %X\n",scancode);
+                       return; /* swallow it */
+               }
+               keycode=kbd_shift_xlate[scancode];
+               if(keycode<'A') { /* we only want the alphas capital */
+                       keycode=kbd_plain_xlate[scancode];
+               }
+       }
+       if(shift==1) { /* shift overwrites caps_lock */
+               if(scancode > (sizeof(kbd_shift_xlate)/sizeof(kbd_shift_xlate[0]))) { /* scancode not in list */
+                       PRINTF("unkown shifted scancode %X\n",scancode);
+                       return; /* swallow it */
+               }
+               keycode=kbd_shift_xlate[scancode];
+       }
+       if(ctrl==1) { /* ctrl overwrites caps_lock and shift */
+               if(scancode > (sizeof(kbd_ctrl_xlate)/sizeof(kbd_ctrl_xlate[0]))) { /* scancode not in list */
+                       PRINTF("unkown ctrl scancode %X\n",scancode);
+                       return; /* swallow it */
+               }
+               keycode=kbd_ctrl_xlate[scancode];
+       }
+       /* check if valid keycode */
+       if(keycode==0xff) {
+               PRINTF("unkown scancode %X\n",scancode);
+               return; /* swallow unknown codes */
+       }
+       
+       kbd_put_queue(keycode);
+       PRINTF("%x\n",keycode);
+}
+
+/*
+ * This reads the keyboard status port, and does the
+ * appropriate action.
+ *
+ */
+unsigned char handle_kbd_event(void)
+{
+       unsigned char status = kbd_read_status();
+       unsigned int work = 10000;
+
+       while ((--work > 0) && (status & KBD_STAT_OBF)) {
+               unsigned char scancode;
+
+               scancode = kbd_read_input();
+
+               /* Error bytes must be ignored to make the
+                  Synaptics touchpads compaq use work */
+               /* Ignore error bytes */
+               if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR)))
+               {
+                       if (status & KBD_STAT_MOUSE_OBF)
+                               ; /* not supported: handle_mouse_event(scancode); */
+                       else
+                               handle_keyboard_event(scancode);
+               }
+               status = kbd_read_status();
+       }
+       if (!work)
+               PRINTF("pc_keyb: controller jammed (0x%02X).\n", status);
+       return status;
+}
+
+
+
+/******************************************************************************
+ * Lowlevel Part of keyboard section
+ */  
+unsigned char kbd_read_status(void)
+{
+       return(in8(CFG_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT));
+} 
+  
+unsigned char kbd_read_input(void)
+{
+       return(in8(CFG_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT));
+} 
+
+void kbd_write_command(unsigned char cmd)
+{
+       out8(CFG_ISA_IO_BASE_ADDRESS + KDB_COMMAND_PORT,cmd);
+} 
+  
+void kbd_write_output(unsigned char data)
+{
+       out8(CFG_ISA_IO_BASE_ADDRESS + KDB_DATA_PORT, data);
+} 
+int kbd_read_data(void)
+{
+       int val;
+       unsigned char status;
+
+       val=-1;
+       status = kbd_read_status();
+       if (status & KBD_STAT_OBF) {
+               val = kbd_read_input();
+               if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
+                       val = -2;
+       }
+       return val;
+}
+
+int kbd_wait_for_input(void)
+{
+       unsigned long timeout;
+       int val;
+       
+       timeout = KBD_TIMEOUT;
+       val=kbd_read_data();
+       while(val < 0)
+       {
+               if(timeout--==0)
+                       return -1;
+               udelay(1000);
+               val=kbd_read_data();
+       }
+       return val;
+}
+
+
+int kb_wait(void)
+{
+       unsigned long timeout = KBC_TIMEOUT * 10;
+
+       do {
+               unsigned char status = handle_kbd_event();
+               if (!(status & KBD_STAT_IBF))
+                       return 0; /* ok */
+               udelay(1000);
+               timeout--;
+       } while (timeout);
+       return 1;
+}
+
+void kbd_write_command_w(int data)
+{
+       if(kb_wait())
+               PRINTF("timeout in kbd_write_command_w\n");
+       kbd_write_command(data);
+}
+
+void kbd_write_output_w(int data)
+{
+       if(kb_wait())
+               PRINTF("timeout in kbd_write_output_w\n");
+       kbd_write_output(data);
+}
+
+void kbd_send_data(unsigned char data)
+{
+       unsigned char status;
+       disable_8259A_irq(1); /* disable interrupt */
+       kbd_write_output_w(data);
+       status = kbd_wait_for_input();
+       if (status == KBD_REPLY_ACK)
+               enable_8259A_irq(1); /* enable interrupt */
+}
+
+
+char * kbd_initialize(void)
+{
+       int status;
+
+       in_pointer = 0; /* delete in Buffer */
+       out_pointer = 0;
+       /*
+        * Test the keyboard interface.
+        * This seems to be the only way to get it going.
+        * If the test is successful a x55 is placed in the input buffer.
+        */
+       kbd_write_command_w(KBD_CCMD_SELF_TEST);
+       if (kbd_wait_for_input() != 0x55) 
+               return "Kbd:   failed self test";
+       /*
+        * Perform a keyboard interface test.  This causes the controller
+        * to test the keyboard clock and data lines.  The results of the
+        * test are placed in the input buffer.
+        */
+       kbd_write_command_w(KBD_CCMD_KBD_TEST);
+       if (kbd_wait_for_input() != 0x00) 
+               return "Kbd:   interface failed self test";
+       /*
+        * Enable the keyboard by allowing the keyboard clock to run.
+        */
+       kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
+       status = kbd_wait_for_input();
+       /*
+        * Reset keyboard. If the read times out
+        * then the assumption is that no keyboard is
+        * plugged into the machine.
+        * This defaults the keyboard to scan-code set 2.
+        *
+        * Set up to try again if the keyboard asks for RESEND.
+        */
+       do {
+               kbd_write_output_w(KBD_CMD_RESET);
+               status = kbd_wait_for_input();
+               if (status == KBD_REPLY_ACK) 
+                       break;
+               if (status != KBD_REPLY_RESEND)
+               {
+                       PRINTF("status: %X\n",status);
+                       return "Kbd:   reset failed, no ACK";
+               }
+       } while (1);
+       if (kbd_wait_for_input() != KBD_REPLY_POR)
+               return "Kbd:   reset failed, no POR";
+
+       /*
+        * Set keyboard controller mode. During this, the keyboard should be
+        * in the disabled state.
+        *
+        * Set up to try again if the keyboard asks for RESEND.
+        */
+       do {
+               kbd_write_output_w(KBD_CMD_DISABLE);
+               status = kbd_wait_for_input();
+               if (status == KBD_REPLY_ACK)
+                       break;
+               if (status != KBD_REPLY_RESEND)
+                       return "Kbd:   disable keyboard: no ACK";
+       } while (1);
+
+       kbd_write_command_w(KBD_CCMD_WRITE_MODE);
+       kbd_write_output_w(KBD_MODE_KBD_INT
+                             | KBD_MODE_SYS
+                             | KBD_MODE_DISABLE_MOUSE
+                             | KBD_MODE_KCC);
+
+       /* ibm powerpc portables need this to use scan-code set 1 -- Cort */
+       kbd_write_command_w(KBD_CCMD_READ_MODE);
+       if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
+               /*
+                * If the controller does not support conversion,
+                * Set the keyboard to scan-code set 1.
+                */
+               kbd_write_output_w(0xF0);
+               kbd_wait_for_input();
+               kbd_write_output_w(0x01);
+               kbd_wait_for_input();
+       }
+       kbd_write_output_w(KBD_CMD_ENABLE);
+       if (kbd_wait_for_input() != KBD_REPLY_ACK)
+               return "Kbd:   enable keyboard: no ACK";
+
+       /*
+        * Finally, set the typematic rate to maximum.
+        */
+       kbd_write_output_w(KBD_CMD_SET_RATE);
+       if (kbd_wait_for_input() != KBD_REPLY_ACK)
+               return "Kbd:   Set rate: no ACK";
+       kbd_write_output_w(0x00);
+       if (kbd_wait_for_input() != KBD_REPLY_ACK)
+               return "Kbd:   Set rate: no ACK";
+       return NULL;
+}
+
+void kbd_interrupt(void)
+{
+       handle_kbd_event();
+}
+
+
+
+/* eof */
+
diff --git a/board/mpl/common/kbd.h b/board/mpl/common/kbd.h
new file mode 100644 (file)
index 0000000..e2cdf37
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+
+#ifndef _KBD_H_
+#define _KBD_H_
+   
+extern int kbd_testc(void);
+extern int kbd_getc(void);
+extern void kbd_interrupt(void);
+extern char *kbd_initialize(void);
+
+unsigned char kbd_is_init(void);
+#define KBD_INTERRUPT 1
+#endif
diff --git a/board/mpl/common/memtst.c b/board/mpl/common/memtst.c
new file mode 100644 (file)
index 0000000..e573c94
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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
+ *
+ */
+
+/* NOT Used yet...
+  add following code to PIP405.c :
+int testdram (unsigned long ramsize)
+{
+    unsigned char s[32];
+               int i;
+               i=getenv_r("testmem",s,32);
+    if (i!=0) {
+       i=(int)simple_strtoul(s,NULL,10);
+                       if((i>0)&&(i<0xf)) {
+                               printf("testing ");
+                               i=mem_test(0,ramsize,i);
+                               if(i>0)
+                                       printf("ERROR ");
+                               else
+                                       printf("Ok ");
+                       }
+    }
+               return(1);
+}
+*/
+
+
+#include <ppcboot.h>
+#include <asm/processor.h>
+#include <405gp_i2c.h>
+
+#define FALSE           0
+#define TRUE            1
+
+#define TEST_QUIET                     8
+#define TEST_SHOW_PROG         4
+#define TEST_SHOW_ERR  2
+#define TEST_SHOW_ALL          1
+
+#define TESTPAT1 0xAA55AA55
+#define TESTPAT2 0x55AA55AA
+#define TEST_PASSED 0
+#define TEST_FAILED 1
+#define MEGABYTE (1024*1024)
+
+
+
+
+
+typedef struct {
+  volatile unsigned long pat1;
+  volatile unsigned long pat2;
+} RAM_MEMTEST_PATTERN2;
+
+typedef struct {
+  volatile unsigned long addr;
+} RAM_MEMTEST_ADDRLINE;
+
+static __inline unsigned long Swap_32(unsigned long val)
+{
+  return(((val << 16) & 0xFFFF0000) | ((val >> 16) & 0x0000FFFF));
+}
+
+void testm_puts(int quiet, char *buf)
+{
+       if((quiet&TEST_SHOW_ALL)==TEST_SHOW_ALL)
+               puts(buf);
+}
+
+
+void Write_Error(int mode, unsigned long addr, unsigned long expected, unsigned long actual)
+{
+       
+       char dispbuf[64];
+       sprintf(dispbuf,"\n ERROR @ 0x%08lX: (exp: 0x%08lX act: 0x%08lX) ",addr,expected,actual);
+    testm_puts(((mode & TEST_SHOW_ERR)==TEST_SHOW_ERR) ? TEST_SHOW_ALL : mode,dispbuf);
+}
+
+
+/*
+ * fills the memblock of <size> bytes from <startaddr> with pat1 and pat2
+ */
+
+
+void RAM_MemTest_WritePattern2(unsigned long startaddr, unsigned long size,
+                         unsigned long pat1, unsigned long pat2)
+{
+  RAM_MEMTEST_PATTERN2 *p, *pe;
+
+  p = (RAM_MEMTEST_PATTERN2 *)startaddr;
+  pe = (RAM_MEMTEST_PATTERN2 *)(startaddr + size);
+
+  while (p < pe) {
+    p->pat1 = pat1;
+    p->pat2 = pat2;
+    p++;
+  } /* endwhile */
+}
+
+/*
+ * checks the memblock of <size> bytes from <startaddr> with pat1 and pat2
+ * returns the address of the first error or NULL if all is well
+ */
+
+void * RAM_MemTest_CheckPattern2(int mode,unsigned long startaddr, unsigned long size,
+                         unsigned long pat1, unsigned long pat2)
+{
+  RAM_MEMTEST_PATTERN2 *p, *pe;
+  unsigned long actual1, actual2;
+
+  p = (RAM_MEMTEST_PATTERN2 *)startaddr;
+  pe = (RAM_MEMTEST_PATTERN2 *)(startaddr + size);
+
+  while (p < pe) {
+    actual1 = p->pat1; actual2 = p->pat2;
+
+    if (actual1 != pat1) {
+      Write_Error(mode,(unsigned long)&(p->pat1), pat1, actual1);
+      return((void *)&(p->pat1));
+    } /* endif */
+
+    if (actual2 != pat2) {
+      Write_Error(mode,(unsigned long)&(p->pat2), pat2, actual2);
+      return((void *)&(p->pat2));
+    } /* endif */
+
+    p++;
+  } /* endwhile */
+
+  return(NULL);
+}
+
+/*
+ * fills the memblock of <size> bytes from <startaddr> with the address
+ */
+
+void RAM_MemTest_WriteAddrLine(unsigned long startaddr, unsigned long size, int swapped)
+{
+  RAM_MEMTEST_ADDRLINE *p, *pe;
+
+  p = (RAM_MEMTEST_ADDRLINE *)startaddr;
+  pe = (RAM_MEMTEST_ADDRLINE *)(startaddr + size);
+
+  if (!swapped) {
+    while (p < pe) {
+      p->addr = (unsigned long)p;
+      p++;
+    } /* endwhile */
+  } else {
+    while (p < pe) {
+      p->addr = Swap_32((unsigned long)p);
+      p++;
+    } /* endwhile */
+  } /* endif */
+}
+
+/*
+ * checks the memblock of <size> bytes from <startaddr>
+ * returns the address of the error or NULL if all is well
+ */
+
+void * RAM_MemTest_CheckAddrLine(int mode,unsigned long startaddr, unsigned long size, int swapped)
+{
+  RAM_MEMTEST_ADDRLINE *p, *pe;
+  unsigned long actual, expected;
+
+  p = (RAM_MEMTEST_ADDRLINE *)startaddr;
+  pe = (RAM_MEMTEST_ADDRLINE *)(startaddr + size);
+
+  if (!swapped) {
+    while (p < pe) {
+      actual = p->addr;
+      expected = (unsigned long)p;
+      if (actual != expected) {
+                               Write_Error(mode,(unsigned long)&(p->addr), expected, actual);
+                               return((void *)&(p->addr));
+      } /* endif */
+      p++;
+    } /* endwhile */
+  } 
+  else {
+       while (p < pe) {
+       actual = p->addr;
+       expected = Swap_32((unsigned long)p);
+       if (actual != expected) {
+                               Write_Error(mode,(unsigned long)&(p->addr), expected, actual);
+                               return((void *)&(p->addr));
+      } /* endif */
+      p++;
+    } /* endwhile */
+  } /* endif */
+
+  return(NULL);
+}
+
+/*
+ * checks the memblock of <size> bytes from <startaddr+size>
+ * returns the address of the error or NULL if all is well
+ */
+
+void * RAM_MemTest_CheckAddrLineReverse(int mode,unsigned long startaddr,
+                                unsigned long size, int swapped)
+{
+  RAM_MEMTEST_ADDRLINE *p, *pe;
+  unsigned long actual, expected;
+
+  p = (RAM_MEMTEST_ADDRLINE *)(startaddr + size - sizeof(p->addr));
+  pe = (RAM_MEMTEST_ADDRLINE *)startaddr;
+
+  if (!swapped) {
+    while (p > pe) {
+      actual = p->addr;
+      expected = (unsigned long)p;
+      if (actual != expected) {
+                               Write_Error(mode,(unsigned long)&(p->addr), expected, actual);
+                               return((void *)&(p->addr));
+      } /* endif */
+      p--;
+    } /* endwhile */
+  } else {
+    while (p > pe) {
+      actual = p->addr;
+      expected = Swap_32((unsigned long)p);
+      if (actual != expected) {
+                               Write_Error(mode,(unsigned long)&(p->addr), expected, actual);
+                               return((void *)&(p->addr));
+      } /* endif */
+      p--;
+    } /* endwhile */
+  } /* endif */
+
+  return(NULL);
+}
+
+/*
+ * fills the memblock of <size> bytes from <startaddr> with walking bit pattern
+ */
+
+void RAM_MemTest_WriteWalkBit(unsigned long startaddr, unsigned long size)
+{
+  volatile unsigned long *p, *pe;
+  unsigned long i;
+
+  p = (unsigned long *)startaddr;
+  pe = (unsigned long *)(startaddr + size);
+  i = 0;
+
+  while (p < pe) {
+    *p = 1UL << i;
+    i = (i + 1 + (((unsigned long)p) >> 7)) % 32;
+    p++;
+  } /* endwhile */
+}
+
+/*
+ * checks the memblock of <size> bytes from <startaddr> 
+ * returns the address of the error or NULL if all is well
+ */
+
+void * RAM_MemTest_CheckWalkBit(int mode,unsigned long startaddr, unsigned long size)
+{
+  volatile unsigned long *p, *pe;
+  unsigned long actual, expected;
+  unsigned long i;
+
+  p = (unsigned long *)startaddr;
+  pe = (unsigned long *)(startaddr + size);
+  i = 0;
+  
+  while (p < pe) {
+    actual = *p;
+    expected = (1UL << i); 
+    if (actual != expected) {
+      Write_Error(mode,(unsigned long)p, expected, actual);
+      return((void *)p);
+    } /* endif */
+    i = (i + 1 + (((unsigned long)p) >> 7)) % 32;
+    p++;
+  } /* endwhile */
+
+  return(NULL);
+}
+
+/*
+ * fills the memblock of <size> bytes from <startaddr> with "random" pattern
+ */
+
+void RAM_MemTest_WriteRandomPattern(unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+  unsigned long i, p;
+  
+  p = *pat;
+
+  for (i = 0; i < (size / 4); i++) {
+    *(unsigned long *)(startaddr + i*4) = p;
+    if ((p % 2) > 0) {
+      p ^= i;
+      p >>= 1;
+      p |= 0x80000000;
+    } else {
+      p ^= ~i;
+      p >>= 1;
+    } /* endif */
+  } /* endfor */
+  *pat = p;
+}
+
+/*
+ * checks the memblock of <size> bytes from <startaddr>
+ * returns the address of the error or NULL if all is well
+ */
+
+void * RAM_MemTest_CheckRandomPattern(int mode,unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+  void *perr = NULL;
+  unsigned long i, p, p1;
+
+  p = *pat;
+
+  for (i = 0; i < (size / 4); i++) {
+    p1 = *(unsigned long *)(startaddr + i*4);
+    if ( p1 != p) {
+      if (perr == NULL) {
+       Write_Error(mode,startaddr + i*4, p, p1);
+       perr = (void *)(startaddr + i*4);
+      } /* endif */
+    } /* endif */
+
+    if ((p % 2) > 0) {
+      p ^= i;
+      p >>= 1;
+      p |= 0x80000000;
+    } else {
+      p ^= ~i;
+      p >>= 1;
+    } /* endif */
+  } /* endfor */
+      
+  *pat = p;
+  return(perr);
+}
+
+
+void RAM_MemTest_WriteData1(unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+       RAM_MemTest_WritePattern2(startaddr, size, TESTPAT1, TESTPAT2);
+}
+
+void * RAM_MemTest_CheckData1(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+       return (RAM_MemTest_CheckPattern2(mode, startaddr, size, TESTPAT1, TESTPAT2));
+}
+
+void RAM_MemTest_WriteData2(unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+       RAM_MemTest_WritePattern2(startaddr, size, TESTPAT2, TESTPAT1);
+}
+
+void * RAM_MemTest_CheckData2(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+       return (RAM_MemTest_CheckPattern2(mode, startaddr, size, TESTPAT2, TESTPAT1));
+}
+
+void RAM_MemTest_WriteAddr1(unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+   RAM_MemTest_WriteAddrLine(startaddr, size, FALSE);
+}
+
+void * RAM_MemTest_Check1Addr1(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+       return(RAM_MemTest_CheckAddrLine(mode,startaddr,size, FALSE));
+}
+
+void * RAM_MemTest_Check2Addr1(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+       return(RAM_MemTest_CheckAddrLineReverse(mode,startaddr,size, FALSE));
+}
+
+void RAM_MemTest_WriteAddr2(unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+   RAM_MemTest_WriteAddrLine(startaddr, size, TRUE);
+}
+
+void * RAM_MemTest_Check1Addr2(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+       return(RAM_MemTest_CheckAddrLine(mode,startaddr,size, TRUE));
+}
+
+void * RAM_MemTest_Check2Addr2(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat)
+{
+       return(RAM_MemTest_CheckAddrLineReverse(mode,startaddr,size, TRUE));
+}
+
+
+typedef struct {
+       void (*test_write)(unsigned long startaddr, unsigned long size, unsigned long *pat);
+       char *test_write_desc; 
+       void * (*test_check1)(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat); 
+       void * (*test_check2)(int mode, unsigned long startaddr, unsigned long size, unsigned long *pat); 
+} RAM_MEMTEST_FUNC;
+
+
+#define TEST_STAGES 5
+const RAM_MEMTEST_FUNC test_stage[TEST_STAGES] = {
+       {RAM_MemTest_WriteData1, "data test 1...\n", RAM_MemTest_CheckData1, NULL},
+       {RAM_MemTest_WriteData2, "data test 2...\n", RAM_MemTest_CheckData2, NULL},
+       {RAM_MemTest_WriteAddr1, "address line test...\n", RAM_MemTest_Check1Addr1, RAM_MemTest_Check2Addr1},
+       {RAM_MemTest_WriteAddr2, "address line test (swapped)...\n", RAM_MemTest_Check1Addr2, RAM_MemTest_Check2Addr2},
+       {RAM_MemTest_WriteRandomPattern, "random data test...\n", RAM_MemTest_CheckRandomPattern, NULL}
+};             
+
+
+
+int mem_test(unsigned long start, unsigned long ramsize, int quiet)
+{
+  unsigned long errors,stage;
+  unsigned long startaddr, size, i;
+  const unsigned long blocksize = 0x80000;      /* check in 512KB blocks */
+  unsigned long *perr;
+  unsigned long rdatapat;
+  char dispbuf[80];
+  int status = TEST_PASSED;
+  int prog=0;
+  
+  errors = 0;
+  startaddr = start;
+  size = ramsize;
+  if((quiet&TEST_SHOW_PROG)==TEST_SHOW_PROG) {
+       prog++;
+       printf(".");
+       }
+       sprintf(dispbuf,"\n\nMemory Test: addr = 0x%lx size = 0x%lx\n",startaddr,size);
+  testm_puts(quiet,dispbuf);
+       for(stage=0;stage<TEST_STAGES;stage++){
+               sprintf(dispbuf,test_stage[stage].test_write_desc); 
+       testm_puts(quiet,dispbuf);
+       /* fill SDRAM */
+       rdatapat = 0x12345678;
+       sprintf(dispbuf,"writing block:     ");
+       testm_puts(quiet,dispbuf);
+       for (i = 0; i < size; i += blocksize) {
+       sprintf(dispbuf,"%04lX\b\b\b\b",i / blocksize);
+       testm_puts(quiet,dispbuf);
+               test_stage[stage].test_write(startaddr+i, blocksize, &rdatapat);
+       } /* endfor */
+       sprintf(dispbuf,"\n");
+       testm_puts(quiet,dispbuf);
+       if((quiet&TEST_SHOW_PROG)==TEST_SHOW_PROG) {
+               prog++;
+               printf(".");
+               }
+       /* check SDRAM */
+       rdatapat = 0x12345678;
+       sprintf(dispbuf,"checking block:     ");
+       testm_puts(quiet,dispbuf);
+       for (i = 0; i < size; i += blocksize) {
+       sprintf(dispbuf,"%04lX\b\b\b\b",i / blocksize);
+       testm_puts(quiet,dispbuf);
+       if ((perr = test_stage[stage].test_check1(quiet,startaddr+i, blocksize,&rdatapat)) != NULL) {
+                               status = TEST_FAILED;
+       } /* endif */
+       } /* endfor */
+       sprintf(dispbuf,"\n");
+       testm_puts(quiet,dispbuf);
+       if((quiet&TEST_SHOW_PROG)==TEST_SHOW_PROG) {
+               prog++;
+               printf(".");
+               }
+               if( test_stage[stage].test_check2!=NULL) {
+               /* check2 SDRAM */
+               sprintf(dispbuf,"2nd checking block:     ");
+               rdatapat = 0x12345678;
+               testm_puts(quiet,dispbuf);
+               for (i = 0; i < size; i += blocksize) {
+               sprintf(dispbuf,"%04lX\b\b\b\b",i / blocksize);
+               testm_puts(quiet,dispbuf);
+               if ((perr = test_stage[stage].test_check2(quiet,startaddr+i, blocksize,&rdatapat)) != NULL) {
+                                       status = TEST_FAILED;
+               } /* endif */
+               } /* endfor */
+               sprintf(dispbuf,"\n");
+               testm_puts(quiet,dispbuf);
+               if((quiet&TEST_SHOW_PROG)==TEST_SHOW_PROG) {
+                       prog++;
+                       printf(".");
+                       }
+               }
+               
+       } /* next stage */
+  if((quiet&TEST_SHOW_PROG)==TEST_SHOW_PROG) {
+       while(prog-->0)
+               printf("\b \b");
+       }
+
+  if (status == TEST_FAILED)
+    errors++;
+
+  return(errors);
+}
+
+
diff --git a/board/mpl/common/pci.c b/board/mpl/common/pci.c
new file mode 100644 (file)
index 0000000..579f3fd
--- /dev/null
@@ -0,0 +1,1411 @@
+/*-----------------------------------------------------------------------------+
+|
+|       This source code has been made available to you by IBM on an AS-IS
+|       basis.  Anyone receiving this source is licensed under IBM
+|       copyrights to use it in any way he or she deems fit, including
+|       copying it, modifying it, compiling it, and redistributing it either
+|       with or without modifications.  No license under IBM patents or
+|       patent applications is to be implied by the copyright license.
+|
+|       Any user of this software should understand that IBM cannot provide
+|       technical support for this software and will not be responsible for
+|       any consequences resulting from the use of this software.
+|
+|       Any person who transfers this source code or any derivative work
+|       must include the IBM copyright notice, this paragraph, and the
+|       preceding two paragraphs in the transferred software.
+|
+|       COPYRIGHT   I B M   CORPORATION 1995
+|       LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
++-----------------------------------------------------------------------------*/
+/*
+ * Adapted for PIP405 03.07.01
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ * 
+ * TODO: Clean-up
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <cmd_boot.h>
+#include "pci.h"
+#include <asm/processor.h>
+#include "isa.h"
+
+
+void pciinfo(int bus_no);
+#ifdef CONFIG_405GP
+
+#ifdef CONFIG_PCI
+
+#undef PCI_DEBUG
+
+/*------------------------------------------------------------------------
+| These are the lowest addresses allowed for PCI configuration.
+| They correspond to lowest available I/O and Memory addresses.
+| In the case where where multiple PMM regs are being used to map
+| different PLB to PCI regions, each region should have it's own
+| minimum address.
++-----------------------------------------------------------------------*/
+unsigned long    LowestMemAddr1 = MIN_PCI_MEMADDR1;
+unsigned long    LowestMemAddr2 = MIN_PCI_MEMADDR2;
+unsigned long    LowestIOAddr   = MIN_PCI_PCI_IOADDR1;
+
+unsigned long    MaxBusNum = 0;
+
+
+
+/*-----------------------------------------------------------------------------+
+| pci_init.  Initializes the 405GP PCI Configuration regs.
++-----------------------------------------------------------------------------*/
+void pci_init(bd_t *dummy)
+{
+   unsigned short temp_short;
+
+#ifdef CONFIG_PCI_HOST
+   /*--------------------------------------------------------------------------+
+   | 405GP PCI Master configuration.
+   | Map one 512 MB range of PLB/processor addresses to PCI memory space.
+   |   PLB address 0x80000000-0x9FFFFFFF ==> PCI address 0x80000000-0x9FFFFFFF
+   |   Use byte reversed out routines to handle endianess.
+   +--------------------------------------------------------------------------*/
+   out32r(PMM0MA,    0x00000000);        /* ensure disabled b4 setting PMM0LA */
+   out32r(PMM0LA,    PCI_M0_LOCAL_ADDR);
+   out32r(PMM0PCILA, PCI_M0_PCI_LOW_ADDR);
+   out32r(PMM0PCIHA, PCI_M0_PCI_HIGH_ADDR);
+   out32r(PMM0MA,    PCI_M0_MASK_ATTRIB);        /* no prefetching, and enable region */
+   /*--------------------------------------------------------------------------+
+   | Map one 512 MB range of PLB/processor addresses to PCI memory space.
+   |   PLB address 0xA0000000-0xBFFFFFFF ==> PCI address 0x00000000-0x1FFFFFFF
+   |   Use byte reversed out routines to handle endianess.
+   | This space is for the VGA card.
+   +--------------------------------------------------------------------------*/
+   out32r(PMM1MA,    0x00000000);        /* ensure disabled b4 setting PMM1LA */
+   out32r(PMM1LA,    PCI_M1_LOCAL_ADDR);
+   out32r(PMM1PCILA, PCI_M1_PCI_LOW_ADDR);
+   out32r(PMM1PCIHA, PCI_M1_PCI_HIGH_ADDR);
+   out32r(PMM1MA,    PCI_M1_MASK_ATTRIB);        /* no prefetching, and enable region */
+   /*--------------------------------------------------------------------------+
+   | PMM2 is not used.  Initialize them to zero.
+   +--------------------------------------------------------------------------*/
+   out32r(PMM2MA,    0x00000000);        /* ensure disabled b4 setting PMM2LA */
+   out32r(PMM2LA,    PCI_M2_LOCAL_ADDR);
+   out32r(PMM2PCILA, PCI_M2_PCI_LOW_ADDR);
+   out32r(PMM2PCIHA, PCI_M2_PCI_HIGH_ADDR);
+   out32r(PMM2MA,    PCI_M2_MASK_ATTRIB);        /* not enabled */
+#endif
+
+   /*--------------------------------------------------------------------------+
+   | 405GP PCI Target configuration.  (PTM1)
+   | Note: PTM1MS is hardwire enabled but we set the enable bit anyway.
+   +--------------------------------------------------------------------------*/
+   out32r(PTM1LA,    CFG_PCI_PTM1LA);   /* insert address                     */
+   out32r(PTM1MS,    CFG_PCI_PTM1MS);   /* insert size, enable bit is 1       */
+
+   /*--------------------------------------------------------------------------+
+   | 405GP PCI Target configuration.  (PTM2)
+   +--------------------------------------------------------------------------*/
+   out32r(PTM2LA,    CFG_PCI_PTM2LA);   /* insert address                     */
+   if (CFG_PCI_PTM2MS == 0)
+     {
+       out32r(PTM2MS,    0x00000001);   /* set enable bit                     */
+       PCI_Write_CFG_Reg(PCIDEVID_405GP, PCIBASEADDR2, 0x00000000, 4);
+       out32r(PTM2MS,    0x00000000);   /* disable                            */
+     }
+   else
+     out32r(PTM2MS,    CFG_PCI_PTM2MS); /* insert size, enable bit is 1       */
+
+   /*
+    * Insert Subsystem Vendor and Device ID
+    */
+   PCI_Write_CFG_Reg(PCIDEVID_405GP, PCISSVENDORID, CFG_PCI_SUBSYS_VENDORID, 2);
+   PCI_Write_CFG_Reg(PCIDEVID_405GP, PCISSDEVICEID, CFG_PCI_SUBSYS_DEVICEID, 2);
+
+#ifdef CONFIG_PCI_HOST
+   /*--------------------------------------------------------------------------+
+   | Write the 405GP PCI Configuration regs.
+   |   Enable 405GP to be a master on the PCI bus (PMM).
+   |   Enable 405GP to act as a PCI memory target (PTM).
+   +--------------------------------------------------------------------------*/
+   temp_short = PCI_Read_CFG_Reg(PCIDEVID_405GP, PCICMD, 2);
+   PCI_Write_CFG_Reg(PCIDEVID_405GP, PCICMD, temp_short | BM_EN | MEM_EN, 2);
+#endif
+
+
+   /*
+    * Set HCE bit (Host Configuration Enabled)
+    */
+   temp_short = PCI_Read_CFG_Reg(PCIDEVID_405GP, PCIBRDGOPT2, 2);
+   PCI_Write_CFG_Reg(PCIDEVID_405GP, PCIBRDGOPT2,(temp_short | 0x0001), 2);
+
+#ifdef CONFIG_PCI_PNP
+   /*--------------------------------------------------------------------------+
+   | Scan the PCI bus and configure devices found.
+   +--------------------------------------------------------------------------*/
+   PCI_Scan(0);
+#endif  /* CONFIG_PCI_PNP */
+
+}
+
+/*-----------------------------------------------------------------------------+
+|  Subroutine:  PCI_Read_CFG_Reg
+|  Description: Read a PCI configuration register 
+|  Inputs:
+|               BusDevFunc      PCI Bus+Device+Function number
+|               Reg             Configuration register number
+|               Width           Number of bytes to read (1, 2, or 4)
+|  Return value:
+|               (unsigned int)  Value of the configuration register read.
+|                      For reads shorter than 4 bytes, return value
+|                      is LSB-justified
++-----------------------------------------------------------------------------*/
+unsigned long     PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width)
+{
+   unsigned int    RegAddr;
+
+   /*--------------------------------------------------------------------------+
+   | bit 31 must be 1 and bits 1:0 must be 0 (note Little Endian bit notation)
+   +--------------------------------------------------------------------------*/
+   RegAddr = 0x80000000 | ((Reg|BusDevFunc) & 0xFFFFFFFC);
+
+   /*--------------------------------------------------------------------------+
+   | Write reg to PCI Config Address
+   +--------------------------------------------------------------------------*/
+   out32r(PCICFGADR, RegAddr);
+
+   /*--------------------------------------------------------------------------+
+   | Read reg value from PCI Config Data
+   +--------------------------------------------------------------------------*/
+   switch (Width)
+   {
+      case 1: return ((unsigned int) in8(PCICFGDATA | (Reg & 0x3)));
+      case 2: return ((unsigned int) in16r(PCICFGDATA | (Reg & 0x3)));
+      case 4: return (in32r(PCICFGDATA | (Reg & 0x3)));
+   }
+
+   return 0; /* not reached: just to satisfy the compiler */
+}
+
+/*-----------------------------------------------------------------------------+
+|  Subroutine:  PCI_Write_CFG_Reg
+|  Description: Write a PCI configuration register.
+|  Inputs:
+|               BusDevFunc      PCI Bus+Device+Function number
+|               Reg             Configuration register number
+|               Value           Configuration register value
+|               Width           Number of bytes to write (1, 2, or 4)
+|  Return value:
+|               0       Successful
+| Updated for pass2 errata #6. Need to disable interrupts and clear the
+| PCICFGADR reg after writing the PCICFGDATA reg.  
++-----------------------------------------------------------------------------*/
+int    PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned long Value, int Width)
+{
+   unsigned int    RegAddr;
+   unsigned int    msr;
+
+   /*--------------------------------------------------------------------------+
+   | Ensure interrupts disabled for pass2 errata #6.
+   +--------------------------------------------------------------------------*/
+   msr = mfmsr();
+   mtmsr(msr & ~(MSR_EE|MSR_CE));
+
+   /*--------------------------------------------------------------------------+
+   | bit 31 must be 1 and bits 1:0 must be 0 (note Little Endian bit notation)
+   +--------------------------------------------------------------------------*/
+   RegAddr = 0x80000000 | ((Reg|BusDevFunc) & 0xFFFFFFFC);
+   /*--------------------------------------------------------------------------+
+   | Write reg to PCI Config Address
+   +--------------------------------------------------------------------------*/
+   out32r(PCICFGADR, RegAddr);
+
+   /*--------------------------------------------------------------------------+
+   | Write reg value to PCI Config Data
+   +--------------------------------------------------------------------------*/
+   switch (Width)
+   {
+      case 1: out8(PCICFGDATA | (Reg & 0x3), (unsigned char)(Value & 0xFF));
+              break;
+      case 2: out16r(PCICFGDATA | (Reg & 0x3),(unsigned short)(Value & 0xFFFF));
+              break;
+      case 4: out32r(PCICFGDATA | (Reg & 0x3), Value);
+              break;
+   }
+
+   /*--------------------------------------------------------------------------+
+   | Write PCI Config Address after writing PCICFGDATA for pass2 errata #6.
+   +--------------------------------------------------------------------------*/
+   out32r(PCICFGADR, 0x00000000);
+
+   /*--------------------------------------------------------------------------+
+   | Restore msr (for pass2 errata #6).
+   +--------------------------------------------------------------------------*/
+   mtmsr(msr);
+
+   return (0);
+}
+
+#include "pci_parts.h"
+
+/*
+ * Returns the pointer to the func config table, or NULL, if it not available 
+ * if the revision is ff in the table, it will not be chcked  
+ */ 
+
+PCI_DEV_CFG_TABLE *PCI_Get_Func_Table(unsigned short vend_id,unsigned short dev_id,unsigned char revision,unsigned char func)
+{
+       int i;
+       i=0;
+       while(pcidevtbl[i].vendorID!=0xffff) {
+               if((pcidevtbl[i].vendorID == vend_id) &&
+                 (pcidevtbl[i].deviceID  == dev_id) &&
+                 (pcidevtbl[i].func      == func) &&
+                 ((pcidevtbl[i].revision == 0xff) || (pcidevtbl[i].revision == revision))) {
+#ifdef PCI_DEBUG
+                       printf("Table found for 0x%04X 0x%04X\n",vend_id,dev_id);
+#endif
+                       return &pcidevtbl[i];
+               }
+               i++; /* proceed all entries */
+       } 
+#ifdef PCI_DEBUG
+       printf("No Table found for 0x%04X 0x%04X\n",vend_id,dev_id);
+#endif
+       return NULL;
+}
+                 
+
+/*-----------------------------------------------------------------------
+|
+|  Subroutine:  PCI_Scan
+|
+|  Prototype:   void    PCI_Scan(int BusNum)
+|
+|  Description: Scan through all 16 allowable PCI IDs and configure
+|               those for which the vendor ID indicates there is a
+|               device present.
+|
+|  Inputs:
+|               BusNum  Bus number where scanning begins
+|
+|  Return value:
+|               None
+|
++----------------------------------------------------------------------*/
+void    PCI_Scan(int bus_no)
+{
+       int device_no,i;
+       int BusDevFunc;
+       unsigned short vend_id,dev_id;
+       unsigned char revision,func,header;
+       PCI_DEV_CFG_TABLE *pci_dev_table=NULL;
+   /*--------------------------------------------------------------------------+
+   | Start with device 1, the 405GP is device 0.  MCG 01/04/99
+   +--------------------------------------------------------------------------*/
+       /* init all known (on Board devices) first */
+       for (device_no = 1; device_no < MAX_PCI_DEVICES; device_no++)
+    {
+               BusDevFunc = (bus_no << 16) | (device_no << 11);
+       if((unsigned short)PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2) != 0xffff) {
+                       header = (unsigned char)PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+                       for(func=0;func<MAX_PCI_FUNCTIONS;func++) { /* scan / init all functions */
+                       BusDevFunc = (bus_no << 16) | (device_no << 11) | (func << 8);
+                               vend_id = (unsigned short)PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2);
+                               if(vend_id==0xffff) {
+                                       #ifdef PCI_DEBUG
+                                       printf("was last function\n");
+                                       #endif
+                                       break;
+                               }
+                               dev_id = (unsigned short)PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2);
+                               revision = (unsigned char)PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_REVISION, 1);
+                               #ifdef PCI_DEBUG
+                               printf("search for 0x%04x 0x%04x 0x%02x %x\n",vend_id,dev_id,revision,func);
+                               #endif
+                               pci_dev_table=PCI_Get_Func_Table(vend_id,dev_id,revision,func);
+                               if(pci_dev_table==NULL) {
+                                       #ifdef PCI_DEBUG
+                                       printf("not found\n");
+                                       #endif
+                                       break;
+                               }
+                               /* table found, configure */
+                               i=0;
+                               while(pci_dev_table->fcntable[i].width!=0) {
+                                       PCI_Write_CFG_Reg(BusDevFunc,pci_dev_table->fcntable[i].index,
+                                               pci_dev_table->fcntable[i].val,pci_dev_table->fcntable[i].width);
+                                       #ifdef PCI_DEBUG
+                                       printf("    Reg 0x%02X Value 0x%08lX Width %02d written\n",pci_dev_table->fcntable[i].index,
+                                               pci_dev_table->fcntable[i].val,pci_dev_table->fcntable[i].width);
+                                       #endif
+                                       i++;
+                               }
+                               if((header & 0x80)==0)
+                                       break; /* no more functions */
+                       } /* next function */
+               } /* if device available */
+       } /* all devices */
+#if 0
+        /***************************************************************************
+        * Since the IO and Memory Area of the ISA Bridge is not relocable, config it
+        * first.
+        ****************************************************************************/
+   isabridgeDev=0;
+   for (Device = 1; Device < MAX_PCI_DEVICES; Device++)
+   {
+      BusDevFunc = (BusNum << 16) | (Device << 11);
+
+      if (PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID,2) != 0xFFFF)
+      {
+         if(PCI_Read_CFG_Reg(BusDevFunc, PCICLASSCODE,2) == 0x0601)
+         {
+                                               isabridgeDev=Device;
+            PCI_Config_ISABridge(BusDevFunc);
+                               break; /* do not scan further  */
+                                       }
+                       }
+               }
+
+   for (Device = 1; Device < MAX_PCI_DEVICES; Device++)
+   {
+      if(Device==isabridgeDev)
+       continue; /* skip ISA Bridge */
+      
+      BusDevFunc = (BusNum << 16) | (Device << 11);
+
+      if (PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID,2) != 0xFFFF)
+      {
+#ifdef PCI_DEBUG
+         printf("Device %d is present\n",Device);
+#endif
+         switch( PCI_Read_CFG_Reg(BusDevFunc, PCICLASSCODE, 2) )
+         {
+            case 0x0604:   /*  PCI-PCI Bridge */
+#ifdef PCI_DEBUG
+                               printf("Device %d is PCI Bridge\n",Device);
+#endif
+                        PCI_Config_Device(BusDevFunc, 2);
+               PCI_Config_Bridge(BusDevFunc);
+               break;
+            case 0x0100:   /*  PCI-PCI Bridge */
+#ifdef PCI_DEBUG
+                               printf("Device %d is SCSI Controller\n",Device);
+#endif
+               PCI_Config_SCSI_contrl(BusDevFunc);
+               break;
+
+            case 0x0300:   /*  VGA Display controller */
+            case 0x0001:   /*  VGA Display controller (pre PCI rev 2.0)*/
+#ifdef PCI_DEBUG
+                               printf("Device %d is VGA\n",Device);
+#endif
+               PCI_Config_VGA_contrl(BusDevFunc);
+               break;
+
+            default:
+#ifdef PCI_DEBUG
+                               printf("Device %d is a 0x%04X\n",Device,PCI_Read_CFG_Reg(BusDevFunc, PCICLASSCODE, 2));
+#endif
+/*               PCI_Config_Device(BusDevFunc, 6); */
+         }
+      }
+      else
+      {
+#ifdef DEBUG
+         printf("Device %d not present\n",Device);
+#endif
+      }
+   }
+#endif
+
+}
+
+
+/*-----------------------------------------------------------------------
+|  Subroutine:  PCI_Config_Device
+|
+|  Description: Configure a PCI device by examining its I/O and memory
+|               address space needs and allocating address space to it by
+|               programming the address decoders in the Base Address Registers.
+|
+|  Inputs:
+|               BusDevFunc    Bus+Device+Function number
+|               NumBaseAddr   Number of base address registers to
+|                             configure
+|  Return value:
+|               None
++----------------------------------------------------------------------*/
+void    PCI_Config_Device(int BusDevFunc, int NumBaseAddr)
+{
+    int     AddrSlot, i;
+    unsigned long  AddrDesc, AddrProg, Min_Gnt_Val, int_line;
+
+    for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++)
+    {
+       PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 0xFFFFFFFF,4);
+
+       AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 4);
+
+       if (AddrDesc == 0)                   /* unimplemented, stop looking */
+          continue;                         /* 01/04/99 MCG */
+
+#ifdef PCI_DEBUG
+       printf("Read Base Addr Reg %d = 0x%08lx\n",AddrSlot,AddrDesc);
+#endif
+
+       if ((AddrDesc & 1) == 0)        /* Memory */
+       {
+          AddrDesc &= 0xFFFFFFF0;
+
+          for (i = 0; (AddrDesc & 1) != 1; i++)
+             AddrDesc = AddrDesc >> 1;
+
+          AddrDesc = 1 << i;
+
+          if ((unsigned long)AddrDesc < 4096)
+             AddrDesc = 4096;
+#ifdef PCI_DEBUG
+          printf("    PCI Memory space = 0x%lx bytes \n",AddrDesc);
+#endif
+          for (AddrProg = MIN_PCI_MEMADDR1; AddrProg < LowestMemAddr1; AddrProg += AddrDesc);
+
+          PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
+          LowestMemAddr1 = AddrProg + AddrDesc;
+       }
+       else                            /* I/O */
+       {
+          AddrDesc &= 0xFFFFFFFC;
+
+          for (i = 0; (AddrDesc & 1) != 1; i++)
+             AddrDesc = AddrDesc >> 1;
+
+          AddrDesc = 1 << i;
+#ifdef PCI_DEBUG
+          printf("    PCI I/O space = 0x%lx bytes \n",AddrDesc);
+#endif
+          for (AddrProg = MIN_PCI_PCI_IOADDR2; AddrProg < LowestIOAddr; AddrProg += AddrDesc);
+
+          PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
+          LowestIOAddr = AddrProg + AddrDesc;
+       }
+
+    }
+
+    Min_Gnt_Val = 0x80;
+    PCI_Write_CFG_Reg(BusDevFunc, PCILATENCYTIM, Min_Gnt_Val, 1);
+
+    /*
+     * Write pci interrupt line register (cpci405 specific)
+     */
+    switch ((BusDevFunc >> 11) & 0x03)
+      {
+      case 0:
+        int_line = 27 + 2;
+        break;
+      case 1:
+        int_line = 27 + 3;
+        break;
+      case 2:
+        int_line = 27 + 0;
+        break;
+      case 3:
+        int_line = 27 + 1;
+        break;
+      }
+    PCI_Write_CFG_Reg(BusDevFunc, PCIINTLINE, int_line, 1);
+
+    /*
+     * Enable i/o space, memory space and master on this device
+     */
+    PCI_Write_CFG_Reg(BusDevFunc, PCICMD, 7, 2);
+
+}
+
+/*-----------------------------------------------------------------------
+|  Subroutine:  PCI_Config_VGA_Device
+|
+|  Description: Configure a PCI VGA device by examining its I/O and memory
+|               address space needs and allocating address space to it by
+|               programming the address decoders in the Base Address Registers.
+|
+|  Inputs:
+|               BusDevFunc    Bus+Device+Function number
+|               NumBaseAddr   Number of base address registers to
+|                             configure
+|  Return value:
+|               None
++----------------------------------------------------------------------*/
+void    PCI_Config_VGA_Device(int BusDevFunc, int NumBaseAddr)
+{
+    int     AddrSlot, i;
+    unsigned long  AddrDesc, AddrProg, Min_Gnt_Val;
+
+    for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++)
+    {
+       PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 0xFFFFFFFF,4);
+
+       AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 4);
+
+       if (AddrDesc == 0)                   /* unimplemented, stop looking */
+          continue;                         /* 01/04/99 MCG */
+
+#ifdef PCI_DEBUG
+       printf("VGA Device Read Base Addr Reg %d = 0x%08lx\n",AddrSlot,AddrDesc);
+#endif
+
+       if ((AddrDesc & 1) == 0)        /* Memory */
+       {
+          AddrDesc &= 0xFFFFFFF0;
+
+          for (i = 0; (AddrDesc & 1) != 1; i++)
+             AddrDesc = AddrDesc >> 1;
+
+          AddrDesc = 1 << i;
+
+          if ((unsigned long)AddrDesc < 4096)
+             AddrDesc = 4096;
+#ifdef PCI_DEBUG
+          printf("    PCI Memory space = 0x%lx bytes \n",AddrDesc);
+#endif
+          for (AddrProg = MIN_PCI_MEMADDR2; AddrProg < LowestMemAddr2; AddrProg += AddrDesc);
+
+          PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
+          LowestMemAddr2 = AddrProg + AddrDesc;
+       }
+       else                            /* I/O */
+       {
+          AddrDesc &= 0xFFFFFFFC;
+
+          for (i = 0; (AddrDesc & 1) != 1; i++)
+             AddrDesc = AddrDesc >> 1;
+
+          AddrDesc = 1 << i;
+#ifdef PCI_DEBUG
+          printf("    PCI I/O space = 0x%lx bytes \n",AddrDesc);
+#endif
+          for (AddrProg = MIN_PCI_PCI_IOADDR2; AddrProg < LowestIOAddr; AddrProg
++= AddrDesc);
+
+          PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
+          LowestIOAddr = AddrProg + AddrDesc;
+       }
+
+    }
+
+    Min_Gnt_Val = 0x80;
+    PCI_Write_CFG_Reg(BusDevFunc, PCILATENCYTIM, Min_Gnt_Val, 1);
+}
+
+/*-----------------------------------------------------------------------
+|
+|  Subroutine:  PCI_Config_Bridge
+|
+|  Prototype:   void    PCI_Config_Bridge(int BusDevFunc)
+|
+|  Description: Configure a PCI-PCI bridge
+|
+|  Inputs:
+|               BusDevFunc      Bus+Device+Function number
+|
+|  Return value:
+|               None
+|
++----------------------------------------------------------------------*/
+void    PCI_Config_Bridge(int BusDevFunc)
+{
+   int     SecondaryBus;
+   int     PrimaryBus;
+   int     CommandReg_Val;
+   int     InitialLowestIOAddr, InitialLowestMemAddr;
+   int     IOBase, MemBase;
+   int     IOLimit, MemLimit;
+
+   InitialLowestIOAddr = LowestIOAddr;
+   InitialLowestMemAddr = LowestMemAddr1;
+
+   CommandReg_Val = (unsigned short)PCI_Read_CFG_Reg(BusDevFunc, PCICMD, 2);
+
+   /* Configure bridge's base address registers */
+
+   PCI_Config_Device(BusDevFunc, 2);
+
+   if ( LowestIOAddr > InitialLowestIOAddr )    /* bridge uses IO space?     */
+      CommandReg_Val |= 0x01;                   /* enable I/O Space          */
+
+   if ( LowestMemAddr1 > InitialLowestMemAddr )  /* bridge uses memory space? */
+      CommandReg_Val |= 0x02;                   /* enable Memory Space       */
+
+   PrimaryBus = (BusDevFunc >> 16) & 0xFF;
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_PRIMARYBUS, PrimaryBus, 1);
+
+   SecondaryBus = ++MaxBusNum;
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SECONDARYBUS, SecondaryBus, 1);
+
+   /* Start with max. possible value for subordinate bus number                    */
+   /* Later, after any additional child busses are found, we'll update this        */
+
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, 0xFF, 1);
+
+   /* IO Base must be on 4Kb boundary.  Adjust if needed */
+
+   if ((LowestIOAddr % 4096) != 0)
+      LowestIOAddr += 4096 - (LowestIOAddr % 4096);
+
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOBASE, (LowestIOAddr>>8) & 0xF0, 1);
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOBASEUPPER16, (LowestIOAddr>>16) & 0xFFFF, 2);
+
+   IOBase = LowestIOAddr;
+
+   /* Mem Base must be on 1 MB boundary.  adjust if needed */
+   if ((LowestMemAddr1 % 0x100000) != 0)
+      LowestMemAddr1 += 0x100000 - (LowestMemAddr1 % 0x100000);
+
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_MEMBASE, (LowestMemAddr1>>16) & 0xFFF0, 2);
+   MemBase = LowestMemAddr1;
+
+   PCI_Scan(SecondaryBus);
+
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, MaxBusNum, 1);
+
+   IOLimit = LowestIOAddr;
+   if (LowestIOAddr > IOBase)           /* IO space used on secondary bus?   */
+   {
+      CommandReg_Val |= 0x01;           /*   enable IO Space                 */
+      IOLimit--;                        /*   IOLimit is highest used address */
+   }
+
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOLIMIT, ((IOLimit)>>8) & 0xF0, 1);
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOLIMITUPPER16, ((IOLimit)>>16) & 0xFFFF, 2);
+
+   /* IOLIMIT is the starting address of a 4K block forwarded by the bridge.       */
+   /* Round LowestIOAddr up to the next 4K boundary if IO space is enabled.        */
+
+   if ((CommandReg_Val & 0x01) == 0x01)
+      LowestIOAddr = (IOLimit | 0xFFF) + 1;
+
+   MemLimit = LowestMemAddr1;
+   if ( LowestMemAddr1 > MemBase )    /* mem. space is used on secondary bus? */
+   {
+      CommandReg_Val |= 0x02;        /*   enable Memory Space                */
+      MemLimit--;                    /*   MemLimit is highest used address   */
+   }
+
+   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_MEMLIMIT, ((MemLimit)>>16) & 0xFFF0, 2);
+
+   /* MEMLIMIT is the starting address of a 1M block forwarded by the bridge.      */
+   /* Round LowestMemAddr up to the next 1M boundary if Memory space is enabled.   */
+
+   if ( (CommandReg_Val & 0x02) == 0x02 )
+           LowestMemAddr1 = (MemLimit | 0xFFFFF) + 1;
+
+   /* Enable Bus Master on secondary bus */
+   CommandReg_Val |= 0x04;
+
+   PCI_Write_CFG_Reg(BusDevFunc, PCICMD, CommandReg_Val, 2);
+
+}
+
+/*-----------------------------------------------------------------------
+|  Subroutine:  PCI_Find_Device
+|
+|  Prototype:   int     PCI_Find_Device(hword VendorID, hword DeviceID);
+|
+|  Description:
+|               Locate a PCI device by vendor and device number
+|
+|  Inputs:
+|               VendorID        Value of the device's Vendor ID field
+|               DeviceID        Value of the device's Device ID field
+|
+|  Return value:
+|               < 0     Device not found
+|               (int)   PCI Bus+Device+Function number
++----------------------------------------------------------------------*/
+int     PCI_Find_Device(unsigned short VendorID, unsigned short DeviceID)
+{
+   int     Device;
+   int     BusDevFunc;
+   int     BusNum;
+   int          Funct;
+
+   for (BusNum = MaxBusNum; BusNum >= 0; BusNum--)
+      for (Device = 0; Device < MAX_PCI_DEVICES; Device++)
+      {
+       for(Funct=0;Funct<MAX_PCI_FUNCTIONS;Funct++)
+                               {
+                                       BusDevFunc = (BusNum << 16) | (Device << 11) | (Funct<<8);
+               if ((unsigned short)PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID, 2) == VendorID
+               && (unsigned short)PCI_Read_CFG_Reg(BusDevFunc, PCIDEVICEID, 2) == DeviceID)
+               return (BusDevFunc);
+                               }
+      }
+
+   return (-1);
+}
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_PCI)
+
+void
+do_pciinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+  int bus_no = 0;
+
+  if (argc == 2)
+    {
+      bus_no = (int)simple_strtoul(argv[1], NULL, 10);
+    }
+
+  pciinfo(bus_no);
+}
+
+
+/*******************************************************************************
+*
+* pciinfo - print information about PCI devices
+*
+*/
+void
+pciinfo(int bus_no)
+{
+  int device_no;
+  unsigned short vendor_id,vendor2_id;
+  int BusDevFunc,funct;
+  int device_no_start = 1;
+  
+  printf ("Scanning all functions of each PCI device on bus %d\n", bus_no);
+
+  if (bus_no == 0)
+    device_no_start = 1;
+  for (device_no=device_no_start; device_no < MAX_PCI_DEVICES; device_no++)
+    {
+      BusDevFunc = (bus_no << 16) | (device_no << 11);
+      vendor_id = (unsigned short)PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID, 2);
+
+      if (vendor_id != 0xffff)
+      {
+          printf("\nFound PCI device %d: Function 0\n", device_no);
+          pciHeaderShow(BusDevFunc);
+                               if(((unsigned char)PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE,1)&0x80)==0x80)
+                                       {
+                                       for(funct=1;funct<MAX_PCI_FUNCTIONS;funct++)
+                                               {
+                                     BusDevFunc = (bus_no << 16) | (device_no << 11) | (funct << 8);
+                                       vendor2_id = PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID, 2);
+                                       if (vendor2_id != vendor_id)
+                                       break;
+                       printf("\nFound PCI device %d: Function %d\n", device_no,funct);
+                       pciHeaderShow(BusDevFunc);
+                                               }
+                                       }
+       }
+    }
+}
+
+
+/*******************************************************************************
+*
+* pciHeaderShow - print a header of the specified PCI device
+*
+* This routine prints a header of the PCI device specified by BusDevFunc.
+*
+*/
+void
+pciHeaderShow(int BusDevFunc)
+{
+  PCI_HEADER_DEVICE headerDevice;
+  PCI_HEADER_BRIDGE headerBridge;
+  PCI_HEADER_DEVICE * pD = &headerDevice;
+  PCI_HEADER_BRIDGE * pB = &headerBridge;
+  
+  pD->headerType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+
+  if (pD->headerType & 0x01)           /* PCI-to-PCI bridge */
+    {
+      pB->vendorId      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2);
+      pB->deviceId      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2);
+      pB->command       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2);
+      pB->status        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_STATUS, 2);
+      pB->revisionId    = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_REVISION, 1);
+      pB->progIf        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PROGRAMMING_IF, 1);
+      pB->subClass      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBCLASS, 1);
+      pB->classCode     = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CLASS, 1);
+      pB->cacheLine     = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CACHE_LINE_SIZE, 1);
+      pB->latency       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, 1);
+      pB->headerType    = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+      pB->bist          = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BIST, 1);
+      pB->base0         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_0, 4);
+      pB->base1         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_1, 4);
+      pB->priBus        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRIMARY_BUS, 1);
+      pB->secBus        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SECONDARY_BUS, 1);
+      pB->subBus        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBORDINATE_BUS, 1);
+      pB->secLatency    = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SEC_LATENCY, 1);
+      pB->ioBase        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_BASE, 1);
+      pB->ioLimit       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_LIMIT, 1);
+      pB->secStatus     = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SEC_STATUS, 2);
+      pB->memBase       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MEM_BASE, 2);
+      pB->memLimit      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MEM_LIMIT, 2);
+      pB->preBase       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_BASE, 2);
+      pB->preLimit      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_LIMIT, 2);
+      pB->preBaseUpper  = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_BASE_U, 4);
+      pB->preLimitUpper = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PRE_MEM_LIMIT_U, 4);
+      pB->ioBaseUpper   = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_BASE_U, 2);
+      pB->ioLimitUpper  = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_IO_LIMIT_U, 2);
+      pB->romBase       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_ROM_BASE, 4);
+      pB->intLine       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BRG_INT_LINE, 1);
+      pB->intPin        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BRG_INT_PIN, 1);
+      pB->control       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BRIDGE_CONTROL, 2);
+      pciBheaderPrint(pB);
+    }
+  else                                 /* PCI device */
+    {
+      pD->vendorId      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2);
+      pD->deviceId      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2);
+      pD->command       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2);
+      pD->status        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_STATUS, 1);
+      pD->revisionId    = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_REVISION, 1);
+      pD->progIf        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PROGRAMMING_IF, 1);
+      pD->subClass      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBCLASS, 1);
+      pD->classCode     = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CLASS, 1);
+      pD->cacheLine     = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CACHE_LINE_SIZE, 1);
+      pD->latency       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, 1);
+      pD->headerType    = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+      pD->bist          = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BIST, 1);
+      pD->base0         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_0, 4);
+      pD->base1         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_1, 4);
+      pD->base2         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_2, 4);
+      pD->base3         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_3, 4);
+      pD->base4         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_4, 4);
+      pD->base5         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_5, 4);
+      pD->cis           = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CIS, 4);
+      pD->subVendorId   = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_VENDER_ID, 2);
+      pD->subSystemId   = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_SYSTEM_ID, 2);
+      pD->romBase       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, 4);
+      pD->intLine       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_LINE, 1);
+      pD->intPin        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_PIN, 1);
+      pD->minGrant      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MIN_GRANT, 1);
+      pD->maxLatency    = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MAX_LATENCY, 1);
+      pciDheaderPrint(pD);
+    }
+}
+
+/*******************************************************************************
+*
+* pciDheaderPrint - print a PCI device header
+*
+* This routine prints a PCI device header.
+*
+*/
+void
+pciDheaderPrint(PCI_HEADER_DEVICE * pD)
+{
+  printf ("  vendor ID =                   0x%.4x\n", (ushort)pD->vendorId);
+  printf ("  device ID =                   0x%.4x\n", (ushort)pD->deviceId);
+  printf ("  command register =            0x%.4x\n", (ushort)pD->command);
+  printf ("  status register =             0x%.4x\n", (ushort)pD->status);     
+  printf ("  revision ID =                 0x%.2x\n", (uchar)pD->revisionId);
+  printf ("  class code =                  0x%.2x\n", (uchar)pD->classCode);   
+  printf ("  sub class code =              0x%.2x\n", (uchar)pD->subClass);
+  printf ("  programming interface =       0x%.2x\n", (uchar)pD->progIf);      
+  printf ("  cache line =                  0x%.2x\n", (uchar)pD->cacheLine);
+  printf ("  latency time =                0x%.2x\n", (uchar)pD->latency);
+  printf ("  header type =                 0x%.2x\n", (uchar)pD->headerType);
+  printf ("  BIST =                        0x%.2x\n", (uchar)pD->bist);        
+  printf ("  base address 0 =              0x%.8x\n", pD->base0);      
+  printf ("  base address 1 =              0x%.8x\n", pD->base1);      
+  printf ("  base address 2 =              0x%.8x\n", pD->base2);      
+  printf ("  base address 3 =              0x%.8x\n", pD->base3);      
+  printf ("  base address 4 =              0x%.8x\n", pD->base4);      
+  printf ("  base address 5 =              0x%.8x\n", pD->base5);      
+  printf ("  cardBus CIS pointer =         0x%.8x\n", pD->cis);        
+  printf ("  sub system vendor ID =        0x%.4x\n", (ushort)pD->subVendorId);
+  printf ("  sub system ID =               0x%.4x\n", (ushort)pD->subSystemId);
+  printf ("  expansion ROM base address =  0x%.8x\n", pD->romBase);
+  printf ("  interrupt line =              0x%.2x\n", (uchar)pD->intLine);
+  printf ("  interrupt pin =               0x%.2x\n", (uchar)pD->intPin);      
+  printf ("  min Grant =                   0x%.2x\n", (uchar)pD->minGrant);
+  printf ("  max Latency =                 0x%.2x\n", (uchar)pD->maxLatency);
+}
+
+/*******************************************************************************
+*
+* pciBheaderPrint - print a PCI-to-PCI bridge header
+*
+* This routine prints a PCI-to-PCI bridge header.
+*
+*/
+void
+pciBheaderPrint(PCI_HEADER_BRIDGE * pB)
+{
+  printf ("  vendor ID =                   0x%.4x\n", (ushort)pB->vendorId);
+  printf ("  device ID =                   0x%.4x\n", (ushort)pB->deviceId);
+  printf ("  command register =            0x%.4x\n", (ushort)pB->command);
+  printf ("  status register =             0x%.4x\n", (ushort)pB->status);     
+  printf ("  revision ID =                 0x%.2x\n", (uchar)pB->revisionId);
+  printf ("  class code =                  0x%.2x\n", (uchar)pB->classCode);   
+  printf ("  sub class code =              0x%.2x\n", (uchar)pB->subClass);
+  printf ("  programming interface =       0x%.2x\n", (uchar)pB->progIf);      
+  printf ("  cache line =                  0x%.2x\n", (uchar)pB->cacheLine);
+  printf ("  latency time =                0x%.2x\n", (uchar)pB->latency);
+  printf ("  header type =                 0x%.2x\n", (uchar)pB->headerType);
+  printf ("  BIST =                        0x%.2x\n", (uchar)pB->bist);
+  printf ("  base address 0 =              0x%.8x\n", pB->base0);      
+  printf ("  base address 1 =              0x%.8x\n", pB->base1);      
+  printf ("  primary bus number =          0x%.2x\n", (uchar)pB->priBus);      
+  printf ("  secondary bus number =        0x%.2x\n", (uchar)pB->secBus);      
+  printf ("  subordinate bus number =      0x%.2x\n", (uchar)pB->subBus);      
+  printf ("  secondary latency timer =     0x%.2x\n", (uchar)pB->secLatency);
+  printf ("  IO base =                     0x%.2x\n", (uchar)pB->ioBase);
+  printf ("  IO limit =                    0x%.2x\n", (uchar)pB->ioLimit);
+  printf ("  secondary status =            0x%.4x\n", (ushort)pB->secStatus);
+  printf ("  memory base =                 0x%.4x\n", (ushort)pB->memBase);
+  printf ("  memory limit =                0x%.4x\n", (ushort)pB->memLimit);   
+  printf ("  prefetch memory base =        0x%.4x\n", (ushort)pB->preBase);
+  printf ("  prefetch memory limit =       0x%.4x\n", (ushort)pB->preLimit);
+  printf ("  prefetch memory base upper =  0x%.8x\n", pB->preBaseUpper);
+  printf ("  prefetch memory limit upper = 0x%.8x\n", pB->preLimitUpper);
+  printf ("  IO base upper 16 bits =       0x%.4x\n", (ushort)pB->ioBaseUpper);
+  printf ("  IO limit upper 16 bits =      0x%.4x\n", (ushort)pB->ioLimitUpper);
+  printf ("  expansion ROM base address =  0x%.8x\n", pB->romBase);
+  printf ("  interrupt line =              0x%.2x\n", (uchar)pB->intLine);
+  printf ("  interrupt pin =               0x%.2x\n", (uchar)pB->intPin);      
+  printf ("  bridge control =              0x%.4x\n", (ushort)pB->control);
+}
+
+
+
+
+/*******************************************************************************
+*
+* pciGetHeader0 - gets the header of the specified PCI device
+*
+* only header 0 .
+*
+*/
+
+int pciGetHeader0(PCI_HEADER_DEVICE * pD,int BusDevFunc)
+{
+  pD->headerType = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+
+  if ((pD->headerType&0x7F)!=0)                /* Not a Header 0 type */
+       return FALSE;
+  else                                 /* PCI device */
+  {
+       pD->vendorId      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_VENDOR_ID, 2);
+       pD->deviceId      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEVICE_ID, 2);
+       pD->command       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_COMMAND, 2);
+       pD->status        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_STATUS, 1);
+       pD->revisionId    = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_REVISION, 1);
+       pD->progIf        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_PROGRAMMING_IF, 1);
+       pD->subClass      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUBCLASS, 1);
+       pD->classCode     = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CLASS, 1);
+       pD->cacheLine     = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CACHE_LINE_SIZE, 1);
+       pD->latency       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_LATENCY_TIMER, 1);
+       pD->headerType    = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_HEADER_TYPE, 1);
+       pD->bist          = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BIST, 1);
+       pD->base0         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_0, 4);
+       pD->base1         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_1, 4);
+       pD->base2         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_2, 4);
+       pD->base3         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_3, 4);
+       pD->base4         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_4, 4);
+       pD->base5         = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_BASE_ADDRESS_5, 4);
+       pD->cis           = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_CIS, 4);
+       pD->subVendorId   = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_VENDER_ID, 2);
+       pD->subSystemId   = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_SUB_SYSTEM_ID, 2);
+       pD->romBase       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_EXPANSION_ROM, 4);
+       pD->intLine       = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_LINE, 1);
+       pD->intPin        = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_DEV_INT_PIN, 1);
+       pD->minGrant      = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MIN_GRANT, 1);
+       pD->maxLatency    = PCI_Read_CFG_Reg(BusDevFunc, PCI_CFG_MAX_LATENCY, 1);
+  }
+  return TRUE;
+}
+
+/*******************************************************************************
+*
+* pciGetResource - gets the Resource information of the specified PCI device
+*
+* 
+*
+*/
+int pciGetResource(PCI_RESOURCE_DESC * pR)
+{
+       PCI_HEADER_DEVICE headerDevice;
+  int                                                  basereg, i;
+  unsigned long  AddrDesc;
+  
+
+       if(pciGetHeader0(&headerDevice,pR->BusDevFunc)==FALSE)
+               return FALSE; /* no header 0 type */
+       /* fill in read only fields */
+       pR->vendorId = headerDevice.vendorId;
+       pR->deviceId = headerDevice.deviceId;
+       pR->revisionId = headerDevice.revisionId;
+       pR->classCode = headerDevice.classCode;
+       pR->subClass = headerDevice.subClass;
+       pR->progIf = headerDevice.progIf;
+       pR->intLine = headerDevice.intLine;
+       pR->intPin = headerDevice.intPin;
+       pR->headerType = headerDevice.headerType;
+       pR->pciInt = 0; /* no Interrupt as default */
+       /* calculate the PCI Interrupt if any.. */
+       if(pR->intPin!=0)
+       {       
+               /* interrupts are routed as follows:
+                  - Device 6, INTA# = INTA#
+                  - Device 7, INTA# = INTB#
+                  - Device 8, INTA# = INTC#
+                  - Device 9, INTA# = INTD#
+                  - Device A, INTA# = INTA#
+                  - Device 0 must be INTA# = INTC# */
+               i=(pR->BusDevFunc >> 11) & 0x1F; /* max 32 devices (Bus nr not yet implemented) */
+               i=i%4; /* dev0 and INTA# = INTC#  */
+               i+=1; /* Adjust it (first step) */
+               i+=pR->intPin;
+               pR->pciInt=(char)((i%4)+1); /* 2nd step  */
+       }
+       /* try to get memory or io descriptions */
+       for (basereg = 0; basereg < MAX_PCI_BASE_REG; basereg++)
+  {
+       pR->size[basereg]=0; /* delete size */
+               pR->attr[basereg]=DESC_IS_NOT_VALID;
+               PCI_Write_CFG_Reg(pR->BusDevFunc, PCIBASEADDR0 + (4*basereg), 0xFFFFFFFF,4);
+    AddrDesc = PCI_Read_CFG_Reg(pR->BusDevFunc, PCIBASEADDR0 + (4*basereg), 4);
+    if (AddrDesc == 0)                   /* unimplemented, stop looking */
+                       continue;               
+               if ((AddrDesc&0x3)==0x1) /* is IO */
+               {
+                       pR->attr[basereg]=DESC_IS_IO;
+                       /* determine size, all bytes which are don't care are 0 */
+                       AddrDesc&=0xFFFFFFFC; /* delete Atributes */
+                       AddrDesc=~AddrDesc;
+                       AddrDesc&=0x0000FFFF; /* Mask unused bits                        */
+                       pR->size[basereg]=AddrDesc+1; /* size  */
+               } 
+               else
+               {
+                       pR->attr[basereg]=DESC_IS_MEM;
+                       switch((AddrDesc&0x6)>>1)
+                       {
+                               case 0x1: 
+                                       pR->attr[basereg]|=DESC_IS_LOWMEM;  /* locate it below 1M */
+                                       break;
+                               case 0x2:
+                                       pR->attr[basereg]|=DESC_IS_64BIT;  /* dual Address.. increment base reg later */
+                                       break;
+                               case 0x3:
+                                       pR->attr[basereg]=DESC_IS_NOT_VALID;  /* Error */
+                                       break;
+                       } /* case */
+                       if((AddrDesc&0x8)==0x8) /* is prefetchable */
+                               pR->attr[basereg]|=DESC_IS_PREFETCH;
+                       /* 64Bit addressing not implemented */
+                       if((pR->attr[basereg]&DESC_IS_64BIT)==DESC_IS_64BIT)
+                       {
+                               basereg++;
+                               if(basereg<MAX_PCI_BASE_REG)
+                               {
+                               pR->size[basereg]=0; /* delete size */
+                                       pR->attr[basereg]=DESC_IS_NOT_VALID;
+                               }
+                               continue;
+                       } /* if DESC_IS_64BIT */
+                       /* determine size                        */
+                       AddrDesc&=0xFFFFFFF0;/* delete attributes */
+                       AddrDesc=~AddrDesc; 
+                       pR->size[basereg]=AddrDesc+1; /* size  */
+               } /* else  */
+       } /* for        basereg */
+       return TRUE;    
+}
+
+#if 0
+/*************************************************************************************
+* pcishowrees
+*/
+void pciShowRes(PCI_RESOURCE_DESC *pD)
+{
+       int i, match;
+       printf("%02d:%02d:%02d ",(char)(pD->BusDevFunc>>16)&0xFF,
+       (char)(pD->BusDevFunc>>11)&0x1F,(char)(pD->BusDevFunc>>8)&0x3);
+
+       /* search memory desc */
+       match=0;
+       for(i=0;i<MAX_PCI_BASE_REG;i++)
+       {
+               if((pD->attr[i]&DESC_IS_IO)==DESC_IS_IO)
+               {
+                       printf("%4lX ",pD->size[i]);
+                       match=1;
+               }       
+       }
+       if(match==0)
+               printf("     ");
+       match=0;
+       for(i=0;i<MAX_PCI_BASE_REG;i++)
+       {
+               if((pD->attr[i]&DESC_IS_MEM)==DESC_IS_MEM)
+               {
+                       printf("%8lX ",pD->size[i]);
+                       match=1;
+               }       
+       }
+       if(match==0)
+               printf("         ");
+       if(pD->intPin==0)
+               printf("      ");
+       else 
+               printf("INT%c# ",(pD->pciInt + 'A')-1);
+       switch (pD->classCode)
+       {
+               case 0x00: 
+                       switch(pD->subClass)
+                       {
+                               case 0: printf("not VGA"); break;
+                               case 1: printf("VGA"); break;
+                               default: printf("unknown"); break;
+                       }
+                       printf("Pre Class: "); 
+                       break;
+               case 0x01: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("SCSI "); break;
+                               case 0x01: printf("IDE "); break;
+                               case 0x02: printf("Floppy "); break;
+                               case 0x03: printf("IPI "); break;
+                               case 0x04: printf("RAID "); break;
+                               case 0x88: printf("other "); break;
+                               default: printf("unknown "); break;
+                       }
+                       printf("Mass Storage ");
+                       break;
+               case 0x02: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("Ethernet"); break;
+                               case 0x01: printf("Token Ring"); break;
+                               case 0x02: printf("FDDI"); break;
+                               case 0x03: printf("ATM"); break;
+                               case 0x80: printf("other"); break;
+                               default: printf("unknown"); break;
+                       }
+                       printf(" Network Controller ");
+                       break;
+               case 0x03: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("%s",((pD->progIf&0x1)==0x1)? "8514 comp":"VGA"); break;
+                               case 0x01: printf("XGA"); break;
+                               case 0x80: printf("other"); break;
+                               default: printf("unknown"); break;
+                       }
+                       printf(" Display Cont. ");
+                       break;
+               case 0x04: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("Video"); break;
+                               case 0x01: printf("Audio"); break;
+                               case 0x80: printf("other"); break;
+                               default: printf("unknown"); break;
+                       }
+                       printf(" Multimedia Device ");
+                       break;
+               case 0x05: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("RAM"); break;
+                               case 0x01: printf("Flash"); break;
+                               case 0x80: printf("other"); break;
+                               default: printf("unknown"); break;
+                       }
+                       printf(" Memory Device ");
+                       break;
+               case 0x06: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("HostBridge"); break;
+                               case 0x01: printf("ISA"); break;
+                               case 0x02: printf("EISA"); break;
+                               case 0x03: printf("MCA"); break;
+                               case 0x04: printf("PCI-PCI"); break;
+                               case 0x05: printf("PCMCIA"); break;
+                               case 0x06: printf("NuBus"); break;
+                               case 0x07: printf("CardBus"); break;
+                               case 0x80: printf("other"); break;
+                               default: printf("unknown"); break;
+                       }
+                       printf(" Bridge ");
+                       break;
+               case 0x07: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00:
+                                       switch(pD->progIf)
+                                       {
+                                               case 0: printf("Generic XT Serial Controller ");break;
+                                               case 1: printf("16450 Serial Controller ");break;
+                                               case 2: printf("16550 Serial Controller ");break;
+                                               default:        printf("unknown Serial Controller ");break;
+                                       }
+                                       break;
+                               case 0x01:
+                                       switch(pD->progIf)
+                                       {
+                                               case 0: printf("Paralell Port ");break;
+                                               case 1: printf("Bidirectional Paralell Port ");break;
+                                               case 2: printf("ECP 1.X Paralell Port ");break;
+                                               default:        printf("unknown Paralall Port ");break;
+                                       }
+                                       break;
+                               case 0x80: printf("other Simple Communications Controller "); break;
+                               default: printf("unknown Simple Communications Controller "); break;
+                       }
+                       break;
+               case 0x08: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00:
+                                       switch(pD->progIf)
+                                       {
+                                               case 0: printf("Generic 8259 PIC ");break;
+                                               case 1: printf("ISA PIC ");break;
+                                               case 2: printf("EISA PIC ");break;
+                                               default:        printf("unknown PIC ");break;
+                                       }
+                                       break;
+                               case 0x01:
+                                       switch(pD->progIf)
+                                       {
+                                               case 0: printf("Generic 8237 DMA ");break;
+                                               case 1: printf("ISA DMA ");break;
+                                               case 2: printf("EISA DMA ");break;
+                                               default:        printf("unknown DMA ");break;
+                                       }
+                                       break;
+                               case 0x02:
+                                       switch(pD->progIf)
+                                       {
+                                               case 0: printf("Generic 8254 Timer ");break;
+                                               case 1: printf("ISA Timer ");break;
+                                               case 2: printf("EISA Timer ");break;
+                                               default:        printf("unknown Timer ");break;
+                                       }
+                                       break;
+                               case 0x03:
+                                       switch(pD->progIf)
+                                       {
+                                               case 0: printf("Generic RTC ");break;
+                                               case 1: printf("ISA RTC ");break;
+                                               default:        printf("unknown RTC ");break;
+                                       }
+                                       break;
+                               case 0x80: printf("other Generic System Peripherals "); break;
+                               default: printf("unknown Generic System Peripherals "); break;
+                       }
+                       break;
+               case 0x09: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("Keyboard Controller "); break;
+                               case 0x01: printf("Digitizer "); break;
+                               case 0x02: printf("Mouse "); break;
+                               case 0x80: printf("other Input Device "); break;
+                               default: printf("unknown Input Device "); break;
+                       }
+                       break;
+               case 0x0A: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("Generic Docking Station "); break;
+                               case 0x80: printf("other Docking Device "); break;
+                               default: printf("unknown Docking Device "); break;
+                       }
+                       break;
+               case 0x0B: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("386 "); break;
+                               case 0x01: printf("486 "); break;
+                               case 0x02: printf("Pentium "); break;
+                               case 0x10: printf("Alpha "); break;
+                               case 0x20: printf("PowerPC "); break;
+                               case 0x40: printf("Co-"); break;
+                               default: printf("unknown "); break;
+                       }
+                       printf("Processor ");
+                       break;
+               case 0x0C: 
+                       switch(pD->subClass)
+                       {
+                               case 0x00: printf("FireWire "); break;
+                               case 0x01: printf("ACCESS.bus "); break;
+                               case 0x02: printf("SSA "); break;
+                               case 0x03: printf("USB "); break;
+                               case 0x04: printf("Fibre Channel "); break;
+                               default: printf("unknown Serial Bus "); break;
+                       }
+                       break;
+       } /* Switch */
+       printf("\n");
+}
+
+#endif
+
+#if 0
+/**************************************************************************************
+* pciScanforDevices
+*/
+
+void pciScanForDevices(int BusNum)
+{
+       
+       PCI_RESOURCE_DESC resourcedesc;
+  int Device,Function,BusDevFunc;
+  unsigned short vendor_id,vendor_id2;
+  
+  printf("PCI        IO   Memory   IRQ Device\n");
+  /*      00:00:00 1234 12345678 INTA# DD */
+       for (Device = 1; Device < MAX_PCI_DEVICES; Device++)
+       {
+               BusDevFunc = (BusNum << 16) | (Device << 11); /* scan only function 0 */
+               vendor_id = PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID,2);
+               if (vendor_id != 0xFFFF)
+               {
+                       
+                       for(Function=0;Function<MAX_PCI_FUNCTIONS; Function++)
+                       {
+                               BusDevFunc=(BusNum << 16) | (Device << 11) | (Function << 8);
+                               vendor_id2=PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID,2);
+                               if(vendor_id!=vendor_id2)
+                                       break;  
+                               resourcedesc.BusDevFunc=BusDevFunc;
+                               /* found a device, get resource desc */
+                               if(pciGetResource(&resourcedesc)==FALSE) /* no Header type 0 */
+                               {
+                                       printf("%02d:%02d:%02d No compatible Header\n",
+                                               BusNum,Device,Function);
+                                       /* Function = MAX_PCI_FUNTIONS; */ /* to prevent further scanning on this dev */
+                                       break;
+                               }
+                               pciShowRes(&resourcedesc);
+                               
+                               if(((resourcedesc.headerType&0x80)!=0x80)&&(Function==0))
+                                       break; /* single function Device */
+                       } /* for Function */
+               } /* if device found */
+       } /* for Device */
+}                      
+#endif
+
+
+
+
+
+#endif /* CONFIG_COMMANDS & CFG_CMD_PCI */
+
+#endif /* CONFIG_PCI */
+
+#endif /* CONFIG_405GP */
diff --git a/board/mpl/common/pci.h b/board/mpl/common/pci.h
new file mode 100644 (file)
index 0000000..ab92dcb
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+
+#ifndef _PCI_H
+#define _PCI_H
+
+
+
+#define TRUE 1
+#define FALSE 0                
+#define MAX_PCI_BASE_REG       6 /* max six mem description per PCI dev */
+#define DESC_IS_IO                             1 /* IO Attribute */
+#define DESC_IS_MEM                            2 /* Memory attribute     */
+#define DESC_IS_PREFETCH       4 /* Memory is Prefetchable */
+#define DESC_IS_LOWMEM         8 /* locate below 1M */
+#define DESC_IS_64BIT                  0x10 /* dual address cycles */
+#define DESC_IS_NOT_VALID      0 /* Memory description is nat valid    */
+
+/*----------------------------------------------------------------------------+
+| 405GP PCI core memory map defines.
++----------------------------------------------------------------------------*/
+#define MIN_PCI_MEMADDR1    0x80000000
+#define MIN_PCI_MEMADDR2    0x00000000
+#define MIN_PLB_PCI_IOADDR  0xE8000000  /* PLB side of PCI I/O address space */
+#define MIN_PCI_PCI_IOADDR1 0x00000000  /* PCI side of PCI I/O address space */
+#define MAX_PCI_PCI_IOADDR1 0x00010000  /* PCI side of PCI I/O address space */
+#define MIN_PCI_PCI_IOADDR2 0x00800000  /* PCI side of PCI I/O address space */
+#define MAX_PCI_DEVICES     32
+#define MAX_PCI_FUNCTIONS              7
+/*----------------------------------------------------------------------------+
+| Defines for the 405GP PCI Config address and data registers followed by
+| defines for the standard PCI device configuration header.
++----------------------------------------------------------------------------*/
+#define PCICFGADR       0xEEC00000
+#define PCICFGDATA      0xEEC00004
+
+#define PCIVENDORID     0x00
+#define PCIDEVICEID     0x02
+#define PCICMD          0x04
+  #define SERR_EN       0x0100
+  #define BM_EN         0x0004
+  #define MEM_EN        0x0002
+  #define IO_EN         0x0001
+#define PCISTATUS       0x06
+  #define CAPABLE_66MHZ 0x0020
+#define PCIREVID        0x08
+#define PCICLASSPI      0x09
+#define PCICLASSCODE    0x0A
+#define PCICACHELINE    0x0C
+#define PCILATENCYTIM   0x0D
+#define PCIHEADERTYPE   0x0E
+#define PCIBIST         0x0F
+#define PCIBASEADDR0    0x10
+#define PCIBASEADDR1    0x14
+#define PCIBASEADDR2    0x18
+#define PCISSVENDORID   0x2C
+#define PCISSDEVICEID   0x2E
+#define PCIINTLINE      0x3C
+#define PCIINTPIN       0x3D
+#define PCIMINGRANT     0x3E
+#define PCIMAXLATENCY   0x3F
+
+#define PCIBUSNUM       0x40        /* 405GP specific parameters */
+#define PCISUBBUSNUM    0x41
+#define PCIDISCOUNT     0x42
+#define PCIBRDGOPT1     0x4A
+#define PCIBRDGOPT2     0x60
+
+/*----------------------------------------------------------------------------+
+| Defines for 405GP PCI Master local configuration regs.
++----------------------------------------------------------------------------*/
+#define PMM0LA          0xEF400000
+#define PMM0MA          0xEF400004
+#define PMM0PCILA       0xEF400008
+#define PMM0PCIHA       0xEF40000C
+#define PMM1LA          0xEF400010
+#define PMM1MA          0xEF400014
+#define PMM1PCILA       0xEF400018
+#define PMM1PCIHA       0xEF40001C
+#define PMM2LA          0xEF400020
+#define PMM2MA          0xEF400024
+#define PMM2PCILA       0xEF400028
+#define PMM2PCIHA       0xEF40002C
+
+/*----------------------------------------------------------------------------+
+| Defines for 405GP PCI Target local configuration regs.
++----------------------------------------------------------------------------*/
+#define PTM1MS          0xEF400030
+#define PTM1LA          0xEF400034
+#define PTM2MS          0xEF400038
+#define PTM2LA          0xEF40003C
+
+/*-----------------------------------------------------------------------------+
+|       PCI-PCI bridge header
++-----------------------------------------------------------------------------*/
+#define PCIPCI_PRIMARYBUS       0x18
+#define PCIPCI_SECONDARYBUS     0x19
+#define PCIPCI_SUBORDINATEBUS   0x1A
+#define PCIPCI_SECONDARYLATENCY 0x1B
+#define PCIPCI_IOBASE           0x1C
+#define PCIPCI_IOLIMIT          0x1D
+#define PCIPCI_SECONDARYSTATUS  0x1E
+#define PCIPCI_MEMBASE          0x20
+#define PCIPCI_MEMLIMIT         0x22
+#define PCIPCI_PREFETCHMEMBASE  0x24
+#define PCIPCI_PREFETCHMEMLIMIT 0x26
+#define PCIPCI_IOBASEUPPER16    0x30
+#define PCIPCI_IOLIMITUPPER16   0x32
+
+#define PCIDEVID_405GP         0x0
+
+/* Standard device configuration register offsets */
+/* Note that only modulo-4 addresses are written to the address register */
+
+#define        PCI_CFG_VENDOR_ID       0x00
+#define        PCI_CFG_DEVICE_ID       0x02
+#define        PCI_CFG_COMMAND         0x04
+#define        PCI_CFG_STATUS          0x06
+#define        PCI_CFG_REVISION        0x08
+#define        PCI_CFG_PROGRAMMING_IF  0x09
+#define        PCI_CFG_SUBCLASS        0x0a
+#define        PCI_CFG_CLASS           0x0b
+#define        PCI_CFG_CACHE_LINE_SIZE 0x0c
+#define        PCI_CFG_LATENCY_TIMER   0x0d
+#define        PCI_CFG_HEADER_TYPE     0x0e
+#define        PCI_CFG_BIST            0x0f
+#define        PCI_CFG_BASE_ADDRESS_0  0x10
+#define        PCI_CFG_BASE_ADDRESS_1  0x14
+#define        PCI_CFG_BASE_ADDRESS_2  0x18
+#define        PCI_CFG_BASE_ADDRESS_3  0x1c
+#define        PCI_CFG_BASE_ADDRESS_4  0x20
+#define        PCI_CFG_BASE_ADDRESS_5  0x24
+#define        PCI_CFG_CIS             0x28
+#define        PCI_CFG_SUB_VENDER_ID   0x2c
+#define        PCI_CFG_SUB_SYSTEM_ID   0x2e
+#define        PCI_CFG_EXPANSION_ROM   0x30
+#define        PCI_CFG_RESERVED_0      0x34
+#define        PCI_CFG_RESERVED_1      0x38
+#define        PCI_CFG_DEV_INT_LINE    0x3c
+#define        PCI_CFG_DEV_INT_PIN     0x3d
+#define        PCI_CFG_MIN_GRANT       0x3e
+#define        PCI_CFG_MAX_LATENCY     0x3f
+#define PCI_CFG_SPECIAL_USE     0x41
+#define PCI_CFG_MODE            0x43
+
+
+/* PCI-to-PCI bridge configuration register offsets */
+/* Note that only modulo-4 addresses are written to the address register */
+
+#define        PCI_CFG_PRIMARY_BUS     0x18
+#define        PCI_CFG_SECONDARY_BUS   0x19
+#define        PCI_CFG_SUBORDINATE_BUS 0x1a
+#define        PCI_CFG_SEC_LATENCY     0x1b
+#define        PCI_CFG_IO_BASE         0x1c
+#define        PCI_CFG_IO_LIMIT        0x1d
+#define        PCI_CFG_SEC_STATUS      0x1e
+#define        PCI_CFG_MEM_BASE        0x20
+#define        PCI_CFG_MEM_LIMIT       0x22
+#define        PCI_CFG_PRE_MEM_BASE    0x24
+#define        PCI_CFG_PRE_MEM_LIMIT   0x26
+#define        PCI_CFG_PRE_MEM_BASE_U  0x28
+#define        PCI_CFG_PRE_MEM_LIMIT_U 0x2c
+#define        PCI_CFG_IO_BASE_U       0x30
+#define        PCI_CFG_IO_LIMIT_U      0x32
+#define        PCI_CFG_ROM_BASE        0x38
+#define        PCI_CFG_BRG_INT_LINE    0x3c
+#define        PCI_CFG_BRG_INT_PIN     0x3d
+#define        PCI_CFG_BRIDGE_CONTROL  0x3e
+
+
+/***********************************************************************
+ * 405GP PCI Master configuration.
+ * Map one 512 MB range of PLB/processor addresses to PCI memory space.
+ *   PLB address 0x80000000-0x9FFFFFFF ==> PCI address 0x80000000-0x9FFFFFFF
+ *   Use byte reversed out routines to handle endianess.
+ ***********************************************************************/
+#define PCI_M0_LOCAL_ADDR      0x80000000
+#define PCI_M0_PCI_LOW_ADDR    0x80000000
+#define PCI_M0_PCI_HIGH_ADDR   0x00000000
+#define PCI_M0_MASK_ATTRIB     0xE0000001  /* no prefetching, and enable region */
+/**************************************************************************
+ * Map one 512 MB range of PLB/processor addresses to PCI memory space.
+ * PLB address 0xA0000000-0xBFFFFFFF ==> PCI address 0x00000000-0x1FFFFFFF
+ * This space is for the VGA card.
+ **************************************************************************/
+#define PCI_M1_LOCAL_ADDR      0xA0000000
+#define PCI_M1_PCI_LOW_ADDR    0x00000000
+#define PCI_M1_PCI_HIGH_ADDR   0x00000000
+#define PCI_M1_MASK_ATTRIB     0xE0000001  /* no prefetching, and enable region */
+/***************************************************************************
+ * PMM2 is not used.  Initialize them to zero.
+ *****************************************************************************/
+#define PCI_M2_LOCAL_ADDR      0x00000000
+#define PCI_M2_PCI_LOW_ADDR    0x00000000
+#define PCI_M2_PCI_HIGH_ADDR   0x00000000
+#define PCI_M2_MASK_ATTRIB     0x00000000  /* not enabled */
+
+typedef struct pciHeaderDevice
+{
+       short   vendorId;       /* vendor ID */
+       short   deviceId;       /* device ID */
+       short   command;        /* command register */
+       short   status;         /* status register */
+       char    revisionId;     /* revision ID */
+       char    classCode;      /* class code */
+       char    subClass;       /* sub class code */
+       char    progIf;         /* programming interface */
+       char    cacheLine;      /* cache line */
+       char    latency;        /* latency time */
+       char    headerType;     /* header type */
+       char    bist;           /* BIST */
+       int     base0;          /* base address 0 */
+       int     base1;          /* base address 1 */
+       int     base2;          /* base address 2 */
+       int     base3;          /* base address 3 */
+       int     base4;          /* base address 4 */
+       int     base5;          /* base address 5 */
+       int     cis;            /* cardBus CIS pointer */
+       short   subVendorId;    /* sub system vendor ID */
+       short   subSystemId;    /* sub system ID */
+       int     romBase;        /* expansion ROM base address */
+       int     reserved0;      /* reserved */
+       int     reserved1;      /* reserved */
+       char    intLine;        /* interrupt line */
+       char    intPin;         /* interrupt pin */
+       char    minGrant;       /* min Grant */
+       char    maxLatency;     /* max Latency */
+} PCI_HEADER_DEVICE;
+
+typedef struct pciHeaderBridge
+{
+    short      vendorId;       /* vendor ID */
+    short      deviceId;       /* device ID */
+    short      command;        /* command register */
+    short      status;         /* status register */
+    char       revisionId;     /* revision ID */
+    char       classCode;      /* class code */
+    char       subClass;       /* sub class code */
+    char       progIf;         /* programming interface */
+    char       cacheLine;      /* cache line */
+    char       latency;        /* latency time */
+    char       headerType;     /* header type */
+    char       bist;           /* BIST */
+    int                base0;          /* base address 0 */
+    int                base1;          /* base address 1 */
+    char       priBus;         /* primary bus number */
+    char       secBus;         /* secondary bus number */
+    char       subBus;         /* subordinate bus number */
+    char       secLatency;     /* secondary latency timer */
+    char       ioBase;         /* IO base */
+    char       ioLimit;        /* IO limit */
+    short      secStatus;      /* secondary status */
+    short      memBase;        /* memory base */
+    short      memLimit;       /* memory limit */
+    short      preBase;        /* prefetchable memory base */
+    short      preLimit;       /* prefetchable memory limit */
+    int                preBaseUpper;   /* prefetchable memory base upper 32 bits */
+    int                preLimitUpper;  /* prefetchable memory base upper 32 bits */
+    short      ioBaseUpper;    /* IO base upper 16 bits */
+    short      ioLimitUpper;   /* IO limit upper 16 bits */
+    int                reserved;       /* reserved */
+    int                romBase;        /* expansion ROM base address */
+    char       intLine;        /* interrupt line */
+    char       intPin;         /* interrupt pin */
+    short      control;        /* bridge control */
+    } PCI_HEADER_BRIDGE;
+
+
+typedef struct pciRecourceDesc
+{
+       unsigned long   BusDevFunc; /* location of the device */
+       short   vendorId;               /* vendor ID */
+       short   deviceId;               /* device ID */
+       char    revisionId;     /* revision ID */
+       char    classCode;      /* class code */
+       char    subClass;               /* sub class code */
+       char    progIf;         /* programming interface */
+       char    headerType;     /* header type */
+       unsigned long           size[MAX_PCI_BASE_REG];         /* memory sizes */
+       char    attr[MAX_PCI_BASE_REG];         /* memory attributes */
+       char    intLine;        /* interrupt line */
+       char    intPin;         /* interrupt pin */
+       char    pciInt;         /* Pci Interrupt Line ( 0 = no, 1 = A...)*/
+} PCI_RESOURCE_DESC;
+
+
+/* table for PCI Initialization */
+
+typedef struct {
+       const int index;
+       const unsigned long val;
+       const int with;
+} PCI_CFG_TABLE;
+
+
+typedef struct {
+       int             index;  /* address */
+       unsigned long   val;    /* value */
+       int             width;  /* data size */
+}PCI_FCN_CFG_TABLE;
+
+typedef struct {
+       unsigned short  vendorID;       /* Vendor ID */
+       unsigned short  deviceID;       /* Device ID */
+       unsigned char   revision;       /* Device ID */
+       unsigned char   func;           /* Function number */
+       PCI_FCN_CFG_TABLE fcntable[10];
+}PCI_DEV_CFG_TABLE;
+
+
+unsigned long    PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width);
+int    PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned long Value, int Width);
+void  PCI_Scan(int BusNum);
+void  PCI_Config_Device(int BusDevFunc, int NumBaseAddr);
+void  PCI_Config_VGA_Device(int BusDevFunc, int NumBaseAddr);
+void  PCI_Config_Bridge(int BusDevFunc);
+void  PCI_Dump_Device(int BusDevFunc);
+int   PCI_Find_Device(unsigned short VendorID, unsigned short DeviceID);
+void  pciHeaderShow(int BusDevFunc);
+void  pciDheaderPrint(PCI_HEADER_DEVICE * pD);
+void  pciBheaderPrint(PCI_HEADER_BRIDGE * pB);
+void  PCI_Config_ISABridge(int BusDevFunc);
+void  PCI_Config_VGA_contrl(int BusDevFunc);
+
+void pciScanForDevices(int BusNum);
+void pciShowRes(PCI_RESOURCE_DESC *pd);
+int pciGetResource(PCI_RESOURCE_DESC * pR);
+int pciGetHeader0(PCI_HEADER_DEVICE * pD,int BusDevFunc);
+
+/***************************************************************************
+* Defines PIIX4 Config Registers
+****************************************************************************/
+
+/* Function 0 ISA Bridge */
+#define        PCI_CFG_PIIX4_IORT              0x4C    /* 8 bit ISA Recovery Timer Reg (default 0x4D) */
+#define        PCI_CFG_PIIX4_XBCS              0x4E    /* 16 bit XBus Chip select reg (default 0x0003) */
+#define        PCI_CFG_PIIX4_PIRQC             0x60  /* PCI IRQ Route Register 4 x 8bit (default )*/
+#define        PCI_CFG_PIIX4_SERIRQ    0x64
+#define        PCI_CFG_PIIX4_TOM                       0x69
+#define        PCI_CFG_PIIX4_MSTAT             0x6A
+#define        PCI_CFG_PIIX4_MBDMA             0x76
+#define        PCI_CFG_PIIX4_APICBS    0x80
+#define        PCI_CFG_PIIX4_DLC                       0x82
+#define        PCI_CFG_PIIX4_PDMACFG   0x90
+#define        PCI_CFG_PIIX4_DDMABS    0x92
+#define        PCI_CFG_PIIX4_GENCFG    0xB0
+#define        PCI_CFG_PIIX4_RTCCFG    0xCB
+
+/* IO Addresses */
+#define PIIX4_ISA_DMA1_CH0BA   0x00
+#define PIIX4_ISA_DMA1_CH0CA   0x01
+#define PIIX4_ISA_DMA1_CH1BA   0x02
+#define PIIX4_ISA_DMA1_CH1CA   0x03
+#define PIIX4_ISA_DMA1_CH2BA   0x04
+#define PIIX4_ISA_DMA1_CH2CA   0x05
+#define PIIX4_ISA_DMA1_CH3BA   0x06
+#define PIIX4_ISA_DMA1_CH3CA   0x07
+#define PIIX4_ISA_DMA1_CMDST   0x08
+#define PIIX4_ISA_DMA1_REQ             0x09
+#define PIIX4_ISA_DMA1_WSBM            0x0A
+#define PIIX4_ISA_DMA1_CH_MOD  0x0B
+#define PIIX4_ISA_DMA1_CLR_PT  0x0C
+#define PIIX4_ISA_DMA1_M_CLR   0x0D
+#define PIIX4_ISA_DMA1_CLR_M   0x0E
+#define PIIX4_ISA_DMA1_RWAMB   0x0F
+
+#define PIIX4_ISA_DMA2_CH0BA   0xC0
+#define PIIX4_ISA_DMA2_CH0CA   0xC1
+#define PIIX4_ISA_DMA2_CH1BA   0xC2
+#define PIIX4_ISA_DMA2_CH1CA   0xC3
+#define PIIX4_ISA_DMA2_CH2BA   0xC4
+#define PIIX4_ISA_DMA2_CH2CA   0xC5
+#define PIIX4_ISA_DMA2_CH3BA   0xC6
+#define PIIX4_ISA_DMA2_CH3CA   0xC7
+#define PIIX4_ISA_DMA2_CMDST   0xD0
+#define PIIX4_ISA_DMA2_REQ             0xD2
+#define PIIX4_ISA_DMA2_WSBM            0xD4
+#define PIIX4_ISA_DMA2_CH_MOD  0xD6
+#define PIIX4_ISA_DMA2_CLR_PT  0xD8
+#define PIIX4_ISA_DMA2_M_CLR   0xDA
+#define PIIX4_ISA_DMA2_CLR_M   0xDC
+#define PIIX4_ISA_DMA2_RWAMB   0xDE
+
+#define PIIX4_ISA_INT1_ICW1            0x20
+#define PIIX4_ISA_INT1_OCW2            0x20
+#define PIIX4_ISA_INT1_OCW3            0x20
+#define PIIX4_ISA_INT1_ICW2            0x21
+#define PIIX4_ISA_INT1_ICW3            0x21
+#define PIIX4_ISA_INT1_ICW4            0x21
+#define PIIX4_ISA_INT1_OCW1            0x21
+
+#define PIIX4_ISA_INT1_ELCR            0x4D0
+
+#define PIIX4_ISA_INT2_ICW1            0xA0
+#define PIIX4_ISA_INT2_OCW2            0xA0
+#define PIIX4_ISA_INT2_OCW3            0xA0
+#define PIIX4_ISA_INT2_ICW2            0xA1
+#define PIIX4_ISA_INT2_ICW3            0xA1
+#define PIIX4_ISA_INT2_ICW4            0xA1
+#define PIIX4_ISA_INT2_OCW1            0xA1
+#define PIIX4_ISA_INT2_IMR             0xA1 /* read only */
+
+#define PIIX4_ISA_INT2_ELCR            0x4D1
+
+#define PIIX4_ISA_TMR0_CNT_ST  0x40
+#define PIIX4_ISA_TMR1_CNT_ST  0x41
+#define PIIX4_ISA_TMR2_CNT_ST  0x42
+#define PIIX4_ISA_TMR_TCW                      0x43
+
+#define PIIX4_ISA_RST_XBUS             0x60
+
+#define PIIX4_ISA_NMI_CNT_ST   0x61
+#define PIIX4_ISA_NMI_ENABLE   0x70
+
+#define PIIX4_ISA_RTC_INDEX            0x70
+#define PIIX4_ISA_RTC_DATA             0x71
+#define PIIX4_ISA_RTCEXT_IND   0x70
+#define PIIX4_ISA_RTCEXT_DATA  0x71
+
+#define PIIX4_ISA_DMA1_CH2LPG  0x81
+#define PIIX4_ISA_DMA1_CH3LPG  0x82
+#define PIIX4_ISA_DMA1_CH1LPG  0x83
+#define PIIX4_ISA_DMA1_CH0LPG  0x87
+#define PIIX4_ISA_DMA2_CH2LPG  0x89
+#define PIIX4_ISA_DMA2_CH3LPG  0x8A
+#define PIIX4_ISA_DMA2_CH1LPG  0x8B
+#define PIIX4_ISA_DMA2_LPGRFR  0x8F
+
+#define PIIX4_ISA_PORT_92                      0x92
+
+#define PIIX4_ISA_APM_CONTRL   0xB2
+#define PIIX4_ISA_APM_STATUS   0xB3
+
+#define PIIX4_ISA_COCPU_ERROR  0xF0
+
+/* Function 1 IDE Controller */
+#define        PCI_CFG_PIIX4_BMIBA             0x20
+#define        PCI_CFG_PIIX4_IDETIM    0x40
+#define        PCI_CFG_PIIX4_SIDETIM   0x44
+#define        PCI_CFG_PIIX4_UDMACTL   0x48
+#define        PCI_CFG_PIIX4_UDMATIM 0x4A
+
+/* Function 2 USB Controller */
+#define        PCI_CFG_PIIX4_SBRNUM    0x60
+#define        PCI_CFG_PIIX4_LEGSUP    0xC0
+
+/* Function 3 Power Management */
+#define        PCI_CFG_PIIX4_PMAB              0x40
+#define        PCI_CFG_PIIX4_CNTA              0x44
+#define        PCI_CFG_PIIX4_CNTB              0x48
+#define        PCI_CFG_PIIX4_GPICTL    0x4C
+#define        PCI_CFG_PIIX4_DEVRESD   0x50
+#define        PCI_CFG_PIIX4_DEVACTA   0x54
+#define        PCI_CFG_PIIX4_DEVACTB   0x58
+#define        PCI_CFG_PIIX4_DEVRESA   0x5C
+#define        PCI_CFG_PIIX4_DEVRESB   0x60
+#define        PCI_CFG_PIIX4_DEVRESC   0x64
+#define        PCI_CFG_PIIX4_DEVRESE   0x68
+#define        PCI_CFG_PIIX4_DEVRESF   0x6C
+#define        PCI_CFG_PIIX4_DEVRESG   0x70
+#define        PCI_CFG_PIIX4_DEVRESH   0x74
+#define        PCI_CFG_PIIX4_DEVRESI   0x78
+
+
+#endif
diff --git a/board/mpl/common/pci_parts.h b/board/mpl/common/pci_parts.h
new file mode 100644 (file)
index 0000000..2be4141
--- /dev/null
@@ -0,0 +1,131 @@
+ /*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#ifndef _PCI_PARTS_H_
+#define _PCI_PARTS_H_
+
+
+/* Board specific file containing:
+ * - PCI Memory Mapping
+ * - PCI IO Mapping
+ * - PCI Interrupt Mapping
+ */
+
+/* PIP405 PCI INT Routing:
+ *                      IRQ0  VECTOR
+ * PIXX4 IDSEL  = AD16  INTA#  28 (Function 2 USB is INTD# = 31)
+ * VGA   IDSEL  = AD17  INTB#  29
+ * SCSI  IDSEL  = AD18  INTC#  30
+ * PC104 IDSEL0 = AD20  INTA#  28
+ * PC104 IDSEL1 = AD21  INTB#  29
+ * PC104 IDSEL2 = AD22  INTC#  30
+ * PC104 IDSEL3 = AD23  INTD#  31
+ *
+ * busdevfunc = EXXX XXXX BBBB BBBB DDDD DFFF RRRR RR00
+ *              ^         ^         ^     ^   ^
+ *             31        23        15    10   7
+ * E = Enabled
+ * B = Bussnumber
+ * D = Devicenumber (Device0 = AD10)
+ * F = Functionnumber
+ * R = Registernumber
+ *
+ * Device = (busdevfunc>>11) + 10
+ * Vector = devicenumber % 4 + 28
+ *
+ */
+#define PCI_DEV_NUMBER(x)      (((x>>11) & 0x1f) + 10)
+#define PCI_IRQ_VECTOR(x)      (PCI_DEV_NUMBER(x) % 4) + 28
+
+
+/* PCI Device List for PIP405 */
+
+/* Mapping:
+ * +-------------+------------+------------+--------------------------------+
+ * ¦ PCI MemAddr | PCI IOAddr | Local Addr | Device / Function              |
+ * +-------------+------------+------------+--------------------------------+
+ * |  0x00000000 |            | 0xA0000000 | ISA Memory (hard wired)        |
+ * |  0x00FFFFFF |            | 0xA0FFFFFF |                                |
+ * +-------------+------------+------------+--------------------------------+
+ * |             | 0x00000000 | 0xE8000000 | ISA IO (hard wired)            |
+ * |             | 0x0000FFFF | 0xE800FFFF |                                |
+ * +-------------+------------+------------+--------------------------------+
+ * |  0x80000000 |            | 0x80000000 | VGA Controller Memory          |
+ * |  0x80FFFFFF |            | 0x80FFFFFF |                                |
+ * +-------------+------------+------------+--------------------------------+
+ * |  0x81000000 |            | 0x81000000 | SCSI Controller Memory         |
+ * |  0x81FFFFFF |            | 0x81FFFFFF |                                |
+ * +-------------+------------+------------+--------------------------------+
+ */
+
+static PCI_DEV_CFG_TABLE pcidevtbl[]={
+/* PIIX4 ISA Bridge Function 0 */
+{0x8086,0x7110,        0xff,0, {
+       {PCI_CFG_PIIX4_SERIRQ,  0xD0,           1},/* enable Continous SERIRQ Pin */
+       {PCI_CFG_PIIX4_GENCFG,  0x00010000,     4},/* enable SERIRQs     */
+       {PCI_CFG_PIIX4_XBCS,    0x0080,         2}, /* disable all peri CS  */
+       {PCI_CFG_PIIX4_RTCCFG,  0x21,           1}, /* enable RTC          */
+       {0xFFFF, 0,0}}                          /* end of device table */
+},
+/* PIIX4 IDE Controller Function 1 */
+{0x8086,0x7111,0xff,1,{
+       {PCI_CFG_COMMAND,      0x0001,     2},/* enable IO access */
+       {PCI_CFG_PIIX4_IDETIM, 0x80008000, 4},/* enable Both IDE channels        */
+       {0xFFFF, 0,0}}                          /* end of device table */
+},
+/* PIIX4 USB Controller Function 2 */
+{0x8086,0x7112,0xff,2,{
+       {PCI_CFG_DEV_INT_LINE,            31, 1},/* Int vector = 31 */
+       {PCI_CFG_BASE_ADDRESS_4,  0x0000E001, 4},/* Set IO Address to 0xe000 to 0xe01F   */
+       {PCI_CFG_LATENCY_TIMER,         0x80, 1},/* Latency Timer 0x80 */
+       {0xC0,                                            0x2000, 2}, /* Legacy support */
+       {PCI_CFG_COMMAND,             0x0005, 2},/* enable IO access and Master */
+       {0xFFFF, 0,0}}                          /* end of device table */
+},
+/* VGA Controller  ct69000 (logical device 0) */
+{0x102C,0x00C0,0xff,0,{
+       {PCI_CFG_BASE_ADDRESS_0, 0x80000000, 4},/* Frame buffer access */
+       {PCI_CFG_EXPANSION_ROM,  0x00000000, 4},/* disable ROM */
+       {PCI_CFG_DEV_INT_LINE,           29, 1},/* Int vector = 29 */
+       {PCI_CFG_COMMAND,            0x0003, 2},/* enable IO access */
+       {0xFFFF, 0,0}}                          /* end of device table */
+},
+/* Symbois 810 function 0 */
+{0x1000,0x0001,0xff,0,{
+       {PCI_CFG_BASE_ADDRESS_0, 0x00001001, 4},/* IO Base address */
+       {PCI_CFG_BASE_ADDRESS_1, 0x81000000, 4},/* Memory Base address */
+       {PCI_CFG_DEV_INT_LINE,           30, 1},/* Int vector = 30 */
+       {PCI_CFG_COMMAND,            0x0006, 2},/* enable Memory access and busmaster */
+       {0xFFFF, 0,0}}                          /* end of device table */
+},
+/* Terminator */
+{0xffff,0xffff,0xff,0xff,{
+       {0xFFFF, 0,0}}                          /* end of device table */
+}
+};
+#endif /* _PCI_PARTS_H_ */
+
+
+
+
+
diff --git a/board/mpl/common/sym53c8xx.c b/board/mpl/common/sym53c8xx.c
new file mode 100644 (file)
index 0000000..77eb0e0
--- /dev/null
@@ -0,0 +1,751 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch.
+ *
+ * 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
+ * partly derived from
+ * linux/drivers/scsi/sym53c8xx.c
+ *
+ */
+
+/* 
+ * SCSI support based on the chip sym53C810.
+ */
+
+#include <ppcboot.h>
+#include <command.h> 
+#include <cmd_boot.h>
+#include "pci.h"
+#include <asm/processor.h>
+#include "sym53c8xx_defs.h"
+#include <scsi.h>
+
+#undef SYM53C8XX_DEBUG
+
+#ifdef SYM53C8XX_DEBUG
+#define        PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX)
+
+
+#undef SCSI_SINGLE_STEP
+/*
+ * Single Step is only used for debug purposes
+ */
+#ifdef SCSI_SINGLE_STEP
+static unsigned long start_script_select;
+static unsigned long start_script_msgout;
+static unsigned long start_script_msgin;
+static unsigned long start_script_msg_ext;
+static unsigned long start_script_cmd;
+static unsigned long start_script_data_in;
+static unsigned long start_script_data_out;
+static unsigned long start_script_status;
+static unsigned long start_script_complete;
+static unsigned long start_script_error;
+static unsigned long start_script_reselection;
+static unsigned int len_script_select;
+static unsigned int len_script_msgout;
+static unsigned int len_script_msgin;
+static unsigned int len_script_msg_ext;
+static unsigned int len_script_cmd;
+static unsigned int len_script_data_in;
+static unsigned int len_script_data_out;
+static unsigned int len_script_status;
+static unsigned int len_script_complete;
+static unsigned int len_script_error;
+static unsigned int len_script_reselection;
+#endif
+
+
+static unsigned short scsi_int_mask;           /* shadow register for SCSI related interrupts */
+static unsigned char  script_int_mask; /* shadow register for SCRIPT related interrupts */
+static unsigned long script_select[8]; /* script for selection */
+static unsigned long script_msgout[8]; /* script for message out phase (NOT USED) */
+static unsigned long script_msgin[14]; /* script for message in phase */
+static unsigned long script_msg_ext[32]; /* script for message in phase when more than 1 byte message */
+static unsigned long script_cmd[18];    /* script for command phase */
+static unsigned long script_data_in[8]; /* script for data in phase */
+static unsigned long script_data_out[8]; /* script for data out phase */
+static unsigned long script_status[6]; /* script for status phase */
+static unsigned long script_complete[10]; /* script for complete */
+static unsigned long script_reselection[4]; /* script for reselection (NOT USED) */
+static unsigned long script_error[2]; /* script for error handling */
+
+static unsigned long int_stat[3]; /* interrupt status */
+static unsigned long scsi_mem_addr; /* base memory address =SCSI_MEM_ADDRESS; */
+
+
+#define SCSI_MAX_RETRY 3 /* number of retries in scsi_issue() */
+
+#define SCSI_MAX_RETRY_NOT_READY 10 /* number of retries when device is not ready */
+#define SCSI_NOT_READY_TIME_OUT 500 /* timeout per retry when not ready */
+
+/*********************************************************************************
+ * forward declerations
+ */
+
+void scsi_chip_init(void);
+void handle_scsi_int(void);
+
+
+/********************************************************************************
+ * reports SCSI errors to the user
+ */
+void scsi_print_error(ccb *pccb)
+{
+       int i;
+       printf("SCSI Error: Target %d LUN %d Command %02X\n",pccb->target, pccb->lun, pccb->cmd[0]);
+       printf("       CCB: ");
+       for(i=0;i<pccb->cmdlen;i++)
+               printf("%02X ",pccb->cmd[i]); 
+       printf("(len=%d)\n",pccb->cmdlen);
+       printf("     Cntrl: ");
+       switch(pccb->contr_stat) {
+               case SIR_COMPLETE:                                              printf("Complete (no Error)\n"); break;
+               case SIR_SEL_ATN_NO_MSG_OUT:    printf("Selected with ATN no MSG out phase\n"); break;
+               case SIR_CMD_OUT_ILL_PH:                        printf("Command out illegal phase\n"); break;
+               case SIR_MSG_RECEIVED:                          printf("MSG received Error\n"); break;
+               case SIR_DATA_IN_ERR:                           printf("Data in Error\n"); break;
+               case SIR_DATA_OUT_ERR:                          printf("Data out Error\n"); break;
+               case SIR_SCRIPT_ERROR:                          printf("Script Error\n"); break;
+               case SIR_MSG_OUT_NO_CMD:                        printf("MSG out no Command phase\n"); break;
+               case SIR_MSG_OVER7:                                     printf("MSG in over 7 bytes\n"); break;
+               case INT_ON_FY:                                                         printf("Interrupt on fly\n"); break;
+               case SCSI_SEL_TIME_OUT:                         printf("SCSI Selection Timeout\n"); break;
+               case SCSI_HNS_TIME_OUT:                         printf("SCSI Handshake Timeout\n"); break;
+               case SCSI_MA_TIME_OUT:                          printf("SCSI Phase Error\n"); break;
+               case SCSI_UNEXP_DIS:                                    printf("SCSI unexpected disconnect\n"); break;
+               default:                                                                                        printf("unknown status %lx\n",pccb->contr_stat); break;
+       }
+       printf("     Sense: SK %x (",pccb->sense_buf[2]&0x0f);
+       switch(pccb->sense_buf[2]&0xf) {
+               case SENSE_NO_SENSE: printf("No Sense)"); break;
+               case SENSE_RECOVERED_ERROR: printf("Recovered Error)"); break;
+               case SENSE_NOT_READY:   printf("Not Ready)"); break;
+               case SENSE_MEDIUM_ERROR: printf("Medium Error)"); break;
+               case SENSE_HARDWARE_ERROR: printf("Hardware Error)"); break;
+               case SENSE_ILLEGAL_REQUEST: printf("Illegal request)"); break;
+               case SENSE_UNIT_ATTENTION: printf("Unit Attention)"); break;
+               case SENSE_DATA_PROTECT: printf("Data Protect)"); break;
+               case SENSE_BLANK_CHECK: printf("Blank check)"); break;
+               case SENSE_VENDOR_SPECIFIC: printf("Vendor specific)"); break;
+               case SENSE_COPY_ABORTED: printf("Copy aborted)"); break;
+               case SENSE_ABORTED_COMMAND:     printf("Aborted Command)"); break;
+               case SENSE_VOLUME_OVERFLOW:     printf("Volume overflow)"); break;
+               case SENSE_MISCOMPARE: printf("Misscompare\n"); break;
+               default: printf("Illegal Sensecode\n"); break;
+       }                       
+       printf(" ASC %x ASCQ %x\n",pccb->sense_buf[12],pccb->sense_buf[13]);
+       printf("    Status: ");
+       switch(pccb->status) {
+               case S_GOOD :   printf("Good\n"); break;
+               case S_CHECK_COND: printf("Check condition\n"); break;
+               case S_COND_MET: printf("Condition Met\n"); break;
+               case S_BUSY: printf("Busy\n"); break;
+               case S_INT: printf("Intermediate\n"); break;
+               case S_INT_COND_MET: printf("Intermediate condition met\n"); break;
+               case S_CONFLICT: printf("Reservation conflict\n"); break;
+               case S_TERMINATED: printf("Command terminated\n"); break;
+               case S_QUEUE_FULL: printf("Task set full\n"); break;
+               default: printf("unknown: %02X\n",pccb->status); break;
+       }
+                       
+}
+
+
+
+/******************************************************************************
+ * sets-up the SCSI controller 
+ * the base memory address is retrived via the PCI_Read_CFG_Reg
+ */
+void scsi_low_level_init(int busdevfunc)
+{
+       unsigned long addr;
+       unsigned char vec;
+       vec=PCI_Read_CFG_Reg(busdevfunc, PCI_CFG_DEV_INT_LINE, 1);
+       addr=PCI_Read_CFG_Reg(busdevfunc, PCI_CFG_BASE_ADDRESS_1, 4);
+       scsi_mem_addr=addr;
+       scsi_chip_init();
+       scsi_bus_reset();
+       irq_install_handler(vec, (interrupt_handler_t *)handle_scsi_int, NULL);
+}
+
+
+/************************************************************************************
+ * Low level Part of SCSI Driver
+ */
+/*
+ * big-endian -> little endian conversion for the script
+ */ 
+unsigned long swap_script(unsigned long val)
+{
+       unsigned long tmp;
+       tmp = ((val>>24)&0xff) | ((val>>8)&0xff00) | ((val<<8)&0xff0000) | ((val<<24)&0xff000000);
+       return tmp;
+}
+
+
+void scsi_write_byte(ulong offset,unsigned char val)
+{
+       out8(scsi_mem_addr+offset,val);
+}
+
+
+unsigned char scsi_read_byte(ulong offset)
+{
+       return(in8(scsi_mem_addr+offset));
+}
+
+
+/********************************************************************************
+ * interrupt handler
+ */
+void handle_scsi_int(void)
+{
+       unsigned char stat,stat1,stat2;
+       unsigned short sstat;
+       int i;
+#ifdef SCSI_SINGLE_STEP
+       unsigned long tt;
+#endif
+       stat=scsi_read_byte(ISTAT);
+       if((stat & DIP)==DIP) { /* DMA Interrupt pending */
+               stat1=scsi_read_byte(DSTAT);
+#ifdef SCSI_SINGLE_STEP 
+               if((stat1 & SSI)==SSI)
+               {
+                       tt=in32r(scsi_mem_addr+DSP);
+                       if(((tt)>=start_script_select) && ((tt)<=start_script_select+len_script_select)) {
+                               printf("select %d\n",(tt-start_script_select)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_msgout) && ((tt)<=start_script_msgout+len_script_msgout)) {
+                               printf("msgout %d\n",(tt-start_script_msgout)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_msgin) && ((tt)<=start_script_msgin+len_script_msgin)) {
+                               printf("msgin %d\n",(tt-start_script_msgin)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_msg_ext) && ((tt)<=start_script_msg_ext+len_script_msg_ext)) {
+                               printf("msgin_ext %d\n",(tt-start_script_msg_ext)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_cmd) && ((tt)<=start_script_cmd+len_script_cmd)) {
+                               printf("cmd %d\n",(tt-start_script_cmd)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_data_in) && ((tt)<=start_script_data_in+len_script_data_in)) {
+                               printf("data_in %d\n",(tt-start_script_data_in)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_data_out) && ((tt)<=start_script_data_out+len_script_data_out)) {
+                               printf("data_out %d\n",(tt-start_script_data_out)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_status) && ((tt)<=start_script_status+len_script_status)) {
+                               printf("status %d\n",(tt-start_script_status)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_complete) && ((tt)<=start_script_complete+len_script_complete)) {
+                               printf("complete %d\n",(tt-start_script_complete)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_error) && ((tt)<=start_script_error+len_script_error)) {
+                               printf("error %d\n",(tt-start_script_error)>>2);
+                               goto end_single;
+                       }
+                       if(((tt)>=start_script_reselection) && ((tt)<=start_script_reselection+len_script_reselection)) {
+                               printf("reselection %d\n",(tt-start_script_reselection)>>2);
+                               goto end_single;
+                       }
+                       printf("sc: %lx\n",tt);
+end_single:
+                       stat2=scsi_read_byte(DCNTL);
+                       stat2|=STD;
+                       scsi_write_byte(DCNTL,stat2);
+               }
+#endif
+               if((stat1 & SIR)==SIR) /* script interrupt */
+               {
+                       int_stat[0]=in32(scsi_mem_addr+DSPS);
+               }
+               if((stat1&DFE)==0) { /* fifo not epmty */
+                       scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */
+                       stat2=scsi_read_byte(STEST3);
+                       scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */
+               }       
+       }
+       if((stat & SIP)==SIP) {  /* scsi interrupt */
+               sstat = (unsigned short)scsi_read_byte(SIST+1);
+               sstat <<=8;
+               sstat |= (unsigned short)scsi_read_byte(SIST);
+               for(i=0;i<3;i++) {
+                       if(int_stat[i]==0)
+                               break; /* found an empty int status */
+               }
+               int_stat[i]=SCSI_INT_STATE | sstat;
+               stat1=scsi_read_byte(DSTAT);
+               if((stat1&DFE)==0) { /* fifo not epmty */
+                       scsi_write_byte(CTEST3,CLF); /* Clear DMA FIFO */
+                       stat2=scsi_read_byte(STEST3);
+                       scsi_write_byte(STEST3,(stat2 | CSF)); /* Clear SCSI FIFO */
+               }       
+       }
+       if((stat & INTF)==INTF) { /* interrupt on Fly */
+               scsi_write_byte(ISTAT,stat); /* clear it */
+               for(i=0;i<3;i++) {
+                       if(int_stat[i]==0)
+                               break; /* found an empty int status */
+               }
+               int_stat[i]=INT_ON_FY;
+       }
+}
+
+
+void scsi_bus_reset(void)
+{
+       unsigned char t;
+       int i;
+       t=scsi_read_byte(SCNTL1);
+       scsi_write_byte(SCNTL1,(t | CRST));
+       udelay(50);
+       scsi_write_byte(SCNTL1,t);
+       for(i=0;i<2000;i++)
+               udelay(1000); /* 2sec to give the devices time to spin up */
+       scsi_chip_init(); /* reinit the chip ...*/
+
+}
+
+void scsi_int_enable(void)
+{
+       scsi_write_byte(SIEN,(unsigned char)scsi_int_mask);
+       scsi_write_byte(SIEN+1,(unsigned char)(scsi_int_mask>>8));
+       scsi_write_byte(DIEN,script_int_mask);
+}
+
+void scsi_write_dsp(unsigned long start)
+{
+       unsigned long val;
+#ifdef SCSI_SINGLE_STEP 
+       unsigned char t;
+#endif
+       val = start;
+       out32r(scsi_mem_addr + DSP,start);      
+#ifdef SCSI_SINGLE_STEP 
+       t=scsi_read_byte(DCNTL);
+  t|=STD;
+       scsi_write_byte(DCNTL,t);
+#endif
+}
+
+/* only used for debug purposes */
+void scsi_print_script(void)
+{
+       printf("script_select @         0x%08lX\n",(unsigned long)&script_select[0]);
+       printf("script_msgout @         0x%08lX\n",(unsigned long)&script_msgout[0]);
+       printf("script_msgin @          0x%08lX\n",(unsigned long)&script_msgin[0]);
+       printf("script_msgext @         0x%08lX\n",(unsigned long)&script_msg_ext[0]);
+       printf("script_cmd @            0x%08lX\n",(unsigned long)&script_cmd[0]);
+       printf("script_data_in @        0x%08lX\n",(unsigned long)&script_data_in[0]);
+       printf("script_data_out @       0x%08lX\n",(unsigned long)&script_data_out[0]);
+       printf("script_status @         0x%08lX\n",(unsigned long)&script_status[0]);
+       printf("script_complete @       0x%08lX\n",(unsigned long)&script_complete[0]);
+       printf("script_error @          0x%08lX\n",(unsigned long)&script_error[0]);
+}
+
+
+
+void scsi_set_script(ccb *pccb)
+{
+       int i;
+       i=0;
+       script_select[i++]=swap_script(SCR_REG_REG(GPREG, SCR_AND, 0xfe));
+       script_select[i++]=0; /* LED ON */
+       script_select[i++]=swap_script(SCR_CLR(SCR_TRG)); /* select initiator mode */
+       script_select[i++]=0;
+       /* script_select[i++]=swap_script(SCR_SEL_ABS_ATN | pccb->target << 16); */
+       script_select[i++]=swap_script(SCR_SEL_ABS | pccb->target << 16);
+       script_select[i++]=swap_script((unsigned long)&script_cmd[0x04]); /* error handling */
+       script_select[i++]=swap_script(SCR_JUMP); /* next section */
+       /*      script_select[i++]=swap_script((unsigned long)&script_msgout[0]); */ /* message out */
+       script_select[i++]=swap_script((unsigned long)&script_cmd[0]); /* command out */
+
+#ifdef SCSI_SINGLE_STEP
+       start_script_select=(unsigned long)&script_select[0];
+       len_script_select=i*4;
+#endif
+
+       i=0;
+       script_msgout[i++]=swap_script(SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)));
+       script_msgout[i++]=SIR_SEL_ATN_NO_MSG_OUT;
+       script_msgout[i++]=swap_script( SCR_MOVE_ABS(1) ^ SCR_MSG_OUT);
+       script_msgout[i++]=swap_script((unsigned long)&pccb->msgout[0]);
+       script_msgout[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_COMMAND))); /* if Command phase */
+       script_msgout[i++]=swap_script((unsigned long)&script_cmd[0]); /* switch to command */
+       script_msgout[i++]=swap_script(SCR_INT); /* interrupt if not */
+       script_msgout[i++]=SIR_MSG_OUT_NO_CMD;
+
+#ifdef SCSI_SINGLE_STEP
+       start_script_msgout=(unsigned long)&script_msgout[0];
+       len_script_msgout=i*4;
+#endif
+       i=0;
+       script_cmd[i++]=swap_script(SCR_MOVE_ABS(pccb->cmdlen) ^ SCR_COMMAND);
+       script_cmd[i++]=swap_script((unsigned long)&pccb->cmd[0]);
+       script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN))); /* message in ? */
+       script_cmd[i++]=swap_script((unsigned long)&script_msgin[0]);
+       script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_OUT))); /* data out ? */
+       script_cmd[i++]=swap_script((unsigned long)&script_data_out[0]);
+       script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_DATA_IN))); /* data in ? */
+       script_cmd[i++]=swap_script((unsigned long)&script_data_in[0]);
+       script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_STATUS)));  /* status ? */
+       script_cmd[i++]=swap_script((unsigned long)&script_status[0]);
+       script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_COMMAND)));  /* command ? */
+       script_cmd[i++]=swap_script((unsigned long)&script_cmd[0]);
+       script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_OUT)));  /* message out ? */
+       script_cmd[i++]=swap_script((unsigned long)&script_msgout[0]);
+       script_cmd[i++]=swap_script(SCR_JUMP ^ IFTRUE (IF (SCR_MSG_IN))); /* just for error handling message in ? */
+       script_cmd[i++]=swap_script((unsigned long)&script_msgin[0]);
+       script_cmd[i++]=swap_script(SCR_INT); /* interrupt if not */
+       script_cmd[i++]=SIR_CMD_OUT_ILL_PH;
+#ifdef SCSI_SINGLE_STEP
+       start_script_cmd=(unsigned long)&script_cmd[0];
+       len_script_cmd=i*4;
+#endif
+       i=0;
+       script_data_out[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_OUT); /* move */
+       script_data_out[i++]=swap_script((unsigned long)pccb->pdata); /* pointer to buffer */
+       script_data_out[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)));
+       script_data_out[i++]=swap_script((unsigned long)&script_status[0]);
+       script_data_out[i++]=swap_script(SCR_INT);
+       script_data_out[i++]=SIR_DATA_OUT_ERR;
+
+#ifdef SCSI_SINGLE_STEP
+       start_script_data_out=(unsigned long)&script_data_out[0];
+       len_script_data_out=i*4;
+#endif
+       i=0;
+       script_data_in[i++]=swap_script(SCR_MOVE_ABS(pccb->datalen)^ SCR_DATA_IN); /* move  */
+       script_data_in[i++]=swap_script((unsigned long)pccb->pdata); /* pointer to buffer */
+       script_data_in[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_STATUS)));
+       script_data_in[i++]=swap_script((unsigned long)&script_status[0]);
+       script_data_in[i++]=swap_script(SCR_INT);
+       script_data_in[i++]=SIR_DATA_IN_ERR;
+#ifdef SCSI_SINGLE_STEP
+       start_script_data_in=(unsigned long)&script_data_in[0];
+       len_script_data_in=i*4;
+#endif
+       i=0;
+       script_msgin[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN);
+       script_msgin[i++]=swap_script((unsigned long)&pccb->msgin[0]);
+       script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)));
+       script_msgin[i++]=swap_script((unsigned long)&script_complete[0]);
+       script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)));
+       script_msgin[i++]=swap_script((unsigned long)&script_complete[0]);
+       script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)));
+       script_msgin[i++]=swap_script((unsigned long)&script_complete[0]);
+       script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)));
+       script_msgin[i++]=swap_script((unsigned long)&script_complete[0]);
+       script_msgin[i++]=swap_script(SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)));
+       script_msgin[i++]=swap_script((unsigned long)&script_msg_ext[0]);
+       script_msgin[i++]=swap_script(SCR_INT);
+       script_msgin[i++]=SIR_MSG_RECEIVED;
+#ifdef SCSI_SINGLE_STEP
+       start_script_msgin=(unsigned long)&script_msgin[0];
+       len_script_msgin=i*4;
+#endif
+       i=0;
+       script_msg_ext[i++]=swap_script(SCR_CLR (SCR_ACK)); /* clear ACK */
+       script_msg_ext[i++]=0;
+       script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* assuming this is the msg length */
+       script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[1]);  
+       script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); 
+       script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */
+       script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+       script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[2]);  
+       script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); 
+       script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */
+       script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+       script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[3]);  
+       script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); 
+       script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */
+       script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+       script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[4]);  
+       script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); 
+       script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */
+       script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+       script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[5]);  
+       script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); 
+       script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */
+       script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+       script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[6]);  
+       script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); 
+       script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */
+       script_msg_ext[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_MSG_IN); /* next */
+       script_msg_ext[i++]=swap_script((unsigned long)&pccb->msgin[7]);  
+       script_msg_ext[i++]=swap_script(SCR_JUMP ^ IFFALSE (IF (SCR_MSG_IN))); 
+       script_msg_ext[i++]=swap_script((unsigned long)&script_complete[0]); /* no more bytes */
+       script_msg_ext[i++]=swap_script(SCR_INT);
+       script_msg_ext[i++]=SIR_MSG_OVER7;
+#ifdef SCSI_SINGLE_STEP
+       start_script_msg_ext=(unsigned long)&script_msg_ext[0];
+       len_script_msg_ext=i*4;
+#endif
+       i=0;
+       script_status[i++]=swap_script(SCR_MOVE_ABS (1) ^ SCR_STATUS);
+       script_status[i++]=swap_script((unsigned long)&pccb->status);
+       script_status[i++]=swap_script(SCR_JUMP ^ IFTRUE (WHEN (SCR_MSG_IN)));
+       script_status[i++]=swap_script((unsigned long)&script_msgin[0]);
+       script_status[i++]=swap_script(SCR_INT);
+       script_status[i++]=SIR_STATUS_ILL_PH;
+#ifdef SCSI_SINGLE_STEP
+       start_script_status=(unsigned long)&script_status[0];
+       len_script_status=i*4;
+#endif
+       i=0;
+       script_complete[i++]=swap_script(SCR_REG_REG (SCNTL2, SCR_AND, 0x7f));
+       script_complete[i++]=0;
+       script_complete[i++]=swap_script(SCR_CLR (SCR_ACK|SCR_ATN));
+       script_complete[i++]=0;
+       script_complete[i++]=swap_script(SCR_WAIT_DISC);
+       script_complete[i++]=0;
+       script_complete[i++]=swap_script(SCR_REG_REG(GPREG, SCR_OR, 0x01));
+       script_complete[i++]=0; /* LED OFF */
+       script_complete[i++]=swap_script(SCR_INT);
+       script_complete[i++]=SIR_COMPLETE;
+#ifdef SCSI_SINGLE_STEP
+       start_script_complete=(unsigned long)&script_complete[0];
+       len_script_complete=i*4;
+#endif
+       i=0;
+       script_error[i++]=swap_script(SCR_INT); /* interrupt if error */
+       script_error[i++]=SIR_SCRIPT_ERROR;
+#ifdef SCSI_SINGLE_STEP
+       start_script_error=(unsigned long)&script_error[0];
+       len_script_error=i*4;
+#endif
+       i=0;
+       script_reselection[i++]=swap_script(SCR_CLR (SCR_TRG)); /* target status */
+       script_reselection[i++]=0;
+       script_reselection[i++]=swap_script(SCR_WAIT_RESEL); 
+       script_reselection[i++]=swap_script((unsigned long)&script_select[0]); /* len = 4 */
+#ifdef SCSI_SINGLE_STEP
+       start_script_reselection=(unsigned long)&script_reselection[0];
+       len_script_reselection=i*4;
+#endif
+}
+
+
+
+void scsi_issue(ccb *pccb)
+{
+       int i;
+       unsigned short sstat;
+       int retrycnt;  /* retry counter */
+       for(i=0;i<3;i++)
+               int_stat[i]=0; /* delete all int status */
+       /* struct pccb must be set-up correctly */
+       retrycnt=0;
+       PRINTF("ID %d issue cmd %02X\n",pccb->target,pccb->cmd[0]);
+       pccb->trans_bytes=0; /* no bytes transfered yet */
+       scsi_set_script(pccb); /* fill in SCRIPT                */
+       scsi_int_mask=STO | UDC | MA; /* Interrupts which are enabled */
+       script_int_mask=0xff; /* enable all Ints */
+       scsi_int_enable();
+       scsi_write_dsp((unsigned long)&script_select[0]); /* start script */
+       /* now we have to wait for IRQs */
+retry: 
+       while(int_stat[0]==0);
+       if(int_stat[0]==SIR_COMPLETE) {
+               if(pccb->msgin[0]==M_DISCONNECT) {
+                       PRINTF("Wait for reselection\n");
+                       for(i=0;i<3;i++)
+                               int_stat[i]=0; /* delete all int status */
+                       scsi_write_dsp((unsigned long)&script_reselection[0]); /* start reselection script */
+                       goto retry;
+               }
+               pccb->contr_stat=SIR_COMPLETE;
+               return;
+       }
+       if((int_stat[0] & SCSI_INT_STATE)==SCSI_INT_STATE) { /* scsi interrupt */
+               sstat=(unsigned short)int_stat[0];
+               if((sstat & STO)==STO) { /* selection timeout */
+                       pccb->contr_stat=SCSI_SEL_TIME_OUT;
+                       scsi_write_byte(GPREG,0x01);
+                       PRINTF("ID: %X Selection Timeout\n",pccb->target);
+                       return;
+               }
+               if((sstat & UDC)==UDC) { /* unexpected disconnect */
+                       pccb->contr_stat=SCSI_UNEXP_DIS;
+                       scsi_write_byte(GPREG,0x01);
+                       PRINTF("ID: %X Unexpected Disconnect\n",pccb->target);
+                       return;
+               }
+               if((sstat & RSL)==RSL) { /* reselection */
+                       pccb->contr_stat=SCSI_UNEXP_DIS;
+                       scsi_write_byte(GPREG,0x01);
+                       PRINTF("ID: %X Unexpected Disconnect\n",pccb->target);
+                       return;
+               }
+               if(((sstat & MA)==MA)||((sstat & HTH)==HTH)) { /* phase missmatch */
+                       if(retrycnt<SCSI_MAX_RETRY) {
+                               pccb->trans_bytes=pccb->datalen - 
+                                       ((unsigned long)scsi_read_byte(DBC) |
+                                       ((unsigned long)scsi_read_byte(DBC+1)<<8) | 
+                                       ((unsigned long)scsi_read_byte(DBC+2)<<16));
+                               for(i=0;i<3;i++)
+                                       int_stat[i]=0; /* delete all int status */
+                               retrycnt++;
+                               PRINTF("ID: %X Phase Missmatch Retry %d Phase %02X transfered %lx\n",
+                                               pccb->target,retrycnt,scsi_read_byte(SBCL),pccb->trans_bytes);
+                               scsi_write_dsp((unsigned long)&script_cmd[4]); /* start retry script */
+                               goto retry;
+                       }
+                       if((sstat & MA)==MA)
+                               pccb->contr_stat=SCSI_MA_TIME_OUT;
+                       else
+                               pccb->contr_stat=SCSI_HNS_TIME_OUT;
+                       PRINTF("Phase Missmatch stat %lx\n",pccb->contr_stat);
+                       return;
+               } /* no phase int */
+               PRINTF("SCSI INT %lX\n",int_stat[0]);
+               pccb->contr_stat=int_stat[0];
+               return;
+       } /* end scsi int */
+       PRINTF("SCRIPT INT %lX phase %02X\n",int_stat[0],scsi_read_byte(SBCL));
+       pccb->contr_stat=int_stat[0];
+       return;
+}
+
+int scsi_exec(ccb *pccb)
+{
+       unsigned char tmpcmd[16],tmpstat;
+       int i,retrycnt,t;
+       unsigned long transbytes,datalen;
+       unsigned char *tmpptr;
+       retrycnt=0;
+retry:
+       scsi_issue(pccb);
+       if(pccb->contr_stat!=SIR_COMPLETE)
+               return FALSE;
+       if(pccb->status==S_GOOD)
+               return TRUE;
+       if(pccb->status==S_CHECK_COND) { /* check condition */
+               for(i=0;i<16;i++)
+                       tmpcmd[i]=pccb->cmd[i];
+               pccb->cmd[0]=SCSI_REQ_SENSE;
+               pccb->cmd[1]=pccb->lun<<5;
+               pccb->cmd[2]=0;
+               pccb->cmd[3]=0;
+               pccb->cmd[4]=14;
+               pccb->cmd[5]=0;
+               pccb->cmdlen=6;
+               pccb->msgout[0]=SCSI_IDENTIFY;
+               transbytes=pccb->trans_bytes;
+               tmpptr=pccb->pdata;
+               pccb->pdata=&pccb->sense_buf[0];
+               datalen=pccb->datalen;
+               pccb->datalen=14;
+               tmpstat=pccb->status;
+               scsi_issue(pccb);
+               for(i=0;i<16;i++)
+                       pccb->cmd[i]=tmpcmd[i];
+               pccb->trans_bytes=transbytes;
+               pccb->pdata=tmpptr;
+               pccb->datalen=datalen;
+               pccb->status=tmpstat;
+               PRINTF("Request_sense sense key %x ASC %x ASCQ %x\n",pccb->sense_buf[2]&0x0f,
+                       pccb->sense_buf[12],pccb->sense_buf[13]);
+               switch(pccb->sense_buf[2]&0xf) {
+                       case SENSE_NO_SENSE: 
+                       case SENSE_RECOVERED_ERROR: 
+                               /* seems to be ok */
+                               return TRUE;
+                               break;
+                       case SENSE_NOT_READY:
+                               if((pccb->sense_buf[12]!=0x04)||(pccb->sense_buf[13]!=0x01)) {
+                                       /* if device is not in process of becoming ready */
+                                       return FALSE;
+                                       break;
+                               } /* else fall through */
+                       case SENSE_UNIT_ATTENTION: 
+                               if(retrycnt<SCSI_MAX_RETRY_NOT_READY) {
+                                       PRINTF("Target %d not ready, retry %d\n",pccb->target,retrycnt);
+                                       for(t=0;t<SCSI_NOT_READY_TIME_OUT;t++)
+                                               udelay(1000); /* 1sec wait */
+                                       retrycnt++;
+                                       goto retry;
+                               }
+                               PRINTF("Target %d not ready, %d retried\n",pccb->target,retrycnt);
+                               return FALSE;
+                       default:
+                               return FALSE;
+               }
+       }
+       PRINTF("Status = %X\n",pccb->status);
+       return FALSE;
+}              
+               
+
+
+
+void scsi_chip_init(void)
+{
+       /* first we issue a soft reset */
+       scsi_write_byte(ISTAT,SRST);
+       udelay(1000);
+       scsi_write_byte(ISTAT,0);
+       /* setup chip */
+       scsi_write_byte(SCNTL0,0xC0); /* full arbitration no start, no message, parity disabled, master */
+       scsi_write_byte(SCNTL1,0x00); 
+       scsi_write_byte(SCNTL2,0x00);
+       scsi_write_byte(SCNTL3,0x13); /* synchronous clock 40/4=10MHz, asynchronous 40MHz */
+       scsi_write_byte(SCID,0x47); /* ID=7, enable reselection */
+       scsi_write_byte(SXFER,0x00); /* synchronous transfer period 10MHz, asynchronous */
+       scsi_write_byte(SDID,0x00);  /* targed SCSI ID = 0 */
+       scsi_int_mask=0x0000; /* no Interrupt is enabled */
+       script_int_mask=0x00;
+       scsi_int_enable();
+       scsi_write_byte(GPREG,0x01); /* GPIO0 is LED (off) */
+       scsi_write_byte(GPCNTL,0x0E); /* GPIO0 is Output */
+       scsi_write_byte(STIME0,0x08); /* handshake timer disabled, selection timeout 512msec */
+       scsi_write_byte(RESPID,0x80); /* repond only to the own ID (reselection) */
+       scsi_write_byte(STEST1,0x00); /* not isolated, SCLK is used */
+       scsi_write_byte(STEST2,0x00); /* no Lowlevel Mode? */
+       scsi_write_byte(STEST3,0x80); /* enable tolerANT */
+       scsi_write_byte(CTEST3,0x04); /* clear FIFO */
+       scsi_write_byte(CTEST4,0x00);
+       scsi_write_byte(CTEST5,0x00);   
+#ifdef SCSI_SINGLE_STEP 
+       scsi_write_byte(DCNTL,IRQM | SSM);      
+       scsi_write_byte(DMODE,MAN);     
+#else
+       scsi_write_byte(DCNTL,IRQM);    
+       scsi_write_byte(DMODE,0x00);    
+#endif
+}
+#endif /* (CONFIG_COMMANDS & CFG_CMD_SCSI) */
+
+
diff --git a/board/mpl/common/sym53c8xx_defs.h b/board/mpl/common/sym53c8xx_defs.h
new file mode 100644 (file)
index 0000000..d1bc3cf
--- /dev/null
@@ -0,0 +1,582 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ *
+ * Most of these definitions are derived from
+ * linux/drivers/scsi/sym53c8xx_defs.h
+ *
+ */
+
+#ifndef _SYM53C8XX_DEFS_H
+#define _SYM53C8XX_DEFS_H
+
+
+#define SCNTL0         0x00    /* full arb., ena parity, par->ATN  */
+
+#define SCNTL1         0x01    /* no reset                         */
+  #define   ISCON   0x10  /* connected to scsi                                         */
+  #define   CRST    0x08  /* force reset                      */
+  #define   IARB    0x02  /* immediate arbitration            */
+
+#define SCNTL2         0x02    /* no disconnect expected           */
+       #define   SDU     0x80  /* cmd: disconnect will raise error */
+       #define   CHM     0x40  /* sta: chained mode                */
+       #define   WSS     0x08  /* sta: wide scsi send           [W]*/
+       #define   WSR     0x01  /* sta: wide scsi received       [W]*/
+
+#define SCNTL3         0x03    /* cnf system clock dependent       */
+       #define   EWS     0x08  /* cmd: enable wide scsi         [W]*/
+       #define   ULTRA   0x80  /* cmd: ULTRA enable                */
+                               /* bits 0-2, 7 rsvd for C1010       */
+
+#define SCID                   0x04            /* cnf host adapter scsi address    */
+       #define   RRE     0x40  /* r/w:e enable response to resel.  */
+       #define   SRE     0x20  /* r/w:e enable response to select  */
+
+#define SXFER                  0x05            /* ### Sync speed and count         */
+                               /* bits 6-7 rsvd for C1010          */
+
+#define SDID                   0x06    /* ### Destination-ID               */
+
+#define GPREG                  0x07    /* ??? IO-Pins                      */
+
+#define SFBR                   0x08    /* ### First byte in phase          */
+
+#define SOCL                   0x09
+       #define   CREQ    0x80  /* r/w: SCSI-REQ                    */
+       #define   CACK    0x40  /* r/w: SCSI-ACK                    */
+       #define   CBSY    0x20  /* r/w: SCSI-BSY                    */
+       #define   CSEL    0x10  /* r/w: SCSI-SEL                    */
+       #define   CATN    0x08  /* r/w: SCSI-ATN                    */
+       #define   CMSG    0x04  /* r/w: SCSI-MSG                    */
+       #define   CC_D    0x02  /* r/w: SCSI-C_D                    */
+       #define   CI_O    0x01  /* r/w: SCSI-I_O                    */
+
+#define SSID                   0x0a
+
+#define SBCL                   0x0b
+
+#define DSTAT                  0x0c
+  #define   DFE     0x80  /* sta: dma fifo empty              */
+  #define   MDPE    0x40  /* int: master data parity error    */
+  #define   BF      0x20  /* int: script: bus fault           */
+  #define   ABRT    0x10  /* int: script: command aborted     */
+  #define   SSI     0x08  /* int: script: single step         */
+  #define   SIR     0x04  /* int: script: interrupt instruct. */
+  #define   IID     0x01  /* int: script: illegal instruct.   */
+
+#define SSTAT0         0x0d
+  #define   ILF     0x80  /* sta: data in SIDL register lsb   */
+  #define   ORF     0x40  /* sta: data in SODR register lsb   */
+  #define   OLF     0x20  /* sta: data in SODL register lsb   */
+  #define   AIP     0x10  /* sta: arbitration in progress     */
+  #define   LOA     0x08  /* sta: arbitration lost            */
+  #define   WOA     0x04  /* sta: arbitration won             */
+  #define   IRST    0x02  /* sta: scsi reset signal           */
+  #define   SDP     0x01  /* sta: scsi parity signal          */
+
+#define SSTAT1         0x0e
+       #define   FF3210  0xf0  /* sta: bytes in the scsi fifo      */
+
+#define SSTAT2         0x0f
+  #define   ILF1    0x80  /* sta: data in SIDL register msb[W]*/
+  #define   ORF1    0x40  /* sta: data in SODR register msb[W]*/
+  #define   OLF1    0x20  /* sta: data in SODL register msb[W]*/
+  #define   DM      0x04  /* sta: DIFFSENS mismatch (895/6 only) */
+  #define   LDSC    0x02  /* sta: disconnect & reconnect      */
+
+#define DSA                            0x10            /* --> Base page                    */
+#define DSA1                   0x11
+#define DSA2                   0x12
+#define DSA3                   0x13
+
+#define ISTAT                  0x14    /* --> Main Command and status      */
+  #define   CABRT   0x80  /* cmd: abort current operation     */
+  #define   SRST    0x40  /* mod: reset chip                  */
+  #define   SIGP    0x20  /* r/w: message from host to ncr    */
+  #define   SEM     0x10  /* r/w: message between host + ncr  */
+  #define   CON     0x08  /* sta: connected to scsi           */
+  #define   INTF    0x04  /* sta: int on the fly (reset by wr)*/
+  #define   SIP     0x02  /* sta: scsi-interrupt              */
+  #define   DIP     0x01  /* sta: host/script interrupt       */
+
+
+#define CTEST0         0x18
+#define CTEST1         0x19
+#define CTEST2         0x1a
+       #define   CSIGP   0x40
+                               /* bits 0-2,7 rsvd for C1010        */
+
+#define CTEST3         0x1b
+       #define   FLF     0x08  /* cmd: flush dma fifo              */
+       #define   CLF           0x04    /* cmd: clear dma fifo              */
+       #define   FM      0x02  /* mod: fetch pin mode              */
+       #define   WRIE    0x01  /* mod: write and invalidate enable */
+                               /* bits 4-7 rsvd for C1010          */
+
+#define DFIFO                  0x20
+#define CTEST4         0x21
+       #define   BDIS    0x80  /* mod: burst disable               */
+       #define   MPEE    0x08  /* mod: master parity error enable  */
+
+#define CTEST5         0x22
+       #define   DFS     0x20  /* mod: dma fifo size               */
+                               /* bits 0-1, 3-7 rsvd for C1010          */
+#define CTEST6         0x23
+
+#define DBC                            0x24    /* ### Byte count and command       */
+#define DNAD                   0x28    /* ### Next command register        */
+#define DSP                            0x2c    /* --> Script Pointer               */
+#define DSPS                   0x30    /* --> Script pointer save/opcode#2 */
+
+#define SCRATCHA       0x34  /* Temporary register a            */
+#define SCRATCHA1      0x35
+#define SCRATCHA2      0x36
+#define SCRATCHA3      0x37
+
+#define DMODE                  0x38
+       #define   BL_2    0x80  /* mod: burst length shift value +2 */
+       #define   BL_1    0x40  /* mod: burst length shift value +1 */
+       #define   ERL     0x08  /* mod: enable read line            */
+       #define   ERMP    0x04  /* mod: enable read multiple        */
+       #define   BOF     0x02  /* mod: burst op code fetch         */
+       #define   MAN     0x01  /* mod: manual start                                     */
+
+#define DIEN           0x39
+#define SBR                    0x3a
+
+#define DCNTL          0x3b                    /* --> Script execution control     */
+       #define   CLSE    0x80  /* mod: cache line size enable      */
+       #define   PFF     0x40  /* cmd: pre-fetch flush             */
+       #define   PFEN    0x20  /* mod: pre-fetch enable            */
+       #define   SSM     0x10  /* mod: single step mode            */
+       #define   IRQM    0x08  /* mod: irq mode (1 = totem pole !) */
+       #define   STD     0x04  /* cmd: start dma mode              */
+       #define   IRQD    0x02  /* mod: irq disable                 */
+       #define   NOCOM   0x01  /* cmd: protect sfbr while reselect */
+                               /* bits 0-1 rsvd for C1010          */
+
+#define ADDER                  0x3c
+
+#define SIEN                   0x40    /* -->: interrupt enable            */
+#define SIST                   0x42    /* <--: interrupt status            */
+  #define   SBMC    0x1000/* sta: SCSI Bus Mode Change (895/6 only) */
+  #define   STO     0x0400/* sta: timeout (select)            */
+  #define   GEN     0x0200/* sta: timeout (general)           */
+  #define   HTH     0x0100/* sta: timeout (handshake)         */
+  #define   MA      0x80  /* sta: phase mismatch              */
+  #define   CMP     0x40  /* sta: arbitration complete        */
+  #define   SEL     0x20  /* sta: selected by another device  */
+  #define   RSL     0x10  /* sta: reselected by another device*/
+  #define   SGE     0x08  /* sta: gross error (over/underflow)*/
+  #define   UDC     0x04  /* sta: unexpected disconnect       */
+  #define   RST     0x02  /* sta: scsi bus reset detected     */
+  #define   PAR     0x01  /* sta: scsi parity error           */
+
+#define SLPAR                          0x44
+#define SWIDE                          0x45
+#define MACNTL                 0x46
+#define GPCNTL                 0x47
+#define STIME0                 0x48    /* cmd: timeout for select&handshake*/
+#define STIME1                 0x49    /* cmd: timeout user defined        */
+#define RESPID                 0x4a    /* sta: Reselect-IDs                */
+
+#define STEST0                 0x4c
+
+#define STEST1                 0x4d
+       #define   SCLK    0x80  /* Use the PCI clock as SCSI clock      */
+       #define   DBLEN   0x08  /* clock doubler running                */
+       #define   DBLSEL  0x04  /* clock doubler selected               */
+  
+
+#define STEST2                 0x4e
+       #define   ROF     0x40  /* reset scsi offset (after gross error!) */
+       #define   EXT     0x02  /* extended filtering                     */
+
+#define STEST3                 0x4f
+       #define   TE     0x80   /* c: tolerAnt enable */
+       #define   HSC    0x20   /* c: Halt SCSI Clock */
+       #define   CSF    0x02   /* c: clear scsi fifo */
+
+#define SIDL                   0x50    /* Lowlevel: latched from scsi data */
+#define STEST4         0x52
+       #define SMODE   0xc0    /* SCSI bus mode      (895/6 only) */
+       #define SMODE_HVD 0x40  /* High Voltage Differential       */
+       #define SMODE_SE  0x80  /* Single Ended                    */
+       #define SMODE_LVD 0xc0  /* Low Voltage Differential        */
+       #define LCKFRQ 0x20     /* Frequency Lock (895/6 only)     */
+                               /* bits 0-5 rsvd for C1010          */
+
+#define SODL                   0x54    /* Lowlevel: data out to scsi data  */
+
+#define SBDL                   0x58    /* Lowlevel: data from scsi data    */
+
+
+
+
+/*-----------------------------------------------------------
+**
+**     Utility macros for the script.
+**
+**-----------------------------------------------------------
+*/
+
+#define REG(r) (r)
+
+/*-----------------------------------------------------------
+**
+**     SCSI phases
+**
+**     DT phases illegal for ncr driver.
+**
+**-----------------------------------------------------------
+*/
+
+#define        SCR_DATA_OUT    0x00000000
+#define        SCR_DATA_IN     0x01000000
+#define        SCR_COMMAND     0x02000000
+#define        SCR_STATUS      0x03000000
+#define SCR_DT_DATA_OUT        0x04000000
+#define SCR_DT_DATA_IN 0x05000000
+#define SCR_MSG_OUT    0x06000000
+#define SCR_MSG_IN      0x07000000
+
+#define SCR_ILG_OUT    0x04000000
+#define SCR_ILG_IN     0x05000000
+
+/*-----------------------------------------------------------
+**
+**     Data transfer via SCSI.
+**
+**-----------------------------------------------------------
+**
+**     MOVE_ABS (LEN)
+**     <<start address>>
+**
+**     MOVE_IND (LEN)
+**     <<dnad_offset>>
+**
+**     MOVE_TBL
+**     <<dnad_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define OPC_MOVE          0x08000000
+
+#define SCR_MOVE_ABS(l) ((0x00000000 | OPC_MOVE) | (l))
+#define SCR_MOVE_IND(l) ((0x20000000 | OPC_MOVE) | (l))
+#define SCR_MOVE_TBL     (0x10000000 | OPC_MOVE)
+
+#define SCR_CHMOV_ABS(l) ((0x00000000) | (l))
+#define SCR_CHMOV_IND(l) ((0x20000000) | (l))
+#define SCR_CHMOV_TBL     (0x10000000)
+
+
+/*-----------------------------------------------------------
+**
+**     Selection
+**
+**-----------------------------------------------------------
+**
+**     SEL_ABS | SCR_ID (0..15)    [ | REL_JMP]
+**     <<alternate_address>>
+**
+**     SEL_TBL | << dnad_offset>>  [ | REL_JMP]
+**     <<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define        SCR_SEL_ABS     0x40000000
+#define        SCR_SEL_ABS_ATN 0x41000000
+#define        SCR_SEL_TBL     0x42000000
+#define        SCR_SEL_TBL_ATN 0x43000000
+
+
+#define SCR_JMP_REL     0x04000000
+#define SCR_ID(id)     (((unsigned long)(id)) << 16)
+
+/*-----------------------------------------------------------
+**
+**     Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+**     WAIT_DISC
+**     dummy: <<alternate_address>>
+**
+**     WAIT_RESEL
+**     <<alternate_address>>
+**
+**-----------------------------------------------------------
+*/
+
+#define        SCR_WAIT_DISC   0x48000000
+#define SCR_WAIT_RESEL  0x50000000
+
+/*-----------------------------------------------------------
+**
+**     Bit Set / Reset
+**
+**-----------------------------------------------------------
+**
+**     SET (flags {|.. })
+**
+**     CLR (flags {|.. })
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_SET(f)     (0x58000000 | (f))
+#define SCR_CLR(f)     (0x60000000 | (f))
+
+#define        SCR_CARRY       0x00000400
+#define        SCR_TRG         0x00000200
+#define        SCR_ACK         0x00000040
+#define        SCR_ATN         0x00000008
+
+
+
+
+/*-----------------------------------------------------------
+**
+**     Memory to memory move
+**
+**-----------------------------------------------------------
+**
+**     COPY (bytecount)
+**     << source_address >>
+**     << destination_address >>
+**
+**     SCR_COPY   sets the NO FLUSH option by default.
+**     SCR_COPY_F does not set this option.
+**
+**     For chips which do not support this option,
+**     ncr_copy_and_bind() will remove this bit.
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_FLUSH 0x01000000
+
+#define SCR_COPY(n) (0xc0000000 | SCR_NO_FLUSH | (n))
+#define SCR_COPY_F(n) (0xc0000000 | (n))
+
+/*-----------------------------------------------------------
+**
+**     Register move and binary operations
+**
+**-----------------------------------------------------------
+**
+**     SFBR_REG (reg, op, data)        reg  = SFBR op data
+**     << 0 >>
+**
+**     REG_SFBR (reg, op, data)        SFBR = reg op data
+**     << 0 >>
+**
+**     REG_REG  (reg, op, data)        reg  = reg op data
+**     << 0 >>
+**
+**-----------------------------------------------------------
+**     On 810A, 860, 825A, 875, 895 and 896 chips the content 
+**     of SFBR register can be used as data (SCR_SFBR_DATA).
+**     The 896 has additionnal IO registers starting at 
+**     offset 0x80. Bit 7 of register offset is stored in 
+**     bit 7 of the SCRIPTS instruction first DWORD.
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS(ofs) ((((ofs) & 0x7f) << 16ul)) /* + ((ofs) & 0x80)) */
+
+#define SCR_SFBR_REG(reg,op,data) \
+        (0x68000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_SFBR(reg,op,data) \
+        (0x70000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+#define SCR_REG_REG(reg,op,data) \
+        (0x78000000 | (SCR_REG_OFS(REG(reg))) | (op) | (((data)&0xff)<<8ul))
+
+
+#define      SCR_LOAD   0x00000000
+#define      SCR_SHL    0x01000000
+#define      SCR_OR     0x02000000
+#define      SCR_XOR    0x03000000
+#define      SCR_AND    0x04000000
+#define      SCR_SHR    0x05000000
+#define      SCR_ADD    0x06000000
+#define      SCR_ADDC   0x07000000
+
+#define      SCR_SFBR_DATA   (0x00800000>>8ul) /* Use SFBR as data */
+
+/*-----------------------------------------------------------
+**
+**     FROM_REG (reg)            SFBR = reg
+**     << 0 >>
+**
+**     TO_REG   (reg)            reg  = SFBR
+**     << 0 >>
+**
+**     LOAD_REG (reg, data)      reg  = <data>
+**     << 0 >>
+**
+**     LOAD_SFBR(data)           SFBR = <data>
+**     << 0 >>
+**
+**-----------------------------------------------------------
+*/
+
+#define        SCR_FROM_REG(reg) \
+       SCR_REG_SFBR(reg,SCR_OR,0)
+
+#define        SCR_TO_REG(reg) \
+       SCR_SFBR_REG(reg,SCR_OR,0)
+
+#define        SCR_LOAD_REG(reg,data) \
+       SCR_REG_REG(reg,SCR_LOAD,data)
+
+#define SCR_LOAD_SFBR(data) \
+        (SCR_REG_SFBR (gpreg, SCR_LOAD, data))
+
+/*-----------------------------------------------------------
+**
+**     LOAD  from memory   to register.
+**     STORE from register to memory.
+**
+**     Only supported by 810A, 860, 825A, 875, 895 and 896.
+**
+**-----------------------------------------------------------
+**
+**     LOAD_ABS (LEN)
+**     <<start address>>
+**
+**     LOAD_REL (LEN)        (DSA relative)
+**     <<dsa_offset>>
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_REG_OFS2(ofs) (((ofs) & 0xff) << 16ul)
+#define SCR_NO_FLUSH2  0x02000000
+#define SCR_DSA_REL2   0x10000000
+
+#define SCR_LOAD_R(reg, how, n) \
+        (0xe1000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_STORE_R(reg, how, n) \
+        (0xe0000000 | how | (SCR_REG_OFS2(REG(reg))) | (n))
+
+#define SCR_LOAD_ABS(reg, n)   SCR_LOAD_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_LOAD_REL(reg, n)   SCR_LOAD_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2, n)
+#define SCR_LOAD_ABS_F(reg, n) SCR_LOAD_R(reg, 0, n)
+#define SCR_LOAD_REL_F(reg, n) SCR_LOAD_R(reg, SCR_DSA_REL2, n)
+
+#define SCR_STORE_ABS(reg, n)  SCR_STORE_R(reg, SCR_NO_FLUSH2, n)
+#define SCR_STORE_REL(reg, n)  SCR_STORE_R(reg, SCR_NO_FLUSH2|SCR_DSA_REL2,n)
+#define SCR_STORE_ABS_F(reg, n)        SCR_STORE_R(reg, 0, n)
+#define SCR_STORE_REL_F(reg, n)        SCR_STORE_R(reg, SCR_DSA_REL2, n)
+
+
+/*-----------------------------------------------------------
+**
+**     Waiting for Disconnect or Reselect
+**
+**-----------------------------------------------------------
+**
+**     JUMP            [ | IFTRUE/IFFALSE ( ... ) ]
+**     <<address>>
+**
+**     JUMPR           [ | IFTRUE/IFFALSE ( ... ) ]
+**     <<distance>>
+**
+**     CALL            [ | IFTRUE/IFFALSE ( ... ) ]
+**     <<address>>
+**
+**     CALLR           [ | IFTRUE/IFFALSE ( ... ) ]
+**     <<distance>>
+**
+**     RETURN          [ | IFTRUE/IFFALSE ( ... ) ]
+**     <<dummy>>
+**
+**     INT             [ | IFTRUE/IFFALSE ( ... ) ]
+**     <<ident>>
+**
+**     INT_FLY         [ | IFTRUE/IFFALSE ( ... ) ]
+**     <<ident>>
+**
+**     Conditions:
+**          WHEN (phase)
+**          IF   (phase)
+**          CARRYSET
+**          DATA (data, mask)
+**
+**-----------------------------------------------------------
+*/
+
+#define SCR_NO_OP       0x80000000
+#define SCR_JUMP        0x80080000
+#define SCR_JUMP64      0x80480000
+#define SCR_JUMPR       0x80880000
+#define SCR_CALL        0x88080000
+#define SCR_CALLR       0x88880000
+#define SCR_RETURN      0x90080000
+#define SCR_INT         0x98080000
+#define SCR_INT_FLY     0x98180000
+
+#define IFFALSE(arg)   (0x00080000 | (arg))
+#define IFTRUE(arg)    (0x00000000 | (arg))
+
+#define WHEN(phase)    (0x00030000 | (phase))
+#define IF(phase)      (0x00020000 | (phase))
+
+#define DATA(D)        (0x00040000 | ((D) & 0xff))
+#define MASK(D,M)      (0x00040000 | (((M ^ 0xff) & 0xff) << 8ul)|((D) & 0xff))
+
+#define CARRYSET       (0x00200000)
+
+
+
+#define SIR_COMPLETE                                    0x10000000
+/* script errors */
+#define SIR_SEL_ATN_NO_MSG_OUT 0x00000001
+#define SIR_CMD_OUT_ILL_PH     0x00000002
+#define SIR_STATUS_ILL_PH                       0x00000003
+#define SIR_MSG_RECEIVED                        0x00000004
+#define SIR_DATA_IN_ERR        0x00000005
+#define SIR_DATA_OUT_ERR                        0x00000006
+#define SIR_SCRIPT_ERROR                        0x00000007
+#define SIR_MSG_OUT_NO_CMD              0x00000008
+#define SIR_MSG_OVER7                                   0x00000009
+/* Fly interrupt */
+#define INT_ON_FY                                                       0x00000080
+/* Hardware errors  are defined in scsi.h */
+
+#define SCSI_IDENTIFY                                  0xC0 
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#endif
diff --git a/board/mpl/common/usb_uhci.c b/board/mpl/common/usb_uhci.c
new file mode 100644 (file)
index 0000000..8f01ddb
--- /dev/null
@@ -0,0 +1,1153 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ * Note: Part of this code has been derived from linux
+ * 
+ */
+
+/**********************************************************************
+ * How it works:
+ * -------------
+ * The framelist / Transfer descriptor / Queue Heads are similar like 
+ * in the linux usb_uhci.c.
+ *
+ * During initialization, the following skeleton is allocated in init_skel:
+ *
+ *         framespecific           |           common chain
+ *
+ * framelist[]
+ * [  0 ]-----> TD ---------\
+ * [  1 ]-----> TD ----------> TD ------> QH -------> QH -------> QH ---> NULL
+ *   ...        TD ---------/
+ * [1023]-----> TD --------/
+ *
+ *              ^^             ^^         ^^          ^^          ^^
+ *              7 TDs for      1 TD for   Start of    Start of    End Chain
+ *              INT (2-128ms)  1ms-INT    CTRL Chain  BULK Chain
+ *
+ *
+ * Since this is a bootloader, the isochronous transfer descriptor have been removed.
+ * 
+ * Interrupt Transfers.
+ * --------------------
+ * For Interupt transfers USB_MAX_TEMP_INT_TD Transfer descriptor are available. They 
+ * will be inserted after the appropriate (depending the interval setting) skeleton TD.
+ * If an interrupt has been detected the dev->irqhandler is called. The status and number
+ * of transfered bytes is stored in dev->irq_status resp. dev->irq_act_len. If the 
+ * dev->irqhandler returns 0, the interrupt TD is removed and disabled. If an 1 is returned,
+ * the interrupt TD will be reactivated.
+ *
+ * Control Transfers
+ * -----------------
+ * Control Transfers are issued by filling the tmp_td with the appropriate data and connect
+ * them to the qh_cntrl queue header. Before other control/bulk transfers can be issued,
+ * the programm has to wait for completion. This does not allows asynchronous data transfer.
+ *
+ * Bulk Transfers
+ * --------------
+ * Bulk Transfers are issued by filling the tmp_td with the appropriate data and connect
+ * them to the qh_bulk queue header. Before other control/bulk transfers can be issued,
+ * the programm has to wait for completion. This does not allows asynchronous data transfer.
+ *
+ *
+ */
+
+#include <ppcboot.h>
+
+#ifdef CONFIG_4xx
+#include <405gp_pci.h>
+#endif
+#ifdef CONFIG_USB_UHCI
+
+#include <usb.h>
+#include "usb_uhci.h"
+
+#define USB_MAX_TEMP_TD      128  /* number of temporary TDs for bulk and control transfers */
+#define USB_MAX_TEMP_INT_TD  32   /* number of temporary TDs for Interrupt transfers */
+
+
+#undef USB_UHCI_DEBUG
+
+#ifdef USB_UHCI_DEBUG
+#define        USB_UHCI_PRINTF(fmt,args...)    printf (fmt ,##args)
+#else
+#define USB_UHCI_PRINTF(fmt,args...)
+#endif
+
+
+static int irqvec = -1;            /* irq vector, if -1 uhci is stopped / reseted */
+unsigned long usb_base_addr;       /* base address */
+
+static uhci_td_t td_int[8];        /* Interrupt Transfer descriptors */
+static uhci_qh_t qh_cntrl;         /* control Queue Head */
+static uhci_qh_t qh_bulk;          /*  bulk Queue Head */
+static uhci_qh_t qh_end;           /* end Queue Head */
+static uhci_td_t td_last;          /* last TD (linked with end chain) */
+
+/* temporary tds */
+static uhci_td_t tmp_td[USB_MAX_TEMP_TD];          /* temporary bulk/control td's  */
+static uhci_td_t tmp_int_td[USB_MAX_TEMP_INT_TD];  /* temporary interrupt td's  */
+
+static unsigned long framelist[1024] __attribute__ ((aligned (0x1000))); /* frame list */
+
+static struct virt_root_hub rh;   /* struct for root hub */
+
+/**********************************************************************
+ * some forward decleration 
+ */
+int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, 
+                                               void *buffer, int transfer_len,struct devrequest *setup);
+
+/* fill a td with the approproiate data. Link, status, info and buffer
+ * are used by the USB controller itselfes, dev is used to identify the 
+ * "connected" device 
+ */
+void usb_fill_td(uhci_td_t* td,unsigned long link,unsigned long status,
+                                       unsigned long info, unsigned long buffer, unsigned long dev)
+{
+       td->link=swap_32(link);
+       td->status=swap_32(status);
+       td->info=swap_32(info);
+       td->buffer=swap_32(buffer);
+       td->dev_ptr=dev; 
+}
+
+/* fill a qh with the approproiate data. Head and element are used by the USB controller 
+ * itselfes. As soon as a valid dev_ptr is filled, a td chain is connected to the qh.
+ * Please note, that after completion of the td chain, the entry element is removed /
+ * marked invalid by the USB controller.
+ */
+void usb_fill_qh(uhci_qh_t* qh,unsigned long head,unsigned long element)
+{
+       qh->head=swap_32(head);
+       qh->element=swap_32(element);
+       qh->dev_ptr=0L;
+}
+
+/* get the status of a td->status 
+ */
+unsigned long usb_uhci_td_stat(unsigned long status)
+{
+       unsigned long result=0;
+       result |= (status & TD_CTRL_NAK)      ? USB_ST_NAK_REC : 0; 
+       result |= (status & TD_CTRL_STALLED)  ? USB_ST_STALLED : 0; 
+       result |= (status & TD_CTRL_DBUFERR)  ? USB_ST_BUF_ERR : 0; 
+       result |= (status & TD_CTRL_BABBLE)   ? USB_ST_BABBLE_DET : 0; 
+       result |= (status & TD_CTRL_CRCTIMEO) ? USB_ST_CRC_ERR : 0; 
+       result |= (status & TD_CTRL_BITSTUFF) ? USB_ST_BIT_ERR : 0; 
+       result |= (status & TD_CTRL_ACTIVE)   ? USB_ST_NOT_PROC : 0;
+       return result;
+}
+
+/* get the status and the transfered len of a td chain.
+ * called from the completion handler
+ */
+int usb_get_td_status(uhci_td_t *td,struct usb_device *dev)
+{
+       unsigned long temp,info;
+       unsigned long stat;
+       uhci_td_t *mytd=td;
+       
+       if(dev->devnum==rh.devnum)
+               return 0;
+       dev->act_len=0;
+       stat=0;
+       do {
+               temp=swap_32((unsigned long)mytd->status);
+               stat=usb_uhci_td_stat(temp);
+               info=swap_32((unsigned long)mytd->info);
+               if(((info & 0xff)!= USB_PID_SETUP) && 
+                               (((info >> 21) & 0x7ff)!= 0x7ff) && 
+                               (temp & 0x7FF)!=0x7ff) 
+               {  /* if not setup and not null data pack */
+                       dev->act_len+=(temp & 0x7FF) + 1; /* the transfered len is act_len + 1 */ 
+               }
+               if(stat) {           /* status no ok */
+                       dev->status=stat;
+                       return -1;
+               }
+               temp=swap_32((unsigned long)mytd->link);
+               mytd=(uhci_td_t *)(temp & 0xfffffff0);
+       }while((temp & 0x1)==0); /* process all TDs */
+       dev->status=stat;
+       return 0; /* Ok */
+}
+
+
+/*-------------------------------------------------------------------
+ *                         LOW LEVEL STUFF
+ *          assembles QHs und TDs for control, bulk and iso
+ *-------------------------------------------------------------------*/
+
+/* Submits a control message. That is a Setup, Data and Status transfer.
+ * Routine does not wait for completion. 
+ */
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                                                                               int transfer_len,struct devrequest *setup)
+{
+       unsigned long destination, status;
+       int maxsze = usb_maxpacket(dev, pipe);
+       unsigned long dataptr;
+       int len; 
+       int pktsze;
+       int i=0;
+       
+       if (!maxsze) {
+               USB_UHCI_PRINTF("uhci_submit_control_urb: pipesize for pipe %lx is zero\n", pipe);
+               return -1;
+       }
+       if(((pipe>>8)&0x7f)==rh.devnum) {
+               /* this is the root hub -> redirect it */
+               return uhci_submit_rh_msg(dev,pipe,buffer,transfer_len,setup);
+       }
+       USB_UHCI_PRINTF("uhci_submit_control start len %x, maxsize %x\n",transfer_len,maxsze);
+       /* The "pipe" thing contains the destination in bits 8--18 */
+       destination = (pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP; /* Setup stage */
+       /* 3 errors */
+       status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
+       /* (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD); */ 
+       /*  Build the TD for the control request, try forever, 8 bytes of data */
+       usb_fill_td(&tmp_td[i],UHCI_PTR_TERM ,status, destination | (7 << 21),(unsigned long)setup,(unsigned long)dev);
+#if 0
+       {
+               char *sp=(char *)setup;
+               printf("SETUP to pipe %lx: %x %x %x %x %x %x %x %x\n", pipe,
+                   sp[0],sp[1],sp[2],sp[3],sp[4],sp[5],sp[6],sp[7]);
+       }
+#endif
+       dataptr = (unsigned long)buffer;
+       len=transfer_len;
+       
+       /* If direction is "send", change the frame from SETUP (0x2D)
+          to OUT (0xE1). Else change it from SETUP to IN (0x69). */
+       destination = (pipe & PIPE_DEVEP_MASK) | ((pipe & USB_DIR_IN)==0 ? USB_PID_OUT : USB_PID_IN);
+       while (len > 0) {
+               /* data stage */
+               pktsze = len;
+               i++;
+               if (pktsze > maxsze)
+                       pktsze = maxsze;
+               destination ^= 1 << TD_TOKEN_TOGGLE;    /* toggle DATA0/1 */
+               usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, destination | ((pktsze - 1) << 21),dataptr,(unsigned long)dev);   /* Status, pktsze bytes of data */
+               tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]);
+
+               dataptr += pktsze;
+               len -= pktsze;
+       }
+
+       /*  Build the final TD for control status */
+       /* It's only IN if the pipe is out AND we aren't expecting data */
+
+       destination &= ~UHCI_PID;
+       if (((pipe & USB_DIR_IN)==0) || (transfer_len == 0))
+               destination |= USB_PID_IN;
+       else
+               destination |= USB_PID_OUT;
+       destination |= 1 << TD_TOKEN_TOGGLE;    /* End in Data1 */
+       i++;
+       status &=~TD_CTRL_SPD;
+       /* no limit on errors on final packet , 0 bytes of data */
+       usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status | TD_CTRL_IOC, destination | (UHCI_NULL_DATA_SIZE << 21),0,(unsigned long)dev);
+       tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]);    /* queue status td */
+       /*      usb_show_td(i+1);*/
+       USB_UHCI_PRINTF("uhci_submit_control end (%d tmp_tds used)\n",i);
+       /* first mark the control QH element terminated */
+       qh_cntrl.element=0xffffffffL;
+       /* set qh active */
+       qh_cntrl.dev_ptr=(unsigned long)dev;
+       /* fill in tmp_td_chain */
+       qh_cntrl.element=swap_32((unsigned long)&tmp_td[0]);    
+       return 0;
+}
+
+/*-------------------------------------------------------------------
+ * Prepare TDs for bulk transfers.
+ */
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len)
+{
+       unsigned long destination, status,info;
+       unsigned long dataptr;
+       int maxsze = usb_maxpacket(dev, pipe);
+       int len;
+       int i=0;
+
+       if(transfer_len < 0) {
+               printf("Negative transfer length in submit_bulk\n");
+               return -1;
+       }
+       if (!maxsze)
+               return -1;
+       /* The "pipe" thing contains the destination in bits 8--18. */
+       destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
+       /* 3 errors */
+       status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
+       /*      ((urb->transfer_flags & USB_DISABLE_SPD) ? 0 : TD_CTRL_SPD) | (3 << 27); */
+       /* Build the TDs for the bulk request */
+       len = transfer_len;
+       dataptr = (unsigned long)buffer;
+       do {                                    
+               int pktsze = len;
+               if (pktsze > maxsze)
+                       pktsze = maxsze;
+               /* pktsze bytes of data  */
+               info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) |
+                       (usb_gettoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
+
+               if((len-pktsze)==0)
+                       status |= TD_CTRL_IOC;  /* last one generates INT */
+
+               usb_fill_td(&tmp_td[i],UHCI_PTR_TERM, status, info,dataptr,(unsigned long)dev); /* Status, pktsze bytes of data */
+               if(i>0)
+                       tmp_td[i-1].link=swap_32((unsigned long)&tmp_td[i]);
+               i++;
+               dataptr += pktsze;
+               len -= pktsze;
+               usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
+       } while (len > 0);
+       /* first mark the bulk QH element terminated */
+       qh_bulk.element=0xffffffffL;
+       /* set qh active */
+       qh_bulk.dev_ptr=(unsigned long)dev;
+       /* fill in tmp_td_chain */
+       qh_bulk.element=swap_32((unsigned long)&tmp_td[0]);     
+       return 0;
+}
+
+
+/* search a free interrupt td
+ */
+uhci_td_t *uhci_alloc_int_td(void)
+{
+       int i;
+       for(i=0;i<USB_MAX_TEMP_INT_TD;i++) {
+               if(tmp_int_td[i].dev_ptr==0) /* no device assigned -> free TD */
+                       return &tmp_int_td[i];
+       }
+       return NULL;
+}
+
+#if 0
+void uhci_show_temp_int_td(void)
+{
+       int i;
+       for(i=0;i<USB_MAX_TEMP_INT_TD;i++) {
+               if((tmp_int_td[i].dev_ptr&0x01)!=0x1L) /* no device assigned -> free TD */
+                       printf("temp_td %d is assigned to dev %lx\n",i,tmp_int_td[i].dev_ptr);
+       }
+       printf("all others temp_tds are free\n");
+}
+#endif
+/*-------------------------------------------------------------------
+ * submits USB interrupt (ie. polling ;-) 
+ */
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len, int interval)
+{
+       int nint, n;
+       unsigned long status, destination;
+       unsigned long info,tmp;
+       uhci_td_t *mytd;
+       if (interval < 0 || interval >= 256)
+               return -1;
+
+       if (interval == 0)
+               nint = 0;
+       else {
+               for (nint = 0, n = 1; nint <= 8; nint++, n += n)        /* round interval down to 2^n */
+                {
+                       if(interval < n) {
+                               interval = n / 2;
+                               break;
+                       }
+               }
+               nint--;
+       }
+
+       USB_UHCI_PRINTF("Rounded interval to %i, chain  %i\n", interval, nint);
+       mytd=uhci_alloc_int_td();
+       if(mytd==NULL) {
+               printf("No free INT TDs found\n");
+               return -1;
+       }
+       status = (pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | (3 << 27);
+/*             (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+*/
+       
+       destination =(pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe) | (((transfer_len - 1) & 0x7ff) << 21);
+
+       info = destination | (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << TD_TOKEN_TOGGLE);
+       tmp = swap_32(td_int[nint].link);
+       usb_fill_td(mytd,tmp,status, info,(unsigned long)buffer,(unsigned long)dev);
+       /* Link it */
+       tmp = swap_32((unsigned long)mytd);
+       td_int[nint].link=tmp;
+       
+       usb_dotoggle (dev, usb_pipeendpoint (pipe), usb_pipeout (pipe));
+       
+       return 0;
+}
+
+/**********************************************************************
+ * Low Level functions 
+ */
+
+
+void reset_hc(void)
+{
+       
+       /* Global reset for 100ms */
+       out16r( usb_base_addr + USBPORTSC1,0x0204);
+       out16r( usb_base_addr + USBPORTSC2,0x0204);
+       out16r( usb_base_addr + USBCMD,USBCMD_GRESET | USBCMD_RS);
+       /* Turn off all interrupts */
+       out16r(usb_base_addr + USBINTR,0);
+       wait_ms(50);
+       out16r( usb_base_addr + USBCMD,0);
+       wait_ms(10);
+}
+               
+void start_hc(void)
+{
+       int timeout = 1000;
+
+       while(in16r(usb_base_addr + USBCMD) & USBCMD_HCRESET) {
+               if (!--timeout) {
+                       printf("USBCMD_HCRESET timed out!\n");
+                       break;
+               }
+       }
+       /* Turn on all interrupts */
+       out16r(usb_base_addr + USBINTR,USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP);
+       /* Start at frame 0 */
+       out16r(usb_base_addr + USBFRNUM,0);
+       /* set Framebuffer base address */
+       out32r(usb_base_addr+USBFLBASEADD,(unsigned long)&framelist);
+       /* Run and mark it configured with a 64-byte max packet */
+       out16r(usb_base_addr + USBCMD,USBCMD_RS | USBCMD_CF | USBCMD_MAXP);
+}
+
+/* Initialize the skeleton
+ */
+void usb_init_skel(void)
+{      
+       unsigned long temp;
+       int n;
+
+       for(n=0;n<USB_MAX_TEMP_INT_TD;n++)
+               tmp_int_td[n].dev_ptr=0L; /* no devices connected */
+       /* last td */
+       usb_fill_td(&td_last,UHCI_PTR_TERM,TD_CTRL_IOC ,0,0,0L); 
+  /* usb_fill_td(&td_last,UHCI_PTR_TERM,0,0,0); */
+       /* End Queue Header */
+       usb_fill_qh(&qh_end,UHCI_PTR_TERM,(unsigned long)&td_last);
+       /* Bulk Queue Header */
+       temp=(unsigned long)&qh_end;
+       usb_fill_qh(&qh_bulk,temp | UHCI_PTR_QH,UHCI_PTR_TERM);
+       /* Control Queue Header */
+       temp=(unsigned long)&qh_bulk;
+       usb_fill_qh(&qh_cntrl, temp | UHCI_PTR_QH,UHCI_PTR_TERM);
+       /* 1ms Interrupt td */
+       temp=(unsigned long)&qh_cntrl;
+       usb_fill_td(&td_int[0],temp | UHCI_PTR_QH,0,0,0,0L);
+       temp=(unsigned long)&td_int[0];
+       for(n=1; n<8; n++)
+               usb_fill_td(&td_int[n],temp,0,0,0,0L);
+       for (n = 0; n < 1024; n++) {
+       /* link all framelist pointers to one of the interrupts */
+               int m, o;
+               if ((n&127)==127)
+                       framelist[n]= swap_32((unsigned long)&td_int[0]);
+               else
+                       for (o = 1, m = 2; m <= 128; o++, m += m)
+                               if ((n & (m - 1)) == ((m - 1) / 2))
+                                               framelist[n]= swap_32((unsigned long)&td_int[o]);
+       }
+}
+
+/* check the common skeleton for completed transfers, and update the status
+ * of the "connected" device. Called from the IRQ routine.
+ */
+void usb_check_skel(void)
+{
+       struct usb_device *dev;
+       /* start with the control qh */
+       if(qh_cntrl.dev_ptr!=0) /* it's a device assigned check if this caused IRQ */ 
+       { 
+               dev=(struct usb_device *)qh_cntrl.dev_ptr;
+               usb_get_td_status(&tmp_td[0],dev); /* update status */
+               if(!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */
+                       qh_cntrl.dev_ptr=0;
+               }
+       }
+       /* now process the bulk */
+       if(qh_bulk.dev_ptr!=0) /* it's a device assigned check if this caused IRQ */ 
+       { 
+               dev=(struct usb_device *)qh_bulk.dev_ptr;
+               usb_get_td_status(&tmp_td[0],dev); /* update status */
+               if(!(dev->status & USB_ST_NOT_PROC)) { /* is not active anymore, disconnect devices */
+                       qh_bulk.dev_ptr=0;
+               }
+       }
+}                              
+
+/* check the interrupt chain, ubdate the status of the appropriate device,
+ * call the appropriate irqhandler and reactivate the TD if the irqhandler
+ * returns with 1
+ */                    
+void usb_check_int_chain(void)
+{
+       int i,res;
+       unsigned long link,status;
+       struct usb_device *dev;
+       uhci_td_t *td,*prevtd;  
+
+       for(i=0;i<8;i++) {
+               prevtd=&td_int[i]; /* the first previous td is the skeleton td */
+               link=swap_32(td_int[i].link) & 0xfffffff0; /* next in chain */
+               td=(uhci_td_t *)link; /* assign it */
+               /* all interrupt TDs are finally linked to the td_int[0].
+                * so we process all until we find the td_int[0].
+                * if int0 chain points to a QH, we're also done  
+          */
+               while(((i>0) && (link != (unsigned long)&td_int[0])) ||
+                                       ((i==0) && !(swap_32(td->link) &  UHCI_PTR_QH)))
+               {
+                       /* check if a device is assigned with this td */
+                       status=swap_32(td->status);
+                       if((td->dev_ptr!=0L) && !(status & TD_CTRL_ACTIVE)) {
+                               /* td is not active and a device is assigned -> call irqhandler */
+                               dev=(struct usb_device *)td->dev_ptr;
+                               dev->irq_act_len=((status & 0x7FF)==0x7FF) ? 0 : (status & 0x7FF) + 1; /* transfered length */
+                               dev->irq_status=usb_uhci_td_stat(status); /* get status */
+                               res=dev->irq_handle(dev); /* call irqhandler */
+                               if(res==1) { 
+                                       /* reactivate */
+                                       status|=TD_CTRL_ACTIVE;
+                                       td->status=swap_32(status);
+                                       prevtd=td; /* previous td = this td */
+                               }
+                               else {
+                                       prevtd->link=td->link; /* link previous td directly to the nex td -> unlinked */
+                                       /* remove device pointer */
+                                       td->dev_ptr=0L;
+                               }
+                       } /* if we call the irq handler */
+                       link=swap_32(td->link) & 0xfffffff0; /* next in chain */
+                       td=(uhci_td_t *)link; /* assign it */
+               } /* process all td in this int chain */
+       } /* next interrupt chain */
+}      
+                       
+
+/* usb interrupt service routine.
+ */
+void handle_usb_interrupt(void)
+{
+       unsigned short status;
+       
+       /*
+        * Read the interrupt status, and write it back to clear the
+        * interrupt cause
+        */
+
+       status = in16r(usb_base_addr + USBSTS);
+
+       if (!status)            /* shared interrupt, not mine */
+               return;
+       if (status != 1) {
+               /* remove host controller halted state */
+               if ((status&0x20) && ((in16r(usb_base_addr+USBCMD) && USBCMD_RS)==0)) {
+                       out16r(usb_base_addr + USBCMD, USBCMD_RS | in16r(usb_base_addr + USBCMD));
+               }
+       }
+       usb_check_int_chain(); /* call interrupt handlers for int tds */
+       usb_check_skel(); /* call completion handler for common transfer routines */
+       out16r(usb_base_addr+USBSTS,status);
+}
+
+
+/* init uhci
+ */
+int usb_lowlevel_init(void)
+{
+       unsigned long temp;
+       int     busdevfunc;
+
+       busdevfunc=PCI_Find_Device(USB_UHCI_VEND_ID,USB_UHCI_DEV_ID); /* get PCI Device ID */
+       if(busdevfunc==-1) {
+               printf("Error USB UHCI (%04X,%04X) not found\n",USB_UHCI_VEND_ID,USB_UHCI_DEV_ID);
+               return -1;
+       }
+       irqvec=PCI_Read_CFG_Reg(busdevfunc,PCI_CFG_DEV_INT_LINE,1);
+       irq_free_handler(irqvec);
+       USB_UHCI_PRINTF("Interrupt Line = %d, is %d\n",irqvec);
+       temp=PCI_Read_CFG_Reg(busdevfunc,PCI_CFG_DEV_INT_PIN,1);
+       USB_UHCI_PRINTF("Interrupt Pin = %ld\n",temp);
+       usb_base_addr=PCI_Read_CFG_Reg(busdevfunc,PCI_CFG_BASE_ADDRESS_4,4);
+       USB_UHCI_PRINTF("IO Base Address = 0x%lx\n",usb_base_addr);
+       usb_base_addr&=0xFFFFFFF0;
+       usb_base_addr+=CFG_ISA_IO_BASE_ADDRESS;
+       rh.devnum = 0;
+       usb_init_skel();
+       reset_hc();
+       start_hc();     
+       irq_install_handler(irqvec, (interrupt_handler_t *)handle_usb_interrupt, NULL);
+       return 0;
+}
+
+/* stop uhci 
+ */
+int usb_lowlevel_stop(void)
+{
+       if(irqvec==-1)
+               return 1;
+       irq_free_handler(irqvec);
+       reset_hc();
+       irqvec=-1;
+       return 0;
+}
+
+/*******************************************************************************************
+ * Virtual Root Hub
+ * Since the uhci does not have a real HUB, we simulate one ;-)
+ */
+#undef USB_RH_DEBUG
+
+#ifdef USB_RH_DEBUG
+#define        USB_RH_PRINTF(fmt,args...)      printf (fmt ,##args)
+static void usb_display_wValue(unsigned short wValue,unsigned short wIndex);
+static void usb_display_Req(unsigned short req);
+#else
+#define USB_RH_PRINTF(fmt,args...)
+static void usb_display_wValue(unsigned short wValue,unsigned short wIndex) {}
+static void usb_display_Req(unsigned short req) {}
+#endif
+
+static unsigned char root_hub_dev_des[] =
+{
+       0x12,                   /*  __u8  bLength; */
+       0x01,                   /*  __u8  bDescriptorType; Device */
+       0x00,                   /*  __u16 bcdUSB; v1.0 */
+       0x01,
+       0x09,                   /*  __u8  bDeviceClass; HUB_CLASSCODE */
+       0x00,                   /*  __u8  bDeviceSubClass; */
+       0x00,                   /*  __u8  bDeviceProtocol; */
+       0x08,                   /*  __u8  bMaxPacketSize0; 8 Bytes */
+       0x00,                   /*  __u16 idVendor; */
+       0x00,
+       0x00,                   /*  __u16 idProduct; */
+       0x00,
+       0x00,                   /*  __u16 bcdDevice; */
+       0x00,
+       0x01,                   /*  __u8  iManufacturer; */
+       0x00,                   /*  __u8  iProduct; */
+       0x00,                   /*  __u8  iSerialNumber; */
+       0x01                    /*  __u8  bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static unsigned char root_hub_config_des[] =
+{
+       0x09,                   /*  __u8  bLength; */
+       0x02,                   /*  __u8  bDescriptorType; Configuration */
+       0x19,                   /*  __u16 wTotalLength; */
+       0x00,
+       0x01,                   /*  __u8  bNumInterfaces; */
+       0x01,                   /*  __u8  bConfigurationValue; */
+       0x00,                   /*  __u8  iConfiguration; */
+       0x40,                   /*  __u8  bmAttributes; 
+                                  Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */
+       0x00,                   /*  __u8  MaxPower; */
+
+     /* interface */
+       0x09,                   /*  __u8  if_bLength; */
+       0x04,                   /*  __u8  if_bDescriptorType; Interface */
+       0x00,                   /*  __u8  if_bInterfaceNumber; */
+       0x00,                   /*  __u8  if_bAlternateSetting; */
+       0x01,                   /*  __u8  if_bNumEndpoints; */
+       0x09,                   /*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
+       0x00,                   /*  __u8  if_bInterfaceSubClass; */
+       0x00,                   /*  __u8  if_bInterfaceProtocol; */
+       0x00,                   /*  __u8  if_iInterface; */
+
+     /* endpoint */
+       0x07,                   /*  __u8  ep_bLength; */
+       0x05,                   /*  __u8  ep_bDescriptorType; Endpoint */
+       0x81,                   /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
+       0x03,                   /*  __u8  ep_bmAttributes; Interrupt */
+       0x08,                   /*  __u16 ep_wMaxPacketSize; 8 Bytes */
+       0x00,
+       0xff                    /*  __u8  ep_bInterval; 255 ms */
+};
+
+
+static unsigned char root_hub_hub_des[] =
+{
+       0x09,                   /*  __u8  bLength; */
+       0x29,                   /*  __u8  bDescriptorType; Hub-descriptor */
+       0x02,                   /*  __u8  bNbrPorts; */
+       0x00,                   /* __u16  wHubCharacteristics; */
+       0x00,
+       0x01,                   /*  __u8  bPwrOn2pwrGood; 2ms */
+       0x00,                   /*  __u8  bHubContrCurrent; 0 mA */
+       0x00,                   /*  __u8  DeviceRemovable; *** 7 Ports max *** */
+       0xff                    /*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
+};
+
+static unsigned char root_hub_str_index0[] =
+{
+       0x04,                   /*  __u8  bLength; */
+       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
+       0x09,                   /*  __u8  lang ID */
+       0x04,                   /*  __u8  lang ID */
+};
+
+static unsigned char root_hub_str_index1[] =
+{
+       28,                     /*  __u8  bLength; */
+       0x03,                   /*  __u8  bDescriptorType; String-descriptor */
+       'U',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'H',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'C',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'I',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       ' ',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'R',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'o',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'o',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       't',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       ' ',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'H',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'u',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+       'b',                    /*  __u8  Unicode */
+       0,                              /*  __u8  Unicode */
+};
+
+
+/*
+ * Root Hub Control Pipe (interrupt Pipes are not supported)
+ */
+
+
+int uhci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len,struct devrequest *cmd)
+{
+       void *data = buffer;
+       int leni = transfer_len;
+       int len = 0;
+       int status = 0;
+       int stat = 0;
+       int i;
+
+       unsigned short cstatus;
+
+       unsigned short bmRType_bReq;
+       unsigned short wValue;
+       unsigned short wIndex;
+       unsigned short wLength;
+
+       if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) {
+               printf("Root-Hub submit IRQ: NOT implemented\n");
+#if 0
+               uhci->rh.urb = urb;
+               uhci->rh.send = 1;
+               uhci->rh.interval = urb->interval;
+               rh_init_int_timer (urb);
+#endif
+               return 0;
+       }
+       bmRType_bReq = cmd->requesttype | cmd->request << 8;
+       wValue = swap_16(cmd->value);
+       wIndex = swap_16(cmd->index);
+       wLength = swap_16(cmd->length);
+       usb_display_Req(bmRType_bReq);
+       for (i = 0; i < 8; i++)
+               rh.c_p_r[i] = 0;
+       USB_RH_PRINTF("Root-Hub: adr: %2x cmd(%1x): %02x%02x %04x %04x %04x\n",
+            dev->devnum, 8, cmd->requesttype,cmd->request, wValue, wIndex, wLength);
+       
+       switch (bmRType_bReq) {
+               /* Request Destination:
+                  without flags: Device, 
+                  RH_INTERFACE: interface, 
+                  RH_ENDPOINT: endpoint,
+                  RH_CLASS means HUB here, 
+                  RH_OTHER | RH_CLASS  almost ever means HUB_PORT here 
+                */
+
+       case RH_GET_STATUS:
+               *(unsigned short *) data = swap_16(1);
+               len=2;
+               break;
+       case RH_GET_STATUS | RH_INTERFACE:
+               *(unsigned short *) data = swap_16(0);
+               len=2;
+               break;
+       case RH_GET_STATUS | RH_ENDPOINT:
+               *(unsigned short *) data = swap_16(0);
+               len=2;
+               break;
+       case RH_GET_STATUS | RH_CLASS:
+               *(unsigned long *) data = swap_32(0);
+               len=4;
+               break;  /* hub power ** */
+       case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+               
+               status = in16r(usb_base_addr + USBPORTSC1 + 2 * (wIndex - 1));
+               cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
+                       ((status & USBPORTSC_PEC) >> (3 - 1)) |
+                       (rh.c_p_r[wIndex - 1] << (0 + 4));
+               status = (status & USBPORTSC_CCS) |
+                       ((status & USBPORTSC_PE) >> (2 - 1)) |
+                       ((status & USBPORTSC_SUSP) >> (12 - 2)) |
+                       ((status & USBPORTSC_PR) >> (9 - 4)) |
+                       (1 << 8) |      /* power on ** */
+                       ((status & USBPORTSC_LSDA) << (-8 + 9));
+
+               *(unsigned short *) data = swap_16(status);
+               *(unsigned short *) (data + 2) = swap_16(cstatus);
+               len=4;
+               break;
+       case RH_CLEAR_FEATURE | RH_ENDPOINT:
+               switch (wValue) {
+               case (RH_ENDPOINT_STALL):
+                       len=0;
+                       break;
+               }
+               break;
+
+       case RH_CLEAR_FEATURE | RH_CLASS:
+               switch (wValue) {
+               case (RH_C_HUB_OVER_CURRENT):
+                       len=0;  /* hub power over current ** */
+                       break;
+               }
+               break;
+
+       case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+               usb_display_wValue(wValue,wIndex);
+               switch (wValue) {
+               case (RH_PORT_ENABLE):
+                       status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); 
+                       status = (status & 0xfff5) & ~USBPORTSC_PE; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       len=0;
+                       break;
+               case (RH_PORT_SUSPEND):
+                       status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); 
+                       status = (status & 0xfff5) & ~USBPORTSC_SUSP; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       len=0;
+                       break;
+               case (RH_PORT_POWER):
+                       len=0;  /* port power ** */
+                       break;
+               case (RH_C_PORT_CONNECTION):
+                       status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); 
+                       status = (status & 0xfff5) | USBPORTSC_CSC; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       len=0;
+                       break;
+               case (RH_C_PORT_ENABLE):
+                       status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); 
+                       status = (status & 0xfff5) | USBPORTSC_PEC; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       len=0;
+                       break;
+               case (RH_C_PORT_SUSPEND):
+/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
+                       len=0;
+                       break;
+               case (RH_C_PORT_OVER_CURRENT):
+                       len=0;
+                       break;
+               case (RH_C_PORT_RESET):
+                       rh.c_p_r[wIndex - 1] = 0;
+                       len=0;
+                       break;
+               }
+               break;
+       case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+               usb_display_wValue(wValue,wIndex);
+               switch (wValue) {
+               case (RH_PORT_SUSPEND):
+                       status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); 
+                       status = (status & 0xfff5) | USBPORTSC_SUSP; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       len=0;
+                       break;
+               case (RH_PORT_RESET):
+                       status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); 
+                       status = (status & 0xfff5) | USBPORTSC_PR; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       wait_ms(10);
+                       status = (status & 0xfff5) & ~USBPORTSC_PR; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       udelay(10);
+                       status = (status & 0xfff5) | USBPORTSC_PE; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       wait_ms(10);
+                       status = (status & 0xfff5) | 0xa; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       len=0;
+                       break;
+               case (RH_PORT_POWER):
+                       len=0;  /* port power ** */
+                       break;
+               case (RH_PORT_ENABLE):
+                       status = in16r(usb_base_addr+USBPORTSC1+2*(wIndex-1)); 
+                       status = (status & 0xfff5) | USBPORTSC_PE; 
+                       out16r(usb_base_addr+USBPORTSC1+2*(wIndex-1),status);
+                       len=0;
+                       break;
+               }
+               break;
+
+       case RH_SET_ADDRESS:
+               rh.devnum = wValue;
+               len=0;
+               break;
+       case RH_GET_DESCRIPTOR:
+               switch ((wValue & 0xff00) >> 8) {
+               case (0x01):    /* device descriptor */
+                       i=sizeof(root_hub_config_des);
+                       status=i > wLength ? wLength : i;
+                       len = leni > status ? status : leni;  
+                       memcpy (data, root_hub_dev_des, len);
+                       break;
+               case (0x02):    /* configuration descriptor */
+                       i=sizeof(root_hub_config_des);
+                       status=i > wLength ? wLength : i;
+                       len = leni > status ? status : leni;  
+                       memcpy (data, root_hub_config_des, len);
+                       break;
+               case (0x03):    /*string descriptors */
+                       if(wValue==0x0300) {
+                               i=sizeof(root_hub_str_index0);
+                               status = i > wLength ? wLength : i;
+                               len = leni > status ? status : leni;  
+                               memcpy (data, root_hub_str_index0, len);
+                               break;
+                       }
+                       if(wValue==0x0301) {
+                               i=sizeof(root_hub_str_index1);
+                               status = i > wLength ? wLength : i;
+                               len = leni > status ? status : leni;  
+                               memcpy (data, root_hub_str_index1, len);
+                               break;
+                       }
+                       stat = USB_ST_STALLED;
+               }
+               break;
+
+       case RH_GET_DESCRIPTOR | RH_CLASS:
+               root_hub_hub_des[2] = 2;
+               i=sizeof(root_hub_hub_des);
+               status= i > wLength ? wLength : i;
+               len = leni > status ? status : leni;  
+               memcpy (data, root_hub_hub_des, len);
+               break;
+       case RH_GET_CONFIGURATION:
+               *(unsigned char *) data = 0x01;
+               len = 1;
+               break;
+       case RH_SET_CONFIGURATION:
+               len=0;
+               break;
+       default:
+               stat = USB_ST_STALLED;
+       }
+       USB_RH_PRINTF("Root-Hub stat %lx port1: %x port2: %x\n\n",stat,
+            in16r(usb_base_addr + USBPORTSC1), in16r(usb_base_addr + USBPORTSC2));
+       dev->act_len=len;
+       dev->status=stat;
+       return stat;
+
+}
+
+/********************************************************************************
+ * Some Debug Routines
+ */
+
+#ifdef USB_RH_DEBUG
+
+static void usb_display_Req(unsigned short req)
+{
+       USB_RH_PRINTF("- Root-Hub Request: ");
+       switch (req) {
+       case RH_GET_STATUS:
+               USB_RH_PRINTF("Get Status ");
+               break;
+       case RH_GET_STATUS | RH_INTERFACE:
+               USB_RH_PRINTF("Get Status Interface ");
+               break;
+       case RH_GET_STATUS | RH_ENDPOINT:
+               USB_RH_PRINTF("Get Status Endpoint ");
+               break;
+       case RH_GET_STATUS | RH_CLASS:
+               USB_RH_PRINTF("Get Status Class");
+               break;  /* hub power ** */
+       case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+               USB_RH_PRINTF("Get Status Class Others");
+               break;
+       case RH_CLEAR_FEATURE | RH_ENDPOINT:
+               USB_RH_PRINTF("Clear Feature Endpoint ");
+               break;
+       case RH_CLEAR_FEATURE | RH_CLASS:
+               USB_RH_PRINTF("Clear Feature Class ");
+               break;
+       case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+               USB_RH_PRINTF("Clear Feature Other Class ");
+               break;
+       case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+               USB_RH_PRINTF("Set Feature Other Class ");
+               break;
+       case RH_SET_ADDRESS:
+               USB_RH_PRINTF("Set Address ");
+               break;
+       case RH_GET_DESCRIPTOR:
+               USB_RH_PRINTF("Get Descriptor ");
+               break;
+       case RH_GET_DESCRIPTOR | RH_CLASS:
+               USB_RH_PRINTF("Get Descriptor Class ");
+               break;
+       case RH_GET_CONFIGURATION:
+               USB_RH_PRINTF("Get Configuration ");
+               break;
+       case RH_SET_CONFIGURATION:
+               USB_RH_PRINTF("Get Configuration ");
+               break;
+       default:
+               USB_RH_PRINTF("****UNKNOWN**** 0x%04X ",req);
+       }
+       USB_RH_PRINTF("\n");
+
+}
+
+static void usb_display_wValue(unsigned short wValue,unsigned short wIndex)
+{
+       switch (wValue) {
+               case (RH_PORT_ENABLE):
+                       USB_RH_PRINTF("Root-Hub: Enable Port %d\n",wIndex);
+                       break;
+               case (RH_PORT_SUSPEND):
+                       USB_RH_PRINTF("Root-Hub: Suspend Port %d\n",wIndex);
+                       break;
+               case (RH_PORT_POWER):
+                       USB_RH_PRINTF("Root-Hub: Port Power %d\n",wIndex);
+                       break;
+               case (RH_C_PORT_CONNECTION):
+                       USB_RH_PRINTF("Root-Hub: C Port Connection Port %d\n",wIndex);
+                       break;
+               case (RH_C_PORT_ENABLE):
+                       USB_RH_PRINTF("Root-Hub: C Port Enable Port %d\n",wIndex);
+                       break;
+               case (RH_C_PORT_SUSPEND):
+                       USB_RH_PRINTF("Root-Hub: C Port Suspend Port %d\n",wIndex);
+                       break;
+               case (RH_C_PORT_OVER_CURRENT):
+                       USB_RH_PRINTF("Root-Hub: C Port Over Current Port %d\n",wIndex);
+                       break;
+               case (RH_C_PORT_RESET):
+                       USB_RH_PRINTF("Root-Hub: C Port reset Port %d\n",wIndex);
+                       break;
+               default:
+                       USB_RH_PRINTF("Root-Hub: unknown %x %x\n",wValue,wIndex);
+                       break;
+       }
+}
+                
+#endif
+
+
+
+#ifdef USB_UHCI_DEBUG
+
+static int usb_display_td(uhci_td_t *td)
+{
+       unsigned long tmp;
+       int valid;
+       
+       printf("TD at %p:\n",td);
+       
+       tmp=swap_32(td->link);
+       printf("Link points to 0x%08lX, %s first, %s, %s\n",tmp&0xfffffff0,
+               ((tmp & 0x4)==0x4) ? "Depth" : "Breath", 
+               ((tmp & 0x2)==0x2) ? "QH" : "TD", 
+               ((tmp & 0x1)==0x1) ? "invalid" : "valid");
+       valid=((tmp & 0x1)==0x0);
+       tmp=swap_32(td->status);
+       printf("     %s %ld Errors %s %s %s \n     %s %s %s %s %s %s\n     Len 0x%lX\n",
+               (((tmp>>29)&0x1)==0x1) ? "SPD Enable" : "SPD Disable",
+               ((tmp>>28)&0x3),
+               (((tmp>>26)&0x1)==0x1) ? "Low Speed" : "Full Speed",
+               (((tmp>>25)&0x1)==0x1) ? "ISO " : "",
+               (((tmp>>24)&0x1)==0x1) ? "IOC " : "",
+               (((tmp>>23)&0x1)==0x1) ? "Active " : "Inactive ",
+               (((tmp>>22)&0x1)==0x1) ? "Stalled" : "",
+               (((tmp>>21)&0x1)==0x1) ? "Data Buffer Error" : "",
+               (((tmp>>20)&0x1)==0x1) ? "Babble" : "",
+               (((tmp>>19)&0x1)==0x1) ? "NAK" : "",
+               (((tmp>>18)&0x1)==0x1) ? "Bitstuff Error" : "",
+               (tmp&0x7ff));
+       tmp=swap_32(td->info);
+       printf("     MaxLen 0x%lX\n",((tmp>>21)&0x7FF));
+       printf("     %s Endpoint 0x%lX Dev Addr 0x%lX PID 0x%lX\n",((tmp>>19)&0x1)==0x1 ? "TOGGLE" : "",
+               ((tmp>>15)&0xF),((tmp>>8)&0x7F),tmp&0xFF);
+       tmp=swap_32(td->buffer);
+       printf("     Buffer 0x%08lX\n",tmp);
+       printf("     DEV %08lX\n",td->dev_ptr);
+       return valid;
+}
+       
+        
+void usb_show_td(int max)
+{
+       int i;
+       if(max>0) {
+               for(i=0;i<max;i++) {
+                       usb_display_td(&tmp_td[i]);
+               }
+       }
+       else {
+               i=0;
+               do {
+                       printf("tmp_td[%d]\n",i);
+               }while(usb_display_td(&tmp_td[i++]));
+       }
+}
+
+
+#endif
+#endif /* CONFIG_USB_UHCI */
+
+/* EOF */
diff --git a/board/mpl/common/usb_uhci.h b/board/mpl/common/usb_uhci.h
new file mode 100644 (file)
index 0000000..de2b7b7
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ * Note: Part of this code has been derived from linux
+ * 
+ */
+#ifndef _USB_UHCI_H_
+#define _USB_UHCI_H_
+
+
+/* Command register */
+#define USBCMD         0
+#define   USBCMD_RS       0x0001       /* Run/Stop */
+#define   USBCMD_HCRESET  0x0002       /* Host reset */
+#define   USBCMD_GRESET   0x0004       /* Global reset */
+#define   USBCMD_EGSM     0x0008       /* Global Suspend Mode */
+#define   USBCMD_FGR      0x0010       /* Force Global Resume */
+#define   USBCMD_SWDBG    0x0020       /* SW Debug mode */
+#define   USBCMD_CF       0x0040       /* Config Flag (sw only) */
+#define   USBCMD_MAXP     0x0080       /* Max Packet (0 = 32, 1 = 64) */
+
+/* Status register */
+#define USBSTS         2
+#define   USBSTS_USBINT   0x0001       /* Interrupt due to IOC */
+#define   USBSTS_ERROR    0x0002       /* Interrupt due to error */
+#define   USBSTS_RD       0x0004       /* Resume Detect */
+#define   USBSTS_HSE      0x0008       /* Host System Error - basically PCI problems */
+#define   USBSTS_HCPE     0x0010       /* Host Controller Process Error - the scripts were buggy */
+#define   USBSTS_HCH      0x0020       /* HC Halted */
+
+/* Interrupt enable register */
+#define USBINTR                4
+#define   USBINTR_TIMEOUT 0x0001       /* Timeout/CRC error enable */
+#define   USBINTR_RESUME  0x0002       /* Resume interrupt enable */
+#define   USBINTR_IOC     0x0004       /* Interrupt On Complete enable */
+#define   USBINTR_SP      0x0008       /* Short packet interrupt enable */
+
+#define USBFRNUM      6
+#define USBFLBASEADD  8
+#define USBSOF        12
+
+/* USB port status and control registers */
+#define USBPORTSC1     16
+#define USBPORTSC2     18
+#define   USBPORTSC_CCS   0x0001       /* Current Connect Status ("device present") */
+#define   USBPORTSC_CSC   0x0002       /* Connect Status Change */
+#define   USBPORTSC_PE    0x0004       /* Port Enable */
+#define   USBPORTSC_PEC   0x0008       /* Port Enable Change */
+#define   USBPORTSC_LS    0x0030       /* Line Status */
+#define   USBPORTSC_RD    0x0040       /* Resume Detect */
+#define   USBPORTSC_LSDA  0x0100       /* Low Speed Device Attached */
+#define   USBPORTSC_PR    0x0200       /* Port Reset */
+#define   USBPORTSC_SUSP  0x1000       /* Suspend */
+
+/* Legacy support register */
+#define USBLEGSUP 0xc0
+#define USBLEGSUP_DEFAULT 0x2000       /* only PIRQ enable set */
+
+#define UHCI_NULL_DATA_SIZE 0x7ff      /* for UHCI controller TD */
+#define UHCI_PID            0xff       /* PID MASK */
+
+#define UHCI_PTR_BITS       0x000F
+#define UHCI_PTR_TERM       0x0001
+#define UHCI_PTR_QH         0x0002
+#define UHCI_PTR_DEPTH      0x0004
+
+/* for TD <status>: */
+#define TD_CTRL_SPD         (1 << 29)  /* Short Packet Detect */
+#define TD_CTRL_C_ERR_MASK  (3 << 27)  /* Error Counter bits */
+#define TD_CTRL_LS          (1 << 26)  /* Low Speed Device */
+#define TD_CTRL_IOS         (1 << 25)  /* Isochronous Select */
+#define TD_CTRL_IOC         (1 << 24)  /* Interrupt on Complete */
+#define TD_CTRL_ACTIVE      (1 << 23)  /* TD Active */
+#define TD_CTRL_STALLED     (1 << 22)  /* TD Stalled */
+#define TD_CTRL_DBUFERR     (1 << 21)  /* Data Buffer Error */
+#define TD_CTRL_BABBLE      (1 << 20)  /* Babble Detected */
+#define TD_CTRL_NAK         (1 << 19)  /* NAK Received */
+#define TD_CTRL_CRCTIMEO    (1 << 18)  /* CRC/Time Out Error */
+#define TD_CTRL_BITSTUFF    (1 << 17)  /* Bit Stuff Error */
+#define TD_CTRL_ACTLEN_MASK 0x7ff      /* actual length, encoded as n - 1 */
+
+#define TD_CTRL_ANY_ERROR      (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
+                                TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
+
+#define TD_TOKEN_TOGGLE                19
+
+/* ------------------------------------------------------------------------------------ 
+   Virtual Root HUB 
+   ------------------------------------------------------------------------------------ */
+/* destination of request */
+#define RH_INTERFACE               0x01
+#define RH_ENDPOINT                0x02
+#define RH_OTHER                   0x03
+
+#define RH_CLASS                   0x20
+#define RH_VENDOR                  0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS           0x0080
+#define RH_CLEAR_FEATURE        0x0100
+#define RH_SET_FEATURE          0x0300
+#define RH_SET_ADDRESS          0x0500
+#define RH_GET_DESCRIPTOR       0x0680
+#define RH_SET_DESCRIPTOR       0x0700
+#define RH_GET_CONFIGURATION    0x0880
+#define RH_SET_CONFIGURATION    0x0900
+#define RH_GET_STATE            0x0280
+#define RH_GET_INTERFACE        0x0A80
+#define RH_SET_INTERFACE        0x0B00
+#define RH_SYNC_FRAME           0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP               0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION         0x00
+#define RH_PORT_ENABLE             0x01
+#define RH_PORT_SUSPEND            0x02
+#define RH_PORT_OVER_CURRENT       0x03
+#define RH_PORT_RESET              0x04
+#define RH_PORT_POWER              0x08
+#define RH_PORT_LOW_SPEED          0x09
+#define RH_C_PORT_CONNECTION       0x10
+#define RH_C_PORT_ENABLE           0x11
+#define RH_C_PORT_SUSPEND          0x12
+#define RH_C_PORT_OVER_CURRENT     0x13
+#define RH_C_PORT_RESET            0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER       0x00
+#define RH_C_HUB_OVER_CURRENT      0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP    0x00
+#define RH_ENDPOINT_STALL          0x01
+
+/* Our Vendor Specific feature */
+#define RH_REMOVE_EP               0x00
+
+
+#define RH_ACK                     0x01
+#define RH_REQ_ERR                 -1
+#define RH_NACK                    0x00
+
+
+/* Transfer descriptor structure */
+typedef struct {
+       unsigned long link;     /* next td/qh (LE)*/
+       unsigned long status;   /* status of the td */
+       unsigned long info;     /* Max Lenght / Endpoint / device address and PID */
+       unsigned long buffer;   /* pointer to data buffer (LE) */
+       unsigned long dev_ptr;  /* pointer to the assigned device (BE) */
+       unsigned long res[3];   /* reserved (TDs must be 8Byte aligned) */
+} uhci_td_t, *puhci_td_t;
+
+/* Queue Header structure */
+typedef struct {
+       unsigned long head;       /* Next QH (LE)*/
+       unsigned long element;          /* Queue element pointer (LE) */
+       unsigned long res[5];     /* reserved */
+       unsigned long dev_ptr;    /* if 0 no tds have been assigned to this qh */
+} uhci_qh_t, *puhci_qh_t;
+
+struct virt_root_hub {
+       int devnum;                         /* Address of Root Hub endpoint */
+       int numports;             /* number of ports */
+       int c_p_r[8];             /* C_PORT_RESET */
+};
+
+#endif /* _USB_UHCI_H_ */
+
diff --git a/board/mpl/common/vga_table.h b/board/mpl/common/vga_table.h
new file mode 100644 (file)
index 0000000..d1cf5a6
--- /dev/null
@@ -0,0 +1,5115 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG, d.peter@mpl.ch.
+ *
+ * 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
+ *
+ * Note: Parts of these software are imported from 
+ *       - UBL, The Universal Talkware Boot Loader
+ *         Copyright (C) 2000 Universal Talkware Inc.
+ *       - Linux
+ *
+ * File: vga_table.c 
+ * 
+ * contains all tables (include fonts) for the vga controller.
+ *
+ **********************************************/
+#ifndef _VGA_TABLE_H
+#define _VGA_TABLE_H
+
+/* table for VGA Initialization  */
+typedef struct {
+       const unsigned char reg;
+       const unsigned char val;
+} VIDEO_CFG_TABLE;
+
+/* Attribute table */
+static VIDEO_CFG_TABLE attr[] = {
+       { 0x00, 0x00 }, /* black */
+       { 0x01, 0x01 }, /* blue */
+       { 0x02, 0x02 }, /* green */     
+       { 0x03, 0x03 }, /* cyan */
+       { 0x04, 0x04 }, /* red */
+       { 0x05, 0x05 }, /* magenta */
+       { 0x06, 0x14 }, /* brown */
+       { 0x07, 0x07 }, /* white */
+       { 0x08, 0x38 }, /* dark gray */
+       { 0x09, 0x39 }, /* light blue */
+       { 0x0A, 0x3A }, /* light green */
+       { 0x0B, 0x3B }, /* light Cyan */
+       { 0x0C, 0x3C }, /* light red */
+       { 0x0D, 0x3D }, /* light magenta */
+       { 0x0E, 0x3E }, /* yellow */
+       { 0x0F, 0x3F }, /* intense white */
+       { 0x10, 0x0C }, /* mode control */
+       { 0x11, 0x00 }, /* overscan color */
+       { 0x12, 0x0f }, /* color plane enable */
+       { 0x13, 0x08 }, /* horizontal Pel Panning */
+       { 0x14, 0x00 }, /* color select */
+       { 0xFF, 0xFF}           /* end of table */ 
+};
+
+/* Values for VGA 80 x 25 Text mode */
+static VIDEO_CFG_TABLE crtc[] = {
+       {0x00,0x5F},    /* horizontal total */
+       {0x01,0x4F},    /* horizontal displayed */
+       {0x02,0x50},    /* horizontal blank start */
+       {0x03,0x82},    /* horizontal blank end MIP520 BIOS*/
+       {0x04,0x55},    /* horizontal synch pos  MIP520 */
+       {0x05,0x9F},    /* horizontal synch width BIOS Source */
+       {0x06,0xBF},    /* vertical total BIOS MIP520*/
+       {0x07,0x1F},    /* overflow */
+       {0x08,0x00},    /* prescan  */
+       {0x09,0x4F},    /* maximum scanline */
+       {0x0A,0x0D},    /* cursor start */
+       {0x0B,0x0E},    /* cursor end */
+       {0x0C,0x00},    /* start address high byte */
+       {0x0D,0x00},    /* start address low byte */
+       {0x0E,0x07},    /* cursor location high byte */
+       {0x0F,0x80},    /* cursor location low byte */
+       {0x10,0x9C},    /* vertical synch start BIOS MIP520*/
+       {0x11,0x8E},    /* vertical synch end */
+       {0x12,0x8F},    /* vertical display enable end BIOS MIP520 */
+       {0x13,0x28},    /* offset */
+       {0x14,0x1F},    /* underline row */
+       {0x15,0x96},    /* verical blank start */
+       {0x16,0xB9},    /* verical blank end */
+       {0x17,0xA3},    /* crt Mode Control */
+       {0x18,0xFF},    /* line compare */
+       /* added for 69000 */
+       {0x22,0x20},    /* Memory Latch */
+       {0x30,0x00},    /* ext. total vertical register */
+       {0x31,0x00},    /* ext. vertical display end */
+       {0x32,0x00},    /* ext. vertical synch */
+       {0x33,0x00},    /* ext. vertical blanking start */
+       {0x38,0x00},    /* ext. total horizontal register */
+       {0x3C,0x00},    /* ext. horizontal blanking end */
+       {0x40,0x00},    /* ext. start address */
+       {0x41,0x00},    /* ext. offset */
+       {0x70,0x4F},    /* interlace control register */
+       {0x71,0x00},    /* NTSC/PAL Video Output Control */
+       {0x72,0x00},    /* NTSC/PAL horizontal serration 1 start */
+       {0x73,0x00},    /* NTSC/PAL horizontal serration 2 start */
+       {0x74,0x00},    /* NTSC/PAL horizontal pulse width */
+       {0x75,0x00},    /* NTSC/PAL filtering burst read length */
+       {0x76,0x00},    /* NTSC/PAL filtering burst read quantity */
+       {0x77,0x00},    /* NTSC/PAL Filtering Control */
+       {0x78,0x00},    /* NTSC/PAL Vertical reduction */
+       {0x79,0x00},    /* NTSC/PAL horizontal total fine adjust */
+       {0xFF,0xFF}             /* end of table */ 
+};
+
+static VIDEO_CFG_TABLE grmr[] = {
+       {0x00,0x00},    /* all planes are reset */
+       {0x01,0x00},    /* no special altering of plane */                
+       {0x02,0x00},    /* color compare */
+       {0x03,0x00},    /* data rotate */
+       {0x04,0x00},    /* read plane 0 */
+       {0x05,0x10},    /* Mode */
+       {0x06,0x0E},    /* misc */
+       {0x07,0x00},    /* Color */
+       {0x08,0xFF},    /* Bitmask */
+       {0xFF,0xFF}             /* end of table */ 
+};
+
+
+static VIDEO_CFG_TABLE seq[] = {
+       {0x00,0x03},    /* release the resets */
+       {0x01,0x00},    /* clocking mode */
+       {0x02,0x03},    /* enable plane 0,1 access */
+       {0x03,0x00},    /* character map */               
+       {0x04,0x02},    /* Memory mode */
+       {0x07,0x00},    /* Reset Counter */
+       {0xFF,0xFF}             /* end of table */ 
+};
+
+static VIDEO_CFG_TABLE xreg[] = {
+
+       { 0x0A, 0x00 }, /* Frame Buffer Mapping */
+       { 0x0B, 0x01 }, /* PCI Write Burst support */
+       { 0x0E, 0x00 }, /* Frame buffer Page select */
+       { 0x20, 0x00 }, /* BitBLT Configuration */
+       /*      { 0x40, 0x03 }, */ /* Memory Access Control */
+       { 0x40, 0x00 }, /* Memory Access Control */
+       { 0x60, 0x00 }, /* Video Pin Control */
+       { 0x61, 0x00 }, /* DPMS Synch control */
+       { 0x62, 0x00 }, /* GPIO Pin Control */
+       { 0x63, 0xBD }, /* GPIO Pin Data*/
+       { 0x67, 0x00 }, /* Pin Tri-State */
+       { 0x80, 0x00 }, /* Pixel Pipeline Config 0 register */
+       { 0x81, 0x00 }, /* Pixel Pipeline Config 1 register */
+       { 0x82, 0x00 }, /* Pixel Pipeline Config 2 register */
+       { 0xA0, 0x00 }, /* Cursor 1 Control Reg */
+       { 0xA1, 0x00 }, /* Cursor 1 Vertical Extension Reg */
+       { 0xA2, 0x00 }, /* Cursor 1 Base Address Low */
+       { 0xA3, 0x00 }, /* Cursor 1 Base Address High */
+       { 0xA4, 0x00 }, /* Cursor 1 X-Position Low */
+       { 0xA5, 0x00 }, /* Cursor 1 X-Position High */
+       { 0xA6, 0x00 }, /* Cursor 1 Y-Position Low */
+       { 0xA7, 0x00 }, /* Cursor 1 Y-Position High */
+       { 0xA8, 0x00 }, /* Cursor 2 Control Reg */
+       { 0xA9, 0x00 }, /* Cursor 2 Vertical Extension Reg */
+       { 0xAA, 0x00 }, /* Cursor 2 Base Address Low */
+       { 0xAB, 0x00 }, /* Cursor 2 Base Address High */
+       { 0xAC, 0x00 }, /* Cursor 2 X-Position Low */
+       { 0xAD, 0x00 }, /* Cursor 2 X-Position High */
+       { 0xAE, 0x00 }, /* Cursor 2 Y-Position Low */
+       { 0xAF, 0x00 }, /* Cursor 2 Y-Position High */
+       { 0xC0, 0x7D }, /* Dot Clock 0 VCO M-Divisor */
+       { 0xC1, 0x07 }, /* Dot Clock 0 VCO N-Divisor */
+       { 0xC3, 0x34 }, /* Dot Clock 0 Divisor select */
+       { 0xC4, 0x55 }, /* Dot Clock 1 VCO M-Divisor */
+       { 0xC5, 0x09 }, /* Dot Clock 1 VCO N-Divisor */
+       { 0xC7, 0x24 }, /* Dot Clock 1 Divisor select */
+       { 0xC8, 0x7D }, /* Dot Clock 2 VCO M-Divisor */
+       { 0xC9, 0x07 }, /* Dot Clock 2 VCO N-Divisor */
+       { 0xCB, 0x34 }, /* Dot Clock 2 Divisor select */
+       { 0xCC, 0x38 }, /* Memory Clock 0 VCO M-Divisor */
+       { 0xCD, 0x03 }, /* Memory Clock 0 VCO N-Divisor */
+       { 0xCE, 0x90 }, /* Memory Clock 0 Divisor select */
+       { 0xCF, 0x06 }, /* Clock Config */
+       { 0xD0, 0x0F }, /* Power Down */
+       { 0xD1, 0x01 }, /* Power Down BitBLT */
+       /*      { 0xD2, 0x0F }, */  /* 2KHz Counter Power Down  */
+       { 0xFF, 0xFF}                   /* end of table */ 
+};
+/* Clock Config:
+ * If Loop Divisor = 1 
+ *   Fvco = (Fref * M/N)
+ *      Fout = Fvco / Post Divisor
+ * Dot Clk0:
+ * ---------
+ * M  = (M Div + 2) = 127
+ * N  = (N Div + 2) = 9
+ * Post Divisor =     8
+ * Loop Divisor =     1
+ * Fref = 14.31818MHz => Fvco 202.045MHz => Dot Clock 0 = 25.25MHz
+ *
+ * Dot Clk1:
+ * ---------
+ * M  = (M Div + 2) = 57
+ * N  = (N Div + 2) = 11
+ * Post Divisor =     4
+ * Loop Divisor =     1
+ * Fref = 14.31818MHz => Fvco 113.24MHz => Dot Clock 1 = 28.31MHz
+ *
+ * Dot Clk2:
+ * ---------
+ * M  = (M Div + 2) = 127
+ * N  = (N Div + 2) = 9
+ * Post Divisor =     8
+ * Loop Divisor =     1
+ * Fref = 14.31818MHz => Fvco 202.045MHz => Dot Clock 2 = 25.25MHz
+ *
+ * Memory Clk:
+ * -----------
+ * M  = (M Div + 2) = 58
+ * N  = (N Div + 2) = 5
+ * Post Divisor =     2
+ * Fref = 14.31818MHz => Fvco 166MHz => Dot Clock 1 = 83MHz
+ *
+ */
+
+
+/* DAC datas */
+static unsigned char dac[][3] = {
+  {0x00, 0x00, 0x00}, /* Index  0 (00) */
+  {0x00, 0x00, 0x2A}, /* Index  1 (01) */
+  {0x00, 0x2A, 0x00}, /* Index  2 (02) */
+  {0x00, 0x2A, 0x2A}, /* Index  3 (03) */
+  {0x2A, 0x00, 0x00}, /* Index  4 (04) */
+  {0x2A, 0x00, 0x2A}, /* Index  5 (05) */
+  {0x2A, 0x2A, 0x00}, /* Index  6 (06) */
+  {0x2A, 0x2A, 0x2A}, /* Index  7 (07) */
+  {0x00, 0x00, 0x15}, /* Index  8 (08) */
+  {0x00, 0x00, 0x3F}, /* Index  9 (09) */
+  {0x00, 0x2A, 0x15}, /* Index 10 (0A) */
+  {0x00, 0x2A, 0x3F}, /* Index 11 (0B) */
+  {0x2A, 0x00, 0x15}, /* Index 12 (0C) */
+  {0x2A, 0x00, 0x3F}, /* Index 13 (0D) */
+  {0x2A, 0x2A, 0x15}, /* Index 14 (0E) */
+  {0x2A, 0x2A, 0x3F}, /* Index 15 (0F) */
+  {0x00, 0x15, 0x00}, /* Index 16 (10) */
+  {0x00, 0x15, 0x2A}, /* Index 17 (11) */
+  {0x00, 0x3F, 0x00}, /* Index 18 (12) */
+  {0x00, 0x3F, 0x2A}, /* Index 19 (13) */
+  {0x2A, 0x15, 0x00}, /* Index 20 (14) */
+  {0x2A, 0x15, 0x2A}, /* Index 21 (15) */
+  {0x2A, 0x3F, 0x00}, /* Index 22 (16) */
+  {0x2A, 0x3F, 0x2A}, /* Index 23 (17) */
+  {0x00, 0x15, 0x15}, /* Index 24 (18) */
+  {0x00, 0x15, 0x3F}, /* Index 25 (19) */
+  {0x00, 0x3F, 0x15}, /* Index 26 (1A) */
+  {0x00, 0x3F, 0x3F}, /* Index 27 (1B) */
+  {0x2A, 0x15, 0x15}, /* Index 28 (1C) */
+  {0x2A, 0x15, 0x3F}, /* Index 29 (1D) */
+  {0x2A, 0x3F, 0x15}, /* Index 30 (1E) */
+  {0x2A, 0x3F, 0x3F}, /* Index 31 (1F) */
+  {0x15, 0x00, 0x00}, /* Index 32 (20) */
+  {0x15, 0x00, 0x2A}, /* Index 33 (21) */
+  {0x15, 0x2A, 0x00}, /* Index 34 (22) */
+  {0x15, 0x2A, 0x2A}, /* Index 35 (23) */
+  {0x3F, 0x00, 0x00}, /* Index 36 (24) */
+  {0x3F, 0x00, 0x2A}, /* Index 37 (25) */
+  {0x3F, 0x2A, 0x00}, /* Index 38 (26) */
+  {0x3F, 0x2A, 0x2A}, /* Index 39 (27) */
+  {0x15, 0x00, 0x15}, /* Index 40 (28) */
+  {0x15, 0x00, 0x3F}, /* Index 41 (29) */
+  {0x15, 0x2A, 0x15}, /* Index 42 (2A) */
+  {0x15, 0x2A, 0x3F}, /* Index 43 (2B) */
+  {0x3F, 0x00, 0x15}, /* Index 44 (2C) */
+  {0x3F, 0x00, 0x3F}, /* Index 45 (2D) */
+  {0x3F, 0x2A, 0x15}, /* Index 46 (2E) */
+  {0x3F, 0x2A, 0x3F}, /* Index 47 (2F) */
+  {0x15, 0x15, 0x00}, /* Index 48 (30) */
+  {0x15, 0x15, 0x2A}, /* Index 49 (31) */
+  {0x15, 0x3F, 0x00}, /* Index 50 (32) */
+  {0x15, 0x3F, 0x2A}, /* Index 51 (33) */
+  {0x3F, 0x15, 0x00}, /* Index 52 (34) */
+  {0x3F, 0x15, 0x2A}, /* Index 53 (35) */
+  {0x3F, 0x3F, 0x00}, /* Index 54 (36) */
+  {0x3F, 0x3F, 0x2A}, /* Index 55 (37) */
+  {0x15, 0x15, 0x15}, /* Index 56 (38) */
+  {0x15, 0x15, 0x3F}, /* Index 57 (39) */
+  {0x15, 0x3F, 0x15}, /* Index 58 (3A) */
+  {0x15, 0x3F, 0x3F}, /* Index 59 (3B) */
+  {0x3F, 0x15, 0x15}, /* Index 60 (3C) */
+  {0x3F, 0x15, 0x3F}, /* Index 61 (3D) */
+  {0x3F, 0x3F, 0x15}, /* Index 62 (3E) */
+  {0x3F, 0x3F, 0x3F}, /* Index 63 (3F) */
+  {0x16, 0x1E, 0x17}, /* Index 64 (40) */
+  {0x27, 0x2F, 0x00}, /* Index 65 (41) */
+  {0x1E, 0x20, 0x18}, /* Index 66 (42) */
+  {0x30, 0x04, 0x06}, /* Index 67 (43) */
+  {0x08, 0x05, 0x12}, /* Index 68 (44) */
+  {0x30, 0x0A, 0x31}, /* Index 69 (45) */
+  {0x08, 0x16, 0x07}, /* Index 70 (46) */
+  {0x1B, 0x33, 0x21}, /* Index 71 (47) */
+  {0x02, 0x2C, 0x16}, /* Index 72 (48) */
+  {0x3D, 0x1C, 0x11}, /* Index 73 (49) */
+  {0x07, 0x22, 0x33}, /* Index 74 (4A) */
+  {0x1D, 0x2B, 0x0A}, /* Index 75 (4B) */
+  {0x1A, 0x15, 0x16}, /* Index 76 (4C) */
+  {0x15, 0x26, 0x24}, /* Index 77 (4D) */
+  {0x05, 0x2B, 0x1E}, /* Index 78 (4E) */
+  {0x11, 0x18, 0x01}, /* Index 79 (4F) */
+  {0x3A, 0x2C, 0x27}, /* Index 80 (50) */
+  {0x25, 0x23, 0x00}, /* Index 81 (51) */
+  {0x2A, 0x16, 0x2A}, /* Index 82 (52) */
+  {0x18, 0x19, 0x17}, /* Index 83 (53) */
+  {0x0B, 0x0F, 0x06}, /* Index 84 (54) */
+  {0x00, 0x34, 0x08}, /* Index 85 (55) */
+  {0x00, 0x19, 0x12}, /* Index 86 (56) */
+  {0x01, 0x06, 0x3B}, /* Index 87 (57) */
+  {0x29, 0x0E, 0x25}, /* Index 88 (58) */
+  {0x20, 0x10, 0x28}, /* Index 89 (59) */
+  {0x02, 0x37, 0x24}, /* Index 90 (5A) */
+  {0x08, 0x2A, 0x2E}, /* Index 91 (5B) */
+  {0x26, 0x2A, 0x22}, /* Index 92 (5C) */
+  {0x0C, 0x0C, 0x2A}, /* Index 93 (5D) */
+  {0x28, 0x07, 0x02}, /* Index 94 (5E) */
+  {0x34, 0x05, 0x2B}, /* Index 95 (5F) */
+  {0x0C, 0x31, 0x33}, /* Index 96 (60) */
+  {0x22, 0x08, 0x30}, /* Index 97 (61) */
+  {0x00, 0x25, 0x01}, /* Index 98 (62) */
+  {0x06, 0x15, 0x01}, /* Index 99 (63) */
+  {0x0D, 0x2A, 0x0A}, /* Index 100 (64) */
+  {0x08, 0x25, 0x16}, /* Index 101 (65) */
+  {0x2A, 0x0A, 0x01}, /* Index 102 (66) */
+  {0x08, 0x3B, 0x28}, /* Index 103 (67) */
+  {0x00, 0x09, 0x04}, /* Index 104 (68) */
+  {0x16, 0x0F, 0x05}, /* Index 105 (69) */
+  {0x02, 0x2F, 0x1D}, /* Index 106 (6A) */
+  {0x06, 0x3E, 0x02}, /* Index 107 (6B) */
+  {0x09, 0x30, 0x07}, /* Index 108 (6C) */
+  {0x34, 0x03, 0x06}, /* Index 109 (6D) */
+  {0x00, 0x15, 0x2A}, /* Index 110 (6E) */
+  {0x39, 0x23, 0x20}, /* Index 111 (6F) */
+  {0x2A, 0x32, 0x0C}, /* Index 112 (70) */
+  {0x09, 0x31, 0x26}, /* Index 113 (71) */
+  {0x27, 0x23, 0x28}, /* Index 114 (72) */
+  {0x20, 0x13, 0x0C}, /* Index 115 (73) */
+  {0x2C, 0x1E, 0x26}, /* Index 116 (74) */
+  {0x20, 0x2F, 0x05}, /* Index 117 (75) */
+  {0x22, 0x1B, 0x22}, /* Index 118 (76) */
+  {0x09, 0x1C, 0x06}, /* Index 119 (77) */
+  {0x16, 0x38, 0x0E}, /* Index 120 (78) */
+  {0x22, 0x16, 0x20}, /* Index 121 (79) */
+  {0x10, 0x17, 0x25}, /* Index 122 (7A) */
+  {0x04, 0x32, 0x22}, /* Index 123 (7B) */
+  {0x20, 0x00, 0x37}, /* Index 124 (7C) */
+  {0x21, 0x15, 0x1A}, /* Index 125 (7D) */
+  {0x01, 0x04, 0x20}, /* Index 126 (7E) */
+  {0x02, 0x0C, 0x1E}, /* Index 127 (7F) */
+  {0x15, 0x15, 0x29}, /* Index 128 (80) */
+  {0x24, 0x3B, 0x00}, /* Index 129 (81) */
+  {0x24, 0x28, 0x01}, /* Index 130 (82) */
+  {0x20, 0x19, 0x07}, /* Index 131 (83) */
+  {0x1A, 0x13, 0x02}, /* Index 132 (84) */
+  {0x04, 0x24, 0x1F}, /* Index 133 (85) */
+  {0x32, 0x30, 0x08}, /* Index 134 (86) */
+  {0x23, 0x12, 0x0B}, /* Index 135 (87) */
+  {0x21, 0x38, 0x00}, /* Index 136 (88) */
+  {0x04, 0x13, 0x09}, /* Index 137 (89) */
+  {0x06, 0x3E, 0x14}, /* Index 138 (8A) */
+  {0x23, 0x22, 0x2D}, /* Index 139 (8B) */
+  {0x3D, 0x35, 0x30}, /* Index 140 (8C) */
+  {0x24, 0x38, 0x05}, /* Index 141 (8D) */
+  {0x18, 0x01, 0x26}, /* Index 142 (8E) */
+  {0x27, 0x11, 0x38}, /* Index 143 (8F) */
+  {0x08, 0x1A, 0x08}, /* Index 144 (90) */
+  {0x00, 0x1A, 0x07}, /* Index 145 (91) */
+  {0x16, 0x0C, 0x30}, /* Index 146 (92) */
+  {0x1B, 0x0A, 0x0B}, /* Index 147 (93) */
+  {0x01, 0x0C, 0x09}, /* Index 148 (94) */
+  {0x00, 0x33, 0x03}, /* Index 149 (95) */
+  {0x13, 0x0A, 0x06}, /* Index 150 (96) */
+  {0x22, 0x19, 0x23}, /* Index 151 (97) */
+  {0x07, 0x30, 0x39}, /* Index 152 (98) */
+  {0x20, 0x07, 0x0D}, /* Index 153 (99) */
+  {0x39, 0x18, 0x20}, /* Index 154 (9A) */
+  {0x32, 0x31, 0x29}, /* Index 155 (9B) */
+  {0x28, 0x3F, 0x02}, /* Index 156 (9C) */
+  {0x02, 0x15, 0x3E}, /* Index 157 (9D) */
+  {0x27, 0x33, 0x0E}, /* Index 158 (9E) */
+  {0x39, 0x2E, 0x1D}, /* Index 159 (9F) */
+  {0x1E, 0x38, 0x10}, /* Index 160 (A0) */
+  {0x01, 0x33, 0x19}, /* Index 161 (A1) */
+  {0x2B, 0x20, 0x0B}, /* Index 162 (A2) */
+  {0x29, 0x0B, 0x23}, /* Index 163 (A3) */
+  {0x25, 0x04, 0x19}, /* Index 164 (A4) */
+  {0x34, 0x36, 0x08}, /* Index 165 (A5) */
+  {0x17, 0x1D, 0x01}, /* Index 166 (A6) */
+  {0x0A, 0x29, 0x10}, /* Index 167 (A7) */
+  {0x14, 0x1C, 0x2B}, /* Index 168 (A8) */
+  {0x02, 0x2C, 0x13}, /* Index 169 (A9) */
+  {0x14, 0x16, 0x3A}, /* Index 170 (AA) */
+  {0x2B, 0x22, 0x28}, /* Index 171 (AB) */
+  {0x2E, 0x0A, 0x22}, /* Index 172 (AC) */
+  {0x00, 0x20, 0x28}, /* Index 173 (AD) */
+  {0x08, 0x22, 0x2D}, /* Index 174 (AE) */
+  {0x2C, 0x17, 0x1D}, /* Index 175 (AF) */
+  {0x02, 0x0D, 0x20}, /* Index 176 (B0) */
+  {0x00, 0x18, 0x2C}, /* Index 177 (B1) */
+  {0x19, 0x19, 0x3C}, /* Index 178 (B2) */
+  {0x20, 0x32, 0x10}, /* Index 179 (B3) */
+  {0x38, 0x1C, 0x21}, /* Index 180 (B4) */
+  {0x36, 0x10, 0x00}, /* Index 181 (B5) */
+  {0x20, 0x08, 0x19}, /* Index 182 (B6) */
+  {0x09, 0x12, 0x01}, /* Index 183 (B7) */
+  {0x1D, 0x39, 0x03}, /* Index 184 (B8) */
+  {0x20, 0x28, 0x11}, /* Index 185 (B9) */
+  {0x35, 0x17, 0x01}, /* Index 186 (BA) */
+  {0x0C, 0x02, 0x08}, /* Index 187 (BB) */
+  {0x39, 0x0D, 0x10}, /* Index 188 (BC) */
+  {0x38, 0x21, 0x16}, /* Index 189 (BD) */
+  {0x29, 0x3E, 0x14}, /* Index 190 (BE) */
+  {0x0A, 0x1C, 0x28}, /* Index 191 (BF) */
+  {0x2F, 0x03, 0x08}, /* Index 192 (C0) */
+  {0x02, 0x18, 0x39}, /* Index 193 (C1) */
+  {0x0F, 0x31, 0x1E}, /* Index 194 (C2) */
+  {0x24, 0x0C, 0x03}, /* Index 195 (C3) */
+  {0x04, 0x1A, 0x04}, /* Index 196 (C4) */
+  {0x30, 0x33, 0x04}, /* Index 197 (C5) */
+  {0x2C, 0x18, 0x36}, /* Index 198 (C6) */
+  {0x18, 0x2F, 0x09}, /* Index 199 (C7) */
+  {0x03, 0x04, 0x03}, /* Index 200 (C8) */
+  {0x22, 0x05, 0x10}, /* Index 201 (C9) */
+  {0x03, 0x24, 0x0A}, /* Index 202 (CA) */
+  {0x00, 0x1E, 0x1A}, /* Index 203 (CB) */
+  {0x00, 0x0A, 0x11}, /* Index 204 (CC) */
+  {0x0E, 0x1F, 0x09}, /* Index 205 (CD) */
+  {0x1B, 0x3A, 0x3B}, /* Index 206 (CE) */
+  {0x22, 0x39, 0x36}, /* Index 207 (CF) */
+  {0x22, 0x10, 0x23}, /* Index 208 (D0) */
+  {0x31, 0x14, 0x2B}, /* Index 209 (D1) */
+  {0x0C, 0x33, 0x35}, /* Index 210 (D2) */
+  {0x27, 0x3E, 0x10}, /* Index 211 (D3) */
+  {0x10, 0x04, 0x30}, /* Index 212 (D4) */
+  {0x05, 0x21, 0x0A}, /* Index 213 (D5) */
+  {0x09, 0x11, 0x24}, /* Index 214 (D6) */
+  {0x02, 0x2B, 0x00}, /* Index 215 (D7) */
+  {0x02, 0x05, 0x15}, /* Index 216 (D8) */
+  {0x11, 0x32, 0x1A}, /* Index 217 (D9) */
+  {0x2E, 0x1B, 0x08}, /* Index 218 (DA) */
+  {0x0D, 0x2F, 0x11}, /* Index 219 (DB) */
+  {0x03, 0x30, 0x28}, /* Index 220 (DC) */
+  {0x15, 0x38, 0x0A}, /* Index 221 (DD) */
+  {0x07, 0x00, 0x00}, /* Index 222 (DE) */
+  {0x1D, 0x1C, 0x20}, /* Index 223 (DF) */
+  {0x35, 0x11, 0x35}, /* Index 224 (E0) */
+  {0x24, 0x29, 0x03}, /* Index 225 (E1) */
+  {0x22, 0x37, 0x39}, /* Index 226 (E2) */
+  {0x11, 0x1B, 0x10}, /* Index 227 (E3) */
+  {0x2D, 0x18, 0x00}, /* Index 228 (E4) */
+  {0x20, 0x2F, 0x10}, /* Index 229 (E5) */
+  {0x21, 0x26, 0x32}, /* Index 230 (E6) */
+  {0x24, 0x10, 0x3D}, /* Index 231 (E7) */
+  {0x27, 0x0E, 0x03}, /* Index 232 (E8) */
+  {0x31, 0x1F, 0x11}, /* Index 233 (E9) */
+  {0x16, 0x0D, 0x02}, /* Index 234 (EA) */
+  {0x24, 0x12, 0x16}, /* Index 235 (EB) */
+  {0x0F, 0x27, 0x18}, /* Index 236 (EC) */
+  {0x10, 0x0E, 0x20}, /* Index 237 (ED) */
+  {0x12, 0x0C, 0x0D}, /* Index 238 (EE) */
+  {0x14, 0x38, 0x0B}, /* Index 239 (EF) */
+  {0x23, 0x0C, 0x09}, /* Index 240 (F0) */
+  {0x13, 0x21, 0x0E}, /* Index 241 (F1) */
+  {0x2C, 0x05, 0x2C}, /* Index 242 (F2) */
+  {0x08, 0x29, 0x01}, /* Index 243 (F3) */
+  {0x36, 0x0A, 0x13}, /* Index 244 (F4) */
+  {0x08, 0x2D, 0x26}, /* Index 245 (F5) */
+  {0x23, 0x30, 0x3E}, /* Index 246 (F6) */
+  {0x33, 0x00, 0x04}, /* Index 247 (F7) */
+  {0x25, 0x1E, 0x3A}, /* Index 248 (F8) */
+  {0x11, 0x2C, 0x26}, /* Index 249 (F9) */
+  {0x20, 0x32, 0x27}, /* Index 250 (FA) */
+  {0x23, 0x21, 0x13}, /* Index 251 (FB) */
+  {0x22, 0x23, 0x1F}, /* Index 252 (FC) */
+  {0x31, 0x08, 0x0A}, /* Index 253 (FD) */
+  {0x00, 0x01, 0x09}, /* Index 254 (FE) */
+  {0x17, 0x07, 0x38} /* Index 255 (FF) */
+};
+
+
+/***********************************************
+ * 8x16 Font 
+ * 
+ * copied from file 
+ * drivers/video/font_8x16.c (LINUX)
+ **********************************************/
+/**********************************************/
+/*                                            */
+/*       Font file generated by cpi2fnt       */
+/*                                            */
+/**********************************************/
+
+#define FONTDATAMAX 4096
+
+unsigned char fontdata_8x16[FONTDATAMAX] = {
+
+       /* 0 0x00 '^@' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 1 0x01 '^A' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x81, /* 10000001 */
+       0xa5, /* 10100101 */
+       0x81, /* 10000001 */
+       0x81, /* 10000001 */
+       0xbd, /* 10111101 */
+       0x99, /* 10011001 */
+       0x81, /* 10000001 */
+       0x81, /* 10000001 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 2 0x02 '^B' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0xff, /* 11111111 */
+       0xdb, /* 11011011 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xc3, /* 11000011 */
+       0xe7, /* 11100111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 3 0x03 '^C' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x6c, /* 01101100 */
+       0xfe, /* 11111110 */
+       0xfe, /* 11111110 */
+       0xfe, /* 11111110 */
+       0xfe, /* 11111110 */
+       0x7c, /* 01111100 */
+       0x38, /* 00111000 */
+       0x10, /* 00010000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 4 0x04 '^D' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x7c, /* 01111100 */
+       0xfe, /* 11111110 */
+       0x7c, /* 01111100 */
+       0x38, /* 00111000 */
+       0x10, /* 00010000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 5 0x05 '^E' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x3c, /* 00111100 */
+       0xe7, /* 11100111 */
+       0xe7, /* 11100111 */
+       0xe7, /* 11100111 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 6 0x06 '^F' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x7e, /* 01111110 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 7 0x07 '^G' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 8 0x08 '^H' */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xe7, /* 11100111 */
+       0xc3, /* 11000011 */
+       0xc3, /* 11000011 */
+       0xe7, /* 11100111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+
+       /* 9 0x09 '^I' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x66, /* 01100110 */
+       0x42, /* 01000010 */
+       0x42, /* 01000010 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 10 0x0a '^J' */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xc3, /* 11000011 */
+       0x99, /* 10011001 */
+       0xbd, /* 10111101 */
+       0xbd, /* 10111101 */
+       0x99, /* 10011001 */
+       0xc3, /* 11000011 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+
+       /* 11 0x0b '^K' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x1e, /* 00011110 */
+       0x0e, /* 00001110 */
+       0x1a, /* 00011010 */
+       0x32, /* 00110010 */
+       0x78, /* 01111000 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x78, /* 01111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 12 0x0c '^L' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 13 0x0d '^M' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3f, /* 00111111 */
+       0x33, /* 00110011 */
+       0x3f, /* 00111111 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x70, /* 01110000 */
+       0xf0, /* 11110000 */
+       0xe0, /* 11100000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 14 0x0e '^N' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7f, /* 01111111 */
+       0x63, /* 01100011 */
+       0x7f, /* 01111111 */
+       0x63, /* 01100011 */
+       0x63, /* 01100011 */
+       0x63, /* 01100011 */
+       0x63, /* 01100011 */
+       0x67, /* 01100111 */
+       0xe7, /* 11100111 */
+       0xe6, /* 11100110 */
+       0xc0, /* 11000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 15 0x0f '^O' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xdb, /* 11011011 */
+       0x3c, /* 00111100 */
+       0xe7, /* 11100111 */
+       0x3c, /* 00111100 */
+       0xdb, /* 11011011 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 16 0x10 '^P' */
+       0x00, /* 00000000 */
+       0x80, /* 10000000 */
+       0xc0, /* 11000000 */
+       0xe0, /* 11100000 */
+       0xf0, /* 11110000 */
+       0xf8, /* 11111000 */
+       0xfe, /* 11111110 */
+       0xf8, /* 11111000 */
+       0xf0, /* 11110000 */
+       0xe0, /* 11100000 */
+       0xc0, /* 11000000 */
+       0x80, /* 10000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 17 0x11 '^Q' */
+       0x00, /* 00000000 */
+       0x02, /* 00000010 */
+       0x06, /* 00000110 */
+       0x0e, /* 00001110 */
+       0x1e, /* 00011110 */
+       0x3e, /* 00111110 */
+       0xfe, /* 11111110 */
+       0x3e, /* 00111110 */
+       0x1e, /* 00011110 */
+       0x0e, /* 00001110 */
+       0x06, /* 00000110 */
+       0x02, /* 00000010 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 18 0x12 '^R' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 19 0x13 '^S' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x00, /* 00000000 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 20 0x14 '^T' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7f, /* 01111111 */
+       0xdb, /* 11011011 */
+       0xdb, /* 11011011 */
+       0xdb, /* 11011011 */
+       0x7b, /* 01111011 */
+       0x1b, /* 00011011 */
+       0x1b, /* 00011011 */
+       0x1b, /* 00011011 */
+       0x1b, /* 00011011 */
+       0x1b, /* 00011011 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 21 0x15 '^U' */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0x60, /* 01100000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x0c, /* 00001100 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 22 0x16 '^V' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0xfe, /* 11111110 */
+       0xfe, /* 11111110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 23 0x17 '^W' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 24 0x18 '^X' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 25 0x19 '^Y' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 26 0x1a '^Z' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x0c, /* 00001100 */
+       0xfe, /* 11111110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 27 0x1b '^[' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0xfe, /* 11111110 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 28 0x1c '^\' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 29 0x1d '^]' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x28, /* 00101000 */
+       0x6c, /* 01101100 */
+       0xfe, /* 11111110 */
+       0x6c, /* 01101100 */
+       0x28, /* 00101000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 30 0x1e '^^' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x38, /* 00111000 */
+       0x7c, /* 01111100 */
+       0x7c, /* 01111100 */
+       0xfe, /* 11111110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 31 0x1f '^_' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0xfe, /* 11111110 */
+       0x7c, /* 01111100 */
+       0x7c, /* 01111100 */
+       0x38, /* 00111000 */
+       0x38, /* 00111000 */
+       0x10, /* 00010000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 32 0x20 ' ' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 33 0x21 '!' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x3c, /* 00111100 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 34 0x22 '"' */
+       0x00, /* 00000000 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x24, /* 00100100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 35 0x23 '#' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0xfe, /* 11111110 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0xfe, /* 11111110 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 36 0x24 '$' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc2, /* 11000010 */
+       0xc0, /* 11000000 */
+       0x7c, /* 01111100 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x86, /* 10000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 37 0x25 '%' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc2, /* 11000010 */
+       0xc6, /* 11000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0xc6, /* 11000110 */
+       0x86, /* 10000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 38 0x26 '&' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x76, /* 01110110 */
+       0xdc, /* 11011100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 39 0x27 ''' */
+       0x00, /* 00000000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 40 0x28 '(' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x0c, /* 00001100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 41 0x29 ')' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 42 0x2a '*' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0xff, /* 11111111 */
+       0x3c, /* 00111100 */
+       0x66, /* 01100110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 43 0x2b '+' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 44 0x2c ',' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 45 0x2d '-' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 46 0x2e '.' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 47 0x2f '/' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x02, /* 00000010 */
+       0x06, /* 00000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0xc0, /* 11000000 */
+       0x80, /* 10000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 48 0x30 '0' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xd6, /* 11010110 */
+       0xd6, /* 11010110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 49 0x31 '1' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x38, /* 00111000 */
+       0x78, /* 01111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 50 0x32 '2' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0x06, /* 00000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 51 0x33 '3' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x3c, /* 00111100 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 52 0x34 '4' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x0c, /* 00001100 */
+       0x1c, /* 00011100 */
+       0x3c, /* 00111100 */
+       0x6c, /* 01101100 */
+       0xcc, /* 11001100 */
+       0xfe, /* 11111110 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x1e, /* 00011110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 53 0x35 '5' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xfc, /* 11111100 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 54 0x36 '6' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x60, /* 01100000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xfc, /* 11111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 55 0x37 '7' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0xc6, /* 11000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 56 0x38 '8' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 57 0x39 '9' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7e, /* 01111110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x0c, /* 00001100 */
+       0x78, /* 01111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 58 0x3a ':' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 59 0x3b ';' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 60 0x3c '<' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x06, /* 00000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x0c, /* 00001100 */
+       0x06, /* 00000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 61 0x3d '=' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 62 0x3e '>' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x0c, /* 00001100 */
+       0x06, /* 00000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 63 0x3f '?' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 64 0x40 '@' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xde, /* 11011110 */
+       0xde, /* 11011110 */
+       0xde, /* 11011110 */
+       0xdc, /* 11011100 */
+       0xc0, /* 11000000 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 65 0x41 'A' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 66 0x42 'B' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfc, /* 11111100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x7c, /* 01111100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0xfc, /* 11111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 67 0x43 'C' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x66, /* 01100110 */
+       0xc2, /* 11000010 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc2, /* 11000010 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 68 0x44 'D' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xf8, /* 11111000 */
+       0x6c, /* 01101100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x6c, /* 01101100 */
+       0xf8, /* 11111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 69 0x45 'E' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x66, /* 01100110 */
+       0x62, /* 01100010 */
+       0x68, /* 01101000 */
+       0x78, /* 01111000 */
+       0x68, /* 01101000 */
+       0x60, /* 01100000 */
+       0x62, /* 01100010 */
+       0x66, /* 01100110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 70 0x46 'F' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x66, /* 01100110 */
+       0x62, /* 01100010 */
+       0x68, /* 01101000 */
+       0x78, /* 01111000 */
+       0x68, /* 01101000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0xf0, /* 11110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 71 0x47 'G' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x66, /* 01100110 */
+       0xc2, /* 11000010 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xde, /* 11011110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x66, /* 01100110 */
+       0x3a, /* 00111010 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 72 0x48 'H' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 73 0x49 'I' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 74 0x4a 'J' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x1e, /* 00011110 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x78, /* 01111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 75 0x4b 'K' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xe6, /* 11100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x6c, /* 01101100 */
+       0x78, /* 01111000 */
+       0x78, /* 01111000 */
+       0x6c, /* 01101100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0xe6, /* 11100110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 76 0x4c 'L' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xf0, /* 11110000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x62, /* 01100010 */
+       0x66, /* 01100110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 77 0x4d 'M' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xee, /* 11101110 */
+       0xfe, /* 11111110 */
+       0xfe, /* 11111110 */
+       0xd6, /* 11010110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 78 0x4e 'N' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xe6, /* 11100110 */
+       0xf6, /* 11110110 */
+       0xfe, /* 11111110 */
+       0xde, /* 11011110 */
+       0xce, /* 11001110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 79 0x4f 'O' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 80 0x50 'P' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfc, /* 11111100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x7c, /* 01111100 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0xf0, /* 11110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 81 0x51 'Q' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xd6, /* 11010110 */
+       0xde, /* 11011110 */
+       0x7c, /* 01111100 */
+       0x0c, /* 00001100 */
+       0x0e, /* 00001110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 82 0x52 'R' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfc, /* 11111100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x7c, /* 01111100 */
+       0x6c, /* 01101100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0xe6, /* 11100110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 83 0x53 'S' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x60, /* 01100000 */
+       0x38, /* 00111000 */
+       0x0c, /* 00001100 */
+       0x06, /* 00000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 84 0x54 'T' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x7e, /* 01111110 */
+       0x5a, /* 01011010 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 85 0x55 'U' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 86 0x56 'V' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x10, /* 00010000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 87 0x57 'W' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xd6, /* 11010110 */
+       0xd6, /* 11010110 */
+       0xd6, /* 11010110 */
+       0xfe, /* 11111110 */
+       0xee, /* 11101110 */
+       0x6c, /* 01101100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 88 0x58 'X' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x6c, /* 01101100 */
+       0x7c, /* 01111100 */
+       0x38, /* 00111000 */
+       0x38, /* 00111000 */
+       0x7c, /* 01111100 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 89 0x59 'Y' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 90 0x5a 'Z' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0xc6, /* 11000110 */
+       0x86, /* 10000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0xc2, /* 11000010 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 91 0x5b '[' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 92 0x5c '\' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x80, /* 10000000 */
+       0xc0, /* 11000000 */
+       0xe0, /* 11100000 */
+       0x70, /* 01110000 */
+       0x38, /* 00111000 */
+       0x1c, /* 00011100 */
+       0x0e, /* 00001110 */
+       0x06, /* 00000110 */
+       0x02, /* 00000010 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 93 0x5d ']' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 94 0x5e '^' */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 95 0x5f '_' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 96 0x60 '`' */
+       0x00, /* 00000000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x0c, /* 00001100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 97 0x61 'a' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x78, /* 01111000 */
+       0x0c, /* 00001100 */
+       0x7c, /* 01111100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 98 0x62 'b' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xe0, /* 11100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x78, /* 01111000 */
+       0x6c, /* 01101100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 99 0x63 'c' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 100 0x64 'd' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x1c, /* 00011100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x3c, /* 00111100 */
+       0x6c, /* 01101100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 101 0x65 'e' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 102 0x66 'f' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x1c, /* 00011100 */
+       0x36, /* 00110110 */
+       0x32, /* 00110010 */
+       0x30, /* 00110000 */
+       0x78, /* 01111000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x78, /* 01111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 103 0x67 'g' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x76, /* 01110110 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x7c, /* 01111100 */
+       0x0c, /* 00001100 */
+       0xcc, /* 11001100 */
+       0x78, /* 01111000 */
+       0x00, /* 00000000 */
+
+       /* 104 0x68 'h' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xe0, /* 11100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x6c, /* 01101100 */
+       0x76, /* 01110110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0xe6, /* 11100110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 105 0x69 'i' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 106 0x6a 'j' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x00, /* 00000000 */
+       0x0e, /* 00001110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+
+       /* 107 0x6b 'k' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xe0, /* 11100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x66, /* 01100110 */
+       0x6c, /* 01101100 */
+       0x78, /* 01111000 */
+       0x78, /* 01111000 */
+       0x6c, /* 01101100 */
+       0x66, /* 01100110 */
+       0xe6, /* 11100110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 108 0x6c 'l' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 109 0x6d 'm' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xec, /* 11101100 */
+       0xfe, /* 11111110 */
+       0xd6, /* 11010110 */
+       0xd6, /* 11010110 */
+       0xd6, /* 11010110 */
+       0xd6, /* 11010110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 110 0x6e 'n' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xdc, /* 11011100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 111 0x6f 'o' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 112 0x70 'p' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xdc, /* 11011100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x7c, /* 01111100 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0xf0, /* 11110000 */
+       0x00, /* 00000000 */
+
+       /* 113 0x71 'q' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x76, /* 01110110 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x7c, /* 01111100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x1e, /* 00011110 */
+       0x00, /* 00000000 */
+
+       /* 114 0x72 'r' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xdc, /* 11011100 */
+       0x76, /* 01110110 */
+       0x66, /* 01100110 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0xf0, /* 11110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 115 0x73 's' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0x60, /* 01100000 */
+       0x38, /* 00111000 */
+       0x0c, /* 00001100 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 116 0x74 't' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x10, /* 00010000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0xfc, /* 11111100 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x36, /* 00110110 */
+       0x1c, /* 00011100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 117 0x75 'u' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 118 0x76 'v' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 119 0x77 'w' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xd6, /* 11010110 */
+       0xd6, /* 11010110 */
+       0xd6, /* 11010110 */
+       0xfe, /* 11111110 */
+       0x6c, /* 01101100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 120 0x78 'x' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x38, /* 00111000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 121 0x79 'y' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7e, /* 01111110 */
+       0x06, /* 00000110 */
+       0x0c, /* 00001100 */
+       0xf8, /* 11111000 */
+       0x00, /* 00000000 */
+
+       /* 122 0x7a 'z' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0xcc, /* 11001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 123 0x7b '{' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x0e, /* 00001110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x70, /* 01110000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x0e, /* 00001110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 124 0x7c '|' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 125 0x7d '}' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x70, /* 01110000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x0e, /* 00001110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x70, /* 01110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 126 0x7e '~' */
+       0x00, /* 00000000 */
+       0x76, /* 01110110 */
+       0xdc, /* 11011100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 127 0x7f '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 128 0x80 '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x66, /* 01100110 */
+       0xc2, /* 11000010 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc2, /* 11000010 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x70, /* 01110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 129 0x81 '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xcc, /* 11001100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 130 0x82 '' */
+       0x00, /* 00000000 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 131 0x83 '' */
+       0x00, /* 00000000 */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0x00, /* 00000000 */
+       0x78, /* 01111000 */
+       0x0c, /* 00001100 */
+       0x7c, /* 01111100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 132 0x84 '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xcc, /* 11001100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x78, /* 01111000 */
+       0x0c, /* 00001100 */
+       0x7c, /* 01111100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 133 0x85 '' */
+       0x00, /* 00000000 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x78, /* 01111000 */
+       0x0c, /* 00001100 */
+       0x7c, /* 01111100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 134 0x86 '' */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x00, /* 00000000 */
+       0x78, /* 01111000 */
+       0x0c, /* 00001100 */
+       0x7c, /* 01111100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 135 0x87 '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x18, /* 00011000 */
+       0x70, /* 01110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 136 0x88 '' */
+       0x00, /* 00000000 */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 137 0x89 '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 138 0x8a '' */
+       0x00, /* 00000000 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 139 0x8b '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x66, /* 01100110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 140 0x8c '' */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x66, /* 01100110 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 141 0x8d '' */
+       0x00, /* 00000000 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 142 0x8e '' */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 143 0x8f '' */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 144 0x90 '' */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x66, /* 01100110 */
+       0x62, /* 01100010 */
+       0x68, /* 01101000 */
+       0x78, /* 01111000 */
+       0x68, /* 01101000 */
+       0x62, /* 01100010 */
+       0x66, /* 01100110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 145 0x91 '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xec, /* 11101100 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x7e, /* 01111110 */
+       0xd8, /* 11011000 */
+       0xd8, /* 11011000 */
+       0x6e, /* 01101110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 146 0x92 '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3e, /* 00111110 */
+       0x6c, /* 01101100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xfe, /* 11111110 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xce, /* 11001110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 147 0x93 '' */
+       0x00, /* 00000000 */
+       0x10, /* 00010000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 148 0x94 '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 149 0x95 '' */
+       0x00, /* 00000000 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 150 0x96 '' */
+       0x00, /* 00000000 */
+       0x30, /* 00110000 */
+       0x78, /* 01111000 */
+       0xcc, /* 11001100 */
+       0x00, /* 00000000 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 151 0x97 '' */
+       0x00, /* 00000000 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 152 0x98 '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7e, /* 01111110 */
+       0x06, /* 00000110 */
+       0x0c, /* 00001100 */
+       0x78, /* 01111000 */
+       0x00, /* 00000000 */
+
+       /* 153 0x99 '' */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 154 0x9a '' */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 155 0x9b '' */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 156 0x9c '' */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0x64, /* 01100100 */
+       0x60, /* 01100000 */
+       0xf0, /* 11110000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0xe6, /* 11100110 */
+       0xfc, /* 11111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 157 0x9d '' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 158 0x9e '' */
+       0x00, /* 00000000 */
+       0xf8, /* 11111000 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xf8, /* 11111000 */
+       0xc4, /* 11000100 */
+       0xcc, /* 11001100 */
+       0xde, /* 11011110 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 159 0x9f '' */
+       0x00, /* 00000000 */
+       0x0e, /* 00001110 */
+       0x1b, /* 00011011 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xd8, /* 11011000 */
+       0x70, /* 01110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 160 0xa0 ' ' */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0x00, /* 00000000 */
+       0x78, /* 01111000 */
+       0x0c, /* 00001100 */
+       0x7c, /* 01111100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 161 0xa1 '¡' */
+       0x00, /* 00000000 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 162 0xa2 '¢' */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 163 0xa3 '£' */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0x00, /* 00000000 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 164 0xa4 '¤' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x76, /* 01110110 */
+       0xdc, /* 11011100 */
+       0x00, /* 00000000 */
+       0xdc, /* 11011100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 165 0xa5 '¥' */
+       0x76, /* 01110110 */
+       0xdc, /* 11011100 */
+       0x00, /* 00000000 */
+       0xc6, /* 11000110 */
+       0xe6, /* 11100110 */
+       0xf6, /* 11110110 */
+       0xfe, /* 11111110 */
+       0xde, /* 11011110 */
+       0xce, /* 11001110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 166 0xa6 '¦' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x3e, /* 00111110 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 167 0xa7 '§' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 168 0xa8 '¨' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x00, /* 00000000 */
+       0x30, /* 00110000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0xc0, /* 11000000 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x7c, /* 01111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 169 0xa9 '©' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 170 0xaa 'ª' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 171 0xab '«' */
+       0x00, /* 00000000 */
+       0x60, /* 01100000 */
+       0xe0, /* 11100000 */
+       0x62, /* 01100010 */
+       0x66, /* 01100110 */
+       0x6c, /* 01101100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0xdc, /* 11011100 */
+       0x86, /* 10000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x3e, /* 00111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 172 0xac '¬' */
+       0x00, /* 00000000 */
+       0x60, /* 01100000 */
+       0xe0, /* 11100000 */
+       0x62, /* 01100010 */
+       0x66, /* 01100110 */
+       0x6c, /* 01101100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x66, /* 01100110 */
+       0xce, /* 11001110 */
+       0x9a, /* 10011010 */
+       0x3f, /* 00111111 */
+       0x06, /* 00000110 */
+       0x06, /* 00000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 173 0xad '­' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x3c, /* 00111100 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 174 0xae '®' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x36, /* 00110110 */
+       0x6c, /* 01101100 */
+       0xd8, /* 11011000 */
+       0x6c, /* 01101100 */
+       0x36, /* 00110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 175 0xaf '¯' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xd8, /* 11011000 */
+       0x6c, /* 01101100 */
+       0x36, /* 00110110 */
+       0x6c, /* 01101100 */
+       0xd8, /* 11011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 176 0xb0 '°' */
+       0x11, /* 00010001 */
+       0x44, /* 01000100 */
+       0x11, /* 00010001 */
+       0x44, /* 01000100 */
+       0x11, /* 00010001 */
+       0x44, /* 01000100 */
+       0x11, /* 00010001 */
+       0x44, /* 01000100 */
+       0x11, /* 00010001 */
+       0x44, /* 01000100 */
+       0x11, /* 00010001 */
+       0x44, /* 01000100 */
+       0x11, /* 00010001 */
+       0x44, /* 01000100 */
+       0x11, /* 00010001 */
+       0x44, /* 01000100 */
+
+       /* 177 0xb1 '±' */
+       0x55, /* 01010101 */
+       0xaa, /* 10101010 */
+       0x55, /* 01010101 */
+       0xaa, /* 10101010 */
+       0x55, /* 01010101 */
+       0xaa, /* 10101010 */
+       0x55, /* 01010101 */
+       0xaa, /* 10101010 */
+       0x55, /* 01010101 */
+       0xaa, /* 10101010 */
+       0x55, /* 01010101 */
+       0xaa, /* 10101010 */
+       0x55, /* 01010101 */
+       0xaa, /* 10101010 */
+       0x55, /* 01010101 */
+       0xaa, /* 10101010 */
+
+       /* 178 0xb2 '²' */
+       0xdd, /* 11011101 */
+       0x77, /* 01110111 */
+       0xdd, /* 11011101 */
+       0x77, /* 01110111 */
+       0xdd, /* 11011101 */
+       0x77, /* 01110111 */
+       0xdd, /* 11011101 */
+       0x77, /* 01110111 */
+       0xdd, /* 11011101 */
+       0x77, /* 01110111 */
+       0xdd, /* 11011101 */
+       0x77, /* 01110111 */
+       0xdd, /* 11011101 */
+       0x77, /* 01110111 */
+       0xdd, /* 11011101 */
+       0x77, /* 01110111 */
+
+       /* 179 0xb3 '³' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 180 0xb4 '´' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xf8, /* 11111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 181 0xb5 'µ' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xf8, /* 11111000 */
+       0x18, /* 00011000 */
+       0xf8, /* 11111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 182 0xb6 '¶' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0xf6, /* 11110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 183 0xb7 '·' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 184 0xb8 '¸' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xf8, /* 11111000 */
+       0x18, /* 00011000 */
+       0xf8, /* 11111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 185 0xb9 '¹' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0xf6, /* 11110110 */
+       0x06, /* 00000110 */
+       0xf6, /* 11110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 186 0xba 'º' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 187 0xbb '»' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x06, /* 00000110 */
+       0xf6, /* 11110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 188 0xbc '¼' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0xf6, /* 11110110 */
+       0x06, /* 00000110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 189 0xbd '½' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 190 0xbe '¾' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xf8, /* 11111000 */
+       0x18, /* 00011000 */
+       0xf8, /* 11111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 191 0xbf '¿' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xf8, /* 11111000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 192 0xc0 'À' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x1f, /* 00011111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 193 0xc1 'Á' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 194 0xc2 'Â' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 195 0xc3 'Ã' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x1f, /* 00011111 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 196 0xc4 'Ä' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 197 0xc5 'Å' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xff, /* 11111111 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 198 0xc6 'Æ' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x1f, /* 00011111 */
+       0x18, /* 00011000 */
+       0x1f, /* 00011111 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 199 0xc7 'Ç' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x37, /* 00110111 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 200 0xc8 'È' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x37, /* 00110111 */
+       0x30, /* 00110000 */
+       0x3f, /* 00111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 201 0xc9 'É' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3f, /* 00111111 */
+       0x30, /* 00110000 */
+       0x37, /* 00110111 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 202 0xca 'Ê' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0xf7, /* 11110111 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 203 0xcb 'Ë' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0xf7, /* 11110111 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 204 0xcc 'Ì' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x37, /* 00110111 */
+       0x30, /* 00110000 */
+       0x37, /* 00110111 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 205 0xcd 'Í' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 206 0xce 'Î' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0xf7, /* 11110111 */
+       0x00, /* 00000000 */
+       0xf7, /* 11110111 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 207 0xcf 'Ï' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 208 0xd0 'Ð' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 209 0xd1 'Ñ' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 210 0xd2 'Ò' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 211 0xd3 'Ó' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x3f, /* 00111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 212 0xd4 'Ô' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x1f, /* 00011111 */
+       0x18, /* 00011000 */
+       0x1f, /* 00011111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 213 0xd5 'Õ' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x1f, /* 00011111 */
+       0x18, /* 00011000 */
+       0x1f, /* 00011111 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 214 0xd6 'Ö' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x3f, /* 00111111 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 215 0xd7 '×' */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0xff, /* 11111111 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+
+       /* 216 0xd8 'Ø' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xff, /* 11111111 */
+       0x18, /* 00011000 */
+       0xff, /* 11111111 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 217 0xd9 'Ù' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xf8, /* 11111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 218 0xda 'Ú' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x1f, /* 00011111 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 219 0xdb 'Û' */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+
+       /* 220 0xdc 'Ü' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+
+       /* 221 0xdd 'Ý' */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+       0xf0, /* 11110000 */
+
+       /* 222 0xde 'Þ' */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+       0x0f, /* 00001111 */
+
+       /* 223 0xdf 'ß' */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0xff, /* 11111111 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 224 0xe0 'à' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x76, /* 01110110 */
+       0xdc, /* 11011100 */
+       0xd8, /* 11011000 */
+       0xd8, /* 11011000 */
+       0xd8, /* 11011000 */
+       0xdc, /* 11011100 */
+       0x76, /* 01110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 225 0xe1 'á' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x78, /* 01111000 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xcc, /* 11001100 */
+       0xd8, /* 11011000 */
+       0xcc, /* 11001100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xcc, /* 11001100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 226 0xe2 'â' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0xc0, /* 11000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 227 0xe3 'ã' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 228 0xe4 'ä' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0xc6, /* 11000110 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 229 0xe5 'å' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0xd8, /* 11011000 */
+       0xd8, /* 11011000 */
+       0xd8, /* 11011000 */
+       0xd8, /* 11011000 */
+       0xd8, /* 11011000 */
+       0x70, /* 01110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 230 0xe6 'æ' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x7c, /* 01111100 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0xc0, /* 11000000 */
+       0x00, /* 00000000 */
+
+       /* 231 0xe7 'ç' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x76, /* 01110110 */
+       0xdc, /* 11011100 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 232 0xe8 'è' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x3c, /* 00111100 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 233 0xe9 'é' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xfe, /* 11111110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 234 0xea 'ê' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0xee, /* 11101110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 235 0xeb 'ë' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x1e, /* 00011110 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x0c, /* 00001100 */
+       0x3e, /* 00111110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x66, /* 01100110 */
+       0x3c, /* 00111100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 236 0xec 'ì' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0xdb, /* 11011011 */
+       0xdb, /* 11011011 */
+       0xdb, /* 11011011 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 237 0xed 'í' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x03, /* 00000011 */
+       0x06, /* 00000110 */
+       0x7e, /* 01111110 */
+       0xdb, /* 11011011 */
+       0xdb, /* 11011011 */
+       0xf3, /* 11110011 */
+       0x7e, /* 01111110 */
+       0x60, /* 01100000 */
+       0xc0, /* 11000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 238 0xee 'î' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x1c, /* 00011100 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x7c, /* 01111100 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x1c, /* 00011100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 239 0xef 'ï' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7c, /* 01111100 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0xc6, /* 11000110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 240 0xf0 'ð' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0xfe, /* 11111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 241 0xf1 'ñ' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x7e, /* 01111110 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 242 0xf2 'ò' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x0c, /* 00001100 */
+       0x06, /* 00000110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 243 0xf3 'ó' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x30, /* 00110000 */
+       0x60, /* 01100000 */
+       0x30, /* 00110000 */
+       0x18, /* 00011000 */
+       0x0c, /* 00001100 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 244 0xf4 'ô' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x0e, /* 00001110 */
+       0x1b, /* 00011011 */
+       0x1b, /* 00011011 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+
+       /* 245 0xf5 'õ' */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0xd8, /* 11011000 */
+       0xd8, /* 11011000 */
+       0xd8, /* 11011000 */
+       0x70, /* 01110000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 246 0xf6 'ö' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 247 0xf7 '÷' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x76, /* 01110110 */
+       0xdc, /* 11011100 */
+       0x00, /* 00000000 */
+       0x76, /* 01110110 */
+       0xdc, /* 11011100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 248 0xf8 'ø' */
+       0x00, /* 00000000 */
+       0x38, /* 00111000 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x38, /* 00111000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 249 0xf9 'ù' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 250 0xfa 'ú' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x18, /* 00011000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 251 0xfb 'û' */
+       0x00, /* 00000000 */
+       0x0f, /* 00001111 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0x0c, /* 00001100 */
+       0xec, /* 11101100 */
+       0x6c, /* 01101100 */
+       0x6c, /* 01101100 */
+       0x3c, /* 00111100 */
+       0x1c, /* 00011100 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 252 0xfc 'ü' */
+       0x00, /* 00000000 */
+       0x6c, /* 01101100 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x36, /* 00110110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 253 0xfd 'ý' */
+       0x00, /* 00000000 */
+       0x3c, /* 00111100 */
+       0x66, /* 01100110 */
+       0x0c, /* 00001100 */
+       0x18, /* 00011000 */
+       0x32, /* 00110010 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 254 0xfe 'þ' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x7e, /* 01111110 */
+       0x7e, /* 01111110 */
+       0x7e, /* 01111110 */
+       0x7e, /* 01111110 */
+       0x7e, /* 01111110 */
+       0x7e, /* 01111110 */
+       0x7e, /* 01111110 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+       /* 255 0xff 'ÿ' */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+       0x00, /* 00000000 */
+
+};
+
+#endif /* #ifndef _VGA_TABLE_H */
diff --git a/board/mpl/common/video.c b/board/mpl/common/video.c
new file mode 100644 (file)
index 0000000..71cd1fb
--- /dev/null
@@ -0,0 +1,756 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ * Note: Parts of these software are imported from 
+ *       - UBL, The Universal Talkware Boot Loader
+ *         Copyright (C) 2000 Universal Talkware Inc.
+ *       - Linux
+ *
+ * 
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <devices.h>
+#include "video.h"
+#ifdef CONFIG_4xx
+#include <405gp_pci.h>
+#endif
+#include "vga_table.h"
+
+#ifdef CONFIG_VIDEO_CT69000
+#define VIDEO_VEND_ID 0x102C
+#define VIDEO_DEV_ID  0x00C0
+#else
+#error  CONFIG_VIDEO_CT69000 must be defined
+#endif
+
+/* 
+ * Routine for resent board info to video
+ * resides in pip405.c
+ */
+extern void video_write_board_info(void); 
+
+#undef VGA_DEBUG
+
+#ifdef VGA_DEBUG
+#define        PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#define VGA_MAXROWS    25
+#define VGA_MAXCOLS 80
+
+#define CRTC_CURSH     14 /* cursor high pos */
+#define CRTC_CURSL     15 /* cursor low pos */
+
+/* description of the hardware layout */
+
+#define ATTRI_INDEX            CFG_ISA_IO_BASE_ADDRESS | 0x3c0                         /* Index and Data write port of the attribute Registers */
+#define ATTRI_DATA             CFG_ISA_IO_BASE_ADDRESS | 0x3c1                         /* Data port of the attribute Registers */
+#define STATUS_REG0            CFG_ISA_IO_BASE_ADDRESS | 0x3c2                         /* Status Register 0 (read only) */
+#define MSR_REG_W                      CFG_ISA_IO_BASE_ADDRESS | 0x3c2                         /* Misc. Output Register (write only) */
+#define SEQ_INDEX                      CFG_ISA_IO_BASE_ADDRESS | 0x3c4                         /* Index port of the Sequencer Controller */
+#define SEQ_DATA                       CFG_ISA_IO_BASE_ADDRESS | 0x3c5                         /* Data port of the Sequencer Controller */
+#define COL_PAL_MASK   CFG_ISA_IO_BASE_ADDRESS | 0x3c6                         /* Color Palette Mask */
+#define COL_PAL_STAT   CFG_ISA_IO_BASE_ADDRESS | 0x3c7                         /* Color Palette Status (read only) */
+#define COL_PAL_IND_R  CFG_ISA_IO_BASE_ADDRESS | 0x3c7                         /* Color Palette Read Mode Index (write only) */
+#define COL_PAL_IND_W  CFG_ISA_IO_BASE_ADDRESS | 0x3c8                         /* Color Palette Write Mode Index */
+#define COL_PAL_DATA   CFG_ISA_IO_BASE_ADDRESS | 0x3c9                         /* Color Palette Data Port */
+#define FCR_REG_R                      CFG_ISA_IO_BASE_ADDRESS | 0x3ca                         /* Feature Control Register (read only) */
+#define MSR_REG_R                      CFG_ISA_IO_BASE_ADDRESS | 0x3cc                         /* Misc. Output Register (read only) */
+#define GR_INDEX                       CFG_ISA_IO_BASE_ADDRESS | 0x3ce                         /* Index port of the Graphic Controller Registers */
+#define GR_DATA                                CFG_ISA_IO_BASE_ADDRESS | 0x3cf                         /* Data port of the Graphic Controller Registers */
+#define FP_INDEX                       CFG_ISA_IO_BASE_ADDRESS | 0x3d0                         /* Index port of the Flat panel Registers */
+#define FP_DATA                                CFG_ISA_IO_BASE_ADDRESS | 0x3d1                         /* Data port of the Flat panel Registers */
+#define MR_INDEX                       CFG_ISA_IO_BASE_ADDRESS | 0x3d2                         /* Index Port of the Multimedia Extension */                            
+#define MR_DATA                                CFG_ISA_IO_BASE_ADDRESS | 0x3d3                         /* Data Port of the Multimedia Extension */
+#define CRT_INDEX                      CFG_ISA_IO_BASE_ADDRESS | 0x3d4                         /* Index port of the CRT Controller */
+#define CRT_DATA                       CFG_ISA_IO_BASE_ADDRESS | 0x3d5                         /* Data port of the CRT Controller */
+#define XREG_INDEX             CFG_ISA_IO_BASE_ADDRESS | 0x3d6                         /* Extended Register index */
+#define XREG_DATA                      CFG_ISA_IO_BASE_ADDRESS | 0x3d7                         /* Extended Register data */
+#define STATUS_REG1            CFG_ISA_IO_BASE_ADDRESS | 0x3da                         /* Input Status Register 1 (read only) */
+#define FCR_REG_W                      CFG_ISA_IO_BASE_ADDRESS | 0x3da                         /* Feature Control Register (write only) */
+
+
+static unsigned char * video_fb;               /* Frame buffer */
+
+/* current hardware state */
+
+static int     video_row;
+static int     video_col;
+static unsigned char video_attr;
+
+static unsigned long font_base_addr;
+/**********************************************************************
+ * some forward declerations...
+ */
+int video_init(int busdevfunc);
+void vga_set_attrib(void);
+void vga_set_crt(void);
+void vga_set_dac(void);
+void vga_set_gr(void);
+void vga_set_seq(void);
+void vga_set_xreg(void);
+void vga_write_sr(unsigned char reg,unsigned char val);
+void vga_write_gr(unsigned char reg,unsigned char val);
+void vga_write_cr(unsigned char reg,unsigned char val);
+void vga_set_font(void);
+
+/***************************************************************************
+ * Init VGA Device
+ */
+
+int drv_video_init(void)
+{
+       int error, devices = 1 ;
+  device_t vgadev ;
+       int     busdevfunc;
+
+       busdevfunc=PCI_Find_Device(VIDEO_VEND_ID,VIDEO_DEV_ID); /* get PCI Device ID */
+       if(busdevfunc==-1) {
+               printf("Error VGA Controller (%04X,%04X) not found\n",VIDEO_VEND_ID,VIDEO_DEV_ID);
+               return -1;
+       }
+       video_init(busdevfunc);
+       video_write_board_info();
+  memset (&vgadev, 0, sizeof(vgadev));
+
+  strcpy(vgadev.name, "vga");
+  vgadev.flags =  DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
+  vgadev.putc = video_putc;
+  vgadev.puts = video_puts;
+  vgadev.getc = NULL;
+  vgadev.tstc = NULL;
+
+  error = device_register (&vgadev);
+               
+  return (error == 0) ? devices : error ;
+}
+
+
+/***********************************************************
+ * VGA Initializing
+ */
+
+int video_init(int busdevfunc)
+{
+  font_base_addr = PCI_Read_CFG_Reg(busdevfunc, PCI_CFG_BASE_ADDRESS_0, 4);
+
+  video_fb = (char*)font_base_addr; /* we look into the big linaer memory area */
+
+  /* set the extended Registers */
+       vga_set_xreg();
+
+       /* set IO Addresses to 0x3Dx (color mode ) */
+       out8(MSR_REG_W,0x01);
+
+  /* Feature Control Register:
+     Bits 7-4 Reserved = 0
+     Bit  3   Vertical Sync select = 1 = Enabled
+     Bits 2-0 Reserved = 010 = as read from memory.
+  */
+  out8(FCR_REG_W,0x02);
+
+
+  /* Miscelaneous output Register:
+     Bits 7-6 (num lines) = 01 = VGA 400 lines,
+     Bit  5   (Odd/Even Page) =  1 = Sleect high page of memory,
+     Bit  4   reserved = 0,
+     Bits 3-2 (Clocl Select) = 01 = 28.322Mhz
+     Bit  1 = Display Ram Enable = 1 = Enable processor access.
+     Bit  0 = Io Address Select = 1 = Color Graphics Enulation.
+  */
+  out8(MSR_REG_W,0x67);
+  /* set the palette */
+  vga_set_dac();
+  /* set the attributes (before we bring up the engine
+     then we dont have to wait for refresh).
+  */
+  vga_set_attrib();
+
+  /* set the crontroller register. */
+  vga_set_crt();
+
+       vga_write_sr(0x00,0x01); /* synchronous reset */
+       vga_write_sr(0x01,0x00); /* clocking mode */
+       vga_write_sr(0x02,0x03); /* write to map 0, 1 */
+       vga_write_sr(0x03,0x00); /* select character map 0 */
+       vga_write_sr(0x04,0x03); /* even-odd addressing */
+       vga_write_sr(0x00,0x03); /* clear synchronous reset */
+
+  vga_set_seq(); /* Set the extended sr's. */
+
+  vga_set_gr(); /* Set the graphic registers. */
+
+  /* load the font */
+  vga_set_font();
+
+  /* initialize the rol/col counts and the text attribute. */
+  video_row=0;
+  video_col=0;
+  video_attr = VGA_ATTR_CLR_WHT;
+
+  /* Clear the video ram */
+  video_clear();
+
+  return 1;
+}
+
+void vga_set_font(void)
+{
+       int i,j;
+       char *fontmap;
+       fontmap = (char *)font_base_addr;
+       
+       vga_write_sr(0x00,0x01); /* synchronous reset */
+       vga_write_sr(0x04,0x06); /* sequential addressing */
+       vga_write_sr(0x02,0x04); /* write to map 2 */
+       vga_write_sr(0x00,0x03); /* clear synchronous reset */
+
+       vga_write_gr(0x04,0x02); /* select map 2 */
+       vga_write_gr(0x05,0x00); /* disable odd-even addressing */
+       vga_write_gr(0x06,0x00); /* map start at 0xa0000 */
+       
+       for(i=0;i<0x100;i++) {
+               for(j=0;j<0x10;j++) {
+                       *((char *)fontmap+i*32+j)=(char)fontdata_8x16[i*16+j];
+               }
+       }
+       vga_write_sr(0x00,0x01); /* synchronous reset */
+       vga_write_sr(0x02,0x03); /* write to map 0 and 1 */
+       vga_write_sr(0x04,0x03); /* odd-even addressing */
+       vga_write_sr(0x03,0x00); /* Character map 0 & 1 */
+       vga_write_sr(0x00,0x03); /* clear synchronous reset */
+
+       vga_write_gr(0x04,0x00); /* select map 0 for CPU */
+       vga_write_gr(0x05,0x10); /* enable odd-even addressing */
+       vga_write_gr(0x06,0x0E); /* map start at 0xb8000 */
+}
+
+
+/* since we are BIG endian, swap attributes and char */
+unsigned short vga_swap_short(unsigned short val)
+{
+       unsigned short swapped;
+       swapped = ((val & 0xff)<<8) | ((val & 0xff00)>>8);
+       return swapped;
+}
+
+/****************************************************
+ * Routines usable Outside world
+ */
+/* scolls the text up row rows */
+void video_scroll(int row)
+{
+  unsigned short clear = ((unsigned short)video_attr << 8) | (' ');
+  unsigned short* addr16 = &((unsigned short *)video_fb)[(VGA_MAXROWS-row)*VGA_MAXCOLS];
+  int i;
+
+       clear=vga_swap_short(clear);
+  memcpy(video_fb, video_fb+row*(VGA_MAXCOLS*2), (VGA_MAXROWS-row)*(VGA_MAXCOLS*2));
+  for (i = 0 ; i < row * VGA_MAXCOLS ; i++)
+    addr16[i] = clear;
+  video_row-=row;
+  video_col=0;
+}
+
+
+unsigned long video_cursor(int col, int row)
+{
+   unsigned short off = row * VGA_MAXCOLS + col ;
+   unsigned long saved = (video_col << 16) | (video_row & 0xFFFF);
+   video_col = col;
+   video_row = row;
+   
+   vga_write_cr(CRTC_CURSH,(unsigned char)((off & 0xff00)>>8)); /* Cursor pos. high */
+   vga_write_cr(CRTC_CURSL,(unsigned char)(off & 0xff));          /* Cursor pos. low */
+   return saved;
+}
+
+void video_set_lxy(unsigned long lxy)
+{
+  int col = (lxy >> 16) & 0xFFFF;
+  int row = lxy & 0xFFFF;
+  video_cursor(col,row);
+}
+
+unsigned long video_get_lxy(void)
+{
+   return (video_col << 16) | (video_row & 0xFFFF);
+}
+
+void video_clear(void)
+{
+  int i;
+  unsigned short clear = ((unsigned short)video_attr << 8) | (' ');
+  unsigned short * addr16 = (unsigned short * )video_fb;
+       clear=vga_swap_short(clear);
+  video_row = video_col = 0;
+  for (i = 0 ; i < 2000 ; i++) {
+    addr16[i] = clear;
+  }
+}
+
+void video_copy(unsigned short *buffer)
+{
+  int i;
+  unsigned short * addr16 = (unsigned short * )video_fb;
+  for (i = 0 ; i < 2000 ; i++) {
+    buffer[i] = addr16[i];
+  }
+}
+
+void video_write(unsigned short *buffer)
+{
+  int i;
+  unsigned short * addr16 = (unsigned short *)video_fb;
+  for (i = 0 ; i < 2000 ; i++) {
+    addr16[i] = buffer[i];
+  }
+}
+
+void video_putc(char ch)
+{
+       char* addr;
+#if 0
+       char buf[48];
+       char buf1[16];
+       static int i=0;
+       
+       sprintf(buf1,"%02X ",ch);
+       serial_puts(buf1);
+       buf[i++]=((ch>=0x20)&&(ch<=0x7f)) ? ch : '.';
+       if(i>=16) {
+               buf[i++]='\n';
+               buf[i]='\0';
+               i=0;
+               serial_puts("     ");
+               serial_puts(buf);
+       }
+#endif
+       switch (ch) {
+               case '\n':
+                       video_col=0;
+                       video_row++;
+                       break;
+               case '\r':
+                       video_col=0;
+                       break;
+               case '\t':
+      video_col += 8 - video_col % 8;
+      break;
+    case '\a':
+/*      beep(); */
+      break;
+    case '\b':
+      if(video_col)
+                               video_col--;
+      else 
+                               return;
+      break;
+    default:
+      addr = video_fb + 2 * video_row * 80 + 2 * video_col;
+      
+      *((char *)addr+1) = (char) video_attr;
+      *((char *)addr) = (char) ch;
+      video_col++;
+      if (video_col > (VGA_MAXCOLS-1)) {
+                               video_row++;
+                               video_col=0;
+      }
+   }
+
+   /* If we're on the bottom of the secreen, wrap one row */
+   if (video_row > (VGA_MAXROWS-1))
+     video_scroll(1);
+    video_cursor(video_col, video_row);
+}
+
+
+unsigned char video_set_attr(unsigned char attr) 
+{
+  unsigned char saved_attr = video_attr;
+  video_attr = attr;
+  return saved_attr;
+}
+
+unsigned char video_set_attr_xy(unsigned char attr, int x, int y) 
+{
+  unsigned char *addr = video_fb + (x * 80 + y) * 2 + 1;
+  unsigned char saved_attr = *addr;
+  *addr = attr;
+  return saved_attr;
+}
+
+/* put char at xy */
+void video_putc_xy(char ch, int x, int y) 
+{
+  video_col = x;
+  video_row = y;
+  video_putc(ch);
+}
+
+/* put char at xy relative to the position */
+void video_putc_rxy(char ch, int x, int y) 
+{
+  video_col += x;
+  video_row += y;
+  video_putc(ch);
+}
+
+/* put char with attribute at xy */
+void video_putc_axy(char ch, char attr, int x, int y) 
+{
+  unsigned char saved_attr = video_set_attr(attr);
+  video_col = x;
+  video_row = y;
+  video_putc(ch);
+  video_set_attr(saved_attr);
+}
+
+void video_puts(const char *s)
+{
+   while(*s) {
+      video_putc(*s);
+      s++;
+   }
+}
+
+void video_puts_a(const char *s, char attr) 
+{
+  unsigned char saved_attr = video_set_attr(attr);
+  video_puts(s);
+  video_set_attr(saved_attr);
+}
+
+void video_puts_xy(const char *s, int x, int y) 
+{
+  video_cursor(x,y);
+  video_puts(s);
+}
+
+void video_puts_axy(const char *s, char attr, int x, int y) 
+{
+  unsigned char saved_attr = video_set_attr(attr);
+  video_puts_xy(s, x, y);
+  video_set_attr(saved_attr);
+}
+
+void video_wipe_ca_area(unsigned char ch, char attr, int x, int y, int w, int h) 
+{
+  int r, c;
+  /* better to do this as word writes */ 
+  unsigned short * addr16 = (unsigned short  *)video_fb + (y * 80 + x);
+  unsigned short charattr = (unsigned short)ch << 8 | attr;
+       charattr=vga_swap_short(charattr);
+  for (r = 0 ; r < h ; r++, addr16 += 80) {
+    for (c = 0 ; c < w ; c++) {
+      addr16[c] = charattr;
+    }
+  }
+}
+
+void video_wipe_a_area(unsigned char attr, int x, int y, int w, int h) 
+{
+  int r, c;
+  /* better to do this as word writes */ 
+  unsigned short * addr16 = (unsigned short *)video_fb + (y * 80 + x);
+  for (r = 0 ; r < h ; r++, addr16 += 80) {
+    for (c = 0 ; c < w ; c++) {
+      ((char*)addr16)[c*2+1] = attr;
+    }
+  }
+}
+
+void video_wipe_c_area(unsigned char ch, int x, int y, int w, int h) 
+{
+  int r, c;
+  /* better to do this as word writes */ 
+  unsigned short * addr16 = (unsigned short  *)video_fb + (y * 80 + x);
+  for (r = 0 ; r < h ; r++, addr16 += 80) {
+    for (c = 0 ; c < w ; c++) {
+      ((char*)addr16)[c*2] = ch;
+    }
+  }
+}
+
+
+/*
+tl t tr
+l    l
+bl b br
+*/
+typedef struct {
+  unsigned char tl; /* top left corner */
+  unsigned char t;  /* top edge */
+  unsigned char tr; /* top right corner */
+  unsigned char l;  /* left edge */
+  unsigned char r;  /* right edge */
+  unsigned char bl; /* bottom left corner */
+  unsigned char b;  /* bottom edge */
+  unsigned char br; /* bottom right corner */
+} box_chars_t;
+
+box_chars_t sbox_chars = {
+  0xDA, 0xC4, 0xBF,
+  0xB3,       0xB3,
+  0xC0, 0xC4, 0xD9
+};
+
+box_chars_t dbox_chars = {
+  0xC9, 0xCD, 0xBB,
+  0xBA,       0xBA,
+  0xC8, 0xCD, 0xBC
+};
+
+static char cmap[] = "0123456789ABCDEF";
+void video_putchex(char c) 
+{
+  video_putc(cmap[(c >> 4 ) & 0xF]);
+  video_putc(cmap[c & 0xF]);
+}
+
+void video_putchexl(char c) 
+{
+  video_putc(cmap[c & 0xF]);
+}
+
+void video_putchexh(char c) 
+{
+  video_putc(cmap[(c >> 4) & 0xF]);
+}
+
+#define VGA_CELL_CA(a,c) (((unsigned short)c<<8)|a) /* for BIG endians */
+
+void video_gbox_area(box_chars_t *box_chars_p, int x, int y, int w, int h) 
+{
+  int r, c;
+  /* better to do this as word writes */ 
+  unsigned short* addr16 = (unsigned short *)video_fb + (y * VGA_MAXCOLS + x);
+  for (r = 0 ; r < h ; r++, addr16 += VGA_MAXCOLS) {
+    if (r == 0) {
+      addr16[0]   = VGA_CELL_CA(video_attr, box_chars_p->tl);
+      addr16[w-1] = VGA_CELL_CA(video_attr, box_chars_p->tr);
+      for (c = 1 ; c < w - 1 ; c++)
+                               addr16[c] = VGA_CELL_CA(video_attr, box_chars_p->t);
+    } else if (r == h - 1) {
+      addr16[0] = VGA_CELL_CA(video_attr, box_chars_p->bl);
+      addr16[w-1] = VGA_CELL_CA(video_attr, box_chars_p->br);
+      for (c = 1 ; c < w - 1 ; c++)
+                               addr16[c] = VGA_CELL_CA(video_attr, box_chars_p->b);
+    } else {
+      addr16[0] = VGA_CELL_CA(video_attr, box_chars_p->l);
+      addr16[w-1] = VGA_CELL_CA(video_attr, box_chars_p->r);
+    }
+  }
+}
+
+/* Writes a box on the screen */
+void video_box_area(int x, int y, int w, int h) {
+  video_gbox_area(&sbox_chars, x, y, w, h);
+}
+/*writes a box with double lines on the screen */
+void video_dbox_area(int x, int y, int w, int h) {
+  video_gbox_area(&dbox_chars, x, y, w, h);
+}
+
+/* routines to set the VGA registers */
+
+/* set attributes */
+void vga_set_attrib(void)
+{
+       int i;
+       unsigned char status;
+       
+       status=in8(STATUS_REG1);
+       i=0;
+       
+       while(attr[i].reg!=0xFF) {
+               out8(ATTRI_INDEX,attr[i].reg);
+               out8(ATTRI_INDEX,attr[i].val); /* Attribute uses index for index and data */
+               i++;
+       }
+       out8(ATTRI_INDEX,0x20); /* unblank the screen */
+}
+
+/* set CRT Controller Registers */
+void vga_set_crt(void)
+{
+       int i;
+       i=0;
+       while(crtc[i].reg!=0xFF) {
+               out8(CRT_INDEX,crtc[i].reg);
+               out8(CRT_DATA,crtc[i].val); 
+               i++;
+       }
+}
+/* Set Palette Registers (DAC) */
+void vga_set_dac(void)
+{
+       int i;
+       for(i=0;i<256;i++) {
+               out8(COL_PAL_IND_W,(unsigned char)i);
+               out8(COL_PAL_DATA,dac[i][0]); /* red */
+               out8(COL_PAL_DATA,dac[i][1]); /* green */
+               out8(COL_PAL_DATA,dac[i][2]); /* blue */
+       }
+       out8(COL_PAL_MASK,0xff); /* set mask */
+}
+/* set Graphic Controller Register */
+void vga_set_gr(void)
+{
+       int i;
+       i=0;
+       while(grmr[i].reg!=0xFF) {
+               out8(GR_INDEX,grmr[i].reg);
+               out8(GR_DATA,grmr[i].val); 
+               i++;
+       }
+}
+
+/* Set Sequencer Registers */
+void vga_set_seq(void)
+{
+       int i;
+       i=0;
+       while(seq[i].reg!=0xFF) {
+               out8(SEQ_INDEX,seq[i].reg);
+               out8(SEQ_DATA,seq[i].val); 
+               i++;
+       }
+}
+
+
+/* Set Extension Registers */
+void vga_set_xreg(void)
+{
+       int i;
+       i=0;
+       while(xreg[i].reg!=0xFF) {
+               out8(XREG_INDEX,xreg[i].reg);
+               out8(XREG_DATA,xreg[i].val); 
+               i++;
+       }
+}
+
+/************************************************************
+ * some helping routines
+ */
+void vga_write_sr(unsigned char reg,unsigned char val)
+{
+       out8(SEQ_INDEX,reg);
+       out8(SEQ_DATA,val); 
+}
+
+void vga_write_gr(unsigned char reg,unsigned char val)
+{
+       out8(GR_INDEX,reg);
+       out8(GR_DATA,val); 
+}
+
+void vga_write_cr(unsigned char reg,unsigned char val)
+{
+       out8(CRT_INDEX,reg);
+       out8(CRT_DATA,val); 
+}
+
+
+#if 0
+void video_dump_reg(void)
+{
+       /* first dump attributes */
+       int i;
+       unsigned char status;
+
+       
+       printf("Extended Regs:\n");     
+       i=0;
+       while(xreg[i].reg!=0xFF) {
+               out8(XREG_INDEX,xreg[i].reg);
+               status=in8(XREG_DATA);
+               printf("XR%02X is %02X, should be %02X\n",xreg[i].reg,status,xreg[i].val);
+               i++;
+       }
+       printf("Sequencer Regs:\n");    
+       i=0;
+       while(seq[i].reg!=0xFF) {
+               out8(SEQ_INDEX,seq[i].reg);
+               status=in8(SEQ_DATA);
+               printf("SR%02X is %02X, should be %02X\n",seq[i].reg,status,seq[i].val);
+               i++;
+       }
+       printf("Graphic Regs:\n");      
+       i=0;
+       while(grmr[i].reg!=0xFF) {
+               out8(GR_INDEX,grmr[i].reg);
+               status=in8(GR_DATA);
+               printf("GR%02X is %02X, should be %02X\n",grmr[i].reg,status,grmr[i].val);
+               i++;
+       }
+       printf("CRT Regs:\n");  
+       i=0;
+       while(crtc[i].reg!=0xFF) {
+               out8(CRT_INDEX,crtc[i].reg);
+               status=in8(CRT_DATA);
+               printf("CR%02X is %02X, should be %02X\n",crtc[i].reg,status,crtc[i].val);
+               i++;
+       }
+       printf("Attributes:\n");        
+       status=in8(STATUS_REG1);
+       i=0;
+       while(attr[i].reg!=0xFF) {
+               out8(ATTRI_INDEX,attr[i].reg);
+               status=in8(ATTRI_DATA);
+               out8(ATTRI_INDEX,attr[i].val); /* Attribute uses index for index and data */
+               printf("AR%02X is %02X, should be %02X\n",attr[i].reg,status,attr[i].val);
+               i++;
+       }
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/board/mpl/common/video.h b/board/mpl/common/video.h
new file mode 100644 (file)
index 0000000..3c6f513
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#ifndef _VIDEO_H
+#define _VIDEO_H
+
+int video_init(int busdevfunc);
+void video_clear(void);
+void video_putc(char ch);
+void video_puts(const char *s);
+void video_puts_a(const char *s, char attr); 
+unsigned char video_set_attr(unsigned char attr);
+
+void video_box_area(int x, int y, int w, int h);
+void video_dbox_area(int x, int y, int w, int h);
+void video_wipe_c_area(unsigned char ch, int x, int y, int w, int h);
+
+void video_wipe_a_area(unsigned char attr, int x, int y, int w, int h); 
+void video_wipe_ca_area(unsigned char ch, char attr, int x, int y, int w, int h); 
+void video_puts_axy(const char *s, char attr, int x, int y); 
+void video_putc_rxy(char ch, int x, int y); 
+void video_putc_xy(char ch, int x, int y); 
+unsigned char video_set_attr_xy(unsigned char attr, int x, int y); 
+void video_copy(unsigned short *buffer);
+void video_write(unsigned short *buffer);
+
+#define VGA_ATTR_CLR_RED       0x4
+#define VGA_ATTR_CLR_GRN       0x2
+#define VGA_ATTR_CLR_BLU       0x1
+#define VGA_ATTR_CLR_YEL       (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN)
+#define VGA_ATTR_CLR_CYN       (VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU)
+#define VGA_ATTR_CLR_MAG       (VGA_ATTR_CLR_BLU | VGA_ATTR_CLR_RED)
+#define VGA_ATTR_CLR_BLK       0
+#define VGA_ATTR_CLR_WHT       (VGA_ATTR_CLR_RED | VGA_ATTR_CLR_GRN | VGA_ATTR_CLR_BLU)
+
+#define VGA_ATTR_BNK                   0x80
+#define VGA_ATTR_ITN                   0x08
+
+#define VGA_ATTR_BG_MSK  0x70
+#define VGA_ATTR_FG_MSK  0x07
+
+#define VGA_ATTR_BG_GET(v) (((v) & VGA_ATTR_BG_MSK)>>4)
+#define VGA_ATTR_BG_SET(v, c) (((c) & VGA_ATTR_FG_MSK)<<4) | (v & ~VGA_ATTR_BG_MSK))
+
+#define VGA_ATTR_FG_GET(v) ((v) & VGA_ATTR_FG_MSK)
+#define VGA_ATTR_FG_SET(v, c) ((c) & VGA_ATTR_FG_MSK) | (v & ~VGA_ATTR_FG_MSK))
+
+#define VGA_ATTR_FG_BG_SET(v, b, f) (VGA_ATTR_BG_SET(v, b) | VGA_ATTR_FG_SET(v, cf))
+
+#define VGA_ATTR_INVERT(A) ((((A)&0x7)<<4)|(((A)&0x70)>>4) |((A)&0x88))
+
+#endif
diff --git a/board/mpl/mip405/Makefile b/board/mpl/mip405/Makefile
new file mode 100644 (file)
index 0000000..bcb1da5
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# (C) Copyright 2000, 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 ../common/flash.o cmd_mip405.o ../common/pci.o ../common/usb_uhci.o ../common/memtst.o
+SOBJS  = init.o
+
+$(LIB):        $(OBJS) $(SOBJS)
+       $(AR) crv $@ $^
+
+clean:
+       rm -f $(SOBJS) $(OBJS)
+
+distclean:     clean
+       rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend:       Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/mpl/mip405/cmd_mip405.c b/board/mpl/mip405/cmd_mip405.c
new file mode 100644 (file)
index 0000000..3829a24
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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
+ *
+ * hacked for PIP405
+ */
+
+#include <ppcboot.h>
+#include <command.h> 
+#include "mip405.h"
+#include <rtc.h>
+#include "../common/isa.h"
+#include "../common/video.h"
+#include <i2c.h>
+extern flash_info_t flash_info[];      /* info for FLASH chips */
+
+int PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned int Value, int Width);
+unsigned int PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width);
+extern void print_mip405_info(void);
+
+
+
+
+
+#define TRUE 1
+#define FALSE 0
+
+#define IMAGE_SIZE 0x80000 
+
+image_header_t header;
+
+
+
+int mip405_prg(unsigned long src,unsigned long size)
+{
+       unsigned long start;
+       flash_info_t *info;
+       int i,rc;
+       unsigned long *magic = (unsigned long *)src;
+       
+       info = &flash_info[0];
+       start = 0 - size;
+       for(i=info->sector_count-1;i>0;i--)
+       {
+               info->protect[i] = 0; /* unprotect this sector */
+               if(start>=info->start[i])
+               break;
+       }
+       /* set-up flash location */
+       /* now erase flash */
+       if(magic[0]!=IH_MAGIC) {
+               printf("Bad Magic number\n");
+               return -1;
+       }
+       printf("Start erasing at %lx (sector %d) (start %lx)\n",
+                               start,i,info->start[i]);
+       flash_erase (info, i, info->sector_count-1);
+       printf("flash erased, programming from 0x%lx 0x%lx Bytes\n",src,size);
+       switch (rc = flash_write ((uchar *)src, start, size)) 
+       {
+               case 0: printf ("programming done\n"); return 0;
+               case 1: printf ("Timeout writing to Flash\n"); return 1;
+               case 2: printf ("Flash not Erased\n"); return 1;
+               case 4: printf ("Can't write to protected Flash sectors\n"); return 1;
+               case 8: printf ("Outside available Flash\n"); return 1;
+               default:        printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc); return 1;
+       }
+  return 1;
+}
+
+
+int mip405_prg_image(unsigned long load_addr)
+{
+       unsigned long data,len,checksum;
+       image_header_t *hdr=&header;  
+       /* Copy header so we can blank CRC field for re-calculation */
+       memcpy (&header, (char *)load_addr, sizeof(image_header_t));
+
+       if (hdr->ih_magic  != IH_MAGIC) {
+               printf ("Bad Magic Number\n");
+               return 1;
+       }
+       if (hdr->ih_os  != IH_OS_PPCBOOT) {
+               printf ("No PPCBOOT Image\n");
+               return 1;
+       }
+       if (hdr->ih_type  != IH_TYPE_FIRMWARE) {
+               printf ("No Firmware Image\n");
+               return 1;
+       }
+       data = (ulong)&header;
+       len  = sizeof(image_header_t);
+       checksum = hdr->ih_hcrc;
+       hdr->ih_hcrc = 0;
+       if (crc32 (0, (char *)data, len) != checksum) {
+               printf ("Bad Header Checksum\n");
+               return 1;
+       }
+       data = load_addr + sizeof(image_header_t);
+       len  = hdr->ih_size;
+       printf ("   Verifying Checksum ... ");
+       if (crc32 (0, (char *)data, len) != hdr->ih_dcrc) {
+               printf ("Bad Data CRC\n");
+               return 1;
+       }
+       printf ("OK\n");
+       return(mip405_prg(data,len));
+} 
+
+
+/* ------------------------------------------------------------------------- */
+
+int do_mip405(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+
+       ulong size,src,device,load_addr;
+       int result;     
+       backup_t back;
+       src = MULTI_PURPOSE_SOCKET_ADDR;
+       size = IMAGE_SIZE;
+
+       if (strcmp(argv[1], "flash") == 0) 
+       {
+               if (strcmp(argv[2], "mem") == 0) {
+                       if(argc==4) {
+                               load_addr=simple_strtoul(argv[3], NULL, 16);
+                       }
+                       else {
+                               load_addr=CFG_LOAD_ADDR;
+                       }
+                       printf ("\nupdating bootloader image from memory at %lX\n",load_addr);
+                       result=mip405_prg_image(load_addr); 
+                       return result;
+               }
+               if (strcmp(argv[2], "mps") == 0) {
+                       printf ("\nupdating bootloader image from MSP\n");
+                       result=mip405_prg(src,size);
+                       return result;
+               }
+               
+       }
+       if (strcmp(argv[1], "mem") == 0) 
+       {
+               result=0;
+               if(argc==3)
+               {
+                       result = (int)simple_strtol(argv[2], NULL, 16);
+           }
+           src=(unsigned long)&result;
+           src-=CFG_MEMTEST_START;
+           src-=(100*1024); /* - 100k */
+           src&=0xfff00000;
+           size=0;
+           do {
+               size++;
+                       printf("Pass %ld\n",size);
+                       mem_test(CFG_MEMTEST_START,src,1);
+                       if(ctrlc())
+                               break;
+                       if(result>0)
+                               result--;
+                       
+               }while(result);
+               return 0;
+       }
+       if (strcmp(argv[1], "info") == 0) 
+       {
+               print_mip405_info();
+               return 0;
+       }
+       if (strcmp(argv[1], "led") == 0) 
+       {
+               device = (ulong)simple_strtoul(argv[2], NULL, 10);
+               user_led0((device==1));
+               return 0;
+       }
+       if (strcmp(argv[1], "getback") == 0) {
+               get_backup_values(&back);
+               back.signature[3]=0;
+               back.serial_name[16]=0;
+               back.eth_addr[20]=0;
+               printf("GetBackUp: signature: %s\n",back.signature);
+               printf("           serial#:   %s\n",back.serial_name);
+               printf("           ethaddr:   %s\n",back.eth_addr);
+               return 0;
+       } 
+       if (strcmp(argv[1], "setback") == 0) {
+               set_backup_values(1);
+               return 0;
+       } 
+       printf("Usage:\n%s\n", cmdtp->usage);
+    return 1;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/board/mpl/mip405/config.mk b/board/mpl/mip405/config.mk
new file mode 100644 (file)
index 0000000..0f8d153
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2000, 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
+#
+
+#
+# esd ADCIOP boards
+#
+
+#TEXT_BASE = 0xFFFE0000
+TEXT_BASE = 0xFFF80000
diff --git a/board/mpl/mip405/init.S b/board/mpl/mip405/init.S
new file mode 100644 (file)
index 0000000..fbefef0
--- /dev/null
@@ -0,0 +1,224 @@
+/*------------------------------------------------------------------------------+
+ *
+ *      This source code has been made available to you by IBM on an AS-IS
+ *      basis.  Anyone receiving this source is licensed under IBM
+ *      copyrights to use it in any way he or she deems fit, including
+ *      copying it, modifying it, compiling it, and redistributing it either
+ *      with or without modifications.  No license under IBM patents or
+ *      patent applications is to be implied by the copyright license.
+ *
+ *      Any user of this software should understand that IBM cannot provide
+ *      technical support for this software and will not be responsible for
+ *      any consequences resulting from the use of this software.
+ *
+ *      Any person who transfers this source code or any derivative work
+ *      must include the IBM copyright notice, this paragraph, and the
+ *      preceding two paragraphs in the transferred software.
+ *
+ *      COPYRIGHT   I B M   CORPORATION 1995
+ *      LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
+ *-------------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ * Function:     ext_bus_cntlr_init
+ * Description:  Initializes the External Bus Controller for the external 
+ *             peripherals. IMPORTANT: For pass1 this code must run from 
+ *             cache since you can not reliably change a peripheral banks
+ *             timing register (pbxap) while running code from that bank.
+ *             For ex., since we are running from ROM on bank 0, we can NOT 
+ *             execute the code that modifies bank 0 timings from ROM, so
+ *             we run it from cache.
+ *     Bank 0 - Flash or Multi Purpose Socket
+ *     Bank 1 - Multi Purpose Socket or Flash (set in C-Code)
+ *     Bank 2 - UART 1 (set in C-Code)
+ *     Bank 3 - UART 2 (set in C-Code)
+ *     Bank 4 - not used
+ *     Bank 5 - not used
+ *     Bank 6 - not used 
+ *     Bank 7 - PLD Register
+ *-----------------------------------------------------------------------------*/
+#include <ppc4xx.h>
+
+#define _LINUX_CONFIG_H 1      /* avoid reading Linux autoconf.h file  */
+
+#include "config_MIP405.h"
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include "mip405.h"
+
+
+       .globl  ext_bus_cntlr_init
+ext_bus_cntlr_init:
+  mflr    r4                      /* save link register */
+  bl      ..getAddr
+..getAddr:
+  mflr    r3                      /* get address of ..getAddr */
+  mtlr    r4                      /* restore link register */
+  addi    r4,0,14                 /* set ctr to 14; used to prefetch */
+  mtctr   r4                      /* 14 cache lines to fit this function */
+                                   /* in cache (gives us 8x14=112 instrctns) */
+..ebcloop:
+  icbt    r0,r3                   /* prefetch cache line for addr in r3 */
+  addi    r3,r3,32                                                             /* move to next cache line */
+  bdnz    ..ebcloop               /* continue for 14 cache lines */
+
+   /*-------------------------------------------------------------------
+    * Delay to ensure all accesses to ROM are complete before changing
+    * bank 0 timings.
+    *------------------------------------------------------------------- */
+       addis   r3,0,0x0
+  ori     r3,r3,0xA000
+  mtctr   r3
+..spinlp:
+  bdnz    ..spinlp                /* spin loop */
+
+       /*-----------------------------------------------------------------------
+        * decide boot up mode
+        *----------------------------------------------------------------------- */
+       addi            r4,0,pb0cr
+       mtdcr           ebccfga,r4
+       mfdcr           r4,ebccfgd
+
+       andi.           r0, r4, 0x2000                  /* mask out irrelevant bits */
+       beq                     0f                                              /* jump if 8 bit bus width */
+
+       /* setup 16 bit things (Flash Boot)
+   *-----------------------------------------------------------------------
+   * Memory Bank 0 (16 Bit Flash) initialization
+   *---------------------------------------------------------------------- */
+
+       addi    r4,0,pb0ap
+       mtdcr   ebccfga,r4
+//     addis   r4,0,0xFF8F 
+//     ori     r4,r4,0xFE80
+//     addis   r4,0,0x9B01 
+//     ori     r4,r4,0x5480
+       addis   r4,0,(FLASH_AP_B)@h 
+       ori     r4,r4,(FLASH_AP_B)@l
+       mtdcr   ebccfgd,r4
+
+       addi    r4,0,pb0cr
+       mtdcr   ebccfga,r4
+       /* BS=0x010(4MB),BU=0x3(R/W), */
+//     addis   r4,0,((FLASH_BASE0_PRELIM & 0xFFF00000) | 0x00050000)@h
+//     ori     r4,r4,0xA000          /* BW=0x01(16 bits) */
+       addis   r4,0,(FLASH_CR_B)@h
+       ori     r4,r4,(FLASH_CR_B)@l
+       mtdcr   ebccfgd,r4
+       b                               1f
+
+0:
+
+       /* 8Bit boot mode: */
+       /*-----------------------------------------------------------------------
+       * Memory Bank 0 Multi Purpose Socket initialization
+       *----------------------------------------------------------------------- */
+       /* 0x7F8FFE80 slowest boot */
+       addi    r4,0,pb0ap
+       mtdcr   ebccfga,r4
+#if 0
+       addis   r4,0,0x9B01 
+       ori     r4,r4,0x5480
+#else
+       addis   r4,0,(MPS_AP_B)@h 
+       ori     r4,r4,(MPS_AP_B)@l
+#endif
+       mtdcr   ebccfgd,r4
+
+       addi    r4,0,pb0cr
+       mtdcr   ebccfga,r4
+       /* BS=0x010(4MB),BU=0x3(R/W), */
+//     addis   r4,0,((FLASH_BASE0_PRELIM & 0xFFF00000) | 0x00050000)@h
+//     ori     r4,r4,0x8000          /* BW=0x0( 8 bits) */
+
+       addis   r4,0,(MPS_CR_B)@h 
+       ori     r4,r4,(MPS_CR_B)@l
+
+       mtdcr   ebccfgd,r4
+
+
+1:
+  /*-----------------------------------------------------------------------
+   * Memory Bank 2-3-4-5-6 (not used) initialization
+   *-----------------------------------------------------------------------*/
+  addi    r4,0,pb1cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb2cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+  
+  addi    r4,0,pb3cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb4cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb5cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+
+       addi    r4,0,pb6cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+
+       addi    r4,0,pb7cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+       nop                             /* pass2 DCR errata #8 */
+  blr
+
+/*-----------------------------------------------------------------------------
+ * Function:     sdram_init
+ * Description:  Configures the internal SRAM memory. and setup the 
+ *               Stackpointer in it.
+ *----------------------------------------------------------------------------- */
+        .globl  sdram_init
+
+sdram_init:
+
+       /*-------------------------------------------------------------------
+        * init OnChip Memory for a temporary stack
+        *------------------------------------------------------------------- */
+
+       lis     r0, 0x7FFF
+       ori     r0, r0, 0xFFFF
+       mfdcr   r3, ocmiscntl           /* get instr-side IRAM config */
+       mfdcr   r4, ocmdscntl   /* get data-side IRAM config */
+       and     r3, r3, r0      /* disable data-side IRAM */
+       and     r4, r4, r0      /* disable data-side IRAM */
+       mtdcr   ocmiscntl, r3   /* set instr-side IRAM config */
+       mtdcr   ocmdscntl, r4   /* set data-side IRAM config */
+       isync
+       lis     r0, OCM_DATA_ADDR@h/* IRAM is mapped here */
+       mtdcr   ocmdsarc, r0    /* set data-side IRAM address */
+       oris    r4, r4, 0xC000  /* enable data-side IRAM */
+       mtdcr   ocmdscntl, r4   /* set data-side IRAM config */
+       isync
+
+       mfdcr   r3, ocmdsarc    /* set temp stackpointer (needed by CONS_Init) */
+       andis.  r3, r3, 0xFC00
+       addi    r1, r3, 0x1000-16
+
+  blr
+
diff --git a/board/mpl/mip405/mip405.c b/board/mpl/mip405/mip405.c
new file mode 100644 (file)
index 0000000..0e4dcb2
--- /dev/null
@@ -0,0 +1,988 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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
+ *
+ *
+ * TODO: clean-up
+ */
+
+/*
+ * How do I program the SDRAM Timing Register (SDRAM0_TR) for a specific SDRAM or DIMM?
+ *
+ * As an example, consider a case where PC133 memory with CAS Latency equal to 2 is being
+ * used with a 200MHz 405GP. For a typical 128Mb, PC133 SDRAM, the relevant minimum
+ * parameters from the datasheet are:
+ * Tclk = 7.5ns (CL = 2)
+ * Trp = 15ns
+ * Trc = 60ns
+ * Trcd = 15ns
+ * Trfc = 66ns
+ *
+ * If we are operating the 405GP with the MemClk output frequency set to 100 MHZ, the clock
+ * period is 10ns and the parameters needed for the Timing Register are:
+ * CASL = CL = 2 clock cycles
+ * PTA = Trp = 15ns / 10ns = 2 clock cycles
+ * CTP = Trc - Trcd - Trp = (60ns - 15ns - 15ns) / 10ns= 3 clock cycles
+ * LDF = 2 clock cycles (but can be extended to meet board-level timing)
+ * RFTA = Trfc = 66ns / 10ns= 7 clock cycles
+ * RCD = Trcd = 15ns / 10ns= 2 clock cycles
+ *
+ * The actual bit settings in the register would be:
+ *
+ * CASL = 0b01
+ * PTA = 0b01
+ * CTP = 0b10
+ * LDF = 0b01
+ * RFTA = 0b011
+ * RCD = 0b01
+ *
+ * If Trfc is not specified in the datasheet for PC100 or PC133 memory, set RFTA = Trc
+ * instead. Figure 24 in the PC SDRAM Specification Rev. 1.7 shows refresh to active delay
+ * defined as Trc rather than Trfc.
+ * When using DIMM modules, most but not all of the required timing parameters can be read
+ * from the Serial Presence Detect (SPD) EEPROM on the module. Specifically, Trc and Trfc
+ * are not available from the EEPROM
+ */
+
+#include <ppcboot.h>
+#include "mip405.h"
+#include <asm/processor.h>
+#include <405gp_i2c.h>
+#include <miiphy.h>
+#include <devices.h>
+
+extern block_dev_desc_t * scsi_get_dev(int dev);
+extern block_dev_desc_t * ide_get_dev(int dev);
+
+#undef SDRAM_DEBUG
+
+#define FALSE           0
+#define TRUE            1
+
+/* stdlib.h causes some compatibility problems; should fixe these! -- wd */
+#ifndef __ldiv_t_defined
+typedef struct {
+       long int quot;          /* Quotient     */
+       long int rem;           /* Remainder    */
+} ldiv_t;
+extern ldiv_t ldiv (long int __numer, long int __denom);
+# define __ldiv_t_defined      1
+#endif
+
+
+#define PLD_PART_REG           PER_PLD_ADDR + 0
+#define PLD_VERS_REG           PER_PLD_ADDR + 1
+#define PLD_BOARD_CFG_REG      PER_PLD_ADDR + 2
+#define PLD_IRQ_REG            PER_PLD_ADDR + 3
+#define PLD_COM_MODE_REG       PER_PLD_ADDR + 4
+#define PLD_EXT_CONF_REG       PER_PLD_ADDR + 5
+
+#define MEGA_BYTE (1024*1024)
+
+typedef struct {
+       unsigned char boardtype; /* Board revision and Population Options */
+       unsigned char cal;              /* cas Latency (will be programmend as cal-1) */
+       unsigned char trp;              /* datain27 in clocks */
+       unsigned char trcd;             /* datain29 in clocks */
+       unsigned char tras;             /* datain30 in clocks */
+       unsigned char tctp;             /* tras - trcd in clocks */
+       unsigned char am;               /* Address Mod (will be programmed as am-1) */
+       unsigned char sz;               /* log binary => Size = (4MByte<<sz) 5 = 128, 4 = 64, 3 = 32, 2 = 16, 1=8 */
+       unsigned char ecc;              /* if true, ecc is enabled */
+} sdram_t;
+
+const sdram_t sdram_table[] = {
+       { 0x0f, /* Rev A, 128MByte -1 Board */
+               3,      /* Case Latenty = 3 */
+               3,      /* trp 20ns / 7.5 ns datain[27] */
+               3,      /* trcd 20ns /7.5 ns (datain[29]) */
+               6,  /* tras 44ns /7.5 ns  (datain[30]) */
+               4,      /* tcpt 44 - 20ns = 24ns */
+               3,      /* Address Mode = 3 */
+               5,      /* size value */
+               1},     /* ECC enabled */
+       { 0x07, /* Rev A, 64MByte -2 Board */
+               3,      /* Case Latenty = 3 */
+               3,      /* trp 20ns / 7.5 ns datain[27] */
+               3,      /* trcd 20ns /7.5 ns (datain[29]) */
+               6,  /* tras 44ns /7.5 ns  (datain[30]) */
+               4,      /* tcpt 44 - 20ns = 24ns */
+               2,      /* Address Mode = 2 */
+               4,      /* size value */
+               1},     /* ECC enabled */
+       { 0xff, /* terminator */
+         0xff,
+         0xff,
+         0xff,
+         0xff,
+         0xff,
+         0xff,
+         0xff }
+};
+
+void SDRAM_err(const char *s)
+{
+#ifndef SDRAM_DEBUG
+  serial_init(get_gclk_freq(),9600);
+#endif
+  serial_puts("\n");
+  serial_puts(s);
+  serial_puts("\n enable SDRAM_DEBUG for more info\n");
+       for (;;);
+}
+
+
+unsigned char get_board_revcfg(void)
+{
+       out8(PER_BOARD_ADDR,0);
+       return(in8(PER_BOARD_ADDR));
+}
+
+
+#ifdef SDRAM_DEBUG
+
+void write_hex(unsigned char i)
+{
+       char cc;
+       cc=i>>4;
+       cc&=0xf;
+       if(cc>9)
+               serial_putc(cc+55);
+       else
+               serial_putc(cc+48);
+       cc=i&0xf;
+       if(cc>9)
+               serial_putc(cc+55);
+       else
+               serial_putc(cc+48);
+}
+
+void write_4hex(unsigned long val)
+{
+  write_hex((unsigned char)(val>>24));
+  write_hex((unsigned char)(val>>16));
+  write_hex((unsigned char)(val>>8));
+  write_hex((unsigned char)val);
+}
+
+#endif
+
+
+int init_sdram (void)
+{
+       unsigned long tmp, baseaddr;
+       unsigned short i;
+       unsigned char trp_clocks, trcd_clocks, tras_clocks, trc_clocks,tctp_clocks;
+       unsigned char cal_val;
+       unsigned char bc;
+       unsigned long pbcr,sdram_tim,sdram_bank;
+       unsigned long *p;
+
+
+
+       serial_init(get_gclk_freq(),9600);
+       serial_puts("\nInitializing SDRAM, Please stand by");
+       mtdcr(ebccfga, pb0cr); /* get cs0 config reg */
+       pbcr = mfdcr(ebccfgd);
+       if((pbcr&0x00002000)==0) {
+               /* MPS Boot, set up the flash */
+               mtdcr(ebccfga, pb1ap);
+               mtdcr(ebccfgd, FLASH_AP);
+               mtdcr(ebccfga, pb1cr);
+               mtdcr(ebccfgd, FLASH_CR);
+       }
+       else {
+               /* Flash boot, set up the MPS */
+               mtdcr(ebccfga, pb1ap);
+               mtdcr(ebccfgd, MPS_AP);
+               mtdcr(ebccfga, pb1cr);
+               mtdcr(ebccfgd, MPS_CR);
+       }
+       /* set up UART0 (CS2) and UART1 (CS3) */
+       mtdcr(ebccfga, pb2ap);
+       mtdcr(ebccfgd, UART0_AP);
+       mtdcr(ebccfga, pb2cr);
+       mtdcr(ebccfgd, UART0_CR);
+       mtdcr(ebccfga, pb3ap);
+       mtdcr(ebccfgd, UART1_AP);
+       mtdcr(ebccfga, pb3cr);
+       mtdcr(ebccfgd, UART1_CR);
+
+       /* set up the pld */
+       mtdcr(ebccfga, pb7ap);
+       mtdcr(ebccfgd, PLD_AP);
+       mtdcr(ebccfga, pb7cr);
+       mtdcr(ebccfgd, PLD_CR);
+       /* set up the board rev reg */
+       mtdcr(ebccfga, pb5ap);
+       mtdcr(ebccfgd, BOARD_AP);
+       mtdcr(ebccfga, pb5cr);
+       mtdcr(ebccfgd, BOARD_CR);
+
+
+#ifdef SDRAM_DEBUG
+       out8(PER_BOARD_ADDR,0);
+       bc=in8(PER_BOARD_ADDR);
+       serial_puts("\nBoard Rev: ");
+       write_hex(bc);
+       serial_puts(" (PLD=");
+       bc=in8(PLD_BOARD_CFG_REG);
+       write_hex(bc);
+       serial_puts(")\n");
+#endif
+       bc=get_board_revcfg();
+#ifdef SDRAM_DEBUG
+       serial_puts("\nstart SDRAM Setup\n");
+       serial_puts("\nBoard Rev: ");
+       write_hex(bc);
+       serial_puts("\n");
+#endif
+       i=0;
+       baseaddr=CFG_SDRAM_BASE;
+       while(sdram_table[i].sz!=0xff) {
+               if(sdram_table[i].boardtype==bc)
+                       break;
+               i++;
+       }
+       if(sdram_table[i].boardtype!=bc)
+               SDRAM_err("No SDRAM table found for this board!!!\n");
+#ifdef SDRAM_DEBUG
+       serial_puts(" found table ");
+       write_hex(i);
+       serial_puts(" \n");
+#endif
+       cal_val     = sdram_table[i].cal-1; /* Cas Latency */
+       trp_clocks  = sdram_table[i].trp;       /* 20ns / 7.5 ns datain[27] */
+       trcd_clocks = sdram_table[i].trcd;      /* 20ns /7.5 ns (datain[29]) */
+       tras_clocks = sdram_table[i].tras; /* 44ns /7.5 ns  (datain[30]) */
+       /* ctp = ((trp + tras) - trp - trcd) => tras - trcd */
+       tctp_clocks = sdram_table[i].tctp; /* 44 - 20ns = 24ns */
+       /* trc_clocks is sum of trp_clocks + tras_clocks */
+       trc_clocks = trp_clocks + tras_clocks;
+       /* get SDRAM timing register */
+       mtdcr(memcfga,mem_sdtr1);
+       sdram_tim = mfdcr(memcfgd) & ~0x018FC01F;
+       /* insert CASL value */
+       sdram_tim |= ((unsigned long)(cal_val)) << 23;
+       /* insert PTA value */
+       sdram_tim |= ((unsigned long)(trp_clocks - 1)) << 18;
+       /* insert CTP value */
+       sdram_tim |= ((unsigned long)(trc_clocks - trp_clocks - trcd_clocks)) << 16;
+       /* insert LDF (always 01) */
+       sdram_tim |= ((unsigned long)0x01) << 14;
+       /* insert RFTA value */
+       sdram_tim |= ((unsigned long)(trc_clocks - 4)) << 2;
+       /* insert RCD value */
+       sdram_tim |= ((unsigned long)(trcd_clocks - 1)) << 0;
+
+       tmp = ((unsigned long)(sdram_table[i].am-1) << 13); /* AM = 3 */
+       /* insert SZ value; */
+       tmp |= ((unsigned long)sdram_table[i].sz << 17);
+       /* get SDRAM bank 0 register */
+       mtdcr(memcfga,mem_mb0cf);
+       sdram_bank = mfdcr(memcfgd) & ~0xFFCEE001;
+       sdram_bank |= (baseaddr | tmp | 0x01);
+
+#ifdef SDRAM_DEBUG
+       serial_puts("sdtr: ");
+       write_4hex(sdram_tim);
+       serial_puts("\n");
+#endif
+
+       /* write SDRAM timing register */
+       mtdcr(memcfga,mem_sdtr1);
+       mtdcr(memcfgd,sdram_tim);
+
+#ifdef SDRAM_DEBUG
+       serial_puts("mb0cf: ");
+       write_4hex(sdram_bank);
+       serial_puts("\n");
+#endif
+
+       /* write SDRAM bank 0 register */
+       mtdcr(memcfga,mem_mb0cf);
+       mtdcr(memcfgd,sdram_bank);
+
+       if(get_bus_freq(tmp)>110000000) { /* > 110MHz */
+               /* get SDRAM refresh interval register */
+               mtdcr(memcfga,mem_rtr);
+               tmp = mfdcr(memcfgd) & ~0x3FF80000;
+       tmp |= 0x07F00000;
+       }
+       else {
+               /* get SDRAM refresh interval register */
+               mtdcr(memcfga,mem_rtr);
+               tmp = mfdcr(memcfgd) & ~0x3FF80000;
+       tmp |= 0x05F00000;
+       }
+       /* write SDRAM refresh interval register */
+       mtdcr(memcfga,mem_rtr);
+       mtdcr(memcfgd,tmp);
+       /* enable ECC if used */
+#if 1
+       if(sdram_table[i].ecc) {
+               /* disable checking for all banks */
+#ifdef SDRAM_DEBUG
+               serial_puts("disable ECC.. ");
+#endif
+               mtdcr(memcfga,mem_ecccf);
+               tmp=mfdcr(memcfgd);
+               tmp&=0xff0fffff; /* disable all banks */
+               mtdcr(memcfga,mem_ecccf);
+               /* set up SDRAM Controller with ECC enabled */
+#ifdef SDRAM_DEBUG
+               serial_puts("setup SDRAM Controller.. ");
+#endif
+               mtdcr(memcfgd,tmp);
+               mtdcr(memcfga,mem_mcopt1);
+               tmp = (mfdcr(memcfgd) &  ~0xFFE00000) | 0x90800000;
+               mtdcr(memcfga,mem_mcopt1);
+               mtdcr(memcfgd,tmp);
+               udelay(600);
+#ifdef SDRAM_DEBUG
+               serial_puts("fill the memory..\n");
+#endif
+               serial_puts(".");
+               /* now, fill all the memory */
+               tmp=((4*MEGA_BYTE)<<sdram_table[i].sz);
+               p=(unsigned long)0;
+               while((unsigned long)p<tmp) {
+                       *p++=0L;
+                       if(!((unsigned long)p%0x00800000)) /* every 8MByte */
+                               serial_puts(".");
+
+
+               }
+               /* enable bank 0 */
+               serial_puts(".");
+#ifdef SDRAM_DEBUG
+               serial_puts("enable ECC\n");
+#endif
+               udelay(400);
+               mtdcr(memcfga,mem_ecccf);
+               tmp=mfdcr(memcfgd);
+               tmp|=0x00800000; /* enable bank 0 */
+               mtdcr(memcfgd,tmp);
+               udelay(400);
+       }
+       else
+#endif
+       {
+               /* enable SDRAM controller with no ECC, 32-bit SDRAM width, 16 byte burst */
+               mtdcr(memcfga,mem_mcopt1);
+               tmp = (mfdcr(memcfgd) &  ~0xFFE00000) | 0x80C00000;
+               mtdcr(memcfga,mem_mcopt1);
+               mtdcr(memcfgd,tmp);
+               udelay(400);
+       }
+       serial_puts("\n");
+       return (0);
+}
+
+int board_pre_init (void)
+{
+       init_sdram();
+
+   /*-------------------------------------------------------------------------+
+   | Interrupt controller setup for the PIP405 board.
+   | Note: IRQ 0-15  405GP internally generated; active high; level sensitive
+   |       IRQ 16    405GP internally generated; active low; level sensitive
+   |       IRQ 17-24 RESERVED
+   |       IRQ 25 (EXT IRQ 0) SouthBridge; active low; level sensitive
+   |       IRQ 26 (EXT IRQ 1) NMI: active low; level sensitive
+   |       IRQ 27 (EXT IRQ 2) SMI: active Low; level sensitive
+   |       IRQ 28 (EXT IRQ 3) PCI SLOT 3; active low; level sensitive
+   |       IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive
+   |       IRQ 30 (EXT IRQ 5) PCI SLOT 1; active low; level sensitive
+   |       IRQ 31 (EXT IRQ 6) PCI SLOT 0; active low; level sensitive
+   | Note for MIP405 board:
+   |       An interrupt taken for the SouthBridge (IRQ 25) indicates that
+   |       the Interrupt Controller in the South Bridge has caused the
+   |       interrupt. The IC must be read to determine which device
+   |       caused the interrupt.
+   |
+   +-------------------------------------------------------------------------*/
+       mtdcr(uicsr, 0xFFFFFFFF);        /* clear all ints */
+       mtdcr(uicer, 0x00000000);        /* disable all ints */
+       mtdcr(uiccr, 0x00000000);        /* set all to be non-critical (for now)*/
+       mtdcr(uicpr, 0xFFFFFF80);        /* set int polarities */
+       mtdcr(uictr, 0x10000000);        /* set int trigger levels */
+       mtdcr(uicvcr, 0x00000001);       /* set vect base=0,INT0 highest priority*/
+       mtdcr(uicsr, 0xFFFFFFFF);        /* clear all ints */
+       return 0;
+}
+
+
+/*
+ * Get some PLD Registers
+ */
+
+unsigned short get_pld_parvers(void)
+{
+       unsigned short result;
+       unsigned char rc;
+       rc=in8(PLD_PART_REG);
+       result=(unsigned short)rc<<8;
+       rc=in8(PLD_VERS_REG);
+       result|=rc;
+       return result;
+}
+
+
+
+void user_led0(unsigned char on)
+{
+       if(on)
+               out8(PLD_COM_MODE_REG,(in8(PLD_COM_MODE_REG)|0x4));
+       else
+               out8(PLD_COM_MODE_REG,(in8(PLD_COM_MODE_REG)&0xfb));
+}
+
+
+void ide_set_reset(int idereset)
+{
+       /* if reset = 1 IDE reset will be asserted */
+       if(idereset)
+               out8(PLD_COM_MODE_REG,(in8(PLD_COM_MODE_REG)|0x1));
+       else
+               out8(PLD_COM_MODE_REG,(in8(PLD_COM_MODE_REG)&0xfe));
+}
+
+#define I2C_BACKUP_ADDR 0x7C00 /* 0x200 bytes for backup */
+
+void get_backup_values(backup_t *buf)
+{
+       eeprom_read (CFG_DEF_EEPROM_ADDR,
+                    I2C_BACKUP_ADDR,
+                    (void *)buf,
+                    sizeof(backup_t));
+}
+
+void set_backup_values(int overwrite)
+{
+       backup_t back;
+       int i;
+
+       get_backup_values(&back);
+       if(!overwrite) {
+               if(strncmp(back.signature,"MPL\0",4)==0) {
+                       printf("Not possible to write Backup\n");
+                       return;
+               }
+       }
+       memcpy(back.signature,"MPL\0",4);
+       i=getenv_r("serial#",back.serial_name,16);
+       if(i==0) {
+               printf("Not possible to write Backup\n");
+               return;
+       }
+       back.serial_name[16]=0;
+       i=getenv_r("ethaddr",back.eth_addr,20);
+       if(i==0) {
+               printf("Not possible to write Backup\n");
+               return;
+       }
+       back.eth_addr[20]=0;
+       eeprom_write (CFG_DEF_EEPROM_ADDR,
+                     CFG_ENV_OFFSET+I2C_BACKUP_ADDR,
+                     (void *)&back,
+                     sizeof(backup_t));
+}
+
+
+
+
+/* ------------------------------------------------------------------------- */
+
+/*
+ * Check Board Identity:
+ */
+
+int checkboard (void)
+{
+    unsigned char s[50];
+       unsigned char bc,var,rc;
+       int i;
+       backup_t *b=(backup_t *)s;
+
+       bc=get_board_revcfg();
+       var=~bc;
+       var&=0xf;
+       rc=0;
+       for(i=0;i<4;i++) {
+               rc<<=1;
+               rc+=(var & 0x1);
+               var>>=1;
+       }
+       rc++;
+       i=getenv_r("serial#",s,32);
+    if ((i==0) || strncmp(s, "MIP405", 6)) {
+       get_backup_values(b);
+               if(strncmp(b->signature,"MPL\0",4)!=0) {
+                       printf("### No HW ID - assuming MIP405");
+                       printf("-%d Rev %c",rc, 'A'+((bc>>4)&0xf));
+               }
+               else {
+                       b->serial_name[6]=0;
+               printf("%s-%d Rev %c SN: %s",b->serial_name,rc, 'A'+((bc>>4)&0xf),&b->serial_name[7]);
+               }
+    }
+    else {
+       s[6]=0;
+       printf("%s-%d Rev %c SN: %s",s,rc, 'A'+((bc>>4)&0xf),&s[7]);
+       }
+       bc=in8(PLD_EXT_CONF_REG);
+       printf(" Boot Config: 0x%x\n",bc);
+    return (0);
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+/*
+  initdram(int board_type) reads EEPROM via I2c. EEPROM contains all of
+  the necessary info for SDRAM controller configuration
+*/
+/* ------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+int testdram (unsigned long ramsize);
+
+long int initdram (int board_type)
+{
+
+       unsigned long bank_reg[4],tmp,bank_size;
+       int i,ds;
+       unsigned long TotalSize;
+       ds=0;
+       /* since the DRAM controller is allready set up, calculate the size with the
+         bank registers         */
+       mtdcr(memcfga,mem_mb0cf);
+       bank_reg[0] = mfdcr(memcfgd);
+       mtdcr(memcfga,mem_mb1cf);
+       bank_reg[1] = mfdcr(memcfgd);
+       mtdcr(memcfga,mem_mb2cf);
+       bank_reg[2] = mfdcr(memcfgd);
+       mtdcr(memcfga,mem_mb3cf);
+       bank_reg[3] = mfdcr(memcfgd);
+       TotalSize=0;
+       for(i=0;i<4;i++)
+       {
+               if((bank_reg[i]&0x1)==0x1)
+               {
+                       tmp=(bank_reg[i]>>17)&0x7;
+                       bank_size=4<<tmp;
+                       TotalSize+=bank_size;
+               }
+               else
+                       ds=1;
+       }
+       mtdcr(memcfga,mem_ecccf);
+       tmp= mfdcr(memcfgd);
+
+       if(!tmp)
+               printf("No ");
+       printf("ECC ");
+
+       testdram(TotalSize*MEGA_BYTE);
+       return (TotalSize*MEGA_BYTE);
+}
+
+/* ------------------------------------------------------------------------- */
+
+extern int mem_test(unsigned long start, unsigned long ramsize, int quiet);
+
+int testdram (unsigned long ramsize)
+{
+#ifdef SDRAM_DEBUG
+       mem_test(0L, ramsize, 1);
+#endif
+               /* not yet implemented */
+               return(1);
+}
+
+/* ------------------------------------------------------------------------- */
+
+       /* switches the cs0 and the cs1 to the locations.
+          When boot is TRUE, the the mapping is switched
+          to the boot configuration, If it is FALSE, the
+          flash will be switched in the boot area */
+
+#undef SW_CS_DBG
+#ifdef SW_CS_DBG
+#define        SW_CS_PRINTF(fmt,args...)       printf (fmt ,##args)
+#else
+#define SW_CS_PRINTF(fmt,args...)
+#endif
+
+
+int switch_cs(unsigned char boot)
+{
+       unsigned long pbcr;
+       mtdcr(ebccfga, pb0cr); /* get cs0 config reg */
+       pbcr = mfdcr(ebccfgd);
+       if((pbcr&0x00002000)==0) {
+               /* we need only to switch if boot from MPS */
+               /*printf(" MPS boot mode detected. ");*/
+               /* printf("cs0 cfg: %lx\n",pbcr); */
+               if(boot==TRUE) {
+                       /* switch to boot configuration */
+                       /* this is a 8bit boot, switch cs0 to flash location */
+                       SW_CS_PRINTF("switch to boot mode (MPS on High address\n");
+                       pbcr&=0x000FFFFF; /*mask base address of the cs0 */
+                       pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000);
+                       mtdcr(ebccfga, pb0cr);
+                       mtdcr(ebccfgd, pbcr);
+                       SW_CS_PRINTF("  new cs0 cfg: %lx\n",pbcr);
+                       mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */
+                       pbcr = mfdcr(ebccfgd);
+                       SW_CS_PRINTF(" old cs1 cfg: %lx\n",pbcr);
+                       pbcr&=0x000FFFFF; /*mask base address of the cs1 */
+                       pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000);
+                       mtdcr(ebccfga, pb1cr);
+                       mtdcr(ebccfgd, pbcr);
+                       SW_CS_PRINTF("  new cs1 cfg: %lx, MPS is on High Address\n",pbcr);
+               }
+               else
+               {
+                       /* map flash to boot area, */
+                       SW_CS_PRINTF("map Flash to boot area\n");
+                       pbcr&=0x000FFFFF; /*mask base address of the cs0 */
+                       pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000);
+                       mtdcr(ebccfga, pb0cr);
+                       mtdcr(ebccfgd, pbcr);
+                       SW_CS_PRINTF("  new cs0 cfg: %lx\n",pbcr);
+                       mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */
+                       pbcr = mfdcr(ebccfgd);
+                       SW_CS_PRINTF("  cs1 cfg: %lx\n",pbcr);
+                       pbcr&=0x000FFFFF; /*mask base address of the cs1 */
+                       pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000);
+                       mtdcr(ebccfga, pb1cr);
+                       mtdcr(ebccfgd, pbcr);
+                       SW_CS_PRINTF("  new cs1 cfg: %lx Flash is on High Address\n",pbcr);
+               }
+               return TRUE;
+       }
+       else {
+               SW_CS_PRINTF("Normal boot, no switching necessary\n");
+               return FALSE;
+       }
+}
+
+void misc_init_r(bd_t *bd)
+{
+#if 0
+       unsigned char bc;
+       char buf[128];
+       unsigned char *s;
+       bc=in8(PLD_EXT_CONF_REG);
+       bc>>=4;
+       bc &= 0x0f;
+       sprintf(buf,"bootcmd%d",bc);
+       s = getenv(buf);
+       if(s) {
+               sprintf(buf,"%s",s);
+               setenv("bootcmd",buf);
+       }
+       sprintf(buf,"bootargs%d",bc);
+       s = getenv(buf);
+       if(s) {
+               sprintf(buf,"%s",s);
+               setenv("bootargs",buf);
+       }
+#endif
+       /* it is time to swap the flash permanently to the flash area */
+       switch_cs(FALSE);
+}
+
+
+
+void set_init_backup(void)
+{
+    unsigned char *s;
+       char buf[32];
+       backup_t back;
+
+       s=getenv("serial#");
+       if(!s) {
+               get_backup_values(&back);
+               if(strncmp(back.signature,"MPL\0",4)==0) {
+                       sprintf(buf,"%s",back.serial_name);
+                       setenv("serial#",buf);
+                       sprintf(buf,"%s",back.eth_addr);
+                       setenv("ethaddr",buf);
+                       printf("INFO:  serial# and ethaddr recovered, use saveenv\n");
+               }
+       }
+       else {
+               /* check if back up is set */
+               get_backup_values(&back);
+               if(strncmp(back.signature,"MPL\0",4)!=0) {
+                       set_backup_values(0);
+               }
+       }
+}
+
+extern device_t *stdio_devices[];
+extern char *stdio_names[];
+
+void show_stdio_dev(void)
+{
+       /* Print informations */
+       printf ("In:    ");
+       if (stdio_devices[stdin] == NULL) {
+               printf ("No input devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stdin]->name);
+       }
+
+       printf ("Out:   ");
+       if (stdio_devices[stdout] == NULL) {
+               printf ("No output devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stdout]->name);
+       }
+
+       printf ("Err:   ");
+       if (stdio_devices[stderr] == NULL) {
+               printf ("No error devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stderr]->name);
+       }
+}
+
+
+
+int last_stage_init(void)
+{
+       set_init_backup();
+    if(miiphy_write(0x1, 0x14, 0x2402) != 0) {
+      printf("Error writing to the PHY\n");
+       }
+       show_stdio_dev();
+       return 0;
+}
+
+/***************************************************************************
+ * some helping routines
+ */
+
+int overwrite_console(void)
+{
+       return(in8(PLD_EXT_CONF_REG) & 0x1); /* return TRUE if console should be overwritten */
+}
+
+
+/************************************************************************
+* Print MIP405 Info
+************************************************************************/
+void print_mip405_info(void)
+{
+       unsigned char part,vers,cfg,irq_reg,com_mode,ext;
+
+       part=in8(PLD_PART_REG);
+       vers=in8(PLD_VERS_REG);
+       cfg=in8(PLD_BOARD_CFG_REG);
+       irq_reg=in8(PLD_IRQ_REG);
+       com_mode=in8(PLD_COM_MODE_REG);
+       ext=in8(PLD_EXT_CONF_REG);
+
+       printf("PLD Part %d version %d\n",part,vers);
+       printf("Board Revision %c\n",((cfg>>4)&0xf)+'A');
+       printf("Population Options %d %d %d %d\n",(cfg)&0x1,(cfg>>1)&0x1,(cfg>>2)&0x1,(cfg>>3)&0x1);
+       printf("User LED %s\n",(com_mode & 0x4) ? "on" : "off");
+       printf("UART Clocks %d\n",(com_mode>>4)&0x3);
+       printf("User Config Switch %d %d %d %d %d %d %d %d\n",
+               (ext)&0x1,(ext>>1)&0x1,(ext>>2)&0x1,(ext>>3)&0x1,(ext>>4)&0x1,(ext>>5)&0x1,(ext>>6)&0x1,(ext>>7)&0x1);
+       printf("SER1 uses handshakes %s\n",(ext & 0x80) ? "DTR/DSR" : "RTS/CTS");
+       printf("IDE Reset %s\n",(ext & 0x01) ? "asserted" : "not asserted");
+       printf("IRQs:\n");
+       printf("  PIIX INTR: %s\n",(irq_reg & 0x80) ? "inactive" : "active");
+       printf("  UART0 IRQ: %s\n",(irq_reg & 0x40) ? "inactive" : "active");
+       printf("  UART1 IRQ: %s\n",(irq_reg & 0x20) ? "inactive" : "active");
+       printf("  PIIX SMI:  %s\n",(irq_reg & 0x10) ? "inactive" : "active");
+       printf("  PIIX INIT: %s\n",(irq_reg & 0x8) ? "inactive" : "active");
+       printf("  PIIX NMI:  %s\n",(irq_reg & 0x4) ? "inactive" : "active");
+}
+
+
+/******************************************************
+ * Routines to display the Board information
+ * to the screen (since the VGA will be initialized as last,
+ * we must resend the infos)
+ */
+#ifdef CONFIG_VIDEO
+void video_put_dev_string(block_dev_desc_t *dev_desc)
+{
+       char buf[80];
+       ldiv_t mb;
+       unsigned long lba512; /* number of blocks if 512bytes block size */
+
+       if(dev_desc->type!=DEV_TYPE_UNKNOWN) {
+               if(dev_desc->if_type==IF_TYPE_SCSI)
+                       sprintf(buf,"SCSI %d:  (%d:%d) ",dev_desc->dev,dev_desc->target,dev_desc->lun);
+               else
+                       sprintf(buf,"IDE %d:   ",dev_desc->dev);
+               video_puts(buf);
+               switch(dev_desc->type & 0x1F) {
+                       case DEV_TYPE_HARDDISK: video_puts("Hard Disk"); break;
+                       case DEV_TYPE_CDROM:            video_puts("CD ROM"); break;
+                       case DEV_TYPE_OPDISK:   video_puts("Optical Device"); break;
+                       case DEV_TYPE_TAPE:             video_puts("Tape"); break;
+                       default:                                                        video_puts("unknown"); break;
+               }
+               video_puts(" ");
+               video_puts(dev_desc->vendor);
+               video_puts(" ");
+               if(dev_desc->if_type!=IF_TYPE_IDE)
+                       video_puts(dev_desc->product);
+
+               if((dev_desc->lba * dev_desc->blksz)>0L) {
+                       lba512=dev_desc->lba * (dev_desc->blksz/512);
+                       mb = ldiv(lba512, 2048); /* (1024 *1024 / 512 MB */
+                       /* round to 1 digit */
+                       mb.rem *= 10 * 512;
+                       mb.rem += 512 * 1024;
+                       mb.rem /= 1024 * 1024;
+                       sprintf (buf," %ld x %ld Bytes = %ld.%ld MB\n",dev_desc->lba,dev_desc->blksz,mb.quot, mb.rem);
+               }
+               else {
+                       sprintf (buf," Capacity: not available\n");
+               }
+               video_puts(buf);
+       }
+}
+
+void video_write_board_info(void)
+{
+       extern char version_string[];
+  unsigned long pvr = get_pvr();
+  char buf[32],tmpbuf[80];
+  PPC405_SYS_INFO sys_info;
+  init_data_t *idata = (init_data_t *)(CFG_INIT_RAM_ADDR + CFG_INIT_DATA_OFFSET);
+  unsigned char *s = getenv("serial#");
+  unsigned char *e;
+  unsigned char bc;
+  block_dev_desc_t *dev_desc;
+       int i;
+
+       /* first write PPCBOOT Info */
+       video_puts("\n");
+       video_puts(version_string);
+       video_puts("\n\n");
+       /* then CPU and board infos */
+  get_sys_info(&sys_info);
+  video_puts("CPU:   IBM PowerPC 405GP Rev. ");
+  switch (pvr) {
+    case PVR_405GP_RB: video_putc('B'); break;
+    case PVR_405GP_RC: video_putc('C'); break;
+    case PVR_405GP_RD: video_putc('D'); break;
+    case PVR_405GP_RE: video_putc('E'); break;
+    default: video_puts("unknown"); break;
+  }
+   sprintf(tmpbuf," at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf,idata->cpu_clk),
+         sys_info.freqPLB / 1000000,
+         sys_info.freqPLB / sys_info.pllOpbDiv / 1000000,
+         sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000);
+       video_puts(tmpbuf);
+  if (mfdcr(strap) & PSR_PCI_ASYNC_EN)
+    video_puts("       PCI async ext clock used, ");
+  else {
+       sprintf(buf,"       PCI sync clock at %lu MHz, ", sys_info.freqPLB / sys_info.pllPciDiv / 1000000);
+    video_puts(buf);
+  }
+  if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+    video_puts("internal PCI arbiter enabled\n");
+  else
+    video_puts("external PCI arbiter enabled\n");
+  video_puts("       16 kB I-Cache 8 kB D-Cache\n");
+   /* now some board infos */
+  video_puts("Board: ");
+  if (!s || strncmp(s, "PIP405", 6)) {
+       bc=video_set_attr(VGA_ATTR_CLR_RED | VGA_ATTR_ITN);
+               video_puts("### No HW ID - assuming PIP405");
+  }
+  else {
+       bc=video_set_attr(VGA_ATTR_CLR_GRN);
+       for (e=s; *e; ++e) {
+       if (*e == ' ')
+               break;
+    }
+    for ( ; s<e; ++s) {
+       if(*s=='_') {
+                               ++s;
+                               break;
+                       }
+                       video_putc (*s);
+               }
+               video_puts("  Serial No.: ");
+    for ( ; s<e; ++s) {
+                       video_putc (*s);
+               }
+  }
+       video_set_attr(bc);
+       bc=in8(CONFIG_PORT_ADDR);
+       sprintf(buf," Boot Config 0x%02X\n",bc);
+  video_puts(buf);
+       /* DRAM size    */
+#if 0
+  video_puts("DRAM:    ");
+       sprintf(buf,"%lu MBytes\n",bd_ptr->bi_memsize/0x100000);
+  video_puts(buf);
+  /* flash size: */
+  video_puts("FLASH:   ");
+  if(switch_cs(0)==0) {
+       bc=video_set_attr(VGA_ATTR_CLR_GRN);
+               video_puts("(Flash boot)");
+               video_set_attr(bc);
+       }
+       else {
+       switch_cs(1); /* back to boot mode */
+               bc=video_set_attr(VGA_ATTR_CLR_RED | VGA_ATTR_ITN);
+               video_puts("(Multi Purpose Socket boot)");
+               video_set_attr(bc);
+       }
+       sprintf(buf," %lu MBytes\n",bd_ptr->bi_flashsize/0x100000);
+  video_puts(buf);
+       /* revisions */
+  video_puts("Rev:     ");
+       sprintf(tmpbuf,"PCB Rev: %c PLD%d Rev %d PLD%d Rev %d\n\n",(in8(PLD_BOARD_CFG_REG)&0xf)+'A',
+                               in8(PLD_PART_REG)&0xf,in8(PLD_VERS_REG)&0xf,
+                               (in8(PLD_PART_REG)>>4)&0xf,(in8(PLD_VERS_REG)>>4)&0xf);
+  video_puts(tmpbuf);
+       for(i=0;i<CFG_IDE_MAXDEVICE;i++) {
+               dev_desc=(block_dev_desc_t *)ide_get_dev(i);
+               video_put_dev_string(dev_desc);
+       }
+       video_puts("\n");
+       for(i=0;i<CFG_SCSI_MAX_DEVICE;i++) {
+               dev_desc=(block_dev_desc_t *)scsi_get_dev(i);
+               video_put_dev_string(dev_desc);
+       }
+       video_puts("\n");
+#endif
+}
+
+#endif
+
+
+
+
+
diff --git a/board/mpl/mip405/mip405.h b/board/mpl/mip405/mip405.h
new file mode 100644 (file)
index 0000000..a4ce243
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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
+ *
+ */
+ /****************************************************************************
+ * Global routines used for MIP405
+ *****************************************************************************/
+#ifndef __ASSEMBLY__ 
+int switch_cs(unsigned char boot);
+
+extern int  mem_test(unsigned long start, unsigned long ramsize,int mode); 
+
+void user_led0(unsigned char on);
+
+typedef struct {
+       char signature[4];
+       char serial_name[17];   /* "MIP405_1000xxxxx" */
+       char eth_addr[21];                      /* "00:60:C2:0a:00:00" */
+} backup_t;
+void get_backup_values(backup_t *buf);
+void set_backup_values(int overwrite);
+
+
+#endif
+/* timings */
+/* PLD (CS7) */
+#define PLD_BME        0       /* Burst disable */
+#define PLD_TWE        5       /* 5 * 30ns 120ns Waitstates (access=TWT+1+TH) */
+#define PLD_CSN        1       /* Chipselect is driven inactive for 1 Cycle BTW transfers */
+#define PLD_OEN        1       /* Cycles from CS low to OE low   */
+#define PLD_WBN        1       /* Cycles from CS low to WE low   */
+#define PLD_WBF        1       /* Cycles from WE high to CS high */
+#define PLD_TH 2       /* Number of hold cycles after transfer */
+#define PLD_RE 0       /* Ready disabled */
+#define PLD_SOR        1       /* Sample on Ready disabled */
+#define PLD_BEM        0       /* Byte Write only active on Write cycles */
+#define PLD_PEN        0       /* Parity disable */
+#define PLD_AP         ((PLD_BME << 31) + (PLD_TWE << 23) + (PLD_CSN << 18) + (PLD_OEN << 16) + (PLD_WBN << 14) + \
+                                       (PLD_WBF << 12) + (PLD_TH << 9) + (PLD_RE << 8) + (PLD_SOR << 7) + (PLD_BEM << 6) + (PLD_PEN << 5))
+
+/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */
+#define PLD_BS 0       /* 1 MByte */
+/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */
+#define PLD_BU 3       /* R/W */
+/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */
+#define PLD_BW 0       /* 16Bit */
+#define PLD_CR ((PER_PLD_ADDR & 0xfff00000) + (PLD_BS << 17) + (PLD_BU << 15) + (PLD_BW << 13))
+
+
+/* timings */
+
+#define PER_BOARD_ADDR (PER_UART1_ADDR+(1024*1024))
+/* Dummy CS to get the board revision */
+#define BOARD_BME      0       /* Burst disable */
+#define BOARD_TWE      255     /* 255 * 30ns 120ns Waitstates (access=TWT+1+TH) */
+#define BOARD_CSN      1       /* Chipselect is driven inactive for 1 Cycle BTW transfers */
+#define BOARD_OEN      1       /* Cycles from CS low to OE low   */
+#define BOARD_WBN      1       /* Cycles from CS low to WE low   */
+#define BOARD_WBF      1       /* Cycles from WE high to CS high */
+#define BOARD_TH       2       /* Number of hold cycles after transfer */
+#define BOARD_RE       0       /* Ready disabled */
+#define BOARD_SOR      1       /* Sample on Ready disabled */
+#define BOARD_BEM      0       /* Byte Write only active on Write cycles */
+#define BOARD_PEN      0       /* Parity disable */
+#define BOARD_AP       ((BOARD_BME << 31) + (BOARD_TWE << 23) + (BOARD_CSN << 18) + (BOARD_OEN << 16) + (BOARD_WBN << 14) + \
+                                       (BOARD_WBF << 12) + (BOARD_TH << 9) + (BOARD_RE << 8) + (BOARD_SOR << 7) + (BOARD_BEM << 6) + (BOARD_PEN << 5))
+
+/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */
+#define BOARD_BS       0       /* 1 MByte */
+/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */
+#define BOARD_BU       3       /* R/W */
+/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */
+#define BOARD_BW       0       /* 16Bit */
+#define BOARD_CR       ((PER_BOARD_ADDR & 0xfff00000) + (BOARD_BS << 17) + (BOARD_BU << 15) + (BOARD_BW << 13))
+
+
+/* UART0 CS2 */
+#define UART0_BME      0       /* Burst disable */
+#define UART0_TWE      7       /* 7 * 30ns 210ns Waitstates (access=TWT+1+TH) */
+#define UART0_CSN      1       /* Chipselect is driven inactive for 1 Cycle BTW transfers */
+#define UART0_OEN      1       /* Cycles from CS low to OE low   */
+#define UART0_WBN      1       /* Cycles from CS low to WE low   */
+#define UART0_WBF      1       /* Cycles from WE high to CS high */
+#define UART0_TH       2       /* Number of hold cycles after transfer */
+#define UART0_RE       0       /* Ready disabled */
+#define UART0_SOR      1       /* Sample on Ready disabled */
+#define UART0_BEM      0       /* Byte Write only active on Write cycles */
+#define UART0_PEN      0       /* Parity disable */
+#define UART0_AP       ((UART0_BME << 31) + (UART0_TWE << 23) + (UART0_CSN << 18) + (UART0_OEN << 16) + (UART0_WBN << 14) + \
+                                       (UART0_WBF << 12) + (UART0_TH << 9) + (UART0_RE << 8) + (UART0_SOR << 7) + (UART0_BEM << 6) + (UART0_PEN << 5))
+
+/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */
+#define UART0_BS       0       /* 1 MByte */
+/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */
+#define UART0_BU       3       /* R/W */
+/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */
+#define UART0_BW       0       /* 8Bit */
+#define UART0_CR       ((PER_UART0_ADDR & 0xfff00000) + (UART0_BS << 17) + (UART0_BU << 15) + (UART0_BW << 13))
+
+/* UART1 CS3 */
+#define UART1_AP UART0_AP /* same timing as UART0 */
+#define UART1_CR       ((PER_UART1_ADDR & 0xfff00000) + (UART0_BS << 17) + (UART0_BU << 15) + (UART0_BW << 13))
+
+
+
+/* Flash CS0 or CS 1 */
+/* 0x7F8FFE80 slowest timing at all... */
+#define FLASH_BME_B    1       /* Burst enable */
+#define FLASH_FWT_B    0x6     /* 6 * 30ns 210ns First Wait Access */
+#define FLASH_BWT_B    0x6     /* 6 * 30ns 210ns Burst Wait Access */
+#define FLASH_BME      0       /* Burst disable */
+#define FLASH_TWE      0xb/* 11 * 30ns 330ns Waitstates (access=TWT+1+TH) */
+#define FLASH_CSN      0       /* Chipselect is driven inactive for 1 Cycle BTW transfers */
+#define FLASH_OEN      1       /* Cycles from CS low to OE low   */
+#define FLASH_WBN      1       /* Cycles from CS low to WE low   */
+#define FLASH_WBF      1       /* Cycles from WE high to CS high */
+#define FLASH_TH       2       /* Number of hold cycles after transfer */
+#define FLASH_RE       0       /* Ready disabled */
+#define FLASH_SOR      1       /* Sample on Ready disabled */
+#define FLASH_BEM      0       /* Byte Write only active on Write cycles */
+#define FLASH_PEN      0       /* Parity disable */
+/* Access Parameter Register for non Boot */
+#define FLASH_AP       ((FLASH_BME << 31) + (FLASH_TWE << 23) + (FLASH_CSN << 18) + (FLASH_OEN << 16) + (FLASH_WBN << 14) + \
+                                       (FLASH_WBF << 12) + (FLASH_TH << 9) + (FLASH_RE << 8) + (FLASH_SOR << 7) + (FLASH_BEM << 6) + (FLASH_PEN << 5))
+/* Access Parameter Register for Boot */
+#define FLASH_AP_B     ((FLASH_BME_B << 31) + (FLASH_FWT_B << 26) + (FLASH_BWT_B << 23) + (FLASH_CSN << 18) + (FLASH_OEN << 16) + (FLASH_WBN << 14) + \
+                                       (FLASH_WBF << 12) + (FLASH_TH << 9) + (FLASH_RE << 8) + (FLASH_SOR << 7) + (FLASH_BEM << 6) + (FLASH_PEN << 5))
+
+/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */
+#define FLASH_BS       2       /* 4 MByte */
+/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */
+#define FLASH_BU       3       /* R/W */
+/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */
+#define FLASH_BW       1       /* 16Bit */
+/* CR register for Boot */
+#define FLASH_CR_B     ((FLASH_BASE0_PRELIM & 0xfff00000) + (FLASH_BS << 17) + (FLASH_BU << 15) + (FLASH_BW << 13))
+/* CR register for non Boot */
+#define FLASH_CR       ((MULTI_PURPOSE_SOCKET_ADDR & 0xfff00000) + (FLASH_BS << 17) + (FLASH_BU << 15) + (FLASH_BW << 13))
+
+/* MPS CS1 or CS0 */
+/* Boot CS: */
+#define MPS_BME_B      1       /* Burst enable */
+#define MPS_FWT_B      0x6/* 6 * 30ns 210ns First Wait Access */
+#define MPS_BWT_B      0x6     /* 6 * 30ns 210ns Burst Wait Access */
+#define MPS_BME                0       /* Burst disable */
+#define MPS_TWE                0xb/* 11 * 30ns 330ns Waitstates (access=TWT+1+TH) */
+#define MPS_CSN                0       /* Chipselect is driven inactive for 1 Cycle BTW transfers */
+#define MPS_OEN                1       /* Cycles from CS low to OE low   */
+#define MPS_WBN                1       /* Cycles from CS low to WE low   */
+#define MPS_WBF                1       /* Cycles from WE high to CS high */
+#define MPS_TH         2       /* Number of hold cycles after transfer */
+#define MPS_RE         0       /* Ready disabled */
+#define MPS_SOR                1       /* Sample on Ready disabled */
+#define MPS_BEM                0       /* Byte Write only active on Write cycles */
+#define MPS_PEN                0       /* Parity disable */
+/* Access Parameter Register for non Boot */
+#define MPS_AP                 ((MPS_BME << 31) + (MPS_TWE << 23) + (MPS_CSN << 18) + (MPS_OEN << 16) + (MPS_WBN << 14) + \
+                                       (MPS_WBF << 12) + (MPS_TH << 9) + (MPS_RE << 8) + (MPS_SOR << 7) + (MPS_BEM << 6) + (MPS_PEN << 5))
+/* Access Parameter Register for Boot */
+#define MPS_AP_B               ((MPS_BME_B << 31) + (MPS_FWT_B << 26) + (MPS_BWT_B << 23) + (MPS_CSN << 18) + (MPS_OEN << 16) + (MPS_WBN << 14) + \
+                                       (MPS_WBF << 12) + (MPS_TH << 9) + (MPS_RE << 8) + (MPS_SOR << 7) + (MPS_BEM << 6) + (MPS_PEN << 5))
+
+/* Size: 0=1MB, 1=2MB, 2=4MB, 3=8MB, 4=16MB, 5=32MB, 6=64MB, 7=128MB */
+#define MPS_BS         2       /* 4 MByte */
+/* Usage: 0=disabled, 1=Read only, 2=Write Only, 3=R/W */
+#define MPS_BU         3       /* R/W */
+/* Bus width: 0=8Bit, 1=16Bit, 2=32Bit, 3=Reserved */
+#define MPS_BW         0       /* 8Bit */
+/* CR register for Boot */
+#define MPS_CR_B       ((FLASH_BASE0_PRELIM & 0xfff00000) + (MPS_BS << 17) + (MPS_BU << 15) + (MPS_BW << 13))
+/* CR register for non Boot */
+#define MPS_CR         ((MULTI_PURPOSE_SOCKET_ADDR & 0xfff00000) + (MPS_BS << 17) + (MPS_BU << 15) + (MPS_BW << 13))
+
+
+
diff --git a/board/mpl/mip405/ppcboot.lds b/board/mpl/mip405/ppcboot.lds
new file mode 100644 (file)
index 0000000..e692d4a
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * (C) Copyright 2000, 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
+{
+  .resetvec 0xFFFFFFFC :
+  {
+    *(.resetvec)
+  } = 0xffff
+
+  /* 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      :
+  {
+    /* WARNING - the following is hand-optimized to fit within */
+    /* the sector layout of our flash chips!   XXX FIXME XXX   */
+
+    cpu/ppc4xx/start.o (.text)
+    board/mpl/mip405/init.o    (.text)
+    cpu/ppc4xx/kgdb.o  (.text)
+    cpu/ppc4xx/traps.o (.text)
+    cpu/ppc4xx/interrupts.o    (.text)
+    cpu/ppc4xx/serial.o        (.text)
+    cpu/ppc4xx/cpu_init.o      (.text)
+    cpu/ppc4xx/speed.o (.text)
+    cpu/ppc4xx/405gp_enet.o    (.text)
+    common/dlmalloc.o  (.text)
+    ppc/crc32.o                (.text)
+    ppc/extable.o      (.text)
+    ppc/zlib.o         (.text)
+
+/*    . = env_offset;*/
+/*    common/environment.o(.text)*/
+
+    *(.text)
+    *(.fixup)
+    *(.got1)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(.rodata)
+    *(.rodata1)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _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(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(256);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/board/mpl/pip405/Makefile b/board/mpl/pip405/Makefile
new file mode 100644 (file)
index 0000000..802ab60
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# (C) Copyright 2000, 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 ../common/flash.o cmd_pip405.o ../common/pci.o ../common/isa.o ../common/kbd.o ../common/video.o ../common/sym53c8xx.o ../common/usb_uhci.o ../common/memtst.o
+SOBJS  = init.o
+
+$(LIB):        $(OBJS) $(SOBJS)
+       $(AR) crv $@ $^
+
+clean:
+       rm -f $(SOBJS) $(OBJS)
+
+distclean:     clean
+       rm -f $(LIB) core *.bak .depend
+
+#########################################################################
+
+.depend:       Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+               $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
diff --git a/board/mpl/pip405/cmd_pip405.c b/board/mpl/pip405/cmd_pip405.c
new file mode 100644 (file)
index 0000000..e4f5e0b
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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
+ *
+ * hacked for PIP405
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include "pip405.h"
+#include <rtc.h>
+#include "../common/isa.h"
+#include "../common/video.h"
+#include <i2c.h>
+extern flash_info_t flash_info[];      /* info for FLASH chips */
+
+int PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned int Value, int Width);
+unsigned int PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width);
+
+
+
+
+
+#define TRUE 1
+#define FALSE 0
+
+#define IMAGE_SIZE 0x80000 
+
+image_header_t header;
+
+
+
+int pip405_prg(unsigned long src,unsigned long size)
+{
+       unsigned long start;
+       flash_info_t *info;
+       int i,rc;
+       unsigned long *magic = (unsigned long *)src;
+       
+       info = &flash_info[0];
+       start = 0 - size;
+       for(i=info->sector_count-1;i>0;i--)
+       {
+               info->protect[i] = 0; /* unprotect this sector */
+               if(start>=info->start[i])
+               break;
+       }
+       /* set-up flash location */
+       rc=switch_cs(FALSE);
+       /* now erase flash */
+       if(magic[0]!=IH_MAGIC) {
+               printf("Bad Magic number\n");
+               switch_cs(rc);
+               return -1;
+       }
+       printf("Start erasing at %lx (sector %d) (start %lx)\n",
+                               start,i,info->start[i]);
+       flash_erase (info, i, info->sector_count-1);
+       printf("flash erased, programming 0x%lx Bytes\n",size);
+       switch (rc = flash_write ((uchar *)src, start, size)) 
+       {
+               case 0: printf ("programming done\n"); return 0;
+               case 1: printf ("Timeout writing to Flash\n"); return 1;
+               case 2: printf ("Flash not Erased\n"); return 1;
+               case 4: printf ("Can't write to protected Flash sectors\n"); return 1;
+               case 8: printf ("Outside available Flash\n"); return 1;
+               default:        printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc); return 1;
+       }
+  return 1;
+}
+
+int pip405_prg_image(unsigned long load_addr)
+{
+       unsigned long data,len,checksum;
+       image_header_t *hdr=&header;  
+       /* Copy header so we can blank CRC field for re-calculation */
+       memcpy (&header, (char *)load_addr, sizeof(image_header_t));
+
+       if (hdr->ih_magic  != IH_MAGIC) {
+               printf ("Bad Magic Number\n");
+               return 1;
+       }
+       if (hdr->ih_os  != IH_OS_PPCBOOT) {
+               printf ("No PPCBOOT Image\n");
+               return 1;
+       }
+       if (hdr->ih_type  != IH_TYPE_FIRMWARE) {
+               printf ("No Firmware Image\n");
+               return 1;
+       }
+       data = (ulong)&header;
+       len  = sizeof(image_header_t);
+       checksum = hdr->ih_hcrc;
+       hdr->ih_hcrc = 0;
+       if (crc32 (0, (char *)data, len) != checksum) {
+               printf ("Bad Header Checksum\n");
+               return 1;
+       }
+       data = load_addr + sizeof(image_header_t);
+       len  = hdr->ih_size;
+       printf ("   Verifying Checksum ... ");
+       if (crc32 (0, (char *)data, len) != hdr->ih_dcrc) {
+               printf ("Bad Data CRC\n");
+               return 1;
+       }
+       printf ("OK\n");
+       return(pip405_prg(data,len));
+} 
+
+
+/* ------------------------------------------------------------------------- */
+
+int do_pip405(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+
+       ulong size,src,device,function,load_addr;
+       unsigned char i2c[3];
+       int result;     
+       backup_t back;  
+       src = MULTI_PURPOSE_SOCKET_ADDR;
+       size = IMAGE_SIZE;
+
+       if (strcmp(argv[1], "flash") == 0) 
+       {
+               if (strcmp(argv[2], "floppy") == 0) {
+                       char *local_args[3];
+                       extern int do_fdcboot (cmd_tbl_t *, bd_t *, int, int, char *[]);
+                       printf ("\nupdating bootloader image from floppy\n");
+                       local_args[0] = argv[0];
+                       if(argc==4) {
+                               local_args[1] = argv[3];
+                               local_args[2] = NULL;
+                               load_addr=simple_strtoul(argv[3], NULL, 16);
+                               result=do_fdcboot(cmdtp, bd, 0, 2, local_args);
+                       }
+                       else {
+                               local_args[1] = NULL;
+                               load_addr=CFG_LOAD_ADDR;
+                               result=do_fdcboot(cmdtp, bd, 0, 1, local_args);
+                       }
+                       result=pip405_prg_image(load_addr); 
+                       return result;
+               }
+               if (strcmp(argv[2], "mem") == 0) {
+                       if(argc==4) {
+                               load_addr=simple_strtoul(argv[3], NULL, 16);
+                       }
+                       else {
+                               load_addr=CFG_LOAD_ADDR;
+                       }
+                       printf ("\nupdating bootloader image from memory at %lX\n",load_addr);
+                       result=pip405_prg_image(load_addr); 
+                       return result;
+               }
+               if (strcmp(argv[2], "mps") == 0) {
+                       printf ("\nupdating bootloader image from MSP\n");
+                       result=pip405_prg(src,size);
+                       return result;
+               }
+       }
+       if (strcmp(argv[1], "getback") == 0) {
+               get_backup_values(&back);
+               back.signature[3]=0;
+               back.serial_name[16]=0;
+               back.eth_addr[20]=0;
+               printf("GetBackUp: signature: %s\n",back.signature);
+               printf("           serial#:   %s\n",back.serial_name);
+               printf("           ethaddr:   %s\n",back.eth_addr);
+               return 0;
+       } 
+       if (strcmp(argv[1], "setback") == 0) {
+               set_backup_values(1);
+               return 0;
+       } 
+       if (strcmp(argv[1], "mem") == 0) 
+       {
+               result=0;
+               if(argc==3)
+               {
+                       result = (int)simple_strtol(argv[2], NULL, 16);
+           }
+           src=(unsigned long)&result;
+           src-=CFG_MEMTEST_START;
+           src-=(100*1024); /* - 100k */
+           src&=0xfff00000;
+           size=0;
+           do {
+               size++;
+                       printf("Pass %ld\n",size);
+                       mem_test(CFG_MEMTEST_START,src,1);
+                       if(ctrlc())
+                               break;
+                       if(result>0)
+                               result--;
+                       
+               }while(result);
+               return 0;
+       }
+       if (strcmp(argv[1], "info") == 0) 
+       {
+               print_pip405_info();
+               return 0;
+       }
+       if (strcmp(argv[1], "i2c") == 0) 
+       {
+               i2c[0]=CFG_I2C_EEPROM_ADDR;
+               i2c[1]=0;
+               i2c[2]=0;
+               i2c_read(&i2c[0],3,(unsigned char *)CFG_LOAD_ADDR,512);
+               return 0;
+       }
+       if (strcmp(argv[1], "led") == 0) 
+       {
+               device = (ulong)simple_strtoul(argv[2], NULL, 10);
+               function = (ulong)simple_strtoul(argv[3], NULL, 10);
+               if(device==0)
+                       user_led0((function==1));
+               else
+                       user_led1((function==1));
+               return 0;
+       }
+    printf("Usage:\n%s\n", cmdtp->usage);
+    return 1;
+}
+
+/* ------------------------------------------------------------------------- */
diff --git a/board/mpl/pip405/config.mk b/board/mpl/pip405/config.mk
new file mode 100644 (file)
index 0000000..0f8d153
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# (C) Copyright 2000, 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
+#
+
+#
+# esd ADCIOP boards
+#
+
+#TEXT_BASE = 0xFFFE0000
+TEXT_BASE = 0xFFF80000
diff --git a/board/mpl/pip405/init.S b/board/mpl/pip405/init.S
new file mode 100644 (file)
index 0000000..1723d54
--- /dev/null
@@ -0,0 +1,242 @@
+/*------------------------------------------------------------------------------+
+ *
+ *      This source code has been made available to you by IBM on an AS-IS
+ *      basis.  Anyone receiving this source is licensed under IBM
+ *      copyrights to use it in any way he or she deems fit, including
+ *      copying it, modifying it, compiling it, and redistributing it either
+ *      with or without modifications.  No license under IBM patents or
+ *      patent applications is to be implied by the copyright license.
+ *
+ *      Any user of this software should understand that IBM cannot provide
+ *      technical support for this software and will not be responsible for
+ *      any consequences resulting from the use of this software.
+ *
+ *      Any person who transfers this source code or any derivative work
+ *      must include the IBM copyright notice, this paragraph, and the
+ *      preceding two paragraphs in the transferred software.
+ *
+ *      COPYRIGHT   I B M   CORPORATION 1995
+ *      LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
+ *-------------------------------------------------------------------------------*/
+
+/*-----------------------------------------------------------------------------
+ * Function:     ext_bus_cntlr_init
+ * Description:  Initializes the External Bus Controller for the external 
+ *             peripherals. IMPORTANT: For pass1 this code must run from 
+ *             cache since you can not reliably change a peripheral banks
+ *             timing register (pbxap) while running code from that bank.
+ *             For ex., since we are running from ROM on bank 0, we can NOT 
+ *             execute the code that modifies bank 0 timings from ROM, so
+ *             we run it from cache.
+ *     Bank 0 - Flash or Multi Purpose Socket
+ *     Bank 1 - Multi Purpose Socket or Flash
+ *     Bank 2 - not used
+ *     Bank 3 - not used
+ *     Bank 4 - not used
+ *     Bank 5 - not used
+ *     Bank 6 - used to switch on the 12V for the Multipurpose socket
+ *     Bank 7 - Config Register
+ *-----------------------------------------------------------------------------*/
+#include <ppc4xx.h>
+
+#define _LINUX_CONFIG_H 1      /* avoid reading Linux autoconf.h file  */
+
+#include "config_PIP405.h"
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+#include <asm/cache.h>
+#include <asm/mmu.h>
+        
+        
+       .globl  ext_bus_cntlr_init
+ext_bus_cntlr_init:
+  mflr    r4                      /* save link register */
+  bl      ..getAddr
+..getAddr:
+  mflr    r3                      /* get address of ..getAddr */
+  mtlr    r4                      /* restore link register */
+  addi    r4,0,14                 /* set ctr to 14; used to prefetch */
+  mtctr   r4                      /* 14 cache lines to fit this function */
+                                   /* in cache (gives us 8x14=112 instrctns) */
+..ebcloop:
+  icbt    r0,r3                   /* prefetch cache line for addr in r3 */
+  addi    r3,r3,32                                                             /* move to next cache line */
+  bdnz    ..ebcloop               /* continue for 14 cache lines */
+
+   /*-------------------------------------------------------------------
+    * Delay to ensure all accesses to ROM are complete before changing
+    * bank 0 timings.
+    *------------------------------------------------------------------- */
+       addis   r3,0,0x0
+  ori     r3,r3,0xA000
+  mtctr   r3
+..spinlp:
+  bdnz    ..spinlp                /* spin loop */
+
+       /*-----------------------------------------------------------------------
+        * decide boot up mode
+        *----------------------------------------------------------------------- */
+       addi            r4,0,pb0cr
+       mtdcr           ebccfga,r4
+       mfdcr           r4,ebccfgd
+                               
+       andi.           r0, r4, 0x2000                  /* mask out irrelevant bits */
+       beq                     0f                                                                      /* jump if 8 bit bus width */
+                               
+       /* setup 16 bit things
+   *-----------------------------------------------------------------------
+   * Memory Bank 0 (16 Bit Flash) initialization
+   *---------------------------------------------------------------------- */
+        
+       addi    r4,0,pb0ap
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x9B01
+  ori     r4,r4,0x5480
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb0cr
+  mtdcr   ebccfga,r4
+       /* BS=0x011(8MB),BU=0x3(R/W), */
+  addis   r4,0,((FLASH_BASE0_PRELIM & 0xFFF00000) | 0x00050000)@h 
+  ori     r4,r4,0xA000          /* BW=0x01(16 bits) */
+  mtdcr   ebccfgd,r4
+
+  /*-----------------------------------------------------------------------
+   * Memory Bank 1 (Multi Purpose Socket) initialization
+   *----------------------------------------------------------------------*/
+  addi    r4,0,pb1ap
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0281         
+  ori     r4,r4,0x5480
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb1cr
+  mtdcr   ebccfga,r4
+  /* BS=0x011(8MB),BU=0x3(R/W), */
+  addis   r4,0,((MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000) | 0x00050000)@h 
+  ori     r4,r4,0x8000          /* BW=0x0( 8 bits) */
+  mtdcr   ebccfgd,r4
+       b                               1f      
+                               
+0:
+  /* 8Bit boot mode: */        
+       /*-----------------------------------------------------------------------
+   * Memory Bank 0 Multi Purpose Socket initialization
+   *----------------------------------------------------------------------- */
+        
+       addi    r4,0,pb0ap
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x9B01
+  ori     r4,r4,0x5480
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb0cr
+  mtdcr   ebccfga,r4
+       /* BS=0x011(4MB),BU=0x3(R/W), */
+  addis   r4,0,((FLASH_BASE0_PRELIM & 0xFFF00000) | 0x00050000)@h 
+  ori     r4,r4,0x8000          /* BW=0x0( 8 bits) */
+  mtdcr   ebccfgd,r4
+
+  /*-----------------------------------------------------------------------
+   * Memory Bank 1 (Flash) initialization
+   *-----------------------------------------------------------------------*/
+  addi    r4,0,pb1ap
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0281         
+  ori     r4,r4,0x5480
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb1cr
+  mtdcr   ebccfga,r4
+  /* BS=0x011(8MB),BU=0x3(R/W), */
+  addis   r4,0,((MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000) | 0x00050000)@h 
+  ori     r4,r4,0xA000          /* BW=0x0( 8 bits) */
+  mtdcr   ebccfgd,r4
+
+1:
+  /*-----------------------------------------------------------------------
+   * Memory Bank 2-3-4-5-6 (not used) initialization
+   *-----------------------------------------------------------------------*/
+  addi    r4,0,pb2cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb3cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb4cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb5cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+        
+       addi    r4,0,pb6cr
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0000
+  ori     r4,r4,0x0000
+  mtdcr   ebccfgd,r4
+               
+       /*-----------------------------------------------------------------------
+   * Memory Bank 7 (Config Register) initialization
+   *----------------------------------------------------------------------- */
+  addi    r4,0,pb7ap
+  mtdcr   ebccfga,r4
+  addis   r4,0,0x0181        /* Doc says TWT=3 and Openios TWT=3!! */
+  ori     r4,r4,0x5280          /* disable Ready, BEM=0 */
+  mtdcr   ebccfgd,r4
+
+  addi    r4,0,pb7cr
+  mtdcr   ebccfga,r4
+       /* BS=0x0(1MB),BU=0x3(R/W), */
+  addis   r4,0,((CONFIG_PORT_ADDR & 0xFFF00000) | 0x00010000)@h 
+  ori     r4,r4,0x8000            /* BW=0x0(8 bits) */
+  mtdcr   ebccfgd,r4
+       nop                             /* pass2 DCR errata #8 */
+  blr
+
+/*-----------------------------------------------------------------------------
+ * Function:     sdram_init
+ * Description:  Configures the internal SRAM memory. and setup the 
+ *               Stackpointer in it.
+ *----------------------------------------------------------------------------- */
+        .globl  sdram_init
+
+sdram_init:
+
+       /*-------------------------------------------------------------------
+        * init OnChip Memory for a temporary stack
+        *------------------------------------------------------------------- */
+
+       lis     r0, 0x7FFF
+       ori     r0, r0, 0xFFFF
+       mfdcr   r3, ocmiscntl           /* get instr-side IRAM config */
+       mfdcr   r4, ocmdscntl   /* get data-side IRAM config */
+       and     r3, r3, r0      /* disable data-side IRAM */
+       and     r4, r4, r0      /* disable data-side IRAM */
+       mtdcr   ocmiscntl, r3   /* set instr-side IRAM config */
+       mtdcr   ocmdscntl, r4   /* set data-side IRAM config */
+       isync
+       lis     r0, OCM_DATA_ADDR@h/* IRAM is mapped here */
+       mtdcr   ocmdsarc, r0    /* set data-side IRAM address */
+       oris    r4, r4, 0xC000  /* enable data-side IRAM */
+       mtdcr   ocmdscntl, r4   /* set data-side IRAM config */
+       isync
+
+       mfdcr   r3, ocmdsarc    /* set temp stackpointer (needed by CONS_Init) */
+       andis.  r3, r3, 0xFC00
+       addi    r1, r3, 0x1000-16
+
+  blr
+
diff --git a/board/mpl/pip405/pip405.c b/board/mpl/pip405/pip405.c
new file mode 100644 (file)
index 0000000..f961eb4
--- /dev/null
@@ -0,0 +1,1162 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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
+ *
+ *
+ * TODO: clean-up
+ */
+
+#include <ppcboot.h>
+#include "pip405.h"
+#include <asm/processor.h>
+#include <405gp_i2c.h>
+#include <devices.h>
+#include "../common/isa.h"
+#include "../common/video.h"
+
+
+extern block_dev_desc_t * scsi_get_dev(int dev);
+extern block_dev_desc_t * ide_get_dev(int dev);
+
+#undef SDRAM_DEBUG
+
+#define FALSE           0
+#define TRUE            1
+
+/* stdlib.h causes some compatibility problems; should fixe these! -- wd */
+#ifndef __ldiv_t_defined
+typedef struct {
+       long int quot;          /* Quotient     */
+       long int rem;           /* Remainder    */
+} ldiv_t;
+extern ldiv_t ldiv (long int __numer, long int __denom);
+# define __ldiv_t_defined      1
+#endif
+
+
+
+
+typedef enum {
+  SDRAM_NO_ERR,
+  SDRAM_SPD_COMM_ERR,
+  SDRAM_SPD_CHKSUM_ERR,
+  SDRAM_UNSUPPORTED_ERR,
+  SDRAM_UNKNOWN_ERR
+} SDRAM_ERR;
+
+typedef struct {
+  const unsigned char mode;
+  const unsigned char row;
+  const unsigned char col;
+  const unsigned char bank;
+} SDRAM_SETUP;
+
+static const SDRAM_SETUP sdram_setup_table[] = {
+  {1, 11,  9, 2},
+  {1, 11, 10, 2},
+  {2, 12,  9, 4},
+  {2, 12, 10, 4},
+  {3, 13,  9, 4},
+  {3, 13, 10, 4},
+  {3, 13, 11, 4},
+  {4, 12,  8, 2},
+  {4, 12,  8, 4},
+  {5, 11,  8, 2},
+  {5, 11,  8, 4},
+  {6, 13,  8, 2},
+  {6, 13,  8, 4},
+  {7, 13,  9, 2},
+  {7, 13, 10, 2},
+  {0,  0,  0, 0}
+};
+
+static const unsigned char cal_indextable[] = {
+  9, 23, 25
+};
+
+
+/*
+ * translate ns.ns/10 coding of SPD timing values
+ * into 10 ps unit values
+ */
+
+unsigned short NS10to10PS(unsigned char spd_byte, unsigned char spd_version)
+{
+  unsigned short ns, ns10;
+
+  /* isolate upper nibble */
+  ns = (spd_byte >> 4) & 0x0F;
+  /* isolate lower nibble */
+  ns10 = (spd_byte & 0x0F);
+
+  return(ns*100 + ns10*10);
+}
+
+/*
+ * translate ns.ns/4 coding of SPD timing values
+ * into 10 ps unit values
+ */
+
+unsigned short NS4to10PS(unsigned char spd_byte, unsigned char spd_version)
+{
+  unsigned short ns, ns4;
+
+  /* isolate upper 6 bits */
+  ns = (spd_byte >> 2) & 0x3F;
+  /* isloate lower 2 bits */
+  ns4 = (spd_byte & 0x03);
+
+  return(ns*100 + ns4*25);
+}
+
+/*
+ * translate ns coding of SPD timing values
+ * into 10 ps unit values
+ */
+
+unsigned short NSto10PS(unsigned char spd_byte)
+{
+  return(spd_byte*100);
+}
+
+void SDRAM_err(const char *s)
+{
+#ifndef SDRAM_DEBUG
+  serial_init(get_gclk_freq(),9600);
+#endif
+  serial_puts("\n");
+  serial_puts(s);
+  serial_puts("\n enable SDRAM_DEBUG for more info\n");
+       for (;;);
+}      
+
+
+#ifdef SDRAM_DEBUG
+
+void write_hex(unsigned char i)
+{
+       char cc;
+       cc=i>>4;
+       cc&=0xf;
+       if(cc>9) 
+               serial_putc(cc+55);
+       else
+               serial_putc(cc+48);
+       cc=i&0xf;
+       if(cc>9) 
+               serial_putc(cc+55);
+       else
+               serial_putc(cc+48);
+}
+
+void write_4hex(unsigned long val)
+{
+  write_hex((unsigned char)(val>>24)); 
+  write_hex((unsigned char)(val>>16)); 
+  write_hex((unsigned char)(val>>8)); 
+  write_hex((unsigned char)val); 
+}
+
+#endif
+
+int board_pre_init (void)
+{
+  unsigned char dataout[1];
+  unsigned char datain[128];
+  unsigned long sdram_size;
+  SDRAM_SETUP *t = (SDRAM_SETUP *)sdram_setup_table;
+  unsigned long memclk;
+  unsigned long tmemclk;
+  unsigned long tmp, bank, baseaddr, bank_size;
+  unsigned short i;
+  unsigned char rows, cols, banks, sdram_banks, density;
+  unsigned char supported_cal, trp_clocks, trcd_clocks, tras_clocks, trc_clocks,tctp_clocks;
+  unsigned char cal_index, cal_val, spd_version, spd_chksum;
+  unsigned char buf[8];
+       
+       memclk = get_bus_freq(tmemclk);
+       tmemclk = 1000000000 / (memclk / 100);  /* in 10 ps units */
+
+#ifdef SDRAM_DEBUG
+  serial_init(get_gclk_freq(),9600);
+  serial_puts("\nstart SDRAM Setup\n");
+#endif
+
+  /* Read Serial Presence Detect Information */
+  dataout[0] = 0;
+  for (i=0; i<128;i++)
+    datain[i] = 127;
+  i=i2c_send(SDRAM_EEPROM_WRITE_ADDRESS,1,dataout);
+#ifdef SDRAM_DEBUG
+  serial_puts("i2c_send returns ");
+  write_hex(i);
+#endif
+  i=i2c_receive(SDRAM_EEPROM_READ_ADDRESS,128,datain);
+#ifdef SDRAM_DEBUG
+  serial_puts("\ni2c_receive returns ");
+  write_hex(i);
+  serial_puts("\n");
+#endif
+
+#ifdef SDRAM_DEBUG
+    for (i=0;i<128;i++)
+  {
+      write_hex(datain[i]);
+      serial_puts(" ");
+      if (((i+1)%16) == 0)
+                               serial_puts("\n");
+  }
+  serial_puts("\n");
+#endif
+  spd_chksum = 0;
+  for (i = 0; i < 63; i++) {
+        spd_chksum += datain[i];
+  } /* endfor */
+  if (datain[63] != spd_chksum) {
+#ifdef SDRAM_DEBUG
+    serial_puts("SPD chksum: 0x"); 
+    write_hex(datain[63]);
+    serial_puts(" != calc. chksum: 0x");
+    write_hex(spd_chksum);
+    serial_puts("\n");
+#endif
+               SDRAM_err("SPD checksum Error");
+   }
+  /* SPD seems to be ok, use it */
+
+  /* get SPD version */
+  spd_version = datain[62];
+
+  /* do some sanity checks on the kind of RAM */
+  if ((datain[0] < 0x80) ||       /* less than 128 valid bytes in SPD */
+      (datain[2] != 0x04) ||      /* if not SDRAM */
+      (!((datain[6] == 0x40) ||
+                       (datain[6] == 0x48))) || /* or not (64 Bit or 72 Bit)  */
+      (datain[7] != 0x00) ||
+      (datain[8] != 0x01) ||      /* or not LVTTL signal levels */
+      (datain[126] == 0x66))        /* or a 66Mhz modules */
+    SDRAM_err("unsupported SDRAM");
+#ifdef SDRAM_DEBUG
+  serial_puts("SDRAM sanity ok\n");
+#endif
+
+  /* get number of rows/cols/banks out of byte 3+4+5 */
+  rows = datain[3]; cols = datain[4]; banks = datain[5];
+
+  /* get number of SDRAM banks out of byte 17 and  
+     supported CAS latencies out of byte 18 */
+  sdram_banks = datain[17]; supported_cal = datain[18] & ~0x81;
+
+  while (t->mode != 0) {
+       if ((t->row == rows) && (t->col == cols) && (t->bank == sdram_banks))
+      break;
+    t++;
+  } /* endwhile */
+
+#ifdef SDRAM_DEBUG
+  serial_puts("rows: "); 
+  write_hex(rows);
+  serial_puts(" cols: "); 
+  write_hex(cols);
+  serial_puts(" banks: "); 
+  write_hex(banks);
+  serial_puts(" mode: "); 
+  write_hex(t->mode);
+  serial_puts("\n");
+#endif
+  if (t->mode == 0)
+    SDRAM_err("unsupported SDRAM");
+  /* get tRP, tRCD, tRAS and density from byte 27+29+30+31 */
+#ifdef SDRAM_DEBUG
+  serial_puts("tRP: ");
+  write_hex(datain[27]); 
+  serial_puts("\ntRCD: ");
+  write_hex(datain[29]);
+  serial_puts("\ntRAS: ");
+  write_hex(datain[30]); 
+  serial_puts("\n");
+#endif
+
+  trp_clocks = (NSto10PS(datain[27])+(tmemclk-1)) / tmemclk;
+  trcd_clocks = (NSto10PS(datain[29])+(tmemclk-1)) / tmemclk;
+  tras_clocks = (NSto10PS(datain[30])+(tmemclk-1)) / tmemclk;
+  density = datain[31];
+
+  /* trc_clocks is sum of trp_clocks + tras_clocks */
+  trc_clocks = trp_clocks + tras_clocks;
+       /* ctp = ((trp + tras) - trp - trcd) => tras - trcd */ 
+       tctp_clocks = ((NSto10PS(datain[30])-NSto10PS(datain[29]))+(tmemclk-1)) / tmemclk;
+
+#ifdef SDRAM_DEBUG
+  serial_puts("c_RP: ");
+  write_hex(trp_clocks); 
+  serial_puts("\nc_RCD: ");
+  write_hex(trcd_clocks);
+  serial_puts("\nc_RAS: ");
+  write_hex(tras_clocks); 
+  serial_puts("\nc_RC: (RP+RAS): ");
+  write_hex(trc_clocks); 
+  serial_puts("\nc_CTP: ((RP+RAS)-RP-RCD): ");
+  write_hex(tctp_clocks);
+  serial_puts("\nt_CTP: RAS - RCD: ");
+  write_hex((unsigned char)((NSto10PS(datain[30])-NSto10PS(datain[29]))>>8));
+  write_hex((unsigned char)(NSto10PS(datain[30])-NSto10PS(datain[29])));
+  serial_puts("\ntmemclk: ");
+  write_hex((unsigned char)(tmemclk>>8));
+  write_hex((unsigned char)(tmemclk));
+  serial_puts("\n");
+#endif
+
+  
+  cal_val = 255;
+  for (i = 6, cal_index = 0; (i > 0) && (cal_index < 3); i--) {
+    /* is this CAS latency supported ? */
+    if ((supported_cal >> i) & 0x01) {
+      buf[0]=datain[cal_indextable[cal_index]];
+      if (cal_index < 2) {
+                               if (NS10to10PS(buf[0], spd_version) <= tmemclk)
+                       cal_val = i;
+      } 
+      else {
+                               /* SPD bytes 25+26 have another format */
+                               if (NS4to10PS(buf[0], spd_version) <= tmemclk)
+                               cal_val = i;
+      } /* endif */
+      cal_index++;
+    } /* endif */
+  } /* endfor */
+#ifdef SDRAM_DEBUG
+  serial_puts("CAL: ");
+  write_hex(cal_val+1); 
+  serial_puts("\n");
+#endif
+
+  if (cal_val == 255)
+               SDRAM_err("unsupported SDRAM");
+
+  /* get SDRAM timing register */
+  mtdcr(memcfga,mem_sdtr1);
+  tmp=mfdcr(memcfgd) & ~0x018FC01F;
+  /* insert CASL value */
+/*  tmp |= ((unsigned long)cal_val) << 23; */
+  tmp |= ((unsigned long)cal_val) << 23;
+  /* insert PTA value */
+  tmp |= ((unsigned long)(trp_clocks - 1)) << 18;
+  /* insert CTP value */
+/*  tmp |= ((unsigned long)(trc_clocks - trp_clocks - trcd_clocks - 1)) << 16; */
+  tmp |= ((unsigned long)(trc_clocks - trp_clocks - trcd_clocks)) << 16; 
+  /* insert LDF (always 01) */
+  tmp |= ((unsigned long)0x01) << 14;
+  /* insert RFTA value */
+  tmp |= ((unsigned long)(trc_clocks - 4)) << 2;
+  /* insert RCD value */
+  tmp |= ((unsigned long)(trcd_clocks - 1)) << 0;
+
+#ifdef SDRAM_DEBUG
+  serial_puts("sdtr: ");
+  write_4hex(tmp);
+  serial_puts("\n");
+#endif
+
+  /* write SDRAM timing register */
+  mtdcr(memcfga,mem_sdtr1);
+  mtdcr(memcfgd,tmp);
+       baseaddr=CFG_SDRAM_BASE;
+  bank_size = (((unsigned long)density) << 22) / 2;
+  /* insert AM value */
+  tmp = ((unsigned long)t->mode-1) << 13;
+  /* insert SZ value; */
+  switch (bank_size) {
+    case 0x00400000: tmp |= ((unsigned long)0x00) << 17; break;
+    case 0x00800000: tmp |= ((unsigned long)0x01) << 17; break;
+    case 0x01000000: tmp |= ((unsigned long)0x02) << 17; break;
+    case 0x02000000: tmp |= ((unsigned long)0x03) << 17; break;
+    case 0x04000000: tmp |= ((unsigned long)0x04) << 17; break;
+    case 0x08000000: tmp |= ((unsigned long)0x05) << 17; break;
+    case 0x10000000: tmp |= ((unsigned long)0x06) << 17; break;
+    default: SDRAM_err("unsupported SDRAM");
+  } /* endswitch */
+  /* get SDRAM bank 0 register */
+  mtdcr(memcfga,mem_mb0cf);
+  bank = mfdcr(memcfgd) & ~0xFFCEE001;
+  bank |= (baseaddr | tmp | 0x01);
+#ifdef SDRAM_DEBUG
+  serial_puts("bank0: baseaddr: ");
+       write_4hex(baseaddr);
+  serial_puts(" banksize: ");
+       write_4hex(bank_size);
+  serial_puts(" mb0cf: ");
+       write_4hex(bank);
+  serial_puts("\n");
+#endif
+  baseaddr += bank_size;
+  sdram_size += bank_size;
+
+  /* write SDRAM bank 0 register */
+  mtdcr(memcfga,mem_mb0cf);
+  mtdcr(memcfgd,bank);
+
+  /* get SDRAM bank 1 register */
+  mtdcr(memcfga,mem_mb1cf);
+  bank = mfdcr(memcfgd) & ~0xFFCEE001;
+       sdram_size=0;
+
+#ifdef SDRAM_DEBUG
+  serial_puts("bank1: baseaddr: ");
+       write_4hex(baseaddr);
+  serial_puts(" banksize: ");
+       write_4hex(bank_size);
+#endif
+  if (banks == 2) {
+    bank |= (baseaddr | tmp | 0x01);
+    baseaddr += bank_size;
+    sdram_size += bank_size;
+  } /* endif */
+#ifdef SDRAM_DEBUG
+  serial_puts(" mb1cf: ");
+       write_4hex(bank);
+  serial_puts("\n");
+#endif
+  /* write SDRAM bank 1 register */
+  mtdcr(memcfga,mem_mb1cf);
+  mtdcr(memcfgd,bank);
+
+  /* get SDRAM bank 2 register */
+  mtdcr(memcfga,mem_mb2cf);
+  bank = mfdcr(memcfgd) & ~0xFFCEE001;
+  
+  bank |= (baseaddr | tmp | 0x01);
+
+#ifdef SDRAM_DEBUG
+  serial_puts("bank2: baseaddr: ");
+       write_4hex(baseaddr);
+  serial_puts(" banksize: ");
+       write_4hex(bank_size);
+  serial_puts(" mb2cf: ");
+       write_4hex(bank);
+  serial_puts("\n");
+#endif
+
+  baseaddr += bank_size;
+  sdram_size += bank_size;
+
+  /* write SDRAM bank 2 register */
+  mtdcr(memcfga,mem_mb2cf);
+  mtdcr(memcfgd,bank);
+
+  /* get SDRAM bank 3 register */
+  mtdcr(memcfga,mem_mb3cf);
+  bank = mfdcr(memcfgd) & ~0xFFCEE001;
+
+#ifdef SDRAM_DEBUG
+  serial_puts("bank3: baseaddr: ");
+       write_4hex(baseaddr);
+  serial_puts(" banksize: ");
+       write_4hex(bank_size);
+#endif
+
+  if (banks == 2) {
+    bank |= (baseaddr | tmp | 0x01);
+    baseaddr += bank_size;
+    sdram_size += bank_size;
+  } /* endif */
+
+#ifdef SDRAM_DEBUG
+  serial_puts(" mb3cf: ");
+       write_4hex(bank);
+  serial_puts("\n");
+#endif
+
+  /* write SDRAM bank 3 register */
+  mtdcr(memcfga,mem_mb3cf);
+  mtdcr(memcfgd,bank);
+
+
+  /* get SDRAM refresh interval register */
+  mtdcr(memcfga,mem_rtr);
+  tmp = mfdcr(memcfgd) & ~0x3FF80000;
+
+  if (tmemclk < NSto10PS(16))
+    tmp |= 0x05F00000;
+  else
+    tmp |= 0x03F80000;
+
+  /* write SDRAM refresh interval register */
+  mtdcr(memcfga,mem_rtr);
+  mtdcr(memcfgd,tmp);
+
+  /* enable SDRAM controller with no ECC, 32-bit SDRAM width, 16 byte burst */
+  mtdcr(memcfga,mem_mcopt1);
+  tmp = (mfdcr(memcfgd) &  ~0xFFE00000) | 0x80E00000;
+  mtdcr(memcfga,mem_mcopt1);
+  mtdcr(memcfgd,tmp);
+
+
+  
+   /*-------------------------------------------------------------------------+
+   | Interrupt controller setup for the PIP405 board.
+   | Note: IRQ 0-15  405GP internally generated; active high; level sensitive
+   |       IRQ 16    405GP internally generated; active low; level sensitive
+   |       IRQ 17-24 RESERVED
+   |       IRQ 25 (EXT IRQ 0) SouthBridg; active low; level sensitive
+   |       IRQ 26 (EXT IRQ 1) NMI: active low; level sensitive
+   |       IRQ 27 (EXT IRQ 2) SMI: active Low; level sensitive                          
+   |       IRQ 28 (EXT IRQ 3) PCI SLOT 3; active low; level sensitive
+   |       IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive
+   |       IRQ 30 (EXT IRQ 5) PCI SLOT 1; active low; level sensitive
+   |       IRQ 31 (EXT IRQ 6) PCI SLOT 0; active low; level sensitive
+   | Note for PIP405 board:
+   |       An interrupt taken for the SouthBridge (IRQ 25) indicates that   
+   |       the Interrupt Controller in the South Bridge has caused the 
+   |       interrupt. The IC must be read to determine which device
+   |       caused the interrupt.
+   |          
+   +-------------------------------------------------------------------------*/
+  mtdcr(uicsr, 0xFFFFFFFF);        /* clear all ints */
+  mtdcr(uicer, 0x00000000);        /* disable all ints */
+  mtdcr(uiccr, 0x00000000);        /* set all to be non-critical (for now)*/
+  mtdcr(uicpr, 0xFFFFFF80);        /* set int polarities */
+  mtdcr(uictr, 0x10000000);        /* set int trigger levels */
+  mtdcr(uicvcr, 0x00000001);       /* set vect base=0,INT0 highest priority*/
+  mtdcr(uicsr, 0xFFFFFFFF);        /* clear all ints */
+
+  return 0;
+}
+
+
+/* ------------------------------------------------------------------------- */
+#define I2C_BACKUP_ADDR 0x7C00 /* 0x200 bytes for backup */
+
+void get_backup_values(backup_t *buf)
+{
+       eeprom_read (CFG_DEF_EEPROM_ADDR,
+                    I2C_BACKUP_ADDR,
+                    (void *)buf,
+                    sizeof(backup_t));
+}
+
+void set_backup_values(int overwrite)
+{
+       backup_t back;
+       int i;
+
+       get_backup_values(&back);
+       if(!overwrite) {
+               if(strncmp(back.signature,"MPL\0",4)==0) {
+                       printf("Not possible to write Backup\n");
+                       return;
+               }
+       }
+       memcpy(back.signature,"MPL\0",4);
+       i=getenv_r("serial#",back.serial_name,16);
+       if(i==0) {
+               printf("Not possible to write Backup\n");
+               return;
+       }
+       back.serial_name[16]=0;
+       i=getenv_r("ethaddr",back.eth_addr,20);
+       if(i==0) {
+               printf("Not possible to write Backup\n");
+               return;
+       }
+       back.eth_addr[20]=0;
+       eeprom_write (CFG_DEF_EEPROM_ADDR,
+                     CFG_ENV_OFFSET+I2C_BACKUP_ADDR,
+                     (void *)&back,
+                     sizeof(backup_t));
+}
+
+
+/*
+ * Check Board Identity:
+ */
+
+int checkboard (void)
+{
+    unsigned char s[50];
+       unsigned char bc;
+       int i;
+       backup_t *b=(backup_t *)s;
+       
+       i=getenv_r("serial#",s,32);
+    if ((i==0) || strncmp(s, "PIP405", 6)) {
+       get_backup_values(b);
+               if(strncmp(b->signature,"MPL\0",4)!=0) {
+                       printf("### No HW ID - assuming PIP405");
+               }
+               else {
+                       b->serial_name[6]=0;
+               printf("%s SN: %s",b->serial_name,&b->serial_name[7]);
+               }
+    }
+    else {
+       s[6]=0;
+       printf("%s SN: %s",s,&s[7]);
+       }
+       bc=in8(CONFIG_PORT_ADDR);
+       printf(" Boot Config: 0x%x\n",bc);
+    return (0);
+}
+
+
+/* ------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+/*
+  initdram(int board_type) reads EEPROM via I2c. EEPROM contains all of  
+  the necessary info for SDRAM controller configuration
+*/
+/* ------------------------------------------------------------------------- */
+/* ------------------------------------------------------------------------- */
+int testdram (unsigned long ramsize);
+
+long int initdram (int board_type)
+{
+     
+  unsigned long bank_reg[4],tmp,bank_size;
+       int i,ds;
+  unsigned long TotalSize;
+
+       ds=0;
+       /* since the DRAM controller is allready set up, calculate the size with the 
+         bank registers         */
+       mtdcr(memcfga,mem_mb0cf);
+  bank_reg[0] = mfdcr(memcfgd);
+       mtdcr(memcfga,mem_mb1cf);
+  bank_reg[1] = mfdcr(memcfgd);
+       mtdcr(memcfga,mem_mb2cf);
+  bank_reg[2] = mfdcr(memcfgd);
+       mtdcr(memcfga,mem_mb3cf);
+  bank_reg[3] = mfdcr(memcfgd);
+  TotalSize=0;
+       for(i=0;i<4;i++)
+       {
+               if((bank_reg[i]&0x1)==0x1)
+               {
+                       tmp=(bank_reg[i]>>17)&0x7;
+                       bank_size=4<<tmp;
+                       TotalSize+=bank_size;
+               }
+               else
+                       ds=1;
+       }
+       if(ds==1)
+      printf("single-sided DIMM ");
+  else
+    printf("double-sided DIMM ");
+  testdram(TotalSize*1024*1024);
+       /* bank 2 (SDRAM Clock 2) is not usable if 133MHz SDRAM IF */
+       if(get_gclk_freq()>220000000)
+               TotalSize/=2; 
+  return (TotalSize*1024*1024);
+}
+
+/* ------------------------------------------------------------------------- */
+
+
+int testdram (unsigned long ramsize)
+{
+       /* not yet implemented */
+               return(1);
+}
+
+/* ------------------------------------------------------------------------- */
+
+       /* switches the cs0 and the cs1 to the locations. 
+          When boot is TRUE, the the mapping is switched 
+          to the boot configuration, If it is FALSE, the
+          flash will be switched in the boot area */
+
+
+#undef SW_CS_DBG
+#ifdef SW_CS_DBG
+#define        SW_CS_PRINTF(fmt,args...)       printf (fmt ,##args)
+#else
+#define SW_CS_PRINTF(fmt,args...)
+#endif
+
+
+int switch_cs(unsigned char boot)
+{
+       unsigned long pbcr;
+       mtdcr(ebccfga, pb0cr); /* get cs0 config reg */
+       pbcr = mfdcr(ebccfgd);
+       if((pbcr&0x00002000)==0) {  
+               /* we need only to switch if boot from MPS */
+               SW_CS_PRINTF(" MPS boot mode detected. "); 
+               /* printf("cs0 cfg: %lx\n",pbcr); */
+               if(boot==TRUE) { 
+                       /* switch to boot configuration */
+                       /* this is a 8bit boot, switch cs0 to flash location */
+                       SW_CS_PRINTF("switch to boot mode (MPS on High address\n");  
+                       pbcr&=0x000FFFFF; /*mask base address of the cs0 */
+                       pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000);
+                       mtdcr(ebccfga, pb0cr);
+                       mtdcr(ebccfgd, pbcr);
+                       SW_CS_PRINTF("  new cs0 cfg: %lx\n",pbcr); 
+                       mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */
+                       pbcr = mfdcr(ebccfgd);
+                       SW_CS_PRINTF(" old cs1 cfg: %lx\n",pbcr); 
+                       pbcr&=0x000FFFFF; /*mask base address of the cs1 */
+                       pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000);
+                       mtdcr(ebccfga, pb1cr);
+                       mtdcr(ebccfgd, pbcr);
+                       SW_CS_PRINTF("  new cs1 cfg: %lx, MPS is on High Address\n",pbcr); 
+               }
+               else 
+               { 
+                       /* map flash to boot area, */
+                       SW_CS_PRINTF("map Flash to boot area\n"); 
+                       pbcr&=0x000FFFFF; /*mask base address of the cs0 */
+                       pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000);
+                       mtdcr(ebccfga, pb0cr);
+                       mtdcr(ebccfgd, pbcr);
+                       SW_CS_PRINTF("  new cs0 cfg: %lx\n",pbcr); 
+                       mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */
+                       pbcr = mfdcr(ebccfgd);
+                       SW_CS_PRINTF("  cs1 cfg: %lx\n",pbcr); 
+                       pbcr&=0x000FFFFF; /*mask base address of the cs1 */
+                       pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000);
+                       mtdcr(ebccfga, pb1cr);
+                       mtdcr(ebccfgd, pbcr);
+                       SW_CS_PRINTF("  new cs1 cfg: %lx Flash is on High Address\n",pbcr); 
+               }
+               return TRUE;
+       }
+       else {
+               SW_CS_PRINTF("Normal boot, no switching necessary\n"); 
+               return FALSE;
+       }
+}
+
+void misc_init_r(bd_t *bd)
+{
+       unsigned char bc;
+       char buf[128];
+       unsigned char *s;
+       
+       bc=in8(CONFIG_PORT_ADDR);
+       bc>>=4;
+       bc &= 0x0f;
+       sprintf(buf,"bootcmd%d",bc);
+       s = getenv(buf);
+       if(s) {
+               sprintf(buf,"%s",s);
+               setenv("bootcmd",buf);
+       }
+       sprintf(buf,"bootargs%d",bc);
+       s = getenv(buf);
+       if(s) {
+               sprintf(buf,"%s",s);
+               setenv("bootargs",buf);
+       }
+}
+
+/***************************************************************************
+ * some helping routines
+ */
+
+int overwrite_console(void)
+{
+       return(in8(CONFIG_PORT_ADDR) & 0x1); /* return TRUE if console should be overwritten */
+}
+
+
+void set_init_backup(void)
+{
+    unsigned char *s;
+       char buf[32];
+       backup_t back;
+
+       s=getenv("serial#");
+       if(!s) {
+               get_backup_values(&back);
+               if(strncmp(back.signature,"MPL\0",4)==0) {
+                       sprintf(buf,"%s",back.serial_name);
+                       setenv("serial#",buf);
+                       sprintf(buf,"%s",back.eth_addr);
+                       setenv("ethaddr",buf);
+                       printf("INFO:  serial# and ethaddr recovered, use saveenv\n");
+               }
+       }
+       else {
+               /* check if back up is set */
+               get_backup_values(&back);
+               if(strncmp(back.signature,"MPL\0",4)!=0) {
+                       set_backup_values(0);
+               }               
+       }
+}
+
+extern int isa_init(void);
+
+
+void print_pip405_rev(void)
+{
+       unsigned char part,vers,cfg;
+       part=in8(PLD_PART_REG); 
+       vers=in8(PLD_VERS_REG); 
+       cfg=in8(PLD_BOARD_CFG_REG);
+       printf("Rev:   PIP405-%d Rev %c PLD%d %d PLD%d %d\n",16-((cfg>>4)&0xf),(cfg&0xf)+'A',
+               part&0xf,vers&0xf,(part>>4)&0xf,(vers>>4)&0xf);
+}
+
+extern device_t *stdio_devices[];
+extern char *stdio_names[];
+
+void show_stdio_dev(void)
+{
+       /* Print informations */
+       printf ("In:    ");
+       if (stdio_devices[stdin] == NULL) {
+               printf ("No input devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stdin]->name);
+       }
+
+       printf ("Out:   ");
+       if (stdio_devices[stdout] == NULL) {
+               printf ("No output devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stdout]->name);
+       }
+
+       printf ("Err:   ");
+       if (stdio_devices[stderr] == NULL) {
+               printf ("No error devices available!\n");
+       } else {
+               printf ("%s\n", stdio_devices[stderr]->name);
+       }
+}
+
+
+
+int last_stage_init(void)
+{
+       print_pip405_rev();
+       set_init_backup();
+       isa_init();
+       show_stdio_dev();
+       return 0;
+}
+
+/************************************************************************
+* Print PIP405 Info
+************************************************************************/
+void print_pip405_info(void)
+{
+       unsigned char part,vers,cfg,ledu,sysman,flashcom,can,serpwr,compwr,nicvga,scsirst;
+
+       part=in8(PLD_PART_REG); 
+       vers=in8(PLD_VERS_REG); 
+       cfg=in8(PLD_BOARD_CFG_REG);
+       ledu=in8(PLD_LED_USER_REG);
+       sysman=in8(PLD_SYS_MAN_REG);
+       flashcom=in8(PLD_FLASH_COM_REG);
+       can=in8(PLD_CAN_REG);
+       serpwr=in8(PLD_SER_PWR_REG);
+       compwr=in8(PLD_COM_PWR_REG);
+       nicvga=in8(PLD_NIC_VGA_REG);
+       scsirst=in8(PLD_SCSI_RST_REG);
+       printf("PLD Part %d version %d\n",part&0xf,vers&0xf);
+       printf("PLD Part %d version %d\n",(part>>4)&0xf,(vers>>4)&0xf);
+       printf("Board Revision %c\n",(cfg&0xf)+'A');
+       printf("Population Options %d %d %d %d\n",(cfg>>4)&0x1,(cfg>>5)&0x1,(cfg>>6)&0x1,(cfg>>7)&0x1);
+       printf("User LED0 %s User LED1 %s\n",((ledu&0x1)==0x1) ? "on" : "off",((ledu&0x2)==0x2) ? "on" : "off");
+       printf("Additionally Options %d %d\n",(ledu>>2)&0x1,(ledu>>3)&0x1);
+       printf("User Config Switch %d %d %d %d\n",(ledu>>4)&0x1,(ledu>>5)&0x1,(ledu>>6)&0x1,(ledu>>7)&0x1);
+       switch(sysman&0x3)
+       {
+               case 0: printf("PCI Clocks are running\n"); break;
+               case 1: printf("PCI Clocks are stopped in POS State\n"); break;
+               case 2: printf("PCI Clocks are stopped when PCI_STP# is asserted\n"); break;
+               case 3: printf("PCI Clocks are stopped\n"); break;
+       }
+       switch((sysman>>2)&0x3)
+       {
+               case 0: printf("Main Clocks are running\n"); break;
+               case 1: printf("Main Clocks are stopped in POS State\n"); break;
+               case 2: 
+               case 3: printf("PCI Clocks are stopped\n"); break;
+       }
+       printf("INIT asserts %sINT2# (SMI)\n",((sysman&0x10)==0x10) ? "" : "not ");
+       printf("INIT asserts %sINT1# (NMI)\n",((sysman&0x20)==0x20) ? "" : "not ");
+       printf("INIT occured %d\n",(sysman>>6)&0x1);
+       printf("SER1 is routed to %s\n",((flashcom&0x1)==0x1) ? "RS485" : "RS232");
+       printf("COM2 is routed to %s\n",((flashcom&0x2)==0x2) ? "RS485" : "RS232");
+       printf("RS485 is configured as %s duplex\n",((flashcom&0x4)==0x4) ? "full" : "half");
+       printf("RS485 is connected to %s\n",((flashcom&0x8)==0x8) ? "COM1" : "COM2");
+       printf("SER1 uses handshakes %s\n",((flashcom&0x10)==0x10) ? "DTR/DSR" : "RTS/CTS");
+       printf("Bootflash is %swriteprotected\n",((flashcom&0x20)==0x20) ? "not " : "");
+       printf("Bootflash VPP is %s\n",((flashcom&0x40)==0x40) ? "on" : "off");
+       printf("Bootsector is %swriteprotected\n",((flashcom&0x80)==0x80) ? "not " : "");
+       switch((can)&0x3)
+       {
+               case 0: printf("CAN Controller is on address 0x1000..0x10FF\n"); break;
+               case 1: printf("CAN Controller is on address 0x8000..0x80FF\n"); break;
+               case 2: printf("CAN Controller is on address 0xE000..0xE0FF\n"); break;
+               case 3: printf("CAN Controller is disabled\n"); break;
+       }
+       switch((can>>2)&0x3)
+       {
+               case 0: printf("CAN Controller Reset is ISA Reset\n"); break;
+               case 1: printf("CAN Controller Reset is ISA Reset and POS State\n"); break;
+               case 2: 
+               case 3: printf("CAN Controller is in reset\n"); break;
+       }
+       if(((can>>4)<3)||((can>>4)==8)||((can>>4)==13))
+               printf("CAN Interrupt is disabled\n");
+       else
+               printf("CAN Interrupt is ISA INT%d\n",(can>>4)&0xf);
+       switch(serpwr&0x3)
+       {
+               case 0: printf("SER0 Drivers are enabled\n"); break;
+               case 1: printf("SER0 Drivers are disabled in the POS state\n"); break;
+               case 2: 
+               case 3: printf("SER0 Drivers are disabled\n"); break;
+       }
+       switch((serpwr>>2)&0x3)
+       {
+               case 0: printf("SER1 Drivers are enabled\n"); break;
+               case 1: printf("SER1 Drivers are disabled in the POS state\n"); break;
+               case 2: 
+               case 3: printf("SER1 Drivers are disabled\n"); break;
+       }
+       switch(compwr&0x3)
+       {
+               case 0: printf("COM1 Drivers are enabled\n"); break;
+               case 1: printf("COM1 Drivers are disabled in the POS state\n"); break;
+               case 2: 
+               case 3: printf("COM1 Drivers are disabled\n"); break;
+       }
+       switch((compwr>>2)&0x3)
+       {
+               case 0: printf("COM2 Drivers are enabled\n"); break;
+               case 1: printf("COM2 Drivers are disabled in the POS state\n"); break;
+               case 2: 
+               case 3: printf("COM2 Drivers are disabled\n"); break;
+       }
+       switch((nicvga)&0x3)
+       {
+               case 0: printf("PHY is running\n"); break;
+               case 1: printf("PHY is in Power save mode in POS state\n"); break;
+               case 2: 
+               case 3: printf("PHY is in Power save mode\n"); break;
+       }
+       switch((nicvga>>2)&0x3)
+       {
+               case 0: printf("VGA is running\n"); break;
+               case 1: printf("VGA is in Power save mode in POS state\n"); break;
+               case 2: 
+               case 3: printf("VGA is in Power save mode\n"); break;
+       }
+       printf("PHY is %sreseted\n",((nicvga&0x10)==0x10)?"":"not ");
+       printf("VGA is %sreseted\n",((nicvga&0x20)==0x20)?"":"not ");
+       printf("Reserved Configuration is %d %d\n",(nicvga>>6)&0x1,(nicvga>>7)&0x1);
+       switch((scsirst)&0x3)
+       {
+               case 0: printf("SCSI Controller is running\n"); break;
+               case 1: printf("SCSI Controller is in Power save mode in POS state\n"); break;
+               case 2: 
+               case 3: printf("SCSI Controller is in Power save mode\n"); break;
+       }
+       printf("SCSI termination is %s\n",((scsirst&0x4)==0x4)?"disabled":"enabled");
+       printf("SCSI Controller is %sreseted\n",((scsirst&0x10)==0x10)?"":"not ");
+       printf("IDE disks are %sreseted\n",((scsirst&0x20)==0x20)?"":"not ");
+       printf("ISA Bus is %sreseted\n",((scsirst&0x40)==0x40)?"":"not ");
+       printf("Super IO is %sreseted\n",((scsirst&0x80)==0x80)?"":"not ");
+}
+
+void user_led0(unsigned char on)
+{
+       if(on==TRUE)
+               out8(PLD_LED_USER_REG,(in8(PLD_LED_USER_REG)|0x1));
+       else
+               out8(PLD_LED_USER_REG,(in8(PLD_LED_USER_REG)&0xfe));
+}
+
+void user_led1(unsigned char on)
+{
+       if(on==TRUE)
+               out8(PLD_LED_USER_REG,(in8(PLD_LED_USER_REG)|0x2));
+       else
+               out8(PLD_LED_USER_REG,(in8(PLD_LED_USER_REG)&0xfd));
+}
+
+void ide_set_reset(int idereset)
+{
+       /* if reset = 1 IDE reset will be asserted */
+       unsigned char resreg;
+       resreg=in8(PLD_SCSI_RST_REG);
+       if(idereset==1)
+               resreg|=0x20;
+       else
+               resreg&=0xdf;
+       out8(PLD_SCSI_RST_REG,resreg); 
+}
+
+
+/******************************************************
+ * Routines to display the Board information 
+ * to the screen (since the VGA will be initialized as last,
+ * we must resend the infos)
+ */
+
+void video_put_dev_string(block_dev_desc_t *dev_desc)
+{
+       char buf[80];
+       ldiv_t mb,gb;
+       unsigned long lba512; /* number of blocks if 512bytes block size */
+
+       if(dev_desc->type!=DEV_TYPE_UNKNOWN) {
+               if(dev_desc->if_type==IF_TYPE_SCSI)
+                       sprintf(buf,"SCSI %d:  (%d:%d) ",dev_desc->dev,dev_desc->target,dev_desc->lun);
+               else
+                       sprintf(buf,"IDE %d:   ",dev_desc->dev);
+               video_puts(buf);
+               switch(dev_desc->type & 0x1F) {
+                       case DEV_TYPE_HARDDISK: video_puts("Hard Disk"); break;
+                       case DEV_TYPE_CDROM:            video_puts("CD ROM"); break;
+                       case DEV_TYPE_OPDISK:   video_puts("Optical Device"); break;
+                       case DEV_TYPE_TAPE:             video_puts("Tape"); break;
+                       default:                                                        video_puts("unknown"); break;
+               }
+               video_puts(" ");
+               video_puts(dev_desc->vendor);
+               video_puts(" ");
+               if(dev_desc->if_type!=IF_TYPE_IDE)
+                       video_puts(dev_desc->product);
+       
+               if((dev_desc->lba * dev_desc->blksz)>0L) {
+                       lba512=(dev_desc->lba * (dev_desc->blksz/512));
+                       mb = ldiv(lba512, 2048); /* (1024 *1024 / 512 MB */
+                       /* we do NOT round, because if we round 0.95MByte up, we get 0.10MByte !!*/
+                       mb.rem *= 10;
+                       mb.rem /= 2048;
+                       gb = ldiv(10 * mb.quot + mb.rem, 10240);
+                       gb.rem += 512;
+                       gb.rem /= 1024;
+                       printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%ld x %ld)\n",
+                               mb.quot, mb.rem,
+                               gb.quot, gb.rem,
+                               dev_desc->lba,
+                               dev_desc->blksz);
+               }
+               else {
+                       sprintf (buf," Capacity: not available\n");
+               }
+               video_puts(buf);
+       }
+} 
+
+void video_write_board_info(void)
+{
+       extern char version_string[];
+       unsigned long pvr = get_pvr();
+       char buf[32],tmpbuf[80];
+       PPC405_SYS_INFO sys_info;
+       init_data_t *idata = (init_data_t *)(CFG_INIT_RAM_ADDR + CFG_INIT_DATA_OFFSET);
+       unsigned char *s = getenv("serial#");
+       unsigned char *e;
+       unsigned char bc;
+       
+       /* first write PPCBOOT Info */
+       video_puts("\n");
+       video_puts(version_string);
+       video_puts("\n\n");
+       /* then CPU and board infos */
+       get_sys_info(&sys_info);
+       video_puts("CPU:   IBM PowerPC 405GP Rev. ");
+       switch (pvr) {
+       case PVR_405GP_RB: video_putc('B'); break;
+       case PVR_405GP_RC: video_putc('C'); break;
+       case PVR_405GP_RD: video_putc('D'); break;
+       case PVR_405GP_RE: video_putc('E'); break;
+       default: video_puts("unknown"); break;
+       }
+       sprintf(tmpbuf," at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf,idata->cpu_clk),
+         sys_info.freqPLB / 1000000,
+         sys_info.freqPLB / sys_info.pllOpbDiv / 1000000,
+         sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000);
+       video_puts(tmpbuf);
+       if (mfdcr(strap) & PSR_PCI_ASYNC_EN)
+       video_puts("       PCI async ext clock used, ");
+       else {
+               sprintf(buf,"       PCI sync clock at %lu MHz, ", sys_info.freqPLB / sys_info.pllPciDiv / 1000000);
+       video_puts(buf);
+       }
+       if (mfdcr(strap) & PSR_PCI_ARBIT_EN)
+       video_puts("internal PCI arbiter enabled\n");
+       else
+       video_puts("external PCI arbiter enabled\n");
+       video_puts("       16 kB I-Cache 8 kB D-Cache\n");
+       /* now some board infos */
+       video_puts("Board: ");
+       if (!s || strncmp(s, "PIP405", 6)) {
+               bc=video_set_attr(VGA_ATTR_CLR_RED | VGA_ATTR_ITN);
+               video_puts("### No HW ID - assuming PIP405");
+  }
+  else {
+       bc=video_set_attr(VGA_ATTR_CLR_GRN);
+       for (e=s; *e; ++e) {
+       if (*e == ' ')
+               break;
+    }
+    for ( ; s<e; ++s) {
+       if(*s=='_') {
+                               ++s;
+                               break;
+                       }
+                       video_putc (*s);
+               }
+               video_puts("  Serial No.: ");
+    for ( ; s<e; ++s) {
+                       video_putc (*s);
+               }
+       }
+       video_set_attr(bc);
+       bc=in8(CONFIG_PORT_ADDR);
+       sprintf(buf," Boot Config 0x%02X\n",bc);
+       video_puts(buf);
+       /* DRAM size    */
+       video_puts("DRAM:  ");
+       sprintf(buf,"%lu MBytes\n",bd_ptr->bi_memsize/0x100000);
+       video_puts(buf);
+       /* flash size: */
+       video_puts("FLASH: ");
+       if(switch_cs(0)==0) {
+               bc=video_set_attr(VGA_ATTR_CLR_GRN);
+               video_puts("(Flash boot)");
+               video_set_attr(bc);
+       }
+       else {
+               bc=video_set_attr(VGA_ATTR_CLR_RED | VGA_ATTR_ITN);
+               video_puts("(Multi Purpose Socket boot)");
+               video_set_attr(bc);
+       }
+       sprintf(buf," %lu MBytes\n",bd_ptr->bi_flashsize/0x100000);
+       video_puts(buf);
+}
+
+
+
+
+
+
diff --git a/board/mpl/pip405/pip405.h b/board/mpl/pip405/pip405.h
new file mode 100644 (file)
index 0000000..7adfcef
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
+ *
+ * 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
+ *
+ */
+ /****************************************************************************
+ * Global routines used for PIP405
+ *****************************************************************************/
+int switch_cs(unsigned char boot);
+
+extern int  mem_test(unsigned long start, unsigned long ramsize,int mode); 
+
+void print_pip405_info(void);
+
+void user_led0(unsigned char on);
+void user_led1(unsigned char on);
+
+typedef struct {
+       char signature[4];
+       char serial_name[17];   /* "PIP405_1000xxxxx" */
+       char eth_addr[21];                      /* "00:60:C2:08:00:00" */
+} backup_t;
+
+void get_backup_values(backup_t *buf);
+void set_backup_values(int overwrite);
+
+#define PLD_BASE_ADDRESS               CFG_ISA_IO_BASE_ADDRESS + 0x800
+#define PLD_PART_REG                           PLD_BASE_ADDRESS + 0
+#define PLD_VERS_REG                           PLD_BASE_ADDRESS + 1
+#define PLD_BOARD_CFG_REG              PLD_BASE_ADDRESS + 2
+#define PLD_LED_USER_REG               PLD_BASE_ADDRESS + 3
+#define PLD_SYS_MAN_REG                        PLD_BASE_ADDRESS + 4
+#define PLD_FLASH_COM_REG              PLD_BASE_ADDRESS + 5
+#define PLD_CAN_REG                                    PLD_BASE_ADDRESS + 6
+#define PLD_SER_PWR_REG                        PLD_BASE_ADDRESS + 7
+#define PLD_COM_PWR_REG                        PLD_BASE_ADDRESS + 8
+#define PLD_NIC_VGA_REG                        PLD_BASE_ADDRESS + 9
+#define PLD_SCSI_RST_REG               PLD_BASE_ADDRESS + 0xA
+
+#define PIIX4_VENDOR_ID                        0x8086
+#define PIIX4_IDE_DEV_ID               0x7111
+
+
diff --git a/board/mpl/pip405/ppcboot.lds b/board/mpl/pip405/ppcboot.lds
new file mode 100644 (file)
index 0000000..c260b18
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * (C) Copyright 2000, 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
+{
+  .resetvec 0xFFFFFFFC :
+  {
+    *(.resetvec)
+  } = 0xffff
+
+  /* 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      :
+  {
+    /* WARNING - the following is hand-optimized to fit within */
+    /* the sector layout of our flash chips!   XXX FIXME XXX   */
+
+    cpu/ppc4xx/start.o (.text)
+    board/mpl/pip405/init.o    (.text)
+    cpu/ppc4xx/kgdb.o  (.text)
+    cpu/ppc4xx/traps.o (.text)
+    cpu/ppc4xx/interrupts.o    (.text)
+    cpu/ppc4xx/serial.o        (.text)
+    cpu/ppc4xx/cpu_init.o      (.text)
+    cpu/ppc4xx/speed.o (.text)
+    cpu/ppc4xx/405gp_enet.o    (.text)
+    common/dlmalloc.o  (.text)
+    ppc/crc32.o                (.text)
+    ppc/extable.o      (.text)
+    ppc/zlib.o         (.text)
+
+/*    . = env_offset;*/
+/*    common/environment.o(.text)*/
+
+    *(.text)
+    *(.fixup)
+    *(.got1)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(.rodata)
+    *(.rodata1)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x00FF) & 0xFFFFFF00;
+  _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(256);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(256);
+  __init_end = .;
+
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+}
diff --git a/board/mpl/pip405/ppcboot.lds.debug b/board/mpl/pip405/ppcboot.lds.debug
new file mode 100644 (file)
index 0000000..b8ec990
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * (C) Copyright 2000, 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      :
+  {
+    /* WARNING - the following is hand-optimized to fit within */
+    /* the sector layout of our flash chips!   XXX FIXME XXX   */
+
+    mpc8xx/start.o     (.text)
+    common/dlmalloc.o  (.text)
+    ppc/vsprintf.o     (.text)
+    ppc/crc32.o                (.text)
+    ppc/extable.o      (.text)
+
+    common/environment.o(.text)
+
+    *(.text)
+    *(.fixup)
+    *(.got1)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(.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 = .);
+}
+
index ffbda63b8c2f35ffd7f65b8e6c835a4763da581b..6c32caa114db237594a94254a736c5f89414fcd8 100644 (file)
@@ -36,6 +36,7 @@ COBJS = board.o main.o command.o environment.o bedbug.o \
          cmd_nvedit.o cmd_pcmcia.o \
          cmd_reginfo.o cmd_scsi.o \
          console.o devices.o dlmalloc.o \
+         usb.o usb_storage.o usb_kbd.o cmd_usb.o \
          flash.o hush.o kgdb.o \
          lists.o miiphybb.o miiphyutil.o \
          s_record.o
index de3bf8d36de687ad16898912bc54281bb3037f23..f1603dfaebf05c9832c1d1cfe259bdadda34112a 100644 (file)
@@ -176,7 +176,6 @@ board_init_f (ulong bootflag)
     defined(CONFIG_LWMON)     || \
     defined(CONFIG_MPC8260ADS)|| \
     defined(CONFIG_OCRTC)     || \
-    defined(CONFIG_PIP405)    || \
     defined(CONFIG_RPXSUPER)  || \
     defined(CONFIG_WALNUT405) || \
     defined(CONFIG_W7O)
@@ -761,9 +760,20 @@ void    board_init_r  (bd_t *bd, ulong dest_addr)
 
 #if (CONFIG_COMMANDS & CFG_CMD_SCSI)
     WATCHDOG_RESET();
+    puts ("SCSI:  ");
     scsi_init();
 #endif
 
+#ifdef CONFIG_LAST_STAGE_INIT
+    WATCHDOG_RESET();
+    /*
+     * Some parts can be only initialized if all others (like
+     * Interrupts) are up and running (i.e. the PC-style ISA
+     * keyboard).
+     */
+    last_stage_init ();
+#endif
+
 #if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
     WATCHDOG_RESET();
     bedbug_init();
index fd9146c903741ce7c3e5c1092a57fcba743222a0..0b88e9d150bfccbfce3275844cabb5e9bd70728c 100644 (file)
@@ -53,7 +53,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
     
 
 #if !defined(CONFIG_CPCI405) && !defined(CONFIG_AR405) && \
-               !defined(CONFIG_PIP405) && !defined(CONFIG_W7O) && \
+               !defined(CONFIG_I2C405) && !defined(CONFIG_W7O) && \
     !defined (CONFIG_WALNUT405) && !defined (CONFIG_ERIC)
 
     i2c_state_t state;
@@ -71,7 +71,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
        if (strncmp (argv[1], "res", 3) == 0) {
            printf ("I2C reset 50kHz ... ");
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
            i2c_init ();
 #else
@@ -90,7 +90,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
            else
                printf ("I2C reset %dkHz ... ", speed/1000);
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
            i2c_init ();
 #else
@@ -118,7 +118,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                        , i2c_addr, (ulong)data_addr, size);
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
 #else
@@ -127,7 +127,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
                rc = i2c_receive (i2c_addr, size, data_addr);
@@ -145,7 +145,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                }
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
 #else
@@ -170,7 +170,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
 #else
@@ -178,7 +178,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 #endif
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
                rc = i2c_send (i2c_addr, size, data_addr);
@@ -193,7 +193,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                }
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
 #else
@@ -223,7 +223,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                        i2c_addr, sec_addr, (ulong)data_addr, size);
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
 #else
@@ -231,7 +231,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 #endif
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
                rc = i2c_receive (i2c_addr, size, data_addr);
@@ -248,7 +248,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                }
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
 #else
@@ -275,7 +275,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                        i2c_addr, sec_addr, (ulong)data_addr, size);
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
 #else
@@ -283,7 +283,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
 #endif
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
                rc = i2c_send (i2c_addr, size, data_addr);
@@ -299,7 +299,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
                }
 
 #if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
-               defined(CONFIG_PIP405) || defined(CONFIG_W7O) || \
+               defined(CONFIG_I2C405) || defined(CONFIG_W7O) || \
     defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
 
 #else
index 93b393d9478233736651d656a222e282dbf4952d..d46f3c04f2458fa6e8af9a8f0ef3b2ac39c5757c 100644 (file)
@@ -307,7 +307,8 @@ static int check_ide_device (void)
                        ident = p + 4;
                        break;
                case CISTPL_FUNCID:
-                       func_id = *p;
+                       /* Fix for broken SanDisk which may have 0x80 bit set */
+                       func_id = *p & 0x7F;
                        break;
                case CISTPL_FUNCE:
                        if (n_features < MAX_FEATURES)
index 49a131a68cd1f49fef4be68d49db517df8e8ee43..267c6d82a2cb2370065e6d909a6b805c778e71a6 100644 (file)
@@ -101,7 +101,7 @@ void scsi_scan(int mode)
        ccb* pccb=(ccb *)&tempccb;
 
        if(mode==1) {
-               printf("SCSI: scanning bus for devices...\n");
+               printf("scanning bus for devices...\n");
        }
        for(i=0;i<CFG_SCSI_MAX_DEVICE;i++) {
                scsi_dev_desc[i].target=0xff;
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
new file mode 100644 (file)
index 0000000..ce432bd
--- /dev/null
@@ -0,0 +1,593 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * Most of this source has been derived from the Linux USB
+ * project.
+ *
+ * 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 <command.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_USB)
+
+#include <usb.h>
+#include <cmd_disk.h>
+
+#undef CMD_USB_DEBUG
+
+#ifdef CMD_USB_DEBUG
+#define        CMD_USB_PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define CMD_USB_PRINTF(fmt,args...)
+#endif
+static int usb_stor_curr_dev=-1; /* current device */
+
+/* somme display routines (info command) */
+char * usb_get_class_desc(unsigned char dclass)
+{
+       switch(dclass) {
+               case USB_CLASS_PER_INTERFACE: 
+                       return("See Interface"); 
+               case USB_CLASS_AUDIO: 
+                       return("Audio");
+               case USB_CLASS_COMM: 
+                       return("Communication");
+               case USB_CLASS_HID: 
+                       return("Human Interface");
+               case USB_CLASS_PRINTER: 
+                       return("Printer");
+               case USB_CLASS_MASS_STORAGE: 
+                       return("Mass Storage");
+               case USB_CLASS_HUB: 
+                       return("Hub");
+               case USB_CLASS_DATA: 
+                       return("CDC Data");
+               case USB_CLASS_VENDOR_SPEC: 
+                       return("Vendor specific");
+               default : 
+                       return("");
+       }
+}
+
+void usb_display_class_sub(unsigned char dclass,unsigned char subclass,unsigned char proto)
+{
+       switch(dclass) {
+               case USB_CLASS_PER_INTERFACE: 
+                       printf("See Interface");
+                       break; 
+               case USB_CLASS_HID:
+                       printf("Human Interface, Subclass: ");
+                       switch(subclass) {
+                               case USB_SUB_HID_NONE:
+                                       printf("None");
+                                       break;
+                               case USB_SUB_HID_BOOT:
+                                       printf("Boot ");
+                                       switch(proto) {
+                                               case USB_PROT_HID_NONE:
+                                                       printf("None");
+                                                       break;
+                                               case USB_PROT_HID_KEYBOARD:
+                                                       printf("Keyboard");
+                                                       break;
+                                               case USB_PROT_HID_MOUSE:
+                                                       printf("Mouse");
+                                                       break;
+                                               default:
+                                                       printf("reserved");
+                                       }
+                                       break;
+                               default:
+                                       printf("reserved");
+                       }
+                       break;
+               case USB_CLASS_MASS_STORAGE:
+                       printf("Mass Storage, ");
+                       switch(subclass) {
+                               case US_SC_RBC:
+                                       printf("RBC ");
+                                       break;
+                               case US_SC_8020:
+                                       printf("SFF-8020i (ATAPI)");
+                                       break;
+                               case US_SC_QIC:
+                                       printf("QIC-157 (Tape)");
+                                       break;
+                               case US_SC_UFI:
+                                       printf("UFI");
+                                       break;
+                               case US_SC_8070:
+                                       printf("SFF-8070");
+                                       break;
+                               case US_SC_SCSI:
+                                       printf("Transp. SCSI");
+                                       break;
+                               default:
+                                       printf("reserved");
+                                       break;
+                       }
+                       printf(", ");
+                       switch(proto) {
+                               case US_PR_CB:
+                                       printf("Command/Bulk");
+                                       break;
+                               case US_PR_CBI:
+                                       printf("Command/Bulk/Int");
+                                       break;
+                               case US_PR_BULK:
+                                       printf("Bulk only");
+                                       break;
+                               default:
+                                       printf("reserved");
+                       }
+                       break;
+               default:
+                       printf("%s",usb_get_class_desc(dclass));
+       }
+}
+
+void usb_display_string(struct usb_device *dev,int index)
+{
+       char buffer[256];
+       if(index!=0) {
+               if(usb_string(dev,index,&buffer[0],256)>0);
+                       printf("String: \"%s\"",buffer);
+       }
+}
+
+void usb_display_desc(struct usb_device *dev)
+{
+       if(dev->descriptor.bDescriptorType==USB_DT_DEVICE) {
+               printf("%d: %s,  USB Revision %x.%x\n",dev->devnum,usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass),
+                       (dev->descriptor.bcdUSB>>8) & 0xff,dev->descriptor.bcdUSB & 0xff);
+               if(strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
+                       printf(" - %s %s %s\n",dev->mf,dev->prod,dev->serial);
+               if(dev->descriptor.bDeviceClass) {
+                       printf(" - Class: ");
+                       usb_display_class_sub(dev->descriptor.bDeviceClass,dev->descriptor.bDeviceSubClass,dev->descriptor.bDeviceProtocol);
+                       printf("\n");
+               }
+               else {
+                       printf(" - Class: (from Interface) %s\n",usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass));
+               }
+               printf(" - PacketSize: %d  Configurations: %d\n",dev->descriptor.bMaxPacketSize0,dev->descriptor.bNumConfigurations);           
+               printf(" - Vendor: 0x%04x  Product 0x%04x Version %d.%d\n",dev->descriptor.idVendor,dev->descriptor.idProduct,(dev->descriptor.bcdDevice>>8) & 0xff,dev->descriptor.bcdDevice & 0xff);
+       }
+       
+}
+
+void usb_display_conf_desc(struct usb_config_descriptor *config,struct usb_device *dev)
+{
+       printf("   Configuration: %d\n",config->bConfigurationValue);
+       printf("   - Interfaces: %d %s%s%dmA\n",config->bNumInterfaces,(config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ",
+       (config->bmAttributes & 0x20) ? "Remote Wakeup " : "",config->MaxPower*2);
+       if(config->iConfiguration) {
+               printf("   - ");
+               usb_display_string(dev,config->iConfiguration);
+               printf("\n");
+       }
+}
+
+void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,struct usb_device *dev)
+{
+       printf("     Interface: %d\n",ifdesc->bInterfaceNumber);
+       printf("     - Alternate Settings %d, Endpoints: %d\n",ifdesc->bAlternateSetting,ifdesc->bNumEndpoints);
+       printf("     - Class ");
+       usb_display_class_sub(ifdesc->bInterfaceClass,ifdesc->bInterfaceSubClass,ifdesc->bInterfaceProtocol);
+       printf("\n");
+       if(ifdesc->iInterface) {
+               printf("     - ");
+               usb_display_string(dev,ifdesc->iInterface);
+               printf("\n");
+       }
+}
+
+void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
+{
+       printf("     - Endpoint %d %s ",epdesc->bEndpointAddress & 0xf,(epdesc->bEndpointAddress & 0x80) ? "In" : "Out");
+       switch((epdesc->bmAttributes & 0x03))
+       {
+               case 0: printf("Control"); break;
+               case 1: printf("Isochronous"); break;
+               case 2: printf("Bulk"); break;
+               case 3: printf("Interrupt"); break;
+       }
+       printf(" MaxPacket %d",epdesc->wMaxPacketSize);
+       if((epdesc->bmAttributes & 0x03)==0x3)
+               printf(" Interval %dms",epdesc->bInterval);
+       printf("\n");
+}
+
+/* main routine to diasplay the configs, interfaces and endpoints */
+void usb_display_config(struct usb_device *dev)
+{
+       struct usb_config_descriptor *config;
+       struct usb_interface_descriptor *ifdesc;
+       struct usb_endpoint_descriptor *epdesc;
+       int i,ii;
+
+       config= &dev->config;
+       usb_display_conf_desc(config,dev);
+       for(i=0;i<config->no_of_if;i++) {
+               ifdesc= &config->if_desc[i];
+               usb_display_if_desc(ifdesc,dev);
+               for(ii=0;ii<ifdesc->no_of_ep;ii++) {
+                       epdesc= &ifdesc->ep_desc[ii];
+                       usb_display_ep_desc(epdesc);
+               }
+       }
+       printf("\n");
+}
+
+/* shows the device tree recursively */
+void usb_show_tree_graph(struct usb_device *dev,char *pre)
+{
+       int i,index;
+       int has_child,last_child,port;
+       
+       index=strlen(pre);
+       printf(" %s",pre);
+       /* check if the device has connected children */
+       has_child=0;
+       for(i=0;i<dev->maxchild;i++) {
+               if(dev->children[i]!=NULL)
+                       has_child=1;
+       }
+       /* check if we are the last one */
+       last_child=1;
+       if(dev->parent!=NULL) {
+               for(i=0;i<dev->parent->maxchild;i++) {
+                       /* search for children */
+                       if(dev->parent->children[i]==dev) { 
+                               /* found our pointer, see if we have a little sister */
+                               port=i;
+                               while(i++<dev->parent->maxchild) {
+                                       if(dev->parent->children[i]!=NULL) {
+                                               /* found a sister */
+                                               last_child=0;
+                                               break;
+                                       } /* if */
+                               } /* while */
+                       } /* device found */
+               } /* for all children of the parent */
+               printf("\b+-");
+               /* correct last child */
+               if(last_child) {
+                       pre[index-1]=' ';
+               }
+       } /* if not root hub */
+       else
+               printf(" ");
+       printf("%d ",dev->devnum);
+       pre[index++]=' ';
+       pre[index++]= has_child ? '|' : ' ';
+       pre[index]=0;
+       printf(" %s (%s, %dmA)\n",usb_get_class_desc(dev->config.if_desc[0].bInterfaceClass),
+               dev->slow ? "1.5MBit/s" : "12MBit/s",dev->config.MaxPower * 2);
+       if(strlen(dev->mf) ||
+          strlen(dev->prod) ||
+          strlen(dev->serial))
+               printf(" %s  %s %s %s\n",pre,dev->mf,dev->prod,dev->serial);
+       printf(" %s\n",pre);
+       if(dev->maxchild>0) {
+               for(i=0;i<dev->maxchild;i++) {
+                       if(dev->children[i]!=NULL) {
+                               usb_show_tree_graph(dev->children[i],pre);
+                               pre[index]=0;
+                       }
+               }
+       }
+}      
+
+/* main routine for the tree command */
+void usb_show_tree(struct usb_device *dev)
+{
+       char preamble[32];
+       
+       memset(preamble,0,32);
+       usb_show_tree_graph(dev,&preamble[0]);
+}      
+
+
+
+/******************************************************************************
+ * usb boot command intepreter. Derived from diskboot
+ */
+#ifdef CONFIG_USB_STORAGE
+int do_usbboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+       char *boot_device = NULL;
+       char *ep;
+       int dev, part,rcode;
+       ulong cnt;
+       ulong addr;
+       disk_partition_t info;
+       image_header_t *hdr;
+       block_dev_desc_t *stor_dev;
+
+
+       switch (argc) {
+       case 1:
+               addr = CFG_LOAD_ADDR;
+               boot_device = getenv ("bootdevice");
+               break;
+       case 2:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = getenv ("bootdevice");
+               break;
+       case 3:
+               addr = simple_strtoul(argv[1], NULL, 16);
+               boot_device = argv[2];
+               break;
+       default:
+               printf ("Usage:\n%s\n", cmdtp->usage);
+               return 1;
+       }
+
+       if (!boot_device) {
+               puts ("\n** No boot device **\n");
+               return 1;
+       }
+
+       dev = simple_strtoul(boot_device, &ep, 16);
+       stor_dev=usb_stor_get_dev(dev);
+       if (stor_dev->type == DEV_TYPE_UNKNOWN) {
+               printf ("\n** Device %d not available\n", dev);
+               return 1;
+       }
+       if(stor_dev->block_read==NULL) {
+               printf("storage device not initialized. Use usb scan\n");
+               return 1;
+       }
+       if (*ep) {
+               if (*ep != ':') {
+                       puts ("\n** Invalid boot device, use `dev[:part]' **\n");
+                       return 1;
+               }
+               part = simple_strtoul(++ep, NULL, 16);
+       }
+       
+       if (get_partition_info (stor_dev, part, &info)) {
+               /* try to boot raw .... */
+               strncpy(&info.type[0], BOOT_PART_TYPE, sizeof(BOOT_PART_TYPE));
+               strncpy(&info.name[0], "Raw", 4);
+               info.start=0;
+               info.blksz=0x200;
+               info.size=2880;
+               printf("error reading partinfo...try to boot raw\n");
+       }
+       if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) {
+               printf ("\n** Invalid partition type \"%.32s\""
+                       " (expect \"" BOOT_PART_TYPE "\")\n",
+                       info.type);
+               return 1;
+       }
+       printf ("\nLoading from USB device %d, partition %d: "
+               "Name: %.32s  Type: %.32s\n",
+               dev, part, info.name, info.type);
+
+       printf ("First Block: %ld,  # of blocks: %ld, Block Size: %ld\n",
+               info.start, info.size, info.blksz);
+
+       if (stor_dev->block_read(dev, info.start, 1, (ulong *)addr) != 1) {
+               printf ("** Read error on %d:%d\n", dev, part);
+               return 1;
+       }
+
+       hdr = (image_header_t *)addr;
+
+       if (hdr->ih_magic == IH_MAGIC) {
+               print_image_hdr (hdr);
+               cnt = (hdr->ih_size + sizeof(image_header_t));
+               cnt += info.blksz - 1;
+               cnt /= info.blksz;
+               cnt -= 1;
+       } else {
+               printf("\n** Bad Magic Number **\n");
+               return 1;
+       }
+
+       if (stor_dev->block_read (dev, info.start+1, cnt,
+                     (ulong *)(addr+info.blksz)) != cnt) {
+               printf ("\n** Read error on %d:%d\n", dev, part);
+               return 1;
+       }
+       /* Loading ok, update default load address */
+       load_addr = addr;
+       /* Check if we should attempt an auto-start */
+       if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) {
+               char *local_args[2];
+               extern int do_bootm (cmd_tbl_t *, bd_t *, int, int, char *[]);
+               local_args[0] = argv[0];
+               local_args[1] = NULL;
+               printf ("Automatic boot of image at addr 0x%08lX ...\n", addr);
+               rcode=do_bootm (cmdtp, bd, 0, 1, local_args);
+               return rcode;
+       }
+       return 0;
+}
+#endif /* CONFIG_USB_STORAGE */
+
+
+
+
+/*********************************************************************************
+ * usb command intepreter
+ */
+int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+       
+       int i;
+       struct usb_device *dev;
+       block_dev_desc_t *stor_dev;
+
+       if ((strncmp(argv[1],"reset",5) == 0) ||
+                (strncmp(argv[1],"start",5) == 0)){
+               usb_stop();
+               printf("(Re)start USB...\n");
+               usb_init();
+               return 0; 
+       } 
+       if (strncmp(argv[1],"stop",4) == 0) {
+#ifdef CONFIG_USB_KEYBOARD 
+               if(argc==2) {
+                       if(usb_kbd_deregister()!=0) {
+                               printf("USB not stopped: usbkbd still using USB\n");
+                               return 1;
+                       }
+               }
+               else { /* forced stop, switch console in to serial */
+                       console_assign(stdin,"serial");
+                       usb_kbd_deregister();
+               }
+#endif
+               printf("stopping USB..\n");
+               usb_stop();
+               return 0;
+       } 
+       if (strncmp(argv[1],"tree",4) == 0) {
+               printf("\nDevice Tree:\n");
+               usb_show_tree(usb_get_dev_index(0));    
+               return 0;
+       }
+       if (strncmp(argv[1],"inf",3) == 0) {
+               int d;
+               if(argc==2) {
+                       for(d=0;d<USB_MAX_DEVICE;d++) {
+                               dev=usb_get_dev_index(d);
+                               if(dev==NULL) 
+                                       break;
+                               usb_display_desc(dev);
+                               usb_display_config(dev);
+                       }
+                       return 0;
+               }
+               else {
+                       int d;
+                       
+                       i=simple_strtoul(argv[2], NULL, 16);
+                       printf("config for device %d\n",i);
+                       for(d=0;d<USB_MAX_DEVICE;d++) {
+                               dev=usb_get_dev_index(d);
+                               if(dev==NULL) 
+                                       break;
+                               if(dev->devnum==i)
+                                       break;
+                       }
+                       if(dev==NULL) {
+                               printf("*** NO Device avaiable ***\n");
+                               return 0;
+                       }
+                       else {
+                               usb_display_desc(dev);
+                               usb_display_config(dev);
+                       }
+               }
+               return 0;
+       }
+#ifdef CONFIG_USB_STORAGE
+       if (strncmp(argv[1],"scan",4) == 0) {
+               printf("Scan for storage device:\n");
+               usb_stor_curr_dev=usb_stor_scan(1);
+               if(usb_stor_curr_dev==-1) {
+                       printf("No device found. Not initialized?\n");
+                       return 1;
+               }
+               return 0;
+       } 
+       if (strncmp(argv[1],"part",4) == 0) {
+               int devno, ok;
+               for (ok=0, devno=0; devno<USB_MAX_STOR_DEV; ++devno) {
+                       stor_dev=usb_stor_get_dev(devno);
+                       if (stor_dev->type!=DEV_TYPE_UNKNOWN) {
+                               ok++;
+                               if (devno)
+                                       printf("\n");
+                               printf("print_part of %x\n",devno);
+                               print_part(stor_dev);
+                       }
+               }
+               if (!ok) {
+                       printf("\nno USB devices available\n");
+                       return 1;
+               }
+               return 0;
+       }
+       if (strcmp(argv[1],"read") == 0) {
+               if(usb_stor_curr_dev<0) {
+                       printf("no current device selected\n");
+                       return 1;
+               }
+               if(argc==5) {
+                       unsigned long addr = simple_strtoul(argv[2], NULL, 16);
+                       unsigned long blk  = simple_strtoul(argv[3], NULL, 16);
+                       unsigned long cnt  = simple_strtoul(argv[4], NULL, 16);
+                       unsigned long n;
+                       printf ("\nUSB read: device %d block # %ld, count %ld ... ",
+                                       usb_stor_curr_dev, blk, cnt);
+                       stor_dev=usb_stor_get_dev(usb_stor_curr_dev);
+                       n = stor_dev->block_read(usb_stor_curr_dev, blk, cnt, (ulong *)addr);
+                       printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR");
+                       if(n==cnt)
+                               return 0;
+                       return 1;
+               }
+       }
+       if (strcmp(argv[1],"dev") == 0) {
+               if(argc==3) {
+                       int dev = (int)simple_strtoul(argv[2], NULL, 10);
+                       printf ("\nUSB device %d: ", dev);
+                       if (dev >= USB_MAX_STOR_DEV) {
+                               printf("unknown device\n");
+                               return 1;
+                       }
+                       printf ("\n    Device %d: ", dev);
+                       stor_dev=usb_stor_get_dev(dev);
+                       dev_print(stor_dev);
+                       if(stor_dev->type == DEV_TYPE_UNKNOWN) {
+                               return 1;
+                       }
+                       usb_stor_curr_dev = dev;
+                       printf("... is now current device\n");
+                       return 0;
+               }
+               else {
+                       printf ("\nUSB device %d: ", usb_stor_curr_dev);
+                       stor_dev=usb_stor_get_dev(usb_stor_curr_dev);
+                       dev_print(stor_dev);
+                       if(stor_dev->type == DEV_TYPE_UNKNOWN) {
+                               return 1;
+                       }
+                       return 0;
+               }
+               return 0;
+       }
+#endif /* CONFIG_USB_STORAGE */
+       printf ("Usage:\n%s\n", cmdtp->usage);
+       return 1;
+}
+
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_USB) */
+
+
index 87001f3a9e0f409a080627ef33eb6541015f3068..e6f5ee406a7fe2d047fbfd4b622ffb1687f0419c 100644 (file)
@@ -49,6 +49,7 @@
 #include <cmd_rtc.h>
 
 #include <cmd_fdc.h>           /* Floppy support */
+#include <cmd_usb.h>           /* USB support */
 #include <cmd_scsi.h>
 #include <cmd_mii.h>
 #include <cmd_dcr.h>           /* 4xx DCR register access */
@@ -288,6 +289,8 @@ cmd_tbl_t cmd_tbl[] = {
        CMD_TBL_STACK
        CMD_TBL_STEP
        CMD_TBL_TFTPB
+       CMD_TBL_USBBOOT
+       CMD_TBL_USB
        CMD_TBL_VERS
        CMD_TBL_BSP
        CMD_TBL_QUES
index 0a4a2e8d7437e359d25bd64c3ef25a9c3225653e..89f3b79f99d8b973fe0771920defb27d852670e1 100644 (file)
@@ -21,6 +21,7 @@
  * MA 02111-1307 USA
  */
 
+#include <config.h>
 #include <ppcboot.h>
 #include <stdarg.h>
 #include <malloc.h>
@@ -74,6 +75,49 @@ int device_register (device_t * dev)
        return 0;
 }
 
+/* deregister the device "devname".
+ * returns 0 if success, -1 if device is assigned and 1 if devname not found
+ */
+#ifdef CFG_DEVICE_DEREGISTER
+int device_deregister(char *devname)
+{
+       int i,l,dev_index;
+       device_t *dev;
+       char temp_names[3][8];
+
+       dev_index=-1;
+       for (i=1; i<=ListNumItems(devlist); i++) {
+               dev = ListGetPtrToItem (devlist, i);
+               if(strcmp(dev->name,devname)==0) {
+                       dev_index=i;
+                       break;
+               }
+       }
+       if(dev_index<0) /* device not found */
+               return 0;
+       /* get stdio devices (ListRemoveItem changes the dev list) */   
+       for (l=0 ; l< MAX_FILES; l++) {
+               if (stdio_devices[l] == dev) {
+                       /* Device is assigned -> report error */
+                       return -1;
+               }
+               memcpy (&temp_names[l][0],
+                       stdio_devices[l]->name,
+                       sizeof(stdio_devices[l]->name));
+       }
+       ListRemoveItem(devlist,NULL,dev_index);
+       /* reassign Device list */
+       for (i=1; i<=ListNumItems(devlist); i++) {
+               dev = ListGetPtrToItem (devlist, i);
+               for (l=0 ; l< MAX_FILES; l++) {
+                       if(strcmp(dev->name,temp_names[l])==0) {
+                               stdio_devices[l] = dev;
+                       }
+               }
+       }
+       return 0;
+}
+#endif /* CFG_DEVICE_DEREGISTER */
 
 int devices_init (bd_t *bd, ulong relocation_offset)
 {
@@ -103,9 +147,6 @@ int devices_init (bd_t *bd, ulong relocation_offset)
 #endif
 #ifdef CONFIG_WL_4PPM_KEYBOARD
        drv_wlkbd_init ();
-#endif
-#ifdef CONFIG_ISA_KEYBOARD
-       drv_isa_kbd_init ();
 #endif
        drv_system_init ();
 
index e650bee490a53d9bd9b8ef43f0b618bbeb274096..ee402923db00187da6934ce8a3a0a5fc7e4caaf8 100644 (file)
 #define MIN(a,b)       (((a)<(b)) ? (a) : (b))
 #define CAT4CHARS(a,b,c,d)     ((a<<24) | (b<<16) | (c<<8) | d)
 
-#define kDefaultAllocationPercentIncrease   10  /* increase list size by 10% every time it is full */
-#define kDefaultAllocationminNumItemsIncrease   4   /* always increase list size by 4 items when it is full */
+/* increase list size by 10% every time it is full */
+#define kDefaultAllocationPercentIncrease      10
 
- /* how many items to expand the list by when it becomes full = current listSize (in items) + (hiword percent of list size) +   loword */
-#define NUMITEMSPERALLOC(list) MAX(((*list)->listSize * ((*list)->percentIncrease + 100)) / 100 , (*list)->minNumItemsIncrease)
+/* always increase list size by 4 items when it is full */
+#define kDefaultAllocationminNumItemsIncrease  4
 
-#define ITEMPTR(list, item)     &(((char *)&(*list)->itemList)[ (*(list))->itemSize * (item)])
+/*
+ * how many items to expand the list by when it becomes full
+ * = current listSize (in items) + (hiword percent of list size) + loword
+ */
+#define NUMITEMSPERALLOC(list) MAX(((*list)->listSize * \
+                                   ((*list)->percentIncrease + 100)) / 100, \
+                                   (*list)->minNumItemsIncrease )
 
-#define LIST_SIGNATURE          CAT4CHARS('L', 'I', 'S', 'T');
+#define ITEMPTR(list,item)     &(((char *)&(*list)->itemList)[(*(list))->itemSize * (item)])
+
+#define LIST_SIGNATURE         CAT4CHARS('L', 'I', 'S', 'T');
 
 #define calloc(size,num)       malloc(size*num)
 
 /********************************************************************/
 
-Handle NewHandle(unsigned int numBytes)
+Handle NewHandle (unsigned int numBytes)
 {
-    void            *memPtr;
-    HandleRecord    *hanPtr;
+       void *memPtr;
+       HandleRecord *hanPtr;
 
-    memPtr = calloc(numBytes, 1);
-    hanPtr = (HandleRecord*)calloc(sizeof(HandleRecord), 1);
-    if (hanPtr && (memPtr || numBytes == 0))
-        {
-        hanPtr->ptr = memPtr;
-        hanPtr->size = numBytes;
-        return (Handle)hanPtr;
-        }
-    else
-        {
-        free(memPtr);
-        free(hanPtr);
-        return NULL;
-        }
+       memPtr = calloc (numBytes, 1);
+       hanPtr = (HandleRecord *) calloc (sizeof (HandleRecord), 1);
+       if (hanPtr && (memPtr || numBytes == 0)) {
+               hanPtr->ptr = memPtr;
+               hanPtr->size = numBytes;
+               return (Handle) hanPtr;
+       } else {
+               free (memPtr);
+               free (hanPtr);
+               return NULL;
+       }
 }
-
 /********************************************************************/
 
-void  DisposeHandle(Handle handle)
+void DisposeHandle (Handle handle)
 {
-    if (handle)
-        {
-        free(*handle);
-        free((void *)handle);
-        }
+       if (handle) {
+               free (*handle);
+               free ((void *) handle);
+       }
 }
-
 /********************************************************************/
 
-unsigned int  GetHandleSize(Handle handle)
+unsigned int GetHandleSize (Handle handle)
 {
-    return ((HandleRecord *)handle)->size;
+       return ((HandleRecord *) handle)->size;
 }
-
 /********************************************************************/
 
-int  SetHandleSize(Handle handle, unsigned int newSize)
+int SetHandleSize (Handle handle, unsigned int newSize)
 {
-    HandleRecord    *hanRecPtr = (HandleRecord *)handle;
-    void            *newPtr, *oldPtr;
-    unsigned int    oldSize;
+       HandleRecord *hanRecPtr = (HandleRecord *) handle;
+       void *newPtr, *oldPtr;
+       unsigned int oldSize;
 
 
-    oldPtr = hanRecPtr->ptr;
-    oldSize = hanRecPtr->size;
+       oldPtr = hanRecPtr->ptr;
+       oldSize = hanRecPtr->size;
 
-    if (oldSize == newSize)
-         return 1;
+       if (oldSize == newSize)
+               return 1;
 
-    if (oldPtr == NULL)
-    {
-        newPtr = malloc(newSize);
-    }
-    else
-    {
-        newPtr = realloc(oldPtr, newSize);
-    }
-    if (newPtr || (newSize == 0))
-        {
-        hanRecPtr->ptr = newPtr;
-        hanRecPtr->size = newSize;
-        if (newSize > oldSize)
-            memset ((char *)newPtr+oldSize, 0, newSize-oldSize);
-        return 1;
-        }
-    else
-        return 0;
+       if (oldPtr == NULL) {
+               newPtr = malloc (newSize);
+       } else {
+               newPtr = realloc (oldPtr, newSize);
+       }
+       if (newPtr || (newSize == 0)) {
+               hanRecPtr->ptr = newPtr;
+               hanRecPtr->size = newSize;
+               if (newSize > oldSize)
+                       memset ((char *) newPtr + oldSize, 0, newSize - oldSize);
+               return 1;
+       } else
+               return 0;
 }
 
 #ifdef CFG_ALL_LIST_FUNCTIONS
 
-    /*  Used to compare list elements by their raw data contents */
-static int  ListMemBlockCmp(void *a, void *b, int size)
+/*  Used to compare list elements by their raw data contents */
+static int ListMemBlockCmp (void *a, void *b, int size)
 {
-    return memcmp(a, b, size);
+       return memcmp (a, b, size);
 }
 
-
 /***************************************************************************/
 
-    /*  Binary search numElements of size elementSize in array for a match
-        to the. item. Return the index of the element that matches (0 - numElements - 1).
-        If no match is found return the -i-1 where i is the index (0 - numElements)
-        where the item should be placed. (*theCmp)(a,b) should return  <0 if a<b,
-        0 if a==b, >0 if a>b.
-
-        This function is like the C-Library function bsearch() except that this
-        function returns the index where the item should be placed if it is not
-        found.
-    */
-int BinSearch(void *array, int numElements, int elementSize, void *itemPtr, CompareFunction compareFunction)
-{
-    int low, high, mid, cmp;
-    void *arrayItemPtr;
-
-    for(low=0, high= numElements-1, mid=0, cmp= -1; low <= high; )
-        {
-        mid = (low + high) >> 1;
-
-        arrayItemPtr = (void *) (((char *)array) + (mid*elementSize));
-        cmp = compareFunction ? compareFunction(itemPtr, arrayItemPtr)
-                              : ListMemBlockCmp(itemPtr, arrayItemPtr, elementSize);
-        if (cmp == 0)
-            return mid;
-        else
-        if (cmp < 0)
-            high= mid - 1;
-        else
-            low= mid + 1;
-        }
-    if (cmp > 0)
-        mid++;
-
-    return -mid-1;
+/*
+ * Binary search numElements of size elementSize in array for a match
+ * to the. item. Return the index of the element that matches
+ * (0 - numElements - 1). If no match is found return the -i-1 where
+ * i is the index (0 - numElements) where the item should be placed.
+ * (*theCmp)(a,b) should return <0 if a<b, 0 if a==b, >0 if a>b.
+ *
+ * This function is like the C-Library function bsearch() except that
+ * this function returns the index where the item should be placed if
+ * it is not found.
+ */
+int BinSearch ( void *array, int numElements, int elementSize,
+               void *itemPtr, CompareFunction compareFunction)
+{
+       int low, high, mid, cmp;
+       void *arrayItemPtr;
+
+       for (low = 0, high = numElements - 1, mid = 0, cmp = -1; low <= high;) {
+               mid = (low + high) >> 1;
+
+               arrayItemPtr = (void *) (((char *) array) + (mid * elementSize));
+               cmp = compareFunction
+                       ? compareFunction (itemPtr, arrayItemPtr)
+                       : ListMemBlockCmp (itemPtr, arrayItemPtr, elementSize);
+               if (cmp == 0) {
+                       return mid;
+               } else if (cmp < 0) {
+                       high = mid - 1;
+               } else {
+                       low = mid + 1;
+               }
+       }
+       if (cmp > 0)
+               mid++;
+
+       return -mid - 1;
 }
 
 #endif /* CFG_ALL_LIST_FUNCTIONS */
 
 /*******************************************************************************/
 
-    /* BEGIN PATCH to 4.0.1 - jag 8-29-96 */
-    /*  If numNewItems == 0 then expand the list by the number of items
-       indicated by its allocation policy.
-        If numNewItems > 0 then expand the list by exactly the number of
-       items indicated.
-        If numNewItems < 0 then expand the list by the absolute value of
-       numNewItems plus the number of items indicated by its allocation
-       policy.
-        Returns 1 for success, 0 if out of memory
-    */
-static int  ExpandListSpace (list_t list, int numNewItems)
-{
-    if (numNewItems == 0)
-        numNewItems = NUMITEMSPERALLOC(list);
-    else
-    if (numNewItems < 0)
-        numNewItems = (-numNewItems) + NUMITEMSPERALLOC(list);
-
-    if (SetHandleSize ((Handle)list,
-        sizeof(ListStruct) +
-       ((*list)->listSize + numNewItems) * (*list)->itemSize))
-       {
-           (*list)->listSize += numNewItems;
-           return 1;
-        }
-    else
-    {
-        return 0;
-    }
+/*
+ * If numNewItems == 0 then expand the list by the number of items
+ * indicated by its allocation policy.
+ * If numNewItems > 0 then expand the list by exactly the number of
+ * items indicated.
+ * If numNewItems < 0 then expand the list by the absolute value of
+ * numNewItems plus the number of items indicated by its allocation
+ * policy.
+ * Returns 1 for success, 0 if out of memory
+*/
+static int ExpandListSpace (list_t list, int numNewItems)
+{
+       if (numNewItems == 0) {
+               numNewItems = NUMITEMSPERALLOC (list);
+       } else if (numNewItems < 0) {
+               numNewItems = (-numNewItems) + NUMITEMSPERALLOC (list);
+       }
+
+       if (SetHandleSize ((Handle) list,
+                          sizeof (ListStruct) +
+                          ((*list)->listSize +
+                          numNewItems) * (*list)->itemSize)) {
+               (*list)->listSize += numNewItems;
+               return 1;
+       } else {
+               return 0;
+       }
 }
 
 /*******************************/
 
 #ifdef CFG_ALL_LIST_FUNCTIONS
 
-     /* This function reallocate the list, minus any currently unused portion of its allotted memory. */
-void  ListCompact (list_t list)
+/*
+ * This function reallocate the list, minus any currently unused
+ * portion of its allotted memory.
+ */
+void ListCompact (list_t list)
 {
 
-    if (!SetHandleSize ((Handle)list,
-        sizeof (ListStruct) + (*list)->numItems * (*list)->itemSize))
-        return;
+       if (!SetHandleSize ((Handle) list,
+                           sizeof (ListStruct) +
+                           (*list)->numItems * (*list)->itemSize)) {
+               return;
+       }
 
-    (*list)->listSize = (*list)->numItems;
+       (*list)->listSize = (*list)->numItems;
 }
 
 #endif /* CFG_ALL_LIST_FUNCTIONS */
 
 /*******************************/
 
-list_t  ListCreate (int elementSize)
+list_t ListCreate (int elementSize)
 {
-    list_t    list;
+       list_t list;
 
-    list = (list_t)(NewHandle (sizeof(ListStruct)));   /* create empty list */
-    if (list)
-        {
-        (*list)->signature = LIST_SIGNATURE;
-        (*list)->numItems = 0;
-        (*list)->listSize = 0;
-        (*list)->itemSize = elementSize;
-        (*list)->percentIncrease = kDefaultAllocationPercentIncrease;
-        (*list)->minNumItemsIncrease = kDefaultAllocationminNumItemsIncrease;
-        }
+       list = (list_t) (NewHandle (sizeof (ListStruct)));  /* create empty list */
+       if (list) {
+               (*list)->signature = LIST_SIGNATURE;
+               (*list)->numItems = 0;
+               (*list)->listSize = 0;
+               (*list)->itemSize = elementSize;
+               (*list)->percentIncrease = kDefaultAllocationPercentIncrease;
+               (*list)->minNumItemsIncrease =
+                               kDefaultAllocationminNumItemsIncrease;
+       }
 
-    return list;
+       return list;
 }
 
 /*******************************/
 
-void  ListSetAllocationPolicy (list_t list, int minItemsPerAlloc, int percentIncreasePerAlloc)
+void ListSetAllocationPolicy (list_t list, int minItemsPerAlloc,
+                             int percentIncreasePerAlloc)
 {
-
-    (*list)->percentIncrease = percentIncreasePerAlloc;
-    (*list)->minNumItemsIncrease = minItemsPerAlloc;
+       (*list)->percentIncrease = percentIncreasePerAlloc;
+       (*list)->minNumItemsIncrease = minItemsPerAlloc;
 }
 
 /*******************************/
 
-void  ListDispose (list_t list)
+void ListDispose (list_t list)
 {
-    DisposeHandle ((Handle)list);
+       DisposeHandle ((Handle) list);
 }
-
 /*******************************/
 
 #ifdef CFG_ALL_LIST_FUNCTIONS
 
-void  ListDisposePtrList(list_t list)
+void ListDisposePtrList (list_t list)
 {
-    int index;
-    int numItems;
+       int index;
+       int numItems;
 
-    if (list)
-        {
-        numItems = ListNumItems(list);
+       if (list) {
+               numItems = ListNumItems (list);
 
-        for (index = 1; index <= numItems; index++)
-            free(*(void **)ListGetPtrToItem(list, index));
+               for (index = 1; index <= numItems; index++)
+                       free (*(void **) ListGetPtrToItem (list, index));
 
-        ListDispose(list);
-        }
+               ListDispose (list);
+       }
 }
 
 /*******************************/
 
-void   ListClear (list_t list)  /* keeps memory, resets the number of items to 0 */
+/*
+ * keeps memory, resets the number of items to 0
+ */
+void ListClear (list_t list)
 {
-    if (!list)
-        return;
-    (*list)->numItems = 0;
+       if (!list)
+               return;
+       (*list)->numItems = 0;
 }
 
 /*******************************/
 
-list_t  ListCopy (list_t originalList)   /* copy is only as large as necessary */
+/*
+ * copy is only as large as necessary
+ */
+list_t ListCopy (list_t originalList)
 {
-    list_t    tempList = NULL;
-    int         numItems;
+       list_t tempList = NULL;
+       int numItems;
 
-    if (!originalList)
-        return NULL;
+       if (!originalList)
+               return NULL;
 
-    tempList = ListCreate ((*originalList)->itemSize);
-    if (tempList) {
-        numItems = ListNumItems (originalList);
+       tempList = ListCreate ((*originalList)->itemSize);
+       if (tempList) {
+               numItems = ListNumItems (originalList);
 
-        if (!SetHandleSize ((Handle)tempList,
-            sizeof (ListStruct) + numItems * (*tempList)->itemSize)) {
-            ListDispose (tempList);
-            return NULL;
-            }
+               if (!SetHandleSize ((Handle) tempList,
+                                   sizeof (ListStruct) +
+                                   numItems * (*tempList)->itemSize)) {
+                       ListDispose (tempList);
+                       return NULL;
+               }
 
-        (*tempList)->numItems = (*originalList)->numItems;
-        (*tempList)->listSize = (*originalList)->numItems;
-        (*tempList)->itemSize = (*originalList)->itemSize;
-        (*tempList)->percentIncrease = (*originalList)->percentIncrease;
-        (*tempList)->minNumItemsIncrease = (*originalList)->minNumItemsIncrease;
+               (*tempList)->numItems = (*originalList)->numItems;
+               (*tempList)->listSize = (*originalList)->numItems;
+               (*tempList)->itemSize = (*originalList)->itemSize;
+               (*tempList)->percentIncrease = (*originalList)->percentIncrease;
+               (*tempList)->minNumItemsIncrease =
+                               (*originalList)->minNumItemsIncrease;
 
-        memcpy (ITEMPTR(tempList,0), ITEMPTR(originalList,0),
-            numItems * (*tempList)->itemSize);
-        }
+               memcpy (ITEMPTR (tempList, 0), ITEMPTR (originalList, 0),
+                               numItems * (*tempList)->itemSize);
+       }
 
-    return tempList;
+       return tempList;
 }
 
 /********************************/
 
-int  ListAppend (list_t list1, list_t list2)  /* list1 = list1 + list2 */
+/*
+ * list1 = list1 + list2
+ */
+int ListAppend (list_t list1, list_t list2)
 {
-    int numItemsL1, numItemsL2;
+       int numItemsL1, numItemsL2;
 
-    if (!list2)
-        return 1;
+       if (!list2)
+               return 1;
 
-    if (!list1)
-        return 0;
-    if ((*list1)->itemSize != (*list2)->itemSize)
-        return 0;
+       if (!list1)
+               return 0;
+       if ((*list1)->itemSize != (*list2)->itemSize)
+               return 0;
 
-    numItemsL1 = ListNumItems (list1);
-    numItemsL2 = ListNumItems (list2);
+       numItemsL1 = ListNumItems (list1);
+       numItemsL2 = ListNumItems (list2);
 
-    if (numItemsL2 == 0)
-        return 1;
+       if (numItemsL2 == 0)
+               return 1;
 
-    if (!SetHandleSize ((Handle)list1,
-        sizeof (ListStruct) + (numItemsL1 + numItemsL2) * (*list1)->itemSize))
-        return 0;
+       if (!SetHandleSize ((Handle) list1,
+                           sizeof (ListStruct) + (numItemsL1 + numItemsL2) *
+                                       (*list1)->itemSize)) {
+               return 0;
+       }
 
-    (*list1)->numItems = numItemsL1 + numItemsL2;
-    (*list1)->listSize = numItemsL1 + numItemsL2;
+       (*list1)->numItems = numItemsL1 + numItemsL2;
+       (*list1)->listSize = numItemsL1 + numItemsL2;
 
-    memmove (ITEMPTR(list1,numItemsL1), ITEMPTR(list2,0),
-        numItemsL2 * (*list2)->itemSize);
+       memmove (ITEMPTR (list1, numItemsL1),
+                ITEMPTR (list2, 0),
+                numItemsL2 * (*list2)->itemSize);
 
-    return 1;
+       return 1;
 }
 
 #endif /* CFG_ALL_LIST_FUNCTIONS */
 
 /*******************************/
 
-    /*  returns 1 if the item is inserted, returns 0 if out of memory or
-        bad arguments were passed.
-    */
-int  ListInsertItem (list_t list, void *ptrToItem, int itemPosition)
+/*
+ * returns 1 if the item is inserted, returns 0 if out of memory or
+ * bad arguments were passed.
+ */
+int ListInsertItem (list_t list, void *ptrToItem, int itemPosition)
 {
-    return ListInsertItems (list, ptrToItem, itemPosition, 1);
+       return ListInsertItems (list, ptrToItem, itemPosition, 1);
 }
 
 /*******************************/
 
-int  ListInsertItems (list_t list, void *ptrToItems, int firstItemPosition, int numItemsToInsert)
-{
-    int numItems = (*list)->numItems;
-
-    if (firstItemPosition == numItems + 1)
-        firstItemPosition = LIST_END;
-    else
-    if (firstItemPosition > numItems)
-        return 0;
-
-    if ((*list)->numItems >= (*list)->listSize)
-    {
-       if (!ExpandListSpace (list, -numItemsToInsert)) /* PATCH to 4.0.1 - jag 8-29-96 */
-            return 0;
-    }
-
-    if (firstItemPosition == LIST_START)
-    {
-        if (numItems == 0)
-           firstItemPosition = LIST_END; /* special case for empty list */
-        else
-           firstItemPosition = 1;
-    }
-
-    if (firstItemPosition == LIST_END)  /* add at the end of the list */
-        {
-        if (ptrToItems)
-            memcpy (ITEMPTR(list, numItems), ptrToItems, (*list)->itemSize * numItemsToInsert);
-        else
-            memset (ITEMPTR(list, numItems), 0,
-                (*list)->itemSize * numItemsToInsert);
-
-        (*list)->numItems += numItemsToInsert;
-        }
-    else
-        {                                  /* move part of list up to make room for new item */
-        memmove (ITEMPTR(list,firstItemPosition-1+numItemsToInsert),
-            ITEMPTR(list,firstItemPosition-1),
-            (numItems + 1 - firstItemPosition) * (*list)->itemSize);
-
-        if (ptrToItems)
-            memmove (ITEMPTR(list,firstItemPosition-1), ptrToItems,
-                (*list)->itemSize * numItemsToInsert);
-        else
-            memset (ITEMPTR(list,firstItemPosition-1), 0,
-                (*list)->itemSize * numItemsToInsert);
-
-        (*list)->numItems += numItemsToInsert;
-        }
-
-    return 1;
+int ListInsertItems (list_t list, void *ptrToItems, int firstItemPosition,
+                    int numItemsToInsert)
+{
+       int numItems = (*list)->numItems;
+
+       if (firstItemPosition == numItems + 1)
+               firstItemPosition = LIST_END;
+       else if (firstItemPosition > numItems)
+               return 0;
+
+       if ((*list)->numItems >= (*list)->listSize) {
+               if (!ExpandListSpace (list, -numItemsToInsert))
+                       return 0;
+       }
+
+       if (firstItemPosition == LIST_START) {
+               if (numItems == 0) {
+                       /* special case for empty list */
+                       firstItemPosition = LIST_END;
+               } else {
+                       firstItemPosition = 1;
+               }
+       }
+
+       if (firstItemPosition == LIST_END) {    /* add at the end of the list */
+               if (ptrToItems)
+                       memcpy (ITEMPTR (list, numItems), ptrToItems,
+                                       (*list)->itemSize * numItemsToInsert);
+               else
+                       memset (ITEMPTR (list, numItems), 0,
+                                       (*list)->itemSize * numItemsToInsert);
+
+               (*list)->numItems += numItemsToInsert;
+       } else {                                        /* move part of list up to make room for new item */
+               memmove (ITEMPTR (list, firstItemPosition - 1 + numItemsToInsert),
+                        ITEMPTR (list, firstItemPosition - 1),
+                        (numItems + 1 - firstItemPosition) * (*list)->itemSize);
+
+               if (ptrToItems)
+                       memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems,
+                                        (*list)->itemSize * numItemsToInsert);
+               else
+                       memset (ITEMPTR (list, firstItemPosition - 1), 0,
+                                       (*list)->itemSize * numItemsToInsert);
+
+               (*list)->numItems += numItemsToInsert;
+       }
+
+       return 1;
 }
 
-#ifdef CFG_ALL_LIST_FUNCTIONS
+#ifdef CFG_ALL_LIST_FUNCTIONS
 
 /*******************************/
 
-int  ListEqual (list_t list1, list_t list2)
+int ListEqual (list_t list1, list_t list2)
 {
-    if (list1 == list2)
-        return 1;
+       if (list1 == list2)
+               return 1;
 
-    if (list1 == NULL || list2 == NULL)
-        return 0;
+       if (list1 == NULL || list2 == NULL)
+               return 0;
 
-    if ((*list1)->itemSize == (*list1)->itemSize)
-        if ((*list1)->numItems == (*list2)->numItems)
-            return (memcmp (ITEMPTR(list1,0), ITEMPTR(list2,0),
-                (*list1)->itemSize * (*list1)->numItems) == 0);
+       if ((*list1)->itemSize == (*list1)->itemSize) {
+           if ((*list1)->numItems == (*list2)->numItems) {
+               return (memcmp (ITEMPTR (list1, 0), ITEMPTR (list2, 0),
+                               (*list1)->itemSize * (*list1)->numItems) == 0);
+           }
+       }
 
-    return 0;
+       return 0;
 }
 
 /*******************************/
 
-     /* The item pointed to by ptrToItem is copied over the current item at itemPosition */
-void  ListReplaceItem (list_t list, void *ptrToItem, int itemPosition)
+/*
+ * The item pointed to by ptrToItem is copied over the current item
+ * at itemPosition
+ */
+void ListReplaceItem (list_t list, void *ptrToItem, int itemPosition)
 {
-    ListReplaceItems (list, ptrToItem, itemPosition, 1);
+       ListReplaceItems (list, ptrToItem, itemPosition, 1);
 }
 
 /*******************************/
 
-     /* The item pointed to by ptrToItems is copied over the current item at itemPosition */
-void  ListReplaceItems (list_t list, void *ptrToItems, int firstItemPosition, int numItemsToReplace)
+/*
+ * The item pointed to by ptrToItems is copied over the current item
+ * at itemPosition
+ */
+void ListReplaceItems ( list_t list, void *ptrToItems,
+                       int firstItemPosition, int numItemsToReplace)
 {
 
-    if (firstItemPosition == LIST_END)
-        firstItemPosition = (*list)->numItems;
-    else
-    if (firstItemPosition == LIST_START)
-        firstItemPosition = 1;
+       if (firstItemPosition == LIST_END)
+               firstItemPosition = (*list)->numItems;
+       else if (firstItemPosition == LIST_START)
+               firstItemPosition = 1;
 
-    memmove (ITEMPTR(list,firstItemPosition-1), ptrToItems,
-        (*list)->itemSize * numItemsToReplace);
+       memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems,
+                        (*list)->itemSize * numItemsToReplace);
 }
 
 /*******************************/
 
-void  ListRemoveItem (list_t list, void *itemDestination, int itemPosition)
+void ListGetItem (list_t list, void *itemDestination, int itemPosition)
 {
-    ListRemoveItems (list, itemDestination, itemPosition, 1);
+       ListGetItems (list, itemDestination, itemPosition, 1);
 }
 
+#endif /* CFG_ALL_LIST_FUNCTIONS */
+
 /*******************************/
 
-void  ListRemoveItems (list_t list, void *itemsDestination, int firstItemPosition, int numItemsToRemove)
+#if defined(CFG_ALL_LIST_FUNCTIONS) || defined(CFG_DEVICE_DEREGISTER)
+
+void ListRemoveItem (list_t list, void *itemDestination, int itemPosition)
 {
-    int firstItemAfterChunk, numToMove;
+       ListRemoveItems (list, itemDestination, itemPosition, 1);
+}
 
-    if (firstItemPosition == LIST_START)
-        firstItemPosition = 1;
-    else
-    if (firstItemPosition == LIST_END)
-        firstItemPosition = (*list)->numItems;
+/*******************************/
 
-    if (itemsDestination != NULL)
-         memcpy (itemsDestination, ITEMPTR(list,firstItemPosition-1),
-            (*list)->itemSize * numItemsToRemove);
+void ListRemoveItems (list_t list, void *itemsDestination,
+                     int firstItemPosition, int numItemsToRemove)
+{
+       int firstItemAfterChunk, numToMove;
 
-    firstItemAfterChunk = firstItemPosition + numItemsToRemove;
-    numToMove = (*list)->numItems - (firstItemAfterChunk - 1);
+       if (firstItemPosition == LIST_START)
+               firstItemPosition = 1;
+       else if (firstItemPosition == LIST_END)
+               firstItemPosition = (*list)->numItems;
 
-    if (numToMove > 0)  /* move part of list down to cover hole left by removed item */
-        memmove (ITEMPTR(list,firstItemPosition-1),
-                 ITEMPTR(list,firstItemAfterChunk-1),
-                 (*list)->itemSize * numToMove);
+       if (itemsDestination != NULL)
+               memcpy (itemsDestination, ITEMPTR (list, firstItemPosition - 1),
+                               (*list)->itemSize * numItemsToRemove);
 
-    (*list)->numItems -= numItemsToRemove;
-}
+       firstItemAfterChunk = firstItemPosition + numItemsToRemove;
+       numToMove = (*list)->numItems - (firstItemAfterChunk - 1);
 
-/*******************************/
+       if (numToMove > 0) {
+               /*
+                * move part of list down to cover hole left by removed item
+                */
+               memmove (ITEMPTR (list, firstItemPosition - 1),
+                                ITEMPTR (list, firstItemAfterChunk - 1),
+                                (*list)->itemSize * numToMove);
+       }
 
-void  ListGetItem (list_t list, void *itemDestination, int itemPosition)
-{
-    ListGetItems (list, itemDestination, itemPosition, 1);
+       (*list)->numItems -= numItemsToRemove;
 }
-
-#endif /* CFG_ALL_LIST_FUNCTIONS */
+#endif /* CFG_ALL_LIST_FUNCTIONS || CFG_DEVICE_DEREGISTER */
 
 /*******************************/
 
-void  ListGetItems(list_t list, void *itemsDestination, int firstItemPosition, int numItemsToGet)
+void ListGetItems (list_t list, void *itemsDestination,
+                  int firstItemPosition, int numItemsToGet)
 {
 
-    if (firstItemPosition == LIST_START)
-        firstItemPosition = 1;
-    else
-    if (firstItemPosition == LIST_END)
-        firstItemPosition = (*list)->numItems;
+       if (firstItemPosition == LIST_START)
+               firstItemPosition = 1;
+       else if (firstItemPosition == LIST_END)
+               firstItemPosition = (*list)->numItems;
 
-    memcpy (itemsDestination, ITEMPTR(list,firstItemPosition-1),
-        (*list)->itemSize * numItemsToGet);
+       memcpy (itemsDestination,
+               ITEMPTR (list, firstItemPosition - 1),
+               (*list)->itemSize * numItemsToGet);
 }
 
 /*******************************/
 
-    /*  Returns a pointer to the item at itemPosition. returns null if an errors occurred.
-    */
-void *  ListGetPtrToItem (list_t list, int itemPosition)
+/*
+ * Returns a pointer to the item at itemPosition. returns null if an
+ * errors occurred.
+ */
+void *ListGetPtrToItem (list_t list, int itemPosition)
 {
-    if (itemPosition == LIST_START)
-        itemPosition = 1;
-    else
-    if (itemPosition == LIST_END)
-        itemPosition = (*list)->numItems;
+       if (itemPosition == LIST_START)
+               itemPosition = 1;
+       else if (itemPosition == LIST_END)
+               itemPosition = (*list)->numItems;
 
-    return ITEMPTR(list,itemPosition-1);
+       return ITEMPTR (list, itemPosition - 1);
 }
 
 /*******************************/
 
-     /* returns a pointer the lists data (abstraction violation for optimization) */
-void *  ListGetDataPtr (list_t list)
+/*
+ * returns a pointer the lists data (abstraction violation for
+ * optimization)
+ */
+void *ListGetDataPtr (list_t list)
 {
-    return &((*list)->itemList[0]);
+       return &((*list)->itemList[0]);
 }
 
 /********************************/
 
 #ifdef CFG_ALL_LIST_FUNCTIONS
 
-int  ListApplyToEach (list_t list, int ascending, ListApplicationFunc funcToApply, void *callbackData)
-{
-    int result = 0, index;
-
-    if (!list || !funcToApply)
-        goto Error;
-
-    if (ascending)
-        {
-        for (index = 1; index <= ListNumItems (list); index++)
-            {
-            result  = funcToApply (index, ListGetPtrToItem (list, index),
-                callbackData);
-            if (result < 0)
-                goto Error;
-            }
-        }
-    else
-        {
-        for (index = ListNumItems (list); index > 0 &&
-            index <= ListNumItems (list); index--)
-            {
-            result  = funcToApply (index, ListGetPtrToItem (list, index),
-                callbackData);
-            if (result < 0)
-                goto Error;
-            }
-        }
+int ListApplyToEach (list_t list, int ascending,
+                    ListApplicationFunc funcToApply,
+                    void *callbackData)
+{
+       int result = 0, index;
+
+       if (!list || !funcToApply)
+               goto Error;
+
+       if (ascending) {
+               for (index = 1; index <= ListNumItems (list); index++) {
+                       result = funcToApply (index,
+                                             ListGetPtrToItem (list, index),
+                                             callbackData);
+                       if (result < 0)
+                               goto Error;
+               }
+       } else {
+               for (index = ListNumItems (list);
+                    index > 0 && index <= ListNumItems (list);
+                    index--) {
+                       result = funcToApply (index,
+                                             ListGetPtrToItem (list, index),
+                                             callbackData);
+                       if (result < 0)
+                               goto Error;
+               }
+       }
 
 Error:
-    return result;
+       return result;
 }
 
-#endif /* CFG_ALL_LIST_FUNCTIONS */
+#endif /* CFG_ALL_LIST_FUNCTIONS */
 
 /********************************/
 
-int  ListGetItemSize (list_t list)
+int ListGetItemSize (list_t list)
 {
-    return (*list)->itemSize;
+       return (*list)->itemSize;
 }
 
 /********************************/
 
-int  ListNumItems (list_t list)
+int ListNumItems (list_t list)
 {
-    return (*list)->numItems;
+       return (*list)->numItems;
 }
 
 /*******************************/
 
 #ifdef CFG_ALL_LIST_FUNCTIONS
 
-void  ListRemoveDuplicates (list_t list, CompareFunction compareFunction)
+void ListRemoveDuplicates (list_t list, CompareFunction compareFunction)
 {
-    int numItems, index, startIndexForFind, duplicatesIndex;
+       int numItems, index, startIndexForFind, duplicatesIndex;
 
-    numItems = ListNumItems (list);
+       numItems = ListNumItems (list);
 
-    for (index = 1; index < numItems; index++)
-        {
-        startIndexForFind = index + 1;
-        while (startIndexForFind <= numItems)
-            {
-            duplicatesIndex = ListFindItem (list, ListGetPtrToItem (list, index),
-                startIndexForFind, compareFunction);
-            if (duplicatesIndex > 0)
-                {
-                ListRemoveItem (list, NULL, duplicatesIndex);
-                numItems--;
-                startIndexForFind = duplicatesIndex;
-                }
-             else
-                break;
-            }
-        }
+       for (index = 1; index < numItems; index++) {
+               startIndexForFind = index + 1;
+               while (startIndexForFind <= numItems) {
+                       duplicatesIndex =
+                               ListFindItem (list,
+                                             ListGetPtrToItem (list, index),
+                                             startIndexForFind,
+                                             compareFunction);
+                       if (duplicatesIndex > 0) {
+                               ListRemoveItem (list, NULL, duplicatesIndex);
+                               numItems--;
+                               startIndexForFind = duplicatesIndex;
+                       } else {
+                               break;
+                       }
+               }
+       }
 }
 
 /*******************************/
@@ -603,93 +634,101 @@ void  ListRemoveDuplicates (list_t list, CompareFunction compareFunction)
 
 /*******************************/
 
-int  ListFindItem (list_t list, void *ptrToItem, int startingPosition, CompareFunction compareFunction)
+int ListFindItem (list_t list, void *ptrToItem, int startingPosition,
+                 CompareFunction compareFunction)
 {
-    int numItems, size, index, cmp;
-    void *listItemPtr;
+       int numItems, size, index, cmp;
+       void *listItemPtr;
 
-    if ((numItems = (*list)->numItems) == 0)
-        return 0;
+       if ((numItems = (*list)->numItems) == 0)
+               return 0;
 
-    size = (*list)->itemSize;
+       size = (*list)->itemSize;
 
-    if (startingPosition == LIST_START)
-        startingPosition = 1;
-    else
-    if (startingPosition == LIST_END)
-        startingPosition = numItems;
+       if (startingPosition == LIST_START)
+               startingPosition = 1;
+       else if (startingPosition == LIST_END)
+               startingPosition = numItems;
 
-    for (index = startingPosition; index <= numItems; index++)
-        {
-        listItemPtr = ITEMPTR(list,index-1);
-        cmp = compareFunction ? compareFunction(ptrToItem, listItemPtr)
-                              : ListMemBlockCmp(ptrToItem, listItemPtr, size);
-        if (cmp == 0)
-            return index;
-        }
+       for (index = startingPosition; index <= numItems; index++) {
+               listItemPtr = ITEMPTR (list, index - 1);
+               cmp = compareFunction
+                       ? compareFunction (ptrToItem, listItemPtr)
+                       : ListMemBlockCmp (ptrToItem, listItemPtr, size);
+               if (cmp == 0)
+                       return index;
+       }
 
-    return 0;
+       return 0;
 }
 
 /*******************************/
 
-int  ShortCompare(void *a, void *b)
+int ShortCompare (void *a, void *b)
 {
-    if (*(short *)a < *(short *)b) return -1;
-    if (*(short *)a > *(short *)b) return  1;
-    return 0;
+       if (*(short *) a < *(short *) b)
+               return -1;
+       if (*(short *) a > *(short *) b)
+               return 1;
+       return 0;
 }
 
 /*******************************/
 
-int  IntCompare(void *a, void *b)
+int IntCompare (void *a, void *b)
 {
-   if (*(int *)a < *(int *)b) return -1;
-   if (*(int *)a > *(int *)b) return  1;
-   return 0;
+       if (*(int *) a < *(int *) b)
+               return -1;
+       if (*(int *) a > *(int *) b)
+               return 1;
+       return 0;
 }
 
 /*******************************/
 
-int  CStringCompare(void *a, void *b)
+int CStringCompare (void *a, void *b)
 {
-    return strcmp(*(char **)a, *(char **)b);
+       return strcmp (*(char **) a, *(char **) b);
 }
 
 /*******************************/
 
 
-int  ListBinSearch (list_t list, void *ptrToItem, CompareFunction compareFunction)
+int ListBinSearch (list_t list, void *ptrToItem,
+                  CompareFunction compareFunction)
 {
-    int index;
+       int index;
 
-    index = BinSearch (ITEMPTR(list,0), (int)(*list)->numItems,
-        (int)(*list)->itemSize, ptrToItem, compareFunction);
+       index = BinSearch (ITEMPTR (list, 0),
+                          (int) (*list)->numItems,
+                          (int) (*list)->itemSize, ptrToItem,
+                          compareFunction);
 
-    if (index >= 0)
-        index++;        /* lists start from 1 */
-    else
-        index = 0;      /* item not found */
+       if (index >= 0)
+               index++;                        /* lists start from 1 */
+       else
+               index = 0;                      /* item not found */
 
-    return index;
+       return index;
 }
 
 /**************************************************************************/
 
-    /*  Reserves memory for numItems in the list. If it succeeds then
       numItems items can be inserted without possibility of an
-        out of memory error (useful to simplify error recovery in
-        complex functions). Returns 1 if success, 0 if
       out of memory.
   */
-int  ListPreAllocate (list_t list, int numItems)
+/*
* Reserves memory for numItems in the list. If it succeeds then
+ * numItems items can be inserted without possibility of an out of
+ * memory error (useful to simplify error recovery in complex
* functions). Returns 1 if success, 0 if out of memory.
+ */
+int ListPreAllocate (list_t list, int numItems)
 {
-
-    if ((*list)->listSize - (*list)->numItems < numItems)
-        return ExpandListSpace (list,
-            numItems - ((*list)->listSize - (*list)->numItems));
-    else
-        return 1;    /* enough items are already pre-allocated */
+       if ((*list)->listSize - (*list)->numItems < numItems) {
+               return ExpandListSpace (list,
+                                       numItems - ((*list)->listSize -
+                                               (*list)->numItems));
+       } else {
+               return 1;       /* enough items are already pre-allocated */
+       }
 }
 
-#endif /* CFG_ALL_LIST_FUNCTIONS */
+#endif /* CFG_ALL_LIST_FUNCTIONS */
diff --git a/common/usb.c b/common/usb.c
new file mode 100644 (file)
index 0000000..b9f577e
--- /dev/null
@@ -0,0 +1,1066 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * Most of this source has been derived from the Linux USB
+ * project.
+ *
+ * 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
+ *
+ */
+
+
+/*
+ * How it works:
+ * 
+ * Since this is a bootloader, the devices will not be automatic 
+ * (re)configured on hotplug, but after a restart of the USB the
+ * device should work.
+ *
+ * For each transfer (except "Interrupt") we wait for completion. 
+ */
+#include <ppcboot.h>
+#include <command.h>
+#include <asm/processor.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_USB)
+
+#include <usb.h>
+#ifdef CONFIG_4xx
+#include <405gp_pci.h>
+#endif
+
+
+
+#undef USB_DEBUG
+
+#ifdef USB_DEBUG
+#define        USB_PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define USB_PRINTF(fmt,args...)
+#endif
+
+static struct usb_device usb_dev[USB_MAX_DEVICE];
+static int dev_index;
+static int running;
+static int asynch_allowed;
+static struct devrequest setup_packet;
+
+/**********************************************************************
+ * some forward declerations...
+ */
+void usb_scan_devices(void);
+
+int usb_hub_probe(struct usb_device *dev, int ifnum);
+void usb_hub_reset(void);
+
+/***********************************************************************
+ * wait_ms
+ */
+
+void __inline__ wait_ms(unsigned long ms)
+{
+       while(ms-->0)
+               udelay(1000);
+}
+/***************************************************************************
+ * Init USB Device
+ */
+
+int usb_init(void)
+{
+       int result;
+       
+       running=0;
+       dev_index=0;
+       asynch_allowed=1;
+       usb_hub_reset();
+       /* init low_level USB */
+       printf("USB:   ");
+       result = usb_lowlevel_init();
+       /* if lowlevel init is OK, scan the bus for devices i.e. search HUBs and configure them */
+       if(result==0) {
+               printf("scanning bus for devices... ");
+               running=1;
+               usb_scan_devices();
+               return 0;
+       }
+       else {
+               printf("Error, couldn't init Lowlevel part\n");
+               return -1;
+       }
+}
+
+/******************************************************************************
+ * Stop USB this stops the LowLevel Part and deregisters USB devices.
+ */
+int usb_stop(void)
+{
+       asynch_allowed=1;
+       usb_hub_reset();
+       return usb_lowlevel_stop();
+}
+
+/*
+ * disables the asynch behaviour of the control message. This is used for data 
+ * transfers that uses the exclusiv access to the control and bulk messages.
+ */
+void usb_disable_asynch(int disable)
+{
+       asynch_allowed=!disable;
+}
+       
+
+/*-------------------------------------------------------------------
+ * Message wrappers.  
+ *  
+ */
+
+/* 
+ * submits an Interrupt Message 
+ */
+int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, 
+                       void *buffer,int transfer_len, int interval)
+{
+       return submit_int_msg(dev,pipe,buffer,transfer_len,interval);
+}
+
+/*
+ * submits a control message and waits for comletion (at least timeout * 1ms)
+ * If timeout is 0, we don't wait for completion (used as example to set and 
+ * clear keyboards LEDs). For data transfers, (storage transfers) we don't 
+ * allow control messages with 0 timeout, by previousely resetting the flag
+ * asynch_allowed (usb_disable_asynch(1)).
+ * returns the transfered length if OK or -1 if error. The transfered length
+ * and the current status are stored in the dev->act_len and dev->status.
+ */
+int usb_control_msg(struct usb_device *dev, unsigned int pipe,
+                       unsigned char request, unsigned char requesttype,
+                       unsigned short value, unsigned short index, 
+                       void *data, unsigned short size, int timeout)
+{
+       if((timeout==0)&&(!asynch_allowed)) /* request for a asynch control pipe is not allowed */
+               return -1;
+       /* set setup command */
+       setup_packet.requesttype = requesttype;
+       setup_packet.request = request;
+       setup_packet.value = swap_16(value);
+       setup_packet.index = swap_16(index);
+       setup_packet.length = swap_16(size);
+       USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X\nvalue 0x%X index 0x%X length 0x%X\n",
+               request,requesttype,value,index,size);
+       dev->status=USB_ST_NOT_PROC; /*not yet processed */
+       
+       submit_control_msg(dev,pipe,data,size,&setup_packet);
+       if(timeout==0) {
+               return (int)size;
+       }
+       while(timeout--) {
+               if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
+                       break;
+               wait_ms(1);
+       }
+       if(dev->status==0)
+               return dev->act_len;
+       else {
+               return -1;
+       }
+}              
+
+/*-------------------------------------------------------------------
+ * submits bulk message, and waits for completion. returns 0 if Ok or
+ * -1 if Error. 
+ * synchronous behavior 
+ */
+int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, 
+                       void *data, int len, int *actual_length, int timeout)
+{
+       if (len < 0)
+               return -1;
+       dev->status=USB_ST_NOT_PROC; /*not yet processed */
+       submit_bulk_msg(dev,pipe,data,len);
+       while(timeout--) {
+               if(!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
+                       break;
+               wait_ms(1);
+       }
+       *actual_length=dev->act_len;
+       if(dev->status==0)
+               return 0;
+       else 
+               return -1;
+}
+
+
+/*-------------------------------------------------------------------
+ * Max Packet stuff
+ */
+
+/*
+ * returns the max packet size, depending on the pipe direction and
+ * the configurations values 
+ */
+int usb_maxpacket(struct usb_device *dev,unsigned long pipe)
+{
+       if((pipe & USB_DIR_IN)==0) /* direction is out -> use emaxpacket out */
+               return(dev->epmaxpacketout[((pipe>>15) & 0xf)]);
+       else
+               return(dev->epmaxpacketin[((pipe>>15) & 0xf)]);
+}
+/*
+ * set the max packed value of all endpoints in the given configuration
+ */
+int usb_set_maxpacket(struct usb_device *dev)
+{
+       int i,ii,b;
+       struct usb_endpoint_descriptor *ep;
+       
+       for(i=0; i<dev->config.bNumInterfaces;i++) {
+               for(ii=0; ii<dev->config.if_desc[i].bNumEndpoints; ii++) {
+                       ep=&dev->config.if_desc[i].ep_desc[ii];
+                       b=ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+
+                       if((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)==USB_ENDPOINT_XFER_CONTROL) {        /* Control => bidirectional */
+                               dev->epmaxpacketout[b] = ep->wMaxPacketSize;
+                               dev->epmaxpacketin [b] = ep->wMaxPacketSize;
+                               USB_PRINTF("##Control EP epmaxpacketout/in[%d] = %d\n",b,dev->epmaxpacketin[b]);        
+                       }
+                       else {
+                               if ((ep->bEndpointAddress & 0x80)==0) { /* OUT Endpoint */
+                                       if(ep->wMaxPacketSize > dev->epmaxpacketout[b]) {
+                                               dev->epmaxpacketout[b] = ep->wMaxPacketSize;
+                                               USB_PRINTF("##EP epmaxpacketout[%d] = %d\n",b,dev->epmaxpacketout[b]);
+                                       }       
+                               } 
+                               else  { /* IN Endpoint */
+                                       if(ep->wMaxPacketSize > dev->epmaxpacketin[b]) {
+                                               dev->epmaxpacketin[b] = ep->wMaxPacketSize;
+                                               USB_PRINTF("##EP epmaxpacketin[%d] = %d\n",b,dev->epmaxpacketin[b]);
+                                       }       
+                               } /* if out */
+                       } /* if control */ 
+               } /* for each endpoint */
+       }
+       return 0;
+}
+
+/*******************************************************************************
+ * Parse the config, located in buffer, and fills the dev->config structure.
+ * Note that all little/big endian swapping are done automatically.
+ */  
+int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
+{
+       struct usb_descriptor_header *head;
+       int index,ifno,epno;
+       ifno=-1;
+       epno=-1;
+       
+       dev->configno=cfgno;
+       head =(struct usb_descriptor_header *)&buffer[0];
+       if(head->bDescriptorType!=USB_DT_CONFIG) { 
+               printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType);
+               return -1;
+       }
+       memcpy(&dev->config,buffer,buffer[0]);
+       dev->config.wTotalLength=swap_16(dev->config.wTotalLength);
+       dev->config.no_of_if=0;
+
+       index=dev->config.bLength;
+       /* Ok the first entry must be a configuration entry, now process the others */
+       head=(struct usb_descriptor_header *)&buffer[index];
+       while(index+1 < dev->config.wTotalLength) {
+               switch(head->bDescriptorType) {
+                       case USB_DT_INTERFACE:
+                               ifno=dev->config.no_of_if;
+                               dev->config.no_of_if++; /* found an interface desc, increase numbers */
+                               memcpy(&dev->config.if_desc[ifno],&buffer[index],buffer[index]); /* copy new desc */
+                               dev->config.if_desc[ifno].no_of_ep=0;
+                               
+                               break;
+                       case USB_DT_ENDPOINT:
+                               epno=dev->config.if_desc[ifno].no_of_ep;
+                               dev->config.if_desc[ifno].no_of_ep++; /* found an endpoint */
+                               memcpy(&dev->config.if_desc[ifno].ep_desc[epno],&buffer[index],buffer[index]);
+                               dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize
+                                       =swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize);
+                               USB_PRINTF("if %d, ep %d\n",ifno,epno);
+                               break;
+                       default:
+                               if(head->bLength==0)
+                                       return 1;
+                               USB_PRINTF("unknown Description Type : %x\n",head->bDescriptorType);
+                               {
+                                       int i;
+                                       unsigned char *ch;
+                                       ch=(unsigned char *)head;
+                                       for(i=0;i<head->bLength; i++)
+                                               USB_PRINTF("%02X ",*ch++);
+                                       USB_PRINTF("\n\n\n");
+                               }
+                               break;
+               }
+               index+=head->bLength;
+               head=(struct usb_descriptor_header *)&buffer[index];
+       }
+       return 1;
+}
+
+/*********************************************************************** 
+ * Clears an endpoint
+ * endp: endpoint number in bits 0-3;
+ * direction flag in bit 7 (1 = IN, 0 = OUT)
+ */
+int usb_clear_halt(struct usb_device *dev, int pipe)
+{
+       int result;
+       unsigned short status;
+       int endp=usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
+
+       result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 
+               USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, USB_CNTL_TIMEOUT * 3);
+
+       /* don't clear if failed */
+       if (result < 0)
+               return result;
+       result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
+               &status, sizeof(status), USB_CNTL_TIMEOUT * 3);
+       if (result < 0)
+               return result;
+       USB_PRINTF("usb_clear_halt: status 0x%x\n",status);
+       if (status & 1)
+               return -1;              /* still halted */
+       usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
+       /* toggle is reset on clear */
+       usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
+       return 0;
+}
+
+
+/**********************************************************************
+ * get_descriptor type
+ */            
+int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
+{
+       int res;
+       res = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+                       (type << 8) + index, 0, 
+                       buf, size, USB_CNTL_TIMEOUT);
+       return res;
+}
+
+/**********************************************************************
+ * gets configuration cfgno and store it in the buffer 
+ */
+int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno)
+{
+       int result;
+       unsigned int tmp;
+       struct usb_config_descriptor *config;
+       
+       
+       config=(struct usb_config_descriptor *)&buffer[0];
+       result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
+       if (result < 8) {
+               if (result < 0)
+                       printf("unable to get descriptor, error %lX\n",dev->status);
+               else
+                       printf("config descriptor too short (expected %i, got %i)\n",8,result);
+               return -1;
+       }
+       tmp=swap_16(config->wTotalLength);
+       
+       result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, tmp);
+       USB_PRINTF("get_conf_no %d Result %d, wLength %d\n",cfgno,result,tmp);
+       return result;
+}
+
+/********************************************************************
+ * set address of a device to the value in dev->devnum.
+ * This can only be done by addressing the device via the default address (0)
+ */
+int usb_set_address(struct usb_device *dev)
+{
+       int res;
+
+       USB_PRINTF("set address %d\n",dev->devnum);
+       res=usb_control_msg(dev, usb_snddefctrl(dev),
+               USB_REQ_SET_ADDRESS, 0,
+               (dev->devnum),0,
+               NULL,0, USB_CNTL_TIMEOUT);
+       return res;
+}
+
+/********************************************************************
+ * set interface number to interface
+ */
+int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+{
+       struct usb_interface_descriptor *if_face = NULL;
+       int ret, i;
+
+       for (i=0; i<dev->config.bNumInterfaces; i++) {
+               if (dev->config.if_desc[i].bInterfaceNumber == interface) {
+                       if_face = &dev->config.if_desc[i];
+                       break;
+               }
+       }
+       if (!if_face) {
+               printf("selecting invalid interface %d", interface);
+               return -1;
+       }
+
+       if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+           USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
+           interface, NULL, 0, USB_CNTL_TIMEOUT * 5)) < 0)
+               return ret;
+
+       if_face->act_altsetting = (unsigned char)alternate;
+       usb_set_maxpacket(dev);
+       return 0;
+}
+
+/********************************************************************
+ * set configuration number to configuration
+ */
+int usb_set_configuration(struct usb_device *dev, int configuration)
+{
+       int res;
+       USB_PRINTF("set configuration %d\n",configuration);
+       /* set setup command */
+       res=usb_control_msg(dev, usb_sndctrlpipe(dev,0),
+               USB_REQ_SET_CONFIGURATION, 0,
+               configuration,0,
+               NULL,0, USB_CNTL_TIMEOUT);
+       if(res==0) {
+               dev->toggle[0] = 0;
+               dev->toggle[1] = 0;
+               return 0;
+       }
+       else
+               return -1;
+}
+
+/********************************************************************
+ * set protocol to protocol
+ */
+int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol)
+{
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+               protocol, ifnum, NULL, 0, USB_CNTL_TIMEOUT);
+}
+
+/********************************************************************
+ * set idle
+ */
+int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id)
+{
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+               (duration << 8) | report_id, ifnum, NULL, 0, USB_CNTL_TIMEOUT);
+} 
+
+/********************************************************************
+ * get report
+ */
+int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size)
+{
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+               (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
+}
+
+/********************************************************************
+ * get class descriptor
+ */
+int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
+               unsigned char type, unsigned char id, void *buf, int size)
+{
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
+               (type << 8) + id, ifnum, buf, size, USB_CNTL_TIMEOUT);
+}
+
+/********************************************************************
+ * get string index in buffer 
+ */
+int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size)
+{
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+               (USB_DT_STRING << 8) + index, langid, buf, size, USB_CNTL_TIMEOUT);
+}
+
+/********************************************************************
+ * usb_string:
+ * Get string index and translate it to ascii.
+ * returns string length (> 0) or error (< 0)
+ */
+int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
+{
+       
+       unsigned char mybuf[256];
+       unsigned char *tbuf;
+       int err;
+       unsigned int u, idx;
+
+       if (size <= 0 || !buf || !index)
+               return -1;
+       buf[0] = 0;
+       tbuf=&mybuf[0];
+  
+       /* get langid for strings if it's not yet known */
+       if (!dev->have_langid) {
+               err = usb_get_string(dev, 0, 0, tbuf, 4);
+               if (err < 0) {
+                       USB_PRINTF("error getting string descriptor 0 (error=%x)\n",dev->status);
+                       return -1;
+               } else if (tbuf[0] < 4) {
+                       USB_PRINTF("string descriptor 0 too short\n");
+                       return -1;
+               } else {
+                       dev->have_langid = -1;
+                       dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
+                               /* always use the first langid listed */
+                       USB_PRINTF("USB device number %d default language ID 0x%x\n",
+                               dev->devnum, dev->string_langid);
+               }
+       }
+       /* Just ask for a maximum length string and then take the length
+        * that was returned. */
+       err = usb_get_string(dev, dev->string_langid, index, tbuf, 4);
+       if (err < 0)
+               return err;
+       u=tbuf[0];
+       USB_PRINTF("Strn Len %d, index %d\n",u,index);  
+       err = usb_get_string(dev, dev->string_langid, index, tbuf, u);
+       if (err < 0)  
+               return err;
+       size--;         /* leave room for trailing NULL char in output buffer */
+       for (idx = 0, u = 2; u < err; u += 2) {
+               if (idx >= size)
+                       break;
+               if (tbuf[u+1])                  /* high byte */
+                       buf[idx++] = '?';  /* non-ASCII character */
+               else
+                       buf[idx++] = tbuf[u];
+       }
+       buf[idx] = 0;
+       err = idx;
+       return err;
+}
+
+/********************************************************************
+ * USB device handling:
+ * the USB device are static allocated [USB_MAX_DEVICE].
+ */
+
+
+/* returns a pointer to the device with the index [index].
+ * if the device is not assigned (dev->devnum==-1) returns NULL
+ */ 
+struct usb_device * usb_get_dev_index(int index)
+{
+       if(usb_dev[index].devnum==-1)
+               return NULL;
+       else
+               return &usb_dev[index];
+}
+
+
+/* returns a pointer of a new device structure or NULL, if
+ * no device struct is available
+ */
+struct usb_device * usb_alloc_new_device(void)
+{
+       int i;
+       USB_PRINTF("New Device %d\n",dev_index);
+       if(dev_index==USB_MAX_DEVICE) {
+               printf("ERROR, to many USB Devices max=%d\n",USB_MAX_DEVICE);
+               return NULL;
+       }
+       usb_dev[dev_index].devnum=dev_index+1; /* default Address is 0, real addresses start with 1 */
+       usb_dev[dev_index].maxchild=0;
+       for(i=0;i<USB_MAXCHILDREN;i++)
+               usb_dev[dev_index].children[i]=NULL;
+       usb_dev[dev_index].parent=NULL;
+       dev_index++;
+       return &usb_dev[dev_index-1];
+}
+
+   
+/*
+ * By the time we get here, the device has gotten a new device ID 
+ * and is in the default state. We need to identify the thing and
+ * get the ball rolling..
+ *
+ * Returns 0 for success, != 0 for error.
+ */
+int usb_new_device(struct usb_device *dev)
+{
+       int addr, err; 
+       int tmp;
+       unsigned char tmpbuf[256];
+       dev->descriptor.bMaxPacketSize0 = 8;  /* Start off at 8 bytes  */
+       dev->maxpacketsize = 0;         /* Default to 8 byte max packet size */
+       dev->epmaxpacketin [0] = 8;
+       dev->epmaxpacketout[0] = 8;
+
+       /* We still haven't set the Address yet */
+       addr = dev->devnum;
+       dev->devnum = 0;
+       err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
+       if (err < 8) {
+               printf("\n      USB device not responding, giving up (status=%lX)\n",dev->status);
+               return 1;
+       }
+       dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
+       dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
+       switch (dev->descriptor.bMaxPacketSize0) {
+               case 8: dev->maxpacketsize = 0; break;
+               case 16: dev->maxpacketsize = 1; break;
+               case 32: dev->maxpacketsize = 2; break;
+               case 64: dev->maxpacketsize = 3; break;
+       }
+       dev->devnum = addr;
+
+       err = usb_set_address(dev); /* set address */
+       
+       if (err < 0) {
+               printf("\n      USB device not accepting new address (error=%lX)\n", dev->status);
+               return 1;
+       }
+
+       wait_ms(10);    /* Let the SET_ADDRESS settle */
+
+       tmp = sizeof(dev->descriptor);
+
+       err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor));
+       if (err < tmp) {
+               if (err < 0)
+                       printf("unable to get device descriptor (error=%d)\n",err);
+               else
+                       printf("USB device descriptor short read (expected %i, got %i)\n",tmp,err);
+               return 1;
+       }
+       /* correct le values */
+       dev->descriptor.bcdUSB=swap_16(dev->descriptor.bcdUSB);
+       dev->descriptor.idVendor=swap_16(dev->descriptor.idVendor);
+       dev->descriptor.idProduct=swap_16(dev->descriptor.idProduct);
+       dev->descriptor.bcdDevice=swap_16(dev->descriptor.bcdDevice);
+       /* only support for one config for now */
+       usb_get_configuration_no(dev,&tmpbuf[0],0);
+       usb_parse_config(dev,&tmpbuf[0],0);
+       usb_set_maxpacket(dev);
+       /* we set the default configuration here */
+       if (usb_set_configuration(dev, dev->config.bConfigurationValue)) {
+               printf("failed to set default configuration len %d, status %lX\n",dev->act_len,dev->status);
+               return -1;
+       }
+       USB_PRINTF("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
+               dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
+       memset(dev->mf, 0, sizeof(dev->mf));
+       memset(dev->prod, 0, sizeof(dev->prod));
+       memset(dev->serial, 0, sizeof(dev->serial));
+       if (dev->descriptor.iManufacturer)
+               usb_string(dev, dev->descriptor.iManufacturer, dev->mf, sizeof(dev->mf));
+       if (dev->descriptor.iProduct)
+               usb_string(dev, dev->descriptor.iProduct, dev->prod, sizeof(dev->prod));
+       if (dev->descriptor.iSerialNumber)
+               usb_string(dev, dev->descriptor.iSerialNumber, dev->serial, sizeof(dev->serial));
+       USB_PRINTF("Manufacturer %s\n", dev->mf);
+       USB_PRINTF("Product      %s\n", dev->prod);
+       USB_PRINTF("SerialNumber %s\n", dev->serial);
+       /* now prode if the device is a hub */
+       usb_hub_probe(dev,0);
+       return 0;
+}
+
+/* build device Tree  */
+void usb_scan_devices(void)
+{
+       int i;
+       struct usb_device *dev;
+       
+       /* first make all devices unknown */
+       for(i=0;i<USB_MAX_DEVICE;i++) {
+               memset(&usb_dev[i],0,sizeof(struct usb_device));
+               usb_dev[i].devnum=-1;
+       }
+       dev_index=0;
+       /* device 0 is always present (root hub, so let it analyze) */
+       dev=usb_alloc_new_device();
+       usb_new_device(dev);
+       printf("%d USB Devices found\n",dev_index);
+       /* insert "driver" if possible */
+#ifdef CONFIG_USB_KEYBOARD
+       drv_usb_kbd_init();
+       USB_PRINTF("scan end\n");
+#endif
+}
+
+
+/****************************************************************************
+ * HUB "Driver"
+ * Probes device for being a hub and configurate it
+ */
+#undef USB_HUB_DEBUG
+
+#ifdef USB_HUB_DEBUG
+#define        USB_HUB_PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define USB_HUB_PRINTF(fmt,args...)
+#endif
+
+
+static struct usb_hub_device hub_dev[USB_MAX_HUB];
+static int usb_hub_index;
+
+
+int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size)
+{
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+               USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
+               USB_DT_HUB << 8, 0, data, size, USB_CNTL_TIMEOUT);
+}
+
+int usb_clear_hub_feature(struct usb_device *dev, int feature)
+{
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, USB_CNTL_TIMEOUT);
+}
+
+int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
+{
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT);
+}
+
+int usb_set_port_feature(struct usb_device *dev, int port, int feature)
+{
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, USB_CNTL_TIMEOUT);
+}
+
+int usb_get_hub_status(struct usb_device *dev, void *data)
+{
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
+                       data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
+}
+
+int usb_get_port_status(struct usb_device *dev, int port, void *data)
+{
+       return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+                       USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
+                       data, sizeof(struct usb_hub_status), USB_CNTL_TIMEOUT);
+}
+
+
+static void usb_hub_power_on(struct usb_hub_device *hub)
+{
+       int i;
+       struct usb_device *dev;
+       
+       dev=hub->pusb_dev;
+       /* Enable power to the ports */
+       USB_HUB_PRINTF("enabling power on all ports\n");
+       for (i = 0; i < dev->maxchild; i++) {
+               usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
+               USB_HUB_PRINTF("port %d returns %lX\n",i+1,dev->status);
+               wait_ms(hub->desc.bPwrOn2PwrGood * 2);
+       }
+}
+
+void usb_hub_reset(void)
+{
+       usb_hub_index=0;
+}
+
+struct usb_hub_device *usb_hub_allocate(void)
+{
+       if(usb_hub_index<USB_MAX_HUB) {
+               return &hub_dev[usb_hub_index++];
+       }
+       printf("ERROR: USB_MAX_HUB (%d) reached\n",USB_MAX_HUB);
+       return NULL;
+}
+
+#define MAX_TRIES 5
+       
+void usb_hub_port_connect_change(struct usb_device *dev, int port)
+{
+       struct usb_device *usb;
+       struct usb_port_status portsts;
+       unsigned short portstatus, portchange;
+       int tries;
+
+       /* Check status */
+       if (usb_get_port_status(dev, port + 1, &portsts)<0) {
+               USB_HUB_PRINTF("get_port_status failed\n");
+               return;
+       }
+
+       portstatus = swap_16(portsts.wPortStatus);
+       portchange = swap_16(portsts.wPortChange);
+       USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus, portchange,
+               portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
+
+       /* Clear the connection change status */
+       usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_CONNECTION);
+
+       /* Disconnect any existing devices under this port */
+       if (((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
+            (!(portstatus & USB_PORT_STAT_ENABLE)))|| (dev->children[port])) {
+               USB_HUB_PRINTF("usb_disconnect(&hub->children[port]);\n");
+               /* Return now if nothing is connected */
+               if (!(portstatus & USB_PORT_STAT_CONNECTION))
+                       return;
+       }
+       wait_ms(200);   
+
+       /* Reset the port */
+
+       for(tries=0;tries<MAX_TRIES;tries++) {
+               
+               usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);
+               wait_ms(200);   
+               
+               if (usb_get_port_status(dev, port + 1, &portsts)<0) {
+                       USB_HUB_PRINTF("get_port_status failed status %lX\n",dev->status);
+                       return;
+               }
+               portstatus = swap_16(portsts.wPortStatus);
+               portchange = swap_16(portsts.wPortChange);
+               USB_HUB_PRINTF("portstatus %x, change %x, %s\n", portstatus ,portchange,
+                       portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
+               USB_HUB_PRINTF("STAT_C_CONNECTION = %d STAT_CONNECTION = %d  USB_PORT_STAT_ENABLE %d\n",
+                       (portchange & USB_PORT_STAT_C_CONNECTION) ? 1 : 0,
+                       (portstatus & USB_PORT_STAT_CONNECTION) ? 1 : 0,
+                       (portstatus & USB_PORT_STAT_ENABLE) ? 1 : 0);
+               if ((portchange & USB_PORT_STAT_C_CONNECTION) ||
+                   !(portstatus & USB_PORT_STAT_CONNECTION))
+                       return;
+
+               if (portstatus & USB_PORT_STAT_ENABLE)
+                       break;
+
+               wait_ms(200);
+       }
+
+       if (tries==MAX_TRIES) {
+               USB_HUB_PRINTF("Cannot enable port %i after %i retries, disabling port.\n", port+1, MAX_TRIES);
+               USB_HUB_PRINTF("Maybe the USB cable is bad?\n");
+               return;
+       }
+
+       usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_C_RESET);
+       wait_ms(200);
+
+       /* Allocate a new device struct for it */
+       usb=usb_alloc_new_device();
+       usb->slow = (portstatus & USB_PORT_STAT_LOW_SPEED) ? 1 : 0;
+
+       dev->children[port] = usb;
+       usb->parent=dev;
+       /* Run it through the hoops (find a driver, etc) */
+       if (usb_new_device(usb)) {
+               /* Woops, disable the port */
+               USB_HUB_PRINTF("hub: disabling port %d\n", port + 1);
+               usb_clear_port_feature(dev, port + 1, USB_PORT_FEAT_ENABLE);
+       }
+}
+
+
+int usb_hub_configure(struct usb_device *dev)
+{
+       unsigned char buffer[256], *bitmap;
+       struct usb_hub_descriptor *descriptor;
+       struct usb_hub_status *hubsts;
+       int i;
+       struct usb_hub_device *hub;
+
+       /* "allocate" Hub device */
+       hub=usb_hub_allocate();
+       if(hub==NULL)
+               return -1;
+       hub->pusb_dev=dev;
+       /* Get the the hub descriptor */
+       if (usb_get_hub_descriptor(dev, buffer, 4) < 0) {
+               USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor, giving up %lX\n",dev->status);
+               return -1;
+       }
+       descriptor = (struct usb_hub_descriptor *)buffer;
+       if (usb_get_hub_descriptor(dev, buffer, descriptor->bLength) < 0) {
+               USB_HUB_PRINTF("usb_hub_configure: failed to get hub descriptor 2nd giving up %lX\n",dev->status);
+               return -1;
+       }
+       memcpy((unsigned char *)&hub->desc,buffer,descriptor->bLength);
+       /* adjust 16bit values */
+       hub->desc.wHubCharacteristics=swap_16(descriptor->wHubCharacteristics);
+       /* set the bitmap */
+       bitmap=(unsigned char *)&hub->desc.DeviceRemovable[0];
+       memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* devices not removable by default */
+       bitmap=(unsigned char *)&hub->desc.PortPowerCtrlMask[0];
+       memset(bitmap,0xff,(USB_MAXCHILDREN+1+7)/8); /* PowerMask = 1B */
+       for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) {
+               hub->desc.DeviceRemovable[i]=descriptor->DeviceRemovable[i];
+       }
+       for(i=0;i<((hub->desc.bNbrPorts + 1 + 7)/8);i++) {
+               hub->desc.DeviceRemovable[i]=descriptor->PortPowerCtrlMask[i];
+       }
+       dev->maxchild = descriptor->bNbrPorts;
+       USB_HUB_PRINTF("%d ports detected\n", dev->maxchild);
+
+       switch (hub->desc.wHubCharacteristics & HUB_CHAR_LPSM) {
+               case 0x00:
+                       USB_HUB_PRINTF("ganged power switching\n");
+                       break;
+               case 0x01:
+                       USB_HUB_PRINTF("individual port power switching\n");
+                       break;
+               case 0x02:
+               case 0x03:
+                       USB_HUB_PRINTF("unknown reserved power switching mode\n");
+                       break;
+       }
+
+       if (hub->desc.wHubCharacteristics & HUB_CHAR_COMPOUND)
+               USB_HUB_PRINTF("part of a compound device\n");
+       else
+               USB_HUB_PRINTF("standalone hub\n");
+
+       switch (hub->desc.wHubCharacteristics & HUB_CHAR_OCPM) {
+               case 0x00:
+                       USB_HUB_PRINTF("global over-current protection\n");
+                       break;
+               case 0x08:
+                       USB_HUB_PRINTF("individual port over-current protection\n");
+                       break;
+               case 0x10:
+               case 0x18:
+                       USB_HUB_PRINTF("no over-current protection\n");
+      break;
+       }
+       USB_HUB_PRINTF("power on to power good time: %dms\n", descriptor->bPwrOn2PwrGood * 2);
+       USB_HUB_PRINTF("hub controller current requirement: %dmA\n", descriptor->bHubContrCurrent);
+       for (i = 0; i < dev->maxchild; i++)
+               USB_HUB_PRINTF("port %d is%s removable\n", i + 1,
+                       hub->desc.DeviceRemovable[(i + 1)/8] & (1 << ((i + 1)%8)) ? " not" : "");
+       if (usb_get_hub_status(dev, buffer) < 0) {
+               USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",dev->status);
+               return -1;
+       }
+       hubsts = (struct usb_hub_status *)buffer;
+       USB_HUB_PRINTF("get_hub_status returned status %X, change %X\n",
+               swap_16(hubsts->wHubStatus),swap_16(hubsts->wHubChange));
+       USB_HUB_PRINTF("local power source is %s\n",
+               (swap_16(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");
+       USB_HUB_PRINTF("%sover-current condition exists\n",
+               (swap_16(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no ");
+       usb_hub_power_on(hub);
+       for (i = 0; i < dev->maxchild; i++) {
+               struct usb_port_status portsts;
+               unsigned short portstatus, portchange;
+
+               if (usb_get_port_status(dev, i + 1, &portsts) < 0) {
+                       USB_HUB_PRINTF("get_port_status failed\n");
+                       continue;
+               }
+               portstatus = swap_16(portsts.wPortStatus);
+               portchange = swap_16(portsts.wPortChange);
+               USB_HUB_PRINTF("Port %d Status %X Change %X\n",i+1,portstatus,portchange);
+               if (portchange & USB_PORT_STAT_C_CONNECTION) {
+                       USB_HUB_PRINTF("port %d connection change\n", i + 1);
+                       usb_hub_port_connect_change(dev, i); 
+               }
+               if (portchange & USB_PORT_STAT_C_ENABLE) {
+                       USB_HUB_PRINTF("port %d enable change, status %x\n", i + 1, portstatus);
+                       usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
+
+                       /* EM interference sometimes causes bad shielded USB devices to 
+                        * be shutdown by the hub, this hack enables them again.
+                        * Works at least with mouse driver */ 
+                       if (!(portstatus & USB_PORT_STAT_ENABLE) && 
+                               (portstatus & USB_PORT_STAT_CONNECTION) && (dev->children[i])) {
+                               USB_HUB_PRINTF("already running port %i disabled by hub (EMI?), re-enabling...\n",
+                                       i + 1);
+                                       usb_hub_port_connect_change(dev, i);
+                       }
+               }
+               if (portstatus & USB_PORT_STAT_SUSPEND) {
+                       USB_HUB_PRINTF("port %d suspend change\n", i + 1);
+                       usb_clear_port_feature(dev, i + 1,  USB_PORT_FEAT_SUSPEND);
+               }
+                       
+               if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
+                       USB_HUB_PRINTF("port %d over-current change\n", i + 1);
+                       usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
+                       usb_hub_power_on(hub);
+               }
+
+               if (portchange & USB_PORT_STAT_C_RESET) {
+                       USB_HUB_PRINTF("port %d reset change\n", i + 1);
+                       usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
+               }
+       } /* end for i all ports */
+
+       return 0;
+}
+
+int usb_hub_probe(struct usb_device *dev, int ifnum)
+{
+       struct usb_interface_descriptor *iface;
+       struct usb_endpoint_descriptor *ep;
+       int ret;
+
+       iface = &dev->config.if_desc[ifnum];
+       /* Is it a hub? */
+       if (iface->bInterfaceClass != USB_CLASS_HUB)
+               return 0;
+       /* Some hubs have a subclass of 1, which AFAICT according to the */
+       /*  specs is not defined, but it works */
+       if ((iface->bInterfaceSubClass != 0) &&
+           (iface->bInterfaceSubClass != 1))
+               return 0;
+       /* Multiple endpoints? What kind of mutant ninja-hub is this? */
+       if (iface->bNumEndpoints != 1)
+               return 0;
+       ep = &iface->ep_desc[0];
+       /* Output endpoint? Curiousier and curiousier.. */
+       if (!(ep->bEndpointAddress & USB_DIR_IN))
+               return 0;
+       /* If it's not an interrupt endpoint, we'd better punt! */
+       if ((ep->bmAttributes & 3) != 3)
+               return 0;
+       /* We found a hub */
+       USB_HUB_PRINTF("USB hub found\n");
+       ret=usb_hub_configure(dev);
+       return ret;
+}
+
+#endif /* (CONFIG_COMMANDS & CFG_CMD_USB) */
+
+/* EOF */
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
new file mode 100644 (file)
index 0000000..5f5d619
--- /dev/null
@@ -0,0 +1,734 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * Part of this source has been derived from the Linux USB
+ * project.
+ *
+ * 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 <devices.h>
+
+#ifdef CONFIG_USB_KEYBOARD
+
+#include <usb.h>
+
+#undef USB_KBD_DEBUG
+/* 
+ * if overwrite_console returns 1, the stdin, stderr and stdout
+ * are switched to the serial port, else the settings in the 
+ * environment are used
+ */
+#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE
+extern int overwrite_console (void);
+#else
+int overwrite_console (void)
+{
+       return (0);
+}
+#endif
+
+#ifdef USB_KBD_DEBUG
+#define        USB_KBD_PRINTF(fmt,args...)     printf (fmt ,##args)
+#else
+#define USB_KBD_PRINTF(fmt,args...)
+#endif
+
+
+#define REPEAT_RATE  40/4 /* 40msec -> 25cps */
+#define REPEAT_DELAY 10 /* 10 x REAPEAT_RATE = 400msec */
+
+#define NUM_LOCK       0x53
+#define CAPS_LOCK 0x39
+#define SCROLL_LOCK 0x47
+
+
+/* Modifier bits */
+#define LEFT_CNTR              0
+#define LEFT_SHIFT     1
+#define LEFT_ALT               2
+#define LEFT_GUI               3
+#define RIGHT_CNTR     4
+#define RIGHT_SHIFT    5
+#define RIGHT_ALT              6
+#define RIGHT_GUI              7
+
+#define USB_KBD_BUFFER_LEN 0x20  /* size of the keyboardbuffer */
+
+static volatile char usb_kbd_buffer[USB_KBD_BUFFER_LEN];
+static volatile int usb_in_pointer = 0;
+static volatile int usb_out_pointer = 0;
+
+unsigned char new[8];
+unsigned char old[8]; 
+int repeat_delay;
+#define DEVNAME "usbkbd"
+static unsigned char num_lock = 0;
+static unsigned char caps_lock = 0;
+static unsigned char scroll_lock = 0;
+
+static unsigned char leds __attribute__ ((aligned (0x4)));
+
+static unsigned char usb_kbd_numkey[] = {
+        '1', '2', '3', '4', '5', '6', '7', '8', '9', '0','\r',0x1b,'\b','\t',' ', '-',
+        '=', '[', ']','\\', '#', ';', '\'', '`', ',', '.', '/'
+};
+static unsigned char usb_kbd_numkey_shifted[] = {
+        '!', '@', '#', '$', '%', '^', '&', '*', '(', ')','\r',0x1b,'\b','\t',' ', '_',
+        '+', '{', '}', '|', '~', ':', '"', '~', '<', '>', '?'
+};
+
+/******************************************************************
+ * Queue handling 
+ ******************************************************************/
+/* puts character in the queue and sets up the in and out pointer */
+static void usb_kbd_put_queue(char data)
+{
+       if((usb_in_pointer+1)==USB_KBD_BUFFER_LEN) {
+               if(usb_out_pointer==0) {
+                       return; /* buffer full */
+               } else{
+                       usb_in_pointer=0;
+               }
+       } else {
+               if((usb_in_pointer+1)==usb_out_pointer)
+                       return; /* buffer full */
+               usb_in_pointer++;
+       }
+       usb_kbd_buffer[usb_in_pointer]=data;
+       return;
+}
+
+/* test if a character is in the queue */
+static int usb_kbd_testc(void)
+{
+       if(usb_in_pointer==usb_out_pointer)
+               return(0); /* no data */
+       else
+               return(1);      
+}
+/* gets the character from the queue */
+static int usb_kbd_getc(void)
+{
+       char c;
+       while(usb_in_pointer==usb_out_pointer);
+       if((usb_out_pointer+1)==USB_KBD_BUFFER_LEN) 
+               usb_out_pointer=0;
+       else
+               usb_out_pointer++;
+       c=usb_kbd_buffer[usb_out_pointer];
+       return (int)c;
+       
+}
+
+/* forward decleration */
+static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum);
+
+/* search for keyboard and register it if found */
+int drv_usb_kbd_init(void)
+{
+       int error,i,index;
+       device_t usb_kbd_dev,*old_dev;
+       struct usb_device *dev;
+       char *stdinname  = getenv ("stdin");
+
+       usb_in_pointer=0;
+       usb_out_pointer=0;
+       /* scan all USB Devices */
+       for(i=0;i<USB_MAX_DEVICE;i++) {
+               dev=usb_get_dev_index(i); /* get device */
+               if(dev->devnum!=-1) {
+                       if(usb_kbd_probe(dev,0)==1) { /* Ok, we found a keyboard */
+                               /* check, if it is already registered */
+                               USB_KBD_PRINTF("USB KBD found set up device.\n");
+                               for (index=1; index<=ListNumItems(devlist); index++) {
+                                       old_dev = ListGetPtrToItem(devlist, index);
+                                       if(strcmp(old_dev->name,DEVNAME)==0) {
+                                               /* ok, already registered, just return ok */
+                                               USB_KBD_PRINTF("USB KBD is already registered.\n");
+                                               return 1;
+                                       }
+                               }
+                               /* register the keyboard */     
+                               USB_KBD_PRINTF("USB KBD register.\n");
+                               memset (&usb_kbd_dev, 0, sizeof(device_t));
+                               strcpy(usb_kbd_dev.name, DEVNAME);
+                               usb_kbd_dev.flags =  DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+                               usb_kbd_dev.putc = NULL;
+                               usb_kbd_dev.puts = NULL;
+                               usb_kbd_dev.getc = usb_kbd_getc;
+                               usb_kbd_dev.tstc = usb_kbd_testc;
+                               error = device_register (&usb_kbd_dev);
+                               if(error==0) {
+                                       /* check if this is the standard input device */
+                                       if(strcmp(stdinname,DEVNAME)==0) {
+                                               /* reassign the console */
+                                               if(overwrite_console()) {
+                                                       return 1;
+                                               }
+                                               error=console_assign(stdin,DEVNAME);
+                                               if(error==0)
+                                                       return 1;
+                                               else 
+                                                       return error;
+                                       }
+                                       return 1;
+                               }
+                               return error;
+                       }
+               }
+       }
+       /* no USB Keyboard found */
+       return -1;
+}
+
+
+/* deregistering the keyboard */
+int usb_kbd_deregister(void)
+{
+       return device_deregister(DEVNAME);
+}
+
+/**************************************************************************
+ * Low Level drivers
+ */
+
+/* set the LEDs. Since this is used in the irq routine, the control job
+   is issued with a timeout of 0. This means, that the job is queued without
+   waiting for job completion */
+   
+static void usb_kbd_setled(struct usb_device *dev)
+{
+       struct usb_interface_descriptor *iface;
+       iface = &dev->config.if_desc[0];
+       leds=0;
+       if(scroll_lock!=0)
+               leds|=1;
+       leds<<=1;
+       if(caps_lock!=0)
+               leds|=1;
+       leds<<=1;
+       if(num_lock!=0)
+               leds|=1;
+       usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+               USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+               0x200, iface->bInterfaceNumber,(void *)&leds, 1, 0);
+
+}
+
+
+#define CAPITAL_MASK 0x20
+/* Translate the scancode in ASCII */
+static int usb_kbd_translate(unsigned char scancode,unsigned char modifier,int pressed)
+{
+       unsigned char keycode;
+
+       if(pressed==0) { 
+               /* key released */
+               repeat_delay=0;
+               return 0;
+       }
+       if(pressed==2) {
+               repeat_delay++;
+               if(repeat_delay<REPEAT_DELAY)
+                       return 0;
+               repeat_delay=REPEAT_DELAY;
+       }
+       keycode=0;
+       if((scancode>3) && (scancode<0x1d)) { /* alpha numeric values */
+               keycode=scancode-4 + 0x61;
+               if(caps_lock)
+                       keycode&=~CAPITAL_MASK; /* switch to capital Letters */
+               if(((modifier&(1<<LEFT_SHIFT))!=0)||((modifier&(1<<RIGHT_SHIFT))!=0)) {
+                       if(keycode & CAPITAL_MASK)
+                               keycode&=~CAPITAL_MASK; /* switch to capital Letters */
+                       else
+                               keycode|=CAPITAL_MASK; /* switch to non capital Letters */
+               }
+       }
+       if((scancode>0x1d) && (scancode<0x3A)) {
+               if(((modifier&(1<<LEFT_SHIFT))!=0)||((modifier&(1<<RIGHT_SHIFT))!=0))  /* shifted */
+                       keycode=usb_kbd_numkey_shifted[scancode-0x1e];
+               else /* non shifted */
+                       keycode=usb_kbd_numkey[scancode-0x1e];
+       }
+       if(pressed==1) {
+               if(scancode==NUM_LOCK) {
+                       num_lock=~num_lock;
+                       return 1;
+               }
+               if(scancode==CAPS_LOCK) {
+                       caps_lock=~caps_lock;
+                       return 1;
+               }
+               if(scancode==SCROLL_LOCK) {
+                       scroll_lock=~scroll_lock;
+                       return 1;
+               }
+       }
+       if(keycode!=0) {
+               USB_KBD_PRINTF("%c",keycode);
+               usb_kbd_put_queue(keycode);
+       }
+       return 0;
+}
+
+/* Interrupt service routine */
+static int usb_kbd_irq(struct usb_device *dev)
+{
+       int i,res;
+       
+       if((dev->irq_status!=0)||(dev->irq_act_len!=8))
+       {
+               USB_KBD_PRINTF("usb_keyboard Error %lX, len %d\n",dev->irq_status,dev->irq_act_len);
+               return 1;
+       }
+       res=0;
+       for (i = 2; i < 8; i++) {
+               if (old[i] > 3 && memscan(&new[2], old[i], 6) == &new[8]) {
+                       res|=usb_kbd_translate(old[i],new[0],0);
+               }
+               if (new[i] > 3 && memscan(&old[2], new[i], 6) == &old[8]) {
+                       res|=usb_kbd_translate(new[i],new[0],1);
+               }
+       }
+       if((new[2]>3) && (old[2]==new[2])) /* still pressed */
+               res|=usb_kbd_translate(new[2],new[0],2);
+       if(res==1)
+               usb_kbd_setled(dev);
+       memcpy(&old[0],&new[0], 8);
+       return 1; /* install IRQ Handler again */ 
+}
+
+/* probes the USB device dev for keyboard type */
+static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
+{
+       struct usb_interface_descriptor *iface;
+       struct usb_endpoint_descriptor *ep;
+       int pipe,maxp;
+
+       if (dev->descriptor.bNumConfigurations != 1) return 0;
+       iface = &dev->config.if_desc[ifnum];
+
+       if (iface->bInterfaceClass != 3) return 0;
+       if (iface->bInterfaceSubClass != 1) return 0;
+       if (iface->bInterfaceProtocol != 1) return 0;
+       if (iface->bNumEndpoints != 1) return 0;
+
+       ep = &iface->ep_desc[0];
+       
+       if (!(ep->bEndpointAddress & 0x80)) return 0;
+       if ((ep->bmAttributes & 3) != 3) return 0;
+       USB_KBD_PRINTF("USB KBD found set protocol...\n");
+       /* ok, we found a USB Keyboard, install it */
+       /* usb_kbd_get_hid_desc(dev); */
+       usb_set_protocol(dev, iface->bInterfaceNumber, 0);
+       USB_KBD_PRINTF("USB KBD found set idle...\n");
+       usb_set_idle(dev, iface->bInterfaceNumber, REPEAT_RATE, 0);
+       memset(&new[0], 0, 8);
+       memset(&old[0], 0, 8);
+       repeat_delay=0;
+       pipe = usb_rcvintpipe(dev, ep->bEndpointAddress);
+       maxp = usb_maxpacket(dev, pipe);
+       dev->irq_handle=usb_kbd_irq;
+       USB_KBD_PRINTF("USB KBD enable interrupt pipe...\n");
+       usb_submit_int_msg(dev,pipe,&new[0], maxp > 8 ? 8 : maxp,ep->bInterval);
+       return 1;
+}
+
+
+#if 0
+struct usb_hid_descriptor {
+       unsigned char  bLength; 
+       unsigned char  bDescriptorType; /* 0x21 for HID */
+       unsigned short bcdHID; /* release number */
+       unsigned char  bCountryCode;
+       unsigned char  bNumDescriptors;
+       unsigned char  bReportDescriptorType;
+       unsigned short wDescriptorLength;
+} __attribute__ ((packed));
+       
+/*
+ * We parse each description item into this structure. Short items data
+ * values are expanded to 32-bit signed int, long items contain a pointer
+ * into the data area.
+ */
+
+struct hid_item {
+       unsigned char format;
+       unsigned char size;
+       unsigned char type;
+       unsigned char tag;
+       union {
+           unsigned char   u8;
+           char            s8;
+           unsigned short  u16;
+           short           s16;
+           unsigned long   u32;
+           long            s32;
+           unsigned char  *longdata;
+       } data;
+};
+
+/*
+ * HID report item format
+ */
+
+#define HID_ITEM_FORMAT_SHORT  0
+#define HID_ITEM_FORMAT_LONG   1
+
+/*
+ * Special tag indicating long items
+ */
+
+#define HID_ITEM_TAG_LONG      15
+
+       
+       
+static struct usb_hid_descriptor usb_kbd_hid_desc;
+
+void usb_kbd_display_hid(struct usb_hid_descriptor *hid)
+{
+       printf("USB_HID_DESC:\n");
+       printf("  bLenght               0x%x\n",hid->bLength);
+       printf("  bcdHID                0x%x\n",hid->bcdHID);
+       printf("  bCountryCode          %d\n",hid->bCountryCode);
+       printf("  bNumDescriptors       0x%x\n",hid->bNumDescriptors);
+       printf("  bReportDescriptorType 0x%x\n",hid->bReportDescriptorType);
+       printf("  wDescriptorLength     0x%x\n",hid->wDescriptorLength);
+}
+
+
+/*
+ * Fetch a report description item from the data stream. We support long
+ * items, though they are not used yet.
+ */
+
+static int fetch_item(unsigned char *start,unsigned char *end, struct hid_item *item)
+{
+       if((end - start) > 0) {
+               unsigned char b = *start++;
+               item->type = (b >> 2) & 3;
+               item->tag  = (b >> 4) & 15;
+               if (item->tag == HID_ITEM_TAG_LONG) {
+                       item->format = HID_ITEM_FORMAT_LONG;
+                       if ((end - start) >= 2) {
+                               item->size = *start++;
+                               item->tag  = *start++;
+                               if ((end - start) >= item->size) {
+                                       item->data.longdata = start;
+                                       start += item->size;
+                                       return item->size;
+                               }
+                       }
+               } else {
+                       item->format = HID_ITEM_FORMAT_SHORT;
+                       item->size = b & 3;
+                       switch (item->size) {
+                               case 0:
+                                       return item->size;
+                               case 1:
+                                       if ((end - start) >= 1) {
+                                               item->data.u8 = *start++;
+                                               return item->size;
+                                       }
+                                       break;
+                               case 2:
+                                       if ((end - start) >= 2) {
+                                               item->data.u16 = swap_16((unsigned short *)start);
+                                               start+=2;
+                                               return item->size;
+                                       }
+                               case 3:
+                                       item->size++;
+                                       if ((end - start) >= 4) {
+                                               item->data.u32 = swap_32((unsigned long *)start);
+                                               start+=4;
+                                               return item->size;
+                                       }
+                       }
+               }
+       }
+       return -1;
+}
+
+/*
+ * HID report descriptor item type (prefix bit 2,3)
+ */
+
+#define HID_ITEM_TYPE_MAIN             0
+#define HID_ITEM_TYPE_GLOBAL           1
+#define HID_ITEM_TYPE_LOCAL            2
+#define HID_ITEM_TYPE_RESERVED         3
+/*
+ * HID report descriptor main item tags
+ */
+
+#define HID_MAIN_ITEM_TAG_INPUT                        8
+#define HID_MAIN_ITEM_TAG_OUTPUT               9
+#define HID_MAIN_ITEM_TAG_FEATURE              11
+#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION     10
+#define HID_MAIN_ITEM_TAG_END_COLLECTION       12
+/*
+ * HID report descriptor main item contents
+ */
+
+#define HID_MAIN_ITEM_CONSTANT         0x001
+#define HID_MAIN_ITEM_VARIABLE         0x002
+#define HID_MAIN_ITEM_RELATIVE         0x004
+#define HID_MAIN_ITEM_WRAP             0x008   
+#define HID_MAIN_ITEM_NONLINEAR                0x010
+#define HID_MAIN_ITEM_NO_PREFERRED     0x020
+#define HID_MAIN_ITEM_NULL_STATE       0x040
+#define HID_MAIN_ITEM_VOLATILE         0x080
+#define HID_MAIN_ITEM_BUFFERED_BYTE    0x100
+
+/*
+ * HID report descriptor collection item types
+ */
+
+#define HID_COLLECTION_PHYSICAL                0
+#define HID_COLLECTION_APPLICATION     1
+#define HID_COLLECTION_LOGICAL         2
+/*
+ * HID report descriptor global item tags
+ */
+
+#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE         0
+#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM    1
+#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM    2
+#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM   3
+#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM   4
+#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT      5
+#define HID_GLOBAL_ITEM_TAG_UNIT               6
+#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE                7
+#define HID_GLOBAL_ITEM_TAG_REPORT_ID          8
+#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT       9
+#define HID_GLOBAL_ITEM_TAG_PUSH               10
+#define HID_GLOBAL_ITEM_TAG_POP                        11
+
+/*
+ * HID report descriptor local item tags
+ */
+
+#define HID_LOCAL_ITEM_TAG_USAGE               0
+#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM       1
+#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM       2
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX    3
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM  4
+#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM  5
+#define HID_LOCAL_ITEM_TAG_STRING_INDEX                7
+#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM      8
+#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM      9
+#define HID_LOCAL_ITEM_TAG_DELIMITER           10
+
+
+
+static void usb_kbd_show_item(struct hid_item *item)
+{
+       switch(item->type) {
+               case HID_ITEM_TYPE_MAIN:
+                       switch(item->tag) {
+                               case HID_MAIN_ITEM_TAG_INPUT:
+                                       printf("Main Input");
+                                       break;
+                               case HID_MAIN_ITEM_TAG_OUTPUT:
+                                       printf("Main Output");
+                                       break;
+                               case HID_MAIN_ITEM_TAG_FEATURE:
+                                       printf("Main Feature");
+                                       break;
+                               case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
+                                       printf("Main Begin Collection");
+                                       break;
+                               case HID_MAIN_ITEM_TAG_END_COLLECTION:
+                                       printf("Main End Collection");
+                                       break;
+                               default:
+                                       printf("Main reserved %d",item->tag);
+                                       break;
+                       }
+                       break;
+               case HID_ITEM_TYPE_GLOBAL:
+                       switch(item->tag) {
+                               case HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
+                                       printf("- Global Usage Page");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM:
+                                       printf("- Global Logical Minimum");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM:
+                                       printf("- Global Logical Maximum");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM:
+                                       printf("- Global physical Minimum");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM:
+                                       printf("- Global physical Maximum");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
+                                       printf("- Global Unit Exponent");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_UNIT:
+                                       printf("- Global Unit");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
+                                       printf("- Global Report Size");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_REPORT_ID:
+                                       printf("- Global Report ID");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
+                                       printf("- Global Report Count");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_PUSH:
+                                       printf("- Global Push");
+                                       break;
+                               case HID_GLOBAL_ITEM_TAG_POP:
+                                       printf("- Global Pop");
+                                       break;
+                               default:
+                                       printf("- Global reserved %d",item->tag);
+                                       break;
+                       }
+                       break;
+               case HID_ITEM_TYPE_LOCAL:
+                       switch(item->tag) {
+                               case HID_LOCAL_ITEM_TAG_USAGE:
+                                       printf("-- Local Usage");
+                                       break;
+                               case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM:
+                                       printf("-- Local Usage Minimum");
+                                       break;
+                               case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM:
+                                       printf("-- Local Usage Maximum");
+                                       break;
+                               case HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX:
+                                       printf("-- Local Designator Index");
+                                       break;
+                               case HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM:
+                                       printf("-- Local Designator Minimum");
+                                       break;
+                               case HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM:
+                                       printf("-- Local Designator Maximum");
+                                       break;
+                               case HID_LOCAL_ITEM_TAG_STRING_INDEX:
+                                       printf("-- Local String Index");
+                                       break;
+                               case HID_LOCAL_ITEM_TAG_STRING_MINIMUM:
+                                       printf("-- Local String Minimum");
+                                       break;
+                               case HID_LOCAL_ITEM_TAG_STRING_MAXIMUM:
+                                       printf("-- Local String Maximum");
+                                       break;
+                               case HID_LOCAL_ITEM_TAG_DELIMITER:
+                                       printf("-- Local Delimiter");
+                                       break;
+                               default:
+                                       printf("-- Local reserved %d",item->tag);
+                                       break;
+                       }
+                       break;
+               default:
+                       printf("--- reserved %d",item->type);
+                       break;
+       }
+       switch(item->size) {
+               case 1:
+                       printf("  %d",item->data.u8);
+                       break;
+               case 2:
+                       printf("  %d",item->data.u16);
+                       break;
+               case 4:
+                       printf("  %ld",item->data.u32);
+                       break;
+       }
+       printf("\n");           
+}
+                       
+
+
+static int usb_kbd_get_hid_desc(struct usb_device *dev)
+{
+       unsigned char buffer[256];
+       struct usb_descriptor_header *head;
+       struct usb_config_descriptor *config;
+       int index,len,i;
+       unsigned char *start, *end;
+       struct hid_item item;
+       
+       if(usb_get_configuration_no(dev,&buffer[0],0)==-1)
+               return -1;
+       head =(struct usb_descriptor_header *)&buffer[0];
+       if(head->bDescriptorType!=USB_DT_CONFIG) { 
+               printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType);
+               return -1;
+       }
+       index=head->bLength;
+       config=(struct usb_config_descriptor *)&buffer[0];
+       len=swap_16(config->wTotalLength);
+       /* Ok the first entry must be a configuration entry, now process the others */
+       head=(struct usb_descriptor_header *)&buffer[index];
+       while(index+1 < len) {
+               if(head->bDescriptorType==USB_DT_HID) {
+                       printf("HID desc found\n");
+                       memcpy(&usb_kbd_hid_desc,&buffer[index],buffer[index]);
+                       usb_kbd_hid_desc.bcdHID=swap_16(usb_kbd_hid_desc.bcdHID);
+                       usb_kbd_hid_desc.wDescriptorLength=swap_16(usb_kbd_hid_desc.wDescriptorLength);
+                       usb_kbd_display_hid(&usb_kbd_hid_desc);
+                       len=0;
+                       break;
+               }
+               index+=head->bLength;
+               head=(struct usb_descriptor_header *)&buffer[index];
+       }
+       if(len>0)
+               return -1;
+       len=usb_kbd_hid_desc.wDescriptorLength;
+       if((index = usb_get_class_descriptor(dev, 0, USB_DT_REPORT, 0, &buffer[0], len)) < 0) {
+               printf("reading report descriptor failed\n");
+               return -1;
+       }
+       printf(" report descriptor (size %u, read %d)\n", len, index);
+       start=&buffer[0];
+       end=&buffer[len];
+       i=0;
+       do {
+               index=fetch_item(start,end,&item);
+               i+=index;
+               i++;
+               if(index>=0)
+                       usb_kbd_show_item(&item);
+               
+               start+=index;
+               start++;
+       } while(index>=0);
+
+}
+
+
+#endif
+
+#endif /* CONFIG_USB_KEYBOARD */
+
+/* eof */
+
diff --git a/common/usb_storage.c b/common/usb_storage.c
new file mode 100644 (file)
index 0000000..9b84038
--- /dev/null
@@ -0,0 +1,895 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * Most of this source has been derived from the Linux USB
+ * project.
+ *
+ * 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
+ *
+ */
+
+/* Note:
+ * Currently only the CBI transport protocoll has been implemented, and it 
+ * is only tested with a TEAC USB Floppy. Other Massstorages with CBI or CB
+ * transport protocoll may work as well.
+ */
+
+
+
+#include <ppcboot.h>
+#include <command.h>
+#include <asm/processor.h>
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_USB)
+#include <usb.h>
+
+#ifdef CONFIG_USB_STORAGE 
+
+#undef USB_STOR_DEBUG
+
+#ifdef USB_STOR_DEBUG
+#define        USB_STOR_PRINTF(fmt,args...)    printf (fmt ,##args)
+#else
+#define USB_STOR_PRINTF(fmt,args...)
+#endif
+
+#include <scsi.h>
+/* direction table -- this indicates the direction of the data
+ * transfer for each command code -- a 1 indicates input
+ */
+unsigned char us_direction[256/8] = {
+       0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, 
+       0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
+
+static unsigned char usb_stor_buf[512];
+static ccb usb_ccb;
+
+/*
+ * CBI style
+ */
+
+#define US_CBI_ADSC            0
+
+
+#define USB_MAX_STOR_DEV 5
+static int usb_max_devs; /* number of highest available usb device */
+
+static block_dev_desc_t usb_dev_desc[USB_MAX_STOR_DEV];
+
+struct us_data;
+typedef int (*trans_cmnd)(ccb*, struct us_data*);
+typedef int (*trans_reset)(struct us_data*);
+
+struct us_data {
+       struct usb_device       *pusb_dev;       /* this usb_device */
+       unsigned int            flags;           /* from filter initially */
+       unsigned char           ifnum;           /* interface number */
+       unsigned char           ep_in;           /* in endpoint */
+       unsigned char           ep_out;          /* out ....... */
+       unsigned char           ep_int;          /* interrupt . */
+       unsigned char           subclass;        /* as in overview */
+       unsigned char           protocol;        /* .............. */
+       unsigned char           attention_done;  /* force attn on first cmd */
+       unsigned short  ip_data;         /* interrupt data */
+       int                                                     action;          /* what to do */
+       int                                                     ip_wanted; /* needed */
+       int                                                     *irq_handle;     /* for USB int requests */
+       unsigned int            irqpipe;         /* pipe for release_irq */
+       unsigned char           irqmaxp;        /* max packed for irq Pipe */
+       unsigned char   irqinterval; /* Intervall for IRQ Pipe */
+       ccb                                                     *srb;            /* current srb */
+       trans_reset                     transport_reset; /* reset routine */
+       trans_cmnd                      transport; /* transport routine */
+};
+
+static struct us_data usb_stor[USB_MAX_STOR_DEV];
+
+
+
+#define USB_STOR_TRANSPORT_GOOD    0
+#define USB_STOR_TRANSPORT_FAILED -1
+#define USB_STOR_TRANSPORT_ERROR  -2
+
+
+
+
+
+
+int usb_stor_get_info(struct usb_device *dev, struct us_data *us, block_dev_desc_t *dev_desc);
+int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data *ss);
+unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, unsigned long *buffer);
+struct usb_device * usb_get_dev_index(int index);
+void uhci_show_temp_int_td(void);
+
+block_dev_desc_t *usb_stor_get_dev(int index)
+{
+       return &usb_dev_desc[index];
+}
+
+
+void usb_show_progress(void)
+{
+       printf(".");
+}
+
+/*********************************************************************************
+ * (re)-scan the usb and reports device info
+ * to the user if mode = 1
+ * returns current device or -1 if no
+ */
+int usb_stor_scan(int mode)
+{
+       unsigned char i;
+       struct usb_device *dev;
+
+       if(mode==1) {
+               printf("scanning bus for storage devices...\n");
+       }
+       usb_disable_asynch(1); /* asynch transfer not allowed */
+       
+       for(i=0;i<USB_MAX_STOR_DEV;i++) {
+               memset(&usb_dev_desc[i],0,sizeof(block_dev_desc_t));
+               usb_dev_desc[i].target=0xff;
+               usb_dev_desc[i].if_type=IF_TYPE_SCSI;
+               usb_dev_desc[i].dev=i;
+               usb_dev_desc[i].part_type=PART_TYPE_UNKNOWN;
+               usb_dev_desc[i].block_read=usb_stor_read;
+       }
+       usb_max_devs=0;
+       for(i=0;i<USB_MAX_DEVICE;i++) {
+               dev=usb_get_dev_index(i); /* get device */
+               USB_STOR_PRINTF("i=%d\n",i);
+               if(dev==NULL) {
+                       break; /* no more devices avaiable */
+               }
+               if(usb_storage_probe(dev,0,&usb_stor[usb_max_devs])) { /* ok, it is a storage devices */
+                       /* get info and fill it in */
+                       
+                       if(usb_stor_get_info(dev, &usb_stor[usb_max_devs], &usb_dev_desc[usb_max_devs])) {
+                               if(mode==1) {
+                                       printf ("  Device %d: ", usb_max_devs);
+                                       dev_print(&usb_dev_desc[usb_max_devs]);
+                               } /* if mode */
+                               usb_max_devs++;
+                       } /* if get info ok */
+               } /* if storage device */ 
+               if(usb_max_devs==USB_MAX_STOR_DEV) {
+                       printf("max USB Storage Device reached: %d stopping\n",usb_max_devs);
+                       break;
+               }
+       } /* for */
+       usb_disable_asynch(0); /* asynch transfer allowed */
+       if(usb_max_devs>0)
+               return 0;
+       else
+               return-1;
+}                              
+
+static int usb_stor_irq(struct usb_device *dev)
+{
+       struct us_data *us;
+       us=(struct us_data *)dev->privptr;
+       
+       if(us->ip_wanted) {
+               us->ip_wanted=0;
+       }
+       return 0;
+}
+
+
+#ifdef USB_STOR_DEBUG
+
+static void usb_show_srb(ccb * pccb)
+{
+       int i;
+       printf("SRB: len %d datalen 0x%lX\n ",pccb->cmdlen,pccb->datalen);
+       for(i=0;i<12;i++) {
+               printf("%02X ",pccb->cmd[i]);
+       }
+       printf("\n");
+}
+
+static void display_int_status(unsigned long tmp)
+{
+       printf("Status: %s %s %s %s %s %s %s\n",
+               (tmp & USB_ST_ACTIVE) ? "Active" : "",
+               (tmp & USB_ST_STALLED) ? "Stalled" : "",
+               (tmp & USB_ST_BUF_ERR) ? "Buffer Error" : "",
+               (tmp & USB_ST_BABBLE_DET) ? "Babble Det" : "",
+               (tmp & USB_ST_NAK_REC) ? "NAKed" : "",
+               (tmp & USB_ST_CRC_ERR) ? "CRC Error" : "",
+               (tmp & USB_ST_BIT_ERR) ? "Bitstuff Error" : "");
+}
+#endif
+/***********************************************************************
+ * Data transfer routines
+ ***********************************************************************/
+
+static int us_one_transfer(struct us_data *us, int pipe, char *buf, int length)
+{
+       int max_size;
+       int this_xfer;
+       int result;
+       int partial;
+       int maxtry;
+       int stat;
+
+       /* determine the maximum packet size for these transfers */
+       max_size = usb_maxpacket(us->pusb_dev, pipe) * 16;
+
+       /* while we have data left to transfer */
+       while (length) {
+
+               /* calculate how long this will be -- maximum or a remainder */
+               this_xfer = length > max_size ? max_size : length;
+               length -= this_xfer;
+
+               /* setup the retry counter */
+               maxtry = 10;
+
+               /* set up the transfer loop */
+               do {
+                       /* transfer the data */
+                       USB_STOR_PRINTF("Bulk xfer 0x%x(%d) try #%d\n", 
+                                 (unsigned int)buf, this_xfer, 11 - maxtry);
+                       result = usb_bulk_msg(us->pusb_dev, pipe, buf,
+                                             this_xfer, &partial, USB_CNTL_TIMEOUT*5);
+                       USB_STOR_PRINTF("bulk_msg returned %d xferred %d/%d\n",
+                                 result, partial, this_xfer);
+                       if(us->pusb_dev->status!=0) {
+                               /* if we stall, we need to clear it before we go on */
+#ifdef USB_STOR_DEBUG
+                               display_int_status(us->pusb_dev->status);
+#endif
+                               if (us->pusb_dev->status & USB_ST_STALLED) {
+                                       USB_STOR_PRINTF("stalled ->clearing endpoint halt for pipe 0x%x\n", pipe);
+                                       stat = us->pusb_dev->status;
+                                       usb_clear_halt(us->pusb_dev, pipe);
+                                       us->pusb_dev->status=stat;
+                                       if(this_xfer == partial) {
+                                               USB_STOR_PRINTF("bulk transferred with error %X, but data ok\n",us->pusb_dev->status);
+                                               return 0;
+                                       }
+                                       else                            
+                                               return result;
+                               }
+                               if (us->pusb_dev->status & USB_ST_NAK_REC) {
+                                       USB_STOR_PRINTF("Device NAKed bulk_msg\n");
+                                       return result;
+                               }
+                               if(this_xfer == partial) {
+                                       USB_STOR_PRINTF("bulk transferred with error %d, but data ok\n",us->pusb_dev->status);
+                                       return 0;
+                               }
+                               /* if our try counter reaches 0, bail out */
+                               USB_STOR_PRINTF("bulk transferred with error %d, data %d\n",us->pusb_dev->status,partial);
+                               if (!maxtry--)
+                                               return result;
+                       }
+                       /* update to show what data was transferred */
+                       this_xfer -= partial;
+                       buf += partial;
+                       /* continue until this transfer is done */
+               } while ( this_xfer );
+       }
+
+       /* if we get here, we're done and successful */
+       return 0;
+} 
+
+/* FIXME: this reset function doesn't really reset the port, and it
+ * should. Actually it should probably do what it's doing here, and
+ * reset the port physically
+ */
+static int usb_stor_CB_reset(struct us_data *us)
+{
+       unsigned char cmd[12];
+       int result;
+
+       USB_STOR_PRINTF("CB_reset\n");
+       memset(cmd, 0xFF, sizeof(cmd));
+       cmd[0] = SCSI_SEND_DIAG;
+       cmd[1] = 4;
+       result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+                                US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                                0, us->ifnum, cmd, sizeof(cmd), USB_CNTL_TIMEOUT*5);
+
+       /* long wait for reset */
+       wait_ms(1500);
+       USB_STOR_PRINTF("CB_reset result %d: status %X clearing endpoint halt\n",result,us->pusb_dev->status);
+       usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_in));
+       usb_clear_halt(us->pusb_dev, usb_rcvbulkpipe(us->pusb_dev, us->ep_out));
+
+       USB_STOR_PRINTF("CB_reset done\n");
+       return 0;
+}
+
+/* FIXME: we also need a CBI_command which sets up the completion
+ * interrupt, and waits for it
+ */
+int usb_stor_CB_comdat(ccb *srb, struct us_data *us)
+{
+       int result;
+       int dir_in,retry;
+       unsigned int pipe;
+       unsigned long status;
+       
+       retry=5;
+               dir_in=US_DIRECTION(srb->cmd[0]);
+       
+               if(dir_in)
+                       pipe=usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
+               else
+                       pipe=usb_sndbulkpipe(us->pusb_dev, us->ep_out);
+       while(retry--) {
+               USB_STOR_PRINTF("CBI gets a command: Try %d\n",5-retry);
+#ifdef USB_STOR_DEBUG
+               usb_show_srb(srb);
+#endif
+               /* let's send the command via the control pipe */
+               result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
+                                        US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                                        0, us->ifnum,
+                                        srb->cmd, srb->cmdlen, USB_CNTL_TIMEOUT*5);
+               USB_STOR_PRINTF("CB_transport: control msg returned %d, status %X\n",result,us->pusb_dev->status);
+               /* check the return code for the command */
+               if (result < 0) {
+                       if(us->pusb_dev->status & USB_ST_STALLED) {
+                               status=us->pusb_dev->status;
+                               USB_STOR_PRINTF(" stall during command found, clear pipe\n");
+                               usb_clear_halt(us->pusb_dev,  usb_sndctrlpipe(us->pusb_dev,0));
+                               us->pusb_dev->status=status;
+                       }
+                       USB_STOR_PRINTF(" error during command %02X Stat = %X\n",srb->cmd[0],us->pusb_dev->status);
+                       return result; 
+               }
+               /* transfer the data payload for this command, if one exists*/
+               
+               USB_STOR_PRINTF("CB_transport: control msg returned %d, direction is %s to go 0x%lx\n",result,dir_in ? "IN" : "OUT",srb->datalen);
+               if (srb->datalen) {
+                       result = us_one_transfer(us, pipe, srb->pdata,srb->datalen);
+                       USB_STOR_PRINTF("CBI attempted to transfer data, result is %d status %lX, len %d\n", result,us->pusb_dev->status,us->pusb_dev->act_len);
+                       if(!(us->pusb_dev->status & USB_ST_NAK_REC))
+                               break;
+               } /* if (srb->datalen) */
+               else
+                       break;
+       }       
+       /* return result */
+       
+       return result;
+}
+
+
+int usb_stor_CBI_get_status(ccb *srb, struct us_data *us)
+{
+       int timeout;                    
+
+       us->ip_wanted=1;
+       submit_int_msg(us->pusb_dev,us->irqpipe,
+                       (void *)&us->ip_data,us->irqmaxp ,us->irqinterval);
+  timeout=1000;
+  while(timeout--) {
+       if((volatile int *)us->ip_wanted==0)
+                       break;
+               wait_ms(10);
+       }
+       if (us->ip_wanted) {
+               printf("       Did not get interrupt on CBI\n");
+               us->ip_wanted = 0;
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+       USB_STOR_PRINTF("Got interrupt data 0x%x, transfered %d status 0x%lX\n", us->ip_data,us->pusb_dev->irq_act_len,us->pusb_dev->irq_status);
+       /* UFI gives us ASC and ASCQ, like a request sense */
+       if (us->subclass == US_SC_UFI) {
+               if (srb->cmd[0] == SCSI_REQ_SENSE ||
+                   srb->cmd[0] == SCSI_INQUIRY)
+                       return USB_STOR_TRANSPORT_GOOD; /* Good */
+               else
+                       if (us->ip_data)
+                               return USB_STOR_TRANSPORT_FAILED;
+                       else
+                               return USB_STOR_TRANSPORT_GOOD;
+       } 
+       /* otherwise, we interpret the data normally */
+       switch (us->ip_data) {
+               case 0x0001: 
+                       return USB_STOR_TRANSPORT_GOOD;
+               case 0x0002: 
+                       return USB_STOR_TRANSPORT_FAILED;
+               default: 
+                       return USB_STOR_TRANSPORT_ERROR;
+       } /* switch */
+       return USB_STOR_TRANSPORT_ERROR;
+}
+
+#define USB_TRANSPORT_UNKNOWN_RETRY 5
+#define USB_TRANSPORT_NOT_READY_RETRY 10
+
+int usb_stor_CB_transport(ccb *srb, struct us_data *us)
+{
+       int result,status;
+       ccb *psrb;
+       ccb reqsrb;
+       int retry,notready;
+       
+       psrb=&reqsrb;
+       status=USB_STOR_TRANSPORT_GOOD;
+       retry=0;
+       notready=0;
+       /* issue the command */
+do_retry:
+       result=usb_stor_CB_comdat(srb,us);
+       USB_STOR_PRINTF("command / Data returned %d, status %X\n",result,us->pusb_dev->status);
+       /* if this is an CBI Protocol, get IRQ */
+       if(us->protocol==US_PR_CBI) {
+               status=usb_stor_CBI_get_status(srb,us);
+               /* if the status is error, report it */
+               if(status==USB_STOR_TRANSPORT_ERROR) {
+                       USB_STOR_PRINTF(" USB CBI Command Error\n");
+                       return status;
+               }
+               srb->sense_buf[12]=(unsigned char)(us->ip_data>>8);
+               srb->sense_buf[13]=(unsigned char)(us->ip_data&0xff);
+               if(!us->ip_data) {
+               /* if the status is good, report it */
+                       if(status==USB_STOR_TRANSPORT_GOOD) {
+                               USB_STOR_PRINTF(" USB CBI Command Good\n");
+                               return status;
+                       }
+               }
+       }
+       /* do we have to issue an auto request? */
+       /* HERE we have to check the result */
+       if((result<0) && !(us->pusb_dev->status & USB_ST_STALLED)) {
+               USB_STOR_PRINTF("ERROR %X\n",us->pusb_dev->status);
+               us->transport_reset(us);
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+       if((us->protocol==US_PR_CBI) &&
+                       ((srb->cmd[0]==SCSI_REQ_SENSE) || 
+                       (srb->cmd[0]==SCSI_INQUIRY))) { /* do not issue an autorequest after request sense */
+               USB_STOR_PRINTF("No auto request and good\n");
+               return USB_STOR_TRANSPORT_GOOD;
+       }
+       /* issue an request_sense */
+       memset(&psrb->cmd[0],0,12);
+       psrb->cmd[0]=SCSI_REQ_SENSE;
+       psrb->cmd[1]=srb->lun<<5;
+       psrb->cmd[4]=18;
+       psrb->datalen=18;
+       psrb->pdata=&srb->sense_buf[0];
+       psrb->cmdlen=12;
+       /* issue the command */
+       result=usb_stor_CB_comdat(psrb,us);
+       USB_STOR_PRINTF("auto request returned %d\n",result);
+       /* if this is an CBI Protocol, get IRQ */
+       if(us->protocol==US_PR_CBI) {
+               status=usb_stor_CBI_get_status(psrb,us);
+       }
+       if((result<0)&&!(us->pusb_dev->status & USB_ST_STALLED)) {
+               USB_STOR_PRINTF(" AUTO REQUEST ERROR %d\n",us->pusb_dev->status);
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+       USB_STOR_PRINTF("autorequest returned 0x%02X 0x%02X 0x%02X 0x%02X\n",srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
+       /* Check the auto request result */
+       if((srb->sense_buf[2]==0) &&
+                (srb->sense_buf[12]==0) &&
+                (srb->sense_buf[13]==0)) /* ok, no sense */
+               return USB_STOR_TRANSPORT_GOOD;
+       /* Check the auto request result */
+       switch(srb->sense_buf[2]) {
+               case 0x01: /* Recovered Error */
+                       return USB_STOR_TRANSPORT_GOOD;
+                       break;
+               case 0x02: /* Not Ready */
+                       if(notready++ > USB_TRANSPORT_NOT_READY_RETRY) {
+                               printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X (NOT READY)\n",
+                                       srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
+                               return USB_STOR_TRANSPORT_FAILED;
+                       }
+                       else {
+                               wait_ms(100);
+                               goto do_retry;
+                       }
+                       break;
+               default:
+                       if(retry++ > USB_TRANSPORT_UNKNOWN_RETRY) {
+                               printf("cmd 0x%02X returned 0x%02X 0x%02X 0x%02X 0x%02X\n",
+                                       srb->cmd[0],srb->sense_buf[0],srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
+                               return USB_STOR_TRANSPORT_FAILED;
+                       }
+                       else
+                               goto do_retry;
+                       break;
+       }
+       return USB_STOR_TRANSPORT_FAILED;
+}
+
+
+
+static int usb_inquiry(ccb *srb,struct us_data *ss)
+{
+       int retry,i;
+       retry=3;
+       do {
+               memset(&srb->cmd[0],0,12);
+               srb->cmd[0]=SCSI_INQUIRY;
+               srb->cmd[1]=srb->lun<<5;
+               srb->cmd[4]=36;
+               srb->datalen=36;
+               srb->cmdlen=12;
+               i=ss->transport(srb,ss);
+               USB_STOR_PRINTF("inquiry returns %d\n",i);
+               if(i==0)
+                       break;
+       }while(retry--);
+       if(!retry) {
+               printf("error in inquiry\n");
+               return -1;
+       }
+       return 0;
+}
+
+static int usb_request_sense(ccb *srb,struct us_data *ss)
+{
+       char *ptr;
+       return 0;
+       ptr=srb->pdata;
+       memset(&srb->cmd[0],0,12);
+       srb->cmd[0]=SCSI_REQ_SENSE;
+       srb->cmd[1]=srb->lun<<5;
+       srb->cmd[4]=18;
+       srb->datalen=18;
+       srb->pdata=&srb->sense_buf[0];
+       srb->cmdlen=12;
+       ss->transport(srb,ss);
+       USB_STOR_PRINTF("Request Sense returned %02X %02X %02X\n",srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
+       srb->pdata=ptr;
+       return 0;
+}
+
+static int usb_test_unit_ready(ccb *srb,struct us_data *ss)
+{
+       int retries=10;
+       do {
+               memset(&srb->cmd[0],0,12);
+               srb->cmd[0]=SCSI_TST_U_RDY;
+               srb->cmd[1]=srb->lun<<5;
+               srb->datalen=0;
+               srb->cmdlen=12;
+               if(ss->transport(srb,ss)==USB_STOR_TRANSPORT_GOOD)
+               {
+                       return 0;
+               }
+       } while(retries--);
+       return -1;
+}
+
+static int usb_read_capacity(ccb *srb,struct us_data *ss)
+{
+       int retry;
+       retry=2; /* retries */
+       do {
+               memset(&srb->cmd[0],0,12);
+               srb->cmd[0]=SCSI_RD_CAPAC;
+               srb->cmd[1]=srb->lun<<5;
+               srb->datalen=8;
+               srb->cmdlen=12;
+               if(ss->transport(srb,ss)==USB_STOR_TRANSPORT_GOOD) {
+                       return 0;
+               }
+       }while(retry--);
+       return -1;
+}
+
+static int usb_read_10(ccb *srb,struct us_data *ss, unsigned long start, unsigned short blocks)
+{
+       memset(&srb->cmd[0],0,12);
+       srb->cmd[0]=SCSI_READ10;
+       srb->cmd[1]=srb->lun<<5;
+       srb->cmd[2]=((unsigned char) (start>>24))&0xff;
+       srb->cmd[3]=((unsigned char) (start>>16))&0xff;
+       srb->cmd[4]=((unsigned char) (start>>8))&0xff;
+       srb->cmd[5]=((unsigned char) (start))&0xff;
+       srb->cmd[7]=((unsigned char) (blocks>>8))&0xff;
+       srb->cmd[8]=(unsigned char) blocks & 0xff;
+       srb->cmdlen=12;
+       USB_STOR_PRINTF("read10: start %lx blocks %x\n",start,blocks);
+       return ss->transport(srb,ss);
+}
+
+
+#define USB_MAX_READ_BLK 20 
+
+unsigned long usb_stor_read(int device, unsigned long blknr, unsigned long blkcnt, unsigned long *buffer)
+{
+       unsigned long start,blks, buf_addr;
+       unsigned short smallblks;
+       struct usb_device *dev;
+       int retry,i;
+       ccb *srb=&usb_ccb;
+       device&=0xff;
+       /* Setup  device
+        */
+       USB_STOR_PRINTF("\nusb_read: dev %d \n",device);
+       dev=NULL;
+       for(i=0;i<USB_MAX_DEVICE;i++) {
+               dev=usb_get_dev_index(i);
+               if(dev==NULL) {
+                       return 0;
+               }
+               if(dev->devnum==usb_dev_desc[device].target)
+                       break;
+       }
+
+       usb_disable_asynch(1); /* asynch transfer not allowed */
+       srb->lun=usb_dev_desc[device].lun;
+       buf_addr=(unsigned long)buffer;
+       start=blknr;
+       blks=blkcnt;
+       if(usb_test_unit_ready(srb,(struct us_data *)dev->privptr)) {
+               printf("Device NOT ready\n   Request Sense returned %02X %02X %02X\n",
+                       srb->sense_buf[2],srb->sense_buf[12],srb->sense_buf[13]);
+               return 0;
+       }
+       USB_STOR_PRINTF("\nusb_read: dev %d startblk %lx, blccnt %lx buffer %lx\n",device,start,blks, buf_addr);
+       do {
+               retry=2;
+               srb->pdata=(unsigned char *)buf_addr;
+               if(blks>USB_MAX_READ_BLK) {
+                       smallblks=USB_MAX_READ_BLK;
+               }
+               else {
+                       smallblks=(unsigned short) blks;
+               }
+retry_it:
+               if(smallblks==USB_MAX_READ_BLK)
+                       usb_show_progress();
+               srb->datalen=usb_dev_desc[device].blksz * smallblks;
+               srb->pdata=(unsigned char *)buf_addr;
+               if(usb_read_10(srb,(struct us_data *)dev->privptr, start, smallblks)) {
+                       USB_STOR_PRINTF("Read ERROR\n");
+                       usb_request_sense(srb,(struct us_data *)dev->privptr);
+                       if(retry--)
+                               goto retry_it;
+                       blkcnt-=blks;
+                       break;
+               }
+               start+=smallblks;
+               blks-=smallblks;
+               buf_addr+=srb->datalen;
+       } while(blks!=0);
+       USB_STOR_PRINTF("usb_read: end startblk %lx, blccnt %x buffer %lx\n",start,smallblks,buf_addr);
+       usb_disable_asynch(0); /* asynch transfer allowed */
+       if(blkcnt>=USB_MAX_READ_BLK)
+               printf("\n");
+       return(blkcnt);
+}
+
+
+/* Probe to see if a new device is actually a Storage device */
+int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,struct us_data *ss)
+{
+       struct usb_interface_descriptor *iface;
+       int i;
+       unsigned int flags = 0;
+       
+       int protocol = 0;
+       int subclass = 0;
+
+       
+       memset(ss, 0, sizeof(struct us_data));
+       
+       /* let's examine the device now */
+       iface = &dev->config.if_desc[ifnum];
+
+#if 0
+       /* this is the place to patch some storage devices */
+       USB_STOR_PRINTF("iVendor %X iProduct %X\n",dev->descriptor.idVendor,dev->descriptor.idProduct);
+       if ((dev->descriptor.idVendor) == 0x066b && (dev->descriptor.idProduct) == 0x0103) {
+               USB_STOR_PRINTF("patched for E-USB\n");
+               protocol = US_PR_CB;
+               subclass = US_SC_UFI;       /* an assumption */
+       } 
+#endif
+       
+       if (dev->descriptor.bDeviceClass != 0 ||
+                       iface->bInterfaceClass != USB_CLASS_MASS_STORAGE ||
+                       iface->bInterfaceSubClass < US_SC_MIN ||
+                       iface->bInterfaceSubClass > US_SC_MAX) {
+               /* if it's not a mass storage, we go no further */
+               return 0;
+       }
+
+       /* At this point, we know we've got a live one */
+       USB_STOR_PRINTF("\n\nUSB Mass Storage device detected\n");
+
+       /* Initialize the us_data structure with some useful info */
+       ss->flags = flags;
+       ss->ifnum = ifnum;
+       ss->pusb_dev = dev;
+       ss->attention_done = 0;
+
+       /* If the device has subclass and protocol, then use that.  Otherwise, 
+        * take data from the specific interface.
+        */
+       if (subclass) {
+               ss->subclass = subclass;
+               ss->protocol = protocol;
+       } else {
+               ss->subclass = iface->bInterfaceSubClass;
+               ss->protocol = iface->bInterfaceProtocol;
+       }
+
+       /* set the handler pointers based on the protocol */
+       USB_STOR_PRINTF("Transport: ");
+       switch (ss->protocol) {
+       case US_PR_CB:
+               USB_STOR_PRINTF("Control/Bulk\n");
+               ss->transport = usb_stor_CB_transport;
+               ss->transport_reset = usb_stor_CB_reset;
+               break;
+
+       case US_PR_CBI:
+               USB_STOR_PRINTF("Control/Bulk/Interrupt\n");
+               ss->transport = usb_stor_CB_transport;
+               ss->transport_reset = usb_stor_CB_reset;
+               break;
+       default:
+               printf("USB Starage Transport unknown / not yet implemented\n");
+               return 0;
+               break;
+       }
+
+       /*
+        * We are expecting a minimum of 2 endpoints - in and out (bulk).
+        * An optional interrupt is OK (necessary for CBI protocol).
+        * We will ignore any others.
+        */
+       for (i = 0; i < iface->bNumEndpoints; i++) {
+               /* is it an BULK endpoint? */
+               if ((iface->ep_desc[i].bmAttributes &  USB_ENDPOINT_XFERTYPE_MASK)
+                   == USB_ENDPOINT_XFER_BULK) {
+                       if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
+                               ss->ep_in = iface->ep_desc[i].bEndpointAddress &
+                                       USB_ENDPOINT_NUMBER_MASK;
+                       else
+                               ss->ep_out = iface->ep_desc[i].bEndpointAddress &
+                                       USB_ENDPOINT_NUMBER_MASK;
+               }
+
+               /* is it an interrupt endpoint? */
+               if ((iface->ep_desc[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) 
+                   == USB_ENDPOINT_XFER_INT) {
+                       ss->ep_int = iface->ep_desc[i].bEndpointAddress &
+                               USB_ENDPOINT_NUMBER_MASK;
+                       ss->irqinterval = iface->ep_desc[i].bInterval;
+               }
+       }
+       USB_STOR_PRINTF("Endpoints In %d Out %d Int %d\n",
+                 ss->ep_in, ss->ep_out, ss->ep_int);
+
+       /* Do some basic sanity checks, and bail if we find a problem */
+       if (usb_set_interface(dev, iface->bInterfaceNumber, 0) ||
+           !ss->ep_in || !ss->ep_out || 
+           (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
+               USB_STOR_PRINTF("Problems with device\n");
+               return 0;
+       }
+       /* set class specific stuff */
+       /* We only handle certain protocols.  Currently, this is
+        * the only one.
+        */
+       if (ss->subclass != US_SC_UFI) {
+               printf("Sorry, protocol %d not yet supported.\n",ss->subclass);
+               return 0;
+       }
+       if(ss->ep_int) /* we had found an interrupt endpoint, prepare irq pipe */
+       {
+               /* set up the IRQ pipe and handler */
+       
+               ss->irqinterval = (ss->irqinterval > 0) ? ss->irqinterval : 255; 
+               ss->irqpipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int);
+               ss->irqmaxp = usb_maxpacket(dev, ss->irqpipe);
+               dev->irq_handle=usb_stor_irq;
+               dev->privptr=(void *)ss;
+       }
+       return 1;
+}
+
+int usb_stor_get_info(struct usb_device *dev,struct us_data *ss,block_dev_desc_t *dev_desc)
+{
+       unsigned char perq,modi;
+       unsigned long cap[2];
+       unsigned long *capacity,*blksz;
+       ccb *pccb=&usb_ccb;
+
+       ss->transport_reset(ss);
+       pccb->pdata=usb_stor_buf;
+       
+       dev_desc->target=dev->devnum;
+       pccb->lun=dev_desc->lun;
+       USB_STOR_PRINTF(" address %d\n",dev_desc->target);
+       
+       if(usb_inquiry(pccb,ss))
+               return -1;
+       perq=usb_stor_buf[0];
+       modi=usb_stor_buf[1];
+       if((perq & 0x1f)==0x1f) {
+               return 0; /* skip unknown devices */
+       }
+       if((modi&0x80)==0x80) {/* drive is removable */
+               dev_desc->removable=1;
+       }
+       memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8);
+       memcpy(&dev_desc->product[0], &usb_stor_buf[16], 16);
+       memcpy(&dev_desc->revision[0], &usb_stor_buf[32], 4);
+       dev_desc->vendor[8]=0;
+       dev_desc->product[16]=0;
+       dev_desc->revision[4]=0;
+       USB_STOR_PRINTF("ISO Vers %X, Response Data %X\n",usb_stor_buf[2],usb_stor_buf[3]);     
+       if(usb_test_unit_ready(pccb,ss)) {
+               printf("Device NOT ready\n   Request Sense returned %02X %02X %02X\n",pccb->sense_buf[2],pccb->sense_buf[12],pccb->sense_buf[13]);
+               if(dev_desc->removable==1) {
+                       dev_desc->type=perq;
+                       return 1;
+               }
+               else
+                       return 0;
+       }
+       pccb->pdata=(unsigned char *)&cap[0];
+       memset(pccb->pdata,0,8);
+       if(usb_read_capacity(pccb,ss)!=0) {
+               printf("READ_CAP ERROR\n");
+               cap[0]=2880;
+               cap[1]=0x200;
+       }
+       USB_STOR_PRINTF("Read Capacity returns: 0x%lx, 0x%lx\n",cap[0],cap[1]);
+#if 0
+       if(cap[0]>(0x200000 * 10)) /* greater than 10 GByte */
+               cap[0]>>=16;  
+#endif
+       cap[0]+=1;
+       capacity=&cap[0];
+       blksz=&cap[1];
+       USB_STOR_PRINTF("Capacity = 0x%lx, blocksz = 0x%lx\n",*capacity,*blksz);
+       dev_desc->lba=*capacity;
+       dev_desc->blksz=*blksz;
+       dev_desc->type=perq;
+       USB_STOR_PRINTF(" address %d\n",dev_desc->target);
+       USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type);
+       
+       init_part(dev_desc);
+       
+       USB_STOR_PRINTF("partype: %d\n",dev_desc->part_type);
+       return 1;
+}                              
+
+#endif
+#endif /* CONFIG_USB_STORAGE */
+
+
index 8cc3dddb9cce79f993db75fb2e721f4e944b8eee..030e497efd4a40d0a36d88fcab02a53d205e6ea9 100644 (file)
@@ -68,7 +68,7 @@
 #include <405gp_pci.h>
 #include <asm/processor.h>
 
-#ifndef CONFIG_PIP405
+#if !(defined(CONFIG_PIP405) || defined (CONFIG_MIP405)) 
 
 void pciinfo(int bus_no);
 
index 4cb5246e9d497b41320ce46b4444143ea90d8341..aa2b38f797e2c03dec6f1dd2d7a8f24abbe5ab87 100644 (file)
@@ -109,8 +109,9 @@ int i2c_transfer(unsigned char command_is_reading, unsigned char address,
   int bytes_transfered;
   int result;
   int status;
-  int i, TimeReady, TimeOut;
+  int i, TimeReady;
   ulong freqOPB,freqProc;
+  ulong TimeOut; /* _must_ be unsigned long for fast speeds */
 
   result = IIC_OK;
   bytes_transfered = 0;
@@ -146,8 +147,9 @@ int i2c_transfer(unsigned char command_is_reading, unsigned char address,
 
   /* IIC time out => wait for TimeOut cycles */
   /* TimeOut /= 2; because waiting-loop is 2-instruction loop */
-  TimeOut = freqProc*IIC_TIMEOUT*10;
-  TimeOut /= 2;
+  /* Take care we get no overflow (266MHz = 0x0FDAD680) first divide */
+  TimeOut = freqProc/2;
+  TimeOut *= IIC_TIMEOUT*10;
 
   while ((bytes_transfered < size_to_transfer) && (result == IIC_OK))
     {
index 2e938940ee8b4c289ac724d19698545b9290b117..59ca1f4043337dc1a3dddb8ba8a377ca425d452b 100644 (file)
 
 #if (CONFIG_COMMANDS & CFG_CMD_IDE) || (CONFIG_COMMANDS & CFG_CMD_SCSI)
 
-/* stdlib.h causes some compatibility problems; should fixe these! -- wd */
-#ifndef __ldiv_t_defined
-typedef struct {
-       long int quot;          /* Quotient     */
-       long int rem;           /* Remainder    */
-} ldiv_t;
-extern ldiv_t ldiv (long int __numer, long int __denom);
-# define __ldiv_t_defined      1
-#endif
-
-
 /* ------------------------------------------------------------------------- */
 /*
  * reports device info to the user
  */
-void dev_print(block_dev_desc_t *dev_desc)
+void dev_print (block_dev_desc_t *dev_desc)
 {
-       ldiv_t mb, gb;
        ulong lba512; /* number of blocks if 512bytes block size */
+
        if (dev_desc->type==DEV_TYPE_UNKNOWN) {
-               printf("not available\n");
+               puts ("not available\n");
                return;
        }
-       if(dev_desc->if_type==IF_TYPE_SCSI)  {
+       if (dev_desc->if_type==IF_TYPE_SCSI)  {
                printf ("(%d:%d) ", dev_desc->target,dev_desc->lun);
        }
-       if(dev_desc->if_type==IF_TYPE_IDE) {
+       if (dev_desc->if_type==IF_TYPE_IDE) {
                printf ("Model: %s Firm: %s Ser#: %s\n",
                        dev_desc->vendor,
                        dev_desc->revision,
@@ -73,40 +62,43 @@ void dev_print(block_dev_desc_t *dev_desc)
                        dev_desc->product,
                        dev_desc->revision);
        }
-       printf("            Type: ");
-       if(dev_desc->removable)
-               printf ("Removable ");
-       switch(dev_desc->type & 0x1F) {
-               case DEV_TYPE_HARDDISK: printf("Hard Disk");
+       puts ("            Type: ");
+       if (dev_desc->removable)
+               puts ("Removable ");
+       switch (dev_desc->type & 0x1F) {
+               case DEV_TYPE_HARDDISK: puts ("Hard Disk");
                                        break;
-               case DEV_TYPE_CDROM:    printf("CD ROM");
+               case DEV_TYPE_CDROM:    puts ("CD ROM");
                                        break;
-               case DEV_TYPE_OPDISK:   printf("Optical Device");
+               case DEV_TYPE_OPDISK:   puts ("Optical Device");
                                        break;
-               case DEV_TYPE_TAPE:     printf("Tape");
+               case DEV_TYPE_TAPE:     puts ("Tape");
                                        break;
-               default:                printf("# %02X #", dev_desc->type & 0x1F);
+               default:                printf ("# %02X #", dev_desc->type & 0x1F);
                                        break;
        }
-       printf("\n");
-       if((dev_desc->lba * dev_desc->blksz)>0L) {
-               lba512=(dev_desc->lba * (dev_desc->blksz/512));
-               mb = ldiv(lba512, 2048); /* (1024 *1024 / 512 MB */
+       puts ("\n");
+       if ((dev_desc->lba * dev_desc->blksz)>0L) {
+               ulong mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
+
+               lba512 = (dev_desc->lba * (dev_desc->blksz/512));
+
+               mb = (10 * lba512) / 2048;      /* 2048 = (1024 * 1024) / 512 MB */
                /* round to 1 digit */
-               mb.rem *= 10 * 512;
-               mb.rem += 512 * 1024;
-               mb.rem /= 1024 * 1024;
-               gb = ldiv(10 * mb.quot + mb.rem, 10240);
-               gb.rem += 512;
-               gb.rem /= 1024;
+               mb_quot = mb / 10;
+               mb_rem  = mb - (10 * mb_quot);
+
+               gb = mb / 1024;
+               gb_quot = gb / 10;
+               gb_rem  = gb - (10 * gb_quot);
+
                printf ("            Capacity: %ld.%ld MB = %ld.%ld GB (%ld x %ld)\n",
-                       mb.quot, mb.rem,
-                       gb.quot, gb.rem,
+                       mb_quot, mb_rem,
+                       gb_quot, gb_rem,
                        dev_desc->lba,
                        dev_desc->blksz);
-       }
-       else {
-               printf ("            Capacity: not available\n");
+       } else {
+               puts ("            Capacity: not available\n");
        }
 }
 
@@ -141,9 +133,9 @@ void init_part (block_dev_desc_t * dev_desc)
 }
 
 
-int get_partition_info(block_dev_desc_t *dev_desc, int part, disk_partition_t *info)
+int get_partition_info (block_dev_desc_t *dev_desc, int part, disk_partition_t *info)
 {
-               switch(dev_desc->part_type) {
+               switch (dev_desc->part_type) {
 #ifdef CONFIG_MAC_PARTITION
        case PART_TYPE_MAC:
                if (get_partition_info_mac(dev_desc,part,info) == 0) {
@@ -178,25 +170,25 @@ int get_partition_info(block_dev_desc_t *dev_desc, int part, disk_partition_t *i
 
 static void print_part_header (const char *type, block_dev_desc_t * dev_desc)
 {
-       printf ("\nPartition Map for ");
-       switch(dev_desc->if_type) {
-               case IF_TYPE_IDE:       printf("IDE");
+       puts ("\nPartition Map for ");
+       switch (dev_desc->if_type) {
+               case IF_TYPE_IDE:       puts ("IDE");
                                        break;
-               case IF_TYPE_SCSI:      printf("SCSI");
+               case IF_TYPE_SCSI:      puts ("SCSI");
                                        break;
-               case IF_TYPE_ATAPI:     printf("ATAPI");
+               case IF_TYPE_ATAPI:     puts ("ATAPI");
                                        break;
-               default:                printf("UNKNOWN");
+               default:                puts ("UNKNOWN");
                                        break;
        }
-       printf(" device %d  --   Partition Type: %s\n\n",
+       printf (" device %d  --   Partition Type: %s\n\n",
                        dev_desc->dev, type);
 }
 
 void print_part (block_dev_desc_t * dev_desc)
 {
 
-               switch(dev_desc->part_type) {
+               switch (dev_desc->part_type) {
 #ifdef CONFIG_MAC_PARTITION
        case PART_TYPE_MAC:
                PRINTF ("## Testing for valid MAC partition ##\n");
@@ -220,7 +212,7 @@ void print_part (block_dev_desc_t * dev_desc)
                return;
 #endif
        }
-       printf ("## Unknown partition table\n");
+       puts ("## Unknown partition table\n");
 }
 
 
index 44552c7a7ac85c119fef3ef04f16987298e3e207..c19e1f5623bf8c2d255b8b3c8a63e4c2084018fb 100644 (file)
@@ -87,5 +87,7 @@ spiinfo               3
 stack          5
 step           4
 tftpboot       4
+usbboot                5
+usb            4
 version                4
 ?              1
diff --git a/doc/README.usb b/doc/README.usb
new file mode 100644 (file)
index 0000000..fa5fbec
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ */
+
+USB Support for PIP405 and MIP405 (UHCI)
+========================================
+
+The USB support is implemented on the base of the UHCI Host
+controller.
+
+Currently supported are USB Hubs, USB Keyboards and USB Floppys.
+Tested with a TEAC Floppy TEAC FD-05PUB and Chicony KU-8933 Keyboard.
+
+How it works:
+-------------
+
+The USB (at least the USB UHCI) needs a frame list (4k), transfer
+descripor and queue headers which are all located in the main memory.
+The UHCI allocates every milisecond the PCI bus and reads the current
+frame pointer. This may cause to crash the OS during boot. So the USB
+_MUST_ be stopped during OS boot. This is the reason, why the USB is
+NOT automatically started during start-up. If someone needs the USB
+he has to start it and should therefore be aware that he had to stop
+it before booting the OS.
+
+For USB keyboards this can be done by a script which is automatically
+started after the ppcboot is up and running. To boot an OS with a an
+USB keyboard another script is necessary, which first disables the
+USB and then executes the boot command. If the boot command fails,
+the script can reenable the USB kbd.
+
+Common USB Commands:
+- usb start:
+- usb reset:       (re)starts the USB. All USB devices will be
+                   initialized and a device tree is build for them.
+- usb tree:        shows all USB devices in a tree like display
+- usb info [dev]:   shows all USB infos of the device dev, or of all
+                   the devices
+- usb stop [f]:            stops the USB. If f==1 the USB will also stop if
+                   an USB keyboard is assigned as stdin. The stdin
+                   is then switched to serial input.
+Storage USB Commands:
+- usb scan:        scans the USB for storage devices.The USB must be
+                   running for this command (usb start)
+- usb device [dev]: show or set current USB staorage device
+- usb part [dev]:   print partition table of one or all USB storage
+                   devices
+- usb read addr blk# cnt:
+                   read `cnt' blocks starting at block `blk#'to
+                   memory address `addr'
+- usbboot addr dev:part:
+                   boot from USB device
+
+Config Switches:
+----------------
+CFG_CMD_USB        enables basic USB support and the usb command
+CONFIG_USB_UHCI            defines the lowlevel part.A lowlevel part must be defined if
+                   using CFG_CMD_USB
+CONFIG_USB_KEYBOARD enables the USB Keyboard
+CONFIG_USB_STORAGE  enables the USB storage devices
index 570a3a8e8bb364a41a065e2590c0629cc6b907ec..cbe6a9276601149de7d4a7bdbdd42e5c7be0b167 100644 (file)
@@ -79,6 +79,20 @@ int do_pip405 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
 
 #endif /* CONFIG_PIP405 */
 /* ----------------------------------------------------------------------------*/
+/* ----- MIP405 -----------------------------------------------------------------
+ */
+#if defined(CONFIG_MIP405)
+
+#define        CMD_TBL_BSP MK_CMD_TBL_ENTRY(                           \
+       "mip405",       4,      6,      1,      do_mip405,                      \
+       "mip405  - MIP405 specific Cmds\n",                                     \
+       "flash mem [SrcAddr] - updates PPCBOOT with image in memory\n"                                  \
+       "mip405 flash mps - updates PPCBOOT with image from MPS\n"                                      \
+),
+int do_mip405 (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_MIP405 */
+/* ----------------------------------------------------------------------------*/
 
 /* ----- DASA_SIM ---------------------------------------------------------------
  */
index 2e339c035e7362eb0bb3bdfe50079d40a8259cd1..824293070309ad87bf0cc7a6bc7585988bc76821 100644 (file)
@@ -66,6 +66,7 @@
 
 #define CFG_CMD_ELF    0x0000000100000000      /* ELF (VxWorks) load/boot cmd  */
 #define CFG_CMD_MISC   0x0000000200000000      /* Misc functions like sleep etc*/
+#define CFG_CMD_USB     0x0000000400000000      /* USB Support                 */
 
 #define CFG_CMD_ALL    0xFFFFFFFFFFFFFFFF      /* ALL commands                 */
 
@@ -89,6 +90,7 @@
                        CFG_CMD_DATE    | \
                        CFG_CMD_BEDBUG  | \
                        CFG_CMD_ELF     | \
+                       CFG_CMD_USB     | \
                        CFG_CMD_MII     | \
                        CFG_CMD_BSP     )
 
diff --git a/include/cmd_usb.h b/include/cmd_usb.h
new file mode 100644 (file)
index 0000000..f1917d7
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#ifndef        _CMD_USB_H
+#define        _CMD_USB_H
+
+#include <ppcboot.h>
+#include <command.h>
+
+
+#if (CONFIG_COMMANDS & CFG_CMD_USB)
+
+#ifdef CONFIG_USB_STORAGE
+#define        CMD_TBL_USB     MK_CMD_TBL_ENTRY(                                       \
+       "usb",  4,      5,      1,      do_usb,                         \
+       "usb     - USB sub-system\n",                                           \
+       "reset - reset (rescan) USB controller\n"                                       \
+       "usb  stop [f]  - stop USB [f]=force stop\n"                            \
+       "usb  tree  - show USB device tree\n"                           \
+       "usb  info [dev] - show available USB devices\n"                                \
+       "usb  scan  - (re-)scan USB bus for storage devices\n"                                  \
+       "usb  device [dev] - show or set current USB staorage device\n"                 \
+       "usb  part [dev] - print partition table of one or all USB storage devices\n"   \
+       "usb  read addr blk# cnt - read `cnt' blocks starting at block `blk#'\n"\
+       "     to memory address `addr'\n"                                       \
+),
+
+
+#define        CMD_TBL_USBBOOT MK_CMD_TBL_ENTRY(                                       \
+       "usbboot",      5,      3,      1,      do_usbboot,                                     \
+       "usbboot - boot from USB device\n",                                             \
+       "loadAddr dev:part\n"                   \
+),
+
+#else
+#define        CMD_TBL_USB     MK_CMD_TBL_ENTRY(                                       \
+       "usb",  4,      5,      1,      do_usb,                         \
+       "usb     - USB sub-system\n",                                           \
+       "reset - reset (rescan) USB controller\n"                                       \
+       "usb  tree  - show USB device tree\n"                           \
+       "usb  info [dev] - show available USB devices\n"                                \
+),
+
+#define CMD_TBL_USBBOOT
+#endif 
+
+int do_usb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+int do_usbboot (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+
+
+#else
+#define CMD_TBL_USB
+#define CMD_TBL_USBBOOT
+#endif
+
+#endif /* _CMD_SCSI_H */
+
index fefc7fd808d9bde8603c0fd04ebb1eabcd541829..1be4dcec2b6b7dbc8f85a665b384a7ee8f1c7b2f 100644 (file)
@@ -95,6 +95,7 @@
                                             & ~CFG_CMD_MII     \
                                             & ~CFG_CMD_PCI     \
                                             & ~CFG_CMD_PCMCIA  \
+                                            & ~CFG_CMD_USB     \
                                             & ~CFG_CMD_SCSI    )
 
 #if CONFIG_LANTEC >= 2
diff --git a/include/config_MIP405.h b/include/config_MIP405.h
new file mode 100644 (file)
index 0000000..3e155de
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+ * (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_405GP   1       /* This is a PPC405 CPU         */
+#define CONFIG_4xx             1       /* ...member of PPC4xx family   */
+#define CONFIG_MIP405          1       /* ...on a MIP405 board */
+/***********************************************************
+ * Clock
+ ***********************************************************/
+#define CONFIG_SYS_CLK_FREQ  33000000 /* external frequency to pll   */
+
+/***********************************************************
+ * Command definitions
+ ***********************************************************/
+#define CONFIG_COMMANDS                \
+               (CONFIG_CMD_DFL | \
+                       CFG_CMD_IDE     | \
+                       CFG_CMD_DHCP    | \
+                       CFG_CMD_PCI     | \
+                       CFG_CMD_IRQ     | \
+                       CFG_CMD_EEPROM  | \
+                       CFG_CMD_I2C     | \
+                       CFG_CMD_REGINFO | \
+                       CFG_CMD_DATE    | \
+                       CFG_CMD_ELF     | \
+                       CFG_CMD_USB     | \
+                       CFG_CMD_MII     | \
+                       CFG_CMD_BSP     )
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS  (if any) */
+#include <cmd_confdefs.h>
+
+#define  CFG_HUSH_PARSER
+#define  CFG_PROMPT_HUSH_PS2 "> "
+/**************************************************************
+ * I2C Stuff:
+ * the PIP405 is equiped with an Atmel 24C128/256 EEPROM at address
+ * 0x53.
+ * Caution: on the same bus is the SPD (Serial Presens Detect
+ * EEPROM of the SDRAM
+ * The Atmel EEPROM uses 16Bit addressing.
+ ***************************************************************/
+#define CONFIG_I2C405 
+#define CONFIG_I2C
+#define CONFIG_I2C_X
+#define CFG_I2C_EEPROM_ADDR                    0x53
+#define CFG_ENV_IS_IN_EEPROM    1        /* use EEPROM for environment vars */
+#define CFG_ENV_OFFSET          0x00000    /* environment starts at the beginning of the EEPROM */
+#define CFG_ENV_SIZE            0x00800   /* 2k bytes may be used for env vars */
+/* The Atmel 24C128/256 has 64 byte page write mode using last 6 bits of the address   */
+#define CFG_EEPROM_PAGE_WRITE_BITS 6
+#define CFG_EEPROM_PAGE_WRITE_ENABLE /* enable Page write */
+/***************************************************************
+ * Definitions for Serial Presence Detect EEPROM address
+ * (to get SDRAM settings)
+ ***************************************************************/
+#define SDRAM_EEPROM_WRITE_ADDRESS 0xA0
+#define SDRAM_EEPROM_READ_ADDRESS  0xA1
+
+/**************************************************************
+ * Environment definitions
+ **************************************************************/
+#define CONFIG_BAUDRATE                9600    /* STD Baudrate */
+#define CONFIG_BOOTDELAY       -1                      /* no autoboot */
+
+#define CONFIG_BOOTCOMMAND     "diskboot 200000 0:1; bootm" /* autoboot command                */
+#define CONFIG_BOOTARGS                "console=ttyS0,9600 root=/dev/hda5" /* boot arguments */
+
+#define CONFIG_IPADDR                  10.0.0.100
+#define CONFIG_SERVERIP                10.0.0.1
+
+/***************************************************************
+ * defines if the console is stored in the environment
+ ***************************************************************/
+#define CFG_CONSOLE_IS_IN_ENV  /* stdin, stdout and stderr are in evironment */
+/***************************************************************
+ * defines if an overwrite_console function exists
+ *************************************************************/
+#define CFG_CONSOLE_OVERWRITE_ROUTINE
+#define CFG_CONSOLE_INFO_QUIET
+/***************************************************************
+ * defines if the overwrite_console should be stored in the
+ * environment
+ **************************************************************/
+#undef CFG_CONSOLE_ENV_OVERWRITE
+
+/**************************************************************
+ * loads config
+ *************************************************************/
+#define CONFIG_LOADS_ECHO      1       /* echo on for serial download  */
+#define CFG_LOADS_BAUD_CHANGE  1       /* allow baudrate change        */
+
+#define CONFIG_MISC_INIT_R
+/***********************************************************
+ * 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  */
+
+#undef  CFG_EXT_SERIAL_CLOCK           /* no external serial clock used */
+
+/* The following table includes the supported baudrates */
+#define CFG_BAUDRATE_TABLE      \
+        { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400,     \
+         57600, 115200, 230400, 460800, 921600 }
+
+#define CFG_LOAD_ADDR          0x200000        /* default load address */
+#define CFG_EXTBDINFO          1       /* To use extended board_into (bd_t) */
+
+#define        CFG_HZ          1000            /* decrementer freq: 1 ms ticks */
+
+/*-----------------------------------------------------------------------
+ * PCI stuff
+ *-----------------------------------------------------------------------
+ */
+#define CONFIG_PCI                     /* include pci support          */
+#define CONFIG_PCI_HOST /* configure as pci-host        */
+#define CONFIG_PCI_PNP /* pci plug-and-play                    */
+                                        /* resource configuration       */
+#define CFG_PCI_SUBSYS_VENDORID 0x0000  /* PCI Vendor ID: to-do!!!      */
+#define CFG_PCI_SUBSYS_DEVICEID 0x0000  /* PCI Device ID: to-do!!!      */
+#define CFG_PCI_PTM1LA  0x00000000      /* point to sdram               */
+#define CFG_PCI_PTM1MS  0x80000001      /* 2GB, enable hard-wired to 1  */
+#define CFG_PCI_PTM2LA  0x00000000      /* disabled                     */
+#define CFG_PCI_PTM2MS  0x00000000      /* disabled                     */
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ */
+#define CFG_SDRAM_BASE         0x00000000
+#define CFG_FLASH_BASE         0xFFF80000
+#define CFG_MONITOR_BASE       CFG_FLASH_BASE
+#define CFG_MONITOR_LEN                (512 * 1024)    /* Reserve 512 kB for Monitor   */
+#define CFG_MALLOC_LEN         (128 * 1024)    /* Reserve 128 kB for malloc()  */
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ          (8 << 20)       /* Initial Memory map for Linux */
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS    1       /* max number of memory banks           */
+#define CFG_MAX_FLASH_SECT     256     /* max number of sectors on one chip    */
+
+#define CFG_FLASH_ERASE_TOUT   120000  /* Timeout for Flash Erase (in ms)      */
+#define CFG_FLASH_WRITE_TOUT   500     /* Timeout for Flash Write (in ms)      */
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE     16      /* For all MPC8xx CPUs                  */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CACHELINE_SHIFT    4       /* log base 2 of the above value        */
+#endif
+
+/*
+ * Init Memory Controller:
+ */   
+
+#define FLASH_BASE0_PRELIM     0xFFC00000      /* FLASH bank #0        */
+#define FLASH_BASE1_PRELIM     0               /* FLASH bank #1        */
+
+#define CONFIG_BOARD_PRE_INIT
+
+/* On Chip Memory location */
+#define OCM_DATA_ADDR          0xF0000000
+
+/* Peripheral Bus Mapping */
+#define PER_PLD_ADDR                           0xF4000000 /* smallest window is 1MByte 0x10 0000*/
+#define PER_UART0_ADDR                         0xF4100000 /* smallest window is 1MByte 0x10 0000*/
+#define PER_UART1_ADDR                         0xF4200000 /* smallest window is 1MByte 0x10 0000*/
+
+#define MULTI_PURPOSE_SOCKET_ADDR 0xF8000000
+
+
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in On Chip SRAM)
+ */
+#define CFG_INIT_RAM_ADDR      OCM_DATA_ADDR  /* inside of On Chip SRAM    */
+#define CFG_INIT_RAM_END       0x1000                           /* End of On Chip SRAM        */
+#define CFG_INIT_DATA_SIZE     64                              /* size in bytes reserved for initial data */
+#define CFG_INIT_DATA_OFFSET   (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET     CFG_INIT_DATA_OFFSET
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD  0x01            /* Normal Power-On: Boot from FLASH     */
+#define BOOTFLAG_WARM  0x02            /* Software reboot                      */
+
+
+/***********************************************************************
+ * External peripheral base address
+ ***********************************************************************/
+#define CFG_ISA_IO_BASE_ADDRESS 0xE8000000
+
+/***********************************************************************
+ * Last Stage Init
+ ***********************************************************************/
+#define CONFIG_LAST_STAGE_INIT
+/************************************************************
+ * Ethernet Stuff
+ ***********************************************************/
+#define CONFIG_MII             1       /* MII PHY management           */
+#define        CONFIG_PHY_ADDR         1       /* PHY address                  */
+
+/************************************************************
+ * RTC
+ ***********************************************************/
+#define CONFIG_RTC_MC146818
+#undef CONFIG_WATCHDOG                 /* watchdog disabled            */
+
+/************************************************************
+ * IDE/ATA stuff
+ ************************************************************/
+#define CFG_IDE_MAXBUS         2   /* max. 2 IDE busses        */
+#define CFG_IDE_MAXDEVICE      (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */
+
+#define CFG_ATA_BASE_ADDR      CFG_ISA_IO_BASE_ADDRESS /* base address */
+#define CFG_ATA_IDE0_OFFSET 0x01F0     /* ide0 offste */
+#define CFG_ATA_IDE1_OFFSET 0x0170     /* ide1 offset */
+#define CFG_ATA_DATA_OFFSET 0                          /* data reg offset      */
+#define CFG_ATA_REG_OFFSET  0                          /* reg offset */
+#define CFG_ATA_ALT_OFFSET     0x200           /* alternate register offset */
+
+#undef  CONFIG_IDE_PCMCIA      /* no pcmcia interface required */
+#undef  CONFIG_IDE_LED         /* no led for ide supported     */
+#define CONFIG_IDE_RESET       /* reset for ide supported...   */
+#define CONFIG_IDE_RESET_ROUTINE /* with a special reset function */
+
+/************************************************************
+ * ATAPI support (experimental)
+ ************************************************************/
+#define CONFIG_ATAPI                   /* enable ATAPI Support */
+
+/************************************************************
+ * SCSI support (experimental) only SYM53C8xx supported
+ ************************************************************/
+#undef CONFIG_SCSI_SYM53C8XX
+
+#ifdef CONFIG_SCSI_SYM53C8XX
+#define CFG_SCSI_MAX_LUN                       8 /* number of supported LUNs */
+#define CFG_SCSI_MAX_SCSI_ID   7 /* maximum SCSI ID (0..6) */
+#define CFG_SCSI_MAX_DEVICE            CFG_SCSI_MAX_SCSI_ID * CFG_SCSI_MAX_LUN /* maximum Target devices */
+#endif /* CONFIG_SCSI_SYM53C8XX */
+/************************************************************
+ * DISK Partition support
+ ************************************************************/
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_ISO_PARTITION /* Experimental */
+
+/************************************************************
+ * Keyboard support
+ ************************************************************/
+#undef CONFIG_ISA_KEYBOARD
+
+/************************************************************
+ * Video support
+ ************************************************************/
+#undef CONFIG_VIDEO                    /*To enable video controller support */
+#undef CONFIG_VIDEO_CT69000
+
+/************************************************************
+ * USB support EXPERIMENTAL
+ ************************************************************/
+#define CONFIG_USB_UHCI
+#define CONFIG_USB_KEYBOARD
+#define CONFIG_USB_STORAGE
+
+/* Enable needed helper functions */
+#define CFG_DEVICE_DEREGISTER          /* needs device_deregister */
+
+/************************************************************
+ * Debug support
+ ************************************************************/
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CONFIG_KGDB_BAUDRATE   230400  /* speed to run kgdb serial port */
+#define CONFIG_KGDB_SER_INDEX  2       /* which serial port to use */
+#endif
+
+/************************************************************
+ * Ident
+ ************************************************************/
+#define VERSION_TAG "REL_1_1_1"
+#define CONFIG_IDENT_STRING "\n(c) 2001 by MPL AG Switzerland, MEV-10072-001 " VERSION_TAG
+
+
+#endif /* __CONFIG_H */
index 8688c1967a56ee113280e86bd98d7037310bddfb..b412bd1adf9ac476604f5fccc75738a4630eb9a7 100644 (file)
@@ -91,6 +91,7 @@
                                 CFG_CMD_EEPROM | \
                                 CFG_CMD_FDC    | \
                                 CFG_CMD_IDE    | \
+                                CFG_CMD_USB    | \
                                 CFG_CMD_KGDB   | \
                                 CFG_CMD_MII    | \
                                 CFG_CMD_PCI    | \
index 64f654cd7bd9ca22578fb5c02783447abf3a189a..e6a1a9b6a95e28161117f45825f8d39c5becfb29 100644 (file)
  * Command definitions
  ***********************************************************/
 #define CONFIG_COMMANDS                \
-       (CONFIG_CMD_DFL | CFG_CMD_PCI | CFG_CMD_IRQ | \
-        CFG_CMD_DATE | CFG_CMD_IDE | CFG_CMD_BSP | \
-        CFG_CMD_FDC | CFG_CMD_SCSI )
-
+               (CONFIG_CMD_DFL | \
+                       CFG_CMD_IDE     | \
+                       CFG_CMD_DHCP    | \
+                       CFG_CMD_PCI     | \
+                       CFG_CMD_IRQ     | \
+                       CFG_CMD_EEPROM  | \
+                       CFG_CMD_I2C     | \
+                       CFG_CMD_REGINFO | \
+                       CFG_CMD_FDC     | \
+                       CFG_CMD_SCSI    | \
+                       CFG_CMD_DATE    | \
+                       CFG_CMD_ELF     | \
+                       CFG_CMD_USB     | \
+                       CFG_CMD_MII     | \
+                       CFG_CMD_BSP     )
 /* this must be included AFTER the definition of CONFIG_COMMANDS  (if any) */
 #include <cmd_confdefs.h>
 
-
+#define  CFG_HUSH_PARSER
+#define  CFG_PROMPT_HUSH_PS2 "> "
 /**************************************************************
  * I2C Stuff:
  * the PIP405 is equiped with an Atmel 24C128/256 EEPROM at address
- * 0x53. 
+ * 0x53.
  * Caution: on the same bus is the SPD (Serial Presens Detect
  * EEPROM of the SDRAM
  * The Atmel EEPROM uses 16Bit addressing.
- ***************************************************************/ 
+ ***************************************************************/
 #define CONFIG_I2C_X
+#define CONFIG_I2C405
 #define CFG_I2C_EEPROM_ADDR                    0x53
 #define CFG_ENV_IS_IN_EEPROM    1       /* use EEPROM for environment vars */
 #define CFG_ENV_OFFSET          0x000   /* environment starts at the beginning of the EEPROM */
 #define CFG_ENV_SIZE            0x200   /* 512 bytes may be used for env vars */
 /* The Atmel 24C128/256 has 64 byte page write mode using last 6 bits of the address   */
-#define CFG_EEPROM_PAGE_WRITE_BITS 6   
-#define CFG_EEPROM_PAGE_WRITE_ENABLE /* enable Page write */   
+#define CFG_EEPROM_PAGE_WRITE_BITS 6
+#define CFG_EEPROM_PAGE_WRITE_ENABLE /* enable Page write */
 /***************************************************************
  * Definitions for Serial Presence Detect EEPROM address
  * (to get SDRAM settings)
@@ -75,6 +88,7 @@
 #define SDRAM_EEPROM_WRITE_ADDRESS 0xA0
 #define SDRAM_EEPROM_READ_ADDRESS  0xA1
 
+#define CONFIG_BOARD_PRE_INIT
 /**************************************************************
  * Environment definitions
  **************************************************************/
 
 /***************************************************************
  * defines if the console is stored in the environment
- ***************************************************************/ 
-#define CFG_CONSOLE_IS_IN_ENV  /* stdin, stdout and stderr are in evironment */                                
+ ***************************************************************/
+#define CFG_CONSOLE_IS_IN_ENV  /* stdin, stdout and stderr are in evironment */
 /***************************************************************
  * defines if an overwrite_console function exists
  *************************************************************/
 #define CFG_CONSOLE_OVERWRITE_ROUTINE
-
+#define CFG_CONSOLE_INFO_QUIET
 /***************************************************************
  * defines if the overwrite_console should be stored in the
  * environment
 
 /*
  * Init Memory Controller:
- */   
+ */
 
 #define FLASH_BASE0_PRELIM     0xFFC00000      /* FLASH bank #0        */
 #define FLASH_BASE1_PRELIM     0               /* FLASH bank #1        */
  ***********************************************************************/
 #define CFG_ISA_IO_BASE_ADDRESS 0xE8000000
 
-
+/***********************************************************************
+ * Last Stage Init
+ ***********************************************************************/
+#define CONFIG_LAST_STAGE_INIT
 /************************************************************
  * Ethernet Stuff
  ***********************************************************/
 #define CFG_SCSI_MAX_DEVICE            CFG_SCSI_MAX_SCSI_ID * CFG_SCSI_MAX_LUN /* maximum Target devices */
 
 /************************************************************
- * DISK Partition support 
+ * DISK Partition support
  ************************************************************/
-#define CONFIG_DOS_PARTITION 
-#define CONFIG_MAC_PARTITION 
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
 #define CONFIG_ISO_PARTITION /* Experimental */
 
 /************************************************************
- * Keyboard support 
+ * Keyboard support
  ************************************************************/
 #define CONFIG_ISA_KEYBOARD
 
 /************************************************************
- * Video support 
+ * Video support
  ************************************************************/
 #define CONFIG_VIDEO                   /*To enable video controller support */
 #define CONFIG_VIDEO_CT69000
 
 /************************************************************
- * Debug support 
+ * USB support
+ ************************************************************/
+#define CONFIG_USB_UHCI
+#define CONFIG_USB_KEYBOARD
+#define CONFIG_USB_STORAGE
+
+/* Enable needed helper functions */
+#define CFG_DEVICE_DEREGISTER          /* needs device_deregister */
+
+/************************************************************
+ * Debug support
  ************************************************************/
 #if (CONFIG_COMMANDS & CFG_CMD_KGDB)
 #define CONFIG_KGDB_BAUDRATE   230400  /* speed to run kgdb serial port */
 #endif
 
 /************************************************************
- * Ident 
+ * Ident
  ************************************************************/
-#define VERSION_TAG "REL_1.0.0"
-#define CONFIG_IDENT_STRING "\n(c) 2001 by MPL AG Switzerland, MEV-10066-001 " VERSION_TAG 
+#define VERSION_TAG "REL_1_1_1"
+#define CONFIG_IDENT_STRING "\n(c) 2001 by MPL AG Switzerland, MEV-10066-001 " VERSION_TAG
 
 
 #endif /* __CONFIG_H */
index 3e0c0cf87115fa83cd745bfd2a388dd0fd5e0ecd..1244317cdca1d14fe20e1f7ad446c653307c6995 100644 (file)
                                        CFG_CMD_MII     | \
                                        CFG_CMD_PCMCIA  | \
                                        CFG_CMD_PCI     | \
+                                       CFG_CMD_USB     | \
                                        CFG_CMD_SCSI    ) )
 
 /* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
index 97cf63a24b17fbc7279a93cb89ab994fd730dfa1..1b656395b4820d375bc41f4bcaa3199a1b0f57ac 100644 (file)
@@ -92,6 +92,7 @@ extern char *stdio_names[MAX_FILES];
 int    device_register (device_t * dev);
 int    devices_init (bd_t *, ulong);
 int    devices_done (void);
+int    device_deregister(char *devname);
 #ifdef CONFIG_LCD
 int    drv_lcd_init (bd_t *);
 #endif
@@ -101,8 +102,5 @@ int drv_video_init (void);
 #ifdef CONFIG_WL_4PPM_KEYBOARD
 int    drv_wlkbd_init (void);
 #endif
-#ifdef CONFIG_ISA_KEYBOARD
-int    drv_isa_kbd_init (void);
-#endif
 
 #endif /* _DEVICES_H_ */
index e1534bd83dd19e4c454d09816449a3b810d04223..839330c9e86109815738c05ab7c95610bc386a53 100644 (file)
@@ -36,9 +36,10 @@ int     ListInsertItem(list_t list, void *ptrToItem, int itemPosition);
 int     ListInsertItems(list_t list, void *ptrToItems, int firstItemPosition, int numItemsToInsert);
 void    ListDispose(list_t list);
 void    *ListGetPtrToItem(list_t list, int itemPosition);
+void    ListRemoveItem(list_t list, void *itemDestination, int itemPosition);
+void    ListRemoveItems(list_t list, void *itemsDestination, int firstItemPosition, int numItemsToRemove);
 
 /*
-
 void    ListDisposePtrList(list_t list);
 void    ListGetItem(list_t list, void *itemDestination, int itemPosition);
 void    ListReplaceItem(list_t list, void *ptrToItem, int itemPosition);
index 5467c98e5709b04a3f304027f83348a805816fa2..3585759ee0be107c306df61a29a6d6d66e62a93d 100644 (file)
@@ -182,6 +182,9 @@ int checkboard    (void);
 int    checkflash    (void);
 int    checkdram     (void);
 char * strmhz(char *buf, long hz);
+#ifdef CONFIG_LAST_STAGE_INIT
+int    last_stage_init(void);
+#endif
 
 /* common/cmd_bootm.c */
 void print_image_hdr (image_header_t *hdr);
@@ -200,6 +203,7 @@ int         saveenv(void);
     defined(CONFIG_AR405)      || \
     defined (CONFIG_WALNUT405) || \
     defined (CONFIG_PIP405)    || \
+    defined (CONFIG_MIP405)    || \
     defined (CONFIG_CPCIISER4) || \
     defined (CONFIG_OCRTC)     || \
     defined (CONFIG_DASA_SIM)  || \
@@ -250,6 +254,7 @@ void        reset_phy     (void);
     defined(CONFIG_OCRTC)      || \
     defined(CONFIG_PCU_E)      || \
     defined(CONFIG_PIP405)     || \
+    defined(CONFIG_MIP405)     || \
     defined(CONFIG_PM826)      || \
     defined(CONFIG_SXNI855T)   || \
     defined(CONFIG_TQM8260)    || \
@@ -314,6 +319,7 @@ void        load_sernum_ethaddr(bd_t *bd);
     defined(CONFIG_CANBT)      || \
     defined(CONFIG_WALNUT405)  || \
     defined(CONFIG_PIP405)     || \
+    defined(CONFIG_MIP405)     || \
     defined(CONFIG_CPCIISER4)  || \
     defined(CONFIG_OCRTC)      || \
     defined(CONFIG_ADCIOP)     || \
diff --git a/include/usb.h b/include/usb.h
new file mode 100644 (file)
index 0000000..c1c8d4c
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ * Note: Part of this code has been derived from linux
+ * 
+ */
+#ifndef _USB_H_
+#define _USB_H_
+
+#include <usb_defs.h>
+
+/* Everything is aribtrary */
+#define USB_ALTSETTINGALLOC          4
+#define USB_MAXALTSETTING                 128  /* Hard limit */
+
+#define USB_MAX_DEVICE              32
+#define USB_MAXCONFIG                      8
+#define USB_MAXINTERFACES                8
+#define USB_MAXENDPOINTS                 16
+#define USB_MAXCHILDREN                                                8       /* This is arbitrary */
+#define USB_MAX_HUB                                                                    16
+
+#define USB_CNTL_TIMEOUT 100 /* 100ms timeout */
+
+
+/* String descriptor */
+struct usb_string_descriptor {
+       unsigned char  bLength;
+       unsigned char  bDescriptorType;
+       unsigned short wData[1];
+} __attribute__ ((packed));
+
+/* device request (setup) */
+struct devrequest {
+       unsigned char requesttype;
+       unsigned char request;
+       unsigned short value;
+       unsigned short index;
+       unsigned short length;
+} __attribute__ ((packed));
+
+
+
+/* All standard descriptors have these 2 fields in common */
+struct usb_descriptor_header {
+       unsigned char  bLength;
+       unsigned char  bDescriptorType;
+} __attribute__ ((packed));
+
+/* Device descriptor */
+struct usb_device_descriptor {
+       unsigned char  bLength;
+       unsigned char  bDescriptorType;
+       unsigned short bcdUSB;
+       unsigned char  bDeviceClass;
+       unsigned char  bDeviceSubClass;
+       unsigned char  bDeviceProtocol;
+       unsigned char  bMaxPacketSize0;
+       unsigned short idVendor;
+       unsigned short idProduct;
+       unsigned short bcdDevice;
+       unsigned char  iManufacturer;
+       unsigned char  iProduct;
+       unsigned char  iSerialNumber;
+       unsigned char  bNumConfigurations;
+} __attribute__ ((packed));
+
+
+/* Endpoint descriptor */
+struct usb_endpoint_descriptor {
+       unsigned char  bLength;
+       unsigned char  bDescriptorType;
+       unsigned char  bEndpointAddress;
+       unsigned char  bmAttributes;
+       unsigned short wMaxPacketSize;
+       unsigned char  bInterval;
+       unsigned char  bRefresh;
+       unsigned char  bSynchAddress;
+
+} __attribute__ ((packed));
+/* Interface descriptor */
+struct usb_interface_descriptor {
+       unsigned char  bLength;
+       unsigned char  bDescriptorType;
+       unsigned char  bInterfaceNumber;
+       unsigned char  bAlternateSetting;
+       unsigned char  bNumEndpoints;
+       unsigned char  bInterfaceClass;
+       unsigned char  bInterfaceSubClass;
+       unsigned char  bInterfaceProtocol;
+       unsigned char  iInterface;
+       
+       unsigned char  no_of_ep;
+       unsigned char  act_altsetting;
+       struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
+} __attribute__ ((packed));
+
+
+/* Configuration descriptor information.. */
+struct usb_config_descriptor {
+       unsigned char  bLength;
+       unsigned char  bDescriptorType;
+       unsigned short wTotalLength;
+       unsigned char  bNumInterfaces;
+       unsigned char  bConfigurationValue;
+       unsigned char  iConfiguration;
+       unsigned char  bmAttributes;
+       unsigned char  MaxPower;
+
+       unsigned char  no_of_if;                        /* number of interfaces */
+       struct usb_interface_descriptor if_desc[USB_MAXINTERFACES];
+} __attribute__ ((packed));
+
+
+struct usb_device {
+       int devnum;                                                             /* Device number on USB bus */
+       int slow;                                                                       /* Slow device? */
+       char mf[32];                                    /* manufacturer */
+       char prod[32];                          /* product */
+       char serial[32];          /* serial number */
+
+       int maxpacketsize;                  /* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
+       unsigned int toggle[2];         /* one bit for each endpoint ([0] = IN, [1] = OUT) */
+       unsigned int halted[2];         /* endpoint halts; one bit per endpoint # & direction; */
+                            /* [0] = IN, [1] = OUT */
+       int epmaxpacketin[16];          /* INput endpoint specific maximums */
+       int epmaxpacketout[16];         /* OUTput endpoint specific maximums */
+
+       int configno;                   /* selected config number */
+       struct usb_device_descriptor descriptor; /* Device Descriptor */
+       struct usb_config_descriptor config; /* config descriptor */ 
+
+       int have_langid;                /* whether string_langid is valid yet */
+       int string_langid;              /* language ID for strings */
+       int (*irq_handle)(struct usb_device *dev);
+       unsigned long irq_status;
+       int irq_act_len;                        /* transfered bytes */
+       void *privptr;
+       /*
+        * Child devices -  if this is a hub device
+        * Each instance needs its own set of data structures.
+        */
+       unsigned long status;
+       int act_len;                    /* transfered bytes */
+       int maxchild;                   /* Number of ports if hub */
+       struct usb_device *parent;
+       struct usb_device *children[USB_MAXCHILDREN];
+};
+
+/**********************************************************************
+ * this is how the lowlevel part communicate with the outer world
+ */
+
+#ifdef CONFIG_USB_UHCI
+int usb_lowlevel_init(void);
+int usb_lowlevel_stop(void);
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,int transfer_len);
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                       int transfer_len,struct devrequest *setup);
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+                       int transfer_len, int interval);
+
+/* Defines */
+#define USB_UHCI_VEND_ID 0x8086
+#define USB_UHCI_DEV_ID  0x7112
+
+#else
+#error USB Lowlevel not defined 
+#endif
+
+#ifdef CONFIG_USB_STORAGE
+
+#define USB_MAX_STOR_DEV 5
+block_dev_desc_t *usb_stor_get_dev(int index);
+int usb_stor_scan(int mode);
+
+#endif
+
+#ifdef CONFIG_USB_KEYBOARD
+
+int drv_usb_kbd_init(void);
+int usb_kbd_deregister(void);
+
+#endif
+/* routines */
+int usb_init(void); /* initialize the USB Controller */ 
+int usb_stop(void); /* stop the USB Controller */
+
+
+int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
+int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id);
+struct usb_device * usb_get_dev_index(int index);
+int usb_control_msg(struct usb_device *dev, unsigned int pipe,
+                       unsigned char request, unsigned char requesttype,
+                       unsigned short value, unsigned short index, 
+                       void *data, unsigned short size, int timeout);
+int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, 
+                       void *data, int len, int *actual_length, int timeout);
+int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, 
+                       void *buffer,int transfer_len, int interval);
+void usb_disable_asynch(int disable);
+int usb_maxpacket(struct usb_device *dev,unsigned long pipe);
+void __inline__ wait_ms(unsigned long ms);
+int usb_get_configuration_no(struct usb_device *dev,unsigned char *buffer,int cfgno);
+int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size);
+int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
+               unsigned char type, unsigned char id, void *buf, int size);
+int usb_clear_halt(struct usb_device *dev, int pipe);
+int usb_string(struct usb_device *dev, int index, char *buf, size_t size);
+int usb_set_interface(struct usb_device *dev, int interface, int alternate);
+
+/* big endian -> little endian conversion */ 
+#define swap_16(x) \
+       ((unsigned short)( \
+               (((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
+               (((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
+#define swap_32(x) \
+       ((unsigned long)( \
+               (((unsigned long)(x) & (unsigned long)0x000000ffUL) << 24) | \
+               (((unsigned long)(x) & (unsigned long)0x0000ff00UL) <<  8) | \
+               (((unsigned long)(x) & (unsigned long)0x00ff0000UL) >>  8) | \
+               (((unsigned long)(x) & (unsigned long)0xff000000UL) >> 24) ))
+
+/*
+ * Calling this entity a "pipe" is glorifying it. A USB pipe
+ * is something embarrassingly simple: it basically consists
+ * of the following information:
+ *  - device number (7 bits)
+ *  - endpoint number (4 bits)
+ *  - current Data0/1 state (1 bit)
+ *  - direction (1 bit)
+ *  - speed (1 bit)
+ *  - max packet size (2 bits: 8, 16, 32 or 64)
+ *  - pipe type (2 bits: control, interrupt, bulk, isochronous)
+ *
+ * That's 18 bits. Really. Nothing more. And the USB people have
+ * documented these eighteen bits as some kind of glorious
+ * virtual data structure.
+ *
+ * Let's not fall in that trap. We'll just encode it as a simple
+ * unsigned int. The encoding is:
+ *
+ *  - max size:                bits 0-1        (00 = 8, 01 = 16, 10 = 32, 11 = 64)
+ *  - direction:       bit 7           (0 = Host-to-Device [Out], 1 = Device-to-Host [In])
+ *  - device:          bits 8-14
+ *  - endpoint:                bits 15-18
+ *  - Data0/1:         bit 19
+ *  - speed:           bit 26          (0 = Full, 1 = Low Speed)
+ *  - pipe type:       bits 30-31      (00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk)
+ *
+ * Why? Because it's arbitrary, and whatever encoding we select is really
+ * up to us. This one happens to share a lot of bit positions with the UHCI
+ * specification, so that much of the uhci driver can just mask the bits
+ * appropriately.
+ */
+/* Create various pipes... */
+#define create_pipe(dev,endpoint) \
+               (((dev)->devnum << 8) | (endpoint << 15) | ((dev)->slow << 26) | (dev)->maxpacketsize)
+#define default_pipe(dev) ((dev)->slow <<26)   
+
+#define usb_sndctrlpipe(dev,endpoint)  ((PIPE_CONTROL << 30) | create_pipe(dev,endpoint))
+#define usb_rcvctrlpipe(dev,endpoint)  ((PIPE_CONTROL << 30) | create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndisocpipe(dev,endpoint)  ((PIPE_ISOCHRONOUS << 30) | create_pipe(dev,endpoint))
+#define usb_rcvisocpipe(dev,endpoint)  ((PIPE_ISOCHRONOUS << 30) | create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndbulkpipe(dev,endpoint)  ((PIPE_BULK << 30) | create_pipe(dev,endpoint))
+#define usb_rcvbulkpipe(dev,endpoint)  ((PIPE_BULK << 30) | create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndintpipe(dev,endpoint)   ((PIPE_INTERRUPT << 30) | create_pipe(dev,endpoint))
+#define usb_rcvintpipe(dev,endpoint)   ((PIPE_INTERRUPT << 30) | create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_snddefctrl(dev)            ((PIPE_CONTROL << 30) | default_pipe(dev))
+#define usb_rcvdefctrl(dev)            ((PIPE_CONTROL << 30) | default_pipe(dev) | USB_DIR_IN)
+
+/* The D0/D1 toggle bits */
+#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1)
+#define        usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << ep))
+#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << ep)) | ((bit) << ep))
+
+/* Endpoint halt control/status */
+#define usb_endpoint_out(ep_dir)       (((ep_dir >> 7) & 1) ^ 1)
+#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
+#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
+#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
+
+#define usb_packetid(pipe)     (((pipe) & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT)
+
+#define usb_pipeout(pipe)      ((((pipe) >> 7) & 1) ^ 1)
+#define usb_pipein(pipe)       (((pipe) >> 7) & 1)
+#define usb_pipedevice(pipe)   (((pipe) >> 8) & 0x7f)
+#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff)
+#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
+#define usb_pipedata(pipe)     (((pipe) >> 19) & 1)
+#define usb_pipeslow(pipe)     (((pipe) >> 26) & 1)
+#define usb_pipetype(pipe)     (((pipe) >> 30) & 3)
+#define usb_pipeisoc(pipe)     (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
+#define usb_pipeint(pipe)      (usb_pipetype((pipe)) == PIPE_INTERRUPT)
+#define usb_pipecontrol(pipe)  (usb_pipetype((pipe)) == PIPE_CONTROL)
+#define usb_pipebulk(pipe)     (usb_pipetype((pipe)) == PIPE_BULK)
+
+   
+/*************************************************************************
+ * Hub Stuff
+ */
+struct usb_port_status {
+       unsigned short wPortStatus;
+       unsigned short wPortChange;     
+} __attribute__ ((packed));
+
+struct usb_hub_status {
+       unsigned short wHubStatus;
+       unsigned short wHubChange;
+} __attribute__ ((packed));
+
+
+/* Hub descriptor */
+struct usb_hub_descriptor {
+       unsigned char  bLength;
+       unsigned char  bDescriptorType;
+       unsigned char  bNbrPorts;
+       unsigned short wHubCharacteristics;
+       unsigned char  bPwrOn2PwrGood;
+       unsigned char  bHubContrCurrent;
+       unsigned char  DeviceRemovable[(USB_MAXCHILDREN+1+7)/8];
+       unsigned char  PortPowerCtrlMask[(USB_MAXCHILDREN+1+7)/8];
+               /* DeviceRemovable and PortPwrCtrlMask want to be variable-length 
+          bitmaps that hold max 255 entries. (bit0 is ignored) */
+} __attribute__ ((packed));
+
+
+struct usb_hub_device {
+       struct usb_device *pusb_dev;
+       struct usb_hub_descriptor desc;
+}; 
+           
+#endif /*_USB_H_ */
diff --git a/include/usb_defs.h b/include/usb_defs.h
new file mode 100644 (file)
index 0000000..541aa04
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * (C) Copyright 2001
+ * Denis Peter, MPL AG Switzerland
+ *
+ * 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
+ *
+ * Note: Part of this code has been derived from linux
+ * 
+ */
+#ifndef _USB_DEFS_H_
+#define _USB_DEFS_H_
+
+
+/* Everything is aribtrary */
+#define USB_ALTSETTINGALLOC          4
+#define USB_MAXALTSETTING                 128  /* Hard limit */
+
+#define USB_MAX_DEVICE              32
+#define USB_MAXCONFIG                      8
+#define USB_MAXINTERFACES                8
+#define USB_MAXENDPOINTS                 16
+#define USB_MAXCHILDREN                                                8       /* This is arbitrary */
+#define USB_MAX_HUB                                                                    16
+
+#define USB_CNTL_TIMEOUT 100 /* 100ms timeout */
+
+/* USB constants */
+
+/* Device and/or Interface Class codes */
+#define USB_CLASS_PER_INTERFACE  0     /* for DeviceClass */
+#define USB_CLASS_AUDIO          1
+#define USB_CLASS_COMM           2
+#define USB_CLASS_HID            3
+#define USB_CLASS_PRINTER             7
+#define USB_CLASS_MASS_STORAGE   8
+#define USB_CLASS_HUB            9
+#define USB_CLASS_DATA           10
+#define USB_CLASS_VENDOR_SPEC    0xff
+
+/* some HID sub classes */
+#define USB_SUB_HID_NONE        0
+#define USB_SUB_HID_BOOT        1
+
+/* some UID Protocols */
+#define USB_PROT_HID_NONE       0
+#define USB_PROT_HID_KEYBOARD   1
+#define USB_PROT_HID_MOUSE      2
+
+
+/* Sub STORAGE Classes */
+#define US_SC_RBC              1               /* Typically, flash devices */
+#define US_SC_8020             2               /* CD-ROM */
+#define US_SC_QIC              3               /* QIC-157 Tapes */
+#define US_SC_UFI              4               /* Floppy */
+#define US_SC_8070             5               /* Removable media */
+#define US_SC_SCSI             6               /* Transparent */
+#define US_SC_MIN              US_SC_RBC
+#define US_SC_MAX              US_SC_SCSI
+
+/* STORAGE Protocols */
+#define US_PR_CB               1               /* Control/Bulk w/o interrupt */
+#define US_PR_CBI              0               /* Control/Bulk/Interrupt */
+#define US_PR_BULK             0x50            /* bulk only */
+
+/* USB types */
+#define USB_TYPE_STANDARD   (0x00 << 5)
+#define USB_TYPE_CLASS      (0x01 << 5)
+#define USB_TYPE_VENDOR     (0x02 << 5)
+#define USB_TYPE_RESERVED   (0x03 << 5)
+
+/* USB recipients */
+#define USB_RECIP_DEVICE      0x00
+#define USB_RECIP_INTERFACE   0x01
+#define USB_RECIP_ENDPOINT    0x02
+#define USB_RECIP_OTHER       0x03
+
+/* USB directions */
+#define USB_DIR_OUT           0
+#define USB_DIR_IN            0x80
+
+/* Descriptor types */
+#define USB_DT_DEVICE        0x01
+#define USB_DT_CONFIG        0x02
+#define USB_DT_STRING        0x03
+#define USB_DT_INTERFACE     0x04
+#define USB_DT_ENDPOINT      0x05
+
+#define USB_DT_HID          (USB_TYPE_CLASS | 0x01)
+#define USB_DT_REPORT       (USB_TYPE_CLASS | 0x02)
+#define USB_DT_PHYSICAL     (USB_TYPE_CLASS | 0x03)
+#define USB_DT_HUB          (USB_TYPE_CLASS | 0x09)
+
+/* Descriptor sizes per descriptor type */
+#define USB_DT_DEVICE_SIZE      18
+#define USB_DT_CONFIG_SIZE      9
+#define USB_DT_INTERFACE_SIZE   9
+#define USB_DT_ENDPOINT_SIZE    7
+#define USB_DT_ENDPOINT_AUDIO_SIZE  9  /* Audio extension */
+#define USB_DT_HUB_NONVAR_SIZE  7
+#define USB_DT_HID_SIZE         9
+
+/* Endpoints */
+#define USB_ENDPOINT_NUMBER_MASK  0x0f /* in bEndpointAddress */
+#define USB_ENDPOINT_DIR_MASK     0x80
+
+#define USB_ENDPOINT_XFERTYPE_MASK 0x03        /* in bmAttributes */
+#define USB_ENDPOINT_XFER_CONTROL  0
+#define USB_ENDPOINT_XFER_ISOC     1
+#define USB_ENDPOINT_XFER_BULK     2
+#define USB_ENDPOINT_XFER_INT      3
+
+/* USB Packet IDs (PIDs) */
+#define USB_PID_UNDEF_0             0xf0
+#define USB_PID_OUT                 0xe1
+#define USB_PID_ACK                 0xd2
+#define USB_PID_DATA0               0xc3
+#define USB_PID_UNDEF_4             0xb4
+#define USB_PID_SOF                 0xa5
+#define USB_PID_UNDEF_6             0x96
+#define USB_PID_UNDEF_7             0x87
+#define USB_PID_UNDEF_8             0x78
+#define USB_PID_IN                  0x69
+#define USB_PID_NAK                 0x5a
+#define USB_PID_DATA1               0x4b
+#define USB_PID_PREAMBLE            0x3c
+#define USB_PID_SETUP               0x2d
+#define USB_PID_STALL               0x1e
+#define USB_PID_UNDEF_F             0x0f
+
+/* Standard requests */
+#define USB_REQ_GET_STATUS          0x00
+#define USB_REQ_CLEAR_FEATURE       0x01
+#define USB_REQ_SET_FEATURE         0x03
+#define USB_REQ_SET_ADDRESS         0x05
+#define USB_REQ_GET_DESCRIPTOR      0x06
+#define USB_REQ_SET_DESCRIPTOR      0x07
+#define USB_REQ_GET_CONFIGURATION   0x08
+#define USB_REQ_SET_CONFIGURATION   0x09
+#define USB_REQ_GET_INTERFACE       0x0A
+#define USB_REQ_SET_INTERFACE       0x0B
+#define USB_REQ_SYNCH_FRAME         0x0C
+
+/* HID requests */
+#define USB_REQ_GET_REPORT          0x01
+#define USB_REQ_GET_IDLE            0x02
+#define USB_REQ_GET_PROTOCOL        0x03
+#define USB_REQ_SET_REPORT          0x09
+#define USB_REQ_SET_IDLE            0x0A
+#define USB_REQ_SET_PROTOCOL        0x0B
+
+
+/* "pipe" definitions */
+
+#define PIPE_ISOCHRONOUS    0
+#define PIPE_INTERRUPT      1
+#define PIPE_CONTROL        2
+#define PIPE_BULK           3
+#define PIPE_DEVEP_MASK     0x0007ff00
+
+#define USB_ISOCHRONOUS    0 
+#define USB_INTERRUPT      1
+#define USB_CONTROL        2
+#define USB_BULK           3
+
+/* USB-status codes: */
+#define USB_ST_ACTIVE           0x1            /* TD is active */
+#define USB_ST_STALLED          0x2            /* TD is stalled */
+#define USB_ST_BUF_ERR          0x4            /* buffer error */
+#define USB_ST_BABBLE_DET       0x8            /* Babble detected */
+#define USB_ST_NAK_REC          0x10   /* NAK Received*/
+#define USB_ST_CRC_ERR          0x20   /* CRC/timeout Error */
+#define USB_ST_BIT_ERR          0x40   /* Bitstuff error */
+#define USB_ST_NOT_PROC         0x80000000L    /* Not yet processed */
+
+
+   
+/*************************************************************************
+ * Hub defines 
+ */
+
+/*
+ * Hub request types
+ */
+
+#define USB_RT_HUB     (USB_TYPE_CLASS | USB_RECIP_DEVICE)
+#define USB_RT_PORT    (USB_TYPE_CLASS | USB_RECIP_OTHER)
+
+/*
+ * Hub Class feature numbers
+ */
+#define C_HUB_LOCAL_POWER   0
+#define C_HUB_OVER_CURRENT  1
+
+/*
+ * Port feature numbers
+ */
+#define USB_PORT_FEAT_CONNECTION     0
+#define USB_PORT_FEAT_ENABLE         1
+#define USB_PORT_FEAT_SUSPEND        2
+#define USB_PORT_FEAT_OVER_CURRENT   3
+#define USB_PORT_FEAT_RESET          4
+#define USB_PORT_FEAT_POWER          8
+#define USB_PORT_FEAT_LOWSPEED       9
+#define USB_PORT_FEAT_C_CONNECTION   16
+#define USB_PORT_FEAT_C_ENABLE       17
+#define USB_PORT_FEAT_C_SUSPEND      18
+#define USB_PORT_FEAT_C_OVER_CURRENT 19
+#define USB_PORT_FEAT_C_RESET        20
+
+/* wPortStatus bits */
+#define USB_PORT_STAT_CONNECTION    0x0001
+#define USB_PORT_STAT_ENABLE        0x0002
+#define USB_PORT_STAT_SUSPEND       0x0004
+#define USB_PORT_STAT_OVERCURRENT   0x0008
+#define USB_PORT_STAT_RESET         0x0010
+#define USB_PORT_STAT_POWER         0x0100
+#define USB_PORT_STAT_LOW_SPEED     0x0200
+
+/* wPortChange bits */
+#define USB_PORT_STAT_C_CONNECTION  0x0001
+#define USB_PORT_STAT_C_ENABLE      0x0002
+#define USB_PORT_STAT_C_SUSPEND     0x0004
+#define USB_PORT_STAT_C_OVERCURRENT 0x0008
+#define USB_PORT_STAT_C_RESET       0x0010
+
+/* wHubCharacteristics (masks) */
+#define HUB_CHAR_LPSM               0x0003
+#define HUB_CHAR_COMPOUND           0x0004
+#define HUB_CHAR_OCPM               0x0018
+
+/*
+ *Hub Status & Hub Change bit masks
+ */
+#define HUB_STATUS_LOCAL_POWER 0x0001
+#define HUB_STATUS_OVERCURRENT 0x0002
+
+#define HUB_CHANGE_LOCAL_POWER 0x0001
+#define HUB_CHANGE_OVERCURRENT 0x0002
+
+#endif /*_USB_DEFS_H_ */