aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/u-boot/u-boot-1.2.0/u-boot-kurobox.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/u-boot/u-boot-1.2.0/u-boot-kurobox.patch')
-rw-r--r--recipes/u-boot/u-boot-1.2.0/u-boot-kurobox.patch5595
1 files changed, 5595 insertions, 0 deletions
diff --git a/recipes/u-boot/u-boot-1.2.0/u-boot-kurobox.patch b/recipes/u-boot/u-boot-1.2.0/u-boot-kurobox.patch
new file mode 100644
index 0000000000..79f7a8e48a
--- /dev/null
+++ b/recipes/u-boot/u-boot-1.2.0/u-boot-kurobox.patch
@@ -0,0 +1,5595 @@
+diff -urN u-boot-86xx/MAKEALL u-boot-86xx-kuro_clean/MAKEALL
+--- u-boot-86xx/MAKEALL 2006-10-13 00:27:12.000000000 +0200
++++ u-boot-86xx-kuro_clean/MAKEALL 2006-11-06 22:13:16.000000000 +0100
+@@ -106,9 +106,9 @@
+ LIST_824x=" \
+ A3000 barco BMW CPC45 \
+ CU824 debris eXalion HIDDEN_DRAGON \
+- MOUSSE MUSENKI MVBLUE \
+- OXC PN62 Sandpoint8240 Sandpoint8245 \
+- sbc8240 SL8245 utx8245 \
++ linkstation linkstationhg MOUSSE MUSENKI \
++ MVBLUE OXC PN62 Sandpoint8240 \
++ Sandpoint8245 sbc8240 SL8245 utx8245 \
+ "
+
+ #########################################################################
+diff -urN u-boot-86xx/Makefile u-boot-86xx-kuro_clean/Makefile
+--- u-boot-86xx/Makefile 2006-10-13 00:27:12.000000000 +0200
++++ u-boot-86xx-kuro_clean/Makefile 2006-11-06 22:15:20.000000000 +0100
+@@ -122,7 +122,7 @@
+ CROSS_COMPILE =
+ else
+ ifeq ($(ARCH),ppc)
+-CROSS_COMPILE = powerpc-linux-
++CROSS_COMPILE = ppc_6xx-
+ endif
+ ifeq ($(ARCH),arm)
+ CROSS_COMPILE = arm-linux-
+@@ -237,6 +237,40 @@
+
+ all: $(ALL)
+
++LSMODEL := $(shell head -n 1 include/config.h)
++
++linkstation_HGLAN_RAM: include/config.h
++ @[ -n "$(findstring HGLAN_RAM, $(LSMODEL))" ] || \
++ { echo "Bad configuration: $(LSMODEL)" ; \
++ exit 1 ; \
++ }
++ @make all
++ @mv u-boot.bin u-boot-hg.ram.bin
++
++linkstation_HGLAN: include/config.h
++ @[ -n "$(findstring HGLAN_ROM, $(LSMODEL))" ] || \
++ { echo "Bad configuration: $(LSMODEL)" ; \
++ exit 1 ; \
++ }
++ @make all
++ @mv u-boot.bin u-boot-hg.flash.bin
++
++linkstation_HDLAN_RAM: include/config.h
++ @[ -n "$(findstring HDLAN_RAM, $(LSMODEL))" ] || \
++ { echo "Bad configuration: $(LSMODEL)" ; \
++ exit 1 ; \
++ }
++ @make all
++ @mv u-boot.bin u-boot-hd.ram.bin
++
++linkstation_HDLAN: include/config.h
++ @[ -n "$(findstring HDLAN_ROM, $(LSMODEL))" ] || \
++ { echo "Bad configuration: $(LSMODEL)" ; \
++ exit 1 ; \
++ }
++ @make all
++ @mv u-boot.bin u-boot-hd.flash.bin
++
+ $(obj)u-boot.hex: $(obj)u-boot
+ $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@
+
+@@ -317,6 +351,10 @@
+
+ #########################################################################
+ else
++linkstation_HGLAN_RAM \
++linkstation_HGLAN \
++linkstation_HDLAN_RAM \
++linkstation_HDLAN \
+ all $(obj)u-boot.hex $(obj)u-boot.srec $(obj)u-boot.bin \
+ $(obj)u-boot.img $(obj)u-boot.dis $(obj)u-boot \
+ $(SUBDIRS) version gdbtools updater env depend \
+@@ -1262,6 +1300,38 @@
+ kvme080_config: unconfig
+ @$(MKCONFIG) $(@:_config=) ppc mpc824x kvme080 etin
+
++linkstation_HGLAN_RAM_config: mrproper
++ @>include/config.h ; \
++ echo "/* HGLAN_RAM */" >>include/config.h ; \
++ echo "#define CONFIG_HGLAN 1" >>include/config.h ; \
++ echo "TEXT_BASE = 0x07F00000" >board/linkstation/config.tmp ; \
++ ./mkconfig -a linkstation ppc mpc824x linkstation ; \
++ echo "LinkStation HGLAN -- RAM BUILD ..."
++
++linkstation_HGLAN_config: mrproper
++ @>include/config.h ; \
++ echo "/* HGLAN_ROM */" >>include/config.h ; \
++ echo "#define CONFIG_HGLAN 1" >>include/config.h ; \
++ echo "TEXT_BASE = 0xFFF00000" >board/linkstation/config.tmp ; \
++ ./mkconfig -a linkstation ppc mpc824x linkstation ; \
++ echo "LinkStation HGLAN -- ROM BUILD ..."
++
++linkstation_HDLAN_RAM_config: mrproper
++ @>include/config.h ; \
++ echo "/* HDLAN_RAM */" >>include/config.h ; \
++ echo "#define CONFIG_HLAN 1" >>include/config.h ; \
++ echo "TEXT_BASE = 0x03F00000" >board/linkstation/config.tmp ; \
++ ./mkconfig -a linkstation ppc mpc824x linkstation ; \
++ echo "LinkStation HDLAN -- RAM BUILD ..."
++
++linkstation_HDLAN_config: mrproper
++ @>include/config.h ; \
++ echo "/* HDLAN_ROM */" >>include/config.h ; \
++ echo "#define CONFIG_HLAN 1" >>include/config.h ; \
++ echo "TEXT_BASE = 0xFFF00000" >board/linkstation/config.tmp ; \
++ ./mkconfig -a linkstation ppc mpc824x linkstation ; \
++ echo "LinkStation HDLAN -- ROM BUILD ..."
++
+ MOUSSE_config: unconfig
+ @$(MKCONFIG) $(@:_config=) ppc mpc824x mousse
+
+diff -urN u-boot-86xx/board/linkstation/INSTALL u-boot-86xx-kuro_clean/board/linkstation/INSTALL
+--- u-boot-86xx/board/linkstation/INSTALL 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/INSTALL 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,631 @@
++
++ Installing U-Boot for LinkStation
++
++ For U-Boot port version 2.1.0
++ 16 September 2006
++
++ Copyright (c) 2006 Mihai Georgian
++
++ Permission is granted to copy, distribute and/or modify this document under
++ the terms of the [1]GNU Free Documentation License, Version 1.2 or any later
++ version published by the Free Software Foundation; with no Invariant
++ Sections, no Front-Cover Texts, and no Back-Cover Texts. The full text of
++ the license can be obtained by clicking on the above link.
++
++ No liability for the contents of this document can be accepted. The
++ information in this document is provided in good faith but no warranty can
++ be made for its accuracy and the author does not take any responsibility.
++ Use the concepts, examples and information at your own risk. There may be
++ errors and inaccuracies, that could be damaging to your system.
++
++ Use of a term in this document should not be regarded as affecting the
++ validity of any trademark or service mark. Naming of particular products or
++ brands should not be seen as endorsements.
++ _________________________________________________________________
++
++ WARNING
++
++ Flashing the LinkStation with unauthorised firmare voids your warranty. When
++ installing firmware on an embedded computer things can and, sometimes, do go
++ wrong. The power can go down in the middle of the flash operation or the
++ flash write can fail rendering your LinkStation unusable. Please read this
++ entire page carefully before attempting to install U-Boot.
++
++ If you are not prepared to lose your LinkStation, do not attempt to install
++ U-Boot
++
++ Introduction
++
++ U-Boot for the LinkStation is distributed as a source patch against
++ u-boot-1.1.4. To compile it you will need either a cross toolchain installed
++ on your PC or native development tools installed on your LinkStation. These
++ instructions assume that you are running Linux on a X86 PC and that you are
++ using a cross toolchain.
++
++ To allow testing of U-Boot on your LinkStation without burning it into
++ flash, a kernel module named uloader.o is provided. Uloader allows you to
++ use Linux to load a RAM build of U-Boot and start it. The RAM build of
++ U-Boot is very close to the ROM build. The only differences are the absence
++ of the basic initialisation code (which cannot run from RAM) and the link
++ address. It is strongly recommended that you test U-Boot on your LinkStation
++ using a RAM build before building the ROM version and attempting to burn it
++ into flash. Once you have the RAM build up and running you can use it to
++ install (burn) the ROM version.
++
++ Supported Hardware
++
++ The LinkStation port of U-Boot described in this document supports the
++ following PowerPC based models:
++ 1. LinkStation version 1 (model HD-HLAN-1)
++ 2. KuroBox standard
++ 3. LinkStation HG (model HD-HGLAN)
++ 4. KuroBox HG
++
++ This version of U-Boot will certainly not work on the the LinkStation
++ version 2 (model HD-HLAN-2) as the LinkStation version 2 is based on a MIPS
++ processor. The MIPS processor is completely different from the PowerPC
++ processor and attempting to flash a LinkStation version 2 with PowerPC
++ firmware it is guaranteed to make it completely unusable.
++
++ Get telnet Access
++
++ Try to connect to your LinkStation using telnet. If you see the telnet
++ command prompt, read [2]CGI Exploit (PowerPC) original method of Hacking the
++ LinkStation about how to get telnet access.
++
++ If the above method doesn't work for you, read [3]Turn your LinkStation into
++ a Kuro Box (PowerPC) for other methods to get telnet access.
++
++ The above methods do not work for the LinkStation HG. For this model, the
++ only solution is to load a telnet-enabled version of the firmware. Read the
++ pages about [4]OpenLink and the [5]firmware flasher
++
++ You can also try to flash [6]a modified version of the original firmware.
++
++ Install the Serial Console
++
++ Installing the serial console is not an absolute requirement and it will
++ void your warranty. U-Boot can be installed and controlled without it.
++ However, the serial console will give you the best control over both U-Boot
++ and Linux.
++
++ Read [7]Add a Serial port to the PowerPC Linkstation to learn how to install
++ the serial console.
++
++ Install netcat (nc)
++
++ If you haven't installed the serial console you will need to install netcat
++ (nc). Netcat is a networking utility which reads and writes data across
++ network connections, using the TCP/IP protocol. It comes standard with most
++ Linux distributions. For more information, visit the netcat home page
++ [8]http://netcat.sourceforge.net or [9]http://www.vulnwatch.org/netcat for
++ the Windows version.
++
++ Get the ELDK
++
++ If you don't have a cross toolchain installed, download the DENX Embedded
++ Linux Development Kit (ELDK) from
++ [10]http://ftp.sunet.se/pub/Linux/distributions/eldk/3.1.1/ppc-linux-x86/iso
++ /ppc-2005-03-07.iso, install it and spend some time getting familiar with
++ it.
++
++ Preparation
++
++ Create the build directory and set the environment variable UBOOT_BUILD to
++ the path to it
++ # mkdir <your_build_directory>
++ # export UBOOT_BUILD=<your_build_directory>
++ # cd $UBOOT_BUILD
++ Download the tarball for u-boot-1.1.4 from
++ [11]ftp://ftp.denx.de/pub/u-boot/u-boot-1.1.4.tar.bz2
++ Download the LinkStation patch, [12]u-boot-1.1.4-list-2.1.0.diff.gz
++ Download the uloader module for your LinkStation / KuroBox model.
++ * For the LinkStation 1 / KuroBox standard, download
++ [13]uloader-2.4.17.tar.gz
++ * For the LinkStation HG / KuroBox HG, download [14]uloader-2.4.20.tar.gz
++
++ Untar u-boot-1.1.4 and apply the patch.
++ # tar xjf u-boot-1.1.4.tar.bz2
++ # cd u-boot-1.1.4
++ # gunzip ../u-boot-1.1.4-list-2.01.diff.gz | patch -p1
++
++ Untar the uloader archive for your LinkStation / KuroBox model. The archive
++ contains the source code, a binary module compiled for the original
++ LinkStation kernel and a simple bash script to load and start a RAM build of
++ U-Boot.
++
++ The binary in uloader-2.4.17.tar.gz has been compiled against
++ 2.4.17_mvl21-sandpoint. Use only on the LinkStation 1 / KuroBox standard.
++ The binary in uloader-2.4.20.tar.gz has been compiled against
++ 2.4.20_mvl31-ppc_linkstation. Use only on the LinkStation HG / KuroBog HG.
++ If you have a different kernel version, you may need to recompile the module
++ for your kernel. Compiling the module requires a fully configured kernel
++ source tree. It is recommended to use the same gcc version as the one used
++ to compile the kernel. There is a small but important difference between the
++ two uloader source archives. The difference is the U-Boot load address. If
++ you compile uloader for the LinkStation 1 / KuroBox standard, use the
++ sources in uloader-2.4.17.tar.gz. If you compile for the LinkStation HG /
++ KuroBox HG, use the sources in uloader-2.4.20.tar.gz. In both cases you
++ need to modify the Makefile to match your development environment.
++
++ LinkStation 1 / KuroBox standard
++ # cd ..
++ # tar xzf uloader-2.4.17.tar.gz
++ # cd u-boot-1.1.4
++
++ LinkStation HG / KuroBox HG
++ # cd ..
++ # tar xzf uloader-2.4.20.tar.gz
++ # cd u-boot-1.1.4
++
++ Source your ELDK environment
++ # . <path_to_your_ELDK>/config_6xx
++
++ Configure
++
++ Edit include/configs/linkstation.h and set the following variables for your
++ environment:
++
++ CONFIG_IPADDR_LS - the IP address of your LinkStation while running
++ U-Boot (mandatory). The default address is
++ 192.168.11.150.
++ CONFIG_SERVERIP_LS - the IP address of the NFS/TFTP/DHCP/BOOTP server,
++ normally the address of your Linux PC (mandatory).
++ The default address is 192.168.11.149.
++ CONFIG_NCIP_LS - the address of the computer running netcat (nc),
++ normally the address of your Linux PC (optional).
++ If the define is missing, CONFIG_NCIP_LS will be
++ set to the same value as CONFIG_SERVERIP_LS
++
++ RAM Build
++
++ For LinkStation 1 / KuroBox standard run:
++ make linkstation_HDLAN_RAM_config
++ make linkstation_HDLAN_RAM
++
++ The name of the resulting binary is u-boot-hd.ram.bin
++
++ For LinkStation HG / KuroBox HG run:
++ make linkstation_HGLAN_RAM_config
++ make linkstation_HGLAN_RAM
++
++ The name of the resulting binary is u-boot-hg.ram.bin
++
++ Net Console
++
++ The net console is the U-Boot driver which uses the UDP protocol with a
++ default port of 6666 to send the console output to and receive the console
++ input from a remote computer. You need to run netcat on the remote computer
++ to communicate with the U-Boot net console. The communication is
++ bidirectional. Netcat will display on your screen the console output
++ received from U-Boot and will send your keyboard input back to U-Boot.
++
++ If U-Boot cannot contact the remote computer, it switches the console to the
++ serial port. To show that it changed the console, U-Boot makes the HDD LED
++ blink with the pattern corresponding to the serial console (see The Reset
++ Button below). The timeout period is 20 sec.
++
++ Minimal Console
++
++ U-Boot for the LinkStation is designed to allow some control over the boot
++ process even in the absence of a console. For this, it uses the power button
++ (the big button at the front) and the reset button (the small red button at
++ the back).
++
++ Before installing U-Boot, when the LinkStation is switched on, the power LED
++ starts blinking, the original boot loader starts executing and, very
++ quickly, it starts booting the kernel from flash. If U-Boot is installed,
++ the power LED will change from blinking quickly to blinking very slowly. The
++ blink pattern is the same as the one used to indicate sleep mode in normal
++ operation. When the power LED starts blinking slowly at boot, U-Boot has
++ taken over and it is counting down the boot delay before booting the kernel.
++ The default boot delay is 10 sec. From the moment when the power LED starts
++ blinking slowly and for the duration of the boot delay, you can control the
++ boot process with the power and reset buttons.
++
++ The Power Button
++
++ If you push the power button and keep it pressed for more than 1 sec, the
++ boot process will stop and the LinkStation will wait for a command. A
++ stopped boot process is indicated by the power LED being lit solid. The
++ effect is the same a pressing 's' on the console.
++
++ A long push of the power button acts as a toggle. If the boot delay count
++ down is in progress, a long push of the power button stops the boot process.
++ If the boot process is stopped (U-Boot is at the command prompt, even if you
++ can't see it), a long push of the power button restarts the boot process
++ resetting the boot delay to its original value. The restart of the boot
++ process is indicated by the power LED blinking slowly.
++
++ By default U-Boot supports three pre-configured boot commands:
++ 1. The first boot command will attempt to load and boot a file named
++ boot/vmlinux.UBoot from the first hard disk partition, /dev/hda1. The
++ file can be in any of the U-Boot bootable formats but uImage is the
++ preferred format. If the file is missing or corrupted, U-Boot will fall
++ back to booting the original kernel from flash.
++ 2. The second boot command will boot the original kernel from flash.
++ Please note that the original kernel for the LinkStation 1 / KuroBox
++ standard has a bug in the function that calibrates the decrementer and
++ it will stop for up to 180 sec during boot. This bug is not an U-Boot
++ bug but a kernel bug which is uncovered by the fact that U-Boot
++ activates the decrementer where the original boot loader does not.
++ The original kernel for LinkStation HG / KuroBox HG does not suffer from
++ the above problem.
++ 3. The third boot command will attempt to boot in emergency mode (EM). It
++ does this by passing the argument root=/dev/ram0 to the kernel.
++ LinkStation / LinkStation HG owners should avoid booting in EM mode as
++ the root password for this mode on the LinkStation is unknown.
++ The original kernel for the LinkStation / KuroBox standard and for some
++ of the earlier LinkStation HG / KuroBox HG models ignores the root
++ argument. These models will boot normally from the on-board flash when
++ the EM boot command is used. Read the section on EM mode if your
++ LinkStation HG / KuroBox HG has a kernel that doesn't boot in EM mode
++ using this boot command.
++
++ You can cycle through the boot commands with the power button.
++
++ To see which of the three commands U-Boot is going to execute, press the
++ power button quickly. The HDD LED (the third from the top) will start
++ blinking. The number of times the LED blinks, shows the number of the active
++ boot command. For example, a pattern short on - short off - short on - long
++ off, means that the boot command number 2 is active. U-Boot will repeat the
++ blinking cycle for a total duration of about 5 sec counting from the moment
++ the power button is released.
++
++ A short press of the power button while the HDD LED is blinking will advance
++ the boot command to the next one.
++
++ Changing the boot command does not change the boot status. If the boot is
++ stopped, it will not be restarted. If the boot is in progress, it will not
++ be stopped but the boot delay will be reset to the original value.
++
++ The Reset Button
++
++ Two consoles are currently configured, the serial console and the net
++ console. The first console is the serial console and the second console is
++ the net console (nc). The net console is the default console.
++
++ The reset button can be used, similarly to the power button, to switch
++ consoles. A press on the reset button (here, it doesn't matter how long you
++ keep the button pressed) displays the currently active console using the HDD
++ LED. Repeatedly pressing the reset button while the HDD LED is blinking will
++ toggle between the two consoles. The blinking pattern is different from the
++ one showing the boot command. The pattern which shows that the second (net)
++ console is active is short off - short on - short off - long on. U-Boot will
++ repeat the blinking cycle for a total duration of about 5 sec counting from
++ the moment the reset button is released.
++
++ Load and Test
++
++ Mount the LinkStation SMB public share and copy the following files to it:
++
++ For LinkStation 1 / KuroBox standard
++ # mount -t smbfs -o password="" //<your_linkstation_name_or_ip>/share/mnt
++ # cp u-boot-hd.ram.bin /mnt
++ # cp ../uloader-2.4.17/uloader.o /mnt
++ # cp ../uloader-2.4.17/u-boot-load-hd.sh /mnt
++ # umount /mmt
++
++ For LinkStation HG / KuroBox HG
++ # mount -t smbfs -o password="" //<your_linkstation_name_or_ip>/share/mnt
++ # cp u-boot-hg.ram.bin /mnt
++ # cp ../uloader-2.4.20/uloader.o /mnt
++ # cp ../uloader-2.4.20/u-boot-load-hg.sh /mnt
++ # umount /mmt
++
++ If you installed the serial port, open another window and use minicom to
++ connect to your LinkStation serial console. The serial port settings are
++ 57600,N,8, the same as the settings used by the original Linux kernel.
++
++ Start netcat to communicate with the U-Boot net console. Open another window
++ and run board/linkstation/nc.sh. Nc.sh is a simple script which invokes
++ netcat with the correct options. To quit nc, press ^T (control-T).
++ # cd $UBOOT_BUILD/u-boot-1.1.4
++ # board/linkstation/nc.sh <ip_of_your_linkstation>
++
++ Where <ip_of_your_linkstation> is CONFIG_IPADDR_LS (see Configure U-Boot
++ above). When you run nc.sh nothing will be written to the screen. This is
++ normal as Linux is not using the net console.
++
++ From your original window, use telnet to connect to the LinkStation and
++ launch U-Boot. Replace lshg in the example below with the name / IP address
++ of your LinkStation. Replace myroot with the login you created when you
++ gained telnet access. For LinkStation 1 / KuroBox standard, use
++ u-boot-load-hd.sh instead of u-boot-load-hg.sh. Type the commands shown in
++ bold.
++ # telnet lshg
++ Trying 192.168.0.58...
++ Connected to lshg.
++ Escape character is '^]'.
++ BUFFALO INC. Link Station series HD-HGLAN (IEMITSU)
++ HD-HGLAN6C5 login: myroot
++ Linux (none) 2.4.20_mvl31-ppc_linkstation #3 Thu May 19 13:34:18 JST 2005
++ ppc unknown
++ root@HD-HGLAN6C5:~# cd /mnt/share
++ root@HD-HGLAN6C5:/mnt/share# ./u-boot-load-hg.sh
++ root@HD-HGLAN6C5:/mnt/share# exit
++ Connection closed by foreign host.
++ #
++
++ If you have a serial console you should see the initial U-Boot startup
++ messages. Even if the default console is the net console, U-Boot still sends
++ the console output to the serial port until it initialises the network
++ controller.
++ U-Boot 1.1.4 LiSt 2.1.0 (Sep 12 2006 - 23:09:44) LinkStation HG / KuroBox HG
++ CPU: MPC8245 Revision 1.4 at 262.144 MHz: 16 kB I-Cache 16 kB D-Cache
++ DRAM: 128 MB
++ FLASH: 4 MB
++ *** Warning - bad CRC, using default environment
++ 00 0b 10ec 8169 0200 ff
++ 00 0c 1283 8212 0180 ff
++ 00 0e 1033 0035 0c03 ff
++ 00 0e 1033 0035 0c03 ff
++ 00 0e 1033 00e0 0c03 ff
++ Net: RTL8169#0
++
++ Watch the net console window. After a few seconds, time needed by U-Boot to
++ initialise the network controller and the IDE controller you should see the
++ U-Boot messages.
++ U-Boot 1.1.4 LiSt 2.1.0 (Sep 12 2006 - 23:09:44) LinkStation HG / KuroBox HG
++ IDE: Bus 0: OK
++ Device 0: Model: Maxtor 7Y250P0 Firm: YAR41BW0 Ser#: Y62W8PDE
++ Type: Hard Disk
++ Supports 48-bit addressing
++ Capacity: 239372.4 MB = 233.7 GB (490234752 x 512)
++ Boot in 10 seconds ('s' to stop)...
++
++ Press 's' on your keyboard to stop the boot process.
++
++ If you want to use the serial console, watch the power LED of your
++ LinkStation. When it starts blinking very slowly, use the power button to
++ stop the boot process. Wait for the power LED to go dim and press and hold
++ the power button until the LED lights up brightly indicating that the boot
++ process has stopped. Now press the reset button twice and you should see the
++ U-Boot command prompt (=>) in your minicom window. You can now control
++ U-Boot from the minicom window.
++
++ Using u-boot-load-hd.sh / u-boot-load-hg.sh leads to the above results on
++ devices with the original software. On some LinkStations with modified
++ software, reboot has been modified to send a reboot command to the AVR.
++ This is indicated by the fast blinking of the power LED immediately after
++ running u-boot-load-hd.sh / u-boot-load-hg.sh. Once the AVR receives a
++ reboot command, the reboot process cannot be stopped. The AVR will reboot
++ the LinkStation 5 min after receiving the reboot command.
++ If you find yourself in the above situation you can still test U-Boot by
++ booting your LinkStation with the AVR disabled. Press and hold the reset
++ button and then press the power button. All LEDs will start flashing but
++ your LinkStation will boot normally. Now you can use the procedure
++ described above with one caveat: the AVR being disabled, pressing the
++ buttons will have no effect so you will not be able to test the behaviour
++ of the minimal console.
++
++ Once you get the U-Boot command prompt, start testing it. Read the
++ [15]U-Boot documentation and try each command you are interested in.
++
++ Keep in mind that U-Boot interprets all input number as hex numbers. If, for
++ example, you type 256, U-Boot will interpret it as 598 decimal.
++
++ When you are testing memory write commands, do not attempt to write to the
++ first MB of memory (0x00000000 to 0x00100000) as you will be overwriting the
++ exception vectors and U-Boot will crash.
++
++ An important command is flinfo which displays information about the flash
++ chip. If the information displayed is correct for your flash, test the flash
++ erase and flash write commands. To do this, you will need to find an empty
++ sector, one for which each byte is 0xFF. Hint: check the last flash sector
++ first, chances are that it's empty. When you are testing commands that write
++ to the flash, always remember that you can write a single byte but you can
++ only erase whole sectors.
++
++ Be very careful not to write to the flash memory range 0xFFC00000 to
++ 0xFFF7FFFF. This area contains the Linux kernel, the initial RAM disk used
++ for EM mode, the bootloader and the configuration sector (which holds the
++ "OKOK" or "NGNG" pattern). The range 0xFFF80000 to 0xFFFFFFFF is the user
++ area and, in most cases, is empty. Always check using the U-Boot command md
++ (memory display) if the flash area you intend to use is empty (all bytes are
++ 0xFF). For more information about the flash organisation, read
++ [16]PPCFlashROM for the LinkStation 1 / KuroBox standard or [17]HGFlashROM
++ for the LinkStation HG / KuroBox HG.
++
++ ROM Build
++
++ Once you are happy with the RAM build, you are ready for the ROM build.
++
++ For LinkStation 1 / KuroBox standard run:
++ make linkstation_HDLAN_config
++ make linkstation_HDLAN
++
++ The name of the resulting binary is u-boot-hd.flash.bin
++
++ For LinkStation HG / KuroBox HG run:
++ make linkstation_HGLAN_config
++ make linkstation_HGLAN
++
++ The name of the resulting binary is u-boot-hg.flash.bin
++
++ Install
++
++ Do not attempt to flash from U-Boot if the power LED is blinking. Your
++ LinkStation is likely to reboot and you will end up with a "brick"
++ Test the flash commands thoroughly before deciding to burn U-Boot into
++ flash. Write at least 128 kB to the flash to test potential timeout
++ problems
++ The flash routines in this version of U-Boot for the LinkStation should be
++ able to identify and handle any CFI flash which uses the AMD standard
++ command set. However, they were tested only on a LinkStation with a Fujitsu
++ MBM29PL32TM flash chip and on a LinkStation HG with a ST Micro M29DW324DB
++ flash chip.
++ Be very careful not to flash your hardware with the wrong U-Boot build.
++ Flashing any RAM build or flashing a ROM build for the LinkStation 1 /
++ KuroBox standard into the LinkStation HG / KuroBox HG or viceversa will
++ "brick" your device. This is especially true if you are flashing from Linux
++ as U-Boot has safety checks to avoid flashing the wrong build.
++
++ Flashing U-Boot from U-Boot
++
++ The RAM build of U-Boot can be used to load and flash the ROM build. This is
++ the preferred method.
++
++ Boot your LinkStation normally. Open a telnet session and create a directory
++ to hold the U-Boot flash image.
++ root@linkstation:~# cd /mnt/share
++ root@linkstation:/mnt/share# mkdir u-boot
++
++ Copy the U-Boot flash image to your LinkStation SMB share in the directory
++ u-boot.
++
++ Load the RAM build of U-Boot and at the U-Boot command prompt type:
++ => run upgrade
++
++ U-Boot will attempt to load the ROM build from the directory share/u-boot/
++ on the third partition of the hard drive. If the load is successful, it will
++ do the following:
++ 1. unprotect the bootloader area;
++ 2. erase the bootloader area;
++ 3. copy the loaded file to the bootloader area;
++ 4. verify the copy;
++
++ Here is the output of run upgrade
++ => run upgrade
++ Loading 0:3:share/u-boot/u-boot-hg.flash.bin
++ 174668 bytes read
++ Un-Protected 3 sectors
++ Flash erase: first = 55 @ 0xfff00000
++ last = 57 @ 0xfff20000
++ Flash erase: Done
++ Erased 3 sectors
++ Copy to Flash... done
++ Total of 174668 bytes were the same
++ =>
++
++ When the above sequence finishes, U-Boot returns to the command prompt (=>).
++
++ Depending on your flash chip, the flash operation can take a long time. Wait
++ patiently and do not try to power down or otherwise interrupt the flash or
++ you will end up with a "brick".
++
++ Reboot:
++ => reset
++
++ The power LED should start blinking slowly and, if you have a serial
++ console, you should see the U-Boot startup messages. Your LinkStation is now
++ running U-Boot.
++
++ Flashing U-Boot from Linux
++
++ Connect to your LinkStation using either the serial port or telnet.
++
++ For LinkStation 1 / KuroBox standard run:
++ # cd /mnt/share/u-boot
++ # dd if=u-boot-hd.flash.bin of=/dev/fl2 bs=1k
++ # cmp u-boot.bin /dev/fl2
++
++ For LinkStation HG / KuroBox HG run:
++ # cd /mnt/share/u-boot
++ # dd if=u-boot-hg.flash.bin of=/dev/mtd1 bs=1k
++ # cmp u-boot.bin /dev/mtd1
++
++ The above commands for LinkStation HG / KuroBox HG will work on devices with
++ the original kernel version 2.4.20 but might to work on earlier devices
++ using kernel version 2.4.17. Please check which device corresponds to the
++ bootloader partition on your hardware.
++
++ If the Flash Fails
++
++ If the flash was not written correctly but U-Boot returns at the command
++ prompt, try to re-run run upgrade.
++
++ If the same happens when you attempt to install U-Boot from Linux, try to dd
++ again.
++
++ If your flash fails completely, for example due to a power failure, all is
++ not completely lost. You can still use a JTAG cable to re-flash your
++ Linkstation. Unfortunately, this is a relatively complicated and expensive
++ solution as it involves acquiring or building the JTAG cable and soldering
++ the header for it on the LinkStation motherboard. For more information on
++ how to use a JTAG cable with the LinkStation you can visit
++ [18]www.linkstationwiki.net and [19]www.kurobox.com/mwiki.
++
++ EM Mode
++
++ Warning for the LinkStation / LinkStation HG users
++
++ Do not attempt to boot into EM mode using the method described here. The
++ password for the EM mode is unknown for all LinkStation models.
++
++ Once you have U-Boot installed in the on-board flash, you can boot in EM
++ mode even if the third boot command described above doesn't work.
++
++ Stop the boot countdown by pressing 's' in your net console window and, at
++ the U-Boot command prompt, run:
++ => run writeng
++ => run flboot
++
++ The above commands write "NGNG" to 0xFFF70000 and boot from the on-board
++ flash. To revert to normal boot by writing "OKOK" to 0xFFF70000, run:
++ => run writeok
++ => boot
++
++ Advanced configuration
++
++ The initial U-Boot configuration can be changed by editing the file
++ include/configs/linkstation.h.
++
++ In all the examples below, please note the backslash-zero (\0) at the end of
++ the strings and the space-backslash ( \) at the end of each lines and do not
++ change them.
++
++ Change the name of the default boot file
++
++ Search for the lines containing:
++ "hdpart=0:1\0" \
++ "hdfile=boot/vmlinux.UBoot\0" \
++
++ and change them to the values you want. Partition 0:1 means disk 0,
++ partition 1. Obviously, you can only change the partition number as there is
++ only one disk. The name of the file must be given relative to the root of
++ the partition.
++
++ Change the default console to the serial console
++
++ Search for the lines containing:
++ "stdin=nc\0" \
++ "stdout=nc\0" \
++ "stderr=nc\0" \
++
++ and change them to:
++ "stdin=serial\0" \
++ "stdout=serial\0" \
++ "stderr=serial\0" \
++
++ Change the default boot command to boot from flash
++
++ Search for the lines containing:
++ "bootcmd1=run hdboot;run flboot\0" \
++ "bootcmd2=run flboot\0" \
++
++ and change them to:
++ "bootcmd1=run flboot\0" \
++ "bootcmd2=run hdboot;run flboot\0" \
++
++References
++
++ 1. http://www.linuxnotincluded.org.uk/fdl.txt
++ 2. http://www.linkstationwiki.net/index.php?title=CGI_Exploit_%28PowerPC%29_original_method_of_Hacking_the_LinkStation
++ 3. http://www.linkstationwiki.net/index.php?title=Turn_your_LinkStation_into_a_Kuro_Box_%28PowerPC%29
++ 4. http://linkstationwiki.net/index.php?title=OpenLink
++ 5. http://linkstationwiki.net/index.php?title=The_LinkStation_firmware_flasher
++ 6. http://downloads.linkstationwiki.net/snapshots/HD-HGLAN_149_100_telnet.zip
++ 7. http://www.linkstationwiki.net/index.php?title=Add_a_Serial_port_to_the_PowerPC_Linkstation
++ 8. http://netcat.sourceforge.net/
++ 9. http://www.vulnwatch.org/netcat
++ 10. http://ftp.sunet.se/pub/Linux/distributions/eldk/3.1.1/ppc-linux-x86/iso/ppc-2005-03-07.iso
++ 11. ftp://ftp.denx.de/pub/u-boot/u-boot-1.1.4.tar.bz2
++ 12. http://www.linuxnotincluded.org.uk/linkstation/downloads/u-boot-1.1.4-list-2.1.0.diff.gz
++ 13. http://www.linuxnotincluded.org.uk/linkstation/downloads/uloader-2.4.17.tar.gz
++ 14. http://www.linuxnotincluded.org.uk/linkstation/downloads/uloader-2.4.20.tar.gz
++ 15. http://www.denx.de/wiki/DULG/Manual
++ 16. http://linkstationwiki.net/index.php?title=Information/PPCFlashROM
++ 17. http://linkstationwiki.net/index.php?title=Information/HGFlashROM
++ 18. http://www.linkstationwiki.net/
++ 19. http://www.kurobox.com/mwiki
+diff -urN u-boot-86xx/board/linkstation/Makefile u-boot-86xx-kuro_clean/board/linkstation/Makefile
+--- u-boot-86xx/board/linkstation/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/Makefile 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,41 @@
++#
++# (C) Copyright 2001
++# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++#
++# See file CREDITS for list of people who contributed to this
++# project.
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2 of
++# the License, or (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++# MA 02111-1307 USA
++#
++
++include $(TOPDIR)/config.mk
++
++LIB = lib$(BOARD).a
++
++OBJS = $(BOARD).o flash.o ide.o hwctl.o bootls.o avr.o
++SOBJS = early_init.o
++
++$(LIB): .depend $(OBJS) $(SOBJS)
++ $(AR) crv $@ $(OBJS) $(SOBJS)
++
++#########################################################################
++
++.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
++ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
++
++sinclude .depend
++
++#########################################################################
+diff -urN u-boot-86xx/board/linkstation/avr.c u-boot-86xx-kuro_clean/board/linkstation/avr.c
+--- u-boot-86xx/board/linkstation/avr.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/avr.c 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,307 @@
++/*
++ * avr.c
++ *
++ * AVR functions
++ *
++ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
++ *
++ * 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 <common.h>
++#include <ns16550.h>
++#include <console.h>
++
++/* Button codes from the AVR */
++#define PWRR 0x20 /* Power button release */
++#define PWRP 0x21 /* Power button push */
++#define RESR 0x22 /* Reset button release */
++#define RESP 0x23 /* Reset button push */
++#define AVRINIT 0x33 /* Init complete */
++#define AVRRESET 0x31 /* Reset request */
++
++/* LED commands */
++#define PWRBLINKSTRT '[' /* Blink power LED */
++#define PWRBLINKSTOP 'Z' /* Solid power LED */
++#define HDDLEDON 'W' /* HDD LED on */
++#define HDDLEDOFF 'V' /* HDD LED off */
++#define HDDBLINKSTRT 'Y' /* HDD LED start blink */
++#define HDDBLINKSTOP 'X' /* HDD LED stop blink */
++
++/* Timings for LEDs blinking to show choice */
++#define PULSETIME 250 /* msecs */
++#define LONGPAUSE (5 * PULSETIME)
++
++/* Button press times */
++#define PUSHHOLD 1000 /* msecs */
++#define NOBUTTON (6 * (LONGPAUSE+PULSETIME))
++
++/* Boot and console choices */
++#define MAX_BOOT_CHOICE 3
++
++static char *consoles[] = {
++ "serial",
++#if defined(CONFIG_NETCONSOLE)
++ "nc",
++#endif
++};
++#define MAX_CONS_CHOICE (sizeof(consoles)/sizeof(char *))
++
++#if !defined(CONFIG_NETCONSOLE)
++#define DEF_CONS_CHOICE 0
++#else
++#define DEF_CONS_CHOICE 1
++#endif
++
++#define perror(fmt,args...) printf("%s: ",__FUNCTION__);printf(fmt,##args)
++
++extern void miconCntl_SendCmd(unsigned char dat);
++extern void miconCntl_DisWDT(void);
++
++static int boot_stop;
++
++static int boot_choice = 1;
++static int cons_choice = DEF_CONS_CHOICE;
++
++static char envbuffer[16];
++
++void init_AVR_DUART (void)
++{
++ NS16550_t AVR_port = (NS16550_t) CFG_NS16550_COM2;
++ int clock_divisor = CFG_NS16550_CLK / 16 / 9600;
++
++ /*
++ * AVR port init sequence taken from
++ * the original Linkstation init code
++ * Normal U-Boot serial reinit doesn't
++ * work because the AVR uses even parity
++ */
++ AVR_port->lcr = 0x00;
++ AVR_port->ier = 0x00;
++ AVR_port->lcr = LCR_BKSE;
++ AVR_port->dll = clock_divisor & 0xff;
++ AVR_port->dlm = (clock_divisor >> 8) & 0xff;
++ AVR_port->lcr = LCR_WLS_8 | LCR_PEN | LCR_EPS;
++ AVR_port->mcr = 0x00;
++ AVR_port->fcr = FCR_FIFO_EN | FCR_RXSR | FCR_TXSR;
++
++ miconCntl_DisWDT();
++
++ boot_stop = 0;
++ miconCntl_SendCmd(PWRBLINKSTRT);
++}
++
++void hw_watchdog_reset (void)
++{
++}
++
++static inline int avr_tstc(void)
++{
++ return (NS16550_tstc((NS16550_t)CFG_NS16550_COM2));
++}
++
++static inline char avr_getc(void)
++{
++ return (NS16550_getc((NS16550_t)CFG_NS16550_COM2));
++}
++
++static int push_timeout(char button_code)
++{
++ ulong push_start = get_timer(0);
++ while (get_timer(push_start) <= PUSHHOLD)
++ if (avr_tstc() && avr_getc() == button_code)
++ return 0;
++ return 1;
++}
++
++static void next_boot_choice(void)
++{
++ ulong return_start;
++ ulong pulse_start;
++ int on_times;
++ int button_on;
++ int led_state;
++ char c;
++
++ button_on = 0;
++ return_start = get_timer(0);
++
++ on_times = boot_choice;
++ led_state = 0;
++ miconCntl_SendCmd(HDDLEDOFF);
++ pulse_start = get_timer(0);
++
++ while (get_timer(return_start) <= NOBUTTON || button_on)
++ {
++ if (avr_tstc()) {
++ c = avr_getc();
++ if (c == PWRP)
++ button_on = 1;
++ else if (c == PWRR) {
++ button_on = 0;
++ return_start = get_timer(0);
++ if (++boot_choice > MAX_BOOT_CHOICE)
++ boot_choice = 1;
++ sprintf(envbuffer, "bootcmd%d", boot_choice);
++ if (getenv(envbuffer)) {
++ sprintf(envbuffer, "run bootcmd%d", boot_choice);
++ setenv("bootcmd", envbuffer);
++ }
++ on_times = boot_choice;
++ led_state = 1;
++ miconCntl_SendCmd(HDDLEDON);
++ pulse_start = get_timer(0);
++ } else {
++ perror("Unexpected code: 0x%02X\n", c);
++ }
++ }
++ if (on_times && get_timer(pulse_start) > PULSETIME) {
++ if (led_state == 1) {
++ --on_times;
++ led_state = 0;
++ miconCntl_SendCmd(HDDLEDOFF);
++ } else {
++ led_state = 1;
++ miconCntl_SendCmd(HDDLEDON);
++ }
++ pulse_start = get_timer(0);
++ }
++ if (!on_times && get_timer(pulse_start) > LONGPAUSE) {
++ on_times = boot_choice;
++ led_state = 1;
++ miconCntl_SendCmd(HDDLEDON);
++ pulse_start = get_timer(0);
++ }
++ }
++ if (led_state)
++ miconCntl_SendCmd(HDDLEDOFF);
++}
++
++void next_cons_choice(int console)
++{
++ ulong return_start;
++ ulong pulse_start;
++ int on_times;
++ int button_on;
++ int led_state;
++ char c;
++ device_t *idev;
++ device_t *odev;
++
++ button_on = 0;
++ cons_choice = console;
++ return_start = get_timer(0);
++
++ on_times = cons_choice+1;
++ led_state = 1;
++ miconCntl_SendCmd(HDDLEDON);
++ pulse_start = get_timer(0);
++
++ while (get_timer(return_start) <= NOBUTTON || button_on)
++ {
++ if (avr_tstc()) {
++ c = avr_getc();
++ if (c == RESP)
++ button_on = 1;
++ else if (c == RESR) {
++ button_on = 0;
++ return_start = get_timer(0);
++ cons_choice = (cons_choice + 1) % MAX_CONS_CHOICE;
++ idev = search_device(DEV_FLAGS_INPUT, consoles[cons_choice]);
++ odev = search_device(DEV_FLAGS_OUTPUT, consoles[cons_choice]);
++ console_setfile (stdin, idev);
++ console_setfile (stdout, odev);
++ console_setfile (stderr, odev);
++ on_times = cons_choice+1;
++ led_state = 0;
++ miconCntl_SendCmd(HDDLEDOFF);
++ pulse_start = get_timer(0);
++ } else {
++ perror("Unexpected code: 0x%02X\n", c);
++ }
++ }
++ if (on_times && get_timer(pulse_start) > PULSETIME) {
++ if (led_state == 0) {
++ --on_times;
++ led_state = 1;
++ miconCntl_SendCmd(HDDLEDON);
++ } else {
++ led_state = 0;
++ miconCntl_SendCmd(HDDLEDOFF);
++ }
++ pulse_start = get_timer(0);
++ }
++ if (!on_times && get_timer(pulse_start) > LONGPAUSE) {
++ on_times = cons_choice+1;
++ led_state = 0;
++ miconCntl_SendCmd(HDDLEDOFF);
++ pulse_start = get_timer(0);
++ }
++ }
++ if (led_state);
++ miconCntl_SendCmd(HDDLEDOFF);
++}
++
++int avr_input(void)
++{
++ char avr_button;
++ int ret;
++
++ if (!avr_tstc())
++ return 0;
++
++ avr_button = avr_getc();
++ switch (avr_button) {
++ case PWRP:
++ if (push_timeout(PWRR)) {
++ /* Timeout before power button release */
++ boot_stop = ~boot_stop;
++ if (boot_stop)
++ miconCntl_SendCmd(PWRBLINKSTOP);
++ else
++ miconCntl_SendCmd(PWRBLINKSTRT);
++ /* Wait for power button release */
++ while (avr_getc() != PWRR)
++ ;
++ }
++ else
++ /* Power button released */
++ next_boot_choice();
++ break;
++ case RESP:
++ /* Wait for Reset button release */
++ while (avr_getc() != RESR)
++ ;
++ next_cons_choice(cons_choice);
++ break;
++ case AVRINIT:
++ return 0;
++ default:
++ perror("Unexpected code: 0x%02X\n", avr_button);
++ return 0;
++ }
++ if (boot_stop)
++ return (-3);
++ else
++ return (-2);
++}
++
++void avr_StopBoot(void)
++{
++ boot_stop = ~0;
++ miconCntl_SendCmd(PWRBLINKSTOP);
++}
++
++/* vim: set ts=4: */
+diff -urN u-boot-86xx/board/linkstation/bootls.c u-boot-86xx-kuro_clean/board/linkstation/bootls.c
+--- u-boot-86xx/board/linkstation/bootls.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/bootls.c 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,304 @@
++/*
++ * bootls.c
++ *
++ * Boot a Linkstation kernel of type firmimg.bin
++ *
++ * U-Boot loader code for Linkstation kernel. A file of type firmimg.bin
++ * consists of a header, immediately followed by a compressed kernel image,
++ * followed by a compressed initrd image.
++ *
++ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
++ *
++ * 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
++ *
++ * Derived from:
++ *
++ * arch/ppc/common/misc-simple.c (linux-2.4.17_mvl21-sandpoint)
++ * Author: Matt Porter <mporter@mvista.com>
++ * Derived from arch/ppc/boot/prep/misc.c
++ * 2001 (c) MontaVista, Software, Inc.
++ *
++ * common/cmd_bootm.c (u-boot-1.1.4)
++ * (C) Copyright 2000-2002
++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++ *
++ */
++
++#include <common.h>
++#include <command.h>
++
++#include "firminfo.h"
++
++#define _ALIGN(addr,size) (((addr)+size-1)&(~(size-1)))
++
++struct bi_record {
++ unsigned long tag; /* tag ID */
++ unsigned long size; /* size of record (in bytes) */
++ unsigned long data[0]; /* data */
++};
++
++#define BI_FIRST 0x1010 /* first record - marker */
++#define BI_LAST 0x1011 /* last record - marker */
++
++extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
++extern int gunzip(void *, int, unsigned char *, int *);
++
++/*
++ * output BYTE data
++ */
++static inline void outb(volatile unsigned char *addr, int val)
++{
++ asm volatile("eieio");
++ asm volatile("stb%U0%X0 %1,%0; sync; isync" : "=m" (*addr) : "r" (val));
++}
++
++unsigned long checksum_check(unsigned char* addr, unsigned long size)
++{
++ long *laddr = (long *)addr;
++ unsigned long sum = 0,remain = 0;
++ int i;
++ while(size>=4) {
++ sum += *laddr;
++ laddr++;
++ size -= 4;
++ }
++ addr = (unsigned char*)laddr;
++ for(i=0;i<4;++i) {
++ remain = remain << 8;
++ if(size>i) remain += *addr;
++ addr++;
++ }
++ sum += remain;
++ return sum;
++}
++
++void do_boot_lskernel (cmd_tbl_t *cmdtp,
++ int flag,
++ int argc,
++ char *argv[],
++ unsigned long load_addr,
++ unsigned long *len_ptr,
++ int verify)
++{
++ DECLARE_GLOBAL_DATA_PTR;
++
++ char *zimage_start;
++ int zimage_size;
++ unsigned long initrd_start;
++ unsigned long initrd_end;
++ unsigned long sp;
++ unsigned long cmd_start;
++ unsigned long cmd_end;
++ char *cmdline;
++ char *s;
++ bd_t *kbd;
++ void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
++ unsigned long iflag;
++ struct firminfo *info = (struct firminfo *)load_addr;
++ struct bi_record *rec;
++
++ int i;
++ char *flashstr="FLASH";
++
++ for (i=0; i <= 4; i++)
++ if (info->subver[i] != flashstr[i]) {
++ puts ("Not a Linkstation kernel\n");
++ return;
++ }
++
++ printf("\n******* Product Information *******\n");
++ printf("----------------------------------\n");
++
++ printf("Product Name: %s\n", info->firmname);
++ printf(" VER: %d.%02d\n", info->ver_major, info->ver_minor);
++ printf(" Date: %d/%d/%d %d:%d:%d\n",
++ info->year+1900, info->mon, info->day,
++ info->hour,info->min,info->sec);
++ printf("----------------------------------\n");
++
++ if (verify) {
++ printf("Verifying checksum... ");
++ if (checksum_check((unsigned char*)info, info->size) != 0) {
++ printf("Failed!: checksum %08X, expecting 0\n",
++ checksum_check((unsigned char*)info, info->size));
++ return; /* Returns on error */
++ } else
++ printf("OK\n");
++ }
++
++ zimage_start = (char*)info + info->kernel_offset;
++ zimage_size = (int)info->kernel_size;
++ iflag = disable_interrupts();
++ puts("Uncompressing kernel...");
++ if (gunzip(0, 0x400000, zimage_start, &zimage_size) != 0) {
++ puts ("Failed! MUST reset board to recover\n");
++ do_reset (cmdtp, flag, argc, argv);
++ } else
++ puts("done.\n");
++
++ /*
++ * Allocate space for command line and board info - the
++ * address should be as high as possible within the reach of
++ * the kernel (see CFG_BOOTMAPSZ settings), but in unused
++ * memory, which means far enough below the current stack
++ * pointer.
++ */
++
++ asm( "mr %0,1": "=r"(sp) : );
++ debug ("## Current stack ends at 0x%08lX ", sp);
++ sp -= 2048; /* just to be sure */
++ if (sp > CFG_BOOTMAPSZ)
++ sp = CFG_BOOTMAPSZ;
++ sp &= ~0xF;
++ debug ("=> set upper limit to 0x%08lX\n", sp);
++
++ cmdline = (char *)((sp - CFG_BARGSIZE) & ~0xF);
++ if ((s = getenv("bootargs")) == NULL)
++ s = "root=/dev/hda1";
++ strcpy (cmdline, s);
++ cmd_start = (ulong)&cmdline[0];
++ cmd_end = cmd_start + strlen(cmdline);
++ debug ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end);
++
++ kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF);
++ *kbd = *(gd->bd);
++ if ((s = getenv ("clocks_in_mhz")) != NULL) {
++ /* convert all clock information to MHz */
++ kbd->bi_intfreq /= 1000000L;
++ kbd->bi_busfreq /= 1000000L;
++ }
++
++ kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))0x4;
++
++ if (info->initrd_size > 0) {
++ initrd_start = (unsigned long)((char*)info + info->initrd_offset);
++ initrd_end = initrd_start + info->initrd_size;
++ if(initrd_start > 0xffc00000 && initrd_end < 0xffefffff) {
++ unsigned long nsp;
++ unsigned long data;
++
++ data = initrd_start;
++ /*
++ * the inital ramdisk does not need to be within
++ * CFG_BOOTMAPSZ as it is not accessed until after
++ * the mm system is initialised.
++ *
++ * do the stack bottom calculation again and see if
++ * the initrd will fit just below the monitor stack
++ * bottom without overwriting the area allocated
++ * above for command line args and board info.
++ */
++ asm( "mr %0,1": "=r"(nsp) : );
++ nsp -= 2048; /* just to be sure */
++ nsp &= ~0xF;
++ nsp -= info->initrd_size;
++ nsp &= ~(4096 - 1); /* align on page */
++ initrd_start = nsp;
++ initrd_end = initrd_start + info->initrd_size;
++ printf ("Loading Ramdisk at 0x%08lX, end 0x%08lX ... ",
++ initrd_start, initrd_end);
++ memmove ((void *)initrd_start, (void *)data, info->initrd_size);
++ puts ("OK\n");
++ }
++ } else {
++ initrd_start = 0;
++ initrd_end = 0;
++ }
++
++ /*
++ * The kernel looks for this structure even if
++ * the information in it is replaced by the
++ * Linkstation kernel
++ */
++ rec = (struct bi_record *)_ALIGN((unsigned long)zimage_size +
++ (1 << 20) - 1,(1 << 20));
++ rec->tag = BI_FIRST;
++ rec->size = sizeof(struct bi_record);
++ rec = (struct bi_record *)((unsigned long)rec + rec->size);
++ rec->tag = BI_LAST;
++ rec->size = sizeof(struct bi_record);
++
++#if defined(CONFIG_HLAN) || defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++ // kernel load done.
++ outb(0x80004500, 0x49); // send signal
++ outb(0x80004500, 0x49); // send signal
++ outb(0x80004500, 0x49); // send signal
++ outb(0x80004500, 0x49); // send signal
++#endif
++#if defined(CONFIG_HGLAN)
++ // full speed
++ udelay(10000); /* 10 msec */
++ outb(0x80004500, 0x5D); // send signal
++ outb(0x80004500, 0x5D); // send signal
++ outb(0x80004500, 0x5D); // send signal
++ outb(0x80004500, 0x5D); // send signal
++#endif
++#if defined(CONFIG_HTGL)
++ // LINK/ACT led controll
++ outb(0x80004500, 0x61); // a
++ outb(0x80004500, 0x61); // a
++ outb(0x80004500, 0x39); // 9
++ outb(0x80004500, 0x31); // 1
++ outb(0x80004500, 0x39); // 9
++ outb(0x80004500, 0x30); // 0
++ outb(0x80004500, 0x92); // 1000Mbps down
++ outb(0x80004500, 0x92); // 1000Mbps down
++
++ udelay(10000); /* 10 msec */
++ outb(0x80004500, 0x61); // a
++ outb(0x80004500, 0x61); // a
++ outb(0x80004500, 0x39); // 9
++ outb(0x80004500, 0x30); // 0
++ outb(0x80004500, 0x39); // 9
++ outb(0x80004500, 0x30); // 0
++ outb(0x80004500, 0x90); // 100Mbps down
++ outb(0x80004500, 0x90); // 100Mbps down
++
++ udelay(10000); /* 10 msec */
++ outb(0x80004500, 0x61); // a
++ outb(0x80004500, 0x61); // a
++ outb(0x80004500, 0x38); // 8
++ outb(0x80004500, 0x46); // F
++ outb(0x80004500, 0x39); // 9
++ outb(0x80004500, 0x30); // 0
++ outb(0x80004500, 0x8E); // 10Mbps down
++ outb(0x80004500, 0x8E); // 10Mbps down
++
++ udelay(10000); /* 10 msec */
++ outb(0x80004500, 0x5F); // _
++ outb(0x80004500, 0x5F); // _
++#endif
++
++/*
++ * This is what the original boot loader sends
++ * just before jumping to the kernel start
++ */
++ outb(0xFF000001, 0xFF);
++
++ puts("Booting the kernel\n");
++
++ /*
++ * Linux Kernel Parameters:
++ * r3: ptr to board info data
++ * r4: initrd_start or 0 if no initrd
++ * r5: initrd_end - unused if r4 is 0
++ * r6: Start of command line string
++ * r7: End of command line string
++ */
++ (*kernel)((bd_t *)0xFF000001, initrd_start, initrd_end, cmd_start, cmd_end);
++}
++
++/* vim: set ts=4: */
+diff -urN u-boot-86xx/board/linkstation/config.mk u-boot-86xx-kuro_clean/board/linkstation/config.mk
+--- u-boot-86xx/board/linkstation/config.mk 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/config.mk 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,50 @@
++#
++# (C) Copyright 2001-2003
++# 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
++#
++
++# LinkStation/LinkStation-HG:
++#
++# Valid values for TEXT_BASE are:
++#
++# Standard configuration - all models
++# 0xFFF00000 boot from flash
++#
++# Test configuration (boot from RAM using uloader.o)
++# LinkStation HD-HLAN and KuroBox Standard
++# 0x03F00000 boot from RAM
++# LinkStation HD-HGLAN and KuroBox HG
++# 0x07F00000 boot from RAM
++#
++
++sinclude $(TOPDIR)/board/$(BOARDDIR)/config.tmp
++
++ifndef TEXT_BASE
++# For flash image - all models
++TEXT_BASE = 0xFFF00000
++# For RAM image
++# HLAN and LAN
++#TEXT_BASE = 0x03F00000
++# HGLAN and HGTL
++#TEXT_BASE = 0x07F00000
++endif
++
++PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
+diff -urN u-boot-86xx/board/linkstation/early_init.S u-boot-86xx-kuro_clean/board/linkstation/early_init.S
+--- u-boot-86xx/board/linkstation/early_init.S 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/early_init.S 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,432 @@
++/*
++ * board/linkstation/early_init.S
++ *
++ * Begin at some arbitrary location in RAM or Flash
++ * Initialize core registers
++ * Configure memory controller (Not executing from RAM)
++ * Initialize UARTs
++ * Simple RAM test (currently suspended)
++ *
++ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
++ *
++ * 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 for U-Boot from arch/ppc/boot/linkstation/head.S from
++ * the GPL code for the Buffalo Terastation, derived in its turn from:
++ *
++ * arch/ppc/boot/sandpoint/head.S
++ *
++ * Initial board bringup code for Motorola SPS Sandpoint test platform
++ *
++ * Author: Mark A. Greer
++ * mgreer@mvista.com
++ * Derived from arch/ppc/boot/pcore/head.S (mporter@mvista.com)
++ *
++ * Copyright 2001 MontaVista Software Inc.
++ */
++
++#include <config.h>
++#include <ppc_asm.tmpl>
++#include <mpc824x.h>
++#include <ppc_defs.h>
++#include <asm/cache.h>
++
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
++#define RAM_SIZE 0x04000000
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++#define RAM_SIZE 0x08000000
++#endif
++
++#define UART1 0x80004500
++#define UART1_IER 0x80004501
++#define UART1_FCR 0x80004502
++#define UART1_LCR 0x80004503
++#define UART1_DCR 0x80004511
++#define UART2 0x80004600
++#define UART2_IER 0x80004601
++#define UART2_FCR 0x80004602
++#define UART2_LCR 0x80004603
++#define UART2_DCR 0x80004611
++
++#define WM32(address,data) \
++ lis r3, address@h; \
++ ori r3, r3, address@l; \
++ lis r4, data@h; \
++ ori r4, r4, data@l; \
++ stw r4, 0x0000(r3); \
++ sync; \
++ isync;
++
++#define WM16(address,data) \
++ lis r3, address@h; \
++ ori r3, r3, address@l; \
++ li r4, data; \
++ sth r4, 0x0000(r3); \
++ sync; \
++ isync;
++
++#define WM8(address,data) \
++ lis r3, address@h; \
++ ori r3, r3, address@l; \
++ li r4, data; \
++ stb r4, 0(r3); \
++ sync; \
++ isync;
++
++ .text
++
++ .globl early_init_f
++early_init_f:
++/*
++ * Configure core registers
++ */
++
++ /* Establish default MSR value, exception prefix 0xFFF */
++ li r3,MSR_IP|MSR_FP
++ mtmsr r3
++
++ /* Clear BATS */
++ li r8,0
++ mtspr DBAT0U,r8
++ mtspr DBAT0L,r8
++ mtspr DBAT1U,r8
++ mtspr DBAT1L,r8
++ mtspr DBAT2U,r8
++ mtspr DBAT2L,r8
++ mtspr DBAT3U,r8
++ mtspr DBAT3L,r8
++ mtspr IBAT0U,r8
++ mtspr IBAT0L,r8
++ mtspr IBAT1U,r8
++ mtspr IBAT1L,r8
++ mtspr IBAT2U,r8
++ mtspr IBAT2L,r8
++ mtspr IBAT3U,r8
++ mtspr IBAT3L,r8
++ isync
++ sync
++ sync
++
++ /* Set segment registers */
++ lis r8, 0x0000
++ isync
++ mtsr SR0,r8
++ mtsr SR1,r8
++ mtsr SR2,r8
++ mtsr SR3,r8
++ mtsr SR4,r8
++ mtsr SR5,r8
++ mtsr SR6,r8
++ mtsr SR7,r8
++ mtsr SR8,r8
++ mtsr SR9,r8
++ mtsr SR10,r8
++ mtsr SR11,r8
++ mtsr SR12,r8
++ mtsr SR13,r8
++ mtsr SR14,r8
++ mtsr SR15,r8
++ isync
++ sync
++ sync
++
++ /* Disable L1 icache/dcache */
++ li r4,0x0000
++ isync
++ mtspr HID0,r4
++ sync
++ isync
++
++ /* Flash Invalidate L1 icache/dcache */
++
++ ori r4,r4,0x8000
++ ori r8,r4,0x0800
++ isync
++ mtspr HID0,r8
++ sync
++ isync
++
++ /* Older cores need to manually clear ICFI bit */
++
++ mtspr HID0,r4
++ sync
++ isync
++
++#if !defined(CFG_RAMBOOT)
++melco_config_start:
++ /* --- CPU Configration registor setting for LinkStation --- */
++ WM32(0x80041020,0x000000a0) /* Reset EPIC */
++
++ /* errata for latency timer */
++ WM32(0xFEC00000,0x0d000080)
++ WM8(0xFEE00001,0x20)
++ /* cash size */
++ WM32(0xFEC00000,0x0c000080)
++ WM8(0xFEE00000,0x08)
++ /* PCI configuration command register */
++ WM32(0xFEC00000,0x04000080)
++ WM16(0xFEE00000,0x0600)
++ /* Processor interface configuration register 1 */
++ WM32(0xFEC00000,0xa8000080)
++ /* WM32(0xFEE00000,0xd8131400) */
++ lis r3, 0xFEE00000@h
++ ori r3, r3, 0xFEE00000@l
++
++ lwz r5, 0(r3) /* load PCIR1 Config */
++ lis r4, 0x0
++ ori r4, r4, 0x1000
++ and r5, r4, r5 /* Get Bit20(RCS0) */
++
++ lis r4, 0xd8130400@h
++ ori r4, r4, 0xd8130400@l
++ or r4, r4, r5 /* Save (RCS0) */
++
++ stw r4, 0x0000(r3)
++ sync
++ isync
++
++ /* Processor interface configuration register 2 */
++ WM32(0xFEC00000,0xac000080)
++ WM32(0xFEE00000,0x00000004)
++ /* Embeded Utility Memory Block Base Address register */
++ WM32(0xFEC00000,0x78000080)
++ WM32(0xFEE00000,0x00000080)
++ /* Address map B option register */
++ WM32(0xFEC00000,0xe0000080)
++ WM8(0xFEE00000,0x20) /* DLL_RESET on */
++
++ /* Address map B option register */
++ WM32(0xFEC00000,0xe0000080)
++ WM8(0xFEE00000,0xc0)
++ /* PCI arbiter control register */
++ WM32(0xFEC00000,0x46000080)
++ WM16(0xFEE00002,0x00c0)
++
++ /* Added to use the high drive strength for the memory selects & addressing */
++ WM32(0xFEC00000,0x73000080)
++ /* WM8(0xFEE00003,0x15) */ /*0x17*/
++ /* Motorola Errata refer to User's Manual Errata#19 */
++ /* WM8(0xFEE00003,0xD5) */
++ WM8(0xFEE00003,0x95)
++
++ /* set miscellaneous I/O control register 1 */
++ WM32(0xFEC00000,0x76000080)
++ WM8(0xFEE00002,0x00) /*0x02*/
++ /* set miscellaneous I/O control register 2 */
++ WM32(0xFEC00000,0x77000080)
++ WM8(0xFEE00003,0x30) /* 0x30 */
++
++ /* init memory controller */
++ WM32(0xFEC00000,0x80000080)
++ WM32(0xFEE00000,0x00FFFFFF)
++
++ WM32(0xFEC00000,0x84000080)
++ WM32(0xFEE00000,0xFFFFFFFF)
++
++ WM32(0xFEC00000,0x90000080)
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
++ WM32(0xFEE00000,0x3FFFFFFF) /* 64MB */
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++ WM32(0xFEE00000,0x7FFFFFFF) /* 128MB */
++#endif
++
++ WM32(0xFEC00000,0x94000080)
++ WM32(0xFEE00000,0xFFFFFFFF)
++
++ WM32(0xFEC00000,0x88000080)
++ WM32(0xFEE00000,0x00030303)
++ /* EMSAR2 */
++ WM32(0xFEC00000,0x8C000080)
++ WM32(0xFEE00000,0x03030303)
++ /* select EMSER1 */
++ WM32(0xFEC00000,0x98000080)
++ WM32(0xFEE00000,0x00030303)
++ /* select EMSER2 */
++ WM32(0xFEC00000,0x9C000080)
++ WM32(0xFEE00000,0x03030303)
++
++ /* MMCR1 */
++ WM32(0xFEC00000,0xf0000080)
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
++ WM32(0xFEE00000,0x0200E005) /* bank 0 13xnx4 */
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++ WM32(0xFEE00000,0x0200E005) /* bank 0 13xnx4 */
++#endif
++ /* MCCR2 */
++ WM32(0xFEC00000,0xf4000080)
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
++ WM32(0xFEE00000,0xe0150000) /* 100MHz Memory bus */
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++ WM32(0xFEE00000,0x80150000) /* 133MHz Memory bus */
++#endif
++ /* MCCR3 */
++ WM32(0xFEC00000,0xf8000080)
++ WM32(0xFEE00000,0x00000077) /* BSTOPRE_M =7 / REFREC=8 */
++
++ /* MCCR4 */
++ WM32(0xFEC00000,0xfc000080)
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
++ WM32(0xFEE00000,0x29233222) /* CAS latency=2, burst length=8, Ext Rom=eable */
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++ WM32(0xFEE00000,0x29323222) /* CAS latency=3, burst length=4, Ext Rom=eable */
++#endif
++
++ /* Output driver control register */
++ WM32(0xFEC00000,0x73000080)
++ WM8(0xFEE00003,0x15) /* for all 40 ohm */
++ /* CLK driver Control Register */
++ WM32(0xFEC00000,0x74000080)
++ WM16(0xFEE00000,0x7078)
++ /* select MBEN */
++ WM32(0xFEC00000,0xa0000080)
++ WM8(0xFEE00000, 0x01)
++ /* MPM */
++ WM32(0xFEC00000,0xa3000080)
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
++ WM8(0xFEE00003,0xF2) /* PGMAX = 242 */
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++ WM8(0xFEE00003,0xC9) /* PGMAX = 201 */
++#endif
++ /* ERCR s */
++ WM32(0xFEC00000,0xd0000080) /* ; select ERCR1 */
++ WM32(0xFEE00000,0xffffff85)
++ WM32(0xFEC00000,0xd4000080) /* ; select ERCR2 */
++ WM32(0xFEE00000,0xffffff05)
++ WM32(0xFEC00000,0xd8000080) /* ; select ERCR3 */
++ WM32(0xFEE00000,0x0000f80f)
++ WM32(0xFEC00000,0xdc000080) /* ; select ERCR4 */
++ WM32(0xFEE00000,0x0e000000)
++
++ /* MCCR1 */
++ WM32(0xFEC00000,0xf0000080)
++ WM32(0xFEE00000,0x0200E805) /* 11 + 3 clock wait MEMGO on */
++
++ /* Init UART for AVR */
++ WM8(UART1_LCR,0x00) /* clear LCR */
++ WM8(UART1_IER,0x00) /* disable interrupt */
++ WM8(UART1_LCR,0x80) /* set LCR[DLAB] bit */
++ WM8(UART1_DCR,0x01) /* set DUART mode */
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
++ WM8(UART1, 0x8B) /* set DLL(baudrate 9600bps, 100MHz) */
++ WM8(UART1_IER,0x02) /* set DLM(baudrate 9600bps, 100MHz) */
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++ WM8(UART1, 0x61) /* set DLL(baudrate 9600bps, 133MHz) */
++ WM8(UART1_IER,0x03) /* set DLM(baudrate 9600bps, 133MHz) */
++#endif
++ WM8(UART1_LCR,0x1b) /* set 8data, 1stop, even parity */
++ WM8(UART1, 0x00) /* clear MCR */
++ WM8(UART1_FCR,0x07) /* clear & enable FIFO */
++
++ /* Init UART for CONSOLE */
++ WM8(UART2_LCR,0x00) /* clear LCR */
++ WM8(UART2_IER,0x00) /* disable interrupt */
++ WM8(UART2_LCR,0x80) /* set LCR[DLAB] bit */
++ WM8(UART1_DCR,0x01) /* set DUART mode */
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
++ WM8(UART2, 0x6C) /* set DLL(baudrate 57600bps, 100MHz) */
++ WM8(UART2_IER,0x00) /* set DLM(baudrate 57600bps, 100MHz) */
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++ WM8(UART2, 0x90) /* set DLL(baudrate 57600bps, 133MHz) */
++ WM8(UART2_IER,0x00) /* set DLM(baudrate 57600bps, 133MHz) */
++#endif
++ WM8(UART2_LCR,0x03) /* set 8data, 1stop, non parity */
++ WM8(UART2, 0x00) /* clear MCR */
++ WM8(UART2_FCR,0x07) /* clear & enable FIFO */
++#endif /* !defined (CFG_RAMBOOT)
++
++ /* PCI Command Register initialize */
++ lis r3, 0x8000
++ ori r3, r3, 0x0004
++ lis r4, 0xFEC0
++ ori r4, r4, 0x0000
++ stwbrx r4, 0, r3
++ sync
++ isync
++
++ li r6, 0x0006
++ lis r5, 0xFEE0
++ ori r5, r5, 0x0000
++ sthbrx r5, 0, r6
++ sync
++ isync
++
++#if !defined(CFG_RAMBOOT)
++check_ram:
++ /* Wait 1 sec for AVR become enable */
++ li r3,1000
++ mulli r3,r3,1000
++ mulli r4,r3,1000 /* nanoseconds */
++ addi r4,r4,39
++ li r5,40 /* 40ns if for 100 Mhz bus */
++ divw r4,r4,r5 /* BUS ticks */
++1: mftbu r5
++ mftb r6
++ mftbu r7
++ cmp 0,r5,r7
++ bne 1b /* Get [synced] base time */
++ addc r9,r6,r4 /* Compute end time */
++ addze r8,r5
++2: mftbu r5
++ cmp 0,r5,r8
++ blt 2b
++ bgt 3f
++ mftb r6
++ cmp 0,r6,r9
++ blt 2b
++#if 1
++3:
++#else
++ /* Check RAM */
++ /* set start address(0x00000000) */
++3: xor r4,r4,r4
++ lis r5, RAM_SIZE@h
++ ori r5, r5, RAM_SIZE@l
++ lis r6, 0xaaaa /* mask pattern a */
++ ori r6, r6, 0xaaaa
++ lis r7, 0x5555 /* mask pattern b */
++ ori r7, r7, 0x5555
++ lis r8, 0x0000 /* check step size */
++ ori r8, r8, 0x0100
++check_ram_loop:
++ cmp 0,r4,r5
++ beq check_ram_end
++ stw r6,0(r4)
++ isync
++ lwz r3,0(r4)
++ isync
++ cmp 0,r3,r6
++ bne ram_error
++ stw r7,0x00fc(r4)
++ isync
++ lwz r3,0x00fc(r4)
++ isync
++ cmp 0,r3,r7
++ bne ram_error
++ add r4,r4,r8
++ b check_ram_loop
++ram_error:
++#if defined(CONFIG_LAN)
++ WM8(UART1,0x39) /* ram error */
++#elif defined(CONFIG_HGLAN) ||defined(CONFIG_HLAN) || defined(CONFIG_HTGL)
++ WM8(UART1,0x6F) /* ram error */
++#endif
++ b ram_error
++check_ram_end:
++#endif /* #if 1 */
++#endif /* !defined (CFG_RAMBOOT) */
++
++/* The instruction cache is enabled and the data cache is disabled */
++ blr
+diff -urN u-boot-86xx/board/linkstation/firminfo.h u-boot-86xx-kuro_clean/board/linkstation/firminfo.h
+--- u-boot-86xx/board/linkstation/firminfo.h 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/firminfo.h 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,27 @@
++#define FIRMNAME_MAX 31
++#define SUBVERSION_MAX 31
++#define FIRMINFO_VER 1
++
++struct firminfo {
++ unsigned long info_ver;
++ unsigned long firmid;
++ char firmname[FIRMNAME_MAX+1];
++ char subver[SUBVERSION_MAX+1];
++ unsigned short ver_major;
++ unsigned short ver_minor;
++ unsigned short build;
++ char year;
++ char mon;
++ char day;
++ char hour;
++ char min;
++ char sec;
++ unsigned long size;
++ unsigned long chksum;
++
++ unsigned long kernel_offset;
++ unsigned long kernel_size;
++ unsigned long initrd_offset;
++ unsigned long initrd_size;
++ } __attribute((aligned(4)));
++// ----------------------------------------------------
+diff -urN u-boot-86xx/board/linkstation/flash.c u-boot-86xx-kuro_clean/board/linkstation/flash.c
+--- u-boot-86xx/board/linkstation/flash.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/flash.c 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,893 @@
++/*
++ * flash.c
++ *
++ * Flash device interface for LinkStation
++ * Supports CFI flash devices using the AMD standard command set
++ *
++ * Copyright (C) 2006 Mihai Georgin <u-boot@linuxnotincluded.org.uk>
++ *
++ * 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
++ *
++ * Based on the MTD code from the Linux kernel
++ *
++ * Based on include/melco/flashd.c (linux-2.4.17_mvl21-sandpoint)
++ * Copyright (C) 2001-2004 BUFFALO INC.
++ */
++#include <common.h>
++#include <asm/io.h>
++#include <mpc824x.h>
++
++#if 0
++#define DEBUG_CFI
++#endif
++
++#undef debug
++#ifdef DEBUG_CFI
++#define debug(fmt,args...) printf(fmt,##args)
++#else
++#define debug(fmt,args...)
++#endif /* DEBUG_CFI */
++
++#if CFG_MAX_FLASH_BANKS > 1
++#error Only 1 flash bank supported
++#endif
++
++#define perror(fmt,args...) printf("%s: ",__FUNCTION__);printf(fmt,##args)
++
++#define MAX_ERASE_REGIONS 4
++
++#define P_ID_NONE 0
++#define P_ID_INTEL_EXT 1
++#define P_ID_AMD_STD 2
++#define P_ID_INTEL_STD 3
++#define P_ID_AMD_EXT 4
++#define P_ID_MITSUBISHI_STD 256
++#define P_ID_MITSUBISHI_EXT 257
++#define P_ID_RESERVED 65535
++
++#define CFI_DEVICETYPE_X8 (8 / 8)
++#define CFI_DEVICETYPE_X16 (16 / 8)
++
++#define FLASH_DATA_MASK 0xFF
++
++#define FUJ_MANUFACT_LS (FUJ_MANUFACT & FLASH_DATA_MASK)
++#define STM_MANUFACT_LS (STM_MANUFACT & FLASH_DATA_MASK)
++#define MX_MANUFACT_LS (MX_MANUFACT & FLASH_DATA_MASK)
++
++/* Unknown manufacturer */
++#define FLASH_MAN_UNKNOWN 0xFFFF0000
++
++/* Fujitsu MBM29PL320MT which is using the same */
++/* codes as the AMD Am29LV320MT "mirror" flash */
++#define AMD_ID_MIRROR_LS (AMD_ID_MIRROR & FLASH_DATA_MASK)
++#define AMD_ID_LV320T_2_LS (AMD_ID_LV320T_2 & FLASH_DATA_MASK)
++#define AMD_ID_LV320T_3_LS (AMD_ID_LV320T_3 & FLASH_DATA_MASK)
++
++/* ST Micro M29W320DT and M29W320DB */
++#define STM_ID_29W320DT_LS (STM_ID_29W320DT & FLASH_DATA_MASK)
++#define STM_ID_29W320DB_LS (STM_ID_29W320DB & FLASH_DATA_MASK)
++
++/* ST Micro M29DW324DT and M29DW324DB */
++#define STM_ID_29W324DT_LS (STM_ID_29W324DT & FLASH_DATA_MASK)
++#define STM_ID_29W324DB_LS (STM_ID_29W324DB & FLASH_DATA_MASK)
++
++/* Macronix MX29LV320T */
++#define MX_ID_LV320T_LS (MX_ID_LV320T & FLASH_DATA_MASK)
++
++/* Basic Query Structure */
++struct cfi_ident {
++ __u8 qry[3];
++ __u16 P_ID;
++ __u16 P_ADR;
++ __u16 A_ID;
++ __u16 A_ADR;
++ __u8 VccMin;
++ __u8 VccMax;
++ __u8 VppMin;
++ __u8 VppMax;
++ __u8 WordWriteTimeoutTyp;
++ __u8 BufWriteTimeoutTyp;
++ __u8 BlockEraseTimeoutTyp;
++ __u8 ChipEraseTimeoutTyp;
++ __u8 WordWriteTimeoutMax;
++ __u8 BufWriteTimeoutMax;
++ __u8 BlockEraseTimeoutMax;
++ __u8 ChipEraseTimeoutMax;
++ __u8 DevSize;
++ __u16 InterfaceDesc;
++ __u16 MaxBufWriteSize;
++ __u8 NumEraseRegions;
++ __u32 EraseRegionInfo[MAX_ERASE_REGIONS];
++} __attribute__((packed));
++
++struct cfi_private {
++ __u32 base;
++ int device_type;
++ int addr_unlock1;
++ int addr_unlock2;
++ struct cfi_ident *cfiq;
++ int mfr;
++ int id[3]; /* Supports AMD MirrorBit flash */
++ char *flash_name;
++ int wrd_wr_time;
++ int buf_wr_time;
++ int erase_time;
++ int (*blk_erase)(flash_info_t *info, int s_first, int s_last);
++ int (*blk_write)(flash_info_t *info, __u8 *buf, __u32 addr, int sz);
++};
++
++static inline __u8 cfi_read8(__u32 addr)
++{
++ return (*(volatile __u8 *)(addr));
++}
++
++static inline void cfi_write8(__u8 val, __u32 addr)
++{
++ *(volatile __u8 *)(addr) = val;
++ sync();
++}
++
++/*
++ * Sends a CFI command to a bank of flash for the given type.
++ * Returns the offset to the sent command
++ */
++static inline __u32 cfi_cmd(__u8 cmd, __u32 cmd_addr, __u32 base, int type)
++{
++ __u32 addr;
++
++ addr = base + cmd_addr * type;
++ if (cmd_addr * type == 0x554)
++ ++addr;
++
++ cfi_write8(cmd, addr);
++
++ return addr - base;
++}
++
++static inline __u8 cfi_read_query(__u32 addr)
++{
++ return cfi_read8(addr);
++}
++
++flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
++static struct cfi_private cfis;
++static struct cfi_ident cfi_idents;
++static struct cfi_private *cfi;
++
++static int cfi_probe_chip(struct cfi_private *cfi);
++static unsigned long cfi_amdstd_setup(struct cfi_private *cfi, int primary);
++static void print_cfi_ident(struct cfi_ident *);
++static int flash_amdstd_erase(flash_info_t *info, int s_first, int s_last);
++static int flash_amdstd_wbuff(flash_info_t *info, __u8 *buf, __u32 addr,int sz);
++static int flash_amdstd_wubyp(flash_info_t *info, __u8 *buf, __u32 addr,int sz);
++static int flash_amdstd_write(flash_info_t *info, __u8 *buf, __u32 addr,int sz);
++
++
++
++unsigned long flash_init(void)
++{
++ unsigned long flash_size;
++ __u16 type;
++
++ debug("%s\n", __FUNCTION__);
++
++ cfi = &cfis;
++ memset(cfi, 0, sizeof(struct cfi_private));
++
++ cfi->base = CFG_FLASH_BASE;
++
++ /* Identify CFI chip */
++ /* Probe for X8 device first */
++ cfi->device_type = CFI_DEVICETYPE_X8;
++ if (cfi_probe_chip(cfi)) {
++ /* The probe didn't like it */
++ /* so probe for X16/X8 device */
++ cfi->device_type = CFI_DEVICETYPE_X16;
++ if (cfi_probe_chip(cfi)) {
++ /* The probe didn't like it */
++ return 0UL;
++ }
++ }
++
++ /* Check if it is AMD standard cmd set */
++ type = cfi->cfiq->P_ID;
++ if (type == P_ID_AMD_STD)
++ flash_size = cfi_amdstd_setup(cfi, 1);
++ else {
++ perror("Primary cmd set is not AMD std. Trying alternate.\n");
++ flash_size = 0;
++ }
++ if (!flash_size) {
++ type = cfi->cfiq->A_ID;
++ if (type == P_ID_AMD_STD)
++ flash_size = cfi_amdstd_setup(cfi, 0);
++ else {
++ perror("Alternate cmd set is not AMD std.\n");
++ return 0UL;
++ }
++ }
++
++ if (flash_size && flash_size == 4*1024*1024) {
++ /* Flash protection ON by default */
++ flash_protect(FLAG_PROTECT_SET, cfi->base, cfi->base+flash_size-1, flash_info);
++
++ return flash_size;
++ }
++
++ if (flash_size) {
++ perror("Unsupported flash size: %d\n", flash_size);
++ } else {
++ perror("Vendor Command Set not supported\n");
++ printf("Primary: 0x%04X, Alternate: 0x%04X\n",
++ cfi->cfiq->P_ID, cfi->cfiq->A_ID);
++ }
++ return 0UL;
++}
++
++void flash_print_info(flash_info_t *info)
++{
++ int i;
++
++ debug("%s\n", __FUNCTION__);
++
++ printf("Flash chip: %s\n\n",
++ cfi->flash_name?cfi->flash_name:"UNKNOWN");
++ print_cfi_ident(cfi->cfiq);
++ printf("\nActual values used by U-Boot:\n");
++ printf("Word write timeout: %6d ms\n", cfi->wrd_wr_time);
++ printf("Buffer write timeout: %6d ms\n", cfi->buf_wr_time);
++ printf("Sector erase timeout: %6d ms\n", cfi->erase_time);
++ printf("\nSize: %ld MiB in %d Sectors\n",info->size>>20,info->sector_count);
++ printf (" Sector Start Addresses:");
++ for (i=0; i<info->sector_count; i++) {
++ if (!(i % 5))
++ printf ("\n ");
++ printf (" %08lX%s", info->start[i], info->protect[i]?" (RO)" : " (RW)");
++ }
++ printf ("\n");
++}
++
++int flash_erase(flash_info_t *info, int s_first, int s_last)
++{
++ return (*(cfi->blk_erase))(info, s_first, s_last);
++}
++
++int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt)
++{
++ return (*(cfi->blk_write))(info, src, addr, cnt);
++}
++
++static int cfi_probe_chip(struct cfi_private *cfi)
++{
++ int ofs_factor = cfi->device_type;
++ __u32 base = cfi->base;
++ int num_erase_regions, scount;
++ int i;
++
++ debug("%s\n", __FUNCTION__);
++
++ cfi_cmd(0xF0, 0x00, base, cfi->device_type);
++ cfi_cmd(0x98, 0x55, base, cfi->device_type);
++
++ if (cfi_read8(base + ofs_factor * 0x10) != 'Q' ||
++ cfi_read8(base + ofs_factor * 0x11) != 'R' ||
++ cfi_read8(base + ofs_factor * 0x12) != 'Y') {
++ debug("Not a CFI flash\n");
++ /* Put the chip back into read array mode */
++ cfi_cmd(0xF0, 0x00, base, cfi->device_type);
++ return -1;
++ }
++
++ num_erase_regions = cfi_read_query(base + 0x2C * ofs_factor);
++ if (!num_erase_regions) {
++ perror("No erase regions\n");
++ /* Put the chip back into read read array mode */
++ cfi_cmd(0xF0, 0x00, base, cfi->device_type);
++ return -1;
++ }
++ if (num_erase_regions > MAX_ERASE_REGIONS) {
++ perror("Number of erase regions (%d) > MAX_ERASE_REGIONS (%d)\n",
++ num_erase_regions, MAX_ERASE_REGIONS);
++ /* Put the chip back into read read array mode */
++ cfi_cmd(0xF0, 0x00, base, cfi->device_type);
++ return -1;
++ }
++
++ cfi->cfiq = &cfi_idents;
++ memset(cfi->cfiq, 0, sizeof(struct cfi_ident));
++ debug("cfi->cfiq: 0x%08X\n", cfi->cfiq);
++
++ /* Read the CFI info structure */
++ for (i=0; i < sizeof(struct cfi_ident) + num_erase_regions * 4; i++)
++ ((__u8 *)cfi->cfiq)[i] = cfi_read_query(base + (0x10 + i) * ofs_factor);
++
++ /* Do any necessary byteswapping */
++ cfi->cfiq->P_ID = __le16_to_cpu(cfi->cfiq->P_ID);
++ cfi->cfiq->P_ADR = __le16_to_cpu(cfi->cfiq->P_ADR);
++ cfi->cfiq->A_ID = __le16_to_cpu(cfi->cfiq->A_ID);
++ cfi->cfiq->A_ADR = __le16_to_cpu(cfi->cfiq->A_ADR);
++ cfi->cfiq->InterfaceDesc = __le16_to_cpu(cfi->cfiq->InterfaceDesc);
++ cfi->cfiq->MaxBufWriteSize = __le16_to_cpu(cfi->cfiq->MaxBufWriteSize);
++
++#if 0
++ /* Dump the information therein */
++ print_cfi_ident(cfi->cfiq);
++#endif
++
++ scount = 0;
++ for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
++ cfi->cfiq->EraseRegionInfo[i] = __le32_to_cpu(cfi->cfiq->EraseRegionInfo[i]);
++ scount += (cfi->cfiq->EraseRegionInfo[i] & 0xFFFF) + 1;
++ debug(" Erase Region #%d: sector size 0x%4.4X bytes, %d sectors\n",
++ i, (cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xFF,
++ (cfi->cfiq->EraseRegionInfo[i] & 0xFFFF) + 1);
++ }
++ /* Put it back into Read Mode */
++ cfi_cmd(0xF0, 0, base, cfi->device_type);
++
++ if (scount > CFG_MAX_FLASH_SECT) {
++ perror("Number of sectors (%d) > CFG_MAX_FLASH_SECT (%d)\n",
++ scount, CFG_MAX_FLASH_SECT);
++ return -1;
++ }
++
++ debug("Found x%d device in 8-bit mode\n", cfi->device_type*8);
++
++ return 0;
++}
++
++static char *vendorname(__u16 vendor)
++{
++ switch (vendor) {
++ case P_ID_NONE:
++ return "None";
++ case P_ID_INTEL_EXT:
++ return "Intel/Sharp Extended";
++ case P_ID_AMD_STD:
++ return "AMD/Fujitsu Standard";
++ case P_ID_INTEL_STD:
++ return "Intel/Sharp Standard";
++ case P_ID_AMD_EXT:
++ return "AMD/Fujitsu Extended";
++ case P_ID_MITSUBISHI_STD:
++ return "Mitsubishi Standard";
++ case P_ID_MITSUBISHI_EXT:
++ return "Mitsubishi Extended";
++ case P_ID_RESERVED:
++ return "Not Allowed / Reserved for Future Use";
++ default:
++ return "Unknown";
++ }
++}
++
++static void print_cfi_ident(struct cfi_ident *cfip)
++{
++ printf("CFI Query Results:\n");
++ printf("Primary Vendor Command Set: 0x%4.4X (%s)\n",
++ cfip->P_ID, vendorname(cfip->P_ID));
++ if (cfip->P_ADR)
++ printf("Primary Algorithm Table at 0x%4.4X\n", cfip->P_ADR);
++ else
++ printf("No Primary Algorithm Table\n");
++
++ printf("Alternate Vendor Command Set: 0x%4.4X (%s)\n",
++ cfip->A_ID, vendorname(cfip->A_ID));
++ if (cfip->A_ADR)
++ printf("Alternate Algorithm Table at 0x%4.4X\n", cfip->A_ADR);
++ else
++ printf("No Alternate Algorithm Table\n");
++
++ printf("Vcc Min.: %d.%d V\n", cfip->VccMin >> 4, cfip->VccMin & 0xF);
++ printf("Vcc Max.: %d.%d V\n", cfip->VccMax >> 4, cfip->VccMax & 0xF);
++ if (cfip->VppMin) {
++ printf("Vpp Min.: %d.%d V\n", cfip->VppMin >> 4, cfip->VppMin & 0xF);
++ printf("Vpp Max.: %d.%d V\n", cfip->VppMax >> 4, cfip->VppMax & 0xF);
++ }
++ else
++ printf("No Vpp line\n");
++
++ printf("Typical byte/word write timeout: %d us\n",
++ 1<<cfip->WordWriteTimeoutTyp);
++ printf("Maximum byte/word write timeout: %d us\n",
++ (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
++
++ if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
++ printf("Typical full buffer write timeout: %d us\n",
++ 1<<cfip->BufWriteTimeoutTyp);
++ printf("Maximum full buffer write timeout: %d us\n",
++ (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
++ }
++ else
++ printf("Full buffer write not supported\n");
++
++ printf("Typical block erase timeout: %d ms\n",
++ 1<<cfip->BlockEraseTimeoutTyp);
++ printf("Maximum block erase timeout: %d ms\n",
++ (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
++ if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
++ printf("Typical chip erase timeout: %d ms\n",
++ 1<<cfip->ChipEraseTimeoutTyp);
++ printf("Maximum chip erase timeout: %d ms\n",
++ (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
++ }
++ else
++ printf("Chip erase not supported\n");
++
++ printf("Device size: 0x%X bytes (%d MiB)\n",
++ 1 << cfip->DevSize, 1 << (cfip->DevSize - 20));
++ printf("Flash Device Interface description: 0x%4.4X\n",cfip->InterfaceDesc);
++ switch(cfip->InterfaceDesc) {
++ case 0:
++ printf(" - x8-only asynchronous interface\n");
++ break;
++ case 1:
++ printf(" - x16-only asynchronous interface\n");
++ break;
++ case 2:
++ printf(" - x8 / x16 via BYTE# with asynchronous interface\n");
++ break;
++ case 3:
++ printf(" - x32-only asynchronous interface\n");
++ break;
++ case 65535:
++ printf(" - Not Allowed / Reserved\n");
++ break;
++ default:
++ printf(" - Unknown\n");
++ break;
++ }
++ printf("Max. bytes in buffer write: %d\n", 1 << cfip->MaxBufWriteSize);
++ printf("Number of Erase Block Regions: %d\n", cfip->NumEraseRegions);
++}
++
++static unsigned long cfi_amdstd_setup(struct cfi_private *cfi, int primary)
++{
++ flash_info_t *info = &flash_info[0];
++ __u32 base = cfi->base;
++ int ofs_factor = cfi->device_type;
++ __u32 addr_et = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
++ __u8 major, minor, bootloc;
++ __u32 offset, ernum, ersize;
++ int i, j;
++
++ /* Put the chip into read array mode */
++ cfi_cmd(0xF0, 0x00, base, cfi->device_type);
++ /* Autoselect */
++ cfi_cmd(0xAA, 0x555, base, cfi->device_type);
++ cfi_cmd(0x55, 0x2AA, base, cfi->device_type);
++ cfi_cmd(0x90, 0x555, base, cfi->device_type);
++ /* Read manufacturer and device id */
++ cfi->mfr = cfi_read_query(base + 0x00 * ofs_factor);
++ if ((cfi->id[0] = cfi_read_query(base + 0x01 * ofs_factor)) == 0x7E) {
++ cfi->id[1] = cfi_read_query(base + 0x0E * ofs_factor);
++ cfi->id[2] = cfi_read_query(base + 0x0F * ofs_factor);
++ }
++ /* Put the chip into read array mode */
++ cfi_cmd(0xF0, 0x00, base, cfi->device_type);
++
++ /* Put the chip into read query mode */
++ cfi_cmd(0x98, 0x55, base, cfi->device_type);
++ /* Find the boot block location and swap the erase regions as necessary */
++ major = cfi_read_query(base + (addr_et + 3) * ofs_factor);
++ minor = cfi_read_query(base + (addr_et + 4) * ofs_factor);
++ debug(" Amd/Fujitsu Extended Query Table v%c.%c at 0x%4.4X\n",
++ major, minor, addr_et);
++
++ if (((major << 8) | minor) < 0x3131) {
++ /* CFI version 1.0 => don't trust bootloc */
++ if (cfi->id[0] & 0x80) {
++ printf("Device ID is 0x%02X. Assuming broken CFI table.\n",
++ cfi->id[0]);
++ bootloc = 3; /* top boot */
++ } else
++ bootloc = 2; /* bottom boot */
++ } else
++ bootloc = cfi_read_query(base + (addr_et + 0xF) * ofs_factor);
++
++ if (bootloc == 3 && cfi->cfiq->NumEraseRegions > 1) {
++ debug("Top boot block. Swapping erase regions.\n");
++ for (i=0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
++ int j = (cfi->cfiq->NumEraseRegions-1)-i;
++ __u32 swap;
++
++ swap = cfi->cfiq->EraseRegionInfo[i];
++ cfi->cfiq->EraseRegionInfo[i] = cfi->cfiq->EraseRegionInfo[j];
++ cfi->cfiq->EraseRegionInfo[j] = swap;
++ }
++ }
++
++ /* Put the chip into read array mode */
++ cfi_cmd(0xF0, 0x00, base, cfi->device_type);
++
++ switch (cfi->device_type) {
++ case CFI_DEVICETYPE_X8:
++ /* X8 chip */
++ cfi->addr_unlock1 = 0x555;
++ cfi->addr_unlock2 = 0x2AA;
++ break;
++ case CFI_DEVICETYPE_X16:
++ /* X16 chip in X8 mode */
++ cfi->addr_unlock1 = 0xAAA;
++ cfi->addr_unlock2 = 0x555;
++ break;
++ default:
++ perror("Unsupported device type %d\n", cfi->device_type);
++ return 0UL;
++ }
++
++ cfi->wrd_wr_time = 1 << cfi->cfiq->WordWriteTimeoutTyp;
++ cfi->wrd_wr_time *= 1 << cfi->cfiq->WordWriteTimeoutMax;
++ /* Word write time is in us, convert to ms */
++ cfi->wrd_wr_time = cfi->wrd_wr_time / 1000 + 1;
++ if (cfi->wrd_wr_time == 1)
++ /* Account for the timer resolution which is 1 ms */
++ cfi->wrd_wr_time = 2;
++ cfi->buf_wr_time = 1 << cfi->cfiq->BufWriteTimeoutTyp;
++ cfi->buf_wr_time *= 1 << cfi->cfiq->BufWriteTimeoutMax;
++ /* Buffer write time is in us, convert to ms */
++ cfi->buf_wr_time = cfi->buf_wr_time / 1000 + 1;
++ if (cfi->buf_wr_time == 1)
++ /* Account for the timer resolution which is 1 ms */
++ cfi->buf_wr_time = 2;
++ cfi->erase_time = 1 << cfi->cfiq->BlockEraseTimeoutTyp;
++ cfi->erase_time *= 1 << cfi->cfiq->BlockEraseTimeoutMax;
++
++ info->size = (1 << cfi->cfiq->DevSize);
++
++ info->sector_count = 0;
++ offset = CFG_FLASH_BASE;
++ for (i=0; i < cfi->cfiq->NumEraseRegions; i++) {
++ ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xFF);
++ ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xFFFF) + 1;
++
++ for (j=0; j < ernum; j++) {
++ info->start[info->sector_count + j] = offset;
++ offset += ersize;
++ }
++
++ info->sector_count += ernum;
++ }
++
++ switch (cfi->mfr) {
++ case FUJ_MANUFACT_LS:
++ info->flash_id = FLASH_MAN_FUJ;
++ switch (cfi->id[0]) {
++ case AMD_ID_MIRROR_LS:
++ if (cfi->id[1] == AMD_ID_LV320T_2_LS &&
++ cfi->id[2] == AMD_ID_LV320T_3_LS) {
++ info->flash_id += FLASH_AMLV320T;
++ cfi->blk_write = flash_amdstd_wbuff;
++ cfi->flash_name = "FUJITSU MBM29PL32TM";
++ } else
++ info->flash_id += FLASH_UNKNOWN;
++ break;
++ default:
++ info->flash_id += FLASH_UNKNOWN;
++ break;
++ }
++ break;
++ case STM_MANUFACT_LS:
++ info->flash_id = FLASH_MAN_STM;
++ switch (cfi->id[0]) {
++ case STM_ID_29W320DT_LS:
++ info->flash_id += FLASH_STMW320DT;
++ cfi->blk_write = flash_amdstd_wubyp;
++ cfi->flash_name = "STMICRO M29W320DT";
++ break;
++ case STM_ID_29W320DB_LS:
++ info->flash_id += FLASH_STMW320DB;
++ cfi->blk_write = flash_amdstd_wubyp;
++ cfi->flash_name = "STMICRO M29W320DB";
++ break;
++ case STM_ID_29W324DT_LS:
++ info->flash_id += FLASH_STMW324DT;
++ cfi->blk_write = flash_amdstd_wubyp;
++ cfi->flash_name = "STMICRO M29W324DT";
++ break;
++ case STM_ID_29W324DB_LS:
++ info->flash_id += FLASH_STMW324DB;
++ cfi->blk_write = flash_amdstd_wubyp;
++ cfi->flash_name = "STMICRO M29W324DB";
++ break;
++ default:
++ info->flash_id += FLASH_UNKNOWN;
++ break;
++ }
++ break;
++ case MX_MANUFACT_LS:
++ info->flash_id = FLASH_MAN_MX;
++ switch (cfi->id[0]) {
++ case MX_ID_LV320T_LS:
++ info->flash_id += FLASH_MXLV320T;
++ cfi->blk_write = flash_amdstd_write;
++ cfi->flash_name = "MXIC MX29LV320T";
++ break;
++ default:
++ info->flash_id += FLASH_UNKNOWN;
++ break;
++ }
++ break;
++ default:
++ info->flash_id = FLASH_AMD_COMP;
++ break;
++ }
++
++ if ((info->flash_id & FLASH_TYPEMASK) == FLASH_UNKNOWN) {
++ /* Unknown but supported CFI flash */
++ cfi->flash_name = NULL;
++ if (cfi->cfiq->MaxBufWriteSize)
++ cfi->blk_write = flash_amdstd_wbuff;
++ else
++ cfi->blk_write = flash_amdstd_write;
++ }
++
++ cfi->blk_erase = flash_amdstd_erase;
++
++ return info->size;
++}
++
++#define BIT(x) (1<<x)
++/*
++ * Check the flash command state
++ */
++static int flash_amdstd_state(__u32 addr, __u32 target, int timeout)
++{
++ __u32 start_time = get_timer(0);
++ __u32 data;
++
++ debug("%s\n", __FUNCTION__);
++
++ do {
++ data = cfi_read8(addr);
++ if((data & BIT(7)) == (target & BIT(7)))
++ return 0;
++ if(data & BIT(5)) {
++ data = cfi_read8(addr);
++ if((data & BIT(7)) == (target & BIT(7)))
++ return 0;
++ else
++ return -1;
++ }
++ } while (get_timer(start_time) < timeout);
++ return -1;
++}
++
++/*
++ * Verify data written to flash
++ */
++static int flash_amdstd_vrfy(flash_info_t *info, __u8 *buf, __u32 addr, int sz)
++{
++ __u32 base = cfi->base;
++ __u8 *faddr;
++ long i;
++
++ debug("%s\n", __FUNCTION__);
++
++ faddr = (__u8 *)addr;
++ for(i=0; i < sz; i++) {
++ if(faddr[i] != buf[i]) {
++ printf("Flash Write verify fail at %08x. ", &faddr[i]);
++ printf("Expecting: %02X, Actual: %02X\n", faddr[i], buf[i]);
++ printf("Retrying...");
++ cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0xA0, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++ cfi_write8(buf[i], (__u32)&faddr[i]);
++ if (flash_amdstd_state((__u32)&faddr[i], buf[i], cfi->wrd_wr_time)) {
++ printf("failed again\n");
++ cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
++ return 1;
++ } else
++ printf("suceeded\n");
++ }
++ }
++ return 0;
++}
++
++/*
++ * Erase flash sectors
++ */
++static int flash_amdstd_erase(flash_info_t *info, int s_first, int s_last)
++{
++ int prot, sect, nsect, flag;
++ __u32 l_sect;
++ __u32 base = cfi->base;
++
++ debug("%s\n", __FUNCTION__);
++
++ if (!info->size) {
++ printf ("Flash erase: Can't erase unsupported flash\n");
++ return 1;
++ }
++
++ if (s_first < 0 || s_first > s_last ||
++ s_first > (info->sector_count - 1) ||
++ s_last > (info->sector_count - 1)) {
++ printf ("Flash erase: no sectors to erase\n");
++ return 1;
++ }
++
++ printf("\nFlash erase: first = %d @ 0x%08lx\n",
++ s_first, info->start[s_first]);
++ printf(" last = %d @ 0x%08lx\n", s_last, info->start[s_last]);
++
++ nsect = s_last - s_first + 1;
++ for (prot = 0, sect=s_first; sect<=s_last; ++sect)
++ if (info->protect[sect])
++ prot++;
++ if (prot) {
++ if (prot == nsect) {
++ printf("Warning: All requested sectors are protected!\n");
++ printf(" No sectors to erase\n");
++ return 1;
++ }
++ else
++ printf("Warning: %d protected sectors will not be erased!\n", prot);
++ }
++ cfi_cmd(0xF0, 0x00, base, CFI_DEVICETYPE_X8);
++ udelay(1000);
++
++ /* Disable interrupts which might cause a timeout here */
++ flag = disable_interrupts();
++
++ cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x80, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
++ for (sect = s_first; sect <= s_last; sect++)
++ if (!info->protect[sect]) {
++ l_sect = info->start[sect];
++ cfi_write8(0x30, l_sect);
++ }
++ /* Erase begins 50us after the last sector address */
++ udelay(50);
++
++ /* All erase commands sent, enable interrupts */
++ if (flag)
++ enable_interrupts();
++
++ if (flash_amdstd_state(l_sect, 0xff, cfi->erase_time * nsect)) {
++ printf("Flash erase: Timeout\n");
++ cfi_cmd(0xF0, 0x00, base, CFI_DEVICETYPE_X8);
++ return 1;
++ }
++ printf("Flash erase: Done\n");
++ return 0;
++}
++
++/*
++ * Write to flash using Write Buffer programming
++ */
++static int flash_amdstd_wbuff(flash_info_t *info, __u8 *buf, __u32 addr, int sz)
++{
++ __u32 base = cfi->base;
++ __u32 wbufsz;
++ __u32 size, wsize, waddr, saddr;
++ __u8 *wbuf;
++ int i;
++
++ debug("%s\n", __FUNCTION__);
++
++ size = sz;
++ wbuf = buf;
++ wbufsz = 1 << cfi->cfiq->MaxBufWriteSize;
++
++ waddr = (addr + wbufsz - 1) & ~(wbufsz - 1);
++ if (waddr > addr)
++ wsize = waddr-addr;
++ else
++ wsize = wbufsz;
++ if (wsize > size)
++ wsize = size;
++ waddr = addr;
++
++ while (size > 0) {
++ for (i = 0; i < info->sector_count; i++)
++ if (waddr < info->start[i])
++ break;
++ saddr = info->start[i-1];
++
++ cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
++ cfi_write8(0x25, saddr);
++ cfi_write8(wsize-1, saddr);
++ for (i = 0; i < wsize; i++)
++ cfi_write8(*wbuf++, waddr++);
++ cfi_write8(0x29, saddr);
++
++ if (flash_amdstd_state(waddr-1, *(wbuf-1), cfi->buf_wr_time)) {
++ printf("Flash write buffer: Timeout\n");
++ cfi_cmd(0xF0, 0x00, base, CFI_DEVICETYPE_X8);
++ return 1;
++ }
++
++ size -= wsize;
++ if ((wsize = wbufsz) > size)
++ wsize = size;
++ }
++
++ return flash_amdstd_vrfy(info, buf, addr, sz);
++}
++
++/*
++ * Write to flash using Unlock Bypass command sequence
++ */
++static int flash_amdstd_wubyp(flash_info_t *info, __u8 *buf, __u32 addr, int sz)
++{
++ __u32 base = cfi->base;
++ __u32 waddr;
++ long i;
++
++ debug("%s\n", __FUNCTION__);
++
++ waddr = addr;
++
++ cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x20, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++
++ for(i=0; i < sz; i++) {
++ cfi_write8(0xA0, waddr);
++ cfi_write8(buf[i], waddr);
++ if (flash_amdstd_state(waddr, buf[i], cfi->wrd_wr_time)) {
++ printf("Flash unlock bypass write: Timeout\n");
++ cfi_cmd(0x90, 0, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x00, 0, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
++ return 1;
++ }
++ waddr++;
++ }
++ cfi_cmd(0x90, 0, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x00, 0, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
++
++ return flash_amdstd_vrfy(info, buf, addr, sz);
++}
++
++/*
++ * Write to flash using Word/Byte Program command sequence
++ */
++static int flash_amdstd_write(flash_info_t *info, __u8 *buf, __u32 addr, int sz)
++{
++ __u32 base = cfi->base;
++ __u32 waddr;
++ long i;
++
++ debug("%s\n", __FUNCTION__);
++
++ waddr = addr;
++
++ cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
++ for (i = 0; i < sz; i++) {
++ cfi_cmd(0xAA, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0x55, cfi->addr_unlock2, base, CFI_DEVICETYPE_X8);
++ cfi_cmd(0xA0, cfi->addr_unlock1, base, CFI_DEVICETYPE_X8);
++ cfi_write8(buf[i], waddr);
++ if (flash_amdstd_state(waddr, buf[i], cfi->wrd_wr_time)) {
++ printf("Flash write: Timeout\n");
++ cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
++ return 1;
++ }
++ waddr++;
++ }
++ cfi_cmd(0xF0, 0, base, CFI_DEVICETYPE_X8);
++
++ return flash_amdstd_vrfy(info, buf, addr, sz);
++}
++
++/* vim: set ts=4: */
+diff -urN u-boot-86xx/board/linkstation/hwctl.c u-boot-86xx-kuro_clean/board/linkstation/hwctl.c
+--- u-boot-86xx/board/linkstation/hwctl.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/hwctl.c 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,258 @@
++/*
++ * hwctl.c
++ *
++ * LinkStation HW Control Driver
++ *
++ * Copyright (C) 2001-2004 BUFFALO INC.
++ *
++ * This software may be used and distributed according to the terms of
++ * the GNU General Public License (GPL), incorporated herein by reference.
++ * Drivers based on or derived from this code fall under the GPL and must
++ * retain the authorship, copyright and license notice. This file is not
++ * a complete program and may only be used when the entire operating
++ * system is licensed under the GPL.
++ *
++ */
++
++#include <config.h>
++#include <common.h>
++#include <command.h>
++
++#define mdelay(n) udelay((n)*1000)
++
++#define AVR_PORT CFG_NS16550_COM2
++extern void udelay(unsigned long usec);
++
++
++// output BYTE data
++static inline void out_b(volatile unsigned char *addr, int val)
++{
++ __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val));
++}
++
++#if 0
++// PWR,DISK_FULL/STATUS,DIAG LED controll
++void blink_led(unsigned char state)
++{
++#ifdef CONFIG_HTGL
++ switch (state)
++ {
++ case FLASH_CLEAR_START:
++ case FLASH_UPDATE_START:
++ out_b(AVR_PORT, 0x61);
++ out_b(AVR_PORT, 0x61);
++ out_b(AVR_PORT, 0x38);
++ out_b(AVR_PORT, 0x30);
++ out_b(AVR_PORT, 0x34);
++ out_b(AVR_PORT, 0x31);
++ mdelay(10);
++ out_b(AVR_PORT, 0x61);
++ out_b(AVR_PORT, 0x61);
++ out_b(AVR_PORT, 0x38);
++ out_b(AVR_PORT, 0x31);
++ out_b(AVR_PORT, 0x34);
++ out_b(AVR_PORT, 0x31);
++ mdelay(10);
++ out_b(AVR_PORT, 0x71);
++ out_b(AVR_PORT, 0x71);
++// out_b(AVR_PORT, 0x71);
++// out_b(AVR_PORT, 0x71);
++ mdelay(10);
++ out_b(AVR_PORT, 0x73);
++ out_b(AVR_PORT, 0x73);
++// out_b(AVR_PORT, 0x73);
++// out_b(AVR_PORT, 0x73);
++ mdelay(10);
++ break;
++ case FLASH_CLEAR_END:
++ case FLASH_UPDATE_END:
++ out_b(AVR_PORT, 0x70);
++ out_b(AVR_PORT, 0x70);
++// out_b(AVR_PORT, 0x70);
++// out_b(AVR_PORT, 0x70);
++ mdelay(10);
++ out_b(AVR_PORT, 0x72);
++ out_b(AVR_PORT, 0x72);
++// out_b(AVR_PORT, 0x72);
++// out_b(AVR_PORT, 0x72);
++ mdelay(10);
++ break;
++ case RAID_RESYNC_START:
++ break;
++ case RAID_RESYNC_END:
++ break;
++ default:
++ out_b(AVR_PORT, state);
++ out_b(AVR_PORT, state);
++ out_b(AVR_PORT, state);
++ out_b(AVR_PORT, state);
++ break;
++ }
++#else
++ out_b(AVR_PORT, state);
++ out_b(AVR_PORT, state);
++ out_b(AVR_PORT, state);
++ out_b(AVR_PORT, state);
++#endif
++
++}
++#endif
++
++// 2005.5.10 BUFFALO add
++//--------------------------------------------------------------
++static inline void miconCntl_SendUart(unsigned char dat)
++{
++ out_b((char *)AVR_PORT, dat);
++ udelay(1000);
++}
++
++//--------------------------------------------------------------
++void miconCntl_SendCmd(unsigned char dat)
++{
++ int i;
++
++ for (i=0; i<4; i++){
++ miconCntl_SendUart(dat);
++ }
++}
++
++//--------------------------------------------------------------
++void miconCntl_FanLow(void)
++{
++ debug("%s\n",__FUNCTION__);
++#ifdef CONFIG_HTGL
++ miconCntl_SendCmd(0x5C);
++#endif
++}
++//--------------------------------------------------------------
++void miconCntl_FanHigh(void)
++{
++ debug("%s\n",__FUNCTION__);
++#ifdef CONFIG_HTGL
++ miconCntl_SendCmd(0x5D);
++#endif
++}
++
++//--------------------------------------------------------------
++//1000Mbps
++void miconCntl_Eth1000M(int up)
++{
++ debug("%s (%d)\n",__FUNCTION__,up);
++#ifdef CONFIG_HTGL
++ if (up){
++ miconCntl_SendCmd(0x93);
++ }else{
++ miconCntl_SendCmd(0x92);
++ }
++#else
++ if (up){
++ miconCntl_SendCmd(0x5D);
++ }else{
++ miconCntl_SendCmd(0x5C);
++ }
++#endif
++}
++//--------------------------------------------------------------
++//100Mbps
++void miconCntl_Eth100M(int up)
++{
++ debug("%s (%d)\n",__FUNCTION__,up);
++#ifdef CONFIG_HTGL
++ if (up){
++ miconCntl_SendCmd(0x91);
++ }else{
++ miconCntl_SendCmd(0x90);
++ }
++#else
++ if (up){
++ miconCntl_SendCmd(0x5C);
++ }
++#endif
++}
++//--------------------------------------------------------------
++//10Mbps
++void miconCntl_Eth10M(int up)
++{
++ debug("%s (%d)\n",__FUNCTION__,up);
++#ifdef CONFIG_HTGL
++ if (up){
++ miconCntl_SendCmd(0x8F);
++ }else{
++ miconCntl_SendCmd(0x8E);
++ }
++#else
++ if (up){
++ miconCntl_SendCmd(0x5C);
++ }
++#endif
++}
++//--------------------------------------------------------------
++//��������
++void miconCntl_5f(void)
++{
++ debug("%s\n",__FUNCTION__);
++ miconCntl_SendCmd(0x5F);
++ mdelay(100);
++}
++
++//--------------------------------------------------------------
++// "reboot start" signal
++void miconCntl_Reboot(void)
++{
++ debug("%s\n",__FUNCTION__);
++ miconCntl_SendCmd(0x43);
++}
++#if 0
++//--------------------------------------------------------------
++// Raid recovery start
++void miconCntl_RadiRecovery(void)
++{
++ debug("%s\n",__FUNCTION__);
++#ifdef CONFIG_HTGL
++ miconCntl_SendUart(0x61); // a
++ miconCntl_SendUart(0x61); // a
++ miconCntl_SendUart(0x38); // 8
++ miconCntl_SendUart(0x30); // 0
++ miconCntl_SendUart(0x34); // 4
++ miconCntl_SendUart(0x31); // 1
++ miconCntl_SendCmd(0x71); // q
++#endif
++}
++//--------------------------------------------------------------
++// Raid recovery finish
++void miconCntl_RadiRecoveryFin(void)
++{
++ debug("%s\n",__FUNCTION__);
++#ifdef CONFIG_HTGL
++ miconCntl_SendCmd(0x70);
++#endif
++}
++#endif
++
++// ---------------------------------------------------------------
++// Disable watchdog timer
++void miconCntl_DisWDT(void)
++{
++ debug("%s\n",__FUNCTION__);
++ miconCntl_SendCmd(0x41); // A
++ miconCntl_SendCmd(0x46); // F
++ miconCntl_SendCmd(0x4A); // J
++ miconCntl_SendCmd(0x3E); // >
++ miconCntl_SendCmd(0x56); // V
++ miconCntl_SendCmd(0x3E); // >
++ miconCntl_SendCmd(0x5A); // Z
++ miconCntl_SendCmd(0x56); // V
++ miconCntl_SendCmd(0x4B); // K
++}
++// ---------------------------------------------------------------
++// U-Boot calls this function
++int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
++{
++ disable_interrupts();
++ miconCntl_Reboot();
++ while (1)
++ miconCntl_SendUart(0x47); /* Wait for reboot */
++
++}
++
++/* vim: set ts=4: */
+diff -urN u-boot-86xx/board/linkstation/ide.c u-boot-86xx-kuro_clean/board/linkstation/ide.c
+--- u-boot-86xx/board/linkstation/ide.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/ide.c 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,101 @@
++/*
++ * (C) Copyright 2000
++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ *
++ */
++/* ide.c - ide support functions */
++
++
++#include <common.h>
++
++#ifdef CFG_CMD_IDE
++#include <ata.h>
++#include <ide.h>
++#include <pci.h>
++
++#define IT8212_PCI_CpuCONTROL 0x5e
++#define IT8212_PCI_PciModeCONTROL 0x50
++#define IT8212_PCI_IdeIoCONFIG 0x40
++#define IT8212_PCI_IdeBusSkewCONTROL 0x4c
++#define IT8212_PCI_IdeDrivingCURRENT 0x42
++
++extern ulong ide_bus_offset[CFG_IDE_MAXBUS];
++extern struct pci_controller hose;
++
++int ide_preinit (void)
++{
++ int status;
++ pci_dev_t devbusfn;
++ int l;
++
++ status = 1;
++ for (l = 0; l < CFG_IDE_MAXBUS; l++) {
++ ide_bus_offset[l] = -ATA_STATUS;
++ }
++ devbusfn = pci_find_device (PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680, 0);
++ if (devbusfn == -1)
++ devbusfn = pci_find_device (PCI_VENDOR_ID_ITE,PCI_DEVICE_ID_ITE_8212,0);
++ if (devbusfn != -1) {
++ status = 0;
++
++ pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0,
++ (u32 *) &ide_bus_offset[0]);
++ ide_bus_offset[0] &= 0xfffffffe;
++ ide_bus_offset[0] = pci_hose_bus_to_phys(&hose,
++ ide_bus_offset[0] & 0xfffffffe,
++ PCI_REGION_IO);
++ pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_2,
++ (u32 *) &ide_bus_offset[1]);
++ ide_bus_offset[1] &= 0xfffffffe;
++ ide_bus_offset[1] = pci_hose_bus_to_phys(&hose,
++ ide_bus_offset[1] & 0xfffffffe,
++ PCI_REGION_IO);
++ }
++
++ if (pci_find_device (PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8212, 0) != -1) {
++ pci_write_config_byte(devbusfn, IT8212_PCI_CpuCONTROL, 0x01);
++ pci_write_config_byte(devbusfn, IT8212_PCI_PciModeCONTROL, 0x00);
++ pci_write_config_word(devbusfn, PCI_COMMAND, 0x0047);
++#ifdef CONFIG_IT8212_SECONDARY_ENABLE
++ pci_write_config_word(devbusfn, IT8212_PCI_IdeIoCONFIG, 0xA0F3);
++#else
++ pci_write_config_word(devbusfn, IT8212_PCI_IdeIoCONFIG, 0x8031);
++#endif
++ pci_write_config_dword(devbusfn, IT8212_PCI_IdeBusSkewCONTROL, 0x02040204);
++// __LS_COMMENT__ BUFFALO changed 2004.11.10 changed for EMI
++ pci_write_config_byte(devbusfn, IT8212_PCI_IdeDrivingCURRENT, 0x36); // 10mA
++// pci_write_config_byte(dev, IT8212_PCI_IdeDrivingCURRENT, 0x09); // 4mA
++// pci_write_config_byte(dev, IT8212_PCI_IdeDrivingCURRENT, 0x12); // 6mA
++// pci_write_config_byte(dev, IT8212_PCI_IdeDrivingCURRENT, 0x24); // 6mA,2mA
++// pci_write_config_byte(dev, IT8212_PCI_IdeDrivingCURRENT, 0x2D); // 8mA,4mA
++ pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x00);
++ }
++
++ return (status);
++}
++
++void ide_set_reset (int flag) {
++ return;
++}
++
++#endif /* of CONFIG_CMDS_IDE */
++
++/* vim: set ts=4: */
+diff -urN u-boot-86xx/board/linkstation/linkstation.c u-boot-86xx-kuro_clean/board/linkstation/linkstation.c
+--- u-boot-86xx/board/linkstation/linkstation.c 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/linkstation.c 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,127 @@
++/*
++ * linkstation.c
++ *
++ * Misc LinkStation specific functions
++ *
++ * Copyright (C) 2006 Mihai Georgin <u-boot@linuxnotincluded.org.uk>
++ *
++ * 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 <version.h>
++#include <common.h>
++#include <mpc824x.h>
++#include <asm/io.h>
++#include <ns16550.h>
++
++#ifdef CONFIG_PCI
++#include <pci.h>
++#endif
++
++extern void init_AVR_DUART(void);
++extern void hw_watchdog_reset(void);
++
++int checkboard (void)
++{
++ DECLARE_GLOBAL_DATA_PTR;
++ ulong busfreq = get_bus_freq (0);
++ char buf[32];
++ char *p;
++ bd_t *bd = gd->bd;
++
++ init_AVR_DUART();
++ hw_watchdog_reset();
++
++ if ((p = getenv ("console_nr")) != NULL) {
++ unsigned long con_nr = simple_strtoul (p, NULL, 10) & 3;
++
++ bd->bi_baudrate &= ~3;
++ bd->bi_baudrate |= con_nr & 3;
++ }
++ return 0;
++}
++
++long int initdram (int board_type)
++{
++ return (get_ram_size(CFG_SDRAM_BASE, CFG_MAX_RAM_SIZE));
++}
++
++/*
++ * Initialize PCI Devices
++ */
++#ifdef CONFIG_PCI
++
++#ifndef CONFIG_PCI_PNP
++
++static struct pci_config_table pci_linkstation_config_table[] = {
++ /* vendor, device, class */
++ /* bus, dev, func */
++ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
++ PCI_ANY_ID, 0x0b, 0, /* AN983B or RTL8110S */
++ /* ethernet controller */
++ pci_cfgfunc_config_device, { PCI_ETH_IOADDR,
++ PCI_ETH_MEMADDR,
++ PCI_COMMAND_IO |
++ PCI_COMMAND_MEMORY |
++ PCI_COMMAND_MASTER }},
++ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
++ PCI_ANY_ID, 0x0c, 0, /* SII680 or IT8211AF */
++ /* ide controller */
++ pci_cfgfunc_config_device, { PCI_IDE_IOADDR,
++ PCI_IDE_MEMADDR,
++ PCI_COMMAND_IO |
++ PCI_COMMAND_MEMORY |
++ PCI_COMMAND_MASTER }},
++ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
++ PCI_ANY_ID, 0x0e, 0, /* D720101 USB controller, 1st USB 1.1 */
++ pci_cfgfunc_config_device, { PCI_USB0_IOADDR,
++ PCI_USB0_MEMADDR,
++ PCI_COMMAND_MEMORY |
++ PCI_COMMAND_MASTER }},
++ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
++ PCI_ANY_ID, 0x0e, 1, /* D720101 USB controller, 2nd USB 1.1 */
++ pci_cfgfunc_config_device, { PCI_USB1_IOADDR,
++ PCI_USB1_MEMADDR,
++ PCI_COMMAND_MEMORY |
++ PCI_COMMAND_MASTER }},
++ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
++ PCI_ANY_ID, 0x0e, 2, /* D720101 USB controller, USB 2.0 */
++ pci_cfgfunc_config_device, { PCI_USB2_IOADDR,
++ PCI_USB2_MEMADDR,
++ PCI_COMMAND_MEMORY |
++ PCI_COMMAND_MASTER }},
++ { }
++};
++#endif
++
++struct pci_controller hose = {
++#ifndef CONFIG_PCI_PNP
++ config_table:pci_linkstation_config_table,
++#endif
++};
++
++void pci_init_board (void)
++{
++ pci_mpc824x_init (&hose);
++
++ /* Reset USB 1.1 */
++ out_le32(PCI_USB0_MEMADDR+8, 1);
++ out_le32(PCI_USB1_MEMADDR+8, 1);
++
++}
++#endif /* CONFIG_PCI */
++
++/* vim: set ts=4: */
+diff -urN u-boot-86xx/board/linkstation/nc.sh u-boot-86xx-kuro_clean/board/linkstation/nc.sh
+--- u-boot-86xx/board/linkstation/nc.sh 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/nc.sh 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,10 @@
++#! /bin/bash
++
++[ $# = 1 ] || { echo "Usage: $0 target_ip" >&2 ; exit 1 ; }
++TARGET_IP=$1
++
++stty -icanon -echo intr ^T
++#nc -u -l -p 6666 < /dev/null &
++nc -u -p 6666 -v -v ${TARGET_IP} 6666
++stty icanon echo intr ^C
++
+diff -urN u-boot-86xx/board/linkstation/u-boot.lds u-boot-86xx-kuro_clean/board/linkstation/u-boot.lds
+--- u-boot-86xx/board/linkstation/u-boot.lds 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/board/linkstation/u-boot.lds 2006-11-06 22:05:38.000000000 +0100
+@@ -0,0 +1,138 @@
++/*
++ * (C) Copyright 2001
++ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
++ *
++ * See file CREDITS for list of people who contributed to this
++ * project.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++ * MA 02111-1307 USA
++ */
++
++OUTPUT_ARCH(powerpc)
++/*
++SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); SEARCH_DIR(/usr/lib/gcc-lib/ppc-linux/3.3.3);
++*/
++/* Do we need any of these for elf?
++ __DYNAMIC = 0; */
++SECTIONS
++{
++ /* Read-only sections, merged into text segment: */
++ . = + SIZEOF_HEADERS;
++ .interp : { *(.interp) }
++ .hash : { *(.hash) }
++ .dynsym : { *(.dynsym) }
++ .dynstr : { *(.dynstr) }
++ .rel.text : { *(.rel.text) }
++ .rela.text : { *(.rela.text) }
++ .rel.data : { *(.rel.data) }
++ .rela.data : { *(.rela.data) }
++ .rel.rodata : { *(.rel.rodata) }
++ .rela.rodata : { *(.rela.rodata) }
++ .rel.got : { *(.rel.got) }
++ .rela.got : { *(.rela.got) }
++ .rel.ctors : { *(.rel.ctors) }
++ .rela.ctors : { *(.rela.ctors) }
++ .rel.dtors : { *(.rel.dtors) }
++ .rela.dtors : { *(.rela.dtors) }
++ .rel.bss : { *(.rel.bss) }
++ .rela.bss : { *(.rela.bss) }
++ .rel.plt : { *(.rel.plt) }
++ .rela.plt : { *(.rela.plt) }
++ .init : { *(.init) }
++ .plt : { *(.plt) }
++ .text :
++ {
++ cpu/mpc824x/start.o (.text)
++ lib_ppc/board.o (.text)
++ lib_ppc/ppcstring.o (.text)
++ lib_generic/vsprintf.o (.text)
++ lib_generic/crc32.o (.text)
++ lib_generic/zlib.o (.text)
++
++ . = DEFINED(env_offset) ? env_offset : .;
++ common/environment.o (.text)
++
++ *(.text)
++
++ *(.fixup)
++ *(.got1)
++ . = ALIGN(16);
++ *(.rodata)
++ *(.rodata1)
++ *(.rodata.str1.4)
++ *(.eh_frame)
++ }
++ .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 = .);
++
++ . = .;
++ __u_boot_cmd_start = .;
++ .u_boot_cmd : { *(.u_boot_cmd) }
++ __u_boot_cmd_end = .;
++
++
++ . = .;
++ __start___ex_table = .;
++ __ex_table : { *(__ex_table) }
++ __stop___ex_table = .;
++
++ . = ALIGN(4096);
++ __init_begin = .;
++ .text.init : { *(.text.init) }
++ .data.init : { *(.data.init) }
++ . = ALIGN(4096);
++ __init_end = .;
++
++ __bss_start = .;
++ .bss :
++ {
++ *(.sbss) *(.scommon)
++ *(.dynbss)
++ *(.bss)
++ *(COMMON)
++ }
++
++ _end = . ;
++ PROVIDE (end = .);
++}
+diff -urN u-boot-86xx/common/cmd_bootm.c u-boot-86xx-kuro_clean/common/cmd_bootm.c
+--- u-boot-86xx/common/cmd_bootm.c 2006-10-13 00:27:16.000000000 +0200
++++ u-boot-86xx-kuro_clean/common/cmd_bootm.c 2006-11-06 22:05:38.000000000 +0100
+@@ -193,6 +193,12 @@
+ verify = 0;
+ } else
+ #endif /* __I386__ */
++#ifdef CONFIG_LINKSTATION
++ extern boot_os_Fcn do_boot_lskernel;
++ do_boot_lskernel(cmdtp, flag, argc, argv,
++ addr, NULL, verify);
++ return 1; /* Only returns on error */
++#endif
+ {
+ puts ("Bad Magic Number\n");
+ SHOW_BOOT_PROGRESS (-1);
+diff -urN u-boot-86xx/common/cmd_ext2.c u-boot-86xx-kuro_clean/common/cmd_ext2.c
+--- u-boot-86xx/common/cmd_ext2.c 2006-10-13 00:27:16.000000000 +0200
++++ u-boot-86xx-kuro_clean/common/cmd_ext2.c 2006-11-06 22:05:38.000000000 +0100
+@@ -283,7 +283,8 @@
+ sprintf(buf, "%lX", filelen);
+ setenv("filesize", buf);
+
+- return(filelen);
++// return(filelen);
++ return(0);
+ }
+
+ U_BOOT_CMD(
+diff -urN u-boot-86xx/common/console.c u-boot-86xx-kuro_clean/common/console.c
+--- u-boot-86xx/common/console.c 2006-10-13 00:27:16.000000000 +0200
++++ u-boot-86xx-kuro_clean/common/console.c 2006-11-06 22:05:38.000000000 +0100
+@@ -48,7 +48,7 @@
+
+ #endif /* CFG_CONSOLE_IS_IN_ENV */
+
+-static int console_setfile (int file, device_t * dev)
++int console_setfile (int file, device_t * dev)
+ {
+ int error = 0;
+
+@@ -444,22 +444,27 @@
+ gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */
+
+ #ifndef CFG_CONSOLE_INFO_QUIET
++ if (strcmp(stdio_devices[stdout]->name, "serial")) {
++ extern char version_string[];
++ printf ("\n%s\n", version_string);
++ }
++
+ /* Print information */
+- puts ("In: ");
++ puts ("stdin : ");
+ if (stdio_devices[stdin] == NULL) {
+ puts ("No input devices available!\n");
+ } else {
+ printf ("%s\n", stdio_devices[stdin]->name);
+ }
+
+- puts ("Out: ");
++ puts ("stdout: ");
+ if (stdio_devices[stdout] == NULL) {
+ puts ("No output devices available!\n");
+ } else {
+ printf ("%s\n", stdio_devices[stdout]->name);
+ }
+
+- puts ("Err: ");
++ puts ("stderr: ");
+ if (stdio_devices[stderr] == NULL) {
+ puts ("No error devices available!\n");
+ } else {
+diff -urN u-boot-86xx/common/main.c u-boot-86xx-kuro_clean/common/main.c
+--- u-boot-86xx/common/main.c 2006-10-13 00:27:16.000000000 +0200
++++ u-boot-86xx-kuro_clean/common/main.c 2006-11-06 22:05:38.000000000 +0100
+@@ -84,6 +84,11 @@
+ extern void mdm_init(void); /* defined in board.c */
+ #endif
+
++#ifdef CONFIG_LINKSTATION
++extern int avr_input(void);
++extern void avr_StopBoot(void);
++#endif
++
+ /***************************************************************************
+ * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
+ * returns: 0 - no key string, allow autoboot
+@@ -162,7 +167,14 @@
+ /* In order to keep up with incoming data, check timeout only
+ * when catch up.
+ */
++ uint64_t onesec = endtick(1);
++ int bootremain = bootdelay;
+ while (!abort && get_ticks() <= etime) {
++ if (get_ticks() >= onesec) {
++ onesec = endtick(1);
++ putc('\r');
++ printf (CONFIG_AUTOBOOT_PROMPT, --bootremain);
++ }
+ for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
+ if (delaykey[i].len > 0 &&
+ presskey_len >= delaykey[i].len &&
+@@ -183,6 +195,20 @@
+ }
+ }
+
++#ifdef CONFIG_LINKSTATION
++ int avr_action = avr_input();
++ if (avr_action == -3)
++ /* Abort boot */
++ abort = 1;
++ else if (avr_action == -2) {
++ /* Restart boot */
++ putc('\r');
++ printf (CONFIG_AUTOBOOT_PROMPT, bootdelay);
++ etime = endtick(bootdelay);
++ onesec = endtick(1);
++ bootremain = bootdelay;
++ }
++#endif
+ if (tstc()) {
+ if (presskey_len < presskey_max) {
+ presskey [presskey_len ++] = getc();
+@@ -195,6 +221,7 @@
+ }
+ }
+ }
++ putc('\n');
+ # if DEBUG_BOOTKEYS
+ if (!abort)
+ puts ("key timeout\n");
+@@ -411,6 +438,10 @@
+ int prev = disable_ctrlc(1); /* disable Control C checking */
+ # endif
+
++#ifdef CONFIG_LINKSTATION
++ s = getenv("bootcmd"); /* bootcmd can change (see avr.c) */
++#endif
++
+ # ifndef CFG_HUSH_PARSER
+ run_command (s, 0);
+ # else
+@@ -445,6 +476,10 @@
+ }
+ #endif
+
++#ifdef CONFIG_LINKSTATION
++ avr_StopBoot();
++#endif
++
+ /*
+ * Main Loop for Monitor Command Processing
+ */
+@@ -469,6 +504,10 @@
+ strcpy (lastcommand, console_buffer);
+ else if (len == 0)
+ flag |= CMD_FLAG_REPEAT;
++#ifdef CONFIG_LINKSTATION
++ else if (len == -2)
++ return;
++#endif
+ #ifdef CONFIG_BOOT_RETRY_TIME
+ else if (len == -2) {
+ /* -2 means timed out, retry autoboot
+@@ -978,6 +1017,15 @@
+ show_activity(0);
+ }
+ #endif
++#ifdef CONFIG_LINKSTATION
++ while (!tstc()) {
++ int avr_ret = avr_input();
++ if (avr_ret == -2)
++ return (-2);
++ else if (avr_ret > 0)
++ return avr_ret;
++ }
++#endif
+ c = getc();
+
+ /*
+diff -urN u-boot-86xx/cpu/mpc824x/cpu.c u-boot-86xx-kuro_clean/cpu/mpc824x/cpu.c
+--- u-boot-86xx/cpu/mpc824x/cpu.c 2006-10-13 00:27:17.000000000 +0200
++++ u-boot-86xx-kuro_clean/cpu/mpc824x/cpu.c 2006-11-06 22:05:38.000000000 +0100
+@@ -92,6 +92,7 @@
+
+ /*------------------------------------------------------------------- */
+
++#ifndef CONFIG_LINKSTATION
+ int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+ {
+ ulong msr, addr;
+@@ -125,6 +126,7 @@
+ return 1;
+
+ }
++#endif
+
+ /* ------------------------------------------------------------------------- */
+
+diff -urN u-boot-86xx/cpu/mpc824x/start.S u-boot-86xx-kuro_clean/cpu/mpc824x/start.S
+--- u-boot-86xx/cpu/mpc824x/start.S 2006-10-13 00:27:17.000000000 +0200
++++ u-boot-86xx-kuro_clean/cpu/mpc824x/start.S 2006-11-06 22:05:38.000000000 +0100
+@@ -130,7 +130,7 @@
+
+
+ in_flash:
+-#if defined(CONFIG_BMW)
++#if defined(CONFIG_BMW) || defined(CONFIG_LINKSTATION)
+ bl early_init_f /* Must be ASM: no stack yet! */
+ #endif
+ /*
+@@ -155,6 +155,7 @@
+ mtspr HID0, r2
+ sync
+
++#if !defined(CONFIG_LINKSTATION)
+ /* Allocate Initial RAM in data cache.
+ */
+ lis r3, CFG_INIT_RAM_ADDR@h
+@@ -175,6 +176,7 @@
+ ori r3, r3, 0x0080
+ sync
+ mtspr 1011, r3
++#endif /* !CONFIG_LINKSTATION */
+ #endif /* !CONFIG_BMW */
+ /*
+ * Thisk the stack pointer *somewhere* sensible. Doesnt
+@@ -195,7 +197,9 @@
+ GET_GOT /* initialize GOT access */
+
+ /* r3: IMMR */
++#if !defined(CONFIG_LINKSTATION)
+ bl cpu_init_f /* run low-level CPU init code (from Flash) */
++#endif
+
+ mr r3, r21
+ /* r3: BOOTFLAG */
+@@ -475,7 +479,7 @@
+ mr r10, r5 /* Save copy of Destination Address */
+
+ mr r3, r5 /* Destination Address */
+-#ifdef CFG_RAMBOOT
++#if defined(CFG_RAMBOOT) && !defined(CONFIG_LINKSTATION)
+ lis r4, CFG_SDRAM_BASE@h /* Source Address */
+ ori r4, r4, CFG_SDRAM_BASE@l
+ #else
+@@ -689,6 +693,14 @@
+ cmplw 0, r7, r8
+ blt 4b
+
++ mfmsr r7 /* Exception prefix 0x000 */
++ li r8,0
++ ori r8,r8,MSR_IP
++ andc r7,r7,r8
++ SYNC
++ mtmsr r7
++ SYNC
++
+ mtlr r4 /* restore link register */
+ blr
+
+diff -urN u-boot-86xx/drivers/dc2114x.c u-boot-86xx-kuro_clean/drivers/dc2114x.c
+--- u-boot-86xx/drivers/dc2114x.c 2006-10-13 00:27:17.000000000 +0200
++++ u-boot-86xx-kuro_clean/drivers/dc2114x.c 2006-11-06 22:05:38.000000000 +0100
+@@ -27,14 +27,20 @@
+ #include <net.h>
+ #include <pci.h>
+
++#if 0
++#define DEBUG_TRACE
++#define DEBUG_TULIP
++#endif
++
+ #undef DEBUG_SROM
+ #undef DEBUG_SROM2
+
+ #undef UPDATE_SROM
+
+-/* PCI Registers.
++/*
++ * PCI Registers.
+ */
+-#define PCI_CFDA_PSM 0x43
++#define PCI_CFDA_PSM 0x43
+
+ #define CFRV_RN 0x000000f0 /* Revision Number */
+
+@@ -43,10 +49,12 @@
+
+ #define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */
+
+-/* Ethernet chip registers.
++/*
++ * Ethernet chip registers.
+ */
+ #define DE4X5_BMR 0x000 /* Bus Mode Register */
+ #define DE4X5_TPD 0x008 /* Transmit Poll Demand Reg */
++#define DE4X5_RPD 0x010 /* Receive Poll Demand Reg */
+ #define DE4X5_RRBA 0x018 /* RX Ring Base Address Reg */
+ #define DE4X5_TRBA 0x020 /* TX Ring Base Address Reg */
+ #define DE4X5_STS 0x028 /* Status Register */
+@@ -54,7 +62,8 @@
+ #define DE4X5_SICR 0x068 /* SIA Connectivity Register */
+ #define DE4X5_APROM 0x048 /* Ethernet Address PROM */
+
+-/* Register bits.
++/*
++ * Register bits.
+ */
+ #define BMR_SWR 0x00000001 /* Software Reset */
+ #define STS_TS 0x00700000 /* Transmit Process State */
+@@ -64,8 +73,10 @@
+ #define OMR_PS 0x00040000 /* Port Select */
+ #define OMR_SDP 0x02000000 /* SD Polarity - MUST BE ASSERTED */
+ #define OMR_PM 0x00000080 /* Pass All Multicast */
++#define OMR_PMS 0x00000040 /* Promiscuous */
+
+-/* Descriptor bits.
++/*
++ * Descriptor bits.
+ */
+ #define R_OWN 0x80000000 /* Own Bit */
+ #define RD_RER 0x02000000 /* Receive End Of Ring */
+@@ -85,10 +96,10 @@
+
+ #define SROM_HWADD 0x0014 /* Hardware Address offset in SROM */
+ #define SROM_RD 0x00004000 /* Read from Boot ROM */
+-#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
++#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
+ #define EE_WRITE_0 0x4801
+ #define EE_WRITE_1 0x4805
+-#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
++#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
+ #define SROM_SR 0x00000800 /* Select Serial ROM when set */
+
+ #define DT_IN 0x00000004 /* Serial Data In */
+@@ -97,6 +108,36 @@
+
+ #define POLL_DEMAND 1
+
++#ifndef PCI_VENDOR_ID_ADMTEK
++# define PCI_VENDOR_ID_ADMTEK 0x1317
++#endif
++#ifndef PCI_DEVICE_ID_ADMTEK_AN983B
++# define PCI_DEVICE_ID_ADMTEK_AN983B 0x985
++#endif
++
++/* The chip types have been taken from linux-2.4.31
++ * drivers/net/tulip/tulip.h
++ * Only COMET is used for now
++ */
++enum chips {
++ DC21040 = 0,
++ DC21041 = 1,
++ DC21140 = 2,
++ DC21142 = 3, DC21143 = 3,
++ LC82C168,
++ MX98713,
++ MX98715,
++ MX98725,
++ AX88140,
++ PNIC2,
++ COMET,
++ COMPEX9881,
++ I21145,
++ DM910X,
++ CONEXANT,
++};
++static int chip_idx = DC21143;
++
+ #ifdef CONFIG_TULIP_FIX_DAVICOM
+ #define RESET_DM9102(dev) {\
+ unsigned long i;\
+@@ -108,58 +149,63 @@
+ #else
+ #define RESET_DE4X5(dev) {\
+ int i;\
+- i=INL(dev, DE4X5_BMR);\
+- udelay(1000);\
++ i=0x01A04000;\
+ OUTL(dev, i | BMR_SWR, DE4X5_BMR);\
+ udelay(1000);\
+ OUTL(dev, i, DE4X5_BMR);\
+ udelay(1000);\
+- for (i=0;i<5;i++) {INL(dev, DE4X5_BMR); udelay(10000);}\
+- udelay(1000);\
+ }
+ #endif
+
+ #define START_DE4X5(dev) {\
+- s32 omr; \
++ u32 omr; \
+ omr = INL(dev, DE4X5_OMR);\
+ omr |= OMR_ST | OMR_SR;\
+ OUTL(dev, omr, DE4X5_OMR); /* Enable the TX and/or RX */\
+ }
+
+ #define STOP_DE4X5(dev) {\
+- s32 omr; \
++ u32 omr; \
+ omr = INL(dev, DE4X5_OMR);\
+ omr &= ~(OMR_ST|OMR_SR);\
+ OUTL(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ \
+ }
+
+-#define NUM_RX_DESC PKTBUFSRX
++#define NUM_RX_DESC 4
+ #ifndef CONFIG_TULIP_FIX_DAVICOM
+- #define NUM_TX_DESC 1 /* Number of TX descriptors */
++ #define NUM_TX_DESC 2 /* Number of TX descriptors */
+ #else
+ #define NUM_TX_DESC 4
+ #endif
+-#define RX_BUFF_SZ PKTSIZE_ALIGN
++#define BUFLEN 1536
+
+ #define TOUT_LOOP 1000000
+
+ #define SETUP_FRAME_LEN 192
+ #define ETH_ALEN 6
++#define ETH_ZLEN 60
+
+ struct de4x5_desc {
+- volatile s32 status;
++ volatile u32 status;
+ u32 des1;
+ u32 buf;
+ u32 next;
+ };
+
+-static struct de4x5_desc rx_ring[NUM_RX_DESC] __attribute__ ((aligned(32))); /* RX descriptor ring */
+-static struct de4x5_desc tx_ring[NUM_TX_DESC] __attribute__ ((aligned(32))); /* TX descriptor ring */
+-static int rx_new; /* RX descriptor ring pointer */
+-static int tx_new; /* TX descriptor ring pointer */
++/* Note: transmit and receive buffers must be longword aligned and
++ longword divisable */
+
+-static char rxRingSize;
+-static char txRingSize;
++/* TX descriptor ring */
++static struct de4x5_desc tx_ring[NUM_TX_DESC] __attribute__ ((aligned(4)));
++/* TX buffer */
++static unsigned char txb[BUFLEN] __attribute__ ((aligned(32)));
++
++/* RX descriptor ring */
++static struct de4x5_desc rx_ring[NUM_RX_DESC] __attribute__ ((aligned(4)));
++/* RX buffers */
++static unsigned char rxb[NUM_RX_DESC * BUFLEN] __attribute__ ((aligned(32)));
++
++static int rx_new; /* RX descriptor ring pointer */
+
+ #if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM)
+ static void sendto_srom(struct eth_device* dev, u_int command, u_long addr);
+@@ -204,6 +250,7 @@
+ static struct pci_device_id supported[] = {
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST },
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 },
++ { PCI_VENDOR_ID_ADMTEK, PCI_DEVICE_ID_ADMTEK_AN983B },
+ #ifdef CONFIG_TULIP_FIX_DAVICOM
+ { PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DAVICOM_DM9102A },
+ #endif
+@@ -214,29 +261,44 @@
+ {
+ int idx=0;
+ int card_number = 0;
+- unsigned int cfrv;
++ unsigned int cfrv;
+ unsigned char timer;
+- pci_dev_t devbusfn;
++ pci_dev_t devbusfn;
+ unsigned int iobase;
+ unsigned short status;
+ struct eth_device* dev;
++ u16 vendor;
++ u16 device;
+
++#ifdef DEBUG_TULIP
++ printf("%s\n", __FUNCTION__);
++#endif
+ while(1) {
+ devbusfn = pci_find_devices(supported, idx++);
+ if (devbusfn == -1) {
+ break;
+ }
++ pci_read_config_word(devbusfn, PCI_VENDOR_ID, &vendor);
++ pci_read_config_word(devbusfn, PCI_DEVICE_ID, &device);
+
+- /* Get the chip configuration revision register. */
+- pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv);
++ debug("dc21x4x: devbusfn: %08lX, VID: %08lX, DID: %08lX\n",
++ devbusfn, vendor, device);
++
++ if (vendor == PCI_VENDOR_ID_ADMTEK && \
++ device == PCI_DEVICE_ID_ADMTEK_AN983B) {
++ chip_idx = COMET;
++ } else {
++ /* Get the chip configuration revision register. */
++ pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv);
+
+ #ifndef CONFIG_TULIP_FIX_DAVICOM
+- if ((cfrv & CFRV_RN) < DC2114x_BRK ) {
+- printf("Error: The chip is not DC21143.\n");
+- continue;
+- }
++ if ((cfrv & CFRV_RN) < DC2114x_BRK ) {
++ printf("Error: The chip is not DC21143.\n");
++ idx++;
++ continue;
++ }
+ #endif
+-
++ }
+ pci_read_config_word(devbusfn, PCI_COMMAND, &status);
+ status |=
+ #ifdef CONFIG_TULIP_USE_IO
+@@ -286,7 +348,10 @@
+ #ifdef CONFIG_TULIP_FIX_DAVICOM
+ sprintf(dev->name, "Davicom#%d", card_number);
+ #else
+- sprintf(dev->name, "dc21x4x#%d", card_number);
++ if (chip_idx == COMET)
++ sprintf(dev->name, "COMET#%d", card_number);
++ else
++ sprintf(dev->name, "dc21x4x#%d", card_number);
+ #endif
+
+ #ifdef CONFIG_TULIP_USE_IO
+@@ -303,8 +368,6 @@
+ /* Ensure we're not sleeping. */
+ pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
+
+- udelay(10 * 1000);
+-
+ #ifndef CONFIG_TULIP_FIX_DAVICOM
+ read_hw_addr(dev, bis);
+ #endif
+@@ -321,8 +384,9 @@
+ int i;
+ int devbusfn = (int) dev->priv;
+
+- /* Ensure we're not sleeping. */
+- pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP);
++#if defined(DEBUG_TULIP) || defined(DEBUG_TRACE)
++ serial_printf("%0lu %s\n", get_timer(0), __FUNCTION__);
++#endif
+
+ #ifdef CONFIG_TULIP_FIX_DAVICOM
+ RESET_DM9102(dev);
+@@ -330,57 +394,71 @@
+ RESET_DE4X5(dev);
+ #endif
+
+- if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) {
+- printf("Error: Cannot reset ethernet controller.\n");
+- return 0;
+- }
+-
+ #ifdef CONFIG_TULIP_SELECT_MEDIA
+ dc21x4x_select_media(dev);
+ #else
+- OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);
++ if (chip_idx == COMET) {
++ /* No multicast */
++ OUTL(dev, 0, 0xAC);
++ OUTL(dev, 0, 0xB0);
++ } else {
++ OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);
++ }
+ #endif
+
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ rx_ring[i].status = cpu_to_le32(R_OWN);
+- rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
+- rx_ring[i].buf = cpu_to_le32(phys_to_bus((u32) NetRxPackets[i]));
+-#ifdef CONFIG_TULIP_FIX_DAVICOM
+- rx_ring[i].next = cpu_to_le32(phys_to_bus((u32) &rx_ring[(i+1) % NUM_RX_DESC]));
+-#else
+- rx_ring[i].next = 0;
+-#endif
++ rx_ring[i].des1 = cpu_to_le32(BUFLEN);
++ rx_ring[i].buf = cpu_to_le32(phys_to_bus((u32)&rxb[i * BUFLEN]));
++ rx_ring[i].next = cpu_to_le32(phys_to_bus((u32)&rx_ring[i+1]));
+ }
++ /* Write the end of list marker to the descriptor lists. */
++ rx_ring[NUM_RX_DESC - 1].des1 |= cpu_to_le32(RD_RER);
++ rx_ring[NUM_RX_DESC - 1].next = cpu_to_le32(phys_to_bus((u32)&rx_ring[0]));
+
+- for (i=0; i < NUM_TX_DESC; i++) {
+- tx_ring[i].status = 0;
+- tx_ring[i].des1 = 0;
+- tx_ring[i].buf = 0;
++ /* Point to the first descriptor */
++ rx_new = 0;
+
+-#ifdef CONFIG_TULIP_FIX_DAVICOM
+- tx_ring[i].next = cpu_to_le32(phys_to_bus((u32) &tx_ring[(i+1) % NUM_TX_DESC]));
+-#else
+- tx_ring[i].next = 0;
+-#endif
+- }
++ /* We only use 1 transmit buffer, but we use 2 descriptors so
++ transmit engines have somewhere to point to if they feel the need */
+
+- rxRingSize = NUM_RX_DESC;
+- txRingSize = NUM_TX_DESC;
++ tx_ring[0].status = 0;
++ tx_ring[0].des1 = 0;
++ tx_ring[0].buf = cpu_to_le32(phys_to_bus((u32)&txb[0]));
++ tx_ring[0].next = cpu_to_le32(phys_to_bus((u32)&tx_ring[1]));
++
++ /* this descriptor should never get used, since it will never be owned
++ by the machine (status will always == 0) */
++
++ tx_ring[1].status = 0;
++ tx_ring[1].des1 = 0;
++ tx_ring[1].buf = cpu_to_le32(phys_to_bus((u32)&txb[0]));
++ tx_ring[1].next = cpu_to_le32(phys_to_bus((u32)&tx_ring[0]));
+
+ /* Write the end of list marker to the descriptor lists. */
+- rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);
+- tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER);
++ tx_ring[1].des1 |= cpu_to_le32(TD_TER);
+
+ /* Tell the adapter where the TX/RX rings are located. */
+- OUTL(dev, phys_to_bus((u32) &rx_ring), DE4X5_RRBA);
+- OUTL(dev, phys_to_bus((u32) &tx_ring), DE4X5_TRBA);
++ OUTL(dev, phys_to_bus((u32) &rx_ring[0]), DE4X5_RRBA);
++ OUTL(dev, phys_to_bus((u32) &tx_ring[0]), DE4X5_TRBA);
++
++ if (chip_idx == COMET) {
++ /* Bit 18 (0x00040000) is reserved in the AN983B */
++ /* datasheet, but it is used by the tulip driver */
++ OUTL(dev, (INL(dev, (DE4X5_OMR)) & ~(OMR_PMS | OMR_PM)) | OMR_PS, DE4X5_OMR);
++ /* Enable automatic Tx underrun recovery */
++ OUTL(dev, INL(dev, 0x88) | 1, 0x88);
++// OUTL(dev, INL(dev, 0x88) | 0x19, 0x88);
++ }
+
+ START_DE4X5(dev);
+
+- tx_new = 0;
+- rx_new = 0;
++ /* Start receiving */
++ OUTL(dev, POLL_DEMAND, DE4X5_RPD);
+
+- send_setup_frame(dev, bis);
++ if (chip_idx != COMET) { /* No setup frame needed by COMET */
++ send_setup_frame(dev, bis);
++ }
+
+ return 1;
+ }
+@@ -389,90 +467,117 @@
+ {
+ int status = -1;
+ int i;
++ u32 len = length;
+
+ if (length <= 0) {
+ printf("%s: bad packet size: %d\n", dev->name, length);
+ goto Done;
+ }
+
+- for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
++ for(i = 0; tx_ring[0].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+- printf("%s: tx error buffer not ready\n", dev->name);
++ printf(".%s: Tx not ready\n", dev->name);
+ goto Done;
+ }
+ }
+
+- tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) packet));
+- tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length);
+- tx_ring[tx_new].status = cpu_to_le32(T_OWN);
++ /* Disable the TX */
++ OUTL(dev, INL(dev, DE4X5_OMR) & ~OMR_ST, DE4X5_OMR);
++
++ memcpy(txb, (char*)packet, length);
++
++ /* setup the transmit descriptor */
++ tx_ring[0].des1 = cpu_to_le32(TD_LS | TD_FS | length);
++ tx_ring[0].status = cpu_to_le32(T_OWN);
+
++ /* Point to transmit descriptor */
++ OUTL(dev, phys_to_bus((u32) &tx_ring[0]), DE4X5_TRBA);
++
++ /* Enable the TX */
++ OUTL(dev, INL(dev, DE4X5_OMR) | OMR_ST, DE4X5_OMR);
++
++ /* Immediate transmit demand */
+ OUTL(dev, POLL_DEMAND, DE4X5_TPD);
+
+- for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
++ for(i = 0; tx_ring[0].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+- printf(".%s: tx buffer not ready\n", dev->name);
++ printf(".%s: Tx Timeout\n", dev->name);
+ goto Done;
+ }
+ }
+
+- if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) {
+-#if 0 /* test-only */
++#ifdef DEBUG_TRACE
++ serial_printf("%0lu Tx L2: %d P: %04X IP: %08X\n",
++ get_timer(0), i, *((u16 *)(packet+0xC)),
++ *((u32 *)(packet+0x1E)));
++#endif
++
++ if (le32_to_cpu(tx_ring[0].status) & TD_ES) {
++#if 1 /* test-only */
+ printf("TX error status = 0x%08X\n",
+- le32_to_cpu(tx_ring[tx_new].status));
++ le32_to_cpu(tx_ring[0].status));
+ #endif
+- tx_ring[tx_new].status = 0x0;
++ tx_ring[0].status = 0x0;
+ goto Done;
+ }
+
+ status = length;
+
+ Done:
+- tx_new = (tx_new+1) % NUM_TX_DESC;
+ return status;
+ }
+
+ static int dc21x4x_recv(struct eth_device* dev)
+ {
+- s32 status;
++ u32 status;
++ int rx_prv;
+ int length = 0;
+
+- for ( ; ; ) {
+- status = (s32)le32_to_cpu(rx_ring[rx_new].status);
++#ifdef DEBUG_TULIP
++ u32 csr5 = INL(dev, DE4X5_STS);
++ if ((csr5 & STS_RS) != 0x00060000) {
++ OUTL(dev, 0x0001ffff, DE4X5_STS);
++ printf("Receive status: 0x%08X\n", csr5);
++ }
++#endif
+
+- if (status & R_OWN) {
+- break;
+- }
++ status = (u32)le32_to_cpu(rx_ring[rx_new].status);
++ if (status & R_OWN)
++ return 0;
+
+- if (status & RD_LS) {
+- /* Valid frame status.
+- */
+- if (status & RD_ES) {
+-
+- /* There was an error.
+- */
+- printf("RX error status = 0x%08X\n", status);
+- } else {
+- /* A valid frame received.
+- */
+- length = (le32_to_cpu(rx_ring[rx_new].status) >> 16);
+-
+- /* Pass the packet up to the protocol
+- * layers.
+- */
+- NetReceive(NetRxPackets[rx_new], length - 4);
+- }
++#ifdef DEBUG_TULIP
++ printf("recv status: 0x%08X\n", status);
++#endif
+
+- /* Change buffer ownership for this frame, back
+- * to the adapter.
+- */
++ if (status & RD_LS) {
++#ifdef DEBUG_TRACE
++ serial_printf("rx: %d status: %08X\n", rx_new, status);
++#endif
++ /* Valid frame status */
++ if (status & RD_ES) {
++ /* There was an error */
++ printf("RX error status = 0x%08X\n", status);
+ rx_ring[rx_new].status = cpu_to_le32(R_OWN);
+- }
++ } else {
++ /* Received valid frame */
++ length = (int)(le32_to_cpu(rx_ring[rx_new].status) >> 16);
++
++ /* Pass the packet up to the protocol layers. */
++ unsigned char rxdata[BUFLEN];
++ memcpy(rxdata, rxb + rx_new * BUFLEN, length - 4);
+
+- /* Update entry information.
+- */
+- rx_new = (rx_new + 1) % rxRingSize;
++ /* Give buffer ownership for this
++ * frame back to the adapter */
++ rx_ring[rx_new].status = cpu_to_le32(R_OWN);
++
++ /* Pass the received packet to the upper layer */
++ NetReceive(rxdata, length - 4);
++ }
+ }
+
++ /* Update current descriptor index */
++ rx_new = (rx_new + 1) % NUM_RX_DESC;
++
+ return length;
+ }
+
+@@ -480,10 +585,12 @@
+ {
+ int devbusfn = (int) dev->priv;
+
++#ifdef DEBUG_TULIP
++ printf("%s\n", __FUNCTION__);
++#endif
+ STOP_DE4X5(dev);
+ OUTL(dev, 0, DE4X5_SICR);
+
+- pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP);
+ }
+
+ static void send_setup_frame(struct eth_device* dev, bd_t *bis)
+@@ -501,30 +608,29 @@
+ }
+ }
+
+- for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
++ for(i = 0; tx_ring[0].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+ printf("%s: tx error buffer not ready\n", dev->name);
+ goto Done;
+ }
+ }
+
+- tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0]));
+- tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN);
+- tx_ring[tx_new].status = cpu_to_le32(T_OWN);
++ tx_ring[0].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0]));
++ tx_ring[0].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN);
++ tx_ring[0].status = cpu_to_le32(T_OWN);
+
+ OUTL(dev, POLL_DEMAND, DE4X5_TPD);
+
+- for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) {
++ for(i = 0; tx_ring[0].status & cpu_to_le32(T_OWN); i++) {
+ if (i >= TOUT_LOOP) {
+ printf("%s: tx buffer not ready\n", dev->name);
+ goto Done;
+ }
+ }
+
+- if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) {
+- printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status));
++ if (le32_to_cpu(tx_ring[0].status) != 0x7FFFFFFF) {
++ printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[0].status));
+ }
+- tx_new = (tx_new+1) % NUM_TX_DESC;
+
+ Done:
+ return;
+@@ -543,7 +649,7 @@
+ static int
+ getfrom_srom(struct eth_device* dev, u_long addr)
+ {
+- s32 tmp;
++ u32 tmp;
+
+ tmp = INL(dev, addr);
+ udelay(1);
+@@ -708,19 +814,27 @@
+ #ifndef CONFIG_TULIP_FIX_DAVICOM
+ static void read_hw_addr(struct eth_device *dev, bd_t *bis)
+ {
+- u_short tmp, *p = (u_short *)(&dev->enetaddr[0]);
+- int i, j = 0;
+-
+- for (i = 0; i < (ETH_ALEN >> 1); i++) {
+- tmp = read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1) + i));
+- *p = le16_to_cpu(tmp);
+- j += *p++;
+- }
+-
+- if ((j == 0) || (j == 0x2fffd)) {
+- memset (dev->enetaddr, 0, ETH_ALEN);
+- debug ("Warning: can't read HW address from SROM.\n");
+- goto Done;
++ if (chip_idx == COMET) {
++ /* COMET reads the ehernet address directly from the EEPROM */
++ *(u32 *)dev->enetaddr = cpu_to_le32(INL(dev, 0xA4));
++ *(u16 *)(dev->enetaddr+4) = cpu_to_le16(INL(dev, 0xA8));
++ *(u32 *)bis->bi_enetaddr = *(u32 *)dev->enetaddr;
++ *(u16 *)(bis->bi_enetaddr+4) = *(u16 *)(dev->enetaddr+4);
++ } else {
++ u_short tmp, *p = (u_short *)(&dev->enetaddr[0]);
++ int i, j = 0;
++
++ for (i = 0; i < (ETH_ALEN >> 1); i++) {
++ tmp=read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1)+i));
++ *p = le16_to_cpu(tmp);
++ j += *p++;
++ }
++
++ if ((j == 0) || (j == 0x2fffd)) {
++ memset (dev->enetaddr, 0, ETH_ALEN);
++ debug ("Warning: can't read HW address from SROM.\n");
++ goto Done;
++ }
+ }
+
+ return;
+@@ -769,3 +883,5 @@
+ #endif /* UPDATE_SROM */
+
+ #endif /* CFG_CMD_NET && CONFIG_NET_MULTI && CONFIG_TULIP */
++
++/* vim: set ts=4: */
+diff -urN u-boot-86xx/drivers/netconsole.c u-boot-86xx-kuro_clean/drivers/netconsole.c
+--- u-boot-86xx/drivers/netconsole.c 2006-10-13 00:27:17.000000000 +0200
++++ u-boot-86xx-kuro_clean/drivers/netconsole.c 2006-11-06 22:05:38.000000000 +0100
+@@ -27,6 +27,7 @@
+
+ #include <command.h>
+ #include <devices.h>
++#include <console.h>
+ #include <net.h>
+
+ DECLARE_GLOBAL_DATA_PTR;
+@@ -124,6 +125,26 @@
+ output_packet_len = len;
+ NetLoop (NETCONS); /* wait for arp reply and send packet */
+ output_packet_len = 0;
++#if defined(CFG_CONSOLE_IS_IN_ENV) || defined(CONFIG_SILENT_CONSOLE)
++ if (NetState == NETLOOP_FAIL) {
++ /* ARP failed, fail back to serial console */
++ device_t *idev;
++ device_t *odev;
++
++ idev = search_device(DEV_FLAGS_INPUT, "serial");
++ odev = search_device(DEV_FLAGS_OUTPUT, "serial");
++
++ console_setfile (stdin, idev);
++ console_setfile (stdout, odev);
++ console_setfile (stderr, odev);
++
++#if defined(CONFIG_LINKSTATION)
++ void next_cons_choice(int console);
++ /* Console 0 is the serial console */
++ next_cons_choice(0);
++#endif
++ }
++#endif
+ return;
+ }
+
+@@ -236,7 +257,8 @@
+
+ input_recursion = 1;
+
+- net_timeout = 1;
++// net_timeout = 1;
++ net_timeout = 50;
+ NetLoop (NETCONS); /* kind of poll */
+
+ input_recursion = 0;
+diff -urN u-boot-86xx/drivers/rtl8169.c u-boot-86xx-kuro_clean/drivers/rtl8169.c
+--- u-boot-86xx/drivers/rtl8169.c 2006-10-13 00:27:17.000000000 +0200
++++ u-boot-86xx-kuro_clean/drivers/rtl8169.c 2006-11-06 22:05:38.000000000 +0100
+@@ -48,7 +48,10 @@
+ *
+ * Indent Options: indent -kr -i8
+ ***************************************************************************/
+-
++/*
++ * 26 August 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
++ * Modified to use le32_to_cpu and cpu_to_le32 properly
++ */
+ #include <common.h>
+ #include <malloc.h>
+ #include <net.h>
+@@ -68,6 +71,7 @@
+ static u32 ioaddr;
+
+ /* Condensed operations for readability. */
++#define virt_to_bus(addr) cpu_to_le32(addr)
+ #define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
+ #define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
+
+@@ -413,23 +417,23 @@
+ ioaddr = dev->iobase;
+
+ cur_rx = tpc->cur_rx;
+- if ((tpc->RxDescArray[cur_rx].status & OWNbit) == 0) {
+- if (!(tpc->RxDescArray[cur_rx].status & RxRES)) {
++ if ((le32_to_cpu(tpc->RxDescArray[cur_rx].status) & OWNbit) == 0) {
++ if (!(le32_to_cpu(tpc->RxDescArray[cur_rx].status) & RxRES)) {
+ unsigned char rxdata[RX_BUF_LEN];
+- length = (int) (tpc->RxDescArray[cur_rx].
+- status & 0x00001FFF) - 4;
++ length = (int) (le32_to_cpu(tpc->RxDescArray[cur_rx].
++ status) & 0x00001FFF) - 4;
+
+ memcpy(rxdata, tpc->RxBufferRing[cur_rx], length);
+ NetReceive(rxdata, length);
+
+ if (cur_rx == NUM_RX_DESC - 1)
+ tpc->RxDescArray[cur_rx].status =
+- (OWNbit | EORbit) + RX_BUF_SIZE;
++ cpu_to_le32((OWNbit | EORbit) + RX_BUF_SIZE);
+ else
+ tpc->RxDescArray[cur_rx].status =
+- OWNbit + RX_BUF_SIZE;
++ cpu_to_le32(OWNbit + RX_BUF_SIZE);
+ tpc->RxDescArray[cur_rx].buf_addr =
+- virt_to_bus(tpc->RxBufferRing[cur_rx]);
++ cpu_to_le32(tpc->RxBufferRing[cur_rx]);
+ } else {
+ puts("Error Rx");
+ }
+@@ -454,6 +458,7 @@
+ u8 *ptxb;
+ int entry = tpc->cur_tx % NUM_TX_DESC;
+ u32 len = length;
++ int ret;
+
+ #ifdef DEBUG_RTL8169_TX
+ int stime = currticks();
+@@ -465,39 +470,46 @@
+
+ /* point to the current txb incase multiple tx_rings are used */
+ ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE];
++#ifdef DEBUG_RTL8169_TX
++ printf("ptxb: %08X, length: %d\n", ptxb, (int)length);
++#endif
+ memcpy(ptxb, (char *)packet, (int)length);
+
+ while (len < ETH_ZLEN)
+ ptxb[len++] = '\0';
+
+- tpc->TxDescArray[entry].buf_addr = virt_to_bus(ptxb);
++ tpc->TxDescArray[entry].buf_addr = cpu_to_le32(ptxb);
+ if (entry != (NUM_TX_DESC - 1)) {
+ tpc->TxDescArray[entry].status =
+- (OWNbit | FSbit | LSbit) | ((len > ETH_ZLEN) ?
+- len : ETH_ZLEN);
++ cpu_to_le32((OWNbit | FSbit | LSbit) |
++ ((len > ETH_ZLEN) ? len : ETH_ZLEN));
+ } else {
+ tpc->TxDescArray[entry].status =
+- (OWNbit | EORbit | FSbit | LSbit) |
+- ((len > ETH_ZLEN) ? length : ETH_ZLEN);
++ cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) |
++ ((len > ETH_ZLEN) ? len : ETH_ZLEN));
+ }
+ RTL_W8(TxPoll, 0x40); /* set polling bit */
+
+ tpc->cur_tx++;
+ to = currticks() + TX_TIMEOUT;
+- while ((tpc->TxDescArray[entry].status & OWNbit) && (currticks() < to)); /* wait */
++ while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit)
++ && (currticks() < to)); /* wait */
+
+ if (currticks() >= to) {
+ #ifdef DEBUG_RTL8169_TX
+ puts ("tx timeout/error\n");
+ printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);
+ #endif
+- return 0;
++ ret = 0;
+ } else {
+ #ifdef DEBUG_RTL8169_TX
+ puts("tx done\n");
+ #endif
+- return length;
++ ret = length;
+ }
++ /* Delay to make net console (nc) work properly */
++ udelay(20);
++ return ret;
+ }
+
+ static void rtl8169_set_rx_mode(struct eth_device *dev)
+@@ -603,13 +615,14 @@
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ if (i == (NUM_RX_DESC - 1))
+ tpc->RxDescArray[i].status =
+- (OWNbit | EORbit) + RX_BUF_SIZE;
++ cpu_to_le32((OWNbit | EORbit) + RX_BUF_SIZE);
+ else
+- tpc->RxDescArray[i].status = OWNbit + RX_BUF_SIZE;
++ tpc->RxDescArray[i].status =
++ cpu_to_le32(OWNbit + RX_BUF_SIZE);
+
+ tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE];
+ tpc->RxDescArray[i].buf_addr =
+- virt_to_bus(tpc->RxBufferRing[i]);
++ cpu_to_le32(tpc->RxBufferRing[i]);
+ }
+
+ #ifdef DEBUG_RTL8169
+@@ -635,17 +648,23 @@
+ if (tpc->TxDescArrays == 0)
+ puts("Allot Error");
+ /* Tx Desscriptor needs 256 bytes alignment; */
+- TxPhyAddr = virt_to_bus(tpc->TxDescArrays);
++ TxPhyAddr = tpc->TxDescArrays;
+ diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8));
+ TxPhyAddr += diff;
+ tpc->TxDescArray = (struct TxDesc *) (tpc->TxDescArrays + diff);
++#ifdef DEBUG_RTL8169
++ printf("tpc->TxDescArray: %08X\n", tpc->TxDescArray);
++#endif
+
+ tpc->RxDescArrays = rx_ring;
+ /* Rx Desscriptor needs 256 bytes alignment; */
+- RxPhyAddr = virt_to_bus(tpc->RxDescArrays);
++ RxPhyAddr = tpc->RxDescArrays;
+ diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8));
+ RxPhyAddr += diff;
+ tpc->RxDescArray = (struct RxDesc *) (tpc->RxDescArrays + diff);
++#ifdef DEBUG_RTL8169
++ printf("tpc->RxDescArray: %08X\n", tpc->RxDescArray);
++#endif
+
+ if (tpc->TxDescArrays == NULL || tpc->RxDescArrays == NULL) {
+ puts("Allocate RxDescArray or TxDescArray failed\n");
+@@ -733,7 +752,7 @@
+
+ /* Get MAC address. FIXME: read EEPROM */
+ for (i = 0; i < MAC_ADDR_LEN; i++)
+- dev->enetaddr[i] = RTL_R8(MAC0 + i);
++ bis->bi_enetaddr[i] = dev->enetaddr[i] = RTL_R8(MAC0 + i);
+
+ #ifdef DEBUG_RTL8169
+ printf("MAC Address");
+@@ -805,33 +824,68 @@
+ PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego);
+ udelay(100);
+
++#ifdef CONFIG_LINKSTATION
++void miconCntl_FanLow(void);
++void miconCntl_FanHigh(void);
++void miconCntl_Eth1000M(int up);
++void miconCntl_Eth100M(int up);
++void miconCntl_Eth10M(int up);
++void miconCntl_5f(void);
++
++ miconCntl_FanLow();
++#endif
++
+ /* wait for auto-negotiation process */
+ for (i = 10000; i > 0; i--) {
+ /* check if auto-negotiation complete */
+ if (mdio_read(PHY_STAT_REG) & PHY_Auto_Neco_Comp) {
+ udelay(100);
+ option = RTL_R8(PHYstatus);
++#if defined(CONFIG_LINKSTATION) && defined(CONFIG_HTGL)
+ if (option & _1000bpsF) {
+ #ifdef DEBUG_RTL8169
+ printf("%s: 1000Mbps Full-duplex operation.\n",
+ dev->name);
+ #endif
+- } else {
++ miconCntl_Eth1000M(1);
++ } else if (option & _100bps) {
++#ifdef DEBUG_RTL8169
++ printf("%s: 100Mbps %s-duplexoperation.\n",
++ dev->name,
++ (option & FullDup) ? "Full" : "Half");
++#endif
++ miconCntl_Eth100M(1);
++ } else if (option & _10bps) {
+ #ifdef DEBUG_RTL8169
+ printf
+- ("%s: %sMbps %s-duplex operation.\n",
++ ("%s: 10Mbps %s-duplex operation.\n",
+ dev->name,
+- (option & _100bps) ? "100" :
+- "10",
+- (option & FullDup) ? "Full" :
+- "Half");
++ (option & FullDup) ? "Full" : "Half");
++#endif
++ miconCntl_Eth100M(1);
++ }
++ miconCntl_5f();
++#else /* !defined(CONFIG_LINKSTATION) || !defined(CONFIG_HTGL) */
++ if (option & _1000bpsF) {
++#ifdef DEBUG_RTL8169
++ printf("%s: 1000Mbps Full-duplex operation.\n",
++ dev->name);
++#endif
++ miconCntl_FanHigh();
++ } else {
++#ifdef DEBUG_RTL8169
++ printk("%s: %sMbps %s-duplex operation.\n",
++ dev->name,
++ (option & _100bps) ? "100" : "10",
++ (option & FullDup) ? "Full" : "Half");
+ #endif
+ }
++#endif
+ break;
+ } else {
+ udelay(100);
+ }
+- } /* end for-loop to wait for auto-negotiation process */
++ } /* end for-loop to wait for auto-negotiation process */
+
+ } else {
+ udelay(100);
+@@ -886,3 +940,5 @@
+ }
+
+ #endif
++
++/* vim: set ts=4: */
+diff -urN u-boot-86xx/fs/ext2/ext2fs.c u-boot-86xx-kuro_clean/fs/ext2/ext2fs.c
+--- u-boot-86xx/fs/ext2/ext2fs.c 2006-10-13 00:27:17.000000000 +0200
++++ u-boot-86xx-kuro_clean/fs/ext2/ext2fs.c 2006-11-06 22:05:38.000000000 +0100
+@@ -35,6 +35,8 @@
+
+ /* Magic value used to identify an ext2 filesystem. */
+ #define EXT2_MAGIC 0xEF53
++/* Magic value used to identify Buffalo's idea of ext2 */
++#define LINKSTATION_MAGIC 0xEF54
+ /* Amount of indirect blocks in an inode. */
+ #define INDIRECT_BLOCKS 12
+ /* Maximum lenght of a pathname. */
+@@ -851,7 +853,8 @@
+ goto fail;
+ }
+ /* Make sure this is an ext2 filesystem. */
+- if (__le16_to_cpu (data->sblock.magic) != EXT2_MAGIC) {
++ if ((__le16_to_cpu (data->sblock.magic) != EXT2_MAGIC) &&
++ (__le16_to_cpu (data->sblock.magic) != LINKSTATION_MAGIC)) {
+ goto fail;
+ }
+ data->diropen.data = data;
+diff -urN u-boot-86xx/include/configs/linkstation.h u-boot-86xx-kuro_clean/include/configs/linkstation.h
+--- u-boot-86xx/include/configs/linkstation.h 1970-01-01 01:00:00.000000000 +0100
++++ u-boot-86xx-kuro_clean/include/configs/linkstation.h 2006-11-06 22:30:33.000000000 +0100
+@@ -0,0 +1,492 @@
++/*
++ * Copyright (C) 2006 Mihai Georgian <u-boot@linuxnotincluded.org.uk>
++ *
++ * 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 __CONFIG_H
++#define __CONFIG_H
++
++#if 0
++#define DEBUG
++#endif
++
++/*-----------------------------------------------------------------------
++ * User configurable settings:
++ * Mandatory settings:
++ * CONFIG_IPADDR_LS - the IP address of the LinkStation
++ * CONFIG_SERVERIP_LS - the address of the server for NFS/TFTP/DHCP/BOOTP
++ * Optional settins:
++ * CONFIG_NCIP_LS - the adress of the computer running net console
++ * if not configured, it will be set to
++ * CONFIG_SERVERIP_LS
++ */
++
++#define CONFIG_IPADDR_LS 192.168.11.150
++#define CONFIG_SERVERIP_LS 192.168.11.149
++
++#if !defined(CONFIG_IPADDR_LS) || !defined(CONFIG_SERVERIP_LS)
++#error Both CONFIG_IPADDR_LS and CONFIG_SERVERIP_LS must be defined
++#endif
++
++#if !defined(CONFIG_NCIP_LS)
++#define CONFIG_NCIP_LS CONFIG_SERVERIP_LS
++#endif
++
++/*----------------------------------------------------------------------
++ * DO NOT CHANGE ANYTHING BELOW, UNLESS YOU KNOW WHAT YOU ARE DOING
++ *---------------------------------------------------------------------*/
++
++#define CONFIG_MPC8245 1
++#define CONFIG_LINKSTATION 1
++
++/*---------------------------------------
++ * Supported models
++ *
++ * LinkStation HDLAN /KuroBox Standard (CONFIG_HLAN)
++ * LinkStation old model (CONFIG_LAN) - totally untested
++ * LinkStation HGLAN / KuroBox HG (CONFIG_HGLAN)
++ *
++ * Models not supported yet
++ * TeraStatin (CONFIG_HTGL)
++ */
++
++#if defined(CONFIG_HLAN) || defined(CONFIG_LAN)
++#define CONFIG_IDENT_STRING " LinkStation / KuroBox"
++#elif defined(CONFIG_HGLAN)
++#define CONFIG_IDENT_STRING " LinkStation HG / KuroBox HG"
++#elif defined(CONFIG_HTGL)
++#define CONFIG_IDENT_STRING " TeraStation"
++#else
++#error No LinkStation model defined
++#endif
++
++#define CONFIG_BOOTDELAY 10
++#define CONFIG_ZERO_BOOTDELAY_CHECK
++#undef CONFIG_BOOT_RETRY_TIME
++
++#define CONFIG_AUTOBOOT_KEYED
++#define CONFIG_AUTOBOOT_PROMPT "Boot in %02d seconds ('s' to stop)..."
++#define CONFIG_AUTOBOOT_STOP_STR "s"
++
++#define CONFIG_COMMANDS (CFG_CMD_BDI | \
++ CFG_CMD_LOADS | \
++ CFG_CMD_LOADB | \
++ CFG_CMD_FLASH | \
++ CFG_CMD_MEMORY | \
++ CFG_CMD_NET | \
++ CFG_CMD_ENV | \
++ CFG_CMD_IDE | \
++ CFG_CMD_PCI | \
++ CFG_CMD_BOOTD | \
++ CFG_CMD_CONSOLE | \
++ CFG_CMD_RUN | \
++ CFG_CMD_ECHO | \
++ CFG_CMD_DHCP | \
++ CFG_CMD_PING | \
++ CFG_CMD_NFS | \
++ CFG_CMD_EXT2 )
++#define CONFIG_BOOTP_MASK CONFIG_BOOTP_ALL
++
++/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
++#include <cmd_confdefs.h>
++
++/*
++ * Miscellaneous configurable options
++ */
++#define CFG_LONGHELP /* undef to save memory */
++#define CFG_PROMPT "=> " /* Monitor Command Prompt */
++#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
++
++#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)
++#define CFG_MAXARGS 16 /* Max number of command args */
++#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
++#define CFG_LOAD_ADDR 0x00800000 /* Default load address: 8 MB */
++
++//#define CONFIG_BOOTCOMMAND "run nfsboot"
++#define CONFIG_BOOTCOMMAND "run bootcmd1"
++#define CONFIG_BOOTARGS "root=/dev/hda1"
++#define CONFIG_NFSBOOTCOMMAND "bootp;run nfsargs;bootm"
++
++#define CFG_CONSOLE_IS_IN_ENV
++
++#define XMK_STR(x) #x
++#define MK_STR(x) XMK_STR(x)
++
++#if defined(CONFIG_HLAN) || defined(CONFIG_LAN)
++#define UBFILE "share/u-boot/u-boot-hd.flash.bin"
++#elif defined(CONFIG_HGLAN)
++#define UBFILE "share/u-boot/u-boot-hg.flash.bin"
++#elif defined(CONFIG_HTGL)
++#define UBFILE "share/u-boot/u-boot-ht.flash.bin"
++#else
++#error No LinkStation model defined
++#endif
++
++#define CONFIG_EXTRA_ENV_SETTINGS \
++ "autoload=no\0" \
++ "stdin=nc\0" \
++ "stdout=nc\0" \
++ "stderr=nc\0" \
++ "ipaddr="MK_STR(CONFIG_IPADDR_LS)"\0" \
++ "netmask=255.255.255.0\0" \
++ "serverip="MK_STR(CONFIG_SERVERIP_LS)"\0" \
++ "ncip="MK_STR(CONFIG_NCIP_LS)"\0" \
++ "netretry=no\0" \
++ "nc=setenv stdin nc;setenv stdout nc;setenv stderr nc\0" \
++ "ser=setenv stdin serial;setenv stdout serial;setenv stderr serial\0" \
++ "ldaddr=800000\0" \
++ "hdpart=0:1\0" \
++ "hdfile=boot/vmlinux.UBoot\0" \
++ "hdload=echo Loading ${hdpart}:${hdfile};ext2load ide ${hdpart} ${ldaddr} ${hdfile}\0" \
++ "boothd=setenv bootargs root=/dev/hda1;bootm ${ldaddr}\0" \
++ "hdboot=run hdload boothd\0" \
++ "flboot=setenv bootargs root=/dev/hda1;bootm ffc00000\0" \
++ "emboot=setenv bootargs root=/dev/ram0;bootm ffc00000\0" \
++ "nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath} " \
++ "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off\0" \
++ "bootretry=30\0" \
++ "bootcmd1=run hdboot;run flboot\0" \
++ "bootcmd2=run flboot\0" \
++ "bootcmd3=run emboot\0" \
++ "writeng=protect off fff70000 fff7ffff;era fff70000 fff7ffff;mw.l 800000 4e474e47 1;cp.b 800000 fff70000 4\0" \
++ "writeok=protect off fff70000 fff7ffff;era fff70000 fff7ffff;mw.l 800000 4f4b4f4b 1;cp.b 800000 fff70000 4\0" \
++ "ubpart=0:3\0" \
++ "ubfile="UBFILE"\0" \
++ "ubload=echo Loading ${ubpart}:${ubfile};ext2load ide ${ubpart} ${ldaddr} ${ubfile}\0" \
++ "ubsaddr=fff00000\0" \
++ "ubeaddr=fff2ffff\0" \
++ "ubflash=protect off ${ubsaddr} ${ubeaddr};era ${ubsaddr} ${ubeaddr};cp.b ${ldaddr} ${ubsaddr} ${filesize};cmp.b ${ldaddr} ${ubsaddr} ${filesize}\0" \
++ "upgrade=run ubload ubflash\0"
++
++/*-----------------------------------------------------------------------
++ * PCI stuff
++ */
++#define CONFIG_PCI
++#undef CONFIG_PCI_PNP
++#define CONFIG_PCI_SCAN_SHOW
++
++#ifndef CONFIG_PCI_PNP
++/* Keep the following defines in sync with the BAT mappings */
++
++#define PCI_ETH_IOADDR 0xbfff00
++#define PCI_ETH_MEMADDR 0xbffffc00
++#define PCI_IDE_IOADDR 0xbffed0
++#define PCI_IDE_MEMADDR 0xbffffb00
++#define PCI_USB0_IOADDR 0
++#define PCI_USB0_MEMADDR 0xbfffe000
++#define PCI_USB1_IOADDR 0
++#define PCI_USB1_MEMADDR 0xbfffd000
++#define PCI_USB2_IOADDR 0
++#define PCI_USB2_MEMADDR 0xbfffcf00
++
++#endif
++
++/*-----------------------------------------------------------------------
++ * Ethernet stuff
++ */
++#define CONFIG_NET_MULTI
++
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN)
++#define CONFIG_TULIP
++#define CONFIG_TULIP_USE_IO
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++#define CONFIG_RTL8169
++#endif
++
++#define CONFIG_NET_RETRY_COUNT 5
++
++#define CONFIG_NETCONSOLE
++
++/*-----------------------------------------------------------------------
++ * 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 0xFFC00000
++#define CFG_MONITOR_BASE TEXT_BASE
++
++#define CFG_RESET_ADDRESS 0xFFF00100
++#define CFG_EUMB_ADDR 0x80000000
++#define CFG_PCI_MEM_ADDR 0xB0000000
++#define CFG_MISC_REGION_ADDR 0xFE000000
++
++#define CFG_MONITOR_LEN 0x00040000 /* 256 kB */
++#define CFG_MALLOC_LEN (512 << 10) /* Reserve some kB for malloc() */
++
++#define CFG_MEMTEST_START 0x00100000 /* memtest works on */
++#define CFG_MEMTEST_END 0x00800000 /* 1M ... 8M in DRAM */
++
++/* Maximum amount of RAM */
++#if defined(CONFIG_HLAN) || defined(CONFIG_LAN)
++#define CFG_MAX_RAM_SIZE 0x04000000 /* 64MB of SDRAM */
++#elif defined(CONFIG_HGLAN) || defined(CONFIG_HTGL)
++#define CFG_MAX_RAM_SIZE 0x08000000 /* 128MB of SDRAM */
++#else
++#error Unknown LinkStation type
++#endif
++
++/*-----------------------------------------------------------------------
++ * Change TEXT_BASE in bord/linkstation/config.mk to get a RAM build
++ *
++ * RAM based builds are for testing purposes. A Linux module, uloader.o,
++ * exists to load U-Boot and pass control to it
++ *
++ * Always do "make clean" after changing the build type
++ */
++#if CFG_MONITOR_BASE < CFG_FLASH_BASE
++#define CFG_RAMBOOT
++#endif
++
++/*-----------------------------------------------------------------------
++ * Definitions for initial stack pointer and data area
++ */
++#if 1 /* RAM is available when the first C function is called */
++#define CFG_INIT_RAM_ADDR (CFG_SDRAM_BASE + CFG_MAX_RAM_SIZE - 0x1000)
++#else
++#define CFG_INIT_RAM_ADDR 0x40000000
++#endif
++#define CFG_INIT_RAM_END 0x1000
++#define CFG_GBL_DATA_SIZE 128
++#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE)
++
++/*----------------------------------------------------------------------
++ * Serial configuration
++ */
++#define CONFIG_CONS_INDEX 1
++#define CONFIG_BAUDRATE 57600
++#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
++
++#define CFG_NS16550
++#define CFG_NS16550_SERIAL
++
++#define CFG_NS16550_REG_SIZE 1
++
++#define CFG_NS16550_CLK get_bus_freq(0)
++
++#define CFG_NS16550_COM1 (CFG_EUMB_ADDR + 0x4600) /* Console port */
++#define CFG_NS16550_COM2 (CFG_EUMB_ADDR + 0x4500) /* AVR port */
++
++/*
++ * Low Level Configuration Settings
++ * (address mappings, register initial values, etc.)
++ * You should know what you are doing if you make changes here.
++ * For the detail description refer to the MPC8245 user's manual.
++ *
++ * Unless indicated otherwise, the values are
++ * taken from the orignal Linkstation boot code
++ *
++ * Most of the low level configuration setttings are normally used
++ * in cpu/mpc824x/cpu_init.c which is NOT used by this implementation.
++ * Low level initialisation is done in board/linkstation/early_init.S
++ * The values below are included for reference purpose only
++ */
++
++/* FIXME: 32.768 MHz is the crystal frequency but */
++/* the real frequency is lower by about 0.75% */
++#define CONFIG_SYS_CLK_FREQ 32768000
++#define CFG_HZ 1000
++
++/* Bit-field values for MCCR1. */
++#define CFG_ROMNAL 0
++#define CFG_ROMFAL 11
++
++#define CFG_BANK0_ROW 2 /* Only bank 0 used: 13 x n x 4 */
++#define CFG_BANK1_ROW 0
++#define CFG_BANK2_ROW 0
++#define CFG_BANK3_ROW 0
++#define CFG_BANK4_ROW 0
++#define CFG_BANK5_ROW 0
++#define CFG_BANK6_ROW 0
++#define CFG_BANK7_ROW 0
++
++/* Bit-field values for MCCR2. */
++#define CFG_TSWAIT 0
++#define CFG_REFINT 1400
++
++/* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4. */
++#define CFG_BSTOPRE 121
++
++/* Bit-field values for MCCR3. */
++#define CFG_REFREC 7
++
++/* Bit-field values for MCCR4. */
++#define CFG_PRETOACT 2
++#define CFG_ACTTOPRE 5 /* Original value was 2 */
++#define CFG_ACTORW 2
++#define CFG_SDMODE_CAS_LAT 2 /* For 100MHz bus. Use 3 for 133MHz */
++#define CFG_REGISTERD_TYPE_BUFFER 1
++#define CFG_EXTROM 1 /* Original setting but there is no EXTROM */
++#define CFG_REGDIMM 0
++#define CFG_DBUS_SIZE2 1
++#define CFG_SDMODE_WRAP 0
++
++#define CFG_PGMAX 0x32 /* All boards use this setting. Original 0x92 */
++#define CFG_SDRAM_DSCD 0x30
++
++/* Memory bank settings.
++ * Only bits 20-29 are actually used from these vales to set the
++ * start/end addresses. The upper two bits will always be 0, and the lower
++ * 20 bits will be 0x00000 for a start address, or 0xfffff for an end
++ * address. Refer to the MPC8240 book.
++ */
++
++#define CFG_BANK0_START 0x00000000
++#define CFG_BANK0_END (CFG_MAX_RAM_SIZE - 1)
++#define CFG_BANK0_ENABLE 1
++#define CFG_BANK1_START 0x3ff00000
++#define CFG_BANK1_END 0x3fffffff
++#define CFG_BANK1_ENABLE 0
++#define CFG_BANK2_START 0x3ff00000
++#define CFG_BANK2_END 0x3fffffff
++#define CFG_BANK2_ENABLE 0
++#define CFG_BANK3_START 0x3ff00000
++#define CFG_BANK3_END 0x3fffffff
++#define CFG_BANK3_ENABLE 0
++#define CFG_BANK4_START 0x3ff00000
++#define CFG_BANK4_END 0x3fffffff
++#define CFG_BANK4_ENABLE 0
++#define CFG_BANK5_START 0x3ff00000
++#define CFG_BANK5_END 0x3fffffff
++#define CFG_BANK5_ENABLE 0
++#define CFG_BANK6_START 0x3ff00000
++#define CFG_BANK6_END 0x3fffffff
++#define CFG_BANK6_ENABLE 0
++#define CFG_BANK7_START 0x3ff00000
++#define CFG_BANK7_END 0x3fffffff
++#define CFG_BANK7_ENABLE 0
++
++#define CFG_ODCR 0x95 /* 0x15 or 0x95 ? */
++
++/*----------------------------------------------------------------------
++ * Initial BAT mappings
++ */
++
++/* NOTES:
++ * 1) GUARDED and WRITETHROUGH not allowed in IBATS
++ * 2) CACHEINHIBIT and WRITETHROUGH not allowed together in same BAT
++ */
++
++/* SDRAM */
++#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE)
++#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_128M | BATU_VS | BATU_VP)
++
++#define CFG_DBAT0L CFG_IBAT0L
++#define CFG_DBAT0U CFG_IBAT0U
++
++/* EUMB: 1MB of address space */
++#define CFG_IBAT1L (CFG_EUMB_ADDR | BATL_PP_10 | BATL_CACHEINHIBIT)
++#define CFG_IBAT1U (CFG_EUMB_ADDR | BATU_BL_1M | BATU_VS | BATU_VP)
++
++#define CFG_DBAT1L (CFG_IBAT1L | BATL_GUARDEDSTORAGE)
++#define CFG_DBAT1U CFG_IBAT1U
++
++/* PCI Mem: 256MB of address space */
++#define CFG_IBAT2L (CFG_PCI_MEM_ADDR | BATL_PP_10 | BATL_CACHEINHIBIT)
++#define CFG_IBAT2U (CFG_PCI_MEM_ADDR | BATU_BL_256M | BATU_VS | BATU_VP)
++
++#define CFG_DBAT2L (CFG_IBAT2L | BATL_GUARDEDSTORAGE)
++#define CFG_DBAT2U CFG_IBAT2U
++
++/* PCI and local ROM/Flash: last 32MB of address space */
++#define CFG_IBAT3L (CFG_MISC_REGION_ADDR | BATL_PP_10 | BATL_CACHEINHIBIT)
++#define CFG_IBAT3U (CFG_MISC_REGION_ADDR | BATU_BL_32M | BATU_VS | BATU_VP)
++
++#define CFG_DBAT3L (CFG_IBAT3L | BATL_GUARDEDSTORAGE)
++#define CFG_DBAT3U CFG_IBAT3U
++
++/*
++ * 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.
++ *
++ * FIXME: This doesn't appear to be true for the newer kernels
++ * which map more that 8 MB
++ */
++#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */
++
++/*-----------------------------------------------------------------------
++ * FLASH organization
++ */
++#undef CFG_FLASH_PROTECTION
++#define CFG_MAX_FLASH_BANKS 1 /* Max number of flash banks */
++#define CFG_MAX_FLASH_SECT 72 /* Max number of sectors per flash */
++
++#define CFG_FLASH_ERASE_TOUT 12000
++#define CFG_FLASH_WRITE_TOUT 1000
++
++
++#define CFG_ENV_IS_IN_FLASH
++/*
++ * The original LinkStation flash organisation uses
++ * 448 kB (0xFFF00000 - 0xFFF6FFFF) for the boot loader
++ * We use the last sector of this area to store the environment
++ * which leaves max. 384 kB for the U-Boot itself
++ */
++#define CFG_ENV_ADDR 0xFFF60000
++#define CFG_ENV_SIZE 0x00010000
++#define CFG_ENV_SECT_SIZE 0x00010000
++
++/*-----------------------------------------------------------------------
++ * Cache Configuration
++ */
++#define CFG_CACHELINE_SIZE 32
++#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
++#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */
++#endif
++
++/*-----------------------------------------------------------------------
++ * IDE/ATA definitions
++ */
++#undef CONFIG_IDE_LED /* No IDE LED */
++#define CONFIG_IDE_RESET /* no reset for ide supported */
++#define CONFIG_IDE_PREINIT /* check for units */
++#define CONFIG_LBA48 /* 48 bit LBA supported */
++
++#if defined(CONFIG_LAN) || defined(CONFIG_HLAN) || defined(CONFIG_HGLAN)
++#define CFG_IDE_MAXBUS 1 /* Scan only 1 IDE bus */
++#define CFG_IDE_MAXDEVICE 1 /* Only 1 drive per IDE bus */
++#elif defined(CONFIG_HGTL)
++#define CFG_IDE_MAXBUS 2 /* Max. 2 IDE busses */
++#define CFG_IDE_MAXDEVICE 2 /* max. 2 drives per IDE bus */
++#else
++#error Config IDE: Unknown LinkStation type
++#endif
++
++#define CFG_ATA_BASE_ADDR 0
++
++#define CFG_ATA_DATA_OFFSET 0 /* Offset for data I/O */
++#define CFG_ATA_REG_OFFSET 0 /* Offset for normal registers */
++#define CFG_ATA_ALT_OFFSET 0 /* Offset for alternate registers */
++
++/*-----------------------------------------------------------------------
++ * Partitions and file system
++ */
++#define CONFIG_DOS_PARTITION
++
++/*-----------------------------------------------------------------------
++ * Internal Definitions
++ *
++ * Boot Flags
++ */
++#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */
++#define BOOTFLAG_WARM 0x02 /* Software reboot */
++
++#endif /* __CONFIG_H */
++
++/* vim: set ts=4: */
+diff -urN u-boot-86xx/include/devices.h u-boot-86xx-kuro_clean/include/devices.h
+--- u-boot-86xx/include/devices.h 2006-10-13 00:27:18.000000000 +0200
++++ u-boot-86xx-kuro_clean/include/devices.h 2006-11-06 22:05:38.000000000 +0100
+@@ -93,6 +93,7 @@
+ int devices_init (void);
+ int devices_done (void);
+ int device_deregister(char *devname);
++int console_setfile (int file, device_t * dev);
+ #ifdef CONFIG_LCD
+ int drv_lcd_init (void);
+ #endif
+@@ -111,5 +112,8 @@
+ #ifdef CONFIG_NETCONSOLE
+ int drv_nc_init (void);
+ #endif
++#if defined(CFG_CONSOLE_IS_IN_ENV) || defined(CONFIG_SPLASH_SCREEN) || defined(CONFIG_SILENT_CONSOLE)
++device_t *search_device (int flags, char *name);
++#endif
+
+ #endif /* _DEVICES_H_ */
+diff -urN u-boot-86xx/include/flash.h u-boot-86xx-kuro_clean/include/flash.h
+--- u-boot-86xx/include/flash.h 2006-10-13 00:27:18.000000000 +0200
++++ u-boot-86xx-kuro_clean/include/flash.h 2006-11-06 22:05:38.000000000 +0100
+@@ -215,6 +215,8 @@
+
+ #define AMD_ID_LV320B_2 0x221A221A /* 2d ID word for AM29LV320MB at 0x38 */
+ #define AMD_ID_LV320B_3 0x22002200 /* 3d ID word for AM29LV320MB at 0x3c */
++#define AMD_ID_LV320T_2 0x221A221A /* 2d ID word for AM29LV320MT at 0x38 */
++#define AMD_ID_LV320T_3 0x22012201 /* 3d ID word for AM29LV320MT at 0x3c */
+
+ #define AMD_ID_LV640U 0x22D722D7 /* 29LV640U ID (64 M, uniform sectors) */
+ #define AMD_ID_LV650U 0x22D722D7 /* 29LV650U ID (64 M, uniform sectors) */
+@@ -246,6 +248,8 @@
+ #define STM_ID_x800AB 0x005B005B /* M29W800AB ID (8M = 512K x 16 ) */
+ #define STM_ID_29W320DT 0x22CA22CA /* M29W320DT ID (32 M, top boot sector) */
+ #define STM_ID_29W320DB 0x22CB22CB /* M29W320DB ID (32 M, bottom boot sect) */
++#define STM_ID_29W324DT 0x225C225C /* M29W324DT ID (32 M, top boot sector) */
++#define STM_ID_29W324DB 0x225D225D /* M29W324DB ID (32 M, bottom boot sect) */
+ #define STM_ID_29W040B 0x00E300E3 /* M29W040B ID (4M = 512K x 8) */
+ #define FLASH_PSD4256GV 0x00E9 /* PSD4256 Flash and CPLD combination */
+
+@@ -353,6 +357,8 @@
+ #define FLASH_STM800AB 0x0051 /* STM M29WF800AB ( 8M = 512K x 16 ) */
+ #define FLASH_STMW320DT 0x0052 /* STM M29W320DT (32 M, top boot sector) */
+ #define FLASH_STMW320DB 0x0053 /* STM M29W320DB (32 M, bottom boot sect)*/
++#define FLASH_STMW324DT 0x005C /* STM M29W320DT (32 M, top boot sector) */
++#define FLASH_STMW324DB 0x005D /* STM M29W320DB (32 M, bottom boot sect)*/
+ #define FLASH_STM320DB 0x00CB /* STM M29W320DB (4M = 64K x 64, bottom)*/
+ #define FLASH_STM800DT 0x00D7 /* STM M29W800DT (1M = 64K x 16, top) */
+ #define FLASH_STM800DB 0x005B /* STM M29W800DB (1M = 64K x 16, bottom)*/
+diff -urN u-boot-86xx/include/pci_ids.h u-boot-86xx-kuro_clean/include/pci_ids.h
+--- u-boot-86xx/include/pci_ids.h 2006-10-13 00:27:18.000000000 +0200
++++ u-boot-86xx-kuro_clean/include/pci_ids.h 2006-11-06 22:05:38.000000000 +0100
+@@ -1473,6 +1473,8 @@
+ #define PCI_DEVICE_ID_ITE_IT8172G_AUDIO 0x0801
+ #define PCI_DEVICE_ID_ITE_IT8181 0x8181
+ #define PCI_DEVICE_ID_ITE_8872 0x8872
++#define PCI_DEVICE_ID_ITE_8211 0x8211
++#define PCI_DEVICE_ID_ITE_8212 0x8212
+
+ #define PCI_DEVICE_ID_ITE_IT8330G_0 0xe886
+
+diff -urN u-boot-86xx/lib_ppc/board.c u-boot-86xx-kuro_clean/lib_ppc/board.c
+--- u-boot-86xx/lib_ppc/board.c 2006-10-13 00:27:19.000000000 +0200
++++ u-boot-86xx-kuro_clean/lib_ppc/board.c 2006-11-06 22:05:38.000000000 +0100
+@@ -439,6 +439,10 @@
+ */
+ addr -= len;
+ addr &= ~(4096 - 1);
++#ifdef CONFIG_LINKSTATION
++ /* U-Boot code at 1 MB boundary to make it easier to debug */
++ addr &= ~(1048576 - 1);
++#endif
+ #ifdef CONFIG_E500
+ /* round down to next 64 kB limit so that IVPR stays aligned */
+ addr &= ~(65536 - 1);
+@@ -895,8 +899,10 @@
+ /* Initialize the jump table for applications */
+ jumptable_init ();
+
++#if !defined(CONFIG_LINKSTATION)
+ /* Initialize the console (after the relocation and devices init) */
+ console_init_r ();
++#endif
+
+ #if defined(CONFIG_CCM) || \
+ defined(CONFIG_COGENT) || \
+@@ -949,6 +955,7 @@
+ if ((s = getenv ("loadaddr")) != NULL) {
+ load_addr = simple_strtoul (s, NULL, 16);
+ }
++ debug("load_addr: %08lx\n", load_addr);
+ #if (CONFIG_COMMANDS & CFG_CMD_NET)
+ if ((s = getenv ("bootfile")) != NULL) {
+ copy_filename (BootFile, s, sizeof (BootFile));
+@@ -998,6 +1005,11 @@
+ reset_phy ();
+ #endif
+
++#if defined(CONFIG_LINKSTATION)
++ /* The LinkStation uses the net console by default */
++ console_init_r ();
++#endif
++
+ #ifdef CONFIG_POST
+ post_run (NULL, POST_RAM | post_bootmode_get(0));
+ #endif
+diff -urN u-boot-86xx/lib_ppc/interrupts.c u-boot-86xx-kuro_clean/lib_ppc/interrupts.c
+--- u-boot-86xx/lib_ppc/interrupts.c 2006-10-13 00:27:19.000000000 +0200
++++ u-boot-86xx-kuro_clean/lib_ppc/interrupts.c 2006-11-06 22:05:38.000000000 +0100
+@@ -40,7 +40,7 @@
+ #endif
+
+ extern int interrupt_init_cpu (unsigned *);
+-extern void timer_interrupt_cpu (struct pt_regs *);
++extern void timer_interrupt_cpu (struct pt_regs *, ulong timestamp);
+
+ static unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
+
+@@ -111,7 +111,7 @@
+ void timer_interrupt (struct pt_regs *regs)
+ {
+ /* call cpu specific function from $(CPU)/interrupts.c */
+- timer_interrupt_cpu (regs);
++ timer_interrupt_cpu (regs, timestamp);
+
+ /* Restore Decrementer Count */
+ set_dec (decrementer_count);
+diff -urN u-boot-86xx/net/net.c u-boot-86xx-kuro_clean/net/net.c
+--- u-boot-86xx/net/net.c 2006-10-13 00:27:19.000000000 +0200
++++ u-boot-86xx-kuro_clean/net/net.c 2006-11-06 22:05:38.000000000 +0100
+@@ -641,6 +641,11 @@
+ {
+ uchar *pkt;
+
++#ifdef ET_DEBUG
++ printf("%s dest: %08lx, dport: %d, sport: %d, len: %d\n",
++ __FUNCTION__, dest, dport, sport, len);
++#endif
++
+ /* convert to new style broadcast */
+ if (dest == 0)
+ dest = 0xFFFFFFFF;
+@@ -758,6 +763,8 @@
+ IPaddr_t tmp;
+ volatile IP_t *ip = (volatile IP_t *)pkt;
+
++ if (!pkt && !dest && !src && !len) /* ARP packet */
++ return;
+ tmp = NetReadIP((void *)&ip->ip_src);
+ if (tmp != NetPingIP)
+ return;
+@@ -1146,7 +1153,7 @@
+ ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid;
+
+ #ifdef ET_DEBUG
+- printf("packet received\n");
++ printf("%s: packet received\n", __FUNCTION__);
+ #endif
+
+ NetRxPkt = inpkt;
+@@ -1171,10 +1178,6 @@
+
+ x = ntohs(et->et_protlen);
+
+-#ifdef ET_DEBUG
+- printf("packet received\n");
+-#endif
+-
+ if (x < 1514) {
+ /*
+ * Got a 802 packet. Check the other protocol field.
+@@ -1305,13 +1308,16 @@
+ /* matched waiting packet's address */
+ if (tmp == NetArpWaitReplyIP) {
+ #ifdef ET_DEBUG
+- puts ("Got it\n");
++ puts ("ARP reply IP matches original pkt IP\n");
+ #endif
+ /* save address for later use */
+ memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
+
+ #ifdef CONFIG_NETCONSOLE
+- (*packetHandler)(0,0,0,0);
++ if (packetHandler)
++ (*packetHandler)(0,0,0,0);
++ else
++ printf("ARP: NULL packetHandler\n");
+ #endif
+ /* modify header, and transmit it */
+ memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
+@@ -1354,7 +1360,10 @@
+ NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
+ memcpy (NetServerEther, &arp->ar_data[ 0], 6);
+
+- (*packetHandler)(0,0,0,0);
++ if (packetHandler)
++ (*packetHandler)(0,0,0,0);
++ else
++ printf("ARP: NULL packetHandler\n");
+ }
+ break;
+
+diff -urN u-boot-86xx/net/nfs.c u-boot-86xx-kuro_clean/net/nfs.c
+--- u-boot-86xx/net/nfs.c 2006-10-13 00:27:19.000000000 +0200
++++ u-boot-86xx-kuro_clean/net/nfs.c 2006-11-06 22:05:38.000000000 +0100
+@@ -29,7 +29,7 @@
+ #include "nfs.h"
+ #include "bootp.h"
+
+-/*#define NFS_DEBUG*/
++#undef NFS_DEBUG
+
+ #if ((CONFIG_COMMANDS & CFG_CMD_NET) && (CONFIG_COMMANDS & CFG_CMD_NFS))
+
+@@ -180,6 +180,9 @@
+ int sport;
+
+ id = ++rpc_id;
++#ifdef NFS_DEBUG
++ printf ("%s xid: %d, rpc_id: %d\n", __FUNCTION__, id, rpc_id);
++#endif
+ pkt.u.call.id = htonl(id);
+ pkt.u.call.type = htonl(MSG_CALL);
+ pkt.u.call.rpcvers = htonl(2); /* use RPC version 2 */
+@@ -213,6 +216,10 @@
+ {
+ uint32_t data[16];
+
++#ifdef NFS_DEBUG
++ printf ("%s\n", __FUNCTION__);
++#endif
++
+ data[0] = 0; data[1] = 0; /* auth credential */
+ data[2] = 0; data[3] = 0; /* auth verifier */
+ data[4] = htonl(prog);
+@@ -234,6 +241,10 @@
+ int len;
+ int pathlen;
+
++#ifdef NFS_DEBUG
++ printf ("%s\n", __FUNCTION__);
++#endif
++
+ pathlen = strlen (path);
+
+ p = &(data[0]);
+@@ -259,6 +270,10 @@
+ uint32_t *p;
+ int len;
+
++#ifdef NFS_DEBUG
++ printf ("%s\n", __FUNCTION__);
++#endif
++
+ if ((NfsSrvMountPort == -1) || (!fs_mounted)) {
+ /* Nothing mounted, nothing to umount */
+ return;
+@@ -286,6 +301,10 @@
+ uint32_t *p;
+ int len;
+
++#ifdef NFS_DEBUG
++ printf ("%s\n", __FUNCTION__);
++#endif
++
+ p = &(data[0]);
+ p = (uint32_t *)rpc_add_credentials ((long *)p);
+
+@@ -308,6 +327,10 @@
+ int len;
+ int fnamelen;
+
++#ifdef NFS_DEBUG
++ printf ("%s\n", __FUNCTION__);
++#endif
++
+ fnamelen = strlen (fname);
+
+ p = &(data[0]);
+@@ -335,6 +358,10 @@
+ uint32_t *p;
+ int len;
+
++#ifdef NFS_DEBUG
++ printf ("%s\n", __FUNCTION__);
++#endif
++
+ p = &(data[0]);
+ p = (uint32_t *)rpc_add_credentials ((long *)p);
+
+@@ -405,8 +432,13 @@
+
+ if (rpc_pkt.u.reply.rstatus ||
+ rpc_pkt.u.reply.verifier ||
+- rpc_pkt.u.reply.astatus ||
+ rpc_pkt.u.reply.astatus) {
++#ifdef NFS_DEBUG
++ printf ("rstatus: %d\n", rpc_pkt.u.reply.rstatus);
++ printf ("verifier: %08lx\n", rpc_pkt.u.reply.verifier);
++ printf ("v2: %08lx\n", rpc_pkt.u.reply.v2);
++ printf ("astatus: %d\n", rpc_pkt.u.reply.astatus);
++#endif
+ return -1;
+ }
+
+@@ -433,13 +465,24 @@
+
+ memcpy ((unsigned char *)&rpc_pkt, pkt, len);
+
+- if (ntohl(rpc_pkt.u.reply.id) != rpc_id)
++ if (ntohl(rpc_pkt.u.reply.id) != rpc_id) {
++#ifdef NFS_DEBUG
++ printf ("rpc_id error. expected: %d, got: %d\n", \
++ rpc_id, ntohl(rpc_pkt.u.reply.id));
++#endif
+ return -1;
++ }
+
+ if (rpc_pkt.u.reply.rstatus ||
+ rpc_pkt.u.reply.verifier ||
+ rpc_pkt.u.reply.astatus ||
+ rpc_pkt.u.reply.data[0]) {
++#ifdef NFS_DEBUG
++ printf ("rstatus: %d\n", rpc_pkt.u.reply.rstatus);
++ printf ("verifier: %08lx\n", rpc_pkt.u.reply.verifier);
++ printf ("astatus: %d\n", rpc_pkt.u.reply.astatus);
++ printf ("data[0]: %08lx\n", rpc_pkt.u.reply.data[0]);
++#endif
+ return -1;
+ }
+
+@@ -544,7 +587,7 @@
+ struct rpc_t rpc_pkt;
+ int rlen;
+
+-#ifdef NFS_DEBUG_nop
++#ifdef NFS_DEBUG
+ printf ("%s\n", __FUNCTION__);
+ #endif
+
+@@ -601,6 +644,8 @@
+ printf ("%s\n", __FUNCTION__);
+ #endif
+
++ if (!pkt && !dest && !src && !len) /* ARP packet */
++ return;
+ if (dest != NfsOurPort) return;
+
+ switch (NfsState) {
+diff -urN u-boot-86xx/tools/Makefile u-boot-86xx-kuro_clean/tools/Makefile
+--- u-boot-86xx/tools/Makefile 2006-10-13 00:27:19.000000000 +0200
++++ u-boot-86xx-kuro_clean/tools/Makefile 2006-11-06 22:18:42.000000000 +0100
+@@ -21,10 +21,10 @@
+ # MA 02111-1307 USA
+ #
+
+-BIN_FILES = img2srec$(SFX) mkimage$(SFX) envcrc$(SFX) gen_eth_addr$(SFX) bmp_logo$(SFX)
++BIN_FILES = img2srec$(SFX) mkimage$(SFX) envcrc$(SFX) gen_eth_addr$(SFX) bmp_logo$(SFX) ncb$(SFX)
+
+ OBJ_LINKS = environment.o crc32.o
+-OBJ_FILES = img2srec.o mkimage.o envcrc.o gen_eth_addr.o bmp_logo.o
++OBJ_FILES = img2srec.o mkimage.o envcrc.o gen_eth_addr.o bmp_logo.o ncb.o
+
+ ifeq ($(ARCH),mips)
+ BIN_FILES += inca-swap-bytes$(SFX)