]> www.infradead.org Git - users/rw/ppcboot.git/commitdiff
Updated from 8xxrom-0.3.0.tar.gz (Magnus Damm, Raphael Bossek)
authorwdenk <wdenk>
Sat, 17 Jun 2000 20:10:14 +0000 (20:10 +0000)
committerwdenk <wdenk>
Sat, 17 Jun 2000 20:10:14 +0000 (20:10 +0000)
51 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Make.config [new file with mode: 0644]
Makefile
bintos19.c
board/Makefile [new file with mode: 0644]
board/ads.c [new file with mode: 0644]
board/board.h [new file with mode: 0644]
board/fads.c [new file with mode: 0644]
config.h [new file with mode: 0644]
disk/Makefile [new file with mode: 0644]
disk/ata.c [new file with mode: 0644]
disk/ata.h [new file with mode: 0644]
disk/disk.c [new file with mode: 0644]
disk/disk.h [new file with mode: 0644]
disk/part.c [new file with mode: 0644]
disk/rom.c [new file with mode: 0644]
disk/rom.h [new file with mode: 0644]
elf.c [new file with mode: 0644]
elf.h [new file with mode: 0644]
extable.c
fs/Makefile [new file with mode: 0644]
fs/ext2.c [new file with mode: 0644]
fs/ext2.h [new file with mode: 0644]
fs/fat.c [new file with mode: 0644]
fs/fat.h [new file with mode: 0644]
fs/file.c [new file with mode: 0644]
fs/file.h [new file with mode: 0644]
fs/test/romfuncs.h [new file with mode: 0644]
fs/test/test.c [new file with mode: 0644]
lib/Makefile [new file with mode: 0644]
lib/ctype.c [new file with mode: 0644]
lib/string.c [new file with mode: 0644]
lib/vsprintf.c [new file with mode: 0644]
m8xx/Makefile [new file with mode: 0644]
m8xx/m8xx.c [new file with mode: 0644]
m8xx/m8xx.h [new file with mode: 0644]
m8xx/ppc_asm.tmpl [new file with mode: 0644]
m8xx/ppc_defs.h [new file with mode: 0644]
m8xx/ppcstring.S [new file with mode: 0644]
m8xx/serial.c [new file with mode: 0644]
m8xx/start.S [new file with mode: 0644]
m8xx/traps.c [new file with mode: 0644]
m8xx/types.h [new file with mode: 0644]
main.c
memstuff.c
mkrombin.c
ppcrom.lds
romfuncs.h [new file with mode: 0644]
start.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..168f248
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,19 @@
+.---------------------------------------------------------.
+|                                                         |
+|  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>
+  ...
+
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..5a965fb
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,280 @@
+                   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
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..52833f3
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,19 @@
+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>
+
diff --git a/Make.config b/Make.config
new file mode 100644 (file)
index 0000000..fcb2308
--- /dev/null
@@ -0,0 +1,60 @@
+#  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
+
index a7f77fe158e14c39503e6ef5b9b47a0012521a5f..06a31df63660d4cca671ddefa7e9105e0a37e6d8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,55 +1,65 @@
+#  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
 
index a32923f880e0c8fff19f1e87aeb9cfc0a5071935..3548d4a82d1cf038fbfdd5e1d677b46e61b9a6d8 100644 (file)
@@ -1,5 +1,20 @@
-
-
+/*  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>
@@ -70,3 +85,5 @@ s_record()
        chksum =~ chksum;       /* one's complement */
        printf("%02X\n", (chksum & 0xff));
 }
+
+// vim: ts=4 expandtab cino=>4 cindent
diff --git a/board/Makefile b/board/Makefile
new file mode 100644 (file)
index 0000000..842118f
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# 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)
diff --git a/board/ads.c b/board/ads.c
new file mode 100644 (file)
index 0000000..36365b4
--- /dev/null
@@ -0,0 +1,723 @@
+/*  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
diff --git a/board/board.h b/board/board.h
new file mode 100644 (file)
index 0000000..859d52c
--- /dev/null
@@ -0,0 +1,14 @@
+/* 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 */
diff --git a/board/fads.c b/board/fads.c
new file mode 100644 (file)
index 0000000..208c1c4
--- /dev/null
@@ -0,0 +1,288 @@
+/*  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;
+}
+
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..f6ed6f3
--- /dev/null
+++ b/config.h
@@ -0,0 +1,55 @@
+/* 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))
+
+
+
+
+
+
diff --git a/disk/Makefile b/disk/Makefile
new file mode 100644 (file)
index 0000000..af660c8
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# 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
diff --git a/disk/ata.c b/disk/ata.c
new file mode 100644 (file)
index 0000000..7ef5466
--- /dev/null
@@ -0,0 +1,282 @@
+/*  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
diff --git a/disk/ata.h b/disk/ata.h
new file mode 100644 (file)
index 0000000..243446e
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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__ */
diff --git a/disk/disk.c b/disk/disk.c
new file mode 100644 (file)
index 0000000..7d37356
--- /dev/null
@@ -0,0 +1,261 @@
+/*  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
diff --git a/disk/disk.h b/disk/disk.h
new file mode 100644 (file)
index 0000000..6c61dee
--- /dev/null
@@ -0,0 +1,48 @@
+/*  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
diff --git a/disk/part.c b/disk/part.c
new file mode 100644 (file)
index 0000000..da87772
--- /dev/null
@@ -0,0 +1,239 @@
+/*  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
diff --git a/disk/rom.c b/disk/rom.c
new file mode 100644 (file)
index 0000000..fdef9f3
--- /dev/null
@@ -0,0 +1,45 @@
+/*  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
diff --git a/disk/rom.h b/disk/rom.h
new file mode 100644 (file)
index 0000000..b2f48c8
--- /dev/null
@@ -0,0 +1,33 @@
+/*  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
diff --git a/elf.c b/elf.c
new file mode 100644 (file)
index 0000000..a379fd4
--- /dev/null
+++ b/elf.c
@@ -0,0 +1,358 @@
+/*  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
diff --git a/elf.h b/elf.h
new file mode 100644 (file)
index 0000000..2754205
--- /dev/null
+++ b/elf.h
@@ -0,0 +1,127 @@
+/*  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
index 8bcdfdb13fd5118093fb0e02d2e65d681a2053dd..0c67a01951e03c17bbfa26728f5715fa42d0d499 100644 (file)
--- a/extable.c
+++ b/extable.c
@@ -1,10 +1,21 @@
-/*
- * 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
@@ -58,8 +69,10 @@ search_exception_table(unsigned long addr)
        /* 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
diff --git a/fs/Makefile b/fs/Makefile
new file mode 100644 (file)
index 0000000..2d726a3
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# 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
diff --git a/fs/ext2.c b/fs/ext2.c
new file mode 100644 (file)
index 0000000..875d24c
--- /dev/null
+++ b/fs/ext2.c
@@ -0,0 +1,649 @@
+/*
+ * 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;
+}
diff --git a/fs/ext2.h b/fs/ext2.h
new file mode 100644 (file)
index 0000000..338c6ce
--- /dev/null
+++ b/fs/ext2.h
@@ -0,0 +1,5 @@
+#include "file.h"
+
+file_detectfs_func     file_ext2_detectfs;
+file_ls_func           file_ext2_ls;
+file_read_func         file_ext2_read;
diff --git a/fs/fat.c b/fs/fat.c
new file mode 100644 (file)
index 0000000..e49816a
--- /dev/null
+++ b/fs/fat.c
@@ -0,0 +1,956 @@
+/* 
+ * 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);
+}
diff --git a/fs/fat.h b/fs/fat.h
new file mode 100644 (file)
index 0000000..f1d3bed
--- /dev/null
+++ b/fs/fat.h
@@ -0,0 +1,5 @@
+#include "file.h"
+
+file_detectfs_func     file_fat_detectfs;
+file_ls_func           file_fat_ls;
+file_read_func         file_fat_read;
diff --git a/fs/file.c b/fs/file.c
new file mode 100644 (file)
index 0000000..af41e40
--- /dev/null
+++ b/fs/file.c
@@ -0,0 +1,200 @@
+/* 
+ * 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);
+}
diff --git a/fs/file.h b/fs/file.h
new file mode 100644 (file)
index 0000000..1a68d21
--- /dev/null
+++ b/fs/file.h
@@ -0,0 +1,29 @@
+#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 */
diff --git a/fs/test/romfuncs.h b/fs/test/romfuncs.h
new file mode 100644 (file)
index 0000000..f9b1ab6
--- /dev/null
@@ -0,0 +1,7 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/types.h>
+
+#define FS_BLOCK_SIZE  512
+
+#define ISDIRDELIM(c)   ((c) == '/' || (c) == '\\')
diff --git a/fs/test/test.c b/fs/test/test.c
new file mode 100644 (file)
index 0000000..12be7f8
--- /dev/null
@@ -0,0 +1,91 @@
+#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;
+}
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644 (file)
index 0000000..fc3f5dc
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# 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)
diff --git a/lib/ctype.c b/lib/ctype.c
new file mode 100644 (file)
index 0000000..b5f72a5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  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 */
+
+
diff --git a/lib/string.c b/lib/string.c
new file mode 100644 (file)
index 0000000..27d2015
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ *  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
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
new file mode 100644 (file)
index 0000000..13e6475
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ *  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(;;);
+}
diff --git a/m8xx/Makefile b/m8xx/Makefile
new file mode 100644 (file)
index 0000000..d49aceb
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# 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
diff --git a/m8xx/m8xx.c b/m8xx/m8xx.c
new file mode 100644 (file)
index 0000000..da0414e
--- /dev/null
@@ -0,0 +1,227 @@
+/* 
+ * 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++;
+  }
+}
+
+/* ------------------------------------------------------------------------- */
+
+
+
+
+
+
diff --git a/m8xx/m8xx.h b/m8xx/m8xx.h
new file mode 100644 (file)
index 0000000..3b2aba0
--- /dev/null
@@ -0,0 +1,26 @@
+/* 
+ * 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__ */
+
+
+
+
+
diff --git a/m8xx/ppc_asm.tmpl b/m8xx/ppc_asm.tmpl
new file mode 100644 (file)
index 0000000..d7f7425
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * 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
diff --git a/m8xx/ppc_defs.h b/m8xx/ppc_defs.h
new file mode 100644 (file)
index 0000000..d1466d3
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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
diff --git a/m8xx/ppcstring.S b/m8xx/ppcstring.S
new file mode 100644 (file)
index 0000000..cc59aaa
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * 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
diff --git a/m8xx/serial.c b/m8xx/serial.c
new file mode 100644 (file)
index 0000000..80cb396
--- /dev/null
@@ -0,0 +1,253 @@
+
+
+/* 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));
+}
+
diff --git a/m8xx/start.S b/m8xx/start.S
new file mode 100644 (file)
index 0000000..ea82f11
--- /dev/null
@@ -0,0 +1,423 @@
+/*  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     
+               
+                       
diff --git a/m8xx/traps.c b/m8xx/traps.c
new file mode 100644 (file)
index 0000000..1afd0a6
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ *  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;
+}
diff --git a/m8xx/types.h b/m8xx/types.h
new file mode 100644 (file)
index 0000000..cdb2a71
--- /dev/null
@@ -0,0 +1,6 @@
+#define _LINUX_CONFIG_H 1
+#include "config.h"
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/mpc8xx.h>
diff --git a/main.c b/main.c
index 5409104bc85595322beca4a7188974abb58c75c8..abbf6af71e7e59358586cb59adb9550064860a57 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1,11 +1,23 @@
-
-/* 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.
@@ -31,10 +43,10 @@ char        parse_buffer[CBSIZE];
  * 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.
@@ -49,24 +61,170 @@ void       disp_mem(void);
 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
@@ -92,40 +250,17 @@ main()
         * 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.
@@ -139,7 +274,8 @@ main()
         */
        for (;;) {
 
-               printf("\nrmon> ");
+               printf("\n%s:%u:%s> ", disk_devs[disk_currentdev].name,
+                      disk_currentpart, file_cwd);
 
                if (read_buffer() == KILL_BUFFER)
                        continue;
@@ -150,8 +286,7 @@ main()
                 */
                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.
@@ -189,26 +324,72 @@ main()
                        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;
@@ -326,7 +507,6 @@ cons_parse(void)
 void
 do_help()
 {
-
        printf("\n\n");
        printf("        md[.b, .w, .l] address [# of objects]\n");
        printf("            - memory display\n");
@@ -346,12 +526,33 @@ do_help()
        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
index 435bf86e1be2b87795acea06d31f2dcca12d8442..05ff2cb2dea75c4c983decdebc310d83e46080d1 100644 (file)
@@ -1,11 +1,21 @@
-
-/* 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
@@ -15,7 +25,6 @@ extern char   *cmd;
 extern char    *params[];
 extern int     nparams;
 extern int     can_repeat;
-extern immap_t *immap;
 extern char    cons_buffer[];
 
 /* Display values from last command.
@@ -31,13 +40,13 @@ uint        mm_last_addr, mm_last_size;
  */
 #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
@@ -75,7 +84,7 @@ disp_mem(void)
        */
        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) {
@@ -118,8 +127,8 @@ disp_mem(void)
 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.
@@ -149,7 +158,7 @@ mod_mem(int incrflag)
         * 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)
@@ -199,7 +208,7 @@ mod_mem(int incrflag)
 void
 write_mem(void)
 {
-       uint    start_addr, size, writeval;
+       ulong   start_addr, size, writeval;
 
        if (nparams != 2) {
                printf("Input Error....   mw addr val\n");
@@ -233,6 +242,7 @@ write_mem(void)
                *((u_char *)start_addr) = (u_char)writeval;
 }
 
+void
 base_mem()
 {
        if (nparams != 0) {
@@ -243,7 +253,7 @@ base_mem()
        else {
                /* Print the current base address.
                */
-               printf("Base Address: 0x%08x\n", base_address);
+               printf("Base Address: 0x%08lx\n", base_address);
        }
 }
 
@@ -255,7 +265,7 @@ base_mem()
 void
 loop_mem(void)
 {
-       uint    start_addr, size, length;
+       ulong   start_addr, size, length;
        uint    i, junk;
        volatile uint   *longp;
        volatile ushort *shortp;
@@ -356,6 +366,7 @@ do_cache_onoff(int select, int onoff)
        }
 }
 
+void
 do_cache(int flag)
 {
        int     tmp_onoff;
@@ -408,7 +419,7 @@ void
 do_memtest()
 {
        int     *memaddr;
-       int     readval, memval;
+       int      memval;
 
        for (;;) {
                memaddr = (uint *)0x00800000;
@@ -423,8 +434,8 @@ do_memtest()
                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++;
@@ -433,3 +444,21 @@ printf("Mem error @ 0x%08x: found %08x, expected 0x%08x\n",
                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
index 06284d331f76d5f61b61725cbcb2dcb7c6011948..a3569d979ec42dc7fe2ba76187a51c6dd4ec0968 100644 (file)
@@ -1,3 +1,20 @@
+/*  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.
@@ -16,6 +33,8 @@
 #include <elf.h>
 #include <stdio.h>
 
+#include <asm-i386/byteorder.h>
+
 #define IBSIZE (64*1024)
 u_char ibuf[IBSIZE];
 u_char dbuf[IBSIZE];
@@ -56,8 +75,8 @@ main (int argc, char **argv)
                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]);
@@ -66,16 +85,22 @@ main (int argc, char **argv)
 
        /* 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);
@@ -84,16 +109,23 @@ main (int argc, char **argv)
        /* 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);
@@ -123,3 +155,5 @@ usage(char *name)
        fprintf(stderr, "Usage: %s ELF_image_file\n", name);
        exit(2);
 }
+
+// vim: ts=4 noexpandtab cino=>4 cindent
index 34f769372b33b34f1f88bf6d0f22aa231e827375..54ccd09267473e8126bfcec0fb17bf6b8f54d110 100644 (file)
@@ -26,7 +26,7 @@ SECTIONS
   .rela.bss      : { *(.rela.bss)              }
   .rel.plt       : { *(.rel.plt)               }
   .rela.plt      : { *(.rela.plt)              }
-/*  .init          : { *(.init)        } =0*/
+  .init          : { *(.init)  }
   .plt : { *(.plt) }
   .text      :
   {
@@ -44,10 +44,15 @@ SECTIONS
   .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)
diff --git a/romfuncs.h b/romfuncs.h
new file mode 100644 (file)
index 0000000..0fc8286
--- /dev/null
@@ -0,0 +1,81 @@
+/*  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 */
+
diff --git a/start.h b/start.h
new file mode 100644 (file)
index 0000000..accbd67
--- /dev/null
+++ b/start.h
@@ -0,0 +1,24 @@
+/* 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);