--- /dev/null
+.---------------------------------------------------------.
+| |
+| We thanks the Linux comunity for this great OS allows |
+| this great things, especially Linus Towards! |
+| |
+`---------------------------------------------------------'
+
+Following people contribute to 8xxROM...
+
+ Magnus Damm <damm@kieraypc01.p.y.ki.era.ericsson.se>
+ Dan Malek <dmalek@jlc.net>
+ Raphael Bossek <raphael.bossek@solutions4linux.de>
+ ...
+
+Thanks goes to follwing people :
+
+ Reinhard Probst <rprobst@speech-design.de>
+ ...
+
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
--- /dev/null
+8xxrom (0.3.0) unstable; urgency=low
+
+ * Added support for the FADS 823.
+ * Added support for PCMCIA slot A and B.
+ * Improved ATA PCMCIA support.
+ * Added Debian GNU/Linux changelog file; yes i'm a Debian developer :-)
+ * Some code cleanups.
+ * Created 8xxrom flash file is a valid ELF file (required for some flash utilities).
+
+ -- Raphael Bossek <raphael.bossek@solutions4linux.de>
+
+8xxrom (0.2.0) unstable; urgency=low
+
+ * Support for FADS/ADS 860 board.
+ * Supports now ext-2 and (v)fat partitions.
+ * More featured boot options.
+
+ -- Magnus Damm <damm@kieraypc01.p.y.ki.era.ericsson.se>
+
--- /dev/null
+# 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+# Copyright (C) 1999 Magnus Damm <damm@kieraypc01.p.y.ki.era.ericsson.se>
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+SYS=m8xx
+INCS = -I$(TOPLEVEL) -I$(TOPLEVEL)/linux/include \
+-I$(TOPLEVEL)/linux/arch/ppc/8xx_io
+
+ROMLOAD=0xFE000000
+DATA=0x00010000
+
+CFLAGS = -g -O2 -mcpu=860 -Wall $(INCS) -D__powerpc__ -DMHZ_50 \
+ -D__KERNEL__ -DDATA_MEM_ADDR=$(DATA) -DCONFIG_8xx -fsigned-char \
+ -msoft-float -pipe -fno-builtin -ffixed-r2 -Wno-uninitialized \
+ -mmultiple -mstring
+
+ASFLAGS=
+LINKFLAGS = -T ppcrom.lds -Ttext $(ROMLOAD) -Tdata $(DATA) -Bstatic
+
+# XXX: This flags allows us to patch the compiled elf file for future
+# use within the flash and for flash utilities that expect a valid
+# elf file (s19 file)
+# We move all section that should also be flashed to ROMLOAD
+# We need also the .bss section but the flags are wrong and so the s19 file
+# does not contain it. we have to change the flags
+OBJCPARAM = --remove-section=.stab --remove-section=.comment --remove-section=.stabstr \
+ --change-section-lma=.data+$(ROMLOAD) --change-section-lma=__ex_table+$(ROMLOAD) --change-section-lma=.bss+$(ROMLOAD) \
+ --set-section-flags=.bss=contents,alloc,load,data
+
+CROSS_COMPILE = powerpc-linux-
+
+LD = $(CROSS_COMPILE)ld
+CC = $(CROSS_COMPILE)gcc
+AR = $(CROSS_COMPILE)ar
+OBJDUMP = $(CROSS_COMPILE)objdump
+OBJCOPY = $(CROSS_COMPILE)objcopy
+
+.S.o:
+ $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
+
+distclean: clean
+ @SUBDIRS="$(SUBDIRS)"; \
+ for i in $$SUBDIRS; do $(MAKE) -C $$i distclean; done
+ rm -f *~ *.bak *.old *.s19 *.elf
+
+# vim: ts=4 noexpandtab syntax=make nonu
+
+# 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+# Copyright (C) 1999 Magnus Damm <damm@kieraypc01.p.y.ki.era.ericsson.se>
#
-# Makefile for the FADS ROM
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-# Use kernel include files to get machine/processor dependent stuff
-INCS = -I../linux/include \
- -I../linux/arch/ppc/8xx_io
-
-ROMLOAD=0xfe000000
-DATA=0x00010000
+TOPLEVEL = .
-CFLAGS = -O2 -mcpu=860 $(INCS) -D__powerpc__ -DMHZ_50 -DFADS_860 \
- -D__KERNEL__ -DDATA_MEM_ADDR=$(DATA) -DCONFIG_8xx -fsigned-char \
- -msoft-float -pipe -fno-builtin -ffixed-r2 -Wno-uninitialized \
- -mmultiple -mstring
+all: s19
-ASFLAGS=
-LINKFLAGS = -T ppcrom.lds -Ttext $(ROMLOAD) -Tdata $(DATA) -Bstatic
+include $(TOPLEVEL)/Make.config
-.S.o:
- $(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
+SUBDIRS = romsys lib board disk fs
+EXTRAOBJS = board/libboard.a disk/libdisk.a fs/libfs.a \
+ romsys/libsys.a lib/liblib.a
# Rom objects....order is important (i.e. start must be first)
-OBJS = start.o main.o serial.o traps.o vsprintf.o ctype.o string.o \
- memstuff.o cflash.o partition.o super.o inode.o dir.o \
- ppcstring.o extable.o
+OBJS = romsys/start.o main.o memstuff.o extable.o elf.o $(EXTRAOBJS)
+
+8xxrom: $(SUBDIRS) $(OBJS) ppcrom.lds
+ @for i in $(SUBDIRS); do $(MAKE) -C $$i; done
+ $(LD) $(LINKFLAGS) $(OBJS) -o 8xxrom
-fadsrom: $(OBJS) mkrombin
- ld $(LINKFLAGS) $(OBJS) -o fadsrom
- mkrombin fadsrom
+$(EXTRAOBJS):
+ @for i in $(SUBDIRS); do $(MAKE) -C $$i; done
# I ran this though 'dd' because on some NFS mounted file systems this
# was pretty slow due to the printf. The 'dd' buffers it into
# more efficient blocks.
-s19: fadsrom bintos19
- bintos19 fadsrom.bin | dd of=fadsrom.s19
+s19: 8xxrom mkrombin bintos19
+ $(OBJCOPY) $(OBJCPARAM) -O elf32-powerpc 8xxrom 8xxrom.elf
+ $(OBJCOPY) -O srec 8xxrom.elf 8xxrom.elf.s19
+ ./mkrombin 8xxrom
+ ./bintos19 8xxrom.bin | dd of=8xxrom.bin.s19
mkrombin: mkrombin.c
- cc -O2 -o mkrombin mkrombin.c
+ cc -O2 -Ilinux/include -o mkrombin mkrombin.c
bintos19: bintos19.c
cc -O2 -o bintos19 bintos19.c
clean:
- rm -f $(OBJS) fadsrom fadsrom.bin fadsrom.s19
+ @for i in $(SUBDIRS); do $(MAKE) -C $$i clean; done
+ rm -f $(OBJS) 8xxrom*
-realclean: clean
+distclean: clean
+ @for i in $(SUBDIRS); do $(MAKE) -C $$i distclean; done
rm -f bintos19 mkrombin
# Dependencies.....This should either be automatic or finished.
-
-start.o: Makefile ppc_asm.tmpl ppc_defs.h
main.o: Makefile
-serial.o: Makefile
+
+# vim: ts=4 noexpandtab nonu
-
-
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
chksum =~ chksum; /* one's complement */
printf("%02X\n", (chksum & 0xff));
}
+
+// vim: ts=4 expandtab cino=>4 cindent
--- /dev/null
+#
+# Makefile for the FADS ROM board specific parts
+#
+
+TOPLEVEL = ..
+
+LIB = libboard.a
+OBJS = fads.o ads.o
+
+all: $(LIB)
+
+include $(TOPLEVEL)/Make.config
+
+$(LIB): $(OBJS)
+ $(AR) cr $@ $(OBJS)
+
+clean:
+ rm -f $(OBJS) $(LIB)
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 1999 Raphael Bossek <raphael.bossek@solutions4linx.de>
+ *
+ * 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 "romfuncs.h"
+#include "m8xx/m8xx.h"
+#include <asm/8xx_immap.h>
+
+/* ------------------------------------------------------------------------- */
+/* dram tables - stolen from the manual */
+
+#if defined(CONFIG_DRAM_50MHZ)
+
+/* 50MHz tables */
+
+const uint dram_60ns[] =
+{ 0x8fffec24, 0x0fffec04, 0x0cffec04, 0x00ffec04,
+ 0x00ffec00, 0x37ffec47, 0xffffffff, 0xffffffff,
+ 0x8fffec24, 0x0fffec04, 0x08ffec04, 0x00ffec0c,
+ 0x03ffec00, 0x00ffec44, 0x00ffcc08, 0x0cffcc44,
+ 0x00ffec0c, 0x03ffec00, 0x00ffec44, 0x00ffcc00,
+ 0x3fffc847, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x8fafcc24, 0x0fafcc04, 0x0cafcc00, 0x11bfcc47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x8fafcc24, 0x0fafcc04, 0x0cafcc00, 0x03afcc4c,
+ 0x0cafcc00, 0x03afcc4c, 0x0cafcc00, 0x03afcc4c,
+ 0x0cafcc00, 0x33bfcc4f, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xc0ffcc84, 0x00ffcc04, 0x07ffcc04, 0x3fffcc06,
+ 0xffffcc85, 0xffffcc05, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff };
+
+const uint dram_70ns[] =
+{ 0x8fffcc24, 0x0fffcc04, 0x0cffcc04, 0x00ffcc04,
+ 0x00ffcc00, 0x37ffcc47, 0xffffffff, 0xffffffff,
+ 0x8fffcc24, 0x0fffcc04, 0x0cffcc04, 0x00ffcc04,
+ 0x00ffcc08, 0x0cffcc44, 0x00ffec0c, 0x03ffec00,
+ 0x00ffec44, 0x00ffcc08, 0x0cffcc44, 0x00ffec04,
+ 0x00ffec00, 0x3fffec47, 0xffffffff, 0xffffffff,
+ 0x8fafcc24, 0x0fafcc04, 0x0cafcc00, 0x11bfcc47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x8fafcc24, 0x0fafcc04, 0x0cafcc00, 0x03afcc4c,
+ 0x0cafcc00, 0x03afcc4c, 0x0cafcc00, 0x03afcc4c,
+ 0x0cafcc00, 0x33bfcc4f, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xe0ffcc84, 0x00ffcc04, 0x00ffcc04, 0x0fffcc04,
+ 0x7fffcc06, 0xffffcc85, 0xffffcc05, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff };
+
+const uint edo_60ns[] =
+{ 0x8ffbec24, 0x0ff3ec04, 0x0cf3ec04, 0x00f3ec04,
+ 0x00f3ec00, 0x37f7ec47, 0xffffffff, 0xffffffff,
+ 0x8fffec24, 0x0ffbec04, 0x0cf3ec04, 0x00f3ec0c,
+ 0x0cf3ec00, 0x00f3ec4c, 0x0cf3ec00, 0x00f3ec4c,
+ 0x0cf3ec00, 0x00f3ec44, 0x03f3ec00, 0x3ff7ec47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x8fffcc24, 0x0fefcc04, 0x0cafcc00, 0x11bfcc47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x8fffcc24, 0x0fefcc04, 0x0cafcc00, 0x03afcc4c,
+ 0x0cafcc00, 0x03afcc4c, 0x0cafcc00, 0x03afcc4c,
+ 0x0cafcc00, 0x33bfcc4f, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xc0ffcc84, 0x00ffcc04, 0x07ffcc04, 0x3fffcc06,
+ 0xffffcc85, 0xffffcc05, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff };
+
+const uint edo_70ns[] =
+{ 0x8ffbcc24, 0x0ff3cc04, 0x0cf3cc04, 0x00f3cc04,
+ 0x00f3cc00, 0x37f7cc47, 0xffffffff, 0xffffffff,
+ 0x8fffcc24, 0x0ffbcc04, 0x0cf3cc04, 0x00f3cc0c,
+ 0x03f3cc00, 0x00f3cc44, 0x00f3ec0c, 0x0cf3ec00,
+ 0x00f3ec4c, 0x03f3ec00, 0x00f3ec44, 0x00f3cc00,
+ 0x33f7cc47, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x8fffcc24, 0x0fefcc04, 0x0cafcc00, 0x11bfcc47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x8fffcc24, 0x0fefcc04, 0x0cafcc00, 0x03afcc4c,
+ 0x0cafcc00, 0x03afcc4c, 0x0cafcc00, 0x03afcc4c,
+ 0x0cafcc00, 0x33bfcc47, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xe0ffcc84, 0x00ffcc04, 0x00ffcc04, 0x0fffcc04,
+ 0x7fffcc04, 0xffffcc86, 0xffffcc05, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff };
+
+#elif defined(CONFIG_DRAM_25MHZ)
+
+/* 25MHz tables */
+
+const uint dram_60ns[] =
+{ 0x0fffcc04, 0x08ffcc00, 0x33ffcc47, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fffcc24, 0x0fffcc04, 0x08ffcc00, 0x03ffcc4c,
+ 0x08ffcc00, 0x03ffcc4c, 0x08ffcc00, 0x03ffcc4c,
+ 0x08ffcc00, 0x33ffcc47, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fafcc04, 0x08afcc00, 0x3fbfcc47, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fafcc04, 0x0cafcc00, 0x01afcc4c, 0x0cafcc00,
+ 0x01afcc4c, 0x0cafcc00, 0x01afcc4c, 0x0cafcc00,
+ 0x31bfcc43, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x80ffcc84, 0x13ffcc04, 0xffffcc87, 0xffffcc05,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff };
+
+const uint dram_70ns[] =
+{ 0x0fffec04, 0x08ffec04, 0x00ffec00, 0x3fffcc47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fffcc24, 0x0fffcc04, 0x08ffcc00, 0x03ffcc4c,
+ 0x08ffcc00, 0x03ffcc4c, 0x08ffcc00, 0x03ffcc4c,
+ 0x08ffcc00, 0x33ffcc47, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fafcc04, 0x08afcc00, 0x3fbfcc47, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fafcc04, 0x0cafcc00, 0x01afcc4c, 0x0cafcc00,
+ 0x01afcc4c, 0x0cafcc00, 0x01afcc4c, 0x0cafcc00,
+ 0x31bfcc43, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xc0ffcc84, 0x01ffcc04, 0x7fffcc86, 0xffffcc05,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff };
+
+const uint edo_60ns[] =
+{ 0x0ffbcc04, 0x0cf3cc04, 0x00f3cc00, 0x33f7cc47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0ffbcc04, 0x09f3cc0c, 0x09f3cc0c, 0x09f3cc0c,
+ 0x08f3cc00, 0x3ff7cc47, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fefcc04, 0x08afcc04, 0x00afcc00, 0x3fbfcc47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fefcc04, 0x08afcc00, 0x07afcc48, 0x08afcc48,
+ 0x08afcc48, 0x39bfcc47, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x80ffcc84, 0x13ffcc04, 0xffffcc87, 0xffffcc05,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff };
+
+const uint edo_70ns[] =
+{ 0x0ffbcc04, 0x0cf3cc04, 0x00f3cc00, 0x33f7cc47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0ffbec04, 0x08f3ec04, 0x03f3ec48, 0x08f3cc00,
+ 0x0ff3cc4c, 0x08f3cc00, 0x0ff3cc4c, 0x08f3cc00,
+ 0x3ff7cc47, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fefcc04, 0x08afcc04, 0x00afcc00, 0x3fbfcc47,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x0fefcc04, 0x08afcc00, 0x07afcc4c, 0x08afcc00,
+ 0x07afcc4c, 0x08afcc00, 0x07afcc4c, 0x08afcc00,
+ 0x37bfcc47, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xc0ffcc84, 0x01ffcc04, 0x7fffcc86, 0xffffcc05,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0x33ffcc07, 0xffffffff, 0xffffffff, 0xffffffff };
+
+
+#else
+#error dram not correct defined - use CONFIG_DRAM_25MHZ or CONFIG_DRAM_50MHZ
+#endif
+
+unsigned char pcmcia_slot_status[ PCMCIA_MAX_SLOTS ];
+
+#define PCMCIA_MAP 0xf0130000
+volatile unsigned char *pcmcia_mem = (unsigned char*)PCMCIA_MAP;
+
+/* ------------------------------------------------------------------------- */
+
+int _ads_draminit(uint base, uint noMbytes, uint edo, uint delay)
+{
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+ /* init upm */
+
+ switch(delay)
+ {
+
+ case 70:
+ if(edo)
+ m8xx_upmconfig(UPMA, (uint *) edo_70ns, sizeof(edo_70ns)/sizeof(uint));
+ else
+ m8xx_upmconfig(UPMA, (uint *) dram_70ns, sizeof(dram_70ns)/sizeof(uint));
+
+ break;
+
+ case 60:
+ if(edo)
+ m8xx_upmconfig(UPMA, (uint *) edo_60ns, sizeof(edo_60ns)/sizeof(uint));
+ else
+ m8xx_upmconfig(UPMA, (uint *) dram_60ns, sizeof(dram_60ns)/sizeof(uint));
+
+ break;
+
+ default : return -1;
+ }
+
+ memctl->memc_mptpr = 0x0400; /* divide by 16 */
+
+ switch(noMbytes)
+ {
+
+ case 8: /* 8 Mbyte uses both CS3 and CS2 */
+ memctl->memc_mamr = 0x13a01114;
+ memctl->memc_or3 = 0xffc00800;
+ memctl->memc_br3 = 0x00400081 + base;
+ memctl->memc_or2 = 0xffc00800;
+ break;
+
+ case 4: /* 4 Mbyte uses only CS2 */
+ memctl->memc_mamr = 0x13a01114;
+ memctl->memc_or2 = 0xffc00800;
+ break;
+
+ case 32: /* 32 Mbyte uses both CS3 and CS2 */
+ memctl->memc_mamr = 0x13b01114;
+ memctl->memc_or3 = 0xff000800;
+ memctl->memc_br3 = 0x01000081 + base;
+ memctl->memc_or2 = 0xff000800;
+ break;
+
+ case 16: /* 16 Mbyte uses only CS2 */
+ memctl->memc_mamr = 0x13b01114;
+ memctl->memc_or2 = 0xff000800;
+ break;
+
+ default:
+ return -1;
+ }
+ memctl->memc_br2 = 0x81 + base; /* use upma */
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void _ads_dramdisable(void)
+{
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+ memctl->memc_br2 = 0x00000000;
+ memctl->memc_br3 = 0x00000000;
+
+ /* maybe we should turn off upma here or something */
+}
+
+/* ------------------------------------------------------------------------- */
+
+int ads_draminit(uint base, uint *noMbytes, uint *delay, uint *type)
+{
+ uint k, m, s;
+
+ k = (*((uint *)BCSR2) >> 23) & 0x0f;
+
+ m = 0;
+
+ switch(k & 0x3)
+ {
+ case 0x00 : m = 4; break; /* "MCM36100 / MT8D132X" */
+ case 0x01 : m = 32; break; /* "MCM36800 / MT16D832X" */
+ case 0x02 : m = 16; break; /* "MCM36400 / MT8D432X" */
+ case 0x03 : m = 8; break; /* "MCM36200 / MT16D832X ?" */
+ }
+
+ switch(k >> 2)
+ {
+ case 0x02 : k = 70; break;
+ case 0x03 : k = 60; break;
+ default : printf("unknown dramdelay (0x%x) - defaulting to 70 ns", k);
+ k = 70;
+ }
+
+#ifdef CONFIG_FADS
+ s = 0; /* the FADS is missing this bit, all rams treated as non-edo */
+#else
+ s = (*((uint *)BCSR2) >> 27) & 0x01;
+#endif
+
+ *noMbytes = m;
+ *delay = k;
+ *type = s;
+
+ if(!_ads_draminit(base, m, s, k))
+ {
+
+ *((uint *)BCSR1) &= ~0x40000000; /* enable dram */
+
+ if(mem_check(base, m << 20))
+ {
+ /* dram off */
+
+ *((uint *)BCSR1) |= 0x40000000; /* disable dram */
+ _ads_dramdisable();
+ return -1; /* ERROR or not connected */
+ }
+ else
+ return 0;
+ }
+ else
+ {
+ _ads_dramdisable();
+ return -1;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* flash detect - according to the presence detect bits */
+
+void ads_flashinit(uint *noMbytes, uint *delay)
+{
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+ uint k, m;
+
+ k = *((uint *)BCSR2) >> 28;
+
+ switch(k)
+ {
+#ifdef CONFIG_FADS
+ case 0x04 : m = 8; break; /* "SM732A2000 / SM73228" */
+ case 0x05 : m = 4; break; /* "SM732A1000A / SM73218" */
+#endif
+ case 0x06 : m = 8; break; /* "MCM29080" */
+ case 0x07 : m = 4; break; /* "MCM29040" */
+ case 0x08 : m = 2; break; /* "MCM29020" */
+#ifdef CONFIG_ADS
+ case 0x0a : m = 4; break; /* "SM732A1000A" */
+ case 0x0b : m = 8; break; /* "SM732A2000" */
+#endif
+ default : printf("unknown flashsize (0x%x) - defaulting to 2 Mbyte", k);
+ m = 2;
+ }
+
+ k = (*((uint *)BCSR3) >> 20) & 0x07;
+
+ switch(k)
+ {
+ case 0x01 : k = 150; break;
+ case 0x02 : k = 120; break;
+ case 0x03 : k = 90; break;
+ default : printf("unknown flashdelay(0x%x) - defaulting to 150 ns", k);
+ k = 150;
+ }
+
+ /* we're supposed to set the correct number of waitstates
+ * but today we just set it to maximum, no hurry */
+
+ /* set or0 to the correct size */
+
+ memctl->memc_or0 = ~((m << 20) - 1) | 0xdf4;
+
+ *noMbytes = m;
+ *delay = k;
+
+}
+
+/* ------------------------------------------------------------------------- */
+/* board detect/check - according to BCSRx */
+
+int ads_boardcheck(void)
+{
+ uint k;
+
+ printf("ADS rev ");
+
+ k = (((*((uint *)BCSR3) >> 23) & 1) << 3)
+ | (((*((uint *)BCSR3) >> 19) & 1) << 2)
+ | (((*((uint *)BCSR3) >> 16) & 3));
+
+ switch(k)
+ {
+ case 0x00 : printf("ENG - this board suck, check the errata, no support\n");
+ return -1;
+ case 0x01 : printf("PILOT - warning, read errata"); break;
+ case 0x02 : printf("A - warning, read errata"); break;
+ case 0x03 : printf("B"); break;
+ default: printf("unknown revision (0x%x)", k); return -1;
+ }
+
+ return 0;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+int ads_pcmciacheck(void)
+{
+ volatile pcmconf8xx_t *pcmp;
+ uint v;
+
+ /* Enable the PCMCIA for a Flash card.
+ */
+
+ pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));
+
+ pcmp->pcmc_pbr0 = PCMCIA_MAP;
+ pcmp->pcmc_por0 = 0xc00ff05d;
+ /* Set all slots to zero by default. */
+ pcmp->pcmc_pgcra = 0;
+ pcmp->pcmc_pgcrb = 0;
+#ifdef PCMCIA_SLOT_A
+ pcmp->pcmc_pgcra = 0x40;
+#endif
+#ifdef PCMCIA_SLOT_B
+ pcmp->pcmc_pgcrb = 0x40;
+#endif
+
+ /* enable PCMCIA buffers */
+ *((uint *)BCSR1) &= ~BCSR1_PCCEN;
+
+ /* Check if any PCMCIA card is luged in. */
+ if (pcmp->pcmc_pipr & 0x18001800)
+ {
+ printf("No card present.\n");
+#ifdef PCMCIA_SLOT_A
+ pcmp->pcmc_pgcra = 0;
+#endif
+#ifdef PCMCIA_SLOT_B
+ pcmp->pcmc_pgcrb = 0;
+#endif
+ return -1;
+ }
+
+ v = 0;
+
+ /* both the ADS and the FADS has a 5V keyed pcmcia connector (?)*/
+
+#ifdef MPC860
+ switch( (pcmp->pcmc_pipr >> 30) & 3 )
+#elif MPC823
+ switch( (pcmp->pcmc_pipr >> 14) & 3 )
+#endif
+ {
+ case 0x00 : printf("5V\n"); v = 5; break;
+ case 0x01 : printf("5V and 3V\n"); v = 5; break;
+ case 0x03 : printf("5V, 3V and x.xV\n"); v = 5; break;
+ }
+
+ if(v == 5)
+ {
+
+#ifdef CONFIG_ADS
+
+ /* Enable 5 volt Vcc.
+ */
+
+ *((uint *)BCSR1) &= ~BCSR1_PCCVCCON;
+
+#endif
+
+#ifdef CONFIG_FADS
+
+ /* Enable 5 volt Vcc.
+ */
+
+ *((uint *)BCSR1) &= ~BCSR1_PCCVCC0;
+ *((uint *)BCSR1) |= BCSR1_PCCVCC1;
+
+#if 0
+ /* Enable PCMCIA drivers and 3.3 voltage.
+ */
+ *((uint *)BCSR1) |= 0x00400000;
+ *((uint *)BCSR1) &= ~0x00b10000;
+#endif
+#endif
+ }
+ else
+ {
+ *((uint *)BCSR1) |= BCSR1_PCCEN; /* disable pcmcia */
+
+ printf("unknown voltage\n");
+ return -1;
+ }
+
+ /* disable pcmcia reset after a while */
+
+ udelay(20);
+
+#ifdef MPC860
+ pcmp->pcmc_pgcra = 0;
+#elif MPC823
+ pcmp->pcmc_pgcrb = 0;
+#endif
+
+ /* If you using a real hd you should give a short
+ * spin-up time. */
+#ifdef CONFIG_DISK_SPINUP_TIME
+ udelay(CONFIG_DISK_SPINUP_TIME);
+#endif
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* init_board() is the first c-code running on our machine! */
+/* the stack is set up at the top of the internal dpram */
+/* not much stack to play around with */
+/* this function is shared between both the FADS and the ADS board */
+
+void board_init(void)
+{
+ bd_t bd;
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+ uint k, m, s;
+ uint memsize = 0;
+ uint status = 0;
+
+ /* Because of the way the 860 starts up and assigns CS0 the
+ * entire address space, we have to set the memory controller
+ * differently. Normally, you write the option register
+ * first, and then enable the chip select by writing the
+ * base register. For CS0, you must write the base register
+ * first, followed by the option register.
+ */
+
+ memctl->memc_br0 = BR0_VALUE; /* (16-9) - set base first */
+ memctl->memc_or0 = OR0_VALUE; /* (16-10) */
+
+ /* BCSRx - Board Control and Status Registers */
+
+ memctl->memc_or1 = OR1_VALUE;
+ memctl->memc_br1 = BR1_VALUE;
+
+ /* SYPCR - contains watchdog control (11-9) */
+
+ immap->im_siu_conf.sc_sypcr = SYPCR_VALUE;
+
+ /* here we should check the RSR register to know what to initialize */
+ /* but what the heck */
+
+ /* SIUMCR - contains debugpins configuration (11-6) */
+
+ immap->im_siu_conf.sc_siumcr = SIUMCR_VALUE;
+
+ /* initialize timebase status and control register (11-26) */
+ /* no need to unlock TBSCRK */
+
+ immap->im_sit.sit_tbscr = 0xc1; //TBSCR_VALUE | 1;
+
+ /* initialize the PIT (11-31) */
+
+ immap->im_sit.sit_piscr = PISCR_VALUE;
+
+ /* initialize the RTC (11-27) */
+
+ // not supported yet
+ //immap->im_sit.sit_rtcsc = RTCSC_VALUE;
+
+ /* set tmbclk to /16 */
+
+ immap->im_clkrst.car_sccr |= 0x02000000;
+
+#ifdef MPC8XX_BUSDIV
+#if MPC8XX_BUSDIV == 2
+
+ immap->im_clkrst.car_sccr |= 0x00020000;
+
+#else
+#error busdiv value not supported
+#endif
+#endif
+
+ /* set the PLL, the low-power modes and the reset control (15-29) */
+
+ immap->im_clkrst.car_plprcr = ((MPC8XX_FACT-1) << 20) | 0x4000;
+
+ /* initialize a temporary bdinfo to pass to the serial-code */
+
+ bd.bi_intfreq = MPC8XX_HZ / 1000000;
+
+ /* turn off everything on the board except the flash as default */
+
+#if defined(CONFIG_FADS)
+
+ *((uint *)BCSR1) = 0x79bc0000;
+ *((uint *)BCSR4) = 0x7ef80000;
+
+#elif defined(CONFIG_ADS)
+
+ // *((uint *)BCSR1) = 0x79fd0000;
+
+#endif
+
+ /* set up serial port */
+
+ serial_init(&bd);
+
+ /* the (F)ADS-board displays crap on the terminal if we don't wait
+ * why? */
+
+ udelay(20);
+
+ display_options();
+
+
+ /* I don't know if it's wise to check the cpu here, maybe we should have
+ * done that a bit earlier */
+
+ printf("cpu: ");
+
+ if(m8xx_checkcpu() == -1)
+ {
+ printf("not supported\n");
+ hang();
+ }
+
+
+ /* check the board */
+
+ printf("board: ");
+
+#if defined(CONFIG_ADS)
+ if(!ads_boardcheck())
+#elif defined(CONFIG_FADS)
+ if(!fads_boardcheck())
+#else
+#error board not defined
+#endif
+ {
+ printf("\n");
+ }
+ else
+ {
+ printf("\n");
+ hang();
+ }
+
+
+ /* initialize flash */
+
+ printf("flash: ");
+
+ ads_flashinit(&m, &k);
+
+ printf("%u Mbytes, delay %u ns\n", m, k);
+
+
+
+ /* the FADS has got SDRAM */
+
+#ifdef CONFIG_FADS
+
+ printf("sdram: ");
+
+ if(fads_sdraminit(memsize, &k) == 0)
+ {
+ printf("4 Mbyte, OK\n");
+ memsize += k << 20;
+ }
+ else
+ printf("ERROR, not used\n");
+
+#endif
+
+
+ /* both the ADS and the FADS has got dram */
+
+ printf("dram: ");
+
+ if(ads_draminit(memsize, &k, &m, &s) == 0)
+ {
+ if(s)
+ printf("EDO, ");
+
+ printf("%u Mbyte, %u ns, OK\n", k, m);
+ memsize += k << 20;
+ }
+ else
+ printf("ERROR, not used\n");
+
+
+
+ /* set up pcmcia controller and card */
+
+ printf("pcmcia: ");
+
+ if(ads_pcmciacheck() == 0)
+ status |= PCMCIA_PRESENT;
+
+ if(!memsize)
+ {
+ printf("No memory found.\n");
+ hang();
+ }
+
+#if 0
+ /* Setup signals to the 68160 and enable it */
+
+ immap->im_ioport.iop_pcdir = 0x0e00;
+ immap->im_ioport.iop_pcdat = 0x05ff;
+
+ *((uint *)BCSR1) &= ~BCSR1_ETHEN;
+#endif
+ /* start_main(stackpos, memsize) */
+
+ start_main((memsize) - 0x10000, memsize, status);
+}
+
+// vim: ts=2 expandtab nu
--- /dev/null
+/* stolen from linux/include/asm-ppc/mpc8xx.h */
+
+#ifndef __CONFIG_8xx_DEFS
+#define __CONFIG_8xx_DEFS
+
+#ifdef CONFIG_ADS
+#include <asm/ads.h>
+#endif
+
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
+
+#endif /* __CONFIG_8xx_DEFS */
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 "romfuncs.h"
+#include "m8xx/m8xx.h"
+#include <asm/8xx_immap.h>
+
+#if defined(CONFIG_SDRAM_100MHZ)
+
+/* ------------------------------------------------------------------------- */
+/* sdram table by Dan Malek */
+
+/* This has the stretched early timing so the 50 MHz
+ * processor can make the 100 MHz timing. This will
+ * work at all processor speeds.
+ */
+
+
+#define SDRAM_MPTPRVALUE 0x0400
+
+#define SDRAM_MBMRVALUE0 0xc3802114 /* (16-14) 50 MHz */
+#define SDRAM_MBMRVALUE1 SDRAM_MBMRVALUE0
+
+#define SDRAM_OR4VALUE 0xffc00a00
+#define SDRAM_BR4VALUE 0x000000c1 /* base address will be or:ed on */
+
+#define SDRAM_MARVALUE 0x88
+
+#define SDRAM_MCRVALUE0 0x80808111 /* run pattern 0x11 */
+#define SDRAM_MCRVALUE1 SDRAM_MCRVALUE0
+
+
+const uint sdram_table[] =
+{
+ /* single read. (offset 0 in upm RAM) */
+ 0xefebfc24, 0x1f07fc24, 0xeeaefc04, 0x11adfc04,
+ 0xefbbbc00, 0x1ff77c45, 0xffffffff, 0xffffffff,
+
+ /* burst read. (offset 8 in upm RAM) */
+ 0xefebfc24, 0x1f07fc24, 0xeeaefc04, 0x10adfc04,
+ 0xf0affc00, 0xf0affc00, 0xf1affc00, 0xefbbbc00,
+ 0x1ff77c45, 0xeffbbc04, 0x1ff77c34, 0xefeabc34,
+ 0x1fb57c35, 0xffffffff, 0xffffffff, 0xffffffff,
+
+ /* single write. (offset 18 in upm RAM) */
+ 0xefebfc24, 0x1f07fc24, 0xeeaebc00, 0x01b93c04,
+ 0x1ff77c45, 0xffffffff, 0xffffffff, 0xffffffff,
+
+ /* burst write. (offset 20 in upm RAM) */
+ 0xefebfc24, 0x1f07fc24, 0xeeaebc00, 0x10ad7c00,
+ 0xf0affc00, 0xf0affc00, 0xe1bbbc04, 0x1ff77c45,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+
+ /* refresh. (offset 30 in upm RAM) */
+ 0xeffafc84, 0x1ff5fc04, 0xfffffc04, 0xfffffc04,
+ 0xfffffc84, 0xfffffc07, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+
+ /* exception. (offset 3c in upm RAM) */
+ 0xeffffc06, 0x1ffffc07, 0xffffffff, 0xffffffff };
+
+#elif defined(CONFIG_SDRAM_50MHZ)
+
+/* ------------------------------------------------------------------------- */
+/* sdram table stolen from the fads manual */
+/* for chip MB811171622A-100 */
+
+/* this table is for 32-50MHz operation */
+
+#define _not_used_ 0xffffffff
+
+#define SDRAM_MPTPRVALUE 0x0400
+
+#define SDRAM_MBMRVALUE0 0x80802114 /* refresh at 32MHz */
+#define SDRAM_MBMRVALUE1 0x80802118
+
+#define SDRAM_OR4VALUE 0xffc00a00
+#define SDRAM_BR4VALUE 0x000000c1 /* base address will be or:ed on */
+
+#define SDRAM_MARVALUE 0x88
+
+#define SDRAM_MCRVALUE0 0x80808105
+#define SDRAM_MCRVALUE1 0x80808130
+
+
+const uint sdram_table[] =
+{
+ /* single read. (offset 0 in upm RAM) */
+ 0x1f07fc04, 0xeeaefc04, 0x11adfc04, 0xefbbbc00,
+ 0x1ff77c47,
+
+ /* MRS initialization (offset 5) */
+
+ 0x1ff77c34, 0xefeabc34, 0x1fb57c35,
+
+ /* burst read. (offset 8 in upm RAM) */
+ 0x1f07fc04, 0xeeaefc04, 0x10adfc04, 0xf0affc00,
+ 0xf0affc00, 0xf1affc00, 0xefbbbc00, 0x1ff77c47,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+
+ /* single write. (offset 18 in upm RAM) */
+ 0x1f27fc04, 0xeeaebc00, 0x01b93c04, 0x1ff77c47,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+
+ /* burst write. (offset 20 in upm RAM) */
+ 0x1f07fc04, 0xeeaebc00, 0x10ad7c00, 0xf0affc00,
+ 0xf0affc00, 0xe1bbbc04, 0x1ff77c47, _not_used_,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+
+ /* refresh. (offset 30 in upm RAM) */
+ 0x1ff5fc84, 0xfffffc04, 0xfffffc04, 0xfffffc04,
+ 0xfffffc84, 0xfffffc07, _not_used_, _not_used_,
+ _not_used_, _not_used_, _not_used_, _not_used_,
+
+ /* exception. (offset 3c in upm RAM) */
+ 0x7ffffc07, _not_used_, _not_used_, _not_used_ };
+
+/* ------------------------------------------------------------------------- */
+
+#else
+#error SDRAM not correctly configured
+#endif
+
+
+int _fads_sdraminit(uint base, uint noMbytes)
+{
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+ if(noMbytes != 4)
+ return -1;
+
+ m8xx_upmconfig(UPMB, (uint *)sdram_table,sizeof(sdram_table)/sizeof(uint));
+
+ memctl->memc_mptpr = SDRAM_MPTPRVALUE;
+
+ /* Configure the refresh (mostly). This needs to be
+ * based upon processor clock speed and optimized to provide
+ * the highest level of performance. For multiple banks,
+ * this time has to be divided by the number of banks.
+ * Although it is not clear anywhere, it appears the
+ * refresh steps through the chip selects for this UPM
+ * on each refresh cycle.
+ * We have to be careful changing
+ * UPM registers after we ask it to run these commands.
+ */
+
+ memctl->memc_mbmr = SDRAM_MBMRVALUE0;
+ memctl->memc_mar = SDRAM_MARVALUE; /* MRS code */
+
+ udelay(200);
+
+ /* Now run the precharge/nop/mrs commands.
+ */
+
+ memctl->memc_mcr = 0x80808111; /* run pattern 0x11 */
+
+ udelay(200);
+
+ /* Run 8 refresh cycles */
+
+ memctl->memc_mcr = SDRAM_MCRVALUE0;
+
+ udelay(200);
+
+ memctl->memc_mbmr = SDRAM_MBMRVALUE1;
+ memctl->memc_mcr = SDRAM_MCRVALUE1;
+
+ udelay(200);
+
+ memctl->memc_mbmr = SDRAM_MBMRVALUE0;
+
+ memctl->memc_or4 = SDRAM_OR4VALUE;
+ memctl->memc_br4 = SDRAM_BR4VALUE | base;
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void _fads_sdramdisable()
+{
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+ memctl->memc_br4 = 0x00000000;
+
+ /* maybe we should turn off upmb here or something */
+}
+
+/* ------------------------------------------------------------------------- */
+
+int fads_sdraminit(uint base, uint *noMbytes)
+{
+ uint m = 4;
+
+ *((uint *)BCSR1) |= 0x00020000; /* enable sdram */
+ /* _fads_sdraminit needs access to sdram */
+ *noMbytes = m;
+
+ if(!_fads_sdraminit(base, m))
+ {
+ if(mem_check(base, m << 20))
+ {
+ *((uint *)BCSR1) &= ~0x00020000; /* disable sdram */
+
+ _fads_sdramdisable();
+
+ return -1;
+ }
+ else
+ return 0;
+ }
+ else
+ {
+ *((uint *)BCSR1) &= ~0x00020000; /* disable sdram */
+
+ _fads_sdramdisable();
+
+ return -1;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+/* board detect/check - according to BCSRx */
+
+int fads_boardcheck(void)
+{
+ uint k;
+
+ k = (*((uint *)BCSR3) >> 24) & 0x3f;
+
+ switch(k)
+ {
+ case 0x03 :
+ case 0x20 :
+ case 0x21 :
+ case 0x22 :
+ case 0x23 :
+ case 0x24 : printf("FADS"); break;
+ default : printf("unknown board (0x%02x)\n", k); return -1;
+ }
+
+ printf(" with db ");
+
+ switch(k)
+ {
+ case 0x03 : printf("MPC823"); break;
+ case 0x20 : printf("MPC801"); break;
+ case 0x21 : printf("MPC850"); break;
+ case 0x22 : printf("MPC821, MPC860 / MPC860SAR / MPC860T"); break;
+ case 0x23 : printf("MPC860SAR"); break;
+ case 0x24 : printf("MPC860T"); break;
+ }
+
+ printf(" rev ");
+
+ k = (((*((uint *)BCSR3) >> 23) & 1) << 3)
+ | (((*((uint *)BCSR3) >> 19) & 1) << 2)
+ | (((*((uint *)BCSR3) >> 16) & 3));
+
+ switch(k)
+ {
+ case 0x01 : printf("ENG or PILOT"); break;
+ default: printf("unknown (0x%x)", k); return -1;
+ }
+
+ return 0;
+}
+
--- /dev/null
+/* config.h - contains configuration options
+ *
+ * this is the place to configure your boot-code
+ * no fancy menuconfig here
+ *
+ * 1999-12-19 added support for 823 by Raphael Bossek <raphael.bossek@solutions4linux.de>
+ * 1999-03-09 created by Magnus Damm <damm@bitsmart.com>
+ */
+
+#undef MPC860
+#define MPC823 1
+
+#define CONFIG_FADS 1 /* define if your board is FADS */
+#undef CONFIG_ADS /* define if your board is ADS */
+
+#define CONFIG_CON_SMC 1 /* What SMC is the console connected to ? */
+
+#define CONFIG_DRAM_50MHZ 1
+#define CONFIG_SDRAM_50MHZ 1
+
+/* disk configuration */
+
+#define CONFIG_DISK_ATA 1
+#undef CONFIG_DISK_ATA_PCMCIABUG
+#undef CONFIG_DISK_ROM
+
+#define CONFIG_DISK_SPINUP_TIME 1000000
+
+#if 0
+#define CONFIG_DISK_DEFAULTDEV "ata"
+#define CONFIG_DISK_DEFAULTPART "1"
+#endif
+
+/* PCMCIA configuration */
+#define PCMCIA_MAX_SLOTS 2
+
+#ifdef MPC860
+# define PCMCIA_SLOT_A 1
+#endif
+#if defined(MCP823) || defined(MPC860)
+# define PCMCIA_SLOT_B 1 /* 823 does only have a B slot */
+#endif
+
+/* clock configuration */
+
+#define MPC8XX_XIN 4000000 /* 4 MHz in */
+#define MPC8XX_FACT 12 /* Multiply by 12 */
+/* #define MPC8XX_BUSDIV 2 */
+#define MPC8XX_HZ ((MPC8XX_XIN) * (MPC8XX_FACT))
+
+
+
+
+
+
--- /dev/null
+#
+# Makefile for the FADS ROM disk functions
+#
+
+TOPLEVEL = ..
+
+LIB = libdisk.a
+OBJS = disk.o part.o ata.o rom.o
+
+all: $(LIB)
+
+include $(TOPLEVEL)/Make.config
+
+$(LIB): $(OBJS)
+ $(AR) cr $@ $(OBJS)
+
+clean:
+ rm -f $(OBJS) $(LIB)
+
+# Dependencies.....This should either be automatic or finished.
+ata.o: Makefile ata.h
+rom.o: Makefile rom.h
+disk.o: Makefile ata.h rom.h
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ * Copyright (C) 1999 Raphael Bossek <raphael.bossek@solutions4linux.de>
+ *
+ * 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 "romfuncs.h"
+#include "ata.h"
+
+int ata_enabled;
+
+__inline__ unsigned ld_le16(volatile unsigned short *addr)
+{
+ unsigned val;
+
+ __asm__ volatile("lhbrx %0,0,%1; eieio" : "=r" (val) : "r" (addr));
+ return val;
+}
+
+
+/*
+ * Read/Write PCMCIA memory space
+ */
+
+/* Moved definition to board/ads.c. This value will be set
+ * at run-time in the ads_pcmciacheck() function; it seams that
+ * the main_loop() function does ZERO the .data (global variables)
+ * section too so we set this value at runtime. */
+extern volatile unsigned char *pcmcia_mem;
+
+#ifdef CONFIG_DISK_ATA_PCMCIABUG
+
+/* this code here looks pretty stupid
+ * but it is actually a workaround for a bug in one MACH-ciruit on the (F)ADS
+ * the access before the pcmcia access must NOT be a flash access
+ * instruction cache must be turned on */
+
+unsigned char inba(volatile unsigned char *address)
+{
+ __asm__ volatile(".align 8");
+ __asm__ volatile("eieio");
+ return (*address);
+}
+
+unsigned char inb(int port)
+{
+ unsigned char *p[2];
+ int k;
+ unsigned char c;
+
+ p[0] = (unsigned char *) 0;
+ p[1] = (unsigned char *) &pcmcia_mem[port];
+
+ for(k = 0; k < 2; k++)
+ c = inba(p[k]);
+
+ return c;
+}
+
+unsigned short inwa(volatile unsigned short *address)
+{
+ __asm__ volatile("eieio");
+ return (*address);
+}
+
+unsigned short inw(int port)
+{
+ unsigned short *p[2];
+ int k;
+ unsigned short c;
+
+ p[0] = (unsigned short *) 0;
+ p[1] = (unsigned short *) &pcmcia_mem[port];
+
+ for(k = 0; k < 2; k++)
+ c = inwa(p[k]);
+
+ return c;
+}
+
+void outb(int port, char val)
+{
+ int k;
+
+ for(k = 0; k < 2; k++)
+ if(k)
+ {
+ __asm__ volatile("eieio");
+ pcmcia_mem[port] = val;
+ }
+ else
+ inba((unsigned char *) 0);
+}
+
+void
+input_swap_data(uint *sect_buf, int words)
+{
+ ushort *dbuf;
+ ushort s;
+
+ dbuf = (ushort *)sect_buf;
+ while (words--) {
+ s = inw(0);
+ *dbuf++ = ld_le16(&s);
+ s = inw(0);
+ *dbuf++ = ld_le16(&s);
+ }
+}
+
+void
+input_data(uint *sect_buf, int words)
+{
+ ushort *dbuf;
+
+ dbuf = (ushort *)sect_buf;
+ while (words--) {
+ *dbuf++ = inw(0);
+ *dbuf++ = inw(0);
+ }
+}
+
+#else /* CONFIG_DISK_ATA_PCMCIABUG */
+
+void
+outb(int port, char val)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ pcmcia_mem[port] = val;
+}
+
+unsigned char
+inb(int port)
+{
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ return (pcmcia_mem[port]);
+}
+
+void
+input_swap_data(uint *sect_buf, int words)
+{
+ ushort *dbuf;
+ volatile ushort *pbuf;
+
+ pbuf = (ushort *)pcmcia_mem;
+ dbuf = (ushort *)sect_buf;
+ while (words--) {
+ *dbuf++ = ld_le16(pbuf);
+ *dbuf++ = ld_le16(pbuf);
+ }
+}
+
+void
+input_data(uint *sect_buf, int words)
+{
+ ushort *dbuf;
+ volatile ushort *pbuf;
+
+ pbuf = (ushort *)pcmcia_mem;
+ dbuf = (ushort *)sect_buf;
+ while (words--) {
+ __asm__ volatile ("eieio");
+ *dbuf++ = *pbuf;
+ __asm__ volatile ("eieio");
+ *dbuf++ = *pbuf;
+ }
+}
+
+#endif /* CONFIG_DISK_ATA_PCMCIABUG */
+
+uint ata_identbuf[ATA_SECTORWORDS];
+
+char *ata_identify(void)
+{
+ u_char stat, *ip;
+ int k;
+
+ if(!ata_enabled)
+ return NULL;
+
+ /* XXX: We use a real harddisk drive; wait 5sec for spin-up */
+ udelay(1000000);
+
+ /* Select drive 0.
+ */
+ outb(DRIVE_HEAD, 0);
+ udelay(500);
+
+ stat = inb(ALT_STATUS);
+ if (!(OK_STAT(stat,READY_STAT,BUSY_STAT))) {
+ printf("Card Not Ready 0x%x\n", stat);
+ return NULL;
+ }
+
+ /* Ask for identify.
+ */
+ outb(STATUS_COMMAND, HD_IDENT);
+ do {
+ udelay(500);
+ stat = inb(ALT_STATUS);
+ } while (stat & BUSY_STAT);
+
+ udelay(500);
+ stat = GET_STAT();
+ if (!(OK_STAT(stat,DRQ_STAT,BAD_R_STAT))) {
+ printf("Ident and no IRQ (0x%x)\n",stat);
+ return NULL;
+ }
+ input_swap_data(ata_identbuf, ATA_SECTORWORDS);
+ (void) GET_STAT(); /* Clear IRQ */
+ ip = (u_char *)ata_identbuf;
+ ip += 27*2;
+
+ for(k = 39; k <= 0; k--)
+ if(ip[k] == ' ' || ip[k] == 0)
+ ip[k] = 0;
+ else
+ break;
+
+ while(*ip == ' ')
+ ip++;
+
+ return ip;
+}
+
+int ata_read(__u32 blocknr, __u32 numberofblocks, void *buffer)
+{
+ u_char stat;
+ uint lba;
+ __u32 *destbuf = buffer;
+
+#if 0
+ printf("ata: reading %u blocks with start from %u\n",
+ numberofblocks, blocknr);
+#endif
+
+ lba = blocknr;
+
+ while (numberofblocks--)
+ {
+ outb(SECTOR_COUNT, 1);
+ outb(LBA_LOW, (lba & 0xff));
+ outb(LBA_MID, ((lba >> 8) & 0xff));
+ outb(LBA_HIGH, ((lba >> 16) & 0xff));
+ outb(DRIVE_HEAD, LBA_SEL);
+ outb(STATUS_COMMAND, HD_READ);
+
+ do
+ {
+ udelay(5);
+ stat = inb(ALT_STATUS);
+ } while (stat & BUSY_STAT);
+
+ while (!(OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)))
+ {
+ printf("Boot READ and no IRQ...boot failed.\n");
+ return -1 ;
+ }
+
+ input_data(destbuf, ATA_SECTORWORDS);
+ (void) GET_STAT(); /* Clear IRQ */
+ destbuf += ATA_SECTORWORDS;
+ lba++;
+ }
+ return 0;
+}
+
+// vim: ts=4 noexpandtab cino=>4 cindent
--- /dev/null
+/*
+ * ata.h
+ *
+ * Dan Malek <dmalec@jlc.net> wrote the main code
+ * Magnus Damm <damm@bitsmart.com> made a pcmcia bug workaround
+ */
+
+#ifndef __ATA_H__
+#define __ATA_H__ 1
+
+#include "romsys/types.h"
+#include "config.h"
+
+/* ATA Flash registers.
+*/
+#define DATA_REG 0
+#define ERROR_REG 1
+#define SECTOR_COUNT 2
+#define SECTOR_NUM 3
+#define CYLINDER_LOW 4
+#define CYLINDER_HIGH 5
+#define DRIVE_HEAD 6
+#define STATUS_COMMAND 7
+#define DEV_CTL 0x0e
+#define ALT_STATUS DEV_CTL
+#define LBA_LOW 3
+#define LBA_MID 4
+#define LBA_HIGH 5
+#define LBA_SEL 0xe0
+
+/* Bits of HD_STATUS */
+#define ERR_STAT 0x01
+#define INDEX_STAT 0x02
+#define ECC_STAT 0x04 /* Corrected error */
+#define DRQ_STAT 0x08
+#define SEEK_STAT 0x10
+#define WRERR_STAT 0x20
+#define READY_STAT 0x40
+#define BUSY_STAT 0x80
+
+/* Values for HD_COMMAND */
+#define HD_READ 0x20
+#define HD_IDENT 0xec
+
+#define GET_ERR() inb(STATUS_COMMAND)
+#define GET_STAT() inb(STATUS_COMMAND)
+#define OK_STAT(stat,good,bad) (((stat)&((good)|(bad)))==(good))
+#define BAD_R_STAT (BUSY_STAT | ERR_STAT)
+#define BAD_W_STAT (BAD_R_STAT | WRERR_STAT)
+#define BAD_STAT (BAD_R_STAT | DRQ_STAT)
+#define DRIVE_READY (READY_STAT | SEEK_STAT)
+#define DATA_READY (DRQ_STAT)
+
+#define ATA_BLOCKSIZE 512 /* bytes */
+#define ATA_BLOCKSIZESHIFT 9 /* 2 ^ ATA_BLOCKSIZESHIFT = 512 */
+#define ATA_SECTORWORDS (512 / 4)
+
+int ata_read(__u32 blocknr, __u32 numberofblocks, void *buffer);
+char *ata_identify(void);
+
+#endif /* __ATA_H__ */
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 "romfuncs.h"
+#include "fs/file.h"
+
+const struct disk_devs_struct disk_devs[] =
+{
+ { "no disk found", NULL, NULL },
+#ifdef CONFIG_DISK_ROM
+ { "rom", rom_read, rom_identify },
+#endif
+#ifdef CONFIG_DISK_ATA
+ { "ata", ata_read, ata_identify },
+#endif
+};
+
+#define DISK_NODEVS (sizeof(disk_devs)/sizeof(struct disk_devs_struct))
+
+unsigned int disk_currentdev = 0;
+unsigned int disk_currentpart = 0;
+
+struct
+{
+ unsigned int status;
+ unsigned int noparts;
+ char *partname[DISK_MAXPARTS];
+ unsigned int partstatus[DISK_MAXPARTS];
+ unsigned int partstart[DISK_MAXPARTS];
+ unsigned int partsize[DISK_MAXPARTS];
+} disk_info[DISK_NODEVS];
+
+
+static int disk_selectdev(unsigned int dev, unsigned int part)
+{
+ if (dev >= DISK_NODEVS) return -1;
+
+ if (!disk_info[dev].status) return -1;
+
+ if (part > disk_info[dev].noparts) return -1;
+
+ if(!disk_info[dev].partstatus[part]) return -1;
+
+ disk_currentdev = dev;
+ disk_currentpart = part;
+
+ return 0;
+}
+
+
+static int check_fs(void)
+{
+ int fstype = file_detectfs();
+
+ if (fstype != FSTYPE_NONE) {
+ printf("Found %s filesystem\n", file_getfsname(fstype));
+ return 0;
+ }
+
+ return -1;
+}
+
+
+int disk_read(__u32 blocknr, __u32 numberofblocks, void *buffer)
+{
+ unsigned int block = blocknr + disk_info[disk_currentdev].partstart[disk_currentpart];
+#if 0
+ printf("disk_read(%u, %u, buf) -> %u\n", blocknr, numberofblocks, block);
+ printf("dev = %u, part = %u\n", disk_currentdev, disk_currentpart);
+#endif
+ return disk_devs[disk_currentdev].read(block, numberofblocks, buffer);
+}
+
+int disk_ident(void)
+{
+ unsigned int k, m;
+ int gotpart = 0, gotboot = 0;
+ int defdev = 1, defpart = 0;
+
+ printf("\nBoot device list:");
+
+ for (k = defdev; k < DISK_NODEVS; k++) {
+ disk_info[k].partname[0] = disk_devs[k].identify();
+ if (disk_info[k].partname[0] == NULL) continue;
+
+ printf("\n %s: %s\n", disk_devs[k].name, disk_info[k].partname[0]);
+
+ disk_info[k].status = 1; /* ok */
+
+ disk_info[k].noparts = 0;
+ disk_info[k].partstatus[0] = 1;
+ disk_info[k].partstart[0] = 0;
+ disk_info[k].partsize[0] = 0;
+
+ disk_selectdev(k, 0);
+
+ if (part_msdos_identify() != 0)
+ continue;
+
+ printf(" Part Start Size Name\n");
+ for (m = 1; m < DISK_MAXPARTS; m++)
+ {
+ int bootable;
+ if (!part_msdos_getinfo(m,
+ &disk_info[k].partname[m],
+ &disk_info[k].partstatus[m],
+ &disk_info[k].partstart[m],
+ &disk_info[k].partsize[m],
+ &bootable))
+ {
+ printf(" %2u: %8u %8u %s\n", m,
+ disk_info[k].partstart[m],
+ disk_info[k].partsize[m],
+ disk_info[k].partname[m]);
+ disk_info[k].noparts++;
+ if (disk_info[k].partstatus[m] && !gotboot && (!gotpart || bootable))
+ {
+ defdev = k;
+ defpart = m;
+ gotpart = 1;
+ gotboot = bootable;
+ }
+ }
+ }
+ }
+ printf("\n");
+
+ disk_selectdev(defdev, defpart);
+
+ check_fs();
+
+ return 0;
+}
+
+/* Read one or more sectors from the flash card. The block numbers
+ * are logical (start at 1), and are based upon the block size. We
+ * assume (correctly for now) that size is a multiple of our sector size.
+ */
+
+void
+rom_bread(void *bp, __u32 block, __u32 size)
+{
+ uint nsect;
+
+
+ // printf("rom_bread(bp, %u, %u)\n", block, size);
+ /* Block numbers are logical, starting at 1.
+ */
+ //block--; nah
+
+ /* We use 512 byte sectors.
+ */
+ nsect = size / 512;
+
+ block = (block * nsect); //damm
+
+ if(disk_read(block, nsect, bp) == -1)
+ printf("cannot read from dev %u, part %u, block %u, nsect %u\n",
+ disk_currentdev, disk_currentpart, block, nsect);
+
+}
+
+
+extern char *params[];
+extern int nparams;
+
+
+/* Load blocks from disk into memory.
+ * disk_load host_addr blocknr noblocks
+ */
+void
+disk_load(void)
+{
+ ulong bp, i, b;
+
+ if (nparams != 3) {
+ printf("\nUsage: disk_load host_addr blocknr noblocks\n");
+ printf(" --> all values in HEX\n");
+ return;
+ }
+
+ asc_to_hex(params[0], &bp);
+ asc_to_hex(params[1], &b);
+ asc_to_hex(params[2], &i);
+
+ disk_read(b, i, (void*)bp);
+}
+
+int disk_dev(void)
+{
+ uint b, t;
+ ulong i;
+
+ i = 1;
+
+ if ((nparams > 2) || (nparams == 0))
+ {
+ printf("\nUsage: disk_dev devname partition\n");
+ printf(" --> values in HEX\n");
+ return -1;
+ }
+
+ for(t = 1; t < DISK_NODEVS; t++)
+ if(!strncmp(params[0],disk_devs[t].name, 3))
+ b = t;
+
+ asc_to_hex(params[1], &i);
+
+ t = disk_selectdev(b, i);
+
+ if (t != 0)
+ {
+ printf("cannot set device/partition\n");
+ return -1;
+ }
+
+ check_fs();
+
+ return 0;
+}
+
+void disk_init(uint status)
+{
+ if(status & PCMCIA_PRESENT)
+ ata_enabled = 1;
+ ata_enabled = 1;
+ disk_ident(); // initialize too
+
+#ifdef CONFIG_DISK_DEFAULTDEV
+
+#ifndef CONFIG_DISK_DEFAULTPART
+#define CONFIG_DISK_DEFAULTPART "0"
+#endif
+
+ printf("Setting default dev/part to %s %s\n",
+ CONFIG_DISK_DEFAULTDEV, CONFIG_DISK_DEFAULTPART);
+
+ params[0] = CONFIG_DISK_DEFAULTDEV;
+ params[1] = CONFIG_DISK_DEFAULTPART;
+ nparams = 2;
+
+ disk_dev();
+#endif
+}
+
+// vim: ts=4 noexpandtab cino=>4 cindent
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 __DISK_H__
+#define __DISK_H__ 1
+
+#include "ata.h"
+#include "rom.h"
+
+#define DISK_MAXPARTS 8
+
+struct disk_devs_struct
+{
+ char *name;
+ int (*read)(__u32, __u32, void *);
+ char *(*identify)(void);
+};
+
+extern const struct disk_devs_struct disk_devs[];
+
+extern uint disk_currentdev;
+extern uint disk_currentpart;
+
+int disk_ident(void);
+void disk_load(void);
+int disk_dev(void);
+int disk_read(__u32 blocknr, __u32 numberofblocks, void *buffer);
+void rom_bread(void *bp, __u32 block, __u32 size);
+void disk_init(uint status);
+
+#endif /* __DISK_H__ */
+
+// vim: ts=4 noexpandtab cino=>4 cindent
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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
+ */
+
+/*
+ * Write an OSF partition to the first sector of the flash disk.
+ * modified by Magnus Damm for MSDOS support
+ */
+#include "romfuncs.h"
+#include <asm/unaligned.h>
+/* XXX: __fswab16 is missing while compiling with -O0 */
+#include <linux/byteorder/swab.h>
+
+struct partition {
+ __u8 boot_ind; /* 0x80 - active */
+ __u8 head; /* starting head */
+ __u8 sector; /* starting sector */
+ __u8 cyl; /* starting cylinder */
+ __u8 sys_ind; /* What partition type */
+ __u8 end_head; /* end head */
+ __u8 end_sector; /* end sector */
+ __u8 end_cyl; /* end cylinder */
+ __u32 start_sect; /* starting sector counting from 0 */
+ __u32 nr_sects; /* nr of sectors in partition */
+} __attribute__((packed));
+
+
+
+#define BOOT_IND(p) (get_unaligned(&p->boot_ind))
+#define SYS_IND(p) (get_unaligned(&p->sys_ind))
+#define NR_SECTS(p) ({ __typeof__(p->nr_sects) __a = \
+ get_unaligned(&p->nr_sects); \
+ le32_to_cpu(__a); \
+ })
+
+#define START_SECT(p) ({ __typeof__(p->start_sect) __a = \
+ get_unaligned(&p->start_sect); \
+ le32_to_cpu(__a); \
+ })
+
+
+#define MSDOS_LABEL_MAGIC 0xAA55
+
+/* this code reads and compares the msdos partitiontable */
+/* code inspired from linux/kernel/genhd.c */
+
+int part_msdos_identify(void)
+{
+ unsigned int sectbuf[512/4];
+
+ disk_read(0, 1, sectbuf); /* read first sector */
+
+ if(*(unsigned short *) (0x1fe + (__u8 *) sectbuf)
+ != cpu_to_le16(MSDOS_LABEL_MAGIC))
+ return -1;
+
+ printf(" MSDOS partition table\n");
+
+ return 0;
+}
+
+
+int part_msdos_getinfo(unsigned int part, char **part_name,
+ unsigned int *part_status, unsigned int *part_start,
+ unsigned int *part_size, int *bootable)
+{
+ struct partition *p;
+ __u8 sectbuf[512];
+ __u8 status;
+ int ret = 0;
+
+ if ((part > 4) || (part == 0)) return -1;
+
+ disk_read(0, 1, sectbuf); /* read first sector */
+
+ p = ((struct partition *) (0x1be + (__u8 *) sectbuf)) + part - 1;
+
+ if (!NR_SECTS(p)) {
+ ret = -1;
+ goto out;
+ }
+
+ status = p->sys_ind;
+
+ switch (status) {
+ case 0x05 :
+ case 0x0f :
+ case 0x85 : *part_name = "Extended (unsupported)"; status = 0; break;
+ case 0x01 : *part_name = "FAT12"; break;
+ case 0x04 :
+ case 0x06 :
+ case 0x0e : *part_name = "FAT16"; break;
+ case 0x0b :
+ case 0x0c : *part_name = "FAT32"; break;
+ case 0x82 : *part_name = "Linux swap"; status = 0; break;
+ case 0x83 : *part_name = "Linux"; break;
+ default : *part_name = "Unknown"; status = 0;
+ }
+
+ *part_status = status;
+
+ *part_start = START_SECT(p); /* + 2; */
+
+ *part_size = NR_SECTS(p);
+
+ *bootable = !!(p->boot_ind);
+
+ out:
+#ifdef DEBUG
+ printf("sys: %u, start: %u, size: %u, boot: %u\n",
+ status, *part_start, *part_size, *bootable);
+#endif
+
+ return ret;
+}
+
+#if 0
+// damm
+
+struct disklabel {
+ unsigned int d_magic;
+ ushort d_type,d_subtype;
+ u_char d_typename[16];
+ u_char d_packname[16];
+ unsigned int d_secsize;
+ unsigned int d_nsectors;
+ unsigned int d_ntracks;
+ unsigned int d_ncylinders;
+ unsigned int d_secpercyl;
+ unsigned int d_secprtunit;
+ ushort d_sparespertrack;
+ ushort d_sparespercyl;
+ unsigned int d_acylinders;
+ ushort d_rpm, d_interleave, d_trackskew, d_cylskew;
+ unsigned int d_headswitch, d_trkseek, d_flags;
+ unsigned int d_drivedata[5];
+ unsigned int d_spare[5];
+ unsigned int d_magic2;
+ ushort d_checksum;
+ ushort d_npartitions;
+ unsigned int d_bbsize, d_sbsize;
+ struct d_partition {
+ unsigned int p_size;
+ unsigned int p_offset;
+ unsigned int p_fsize;
+ u_char p_fstype;
+ u_char p_frag;
+ ushort p_cpg;
+ } d_partitions[8];
+};
+#define DISKLABELMAGIC (0x82564557UL)
+
+struct sect_buf {
+ unsigned int pad[16];
+ struct disklabel dl;
+};
+
+char part_sect[512];
+extern void rom_bread(char *addr, int blkno, int size);
+int part_start;
+
+
+int
+read_partition()
+{
+ struct sect_buf *sb;
+ struct disklabel *dp;
+ struct d_partition *partition;
+ int i;
+
+ sb = (struct sect_buf *)part_sect;
+ dp = &(sb->dl);
+
+ /* Read the partition sector only once. If someone has assigned
+ * a partition for use, we have obviously been here before.
+ */
+ if (part_start == 0) {
+ rom_bread(part_sect, 1, 512);
+
+ partition = dp->d_partitions;
+ if (dp->d_magic != DISKLABELMAGIC) {
+ printf("magic: %08x\n", dp->d_magic);
+ return 0;
+ }
+ if (dp->d_magic2 != DISKLABELMAGIC) {
+ printf("magic2: %08x\n", dp->d_magic2);
+ return 0;
+ }
+ printf("%s\n", (char *)(sb->pad));
+ for (i = 0 ; i < dp->d_npartitions; i++, partition++) {
+ if (partition->p_size)
+ printf("Part %d, %d:%d\n", i, partition->p_offset,
+ partition->p_size);
+ }
+ }
+ return (dp->d_npartitions);
+}
+
+void
+activate_partition(int partno)
+{
+ struct sect_buf *sb;
+ struct disklabel *dp;
+ struct d_partition *partition;
+
+ sb = (struct sect_buf *)part_sect;
+ dp = &(sb->dl);
+ if (partno >= dp->d_npartitions) {
+ printf("Illegal partition %d (only %d)\n", partno,
+ dp->d_npartitions);
+ return;
+ }
+ partition = dp->d_partitions;
+ partition += partno;
+ if (partition->p_size) {
+ part_start = partition->p_offset;
+ }
+ else {
+ printf("Parition %d is not allocated\n", partno);
+ }
+}
+
+#endif
+
+// vim: ts=4 expandtab cino=>4 cindent
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 "rom.h"
+
+/* read a block from the rom */
+
+int rom_read(__u32 blocknr, __u32 numberofblocks, void *buffer)
+{
+ uint *src = (uint *)(ROM_DISKSTART + (blocknr << ROM_BLOCKSIZESHIFT));
+ uint *dst = (uint *)buffer;
+ uint n = (numberofblocks << (ROM_BLOCKSIZESHIFT - 2));
+
+#if 0
+ printf("rom: reading %u bytes from 0x%08x\n", n << 2, (uint) src);
+#endif
+
+ while(n--)
+ *dst++ = *src++;
+
+ return 0;
+}
+
+char *rom_identify(void)
+{
+ /* no check done nowhere */
+
+ return "rom_disk";
+}
+
+// vim: ts=4 noexpandtab cino=>4 cindent
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 __ROM_H__
+#define __ROM_H__ 1
+
+#include "romsys/types.h"
+#include "config.h"
+
+#define ROM_DISKSTART (0x20000 + (BR0_VALUE & 0xffff0000))
+#define ROM_BLOCKSIZE 512 /* bytes */
+#define ROM_BLOCKSIZESHIFT 9 /* 2 ^ ROM_BLOCKSIZESHIFT = 512 */
+
+int rom_read(__u32 blocknr, __u32 numberofblocks, void *buffer);
+char *rom_identify(void);
+
+#endif /* __ROM_H__ */
+
+// vim: ts=4 noexpandtab cino=>4 cindent
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 "romfuncs.h"
+#include "fs/file.h"
+#include <elf.h>
+
+extern char *params[];
+extern int nparams;
+
+void start_elf(int onfs, char *, uint *, bd_t *);
+
+/* Physical address to load the compressed kernel image. */
+#define DEFAULT_LOAD ((uint *)0x00200000)
+
+#define PGSZ 4096
+#define roundup(x) (((x) + (PGSZ-1)) & ~(PGSZ-1))
+
+void elf_bootz(bd_t *bdinfo)
+{
+ u_char stat;
+ char *zimagename;
+
+ /* This is fine when everything works, but we should probably
+ * disable the I-cache if we return due to unsuccessful boot.
+ */
+ //do_cache_onoff(0, 1);
+
+#if 0
+ /* Select drive 0.
+ */
+ outb(DRIVE_HEAD, 0);
+ udelay(500);
+ stat = inb(ALT_STATUS);
+ if (!(OK_STAT(stat,READY_STAT,BUSY_STAT))) {
+ printf("Card Not Ready 0x%x\n", stat);
+ return;
+ }
+#endif
+
+ /* Check for command parameters. Someone could enter:
+ * bootz filename, or
+ * bootz partition filename. */
+
+ if (nparams == 1) {
+ zimagename = params[0];
+ } else {
+ zimagename = "zImage";
+ }
+
+ /* If we have a valid parition, it must also have a
+ * filesystem. If not, we are done ('cause there can't
+ * be an ELF image there either).
+ */
+ if (file_detectfs() == FSTYPE_NONE) {
+ printf("No filesystem found\n");
+ goto try_raw;
+ }
+
+ /* Read the first block, then let the ELF loader to its
+ * thing.
+ */
+ if (file_read(zimagename, DEFAULT_LOAD, FS_BLOCK_SIZE) > 0) {
+ start_elf(1, zimagename, DEFAULT_LOAD, bdinfo);
+ }
+
+ printf("Can't find/load %s\n", zimagename);
+ goto out;
+
+ try_raw:
+
+ /* Read the first sector since it may contain the ELF header.
+ */
+ rom_bread(DEFAULT_LOAD, 1, 512);
+ start_elf(0, "Raw Partition", DEFAULT_LOAD, bdinfo);
+ out:
+ printf("Unable to boot\n\n");
+
+}
+
+
+void bootvm(bd_t *bdinfo, int mode) // mode 0 = normal, mode 1 initrd
+{
+ u_char stat;
+ char *vmlinuxname = "vmlinux";
+ char *initrdname = "initrd";
+ int size, vmsize, rdsize;
+ int vmaddress, rdaddress, bdaddress;
+ uint *src, *dest, *end;
+ void (*start_loc)(bd_t *, uint, uint, uint, uint);
+
+#if 0
+ /* Select drive 0.
+ */
+ outb(DRIVE_HEAD, 0);
+ udelay(500);
+ stat = inb(ALT_STATUS);
+ if (!(OK_STAT(stat,READY_STAT,BUSY_STAT))) {
+ printf("Card Not Ready 0x%x\n", stat);
+ return;
+ }
+#endif
+ /* Check for command parameters. Someone could enter:
+ * bootvm filename or
+ * bootvmi zimagename initrdname
+ */
+
+ if(mode)
+ { // boot with initrd
+ if (nparams == 1)
+ {
+ vmlinuxname = params[0];
+ }
+
+ if (nparams == 2)
+ {
+ vmlinuxname = params[0];
+ initrdname = params[1];
+ }
+ }
+ else
+ { // boot without initrd
+ if (nparams == 1)
+ vmlinuxname = params[0];
+ }
+
+ /* If we have a valid parition, it must also have a
+ * filesystem. If not, we are done ('cause there can't
+ * be an ELF image there either).
+ */
+ if (file_detectfs() == FSTYPE_NONE) {
+ printf("No filesystem found\n");
+ return;
+ }
+
+ /* load vmlinux */
+
+ vmaddress = (uint)DEFAULT_LOAD;
+
+ if ((vmsize = file_read(vmlinuxname, (void*)vmaddress, 0)) <= 0) {
+ return;
+ }
+
+ printf("0x%08x 0x%08x '%s'\n",
+ vmaddress, vmaddress + vmsize, vmlinuxname);
+
+
+ /* relocate board info */
+
+ bdaddress = vmaddress + vmsize;
+
+ if(bdaddress & 3)
+ bdaddress = (bdaddress & ~3) + 4;
+
+ size = sizeof(bd_t) >> 2;
+
+ dest = (uint *) bdaddress;
+ src = (uint *) bdinfo;
+
+ while(size--)
+ *dest++ = *src++;
+
+ printf("0x%08x 0x%08x board information\n",
+ bdaddress, bdaddress + sizeof(bd_t));
+
+
+ /* load initrd */
+
+ if(mode)
+ {
+ rdaddress = bdaddress + sizeof(bd_t);
+
+ if ((rdsize = file_read(initrdname, (void*)rdaddress, 0)) <= 0) {
+ return;
+ }
+
+ printf("0x%08x 0x%08x '%s'\n",
+ rdaddress, rdaddress + rdsize, initrdname);
+ }
+ else
+ {
+ rdsize = 0;
+ rdaddress = 0;
+ }
+
+
+ /* now when we relocate the vmlinux and the board info,
+ * we screw up the bss, this is dirty */
+
+ dest = (uint *) 0;
+ src = (uint *) (vmaddress + 0x10000);
+
+ end = (uint *) (bdaddress + sizeof(bd_t));
+
+ size = ((uint) end) - ((uint) src);
+
+ while(src <= end)
+ *dest++ = *src++;
+
+ printf("0x%08x 0x%08x relocated vmlinux and board info\n",
+ 0, size);
+
+ bdinfo = (bd_t *) (size - sizeof(bd_t));
+
+
+ /* relocate initrd to top of mem */
+
+ if(rdaddress)
+ {
+
+ if(rdsize & 3)
+ rdsize = (rdsize & ~3) + 4;
+
+ /* copy backwards */
+
+ dest = (uint *) (bdinfo->bi_memsize - 4);
+ src = (uint *) (rdaddress + rdsize - 4);
+
+ end = (uint *) (rdaddress);
+
+ rdaddress = (uint) end;
+
+ while(src >= end)
+ *dest-- = *src--;
+
+ printf("0x%08x 0x%08x relocated initrd\n",
+ rdaddress, bdinfo->bi_memsize);
+
+ }
+
+
+ /* start the rest */
+
+ start_loc = (void ((*)())) *((uint *)0);
+
+ do_cache_onoff(0, 1); // turn off cache
+
+ if(mode)
+ size = vmsize;
+ else
+ size = 0;
+
+ printf("(0x%08x)(0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x)\n",
+ (uint) start_loc, (uint) bdinfo, rdaddress, rdsize, 0, 0);
+
+ (*start_loc)(bdinfo, rdaddress, rdsize, 0, 0);
+
+ return;
+}
+
+void
+start_elf(int onfs, char *name, uint *bp, bd_t *bdinfo)
+{
+ uint i, lba, entry, paddr, zstart;
+ void (*start_loc)(bd_t *);
+ Elf32_Ehdr *eh;
+ Elf32_Shdr *sh;
+ Elf32_Phdr *ph;
+
+ /* To boot a compressed Linux image (zImage), we have to
+ * load the image out of the way of the code that does
+ * the decompress. The compressed image is a gzip file with
+ * some code tacked on the front to uncompress it. If you
+ * load the image and jump to the start address, the bss space
+ * will overlap the start of the compressed image and running
+ * the code will trash the file.
+ * The decompress code will figure out that it is not running
+ * at it's link address and relocate itself.
+ */
+ eh = (Elf32_Ehdr *)bp;
+ sh = (Elf32_Shdr *)((unsigned long)eh + eh->e_shoff );
+ ph = (Elf32_Phdr *)((unsigned long)eh + eh->e_phoff );
+
+ if ((eh->e_ident[EI_MAG0] != ELFMAG0) ||
+ (eh->e_ident[EI_MAG1] != ELFMAG1) ||
+ (eh->e_ident[EI_MAG2] != ELFMAG2) ||
+ (eh->e_ident[EI_MAG3] != ELFMAG3)) {
+ printf("%s is not an ELF image\n", name);
+ return;
+ }
+
+ entry = eh->e_entry;
+ paddr = ph->p_paddr;
+ zstart = ph->p_paddr + roundup(ph->p_memsz);
+
+ printf("\nentry 0x%x, phoff 0x%x, shoff 0x%x\n",
+ eh->e_entry, eh->e_phoff, eh->e_shoff);
+
+ printf("phnum 0x%x, shnum 0x%x\n", eh->e_phnum, eh->e_shnum);
+
+ printf("p_offset 0x%x, p_vaddr 0x%x, p_paddr 0x%x\n",
+ ph->p_offset, ph->p_vaddr, ph->p_paddr);
+
+ printf("p_filesz 0x%x, p_memsz 0x%x\n", ph->p_filesz, ph->p_memsz);
+
+#if 0
+ bp = (uint *)((uint)(ph->p_paddr) - (uint)(ph->p_offset));
+#endif
+ bp = (uint *)zstart;
+ printf("Loading at 0x%x\n", zstart);
+
+ /* If this is a real file, load it accordingly. If raw
+ * partition, hope this is big enough.
+ */
+ if (onfs) {
+ if (file_read(name, bp, 0) == 0) {
+ printf("Can't load all of %s.\n", name);
+ return;
+ }
+ }
+ else {
+ lba = 1;
+ i = (500000/512);
+ while (i > 0) {
+ rom_bread(bp, lba, 512);
+ bp += (512/4);
+ lba++;
+ i--;
+ }
+ }
+
+ /* Reset ELF header pointer to the newly loaded image. The
+ * old one may have been written over by loading.
+ */
+ eh = (Elf32_Ehdr *)bp;
+ sh = (Elf32_Shdr *)((unsigned long)eh + eh->e_shoff );
+ ph = (Elf32_Phdr *)((unsigned long)eh + eh->e_phoff );
+
+ /* This should be OK since the enable I-cache function also
+ * invalidates the cache. We are jumping to instructions in
+ * a space we have never been before, so there shouldn't be
+ * anything in the cache.
+ */
+ start_loc = (void ((*)()))(zstart + ph->p_offset + (entry - paddr));
+ printf("Starting 0x%x\n", (uint)start_loc);
+ (*start_loc)(bdinfo);
+
+ /* ...just in case
+ */
+ return;
+}
+
+// vim: ts=4 noexpandtab cino=>4 cindent
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 _ELF_H
+#define _ELF_H
+
+#include "romsys/types.h"
+
+
+/* 32-bit ELF base types. */
+typedef __u32 Elf32_Addr;
+typedef __u16 Elf32_Half;
+typedef __u32 Elf32_Off;
+typedef __s32 Elf32_Sword;
+typedef __u32 Elf32_Word;
+
+/* 64-bit ELF base types. */
+typedef __u64 Elf64_Addr;
+typedef __u16 Elf64_Half;
+typedef __s16 Elf64_SHalf;
+typedef __u64 Elf64_Off;
+typedef __s64 Elf64_Sword;
+typedef __u64 Elf64_Word;
+
+
+#define EI_NIDENT 16
+
+typedef struct elf32_hdr{
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry; /* Entry point */
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+
+typedef struct elf32_phdr{
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+typedef struct elf64_phdr {
+ __s32 p_type;
+ __s32 p_flags;
+ Elf64_Off p_offset; /* Segment file offset */
+ Elf64_Addr p_vaddr; /* Segment virtual address */
+ Elf64_Addr p_paddr; /* Segment physical address */
+ Elf64_Word p_filesz; /* Segment size in file */
+ Elf64_Word p_memsz; /* Segment size in memory */
+ Elf64_Word p_align; /* Segment alignment, file & memory */
+} Elf64_Phdr;
+
+
+typedef struct {
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+typedef struct elf64_shdr {
+ Elf32_Word sh_name; /* Section name, index in string tbl (yes Elf32) */
+ Elf32_Word sh_type; /* Type of section (yes Elf32) */
+ Elf64_Word sh_flags; /* Miscellaneous section attributes */
+ Elf64_Addr sh_addr; /* Section virtual addr at execution */
+ Elf64_Off sh_offset; /* Section file offset */
+ Elf64_Word sh_size; /* Size of section in bytes */
+ Elf32_Word sh_link; /* Index of another section (yes Elf32) */
+ Elf32_Word sh_info; /* Additional section information (yes Elf32) */
+ Elf64_Word sh_addralign; /* Section alignment */
+ Elf64_Word sh_entsize; /* Entry size if section holds table */
+} Elf64_Shdr;
+
+#define EI_MAG0 0 /* e_ident[] indexes */
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+#define EI_VERSION 6
+#define EI_PAD 7
+
+#define ELFMAG0 0x7f /* EI_MAG */
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#endif /* _ELF_H */
+
+// vim: ts=4 noexpandtab cino=>4 cindent
-/*
- * linux/arch/ppc/mm/extable.c
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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.
*
- * from linux/arch/i386/mm/extable.c
+ * 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 <sys/types.h>
+#include "romfuncs.h"
/*
* The exception table consists of pairs of addresses: the first is the
/* There is only the kernel to search. */
ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
if (ex_tab_message)
- printf("Bus Fault @ 0x%08x, fixup 0x%08x\n", addr, ret);
+ printf("Bus Fault @ 0x%08lx, fixup 0x%08lx\n", addr, ret);
if (ret) return ret;
return 0;
}
+
+// vim: ts=4 noexpandtab cino=>4 cindent
--- /dev/null
+#
+# Makefile for the FADS ROM filesystems
+#
+
+TOPLEVEL = ..
+
+all: libfs.a
+
+include $(TOPLEVEL)/Make.config
+
+OBJS = file.o ext2.o fat.o
+
+libfs.a: $(OBJS)
+ $(AR) cr $@ $(OBJS)
+
+testit: clean
+ make file.o CC=gcc "CFLAGS=-DUSE_EXT2FS=0 -Wall -O2 -g -Itest -I. -I.."
+ make fat.o CC=gcc "CFLAGS=-Wall -O2 -g -Itest -I. -I.."
+ make test/test.o CC=gcc "CFLAGS=-Wall -O2 -g -Itest -I."
+ gcc -o $@ test/test.o file.o fat.o
+
+clean:
+ rm -f $(OBJS) libfs.a testit test/test.o
--- /dev/null
+/*
+ * from linux/fs/ext2/inode.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from linux/fs/minix/inode.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * Goal-directed block allocation by Stephen Tweedie
+ * (sct@dcs.ed.ac.uk), 1993, 1998
+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (davem@caip.rutgers.edu), 1995
+ * 64-bit file support on 64-bit platforms by Jakub Jelinek
+ * (jj@sunsite.ms.mff.cuni.cz)
+ */
+#include "romfuncs.h"
+#include "ext2.h"
+
+/* super.c dir.c inode.c */
+
+#include <linux/fs.h>
+#include <linux/ext2_fs.h>
+
+#define NODEBUG
+
+#ifdef DEBUG
+#define EXT2_DPRINT(args...) printf(args)
+#else
+#define EXT2_DPRINT(args...)
+#endif
+#define EXT2_ERROR(arg) printf(arg)
+
+
+static struct inode root_inode;
+static char indblock[BLOCK_SIZE];
+static char tmp_iblk[BLOCK_SIZE];
+static struct inode read_file_inode;
+
+#define rom_inode_bmap(inode, nr) ((inode)->u.ext2_i.i_data[(nr)])
+
+static inline int
+rom_block_bmap (uint *blk, int nr)
+{
+ return le32_to_cpu(blk[nr]);
+}
+
+#if 0
+static uint tmp_bmaps[256];
+
+static int
+rom_ext2_bmap(struct inode * inode, int block)
+{
+ int i;
+ int addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
+ int addr_per_block_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb);
+
+ if (block < 0) {
+ printf ((char*)inode->i_sb, "ext2_bmap", "block < 0");
+ return 0;
+ }
+ if (block >= EXT2_NDIR_BLOCKS + addr_per_block +
+ (1 << (addr_per_block_bits * 2)) +
+ ((1 << (addr_per_block_bits * 2)) << addr_per_block_bits)) {
+ printf ((char*)inode->i_sb, "ext2_bmap", "block > big");
+ return 0;
+ }
+ if (block < EXT2_NDIR_BLOCKS)
+ return rom_inode_bmap (inode, block);
+ block -= EXT2_NDIR_BLOCKS;
+ if (block < addr_per_block) {
+ i = rom_inode_bmap (inode, EXT2_IND_BLOCK);
+ if (!i)
+ return 0;
+ rom_bread(tmp_bmaps, i, inode->i_sb->s_blocksize);
+ return rom_block_bmap(tmp_bmaps, block);
+ }
+ block -= addr_per_block;
+ if (block < (1 << (addr_per_block_bits * 2))) {
+ i = rom_inode_bmap (inode, EXT2_DIND_BLOCK);
+ if (!i)
+ return 0;
+ rom_bread(tmp_bmaps, i, inode->i_sb->s_blocksize);
+ i = rom_block_bmap(tmp_bmaps, block >> addr_per_block_bits);
+ if (!i)
+ return 0;
+ rom_bread(tmp_bmaps, i, inode->i_sb->s_blocksize);
+ return rom_block_bmap(tmp_bmaps, block & (addr_per_block - 1));
+ }
+ block -= (1 << (addr_per_block_bits * 2));
+ i = rom_inode_bmap (inode, EXT2_TIND_BLOCK);
+ if (!i)
+ return 0;
+ rom_bread(tmp_bmaps, i, inode->i_sb->s_blocksize);
+ i = rom_block_bmap (tmp_bmaps,
+ block >> (addr_per_block_bits * 2));
+ if (!i)
+ return 0;
+ rom_bread(tmp_bmaps, i, inode->i_sb->s_blocksize);
+ i = rom_block_bmap (tmp_bmaps,
+ (block >> addr_per_block_bits) & (addr_per_block - 1));
+ if (!i)
+ return 0;
+ rom_bread(tmp_bmaps, i, inode->i_sb->s_blocksize);
+ return rom_block_bmap (tmp_bmaps, block & (addr_per_block - 1));
+}
+#endif
+
+static void
+rom_inode_getblk (struct inode * inode, int nr, char *addr)
+{
+ u32 * p;
+ int tmp;
+
+ p = inode->u.ext2_i.i_data + nr;
+ tmp = *p;
+ rom_bread(addr, tmp, inode->i_sb->s_blocksize);
+}
+
+static void
+rom_block_getblk (struct inode * inode, u_char *indptr, int nr,
+ int blocksize, u_char *new_block)
+{
+ int tmp;
+ u32 * p;
+
+ p = (u32 *) indptr + nr;
+ tmp = le32_to_cpu(*p);
+ rom_bread(new_block, tmp, inode->i_sb->s_blocksize);
+}
+
+static void
+rom_ext2_getblk (struct inode *inode, int block, char *addr)
+{
+ unsigned long b;
+ unsigned long addr_per_block = EXT2_ADDR_PER_BLOCK(inode->i_sb);
+ int addr_per_block_bits = EXT2_ADDR_PER_BLOCK_BITS(inode->i_sb);
+
+ if (block < 0) {
+ printf ((char*)inode->i_sb, "ext2_getblk", "block < 0");
+ return;
+ }
+ if (block > EXT2_NDIR_BLOCKS + addr_per_block +
+ (1 << (addr_per_block_bits * 2)) +
+ ((1 << (addr_per_block_bits * 2)) << addr_per_block_bits)) {
+ printf ((char*)inode->i_sb, "ext2_getblk", "block > big");
+ return;
+ }
+
+ b = block;
+ if (block < EXT2_NDIR_BLOCKS) {
+ rom_inode_getblk (inode, block, addr);
+ return;
+ }
+ block -= EXT2_NDIR_BLOCKS;
+ if (block < addr_per_block) {
+ rom_inode_getblk (inode, EXT2_IND_BLOCK, indblock);
+ rom_block_getblk (inode, indblock, block,
+ inode->i_sb->s_blocksize, addr);
+ return;
+ }
+ block -= addr_per_block;
+ if (block < (1 << (addr_per_block_bits * 2))) {
+ rom_inode_getblk (inode, EXT2_DIND_BLOCK, indblock);
+ rom_block_getblk (inode, indblock, block >> addr_per_block_bits,
+ inode->i_sb->s_blocksize, indblock);
+ rom_block_getblk (inode, indblock, block & (addr_per_block - 1),
+ inode->i_sb->s_blocksize, addr);
+ return;
+ }
+ block -= (1 << (addr_per_block_bits * 2));
+ rom_inode_getblk (inode, EXT2_TIND_BLOCK, indblock);
+ rom_block_getblk (inode, indblock, block >> (addr_per_block_bits * 2),
+ inode->i_sb->s_blocksize, indblock);
+ rom_block_getblk (inode, indblock, (block >> addr_per_block_bits) & (addr_per_block - 1),
+ inode->i_sb->s_blocksize, indblock);
+ rom_block_getblk (inode, indblock, block & (addr_per_block - 1),
+ inode->i_sb->s_blocksize, addr);
+}
+
+
+static void
+rom_ext2_bread (struct inode *inode, int block, char *addr)
+{
+ rom_ext2_getblk (inode, block, addr);
+}
+
+
+static int
+rom_ext2_read_inode (struct inode * inode)
+{
+ struct buffer_head * bh;
+ struct ext2_inode * raw_inode;
+ unsigned long block_group;
+ unsigned long group_desc;
+ unsigned long desc;
+ unsigned long block;
+ unsigned long offset;
+ int event;
+ struct ext2_group_desc * gdp;
+
+ if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&
+ inode->i_ino != EXT2_ACL_DATA_INO &&
+ inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||
+ inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {
+ printf ((char*)inode->i_sb, "ext2_read_inode",
+ "bad inode number: %lu", inode->i_ino);
+ return -1;
+ }
+ block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);
+ if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {
+ printf ((char*)inode->i_sb, "ext2_read_inode",
+ "group >= groups count");
+ return -1;
+ }
+ group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);
+ desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);
+ gdp = (struct ext2_group_desc *) inode->i_sb->u.ext2_sb.s_group_desc[group_desc];
+ if (!gdp) {
+ printf ((char*)inode->i_sb, "ext2_read_inode",
+ "Descriptor not loaded");
+ return -1;
+ }
+
+ /*
+ * Figure out the offset within the block group inode table
+ */
+ offset = ((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) *
+ EXT2_INODE_SIZE(inode->i_sb);
+ block = le32_to_cpu(gdp[desc].bg_inode_table) +
+ (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));
+ rom_bread(tmp_iblk, block, inode->i_sb->s_blocksize);
+
+ offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1);
+ raw_inode = (struct ext2_inode *) (tmp_iblk + offset);
+
+ inode->i_mode = le16_to_cpu(raw_inode->i_mode);
+ inode->i_uid = le16_to_cpu(raw_inode->i_uid);
+ inode->i_gid = le16_to_cpu(raw_inode->i_gid);
+ inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
+ inode->i_size = le32_to_cpu(raw_inode->i_size);
+ inode->i_atime = le32_to_cpu(raw_inode->i_atime);
+ inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);
+ inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);
+ inode->u.ext2_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);
+ inode->i_blksize = PAGE_SIZE; /* This is the optimal IO size (for stat), not the fs block size */
+ inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
+ inode->i_version = ++event;
+ inode->u.ext2_i.i_new_inode = 0;
+ inode->u.ext2_i.i_flags = le32_to_cpu(raw_inode->i_flags);
+ inode->u.ext2_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);
+ inode->u.ext2_i.i_frag_no = raw_inode->i_frag;
+ inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;
+ inode->u.ext2_i.i_osync = 0;
+ inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
+ if (S_ISDIR(inode->i_mode))
+ inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);
+ else {
+ inode->u.ext2_i.i_dir_acl = 0;
+ inode->u.ext2_i.i_high_size =
+ le32_to_cpu(raw_inode->i_size_high);
+#if BITS_PER_LONG < 64
+ if (raw_inode->i_size_high)
+ inode->i_size = (__u32)-1;
+#else
+ inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high))
+ << 32;
+#endif
+ }
+ inode->u.ext2_i.i_version = le32_to_cpu(raw_inode->i_version);
+ inode->u.ext2_i.i_block_group = block_group;
+ inode->u.ext2_i.i_next_alloc_block = 0;
+ inode->u.ext2_i.i_next_alloc_goal = 0;
+ if (inode->u.ext2_i.i_prealloc_count)
+ printf ((char*)inode->i_sb, "ext2_read_inode",
+ "New inode has non-zero prealloc count!");
+ if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
+ inode->i_rdev = to_kdev_t(le32_to_cpu(raw_inode->i_block[0]));
+ else if (S_ISLNK(inode->i_mode) && !inode->i_blocks)
+ for (block = 0; block < EXT2_N_BLOCKS; block++)
+ inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];
+ else for (block = 0; block < EXT2_N_BLOCKS; block++)
+ inode->u.ext2_i.i_data[block] = le32_to_cpu(raw_inode->i_block[block]);
+ inode->i_op = NULL;
+ inode->i_attr_flags = 0;
+ if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {
+ inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS;
+ inode->i_flags |= MS_SYNCHRONOUS;
+ }
+ if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL) {
+ inode->i_attr_flags |= ATTR_FLAG_APPEND;
+ inode->i_flags |= S_APPEND;
+ }
+ if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) {
+ inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;
+ inode->i_flags |= S_IMMUTABLE;
+ }
+ if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) {
+ inode->i_attr_flags |= ATTR_FLAG_NOATIME;
+ inode->i_flags |= MS_NOATIME;
+ }
+ return 0;
+}
+
+
+
+/*
+ * linux/fs/ext2/dir.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/fs/minix/dir.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * ext2 directory handling functions
+ *
+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (davem@caip.rutgers.edu), 1995
+ */
+
+static uint filp_pos;
+static char dtmp[BLOCK_SIZE];
+
+static void
+rom_opendir()
+{
+ filp_pos = 0;
+}
+
+
+static struct ext2_dir_entry_2 *
+rom_ext2_readdir(struct inode *inode)
+{
+ unsigned long offset, blk;
+ int stored;
+ struct ext2_dir_entry_2 * de;
+ struct super_block * sb;
+
+ if (!inode || !S_ISDIR(inode->i_mode))
+ return NULL;
+ sb = inode->i_sb;
+
+ stored = 0;
+
+ offset = filp_pos & (sb->s_blocksize - 1);
+
+ while (filp_pos < inode->i_size) {
+ blk = (filp_pos) >> EXT2_BLOCK_SIZE_BITS(sb);
+ rom_ext2_bread (inode, blk, dtmp);
+
+ while (filp_pos < inode->i_size
+ && offset < sb->s_blocksize) {
+ de = (struct ext2_dir_entry_2 *) (dtmp + offset);
+ offset += le16_to_cpu(de->rec_len);
+ filp_pos += le16_to_cpu(de->rec_len);
+ if (le32_to_cpu(de->inode)) {
+ de->inode = le32_to_cpu(de->inode);
+ return de;
+ }
+ }
+ offset = 0;
+ }
+ return NULL;
+}
+
+
+int
+file_ext2_ls(const char *path)
+{
+ struct ext2_dir_entry_2 * de;
+ struct inode *ip = &root_inode;
+ int files = 0, dirs = 0;
+
+ rom_opendir();
+ while ((de = rom_ext2_readdir(ip)) != NULL) {
+ int isdir = (de->file_type == EXT2_FT_DIR);
+ char dirc;
+
+ if (isdir) {
+ dirs++;
+ dirc = '/';
+ } else {
+ files++;
+ dirc = ' ';
+ }
+ de->name[de->name_len] = '\0';
+ printf(" %s%c\n", de->name, dirc);
+ EXT2_DPRINT("%d: %s\n", de->inode, de->name);
+ }
+ printf("\n%d file(s), %d dir(s)\n\n", files, dirs);
+
+ return 0;
+}
+
+
+long
+file_ext2_read(const char *name, void *buffer, unsigned long maxsize)
+{
+ struct ext2_dir_entry_2 * de;
+ int i, nblocks, blocksize;
+ int targ_namlen;
+ struct inode *dirnode = &root_inode;
+ int reqblks = maxsize/BLOCK_SIZE;
+ __u8 *addr = buffer;
+
+ while(strlen(name))
+ if(*name == '/')
+ name++;
+ else
+ break;
+
+ targ_namlen = strlen(name);
+ rom_opendir();
+ while ((de = rom_ext2_readdir(dirnode)) != NULL) {
+ if (de->name_len != targ_namlen)
+ continue;
+ if (strncmp(de->name, name, de->name_len) == 0) {
+ read_file_inode.i_sb = dirnode->i_sb;
+ read_file_inode.i_ino = de->inode;
+ read_file_inode.i_count = 1;
+ if (rom_ext2_read_inode(&read_file_inode) < 0) {
+ printf("Can't read %s\n", name);
+ return 0;
+ }
+ printf("Size %d\n", (int)read_file_inode.i_size);
+
+ blocksize = read_file_inode.i_sb->s_blocksize;
+ nblocks = read_file_inode.i_size + blocksize - 1;
+ nblocks &= ~(blocksize - 1);
+ nblocks /= blocksize;
+
+ if (reqblks != 0)
+ nblocks = reqblks;
+
+ printf("%d blocks\n", nblocks);
+
+ for (i=0; i<nblocks; i++) {
+ rom_ext2_bread(&read_file_inode, i, addr);
+ addr += blocksize;
+ }
+
+ return read_file_inode.i_size;
+ }
+ }
+ printf("file '%s' not found\n", name);
+
+ return 0;
+}
+
+
+/*
+ * linux/fs/ext2/super.c
+ *
+ * Copyright (C) 1992, 1993, 1994, 1995
+ * Remy Card (card@masi.ibp.fr)
+ * Laboratoire MASI - Institut Blaise Pascal
+ * Universite Pierre et Marie Curie (Paris VI)
+ *
+ * from
+ *
+ * linux/fs/minix/inode.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * Big-endian to little-endian byte-swapping/bitmaps by
+ * David S. Miller (davem@caip.rutgers.edu), 1995
+ */
+
+static char sb_mem[BLOCK_SIZE];
+static struct super_block gensb;
+static int blocksize;
+
+#define log2(n) ffz(~(n))
+
+int file_ext2_detectfs(void)
+{
+ struct ext2_super_block * es;
+ struct super_block *sb;
+ unsigned long logic_sb_block = 1;
+ int db_count;
+ int i;
+
+ sb = &gensb;
+#if 0
+ if (blocksize != 0) {
+ /* Been here before, don't do it again.
+ */
+ return (struct inode *)sb->s_root;
+ }
+#endif
+ blocksize = BLOCK_SIZE;
+
+#if 0
+ if (!(bh = bread (dev, logic_sb_block, blocksize))) {
+ sb->s_dev = 0;
+ unlock_super (sb);
+ printk ("EXT2-fs: unable to read superblock\n");
+ MOD_DEC_USE_COUNT;
+ return -1;
+ }
+#else
+ rom_bread(sb_mem, logic_sb_block, blocksize);
+#endif
+ /*
+ * Note: s_es must be initialized s_es as soon as possible because
+ * some ext2 macro-instructions depend on its value
+ */
+ es = (struct ext2_super_block *) sb_mem;
+ sb->u.ext2_sb.s_es = es;
+ sb->s_magic = le16_to_cpu(es->s_magic);
+
+ if (le16_to_cpu(es->s_magic) != EXT2_SUPER_MAGIC) {
+ EXT2_DPRINT("VFS: Can't find an ext2 filesystem on flash card\n");
+ EXT2_DPRINT("magic 0x%04x, &magic = 0x%08x\n", es->s_magic,
+ (uint) &es->s_magic - (uint) es);
+ return -1;
+ }
+ if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) {
+ if (le32_to_cpu(es->s_feature_incompat) & ~EXT2_FEATURE_INCOMPAT_SUPP) {
+ printf("EXT2-fs: couldn't mount because of "
+ "unsupported optional features.\n");
+ return -1;
+ }
+ }
+
+ sb->s_blocksize_bits = le32_to_cpu(sb->u.ext2_sb.s_es->s_log_block_size) + 10;
+ sb->s_blocksize = 1 << sb->s_blocksize_bits;
+ if (sb->s_blocksize != BLOCK_SIZE) {
+ printf("Ext2-fs bad block size (%u != %u)\n", sb->s_blocksize, BLOCK_SIZE);
+ return -1;
+ }
+ if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
+ sb->u.ext2_sb.s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
+ sb->u.ext2_sb.s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
+ } else {
+ sb->u.ext2_sb.s_inode_size = le16_to_cpu(es->s_inode_size);
+ sb->u.ext2_sb.s_first_ino = le32_to_cpu(es->s_first_ino);
+ if (sb->u.ext2_sb.s_inode_size != EXT2_GOOD_OLD_INODE_SIZE) {
+ printf ("EXT2-fs: unsupported inode size: %d\n",
+ sb->u.ext2_sb.s_inode_size);
+ return -1;
+ }
+ }
+ sb->u.ext2_sb.s_feature_compat = le32_to_cpu(es->s_feature_compat);
+ sb->u.ext2_sb.s_feature_incompat = le32_to_cpu(es->s_feature_incompat);
+ sb->u.ext2_sb.s_feature_ro_compat = le32_to_cpu(es->s_feature_ro_compat);
+ sb->u.ext2_sb.s_frag_size = EXT2_MIN_FRAG_SIZE <<
+ le32_to_cpu(es->s_log_frag_size);
+ if (sb->u.ext2_sb.s_frag_size)
+ sb->u.ext2_sb.s_frags_per_block = sb->s_blocksize /
+ sb->u.ext2_sb.s_frag_size;
+ else
+ sb->s_magic = 0;
+ sb->u.ext2_sb.s_blocks_per_group = le32_to_cpu(es->s_blocks_per_group);
+ sb->u.ext2_sb.s_frags_per_group = le32_to_cpu(es->s_frags_per_group);
+ sb->u.ext2_sb.s_inodes_per_group = le32_to_cpu(es->s_inodes_per_group);
+ sb->u.ext2_sb.s_inodes_per_block = sb->s_blocksize /
+ EXT2_INODE_SIZE(sb);
+ sb->u.ext2_sb.s_itb_per_group = sb->u.ext2_sb.s_inodes_per_group /
+ sb->u.ext2_sb.s_inodes_per_block;
+ sb->u.ext2_sb.s_desc_per_block = sb->s_blocksize /
+ sizeof (struct ext2_group_desc);
+#if 0
+ sb->u.ext2_sb.s_sbh = bh;
+#endif
+ sb->u.ext2_sb.s_resuid = le16_to_cpu(es->s_def_resuid);
+ sb->u.ext2_sb.s_resgid = le16_to_cpu(es->s_def_resgid);
+ sb->u.ext2_sb.s_mount_state = le16_to_cpu(es->s_state);
+// sb->u.ext2_sb.s_rename_lock = 0;
+// sb->u.ext2_sb.s_rename_wait = NULL;
+ sb->u.ext2_sb.s_addr_per_block_bits = log2 (EXT2_ADDR_PER_BLOCK(sb));
+ sb->u.ext2_sb.s_desc_per_block_bits = log2 (EXT2_DESC_PER_BLOCK(sb));
+ if (sb->s_magic != EXT2_SUPER_MAGIC) {
+ printf ("VFS: Can't find an ext2 filesystem on flash card\n");
+ return -1;
+ }
+
+ if (sb->s_blocksize != sb->u.ext2_sb.s_frag_size) {
+ printf ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
+ sb->u.ext2_sb.s_frag_size, sb->s_blocksize);
+ return -1;
+ }
+
+ if (sb->u.ext2_sb.s_blocks_per_group > sb->s_blocksize * 8) {
+ printf ("EXT2-fs: #blocks per group too big: %lu\n",
+ sb->u.ext2_sb.s_blocks_per_group);
+ return -1;
+ }
+ if (sb->u.ext2_sb.s_frags_per_group > sb->s_blocksize * 8) {
+ printf ("EXT2-fs: #fragments per group too big: %lu\n",
+ sb->u.ext2_sb.s_frags_per_group);
+ return -1;
+ }
+ if (sb->u.ext2_sb.s_inodes_per_group > sb->s_blocksize * 8) {
+ printf ("EXT2-fs: #inodes per group too big: %lu\n",
+ sb->u.ext2_sb.s_inodes_per_group);
+ return -1;
+ }
+
+ sb->u.ext2_sb.s_groups_count = (le32_to_cpu(es->s_blocks_count) -
+ le32_to_cpu(es->s_first_data_block) +
+ EXT2_BLOCKS_PER_GROUP(sb) - 1) /
+ EXT2_BLOCKS_PER_GROUP(sb);
+ db_count = (sb->u.ext2_sb.s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
+ EXT2_DESC_PER_BLOCK(sb);
+
+ sb->u.ext2_sb.s_group_desc = (struct buffer_head **)bd_alloc_mem(db_count * sizeof (struct buffer_head *));
+
+ for (i = 0; i < db_count; i++) {
+ uint memaddr;
+
+ memaddr = bd_alloc_mem(blocksize);
+ sb->u.ext2_sb.s_group_desc[i] = (struct buffer_head *)memaddr;
+
+ rom_bread ((char *)memaddr, logic_sb_block + i + 1, sb->s_blocksize);
+ }
+ for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) {
+ sb->u.ext2_sb.s_inode_bitmap_number[i] = 0;
+ sb->u.ext2_sb.s_inode_bitmap[i] = NULL;
+ sb->u.ext2_sb.s_block_bitmap_number[i] = 0;
+ sb->u.ext2_sb.s_block_bitmap[i] = NULL;
+ }
+ sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
+ sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
+ sb->u.ext2_sb.s_db_per_group = db_count;
+ /*
+ * set up enough so that it can read an inode
+ */
+ root_inode.i_sb = sb;
+ root_inode.i_ino = EXT2_ROOT_INO;
+ root_inode.i_count = 1;
+ sb->s_root = (struct dentry *)&root_inode;
+ if (rom_ext2_read_inode(&root_inode) < 0)
+ return -1;
+
+#if 0
+ ext2_setup_super (sb, es, dir_d);
+#endif
+ return 0;
+}
--- /dev/null
+#include "file.h"
+
+file_detectfs_func file_ext2_detectfs;
+file_ls_func file_ext2_ls;
+file_read_func file_ext2_read;
--- /dev/null
+/*
+ * fat.c
+ *
+ * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
+ *
+ *
+ */
+
+#include "romfuncs.h"
+#include "fat.h"
+
+#define noDEBUG
+#define SUPPORT_VFAT
+
+/* XXX: Changed to ext2 default
+#define SECTOR_SIZE 512 */
+#define SECTOR_SIZE FS_BLOCK_SIZE
+
+#if FS_BLOCK_SIZE != SECTOR_SIZE
+#error FS_BLOCK_SIZE != SECTOR_SIZE - This code needs to be fixed!
+#endif
+
+#define MAX_CLUSTSIZE 65536
+#define DIRENTSPERBLOCK (FS_BLOCK_SIZE/sizeof(dir_entry))
+#define DIRENTSPERCLUST ((mydata->clust_size*SECTOR_SIZE)/sizeof(dir_entry))
+
+#define FATBUFBLOCKS 6
+#define FATBUFSIZE (FS_BLOCK_SIZE*FATBUFBLOCKS)
+#define FAT12BUFSIZE ((FATBUFSIZE*3)/2)
+#define FAT16BUFSIZE (FATBUFSIZE/2)
+#define FAT32BUFSIZE (FATBUFSIZE/4)
+
+
+/* Filesystem identifiers */
+#define FAT12_SIGN "FAT12 "
+#define FAT16_SIGN "FAT16 "
+#define FAT32_SIGN "FAT32 "
+#define SIGNLEN 8
+
+/* File attributes */
+#define ATTR_RO 1
+#define ATTR_HIDDEN 2
+#define ATTR_SYS 4
+#define ATTR_VOLUME 8
+#define ATTR_DIR 16
+#define ATTR_ARCH 32
+
+#define ATTR_VFAT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
+
+#define DELETED_FLAG ((char)0xe5) /* Marks deleted files when in name[0] */
+#define aRING 0x05 /* Used to represent 'Ã¥' in name[0] */
+
+
+/* Flags telling whether we should read a file or list a directory */
+#define LS_NO 0
+#define LS_YES 1
+#define LS_DIR 1
+#define LS_ROOT 2
+
+#ifdef DEBUG
+#define FAT_DPRINT(args...) printf(args)
+#else
+#define FAT_DPRINT(args...)
+#endif
+#define FAT_ERROR(arg) printf(arg)
+
+
+#if defined(__linux__) && defined(__KERNEL__)
+#define FAT2CPU16 le16_to_cpu
+#define FAT2CPU32 le32_to_cpu
+#else
+#if 1
+#define FAT2CPU16(x) (x)
+#define FAT2CPU32(x) (x)
+#else
+#define FAT2CPU16(x) ((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8))
+#define FAT2CPU32(x) ((((x) & 0x000000ff) << 24) | \
+ (((x) & 0x0000ff00) << 8) | \
+ (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0xff000000) >> 24))
+#endif
+#endif
+
+#define TOLOWER(c) if((c) >= 'A' && (c) <= 'Z'){(c)+=('a' - 'A');}
+#define START(dent) (FAT2CPU16((dent)->start) \
+ + (mydata->fatsize != 32 ? 0 : \
+ (FAT2CPU16((dent)->starthi) << 16)))
+
+
+typedef struct boot_sector {
+ __u8 ignored[3]; /* Bootstrap code */
+ char system_id[8]; /* Name of fs */
+ __u8 sector_size[2]; /* Bytes/sector */
+ __u8 cluster_size; /* Sectors/cluster */
+ __u16 reserved; /* Number of reserved sectors */
+ __u8 fats; /* Number of FATs */
+ __u8 dir_entries[2]; /* Number of root directory entries */
+ __u8 sectors[2]; /* Number of sectors */
+ __u8 media; /* Media code */
+ __u16 fat_length; /* Sectors/FAT */
+ __u16 secs_track; /* Sectors/track */
+ __u16 heads; /* Number of heads */
+ __u32 hidden; /* Number of hidden sectors */
+ __u32 total_sect; /* Number of sectors (if sectors == 0) */
+
+ /* FAT32 only */
+ __u32 fat32_length; /* Sectors/FAT */
+ __u16 flags; /* Bit 8: fat mirroring, low 4: active fat */
+ __u8 version[2]; /* Filesystem version */
+ __u32 root_cluster; /* First cluster in root directory */
+ __u16 info_sector; /* Filesystem info sector */
+ __u16 backup_boot; /* Backup boot sector */
+ __u16 reserved2[6]; /* Unused */
+} boot_sector;
+
+typedef struct volume_info
+{
+ __u8 drive_number; /* BIOS drive number */
+ __u8 reserved; /* Unused */
+ __u8 ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */
+ __u8 volume_id[4]; /* Volume ID number */
+ char volume_label[11]; /* Volume label */
+ char fs_type[8]; /* Typically FAT12, FAT16, or FAT32 */
+ /* Boot code comes next, all but 2 bytes to fill up sector */
+ /* Boot sign comes last, 2 bytes */
+} volume_info;
+
+typedef struct dir_entry {
+ char name[8],ext[3]; /* Name and extension */
+ __u8 attr; /* Attribute bits */
+ __u8 lcase; /* Case for base and extension */
+ __u8 ctime_ms; /* Creation time, milliseconds */
+ __u16 ctime; /* Creation time */
+ __u16 cdate; /* Creation date */
+ __u16 adate; /* Last access date */
+ __u16 starthi; /* High 16 bits of cluster in FAT32 */
+ __u16 time,date,start;/* Time, date and first cluster */
+ __u32 size; /* File size in bytes */
+} dir_entry;
+
+typedef struct dir_slot {
+ __u8 id; /* Sequence number for slot */
+ __u8 name0_4[10]; /* First 5 characters in name */
+ __u8 attr; /* Attribute byte */
+ __u8 reserved; /* Unused */
+ __u8 alias_checksum;/* Checksum for 8.3 alias */
+ __u8 name5_10[12]; /* 6 more characters in name */
+ __u16 start; /* Unused */
+ __u8 name11_12[4]; /* Last 2 characters in name */
+} dir_slot;
+
+/* Private filesystem parameters */
+typedef struct {
+ int fatsize; /* Size of FAT in bits */
+ __u16 fatlength; /* Length of FAT in sectors */
+ __u16 fat_sect; /* Starting sector of the FAT */
+ __u16 rootdir_sect; /* Start sector of root directory */
+ __u16 clust_size; /* Size of clusters in sectors */
+ __u16 data_begin; /* The sector of the first cluster */
+ __u8 fatbuf[FATBUFSIZE]; /* Current FAT buffer */
+ int fatbufnum; /* Used by get_fatent, init to -1 */
+} fsdata;
+
+
+
+/*
+ Convert a string to lowercase.
+*/
+static void
+downcase(char *str)
+{
+ while (*str != '\0') {
+ TOLOWER(*str);
+ str++;
+ }
+}
+
+
+/*
+ Get the first occurence of a directory delimiter ('/' or '\') in a string.
+ Return index into string if found, -1 otherwise.
+*/
+static int
+dirdelim(char *str)
+{
+ char *start = str;
+
+ while (*str != '\0') {
+ if (ISDIRDELIM(*str)) return str - start;
+ str++;
+ }
+ return -1;
+}
+
+
+/*
+ Match volume_info fs_type strings.
+ Return 0 on match, -1 otherwise.
+*/
+static int
+compare_sign(char *str1, char *str2)
+{
+ char *end = str1+SIGNLEN;
+
+ while (str1 != end) {
+ if (*str1 != *str2) {
+ return -1;
+ }
+ str1++;
+ str2++;
+ }
+
+ return 0;
+}
+
+
+/*
+ Extract zero terminated short name from a directory entry.
+*/
+static void
+get_name(dir_entry *dirent, char *s_name)
+{
+ char *ptr;
+
+ memcpy(s_name, dirent->name, 8);
+ s_name[8] = '\0';
+ ptr = s_name;
+ while (*ptr && *ptr != ' ') ptr++;
+ if (dirent->ext[0] && dirent->ext[0] != ' ') {
+ *ptr = '.';
+ ptr++;
+ memcpy(ptr, dirent->ext, 3);
+ ptr[3] = '\0';
+ while (*ptr && *ptr != ' ') ptr++;
+ }
+ *ptr = '\0';
+ if (*s_name == DELETED_FLAG) *s_name = '\0';
+ else if (*s_name == aRING) *s_name = 'Ã¥';
+ downcase(s_name);
+}
+
+
+/*
+ Get the entry at index 'entry' in a FAT (12/16/32) table.
+ On failure 0x00 is returned.
+*/
+static __u32
+get_fatent(fsdata *mydata, __u32 entry)
+{
+ __u32 bufnum;
+ __u32 offset;
+ __u32 ret = 0x00;
+
+ switch (mydata->fatsize) {
+ case 32:
+ bufnum = entry / FAT32BUFSIZE;
+ offset = entry - bufnum * FAT32BUFSIZE;
+ break;
+ case 16:
+ bufnum = entry / FAT16BUFSIZE;
+ offset = entry - bufnum * FAT16BUFSIZE;
+ break;
+ case 12:
+ bufnum = entry / FAT12BUFSIZE;
+ offset = entry - bufnum * FAT12BUFSIZE;
+ break;
+
+ default:
+ /* Unsupported FAT size */
+ return ret;
+ }
+
+ /* Read a new block of FAT entries into the cache. */
+ if (bufnum != mydata->fatbufnum) {
+ int getsize = FATBUFSIZE/FS_BLOCK_SIZE;
+ __u8 *bufptr = mydata->fatbuf;
+ __u32 fatlength = mydata->fatlength;
+ __u32 startblock = bufnum * FATBUFBLOCKS;
+
+ fatlength *= SECTOR_SIZE; /* We want it in bytes now */
+ startblock += mydata->fat_sect; /* Offset from start of disk */
+
+ if (getsize > fatlength) getsize = fatlength;
+ if (disk_read(startblock, getsize, bufptr) != 0) {
+ FAT_DPRINT("Error reading FAT blocks\n");
+ return ret;
+ }
+ mydata->fatbufnum = bufnum;
+ }
+
+ /* Get the actual entry from the table */
+ switch (mydata->fatsize) {
+ case 32:
+ ret = FAT2CPU32(((__u32*)mydata->fatbuf)[offset]);
+ break;
+ case 16:
+ ret = FAT2CPU16(((__u16*)mydata->fatbuf)[offset]);
+ break;
+ case 12: {
+ __u32 off16 = (offset*3)/4;
+ __u16 val1, val2;
+
+ switch (offset & 0x3) {
+ case 0:
+ ret = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);
+ ret &= 0xfff;
+ break;
+ case 1:
+ val1 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);
+ val1 &= 0xf000;
+ val2 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16+1]);
+ val2 &= 0x00ff;
+ ret = (val2 << 4) | (val1 >> 12);
+ break;
+ case 2:
+ val1 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);
+ val1 &= 0xff00;
+ val2 = FAT2CPU16(((__u16*)mydata->fatbuf)[off16+1]);
+ val2 &= 0x000f;
+ ret = (val2 << 8) | (val1 >> 8);
+ break;
+ case 3:
+ ret = FAT2CPU16(((__u16*)mydata->fatbuf)[off16]);;
+ ret = (ret & 0xfff0) >> 4;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ FAT_DPRINT("ret: %d, offset: %d\n", ret, offset);
+
+ return ret;
+}
+
+
+/*
+ Read at most 'size' bytes from the specified cluster into 'buffer'.
+ Return 0 on success, -1 otherwise.
+*/
+static int
+get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
+{
+ int idx = 0;
+ __u32 startsect;
+
+ if (clustnum > 0) {
+ startsect = mydata->data_begin + clustnum*mydata->clust_size;
+ } else {
+ startsect = mydata->rootdir_sect;
+ }
+
+ FAT_DPRINT("gc - clustnum: %d, startsect: %d\n", clustnum, startsect);
+ while (size > 0) {
+ if (size >= FS_BLOCK_SIZE) {
+ if (disk_read(startsect + idx, 1, buffer) != 0) {
+ FAT_DPRINT("Error reading data\n");
+ return -1;
+ }
+ } else {
+ __u8 *tmpbuf[FS_BLOCK_SIZE];
+ if (disk_read(startsect + idx, 1, tmpbuf) != 0) {
+ FAT_DPRINT("Error reading data\n");
+ return -1;
+ }
+ memcpy(buffer, tmpbuf, size);
+
+ return 0;
+ }
+ buffer += FS_BLOCK_SIZE;
+ size -= FS_BLOCK_SIZE;
+ idx++;
+ }
+
+ return 0;
+}
+
+
+/*
+ Read at most 'maxsize' bytes from the file associated with 'dentptr'
+ into 'buffer'.
+ Return the number of bytes read or -1 on fatal errors.
+*/
+static long
+get_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
+ unsigned long maxsize)
+{
+ unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0;
+ unsigned int bytesperclust = mydata->clust_size * SECTOR_SIZE;
+ __u32 curclust = START(dentptr);
+
+ if (maxsize > 0 && filesize > maxsize) filesize = maxsize;
+
+ FAT_DPRINT("Reading: %ld bytes\n", filesize);
+
+ do {
+ int getsize = (filesize > bytesperclust) ? bytesperclust :
+ filesize;
+
+ if (get_cluster(mydata, curclust, buffer, getsize) != 0) {
+ FAT_ERROR("Error reading cluster\n");
+ return -1;
+ }
+ gotsize += getsize;
+ filesize -= getsize;
+ if (filesize <= 0) return gotsize;
+ buffer += getsize;
+
+ curclust = get_fatent(mydata, curclust);
+ if (curclust <= 0x0001 || curclust >= 0xfff0) {
+ FAT_DPRINT("curclust: 0x%x\n", curclust);
+ FAT_ERROR("Invalid FAT entry\n");
+ return gotsize;
+ }
+ } while (1);
+}
+
+
+#ifdef SUPPORT_VFAT
+/*
+ Extract the file name information from 'slotptr' into 'l_name',
+ starting at l_name[*idx].
+ Return 1 if terminator (zero byte) is found, 0 otherwise.
+*/
+static int
+slot2str(dir_slot *slotptr, char *l_name, int *idx)
+{
+ int j;
+
+ for (j = 0; j <= 8; j += 2) {
+ l_name[*idx] = slotptr->name0_4[j];
+ if (l_name[*idx] == 0x00) return 1;
+ (*idx)++;
+ }
+ for (j = 0; j <= 10; j += 2) {
+ l_name[*idx] = slotptr->name5_10[j];
+ if (l_name[*idx] == 0x00) return 1;
+ (*idx)++;
+ }
+ for (j = 0; j <= 2; j += 2) {
+ l_name[*idx] = slotptr->name11_12[j];
+ if (l_name[*idx] == 0x00) return 1;
+ (*idx)++;
+ }
+
+ return 0;
+}
+
+
+/*
+ Extract the full long filename starting at 'retdent' (which is really
+ a slot) into 'l_name'. If successful also copy the real directory entry
+ into 'retdent'
+ Return 0 on success, -1 otherwise.
+*/
+static int
+get_vfatname(fsdata *mydata, int curclust, __u8 *cluster,
+ dir_entry *retdent, char *l_name)
+{
+ dir_entry *realdent;
+ dir_slot *slotptr = (dir_slot*) retdent;
+ __u8 *nextclust = cluster + mydata->clust_size * SECTOR_SIZE;
+ __u8 counter = slotptr->id & 0xf;
+ int idx = 0;
+
+ while ((__u8*)slotptr < nextclust) {
+ if (counter == 0) break;
+ if ((slotptr->id & 0x0f) != counter) return -1;
+ slotptr++;
+ counter--;
+ }
+
+ if ((__u8*)slotptr >= nextclust) {
+ __u8 block[MAX_CLUSTSIZE];
+ dir_slot *slotptr2;
+
+ slotptr--;
+ curclust = get_fatent(mydata, curclust);
+ if (curclust <= 0x0001 || curclust >= 0xfff0) {
+ FAT_DPRINT("curclust: 0x%x\n", curclust);
+ FAT_ERROR("Invalid FAT entry\n");
+ return -1;
+ }
+ if (get_cluster(mydata, curclust, block,
+ mydata->clust_size * SECTOR_SIZE) != 0) {
+ FAT_DPRINT("Error: reading directory block\n");
+ return -1;
+ }
+ slotptr2 = (dir_slot*) block;
+ while (slotptr2->id > 0x01) {
+ slotptr2++;
+ }
+ /* Save the real directory entry */
+ realdent = (dir_entry*)slotptr2 + 1;
+ while ((__u8*)slotptr2 >= block) {
+ slot2str(slotptr2, l_name, &idx);
+ slotptr2--;
+ }
+ } else {
+ /* Save the real directory entry */
+ realdent = (dir_entry*)slotptr;
+ }
+
+ do {
+ slotptr--;
+ if (slot2str(slotptr, l_name, &idx)) break;
+ } while (!(slotptr->id & 0x40));
+
+ l_name[idx] = '\0';
+ if (*l_name == DELETED_FLAG) *l_name = '\0';
+ else if (*l_name == aRING) *l_name = 'Ã¥';
+ downcase(l_name);
+
+ /* Return the real directory entry */
+ memcpy(retdent, realdent, sizeof(dir_entry));
+
+ return 0;
+}
+
+
+/* Calculate short name checksum */
+static __u8
+mkcksum(const char *str)
+{
+ int i;
+ __u8 ret = 0;
+
+ for (i = 0; i < 11; i++) {
+ ret = (((ret&1)<<7)|((ret&0xfe)>>1)) + str[i];
+ }
+
+ return ret;
+}
+#endif
+
+
+/*
+ Get the directory entry associated with 'filename' from the directory
+ starting at 'startsect'
+*/
+static dir_entry *
+get_dentfromdir(fsdata *mydata, int startsect, char *filename,
+ dir_entry *retdent, int dols)
+{
+ __u16 prevcksum = 0xffff;
+ __u8 block[MAX_CLUSTSIZE];
+ __u32 curclust = START(retdent);
+ int files = 0, dirs = 0;
+
+ FAT_DPRINT("get_dentfromdir: %s\n", filename);
+ while (1) {
+ dir_entry *dentptr;
+ int i;
+
+ if (get_cluster(mydata, curclust, block,
+ mydata->clust_size*SECTOR_SIZE) != 0) {
+ FAT_DPRINT("Error: reading directory block\n");
+ return NULL;
+ }
+ dentptr = (dir_entry*) block;
+ for (i = 0; i < DIRENTSPERCLUST; i++) {
+ char s_name[12], l_name[256];
+
+ l_name[0] = '\0';
+ if ((dentptr->attr & ATTR_VOLUME)) {
+#ifdef SUPPORT_VFAT
+ if ((dentptr->attr & ATTR_VFAT) &&
+ (dentptr->name[0] & 0x40)) {
+ prevcksum = ((dir_slot*)dentptr)
+ ->alias_checksum;
+ get_vfatname(mydata, curclust, block,
+ dentptr, l_name);
+ if (dols) {
+ int isdir = (dentptr->attr&ATTR_DIR);
+ char dirc;
+
+ if (isdir) {
+ dirs++;
+ dirc = '/';
+ } else {
+ files++;
+ dirc = ' ';
+ }
+ printf(" %s%c\n",
+ l_name, dirc);
+ dentptr++;
+ continue;
+ }
+ FAT_DPRINT("vfatname: |%s|\n", l_name);
+ } else
+#endif
+ {
+ /* Volume label or VFAT entry */
+ dentptr++;
+ continue;
+ }
+ }
+ if (dentptr->name[0] == 0) {
+ if (dols) {
+ printf("\n%d file(s), %d dir(s)\n\n",
+ files, dirs);
+ }
+ FAT_DPRINT("Dentname == NULL - %d\n", i);
+ return NULL;
+ }
+#ifdef SUPPORT_VFAT
+ if (dols && mkcksum(dentptr->name) == prevcksum) {
+ dentptr++;
+ continue;
+ }
+#endif
+ get_name(dentptr, s_name);
+ if (dols) {
+ int isdir = (dentptr->attr&ATTR_DIR);
+ char dirc;
+
+ if (isdir) {
+ dirs++;
+ dirc = '/';
+ } else {
+ files++;
+ dirc = ' ';
+ }
+ printf(" %s%c\n", s_name, dirc);
+ dentptr++;
+ continue;
+ }
+ if (strcmp(filename, s_name) &&
+ strcmp(filename, l_name)) {
+ FAT_DPRINT("Mismatch: |%s|%s|\n",
+ s_name, l_name);
+ dentptr++;
+ continue;
+ }
+ memcpy(retdent, dentptr, sizeof(dir_entry));
+
+ FAT_DPRINT("DentName: %s", s_name);
+ FAT_DPRINT(", start: 0x%x", START(dentptr));
+ FAT_DPRINT(", size: 0x%x %s\n",
+ FAT2CPU32(dentptr->size),
+ (dentptr->attr&ATTR_DIR) ? "(DIR)" : "");
+
+ return retdent;
+ }
+ curclust = get_fatent(mydata, curclust);
+ if (curclust <= 0x0001 || curclust >= 0xfff0) {
+ FAT_DPRINT("curclust: 0x%x\n", curclust);
+ FAT_ERROR("Invalid FAT entry\n");
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ Read boot sector and volume info from a FAT filesystem
+*/
+static int
+read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
+{
+ __u8 block[FS_BLOCK_SIZE];
+ volume_info *vistart;
+
+ if (disk_read(0, 1, block) != 0) {
+ FAT_DPRINT("Error: reading block\n");
+ return -1;
+ }
+
+ memcpy(bs, block, sizeof(boot_sector));
+ bs->reserved = FAT2CPU16(bs->reserved);
+ bs->fat_length = FAT2CPU16(bs->fat_length);
+ bs->secs_track = FAT2CPU16(bs->secs_track);
+ bs->heads = FAT2CPU16(bs->heads);
+#if 0 /* UNUSED */
+ bs->hidden = FAT2CPU32(bs->hidden);
+#endif
+ bs->total_sect = FAT2CPU32(bs->total_sect);
+
+ /* FAT32 entries */
+ if (bs->fat_length == 0) {
+ /* Assume FAT32 */
+ bs->fat32_length = FAT2CPU32(bs->fat32_length);
+ bs->flags = FAT2CPU16(bs->flags);
+ bs->root_cluster = FAT2CPU32(bs->root_cluster);
+ bs->info_sector = FAT2CPU16(bs->info_sector);
+ bs->backup_boot = FAT2CPU16(bs->backup_boot);
+ vistart = (volume_info*) (block + sizeof(boot_sector));
+ *fatsize = 32;
+ } else {
+ vistart = (volume_info*) &(bs->fat32_length);
+ *fatsize = 0;
+ }
+ memcpy(volinfo, vistart, sizeof(volume_info));
+
+ /* Terminate fs_type string. Writing past the end of vistart
+ is ok - it's just the buffer. */
+ vistart->fs_type[8] = '\0';
+
+ if (*fatsize == 32) {
+ if (compare_sign(FAT32_SIGN, vistart->fs_type) == 0) {
+ return 0;
+ }
+ } else {
+ if (compare_sign(FAT12_SIGN, vistart->fs_type) == 0) {
+ *fatsize = 12;
+ return 0;
+ }
+ if (compare_sign(FAT16_SIGN, vistart->fs_type) == 0) {
+ *fatsize = 16;
+ return 0;
+ }
+ }
+
+ FAT_DPRINT("Error: broken fs_type sign\n");
+ return -1;
+}
+
+
+static long
+do_fat_read(const char *filename, void *buffer, unsigned long maxsize,
+ int dols)
+{
+ __u8 block[FS_BLOCK_SIZE]; /* Block buffer */
+ char fnamecopy[2048];
+ boot_sector bs;
+ volume_info volinfo;
+ fsdata datablock;
+ fsdata *mydata = &datablock;
+ dir_entry *dentptr;
+ __u16 prevcksum = 0xffff;
+ char *subname = "";
+ int rootdir_size, cursect;
+ int idx, isdir = 0;
+ int files = 0, dirs = 0;
+ long ret = 0;
+ int firsttime;
+
+ if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
+ FAT_DPRINT("Error: reading boot sector\n");
+ return -1;
+ }
+ if (mydata->fatsize == 32) {
+ mydata->fatlength = bs.fat32_length;
+ } else {
+ mydata->fatlength = bs.fat_length;
+ }
+ mydata->fat_sect = bs.reserved;
+ cursect = mydata->rootdir_sect
+ = mydata->fat_sect + mydata->fatlength * bs.fats;
+ mydata->clust_size = bs.cluster_size;
+ if (mydata->fatsize == 32) {
+ rootdir_size = mydata->clust_size;
+ mydata->data_begin = mydata->rootdir_sect /* + rootdir_size */
+ - (mydata->clust_size*2);
+ } else {
+ rootdir_size = ((bs.dir_entries[1] * (int)256
+ + bs.dir_entries[0])
+ * sizeof(dir_entry)) / SECTOR_SIZE;
+ mydata->data_begin = mydata->rootdir_sect + rootdir_size
+ - (mydata->clust_size*2);
+ }
+ mydata->fatbufnum = -1;
+
+ FAT_DPRINT("FAT%d, fatlength: %d\n", mydata->fatsize,
+ mydata->fatlength);
+ FAT_DPRINT("Rootdir begins at sector: %d, offset: %x, size: %d\n"
+ "Data begins at: %d\n",
+ mydata->rootdir_sect, mydata->rootdir_sect * SECTOR_SIZE,
+ rootdir_size, mydata->data_begin);
+ FAT_DPRINT("Cluster size: %d\n", mydata->clust_size);
+
+ /* "cwd" is always the root... */
+ while (ISDIRDELIM(*filename)) filename++;
+ /* Make a copy of the filename and convert it to lowercase */
+ strcpy(fnamecopy, filename);
+ downcase(fnamecopy);
+ if (*fnamecopy == '\0') {
+ if (!dols) return -1;
+ dols = LS_ROOT;
+ } else if ((idx = dirdelim(fnamecopy)) >= 0) {
+ isdir = 1;
+ fnamecopy[idx] = '\0';
+ subname = fnamecopy + idx + 1;
+ /* Handle multiple delimiters */
+ while (ISDIRDELIM(*subname)) subname++;
+ } else if (dols) {
+ isdir = 1;
+ }
+
+ while (1) {
+ int i;
+
+ if (disk_read(cursect, 1, block) != 0) {
+ FAT_DPRINT("Error: reading rootdir block\n");
+ return -1;
+ }
+ dentptr = (dir_entry*) block;
+ for (i = 0; i < DIRENTSPERBLOCK; i++) {
+ char s_name[12], l_name[256];
+
+ l_name[0] = '\0';
+ if ((dentptr->attr & ATTR_VOLUME)) {
+#ifdef SUPPORT_VFAT
+ if ((dentptr->attr & ATTR_VFAT) &&
+ (dentptr->name[0] & 0x40)) {
+ prevcksum = ((dir_slot*)dentptr)
+ ->alias_checksum;
+ get_vfatname(mydata, 0, block,
+ dentptr, l_name);
+ if (dols == LS_ROOT) {
+ int isdir = (dentptr->attr&ATTR_DIR);
+ char dirc;
+
+ if (isdir) {
+ dirs++;
+ dirc = '/';
+ } else {
+ files++;
+ dirc = ' ';
+ }
+ printf(" %s%c\n",
+ l_name, dirc);
+ dentptr++;
+ continue;
+ }
+ FAT_DPRINT("Rootvfatname: |%s|\n",
+ l_name);
+ } else
+#endif
+ {
+ /* Volume label or VFAT entry */
+ dentptr++;
+ continue;
+ }
+ } else if (dentptr->name[0] == 0) {
+ FAT_DPRINT("RootDentname == NULL - %d\n", i);
+ if (dols == LS_ROOT) {
+ printf("\n%d file(s), %d dir(s)\n\n",
+ files, dirs);
+ return 0;
+ }
+ return -1;
+ }
+#ifdef SUPPORT_VFAT
+ else if (dols == LS_ROOT
+ && mkcksum(dentptr->name) == prevcksum) {
+ dentptr++;
+ continue;
+ }
+#endif
+ get_name(dentptr, s_name);
+ if (dols == LS_ROOT) {
+ int isdir = (dentptr->attr&ATTR_DIR);
+ char dirc;
+
+ if (isdir) {
+ dirs++;
+ dirc = '/';
+ } else {
+ files++;
+ dirc = ' ';
+ }
+ printf(" %s%c\n", s_name, dirc);
+ dentptr++;
+ continue;
+ }
+ if (strcmp(fnamecopy, s_name) &&
+ strcmp(fnamecopy, l_name)) {
+ FAT_DPRINT("RootMismatch: |%s|%s|\n",
+ s_name, l_name);
+ dentptr++;
+ continue;
+ }
+ if (isdir && !(dentptr->attr & ATTR_DIR)) return -1;
+
+ FAT_DPRINT("RootName: %s", s_name);
+ FAT_DPRINT(", start: 0x%x", START(dentptr));
+ FAT_DPRINT(", size: 0x%x %s\n",
+ FAT2CPU32(dentptr->size),
+ isdir ? "(DIR)" : "");
+
+ goto rootdir_done; /* We got a match */
+ }
+ cursect++;
+ }
+ rootdir_done:
+
+ firsttime = 1;
+ while (isdir) {
+ int startsect = mydata->data_begin
+ + START(dentptr)*mydata->clust_size;
+ dir_entry dent;
+ char *nextname = NULL;
+
+ dent = *dentptr;
+ dentptr = & dent;
+
+ idx = dirdelim(subname);
+ if (idx >= 0) {
+ subname[idx] = '\0';
+ nextname = subname + idx + 1;
+ /* Handle multiple delimiters */
+ while (ISDIRDELIM(*nextname)) nextname++;
+ if (dols && *nextname == '\0') firsttime = 0;
+ } else {
+ if (dols && firsttime) {
+ firsttime = 0;
+ } else {
+ isdir = 0;
+ }
+ }
+
+ if (get_dentfromdir(mydata, startsect, subname, dentptr,
+ isdir ? 0 : dols) == NULL) {
+ if (dols && !isdir) return 0;
+ return -1;
+ }
+
+ if (idx >= 0) {
+ if (! (dentptr->attr & ATTR_DIR)) return -1;
+ subname = nextname;
+ }
+ }
+ ret = get_contents(mydata, dentptr, buffer, maxsize);
+ FAT_DPRINT("Size: %d, got: %ld\n", FAT2CPU32(dentptr->size), ret);
+
+ return ret;
+}
+
+
+int
+file_fat_detectfs(void)
+{
+ boot_sector bs;
+ volume_info volinfo;
+ int fatsize;
+
+ return read_bootsectandvi(&bs, &volinfo, &fatsize);
+}
+
+
+int
+file_fat_ls(const char *dir)
+{
+ return do_fat_read(dir, NULL, 0, LS_YES);
+}
+
+
+long
+file_fat_read(const char *filename, void *buffer, unsigned long maxsize)
+{
+ return do_fat_read(filename, buffer, maxsize, LS_NO);
+}
--- /dev/null
+#include "file.h"
+
+file_detectfs_func file_fat_detectfs;
+file_ls_func file_fat_ls;
+file_read_func file_fat_read;
--- /dev/null
+/*
+ * file.c
+ *
+ * Mini "VFS" by Marcus Sundberg
+ *
+ *
+ */
+
+#include "romfuncs.h"
+#include "file.h"
+
+#if USE_FATFS
+#include "fat.h"
+#endif
+#if USE_EXT2FS
+#include "ext2.h"
+#endif
+
+struct filesystem {
+ file_detectfs_func *detect;
+ file_ls_func *ls;
+ file_read_func *read;
+ const char name[12];
+};
+
+/* Supported filesystems */
+static const struct filesystem filesystems[] = {
+#if USE_FATFS
+ { file_fat_detectfs, file_fat_ls, file_fat_read, "FAT" },
+#endif
+#if USE_EXT2FS
+ { file_ext2_detectfs, file_ext2_ls, file_ext2_read, "ext2" },
+#endif
+};
+#define NUM_FILESYS (sizeof(filesystems)/sizeof(struct filesystem))
+
+/* The filesystem which was last detected */
+static int current_filesystem = FSTYPE_NONE;
+
+/* The current working directory */
+#define CWD_LEN 511
+char file_cwd[CWD_LEN+1] = "/";
+
+const char *
+file_getfsname(int idx)
+{
+ if (idx < 0 || idx >= NUM_FILESYS) return NULL;
+
+ return filesystems[idx].name;
+}
+
+
+static void
+pathcpy(char *dest, const char *src)
+{
+ char *origdest = dest;
+
+ do {
+ if (dest-file_cwd >= CWD_LEN) {
+ *dest = '\0';
+ return;
+ }
+ *(dest) = *(src);
+ if (*src == '\0') {
+ if (dest-- != origdest && ISDIRDELIM(*dest)) {
+ *dest = '\0';
+ }
+ return;
+ }
+ ++dest;
+ if (ISDIRDELIM(*src)) {
+ while (ISDIRDELIM(*src)) src++;
+ } else {
+ src++;
+ }
+ } while (1);
+}
+
+
+int
+file_cd(const char *path)
+{
+ if (ISDIRDELIM(*path)) {
+ while (ISDIRDELIM(*path)) path++;
+ strncpy(file_cwd+1, path, CWD_LEN-1);
+ } else {
+ const char *origpath = path;
+ char *tmpstr = file_cwd;
+ int back = 0;
+
+ while (*tmpstr != '\0') tmpstr++;
+ do {
+ tmpstr--;
+ } while (ISDIRDELIM(*tmpstr));
+
+ while (*path == '.') {
+ path++;
+ while (*path == '.') {
+ path++;
+ back++;
+ }
+ if (*path != '\0' && !ISDIRDELIM(*path)) {
+ path = origpath;
+ back = 0;
+ break;
+ }
+ while (ISDIRDELIM(*path)) path++;
+ origpath = path;
+ }
+
+ while (back--) {
+ /* Strip off path component */
+ while (!ISDIRDELIM(*tmpstr)) {
+ tmpstr--;
+ }
+ if (tmpstr == file_cwd) {
+ /* Incremented again right after the loop. */
+ tmpstr--;
+ break;
+ }
+ /* Skip delimiters */
+ while (ISDIRDELIM(*tmpstr)) tmpstr--;
+ }
+ tmpstr++;
+ if (*path == '\0') {
+ if (tmpstr == file_cwd) {
+ *tmpstr = '/';
+ tmpstr++;
+ }
+ *tmpstr = '\0';
+ return 0;
+ }
+ *tmpstr = '/';
+ pathcpy(tmpstr+1, path);
+ }
+
+ return 0;
+}
+
+
+int
+file_detectfs(void)
+{
+ int i;
+
+ current_filesystem = FSTYPE_NONE;
+
+ for (i = 0; i < NUM_FILESYS; i++) {
+ if (filesystems[i].detect() == 0) {
+ strcpy(file_cwd, "/");
+ current_filesystem = i;
+ break;
+ }
+ }
+
+ return current_filesystem;
+}
+
+
+int
+file_ls(const char *dir)
+{
+ char fullpath[1024];
+ const char *arg;
+
+ if (current_filesystem == FSTYPE_NONE) {
+ printf("Can't list files without a filesystem!\n");
+ return -1;
+ }
+
+ if (ISDIRDELIM(*dir)) {
+ arg = dir;
+ } else {
+ sprintf(fullpath, "%s/%s", file_cwd, dir);
+ arg = fullpath;
+ }
+ return filesystems[current_filesystem].ls(arg);
+}
+
+
+long
+file_read(const char *filename, void *buffer, unsigned long maxsize)
+{
+ char fullpath[1024];
+ const char *arg;
+
+ if (current_filesystem == FSTYPE_NONE) {
+ printf("Can't load file without a filesystem!\n");
+ return -1;
+ }
+
+ if (ISDIRDELIM(*filename)) {
+ arg = filename;
+ } else {
+ sprintf(fullpath, "%s/%s", file_cwd, filename);
+ arg = fullpath;
+ }
+
+ return filesystems[current_filesystem].read(arg, buffer, maxsize);
+}
--- /dev/null
+#ifndef _FS_FILE_H
+#define _FS_FILE_H
+
+#ifndef USE_FATFS
+#define USE_FATFS 1
+#endif
+#ifndef USE_EXT2FS
+#define USE_EXT2FS 1
+#endif
+
+#define FSTYPE_NONE (-1)
+
+typedef int (file_detectfs_func)(void);
+typedef int (file_ls_func)(const char *dir);
+typedef long (file_read_func)(const char *filename, void *buffer,
+ unsigned long maxsize);
+
+file_detectfs_func file_detectfs;
+file_ls_func file_ls;
+file_read_func file_read;
+
+const char *file_getfsname(int idx);
+
+/* Currently this doesn't check if the dir exists or is valid... */
+int file_cd(const char *path);
+
+extern char file_cwd[]; /* The current working directory */
+
+#endif /* _FS_FILE_H */
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/types.h>
+
+#define FS_BLOCK_SIZE 512
+
+#define ISDIRDELIM(c) ((c) == '/' || (c) == '\\')
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+
+#include "file.h"
+
+
+static char *FILENAME;
+static int fd;
+
+#define BLOCK_SIZE 512
+
+
+int
+disk_read(ulong blocknr, ulong numberofblocks, void *buffer)
+{
+ if (lseek(fd, blocknr*BLOCK_SIZE, SEEK_SET) == -1) {
+ perror("read_block1");
+ fprintf(stderr, "blocknr: %d\n", blocknr);
+ return -1;
+ }
+ if (read(fd, buffer, BLOCK_SIZE*numberofblocks) <= 0) {
+ perror("read_block2");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+void
+init_blocks(void)
+{
+ if ((fd = open(FILENAME, O_RDONLY)) < 0) {
+ perror("open");
+ exit(42);
+ }
+}
+
+
+#if 0
+void
+print_dirent(dir_entry *dirent)
+{
+ char name83[12];
+ char *ptr;
+
+ memcpy(name83, dirent->name, 8);
+ ptr = name83;
+ while (*ptr != ' ') ptr++;
+ if (dirent->ext[0] && dirent->ext[0] != ' ') {
+ *ptr = '.';
+ ptr++;
+ memcpy(ptr, dirent->ext, 3);
+ while (*ptr != ' ') ptr++;
+ }
+ *ptr = '\0';
+
+ printf("Name: %s %s\n", name83,
+ (dirent->attr & ATTR_DIR) ? "(DIR)" : "");
+}
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ unsigned char buffer[4096*1024+1];
+ char *fatfile;
+ long size;
+
+ if (argc < 3) exit(42);
+
+ FILENAME = argv[1];
+ fatfile = argv[2];
+
+ init_blocks();
+ file_detectfs();
+
+ file_ls(fatfile);
+#if 0
+ size = file_read(fatfile, buffer, 4096*1024);
+ if (size <= 0) return 5;
+
+ fflush(stdout);
+ fflush(stderr);
+ write(1, buffer, size);
+#endif
+
+ return 0;
+}
--- /dev/null
+#
+# Makefile for the FADS ROM library
+#
+
+
+TOPLEVEL = ..
+
+LIB = liblib.a
+OBJS = ctype.o string.o vsprintf.o
+
+all: $(LIB)
+
+include $(TOPLEVEL)/Make.config
+
+$(LIB): $(OBJS)
+ $(AR) cr $@ $(OBJS)
+
+clean:
+ rm -f $(OBJS) $(LIB)
--- /dev/null
+/*
+ * linux/lib/ctype.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+#include <linux/ctype.h>
+
+unsigned char _ctype[] = {
+_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
+_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
+_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
+_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
+_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
+_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
+_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
+_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
+_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
+_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
+_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
+_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
+_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
+_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
+_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
+_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
+_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
+_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
+
+
--- /dev/null
+/*
+ * linux/lib/string.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/*
+ * stupid library routines.. The optimized versions should generally be found
+ * as inline code in <asm-xx/string.h>
+ *
+ * These are buggy as well..
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+
+char * ___strtok = NULL;
+
+#ifndef __HAVE_ARCH_STRCPY
+char * strcpy(char * dest,const char *src)
+{
+ char *tmp = dest;
+
+ while ((*dest++ = *src++) != '\0')
+ /* nothing */;
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCPY
+char * strncpy(char * dest,const char *src,size_t count)
+{
+ char *tmp = dest;
+
+ while (count-- && (*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCAT
+char * strcat(char * dest, const char * src)
+{
+ char *tmp = dest;
+
+ while (*dest)
+ dest++;
+ while ((*dest++ = *src++) != '\0')
+ ;
+
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCAT
+char * strncat(char *dest, const char *src, size_t count)
+{
+ char *tmp = dest;
+
+ if (count) {
+ while (*dest)
+ dest++;
+ while ((*dest++ = *src++)) {
+ if (--count == 0) {
+ *dest = '\0';
+ break;
+ }
+ }
+ }
+
+ return tmp;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCMP
+int strcmp(const char * cs,const char * ct)
+{
+ register signed char __res;
+
+ while (1) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ }
+
+ return __res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNCMP
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+ register signed char __res = 0;
+
+ while (count) {
+ if ((__res = *cs - *ct++) != 0 || !*cs++)
+ break;
+ count--;
+ }
+
+ return __res;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRCHR
+char * strchr(const char * s, int c)
+{
+ for(; *s != (char) c; ++s)
+ if (*s == '\0')
+ return NULL;
+ return (char *) s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRRCHR
+char * strrchr(const char * s, int c)
+{
+ const char *p = s + strlen(s);
+ do {
+ if (*p == (char)c)
+ return (char *)p;
+ } while (--p >= s);
+ return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRLEN
+size_t strlen(const char * s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRNLEN
+size_t strnlen(const char * s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSPN
+size_t strspn(const char *s, const char *accept)
+{
+ const char *p;
+ const char *a;
+ size_t count = 0;
+
+ for (p = s; *p != '\0'; ++p) {
+ for (a = accept; *a != '\0'; ++a) {
+ if (*p == *a)
+ break;
+ }
+ if (*a == '\0')
+ return count;
+ ++count;
+ }
+
+ return count;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRPBRK
+char * strpbrk(const char * cs,const char * ct)
+{
+ const char *sc1,*sc2;
+
+ for( sc1 = cs; *sc1 != '\0'; ++sc1) {
+ for( sc2 = ct; *sc2 != '\0'; ++sc2) {
+ if (*sc1 == *sc2)
+ return (char *) sc1;
+ }
+ }
+ return NULL;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRTOK
+char * strtok(char * s,const char * ct)
+{
+ char *sbegin, *send;
+
+ sbegin = s ? s : ___strtok;
+ if (!sbegin) {
+ return NULL;
+ }
+ sbegin += strspn(sbegin,ct);
+ if (*sbegin == '\0') {
+ ___strtok = NULL;
+ return( NULL );
+ }
+ send = strpbrk( sbegin, ct);
+ if (send && *send != '\0')
+ *send++ = '\0';
+ ___strtok = send;
+ return (sbegin);
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMSET
+void * memset(void * s,char c,size_t count)
+{
+ char *xs = (char *) s;
+
+ while (count--)
+ *xs++ = c;
+
+ return s;
+}
+#endif
+
+#ifndef __HAVE_ARCH_BCOPY
+char * bcopy(const char * src, char * dest, int count)
+{
+ char *tmp = dest;
+
+ while (count--)
+ *tmp++ = *src++;
+
+ return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCPY
+void * memcpy(void * dest,const void *src,size_t count)
+{
+ char *tmp = (char *) dest, *s = (char *) src;
+
+ while (count--)
+ *tmp++ = *s++;
+
+ return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMMOVE
+void * memmove(void * dest,const void *src,size_t count)
+{
+ char *tmp, *s;
+
+ if (dest <= src) {
+ tmp = (char *) dest;
+ s = (char *) src;
+ while (count--)
+ *tmp++ = *s++;
+ }
+ else {
+ tmp = (char *) dest + count;
+ s = (char *) src + count;
+ while (count--)
+ *--tmp = *--s;
+ }
+
+ return dest;
+}
+#endif
+
+#ifndef __HAVE_ARCH_MEMCMP
+int memcmp(const void * cs,const void * ct,size_t count)
+{
+ const unsigned char *su1, *su2;
+ signed char res = 0;
+
+ for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
+#endif
+
+/*
+ * find the first occurrence of byte 'c', or 1 past the area if none
+ */
+#ifndef __HAVE_ARCH_MEMSCAN
+void * memscan(void * addr, int c, size_t size)
+{
+ unsigned char * p = (unsigned char *) addr;
+
+ while (size) {
+ if (*p == c)
+ return (void *) p;
+ p++;
+ size--;
+ }
+ return (void *) p;
+}
+#endif
+
+#ifndef __HAVE_ARCH_STRSTR
+char * strstr(const char * s1,const char * s2)
+{
+ int l1, l2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *) s1;
+ l1 = strlen(s1);
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1,s2,l2))
+ return (char *) s1;
+ s1++;
+ }
+ return NULL;
+}
+#endif
--- /dev/null
+/*
+ * linux/lib/vsprintf.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
+/*
+ * Wirzenius wrote this portably, Torvalds fucked it up :-)
+ */
+
+#include <stdarg.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+
+#include "config.h"
+#include "romfuncs.h"
+#include <asm/mpc8xx.h>
+#include <asm/8xx_immap.h>
+
+unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
+{
+ unsigned long result = 0,value;
+
+ if (!base) {
+ base = 10;
+ if (*cp == '0') {
+ base = 8;
+ cp++;
+ if ((*cp == 'x') && isxdigit(cp[1])) {
+ cp++;
+ base = 16;
+ }
+ }
+ }
+ while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp)
+ ? toupper(*cp) : *cp)-'A'+10) < base) {
+ result = result*base + value;
+ cp++;
+ }
+ if (endp)
+ *endp = (char *)cp;
+ return result;
+}
+
+long simple_strtol(const char *cp,char **endp,unsigned int base)
+{
+ if(*cp=='-')
+ return -simple_strtoul(cp+1,endp,base);
+ return simple_strtoul(cp,endp,base);
+}
+
+/* we use this so that we can do without the ctype library */
+#define is_digit(c) ((c) >= '0' && (c) <= '9')
+
+static int skip_atoi(const char **s)
+{
+ int i=0;
+
+ while (is_digit(**s))
+ i = i*10 + *((*s)++) - '0';
+ return i;
+}
+
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIAL 32 /* 0x */
+#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+static char * number(char * str, long num, int base, int size, int precision
+ ,int type)
+{
+ char c,sign,tmp[66];
+ const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ int i;
+
+ if (type & LARGE)
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIAL) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0)
+ tmp[i++] = digits[do_div(num,base)];
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT)))
+ while(size-->0)
+ *str++ = ' ';
+ if (sign)
+ *str++ = sign;
+ if (type & SPECIAL) {
+ if (base==8)
+ *str++ = '0';
+ else if (base==16) {
+ *str++ = '0';
+ *str++ = digits[33];
+ }
+ }
+ if (!(type & LEFT))
+ while (size-- > 0)
+ *str++ = c;
+ while (i < precision--)
+ *str++ = '0';
+ while (i-- > 0)
+ *str++ = tmp[i];
+ while (size-- > 0)
+ *str++ = ' ';
+ return str;
+}
+
+/* Forward decl. needed for IP address printing stuff... */
+int sprintf(char * buf, const char *fmt, ...);
+
+int vsprintf(char *buf, const char *fmt, va_list args)
+{
+ int len;
+ unsigned long num;
+ int i, base;
+ char * str;
+ const char *s;
+
+ int flags; /* flags to number() */
+
+ int field_width; /* width of output field */
+ int precision; /* min. # of digits for integers; max
+ number of chars for from string */
+ int qualifier; /* 'h', 'l', or 'L' for integer fields */
+
+ for (str=buf ; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+ *str++ = *fmt;
+ continue;
+ }
+
+ /* process flags */
+ flags = 0;
+ repeat:
+ ++fmt; /* this also skips first '%' */
+ switch (*fmt) {
+ case '-': flags |= LEFT; goto repeat;
+ case '+': flags |= PLUS; goto repeat;
+ case ' ': flags |= SPACE; goto repeat;
+ case '#': flags |= SPECIAL; goto repeat;
+ case '0': flags |= ZEROPAD; goto repeat;
+ }
+
+ /* get field width */
+ field_width = -1;
+ if (is_digit(*fmt))
+ field_width = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ field_width = va_arg(args, int);
+ if (field_width < 0) {
+ field_width = -field_width;
+ flags |= LEFT;
+ }
+ }
+
+ /* get the precision */
+ precision = -1;
+ if (*fmt == '.') {
+ ++fmt;
+ if (is_digit(*fmt))
+ precision = skip_atoi(&fmt);
+ else if (*fmt == '*') {
+ ++fmt;
+ /* it's the next argument */
+ precision = va_arg(args, int);
+ }
+ if (precision < 0)
+ precision = 0;
+ }
+
+ /* get the conversion qualifier */
+ qualifier = -1;
+ if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
+ qualifier = *fmt;
+ ++fmt;
+ }
+
+ /* default base */
+ base = 10;
+
+ switch (*fmt) {
+ case 'c':
+ if (!(flags & LEFT))
+ while (--field_width > 0)
+ *str++ = ' ';
+ *str++ = (unsigned char) va_arg(args, int);
+ while (--field_width > 0)
+ *str++ = ' ';
+ continue;
+
+ case 's':
+ s = va_arg(args, char *);
+ if (!s)
+ s = "<NULL>";
+
+ len = strnlen(s, precision);
+
+ if (!(flags & LEFT))
+ while (len < field_width--)
+ *str++ = ' ';
+ for (i = 0; i < len; ++i)
+ *str++ = *s++;
+ while (len < field_width--)
+ *str++ = ' ';
+ continue;
+
+ case 'p':
+ if (field_width == -1) {
+ field_width = 2*sizeof(void *);
+ flags |= ZEROPAD;
+ }
+ str = number(str,
+ (unsigned long) va_arg(args, void *), 16,
+ field_width, precision, flags);
+ continue;
+
+
+ case 'n':
+ if (qualifier == 'l') {
+ long * ip = va_arg(args, long *);
+ *ip = (str - buf);
+ } else {
+ int * ip = va_arg(args, int *);
+ *ip = (str - buf);
+ }
+ continue;
+
+ case '%':
+ *str++ = '%';
+ continue;
+
+ /* integer number formats - set up the flags and "break" */
+ case 'o':
+ base = 8;
+ break;
+
+ case 'X':
+ flags |= LARGE;
+ case 'x':
+ base = 16;
+ break;
+
+ case 'd':
+ case 'i':
+ flags |= SIGN;
+ case 'u':
+ break;
+
+ default:
+ *str++ = '%';
+ if (*fmt)
+ *str++ = *fmt;
+ else
+ --fmt;
+ continue;
+ }
+ if (qualifier == 'l')
+ num = va_arg(args, unsigned long);
+ else if (qualifier == 'h') {
+ num = (unsigned short) va_arg(args, int);
+ if (flags & SIGN)
+ num = (short) num;
+ } else if (flags & SIGN)
+ num = va_arg(args, int);
+ else
+ num = va_arg(args, unsigned int);
+ str = number(str, num, base, field_width, precision, flags);
+ }
+ *str = '\0';
+ return str-buf;
+}
+
+int sprintf(char * buf, const char *fmt, ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i=vsprintf(buf,fmt,args);
+ va_end(args);
+ return i;
+}
+
+// static char printbuffer[256];
+
+/* damm:
+ * i've put the printbuffer on the stack - good for printouts without dram */
+
+void printf(const char *fmt, ...)
+{
+ va_list args;
+ uint i;
+ char printbuffer[256]; // damm
+ char *cp;
+
+ va_start(args, fmt);
+
+ /* For this to work, printbuffer must be larger than
+ * anything we ever want to print.
+ */
+ i = vsprintf(printbuffer, fmt, args);
+ va_end(args);
+
+ cp = printbuffer;
+ while (i-- > 0) {
+ serial_putc(*cp);
+ if (*cp == '\n')
+ serial_putc('\r');
+ cp++;
+ }
+}
+
+/* Convert an ascii string to a hex number.
+*/
+static char *hexdigits = "0123456789abcdefABCDEF";
+
+uint
+asc_to_hex(char *cp, ulong *val)
+{
+ char *lp;
+ uint loc, hexval, cnvbytes;
+
+ /* If the first two characters are "0x", skip them.
+ */
+ if ((*cp == '0') && (*(cp + 1) == 'x'))
+ cp += 2;
+
+ hexval = cnvbytes = 0;
+ while (*cp != 0) {
+ lp = strchr(hexdigits, *cp);
+ if (lp != NULL) {
+ /* Found a character we can convert.
+ */
+ hexval *= 16;
+ loc = lp - hexdigits;
+ if (loc > 15) /* Accomodate upper case */
+ loc -= 6;
+ hexval += loc;
+ }
+ else {
+ /* Found something we can't convert. We are done.
+ */
+ *val = hexval;
+ return cnvbytes;
+ }
+ cnvbytes++;
+ cp++;
+ }
+ *val = hexval;
+ return cnvbytes;
+}
+
+void panic(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ printf(fmt);
+ va_end(args);
+
+ /* Hang */
+ for(;;);
+}
--- /dev/null
+#
+# Makefile for the FADS ROM CPU specific parts
+#
+
+TOPLEVEL = ..
+
+LIB = libsys.a
+OBJS = m8xx.o ppcstring.o serial.o traps.o
+
+all: $(LIB)
+
+include $(TOPLEVEL)/Make.config
+
+$(LIB): $(OBJS)
+ $(AR) cr $@ $(OBJS)
+
+clean:
+ rm -f $(OBJS) $(LIB)
+
+# Dependencies.....This should either be automatic or finished.
+start.o: Makefile ppc_asm.tmpl ppc_defs.h
+serial.o: Makefile
--- /dev/null
+/*
+ * m8xx.c
+ *
+ * mpc8xx specific code
+ *
+ * written or collected and sometimes rewritten by
+ * Magnus Damm <damm@bitsmart.com>
+ */
+
+#include "config.h"
+
+#define CONFIG_M8XX 1
+
+#include "romfuncs.h"
+#include <asm/cache.h>
+#include <asm/8xx_immap.h>
+
+int m8xx_checkicache(void);
+int m8xx_checkdcache(void);
+
+#ifdef MPC860
+int m8xx_checkCPU(uint pvr, uint immr)
+{
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ uint k, m;
+
+ /* the highest 16 bits should be 0x0050 for a 860 */
+
+ if((pvr >> 16) != 0x0050)
+ return -1;
+
+ k = (immr << 16) | *((ushort *) &immap->im_cpm.cp_dparam[0xb0]);
+ m = 0;
+
+ switch(k)
+ {
+ case 0x00020001 : printf("pPC860xxZPnn"); break;
+ case 0x00030001 : printf("XPC860xxZPnn"); break;
+
+ case 0x00120003 : printf("XPC860xxZPnnA"); break;
+ case 0x00130003 : printf("XPC860xxZPnnA3"); break;
+
+ case 0x00200004 : printf("XPC860xxZPnnB"); break;
+
+ case 0x00300004 : printf("XPC860xxZPnnC"); break;
+ case 0x00310004 : printf("XPC860xxZPnnC1"); m = 1; break;
+
+
+ case 0x00200064 : printf("XPC860SRZPnnB"); break;
+ case 0x00300065 : printf("XPC860SRZPnnC"); break;
+ case 0x00310065 : printf("XPC860SRZPnnC1"); m = 1; break;
+
+ /* this value is not documented anywhere */
+
+ case 0x40000000 : printf("PPC860PZPnnD"); m = 1; break;
+
+ default: printf("unknown 860 (0x%08x)", k);
+ }
+
+ printf(" at %u MHz:", (MPC8XX_FACT * MPC8XX_XIN) / 1000000);
+
+ printf(" %uKbyte icache", m8xx_checkicache() >> 10);
+ printf(" %uKbyte dcache", m8xx_checkdcache() >> 10);
+
+ /* lets check and see if we're running on a 860T (or P?) */
+
+ immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+ if(immap->im_cpm.cp_fec.fec_addr_low == 0x12345678)
+ printf(" fec present");
+
+ if(!m)
+ printf("\n\n<warning: cpu core has silicon bugs, check the errata>\n");
+
+ printf("\n");
+
+ return 0;
+}
+
+#elif MPC823
+
+int m8xx_checkCPU(uint pvr, uint immr)
+{
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ uint k, m;
+
+ /* the highest 16 bits should be 0x0050 for a 860 */
+
+ if((pvr >> 16) != 0x0050)
+ return -1;
+
+ k = (immr << 16) | *((ushort *) &immap->im_cpm.cp_dparam[0xb0]);
+ m = 0;
+
+ switch(k)
+ {
+ case 0x20010000: break;
+ default: printf("unknown 823 (0x%08x)", k);
+ }
+ printf(" at %u MHz:", (MPC8XX_FACT * MPC8XX_XIN) / 1000000);
+
+ printf(" %uKbyte icache", m8xx_checkicache() >> 10);
+ printf(" %uKbyte dcache", m8xx_checkdcache() >> 10);
+
+ /* lets check and see if we're running on a 860T (or P?) */
+
+ immap->im_cpm.cp_fec.fec_addr_low = 0x12345678;
+ if(immap->im_cpm.cp_fec.fec_addr_low == 0x12345678)
+ printf(" fec present");
+
+ if(!m)
+ printf("\n\n<warning: cpu core has silicon bugs, check the errata>\n");
+
+ printf("\n");
+
+ return 0;
+}
+#endif
+/* ------------------------------------------------------------------------- */
+
+int m8xx_checkcpu(void)
+{
+ uint immr = get_immr();
+ uint pvr = get_pvr();
+
+ /* 850 has PARTNUM 20 */
+ /* 801 has PARTNUM 10 */
+ return m8xx_checkCPU(pvr, immr);
+}
+
+/* ------------------------------------------------------------------------- */
+/* L1 i-cache */
+/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4Kbyte) */
+/* the 860 P (plus) has 256 sets of 16 bytes in 4 ways (= 16Kbyte) */
+
+int m8xx_checkicache(void)
+{
+ u32 cacheon = rd_ic_cst() & IDC_ENABLED;
+ u32 k = BR0_VALUE & ~0x00007fff; /* probe in flash memoryarea */
+ u32 m;
+ u32 lines = -1;
+
+ wr_ic_cst(IDC_UNALL);
+ wr_ic_cst(IDC_INVALL);
+ wr_ic_cst(IDC_DISABLE);
+ __asm__ volatile("isync");
+
+ while(!((m = rd_ic_cst()) & IDC_CERR2))
+ {
+ wr_ic_adr(k);
+ wr_ic_cst(IDC_LDLCK);
+ __asm__ volatile("isync");
+ lines++;
+ k += 0x10; /* the number of bytes in a cacheline */
+ }
+
+ wr_ic_cst(IDC_UNALL);
+ wr_ic_cst(IDC_INVALL);
+
+ if(cacheon)
+ wr_ic_cst(IDC_ENABLE);
+ else
+ wr_ic_cst(IDC_DISABLE);
+
+ __asm__ volatile("isync");
+
+ return lines << 4;
+};
+/* ------------------------------------------------------------------------- */
+/* L1 d-cache */
+/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4Kbyte) */
+/* the 860 P (plus) has 256 sets of 16 bytes in 2 ways (= 8Kbyte) */
+/* call with cache disabled */
+
+int m8xx_checkdcache(void)
+{
+ u32 cacheon = rd_dc_cst() & IDC_ENABLED;
+ u32 k = BR0_VALUE & ~0x00007fff; /* probe in flash memoryarea */
+ u32 m;
+ u32 lines = -1;
+
+ wr_dc_cst(IDC_UNALL);
+ wr_dc_cst(IDC_INVALL);
+ wr_dc_cst(IDC_DISABLE);
+
+ while(!((m = rd_dc_cst()) & IDC_CERR2))
+ {
+ wr_dc_adr(k);
+ wr_dc_cst(IDC_LDLCK);
+ lines++;
+ k += 0x10; /* the number of bytes in a cacheline */
+ }
+
+ wr_dc_cst(IDC_UNALL);
+ wr_dc_cst(IDC_INVALL);
+
+ if(cacheon)
+ wr_dc_cst(IDC_ENABLE);
+ else
+ wr_dc_cst(IDC_DISABLE);
+
+ return lines << 4;
+};
+
+/* ------------------------------------------------------------------------- */
+
+void m8xx_upmconfig(uint upm, uint *table, uint size)
+{
+ uint i;
+ uint addr = 0;
+ volatile immap_t *immap = (immap_t *)IMAP_ADDR;
+ volatile memctl8xx_t *memctl = &immap->im_memctl;
+
+ for (i = 0; i < size; i++)
+ {
+ memctl->memc_mdr = table[i]; /* (16-15) */
+ memctl->memc_mcr = addr | upm; /* (16-16) */
+ addr++;
+ }
+}
+
+/* ------------------------------------------------------------------------- */
+
+
+
+
+
+
--- /dev/null
+/*
+ * m8xx.h
+ *
+ * mpc8xx specific code
+ *
+ * collected and sometimes rewritten by Magnus Damm <damm@bitsmart.com>
+ */
+
+#ifndef __M8XX_H__
+#define __M8XX_H__ 1
+
+#include "types.h"
+
+int m8xx_checkcpu(void);
+
+#define UPMA 0x00000000
+#define UPMB 0x00800000
+
+void m8xx_upmconfig(uint upm, uint *table, uint size);
+
+#endif /* __M8XX_H__ */
+
+
+
+
+
--- /dev/null
+/*
+ * This file contains all the macros and symbols which define
+ * a PowerPC assembly language environment.
+ */
+
+/* Register names */
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+
+
+/* Some special registers */
+
+#define TBRU 269 /* Time base Upper/Lower (Reading) */
+#define TBRL 268
+#define TBWU 284 /* Time base Upper/Lower (Writing) */
+#define TBWL 285
+#define XER 1
+#define LR 8
+#define CTR 9
+#define HID0 1008 /* Hardware Implementation */
+#define PVR 287 /* Processor Version */
+#define SDR1 25 /* MMU hash base register */
+#define DAR 19 /* Data Address Register */
+#define SPR0 272 /* Supervisor Private Registers */
+#define SPRG0 272
+#define SPR1 273
+#define SPRG1 273
+#define SPR2 274
+#define SPRG2 274
+#define SPR3 275
+#define SPRG3 275
+#define DSISR 18
+#define SRR0 26 /* Saved Registers (exception) */
+#define SRR1 27
+#define DEC 22 /* Decrementer */
+#define EAR 282 /* External Address Register */
+#define DER 149
+#define ICTRL 158
+
+
+
+
+/* Registers in the processor's internal memory map that we use.
+*/
+#define IMMR 0xff000000
+
+#define SYPCR 0x00000004
+#define BR0 0x00000100
+#define OR0 0x00000104
+#define BR1 0x00000108
+#define OR1 0x0000010c
+#define BR2 0x00000110
+#define OR2 0x00000114
+#define BR3 0x00000118
+#define OR3 0x0000011c
+#define BR4 0x00000120
+#define OR4 0x00000124
+
+#define MAR 0x00000164
+#define MCR 0x00000168
+#define MAMR 0x00000170
+#define MBMR 0x00000174
+#define MSTAT 0x00000178
+#define MPTPR 0x0000017a
+#define MDR 0x0000017c
+
+#define TBSCR 0x00000200
+#define TBREFF0 0x00000204
+
+#define PLPRCR 0x00000284
+
+#define curptr r2
+
+#define SYNC \
+ sync; \
+ isync
+
+/*
+ * Macros for storing registers into and loading registers from
+ * exception frames.
+ */
+#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
+#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
+#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
+#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+
+/*
+ * GCC sometimes accesses words at negative offsets from the stack
+ * pointer, although the SysV ABI says it shouldn't. To cope with
+ * this, we leave this much untouched space on the stack on exception
+ * entry.
+ */
+#define STACK_UNDERHEAD 64
+
+#if 0
+#define tophys(rd,rs,rt) addis rd,rs,-KERNELBASE@h
+#define tovirt(rd,rs,rt) addis rd,rs,KERNELBASE@h
+#else
+#define tophys(rd,rs,rt) mr rd,rs
+#define tovirt(rd,rs,rt) mr rd,rs
+#endif
+
+/*
+ * Exception entry code. This code runs with address translation
+ * turned off, i.e. using physical addresses.
+ * We assume sprg3 has the physical address of the current
+ * task's thread_struct.
+ */
+#define EXCEPTION_PROLOG \
+ mtspr SPRG0,r20; \
+ mtspr SPRG1,r21; \
+ mfcr r20; \
+ tophys(r21,r1,r21); /* use tophys(kernel sp) otherwise */ \
+ subi r21,r21,INT_FRAME_SIZE+STACK_UNDERHEAD; /* alloc exc. frame */\
+1: stw r20,_CCR(r21); /* save registers */ \
+ stw r22,GPR22(r21); \
+ stw r23,GPR23(r21); \
+ mfspr r20,SPRG0; \
+ stw r20,GPR20(r21); \
+ mfspr r22,SPRG1; \
+ stw r22,GPR21(r21); \
+ mflr r20; \
+ stw r20,_LINK(r21); \
+ mfctr r22; \
+ stw r22,_CTR(r21); \
+ mfspr r20,XER; \
+ stw r20,_XER(r21); \
+ mfspr r22,SRR0; \
+ mfspr r23,SRR1; \
+ stw r0,GPR0(r21); \
+ stw r1,GPR1(r21); \
+ stw r2,GPR2(r21); \
+ stw r1,0(r21); \
+ tovirt(r1,r21,r1); /* set new kernel sp */ \
+ SAVE_4GPRS(3, r21);
+/*
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r21, r22 (SRR0), and r23 (SRR1).
+ */
+
+/*
+ * Exception vectors.
+ */
+#define STD_EXCEPTION(n, label, hdlr) \
+ . = n; \
+label: \
+ EXCEPTION_PROLOG; \
+ lis r3, transfer_to_handler@h; \
+ ori r3, r3, transfer_to_handler@l; \
+ mtlr r3; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ li r20,MSR_KERNEL; \
+ blrl ; \
+ .long hdlr; \
+ .long int_return
--- /dev/null
+/*
+ * WARNING! This file is automatically generated - DO NOT EDIT!
+ */
+#define KERNELBASE -1073741824
+#define STATE 0
+#define NEXT_TASK 64
+#define COUNTER 52
+#define PROCESSOR 916
+#define SIGPENDING 8
+#define TSS 576
+#define MM 880
+#define TASK_STRUCT_SIZE 928
+#define KSP 0
+#define PG_TABLES 4
+#define PGD 8
+#define LAST_SYSCALL 20
+#define PT_REGS 12
+#define PF_TRACESYS 32
+#define TASK_FLAGS 4
+#define TSS_FPR0 24
+#define TSS_FPSCR 284
+#define TSS_SMP_FORK_RET 288
+#define TASK_UNION_SIZE 8192
+#define STACK_FRAME_OVERHEAD 16
+#define INT_FRAME_SIZE 192
+#define GPR0 16
+#define GPR1 20
+#define GPR2 24
+#define GPR3 28
+#define GPR4 32
+#define GPR5 36
+#define GPR6 40
+#define GPR7 44
+#define GPR8 48
+#define GPR9 52
+#define GPR10 56
+#define GPR11 60
+#define GPR12 64
+#define GPR13 68
+#define GPR14 72
+#define GPR15 76
+#define GPR16 80
+#define GPR17 84
+#define GPR18 88
+#define GPR19 92
+#define GPR20 96
+#define GPR21 100
+#define GPR22 104
+#define GPR23 108
+#define GPR24 112
+#define GPR25 116
+#define GPR26 120
+#define GPR27 124
+#define GPR28 128
+#define GPR29 132
+#define GPR30 136
+#define GPR31 140
+#define _NIP 144
+#define _MSR 148
+#define _CTR 156
+#define _LINK 160
+#define _CCR 168
+#define _XER 164
+#define _DAR 180
+#define _DSISR 184
+#define ORIG_GPR3 152
+#define RESULT 188
+#define TRAP 176
--- /dev/null
+/*
+ * String handling functions for PowerPC.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * 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.
+ */
+#include <linux/config.h>
+#include "../kernel/ppc_asm.tmpl"
+#include <asm/processor.h>
+#include <asm/errno.h>
+
+ .globl strcpy
+strcpy:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+ .globl strncpy
+strncpy:
+ cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r6)
+ bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
+ blr
+
+ .globl strcat
+strcat:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r0,1(r5)
+ cmpwi 0,r0,0
+ bne 1b
+ addi r5,r5,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r5)
+ bne 1b
+ blr
+
+ .globl strcmp
+strcmp:
+ addi r5,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r5)
+ cmpwi 1,r3,0
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ beqlr 1
+ beq 1b
+ blr
+
+ .globl strlen
+strlen:
+ addi r4,r3,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ bne 1b
+ subf r3,r3,r4
+ blr
+
+ .globl memset
+memset:
+ rlwimi r4,r4,8,16,23
+ rlwimi r4,r4,16,0,15
+ addi r6,r3,-4
+ cmplwi 0,r5,4
+ blt 7f
+ stwu r4,4(r6)
+ beqlr
+ andi. r0,r6,3
+ add r5,r0,r5
+ subf r6,r0,r6
+ rlwinm r0,r5,32-2,2,31
+ mtctr r0
+ bdz 6f
+1: stwu r4,4(r6)
+ bdnz 1b
+6: andi. r5,r5,3
+7: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r6,r6,3
+8: stbu r4,1(r6)
+ bdnz 8b
+ blr
+
+ .globl bcopy
+bcopy:
+ mr r6,r3
+ mr r3,r4
+ mr r4,r6
+ b memcpy
+
+ .globl memmove
+memmove:
+ cmplw 0,r3,r4
+ bgt backwards_memcpy
+ /* fall through */
+
+ .globl memcpy
+memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ addi r6,r3,-4
+ addi r4,r4,-4
+ beq 2f /* if less than 8 bytes to do */
+ andi. r0,r6,3 /* get dest word aligned */
+ mtctr r7
+ bne 5f
+1: lwz r7,4(r4)
+ lwzu r8,8(r4)
+ stw r7,4(r6)
+ stwu r8,8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,4(r4)
+ addi r5,r5,-4
+ stwu r0,4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r4,r4,3
+ addi r6,r6,3
+4: lbzu r0,1(r4)
+ stbu r0,1(r6)
+ bdnz 4b
+ blr
+5: subfic r0,r0,4
+ mtctr r0
+6: lbz r7,4(r4)
+ addi r4,r4,1
+ stb r7,4(r6)
+ addi r6,r6,1
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl backwards_memcpy
+backwards_memcpy:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ add r6,r3,r5
+ add r4,r4,r5
+ beq 2f
+ andi. r0,r6,3
+ mtctr r7
+ bne 5f
+1: lwz r7,-4(r4)
+ lwzu r8,-8(r4)
+ stw r7,-4(r6)
+ stwu r8,-8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+ lwzu r0,-4(r4)
+ subi r5,r5,4
+ stwu r0,-4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+4: lbzu r0,-1(r4)
+ stbu r0,-1(r6)
+ bdnz 4b
+ blr
+5: mtctr r0
+6: lbzu r7,-1(r4)
+ stbu r7,-1(r6)
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+
+ .globl memcmp
+memcmp:
+ cmpwi 0,r5,0
+ ble- 2f
+ mtctr r5
+ addi r6,r3,-1
+ addi r4,r4,-1
+1: lbzu r3,1(r6)
+ lbzu r0,1(r4)
+ subf. r3,r0,r3
+ bdnzt 2,1b
+ blr
+2: li r3,0
+ blr
+
+ .global memchr
+memchr:
+ cmpwi 0,r5,0
+ ble- 2f
+ mtctr r5
+ addi r3,r3,-1
+1: lbzu r0,1(r3)
+ cmpw 0,r0,r4
+ bdnzf 2,1b
+ beqlr
+2: li r3,0
+ blr
+
+ .globl __copy_tofrom_user
+__copy_tofrom_user:
+ rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
+ addi r6,r3,-4
+ addi r4,r4,-4
+ li r3,0 /* success return value */
+ beq 2f /* if less than 8 bytes to do */
+ andi. r0,r6,3 /* get dest word aligned */
+ mtctr r7
+ bne 5f
+1: lwz r7,4(r4)
+11: lwzu r8,8(r4)
+12: stw r7,4(r6)
+13: stwu r8,8(r6)
+ bdnz 1b
+ andi. r5,r5,7
+2: cmplwi 0,r5,4
+ blt 3f
+14: lwzu r0,4(r4)
+ addi r5,r5,-4
+15: stwu r0,4(r6)
+3: cmpwi 0,r5,0
+ beqlr
+ mtctr r5
+ addi r4,r4,3
+ addi r6,r6,3
+4: lbzu r0,1(r4)
+16: stbu r0,1(r6)
+ bdnz 4b
+ blr
+5: subfic r0,r0,4
+ mtctr r0
+6: lbz r7,4(r4)
+ addi r4,r4,1
+17: stb r7,4(r6)
+ addi r6,r6,1
+ bdnz 6b
+ subf r5,r0,r5
+ rlwinm. r7,r5,32-3,3,31
+ beq 2b
+ mtctr r7
+ b 1b
+99: li r3,-EFAULT
+ blr
+.section __ex_table,"a"
+ .align 2
+ .long 1b,99b
+ .long 11b,99b
+ .long 12b,99b
+ .long 13b,99b
+ .long 14b,99b
+ .long 15b,99b
+ .long 4b,99b
+ .long 16b,99b
+ .long 6b,99b
+ .long 17b,99b
+.text
+
+#undef CLEAR_USE_DCBZ 1
+#undef CLEAR_NO_CACHE 1
+ .globl __clear_user
+__clear_user:
+ addi r6,r3,-4
+ li r3,0
+ li r5,0
+ cmplwi 0,r4,4
+ blt 7f
+ /* clear a single word */
+11: stwu r5,4(r6)
+ beqlr
+#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx)
+ /*
+ * no reason to turn off the cache for a single word
+ * or a few bytes -- Cort
+ */
+ mfspr r7,HID0
+ ori r8,r7,HID0_DLOCK
+ mtspr HID0,r8
+#endif /* CLEAR_NO_CACHE */
+ /* clear word sized chunks */
+ andi. r0,r6,3
+ add r4,r0,r4
+ subf r6,r0,r6
+ /*rlwinm r0,r4,32-2,2,31*/
+ srwi r0,r4,2
+ mtctr r0
+ bdz 6f
+1: stwu r5,4(r6)
+ bdnz 1b
+6: andi. r4,r4,3
+#if defined(CLEAR_NO_CACHE) && defined (CONFIG_6xx)
+ /* restore the original state of HID0 in case cache was off -- Cort */
+ mtspr HID0,r7
+#endif /* CLEAR_NO_CACHE */
+ /* clear byte sized chunks */
+7: cmpwi 0,r4,0
+ beqlr
+ mtctr r4
+ addi r6,r6,3
+8: stbu r5,1(r6)
+ bdnz 8b
+ blr
+99: li r3,-EFAULT
+ blr
+.section __ex_table,"a"
+ .align 2
+ .long 11b,99b
+ .long 1b,99b
+#ifdef CLEAR_USE_DCBZ
+ /*.long 66b,99b*/
+#endif
+ .long 8b,99b
+.text
+
+ .globl __strncpy_from_user
+__strncpy_from_user:
+ addi r6,r3,-1
+ addi r4,r4,-1
+ cmpwi 0,r5,0
+ beq 2f
+ mtctr r5
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ stbu r0,1(r6)
+ bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
+ beq 3f
+2: addi r6,r6,1
+3: subf r3,r3,r6
+ blr
+99: li r3,-EFAULT
+ blr
+.section __ex_table,"a"
+ .align 2
+ .long 1b,99b
+.text
+
+ .globl strlen_user
+strlen_user:
+ addi r4,r3,-1
+1: lbzu r0,1(r4)
+ cmpwi 0,r0,0
+ bne 1b
+ subf r3,r3,r4
+ addi r3,r3,1
+ blr
+99: li r3,0
+ blr
+.section __ex_table,"a"
+ .align 2
+ .long 1b,99b
--- /dev/null
+
+
+/* Minimal serial functions needed to send messages out the serial
+ * port on SMC1.
+ */
+
+#include "romfuncs.h"
+#include "commproc.h"
+
+void
+serial_init(bd_t *bd)
+{
+ volatile immap_t *im = (immap_t *)IMAP_ADDR;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8xx_t *cp = &(im->im_cpm);
+ uint dpaddr;
+
+#if (CONFIG_CON_SMC == 1)
+
+ /* initialize pointers to SMC1 */
+
+ sp = (smc_t *) &(cp->cp_smc[0]);
+ up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC1];
+
+ /* Use Port B for SMC1 instead of other functions.
+ */
+ cp->cp_pbpar |= 0x000000c0;
+ cp->cp_pbdir &= ~0x000000c0;
+ cp->cp_pbodr &= ~0x000000c0;
+
+#if (defined(CONFIG_FADS) || defined(CONFIG_ADS))
+
+ /* Enable RS232 port 1 in BCSR1
+ */
+ *((uint *)BCSR1) &= ~0x01000000;
+#endif
+
+#elif (CONFIG_CON_SMC == 2)
+
+ /* initialize pointers to SMC2 */
+
+ sp = (smc_t *) &(cp->cp_smc[1]);
+ up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC2];
+
+ /* Use Port B for SMC2 instead of other functions.
+ */
+ cp->cp_pbpar |= 0x00000c00;
+ cp->cp_pbdir &= ~0x00000c00;
+ cp->cp_pbodr &= ~0x00000c00;
+
+#if (defined(CONFIG_FADS) || defined(CONFIG_ADS))
+
+ /* Enable RS232 port 2 in BCSR1
+ */
+ *((uint *)BCSR1) &= ~0x00040000;
+#endif
+
+#else /* CONFIG_CON_SMC */
+#error "console not correctly defined"
+#endif
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* Enable SDMA.
+ */
+ im->im_siu_conf.sc_sdcr = 1;
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = 0x800;
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+
+ rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+
+ /* Set up the baud rate generator 1.
+ * See 8xx_io/commproc.c for details.
+ */
+
+ cp->cp_brgc1 =
+ ((((bd->bi_intfreq * 1000000)/16) / 9600) << 1) | CPM_BRG_EN;
+
+#if (CONFIG_CON_SMC == 1)
+
+ cp->cp_simode &= 0xffff0fff; /* connect brg1 to smc1 */
+
+#else
+
+ cp->cp_simode &= 0x0fffffff; /* connect brg1 to smc2 */
+#endif
+
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Single character receive.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+
+ /* Initialize Tx/Rx parameters.
+ */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+#if (CONFIG_CON_SMC == 1)
+
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+#else
+
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC2, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+#endif
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+}
+
+void
+serial_putc(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile cpm8xx_t *cpmp = &(((immap_t *)IMAP_ADDR)->im_cpm);
+
+#if (CONFIG_CON_SMC == 1)
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1];
+#else
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC2];
+#endif
+
+ tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
+
+#if 1
+ /* Wait for last character to go.
+ */
+
+ buf = (char *)tbdf->cbd_bufaddr;
+ while (tbdf->cbd_sc & BD_SC_READY);
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+
+#else
+ buf = (char *)tbdf->cbd_bufaddr;
+ *buf = c;
+
+ // *((char *) tbdf->cbd_bufaddr) = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+
+
+ /* Wait for last character to go.
+ */
+
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+#endif
+
+}
+
+char
+serial_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile cpm8xx_t *cpmp;
+ char c;
+
+ cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+
+#if (CONFIG_CON_SMC == 1)
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1];
+#else
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC2];
+#endif
+
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ /* Wait for character to show up.
+ */
+ buf = (char *)rbdf->cbd_bufaddr;
+ while (rbdf->cbd_sc & BD_SC_EMPTY);
+ c = *buf;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(c);
+}
+
+int
+serial_tstc()
+{
+ volatile cbd_t *rbdf;
+ volatile smc_uart_t *up;
+ volatile cpm8xx_t *cpmp;
+
+ cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
+
+#if (CONFIG_CON_SMC == 1)
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC1];
+#else
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC2];
+#endif
+
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
+
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * The processor starts at 0x00000100 and the code is executed
+ * from flash. The code is organized to be at an other address
+ * in memory, but as long we don't jump around before relocating.
+ * board_init lies at a quite high address and when the cpu has
+ * jumped there, everything is ok.
+ * This works because the cpu gives the flash (CS0) the whole
+ * address space at startup, and board_init lies as a echo of
+ * the flash somewhere up there in the memorymap.
+ *
+ * board_init will change CS0 to be positioned at the correct
+ * address and (s)dram will be positioned at address 0
+ */
+#include "config.h"
+
+#define CONFIG_8xx 1
+#define _LINUX_CONFIG_H 1
+
+#include "ppc_asm.tmpl"
+#include "ppc_defs.h"
+
+#include <asm/processor.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <board/board.h>
+
+/* We don't want the MMU yet.
+*/
+#undef MSR_KERNEL
+#define MSR_KERNEL MSR_
+
+ .text
+ .globl version_string
+version_string:
+ .string "8xxROM 0.3.0"
+ . = 0x100
+ .globl _start
+_start:
+ /* the original fadsrom code by Dan Malek did a lot of setup */
+ /* in assembler, I moved most of the code to C for readability */
+
+ li r10, MSR_ /* Set ME, RI flags */
+ mtmsr r10
+ mtspr SRR1, r10 /* Make SRR1 match MSR */
+
+ /* position IMMR and set up the stack to the internal DPRAM */
+
+ lis r1, IMMR_VALUE@h
+ mtspr 638, r1
+ ori r1,r1,0x3000
+
+
+ /* Reset the caches.
+ */
+
+ lis r21, IDC_UNALL@h /* Unlock all */
+ mtspr IC_CST, r21
+ mtspr DC_CST, r21
+
+ lis r21, IDC_INVALL@h /* Invalidate all */
+ mtspr IC_CST, r21
+ mtspr DC_CST, r21
+
+ lis r21, IDC_DISABLE@h /* Disable data cache */
+ mtspr DC_CST, r21
+
+ lis r21, IDC_ENABLE@h /* Enable instruction cache */
+ mtspr IC_CST, r21
+
+ /* invalidate all tlb's */
+
+ tlbia
+ isync
+
+ /* initialize some sprs that are hard to access from c */
+
+ /* Disable serialized ifetch and show cycles (i.e. set processor
+ * to normal mode).
+ * this is also a silicon bug workaround, see errata
+ */
+
+ li r21, 0x0007
+ mtspr ICTRL, r21
+
+ /* Disable debug mode entry.
+ */
+
+ li r21, 0
+ mtspr DER, r21
+
+ /* let the c-code set up the rest */
+
+ lis r2,board_init@h
+ ori r2,r2,board_init@l
+ mtlr r2 /* Easiest way to do an absolute jump */
+ blr
+
+
+ .globl start_main
+
+start_main:
+
+ /* Initialize stack pointer and jump to main function.
+ * the c-code passed the stackpointer in r3 and the
+ * argument to main in r4.
+ */
+
+ mr r1, r3 /* first argument from c-code */
+ mr r3, r4 /* second argument to first */
+ mr r4, r5 /* third argument to second */
+ bl main_loop
+
+1: b 1b /* Loop forever if main exits */
+
+
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x300, DataStorage, UnknownException)
+
+/* Instruction Storage exception. "Never" generated on the 860. */
+ STD_EXCEPTION(0x400, InstStorage, UnknownException)
+
+/* External Interrupt exception. */
+ STD_EXCEPTION(0x500, ExtInterrupt, UnknownException)
+
+/* Alignment exception. */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ lis r6, transfer_to_handler@h
+ ori r6, r6, transfer_to_handler@l
+ mtlr r6
+ blrl
+ .long AlignmentException
+ .long int_return
+
+/* Program check exception */
+ . = 0x700
+ProgramCheck:
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ lis r6, transfer_to_handler@h
+ ori r6, r6, transfer_to_handler@l
+ mtlr r6
+ blrl
+ .long ProgramCheckException
+ .long int_return
+
+ /* No FPU on MPC8xx. This exception is not supposed to happen.
+ */
+ STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
+
+ /* I guess we could implement decrementer, and may have
+ * to someday for timekeeping.
+ */
+ STD_EXCEPTION(0x900, Decrementer, UnknownException)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
+
+ STD_EXCEPTION(0xc00, SystemCall, UnknownException)
+ STD_EXCEPTION(0xd00, SingleStep, UnknownException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
+
+ /* On the MPC8xx, this is a software emulation interrupt. It occurs
+ * for all unimplemented and illegal instructions.
+ */
+ STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
+
+ STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
+ STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
+ STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
+
+ STD_EXCEPTION(0x1500, Reserved5, UnknownException)
+ STD_EXCEPTION(0x1600, Reserved6, UnknownException)
+ STD_EXCEPTION(0x1700, Reserved7, UnknownException)
+ STD_EXCEPTION(0x1800, Reserved8, UnknownException)
+ STD_EXCEPTION(0x1900, Reserved9, UnknownException)
+ STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
+ STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
+
+ STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
+ STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+
+
+ .globl _end_of_vectors
+_end_of_vectors:
+
+
+ . = 0x2000
+
+/*
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception.
+ * Register r21 is pointer into trap frame, r1 has new stack pointer.
+ */
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ lis r22,MSR_POW@h
+ andc r23,r23,r22
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+#if 0
+ andi. r23,r23,MSR_PR
+ mfspr r23,SPRG3 /* if from user, fix up tss.regs */
+ beq 2f
+ addi r24,r1,STACK_FRAME_OVERHEAD
+ stw r24,PT_REGS(r23)
+2: addi r2,r23,-TSS /* set r2 to current */
+ tovirt(r2,r2,r23)
+#endif
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ mtspr SPRG2,r22 /* r1 is now kernel sp */
+#if 0
+ addi r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */
+ cmplw 0,r1,r2
+ cmplw 1,r1,r24
+ crand 1,1,4
+ bgt stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */
+#endif
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
+
+int_return:
+ mfmsr r30 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r30,r30,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r30
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/* Cache functions.
+*/
+ .globl icache_enable
+icache_enable:
+ SYNC
+ lis r3, IDC_INVALL@h
+ mtspr IC_CST, r3
+ lis r3, IDC_ENABLE@h
+ mtspr IC_CST, r3
+ blr
+
+ .globl icache_disable
+icache_disable:
+ SYNC
+ lis r3, IDC_DISABLE@h
+ mtspr IC_CST, r3
+ blr
+
+ .globl dcache_enable
+dcache_enable:
+#if 0
+ SYNC
+#endif
+#if 1
+ lis r3, 0x0400 /* Set cache mode with MMU off */
+ mtspr MD_CTR, r3
+#endif
+
+ lis r3, IDC_INVALL@h
+ mtspr DC_CST, r3
+#if 0
+ lis r3, DC_SFWT@h
+ mtspr DC_CST, r3
+#endif
+ lis r3, IDC_ENABLE@h
+ mtspr DC_CST, r3
+ blr
+
+ .globl dcache_disable
+dcache_disable:
+ SYNC
+ lis r3, IDC_DISABLE@h
+ mtspr DC_CST, r3
+ lis r3, IDC_INVALL@h
+ mtspr DC_CST, r3
+ blr
+
+ .globl dc_stat
+dc_stat:
+ mfspr r3, DC_CST
+ blr
+
+ .globl dc_read
+dc_read:
+ mtspr DC_ADR, r3
+ mfspr r3, DC_DAT
+ blr
+
+ .globl udelay
+udelay:
+ mulli r4,r3,1000 /* nanoseconds */
+ addi r4,r4,59
+ li r5,60
+ 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
+3: blr
+
+
+ .globl get_immr
+get_immr:
+ mfspr r3, 638
+ blr
+
+ .globl get_pvr
+get_pvr:
+ mfspr r3, PVR
+ blr
+
+
+ .globl wr_ic_cst
+wr_ic_cst:
+ mtspr IC_CST, r3
+ blr
+
+ .globl rd_ic_cst
+rd_ic_cst:
+ mfspr r3, IC_CST
+ blr
+
+ .globl wr_ic_adr
+wr_ic_adr:
+ mtspr IC_ADR, r3
+ blr
+
+
+ .globl wr_dc_cst
+wr_dc_cst:
+ mtspr DC_CST, r3
+ blr
+
+ .globl rd_dc_cst
+rd_dc_cst:
+ mfspr r3, DC_CST
+ blr
+
+ .globl wr_dc_adr
+wr_dc_adr:
+ mtspr DC_ADR, r3
+ blr
+
+
--- /dev/null
+/*
+ * linux/arch/ppc/kernel/traps.c
+ *
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * 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.
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * and Paul Mackerras (paulus@cs.anu.edu.au)
+ */
+
+/*
+ * This file handles the architecture-dependent parts of hardware exceptions
+ */
+
+#include "romfuncs.h"
+#include <linux/types.h>
+#include <asm/processor.h>
+
+/* Returns 0 if exception not found and fixup otherwise. */
+extern unsigned long search_exception_table(unsigned long);
+
+/* THIS NEEDS CHANGING to use the board info structure.
+*/
+#define END_OF_MEM 0x00400000
+
+/*
+ * Trap & Exception support
+ */
+
+void
+print_backtrace(unsigned long *sp)
+{
+ int cnt = 0;
+ unsigned long i;
+
+ printf("Call backtrace: ");
+ while (sp) {
+ if ((uint)sp > END_OF_MEM)
+ break;
+
+ i = sp[1];
+ if (cnt++ % 7 == 0)
+ printf("\n");
+ printf("%08lX ", i);
+ if (cnt > 32) break;
+ sp = (unsigned long *)*sp;
+ }
+ printf("\n");
+}
+
+void show_regs(struct pt_regs * regs)
+{
+ int i;
+
+ printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx\n",
+ regs->nip, regs->xer, regs->link, regs,regs->trap);
+ printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+
+ printf("\n");
+ for (i = 0; i < 32; i++) {
+ if ((i % 8) == 0)
+ {
+ printf("GPR%02d: ", i);
+ }
+
+ printf("%08lX ", regs->gpr[i]);
+ if ((i % 8) == 7)
+ {
+ printf("\n");
+ }
+ }
+}
+
+
+void
+_exception(int signr, struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
+}
+
+void
+MachineCheckException(struct pt_regs *regs)
+{
+ unsigned long fixup;
+
+ /* Probing PCI using config cycles cause this exception
+ * when a device is not present. Catch it and return to
+ * the PCI exception handler.
+ */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ regs->nip = fixup;
+ return;
+ }
+
+ printf("Machine check in kernel mode.\n");
+ printf("Caused by (from msr): ");
+ printf("regs %p ",regs);
+ switch( regs->msr & 0x0000F000)
+ {
+ case (1<<12) :
+ printf("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (1<<13) :
+ printf("Transfer error ack signal\n");
+ break;
+ case (1<<14) :
+ printf("Data parity signal\n");
+ break;
+ case (1<<15) :
+ printf("Address parity signal\n");
+ break;
+ default:
+ printf("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("machine check");
+}
+
+void
+AlignmentException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+/* Copy all of the exception handlers to memory.
+*/
+void
+trap_init(void)
+{
+ extern uint _start, _end_of_vectors;
+ uint *mp, *rp;
+
+ mp = (uint *) ((uint)&_start & 0x3fff);
+ rp = &_start;
+
+ while ((uint)rp < (uint)&_end_of_vectors)
+ *mp++ = *rp++;
+}
+
+/* Probe an address by reading. If not present, return -1, otherwise
+ * return 0.
+ */
+int
+addr_probe(uint *addr)
+{
+#if 0
+ int retval;
+
+ __asm__ __volatile__( \
+ "1: lwz %0,0(%1)\n" \
+ " eieio\n" \
+ " li %0,0\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3: li %0,-1\n" \
+ " b 2b\n" \
+ ".section __ex_table,\"a\"\n" \
+ " .align 2\n" \
+ " .long 1b,3b\n" \
+ ".text" \
+ : "=r" (retval) : "r"(addr));
+
+ return (retval);
+#endif
+ return 0;
+}
--- /dev/null
+#define _LINUX_CONFIG_H 1
+#include "config.h"
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/mpc8xx.h>
-
-/* FADS Boot ROM (skeleton :-).
- * Dan Malek.
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 <sys/types.h>
-#include "asm/fads.h"
-#include <asm/8xx_immap.h>
-
+#include "romfuncs.h"
+#include "fs/file.h"
/* The console monitor is a task in a big loop. It runs at a high
* priority, but is always waiting for console input.
* One command and up to four parameters. Keep a count of the
* number of parameters we find.
*/
-char *cmd;
+char *cmd = "bootz";
char *params[MAXPARMS];
-int nparams;
-int can_repeat;
+int nparams = 0;
+int can_repeat = 1;
/* Display values from last command.
* Memory modify remembered values are different from display memory.
void mod_mem(int);
void write_mem(void);
void loop_mem(void);
-void cf_boot(bd_t *);
-uint asc_to_hex(char *, uint *);
-/* Board information.
-*/
-bd_t *bdinfo;
-
-#define PGSZ 4096
+/* XXX: Changed from 0x1000 -> 0x10000 because the .data section
+ * begins at 0x10000 boundry (0xFE010000). */
+#define PGSZ 0x10000
#define roundup(x) (((x) + (PGSZ-1)) & ~(PGSZ-1))
-immap_t *immap;
+void hang(void)
+{
+ printf("\nboot not possible!\n");
-main()
+ while(1)
+ ;
+}
+
+void display_options(void)
{
- extern char version_string[];
- char ic;
+ extern char version_string[];
+
+ printf("\n\n%s\n\n", version_string);
+ printf("compiletime options: \n");
+
+ printf("board: ");
+
+#ifdef CONFIG_FADS
+ printf("FADS ");
+#endif
+
+#ifdef CONFIG_ADS
+ printf("ADS ");
+#endif
+
+#ifdef CONFIG_DRAM_25MHZ
+ printf("DRAM_25MHZ ");
+#endif
+
+#ifdef CONFIG_DRAM_50MHZ
+ printf("DRAM_50MHZ ");
+#endif
+
+#ifdef CONFIG_FADS
+#ifdef CONFIG_SDRAM_50MHZ
+ printf("SDRAM_50MHZ ");
+#endif
+
+#ifdef CONFIG_SDRAM_100MHZ
+ printf("SDRAM_100MHZ ");
+#endif
+#endif
+ printf("\n");
+
+#if defined(CONFIG_DISK_ROM) || defined(CONFIG_DISK_ATA)
+ printf("disk: ");
+
+#ifdef CONFIG_DISK_ROM
+ printf("DISK_ROM ");
+#endif
+
+#ifdef CONFIG_DISK_ATA
+ printf("DISK_ATA ");
+
+#ifdef CONFIG_DISK_ATA_PCMCIABUG
+ printf("PCMCIABUG ");
+#endif
+#endif
+
+ printf("\n");
+
+#endif /* defined(CONFIG_DISK_ROM) || defined(CONFIG_DISK_ATA) */
+
+ printf("\n");
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+int mem_check(uint base, uint nobytes)
+{
+ uint *p = (uint *) base;
+ uint *p2 = p + 1;
+ uint k;
+
+ /* test databus to memory */
+
+ *p = 0xffffffff;
+ *p2 = 0x00000000;
+
+ if(*p != 0xffffffff)
+ return -1;
+
+ *p = 0x00000000;
+ *p2 = 0xffffffff;
+
+ if(*p != 0x00000000)
+ return -1;
+
+ *p = 0xaaaaaaaa;
+ *p2 = 0x55555555;
+
+ if(*p != 0xaaaaaaaa)
+ return -1;
+
+ *p = 0x55555555;
+ *p2 = 0xaaaaaaaa;
+
+ if(*p != 0x55555555)
+ return -1;
+
+ /* do a wrap check */
+
+ k = 1;
+
+ *p = 0xdeadc0de;
+
+ while(*p == 0xdeadc0de)
+ {
+ *(p+k) = 0;
+ k <<= 1;
+
+ if(k == nobytes / sizeof(uint))
+ return 0;
+ }
+
+ return -1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+void create_board_info(bd_t *bi, uint memsize)
+{
+ bi->bi_memstart = 0;
+ bi->bi_memsize = memsize;
+ bi->bi_intfreq = MPC8XX_HZ / 1000000;
+ bi->bi_busfreq = bi->bi_intfreq;
+#ifdef MPC8XX_BUSDIV
+ bi->bi_busfreq = bi->bi_busfreq / MPC8XX_BUSDIV;
+#else
+ bi->bi_busfreq = bi->bi_intfreq;
+#endif
+ bi->bi_enetaddr[0] = 0x08;
+ bi->bi_enetaddr[1] = 0x00;
+ bi->bi_enetaddr[2] = 0x3e;
+ bi->bi_enetaddr[3] = 0x26;
+ bi->bi_enetaddr[4] = 0x15;
+ bi->bi_enetaddr[5] = 0x59;
+ bi->bi_baudrate = 9600;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+#if 0
+#define MAXCURDEV 7
+#define MAXCURPART 3
+
+static char curdev[MAXCURDEV+1] = " "; /* Must be 7 spaces here */
+static char curpart[MAXCURPART+1] = " "; /* Must be 3 spaces here */
+#endif
+
+void main_loop(uint memsize, uint status)
+{
+ bd_t *bdinfo;
uint *ip, *dp;
int i;
+
extern uint _erotext, __bss_start, _end;
/* First we need to copy all of the initialized data from
* This must remain below 8Mbytes so the kernel can find it
* when it boots.
*/
- bdinfo = (bd_t *)0x003f0000;
- bdinfo->bi_memstart = 0; /* Memory start address */
- bdinfo->bi_memsize = 0x00400000; /* Memory (end) size in bytes */
-#ifdef MHZ_50
- bdinfo->bi_intfreq = 50; /* Internal Freq, in Hz */
- bdinfo->bi_busfreq = 50; /* Bus Freq, in Hz */
-#else
- bdinfo->bi_intfreq = 40; /* Internal Freq, in Hz */
- bdinfo->bi_busfreq = 40; /* Bus Freq, in Hz */
-#endif
+ /* no 8Mbyte check for now - damm */
- immap = (immap_t *)IMAP_ADDR;
+ bdinfo = (bd_t *) (memsize - 0x10000); /* top of mem */
- /* Initialize the serial port.
- */
- serial_init(bdinfo);
+ create_board_info(bdinfo, memsize);
trap_init();
- /* Enable the PCMCIA for a Flash card.
- */
- immap->im_pcmcia.pcmc_pbr0 = 0xf0130000;
- immap->im_pcmcia.pcmc_por0 = 0xc00ff041;
- immap->im_pcmcia.pcmc_pgcra = 0;
- immap->im_pcmcia.pcmc_pgcrb = 0;
-
- /* Enable PCMCIA drivers and 3.3 voltage.
- */
- *((uint *)BCSR1) |= 0x00400000;
- *((uint *)BCSR1) &= ~0x00b10000;
-
- printf("\n%s", version_string);
-
+ disk_init(status);
+
/* Initialize some variables.
* We need legal values for display in case the first time the
* command is used they are not initialized.
*/
for (;;) {
- printf("\nrmon> ");
+ printf("\n%s:%u:%s> ", disk_devs[disk_currentdev].name,
+ disk_currentpart, file_cwd);
if (read_buffer() == KILL_BUFFER)
continue;
*/
if (cons_buffer[0] != 0) {
cons_parse();
- }
- else {
+ } else {
/* If we can repeat the last command, then do
* that. Otherwise, set the command buffer to
* NULL so we don't match any commands.
loop_mem();
continue;
}
- if (!strncmp(cmd, "icache", 5)) {
+ if (!strncmp(cmd, "mtest", 5)) {
+ do_memtest();
+ continue;
+ }
+ if (!strncmp(cmd, "icache", 6)) {
do_cache(0);
continue;
}
- if (!strncmp(cmd, "dcache", 5)) {
+ if (!strncmp(cmd, "dcache", 6)) {
do_cache(1);
continue;
}
- if (!strncmp(cmd, "cfload", 6)) {
- cf_load();
+
+ if (!strncmp(cmd, "load", 9)) {
+ disk_load();
continue;
}
- if (!strncmp(cmd, "cfident", 6)) {
- cf_ident();
+
+ if (!strncmp(cmd, "ident", 10)) {
+ disk_ident();
continue;
}
- if (!strncmp(cmd, "cfboot", 6)) {
- cf_boot(bdinfo);
+
+ if (!strncmp(cmd, "cd", 2)) {
+ if (nparams == 0) {
+ /* Back to the root */
+ file_cd("/");
+ } else {
+ file_cd(params[0]);
+ }
continue;
}
+ if (!strncmp(cmd, "ls", 2)) {
+ int i;
+
+ can_repeat = 1;
+ if (nparams == 0) {
+ file_ls("");
+ continue;
+ }
+ for (i = 0; i < nparams; i++) {
+ file_ls(params[i]);
+ }
+ continue;
+ }
+
+ if (!strncmp(cmd, "dev", 3)) {
+ disk_dev();
+ continue;
+ }
+
+ if (!strncmp(cmd, "bootz", 5)) {
+ elf_bootz(bdinfo);
+ continue;
+ }
+
+ if (!strncmp(cmd, "bootvmi", 7)) {
+ bootvm(bdinfo,1);
+ continue;
+ }
+
+ if (!strncmp(cmd, "bootvm", 6)) {
+ bootvm(bdinfo,0);
+ continue;
+ }
+
if ((strncmp(cmd, "he", 2) == 0) || (cmd[0] == '?')) {
do_help();
continue;
void
do_help()
{
-
printf("\n\n");
printf(" md[.b, .w, .l] address [# of objects]\n");
printf(" - memory display\n");
printf(" - enable or disable data (writethrough) cache\n");
printf(" mtest\n");
printf(" - simple SDRAM read/write test.\n");
- printf(" cfident\n");
- printf(" - Print Compact Flash identity\n");
- printf(" cfload host_addr LBA_sector num_sectors\n");
- printf(" - Read sectors from CF into memory.\n");
- printf(" cfboot [partition] [image]\n");
- printf(" - boot an image from the flash card\n");
+
+ printf(" load address startblock noblocks\n");
+ printf(" - load data from disk to memory.\n");
+
+ printf(" ident\n");
+ printf(" - identify devices.\n");
+
+ printf(" dev devname [partition] \n");
+ printf(" - select active disk device.\n");
+
+ printf(" cd\n");
+ printf(" - change current working directory.\n");
+
+ printf(" ls\n");
+ printf(" - show root directory on active disk.\n");
+
+ printf(" bootz [name] \n");
+ printf(" - boot a zImage from current disk.\n");
+
+ printf(" bootvm [name] \n");
+ printf(" - boot a vmlinux from current disk.\n");
+
+ printf(" bootvmi [vmname] [intrdname] \n");
+ printf(" - boot a vmlinux from current disk.\n");
+
printf(" ALL values are HEX\n");
printf("\n");
}
+
+// vim: st=4 noexpandtab cino=>4 cindent
-
-/* FADS ROM
- * Dan Malek (dmalek@jlc.net)
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
+ *
+ * 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 <sys/types.h>
-#include "asm/fads.h"
-#include <asm/8xx_immap.h>
-
+#include "romfuncs.h"
/* Just point to NULL terminated strings in the input buffer.
* One command and up to four parameters. Keep a count of the
extern char *params[];
extern int nparams;
extern int can_repeat;
-extern immap_t *immap;
extern char cons_buffer[];
/* Display values from last command.
*/
#define DISP_LINE_LEN 16
-static uint base_address;
+static ulong base_address;
void
disp_mem(void)
{
- uint start_addr, size, length;
- uint *longp, i, nbytes, linebytes;
+ ulong start_addr, size, length;
+ uint i, nbytes, linebytes;
u_char *cp;
/* We use the last specified parameters, unless new ones are
*/
nbytes = length * size;
do {
- printf("%08x:", start_addr);
+ printf("%08lx:", start_addr);
linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
cp = (u_char *)start_addr;
for (i=0; i<linebytes; i+= size) {
void
mod_mem(int incrflag)
{
- uint start_addr, size;
- uint i, nbytes;
+ ulong start_addr, size;
+ ulong i, nbytes;
/* We use the last specified parameters, unless new ones are
* entered.
* the next value. A non-converted value exits.
*/
do {
- printf("%08x:", start_addr);
+ printf("%08lx:", start_addr);
if (size == 4)
printf(" %08x", *((uint *)start_addr));
else if (size == 2)
void
write_mem(void)
{
- uint start_addr, size, writeval;
+ ulong start_addr, size, writeval;
if (nparams != 2) {
printf("Input Error.... mw addr val\n");
*((u_char *)start_addr) = (u_char)writeval;
}
+void
base_mem()
{
if (nparams != 0) {
else {
/* Print the current base address.
*/
- printf("Base Address: 0x%08x\n", base_address);
+ printf("Base Address: 0x%08lx\n", base_address);
}
}
void
loop_mem(void)
{
- uint start_addr, size, length;
+ ulong start_addr, size, length;
uint i, junk;
volatile uint *longp;
volatile ushort *shortp;
}
}
+void
do_cache(int flag)
{
int tmp_onoff;
do_memtest()
{
int *memaddr;
- int readval, memval;
+ int memval;
for (;;) {
memaddr = (uint *)0x00800000;
memval = baseval;
do {
if (*memaddr != memval) {
-printf("Mem error @ 0x%08x: found %08x, expected 0x%08x\n",
- memaddr, *memaddr, memval);
+printf("Mem error @ 0x%08lx: found %08x, expected 0x%08x\n",
+ (ulong)memaddr, *memaddr, memval);
}
memaddr++;
memval++;
baseval++;
}
}
+
+
+/* Just a quick memory allocator.
+*/
+static ulong membase = 0x00100000;
+
+ulong
+bd_alloc_mem(int size)
+{
+ ulong retval;
+
+ retval = membase;
+ membase += (size + 3) & ~3;
+
+ return retval;
+}
+
+// vim: ts=4 noexpandtab cino=>4 cindent
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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
+ */
/* Crudely convert the ELF image to a binary we can quickly load into
* the prom simulator or programmer.
#include <elf.h>
#include <stdio.h>
+#include <asm-i386/byteorder.h>
+
#define IBSIZE (64*1024)
u_char ibuf[IBSIZE];
u_char dbuf[IBSIZE];
exit(2);
}
- nscns = ehp->e_phnum;
- epp = (Elf32_Phdr *)((uint)ehp + ehp->e_phoff);
+ nscns = __be16_to_cpu(ehp->e_phnum);
+ epp = (Elf32_Phdr *)((uint)ehp + __be32_to_cpu(ehp->e_phoff));
if (nscns != 2) {
fprintf(stderr, "something wrong with file %s\n", argv[1]);
/* Get the data portion.
*/
- if ((epp->p_type != PT_LOAD) || (epp->p_offset != 0x10000)) {
+#if 1
+ printf(" %d %d %d %d\n", __be32_to_cpu(epp->p_type),
+ __be32_to_cpu(epp->p_offset),
+ __be32_to_cpu(epp->p_filesz),
+ __be32_to_cpu(epp->p_memsz));
+#endif
+
+
+ if ((__be32_to_cpu(epp->p_type) != PT_LOAD)
+ || (__be32_to_cpu(epp->p_offset) != 0x10000)) {
fprintf(stderr, "something wrong with file %s\n", argv[1]);
exit(2);
}
- dsize = epp->p_filesz;
-#if 0
- printf(" %d %d %d %d\n", epp->p_type, epp->p_offset, epp->p_filesz,
- epp->p_memsz);
-#endif
+ dsize = __be32_to_cpu(epp->p_filesz);
+
if (read(elf_fd, dbuf, sizeof(dbuf)) != sizeof(dbuf)) {
fprintf(stderr, "%s doesn't look like ELF\n", argv[1]);
exit(2);
/* Get the instruction portion.
*/
epp++;
- if ((epp->p_type != PT_LOAD) || (epp->p_offset != 0x20000) ||
- (epp->p_filesz != epp->p_memsz)) {
+
+#if 1
+ printf(" %d %d %d %d\n", __be32_to_cpu(epp->p_type),
+ __be32_to_cpu(epp->p_offset),
+ __be32_to_cpu(epp->p_filesz),
+ __be32_to_cpu(epp->p_memsz));
+#endif
+
+ if ((__be32_to_cpu(epp->p_type) != PT_LOAD)
+ || (__be32_to_cpu(epp->p_offset) != 0x20000)
+ || (__be32_to_cpu(epp->p_filesz) != __be32_to_cpu(epp->p_memsz)))
+ {
fprintf(stderr, "something wrong with file %s\n", argv[1]);
exit(2);
}
-#if 0
- printf(" %d %d %d %d\n", epp->p_type, epp->p_offset, epp->p_filesz,
- epp->p_memsz);
-#endif
- size = epp->p_filesz;
+
+ size = __be32_to_cpu(epp->p_filesz);
if (read(elf_fd, ibuf, size) != size) {
fprintf(stderr, "%s doesn't look like ELF\n", argv[1]);
exit(2);
fprintf(stderr, "Usage: %s ELF_image_file\n", name);
exit(2);
}
+
+// vim: ts=4 noexpandtab cino=>4 cindent
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
-/* .init : { *(.init) } =0*/
+ .init : { *(.init) }
.plt : { *(.plt) }
.text :
{
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
- _erotext = .;
- PROVIDE (erotext = .);
+ /* XXX: Moved _erotext where .data will be located
+ * _erotext = .;
+ * PROVIDE (erotext = .); */
+
/* Read-write section, merged into data segment: */
. = (. + 0x0FFF) & 0xFFFFF000;
+ /* XXX: The main_loop() start should use this address */
+ _erotext = .;
+ PROVIDE (erotext = .);
.data :
{
*(.data)
--- /dev/null
+/* 8xxROM - Startup Code for the FADS8xx series of Embedded Boards
+ * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
+ *
+ * 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 __ROMFUNCS_H
+#define __ROMFUNCS_H
+
+#include "config.h"
+#include "romsys/types.h"
+#include "start.h"
+#include "disk/disk.h"
+
+#define PCMCIA_PRESENT 0
+
+/* Defines
+#define FS_BLOCK_SIZE 512 */
+/* XXX: Using default blocksize for ext2 filesystem */
+#define FS_BLOCK_SIZE 4096
+
+#define ISDIRDELIM(c) ((c) == '/' || (c) == '\\')
+
+/* ata.c */
+extern int ata_enabled;
+
+/* elf.c */
+void disk_ls(void);
+void elf_bootz(bd_t *bdinfo);
+void bootvm(bd_t *bdinfo, int mode);
+
+/* fads.c */
+int fads_sdraminit(unsigned int base, unsigned int *noMbytes);
+int fads_boardcheck(void);
+
+/* main.c */
+void hang(void);
+int read_buffer(void);
+int mem_check(unsigned int base, unsigned int nobytes);
+void display_options(void);
+
+/* memstuff.c */
+void base_mem(void);
+void do_cache(int flag);
+void do_cache_onoff(int select, int onoff);
+void do_memtest(void);
+ulong bd_alloc_mem(int size);
+
+/* part.c */
+int part_msdos_identify(void);
+int part_msdos_getinfo(unsigned int part, char **part_name,
+ unsigned int *part_status, unsigned int *part_start,
+ unsigned int *part_size, int *bootable);
+
+/* serial.c */
+void serial_putc(const char c);
+char serial_getc(void);
+void serial_init(bd_t *bd);
+
+/* trap.c */
+void trap_init(void);
+
+/* vsprintf.c */
+unsigned int asc_to_hex(char *cp, ulong *val);
+void printf(const char *fmt, ...);
+void panic(const char *fmt, ...);
+int sprintf(char * buf, const char *fmt, ...);
+
+#endif /* __ROMFUNCS_H */
+
--- /dev/null
+/* C-prototypes for exported functions */
+
+int rd_ic_cst(void);
+int rd_dc_cst(void);
+
+void wr_ic_cst(u32 value);
+u32 rr_ic_cst(void);
+void wr_ic_adr(u32 value);
+
+void wr_dc_cst(u32 value);
+u32 rr_dc_cst(void);
+void wr_dc_adr(u32 value);
+
+void icache_enable(void);
+void dcache_enable(void);
+void icache_disable(void);
+void dcache_disable(void);
+
+void udelay(unsigned long usecs);
+void start_main(unsigned long stackpos,
+ unsigned long memsize, unsigned long status);
+
+uint get_immr(void);
+uint get_pvr(void);