Das U-Boot: Universal Boot Loader
authorwdenk <wdenk>
Wed, 28 Nov 2001 17:49:55 +0000 (17:49 +0000)
committerwdenk <wdenk>
Wed, 28 Nov 2001 17:49:55 +0000 (17:49 +0000)
27 files changed:
board/mousse/u-boot.lds.ram [new file with mode: 0644]
board/sandpoint/early_init.S [new file with mode: 0644]
board/sandpoint/u-boot.lds.mw.debug [new file with mode: 0644]
cpu/mpc824x/drivers/dma/Makefile [new file with mode: 0644]
cpu/mpc824x/drivers/dma/Makefile_pc [new file with mode: 0644]
cpu/mpc824x/drivers/dma/README [new file with mode: 0644]
cpu/mpc824x/drivers/dma/dma.h [new file with mode: 0644]
cpu/mpc824x/drivers/dma/dma1.c [new file with mode: 0644]
cpu/mpc824x/drivers/dma/dma2.S [new file with mode: 0644]
cpu/mpc824x/drivers/dma/dma_export.h [new file with mode: 0644]
cpu/mpc824x/drivers/dma_export.h [new file with mode: 0644]
cpu/mpc824x/drivers/epic.h [new file with mode: 0644]
cpu/mpc824x/drivers/epic/README [new file with mode: 0644]
cpu/mpc824x/drivers/epic/epic2.S [new file with mode: 0644]
cpu/mpc824x/drivers/epic/epicutil.S [new file with mode: 0644]
cpu/mpc824x/drivers/errors.h [new file with mode: 0644]
cpu/mpc824x/drivers/i2c/Makefile [new file with mode: 0644]
cpu/mpc824x/drivers/i2c/Makefile_pc [new file with mode: 0644]
cpu/mpc824x/drivers/i2c/README [new file with mode: 0644]
cpu/mpc824x/drivers/i2c/i2c_export.h [new file with mode: 0644]
cpu/mpc824x/drivers/i2c_export.h [new file with mode: 0644]
cpu/mpc824x/drivers/i2o.h [new file with mode: 0644]
cpu/mpc824x/drivers/i2o/Makefile [new file with mode: 0644]
cpu/mpc824x/drivers/i2o/Makefile_pc [new file with mode: 0644]
cpu/mpc824x/drivers/i2o/i2o.h [new file with mode: 0644]
cpu/mpc824x/drivers/i2o/i2o1.c [new file with mode: 0644]
cpu/mpc824x/drivers/i2o/i2o2.S [new file with mode: 0644]

diff --git a/board/mousse/u-boot.lds.ram b/board/mousse/u-boot.lds.ram
new file mode 100644 (file)
index 0000000..9166c9c
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems Ltd. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+
+MEMORY {
+       ram  (!rx) : org = 0x00000000 , LENGTH = 8M
+       code (!rx) : org = 0x00002000 , LENGTH = (4M - 0x2000)
+       rom   (rx) : org = 0xfff00000 , LENGTH = 512K
+}
+
+SECTIONS
+{
+  _f_init = .;
+  PROVIDE(_f_init = .);
+  _f_init_rom = .;
+  PROVIDE(_f_init_rom = .);
+
+  .init : {
+      cpu/mpc824x/start.o      (.text)
+      *(.init)
+  } > ram
+  _init_size = SIZEOF(.init);
+  PROVIDE(_init_size = SIZEOF(.init));
+
+  ENTRY(_start)
+
+/*  _ftext = .;
+  _ftext_rom = .;
+  _text_size = SIZEOF(.text);
+ */
+  .text : {
+      *(.text)
+      *(.got1)
+      } > ram
+  .rodata : { *(.rodata) } > ram
+  .dtors : { *(.dtors) } > ram
+  .data : { *(.data) } > ram
+  .sdata : { *(.sdata) } > ram
+  .sdata2 : { *(.sdata2)
+      *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+    } > ram
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+  .sbss : { *(.sbss) } > ram
+  .sbss2 : { *(.sbss2) } > ram
+  .bss : { *(.bss) } > ram
+  .debug : { *(.debug) } > ram
+  .line : { *(.line) } > ram
+  .symtab : { *(.symtab) } > ram
+  .shrstrtab : { *(.shstrtab) } > ram
+  .strtab : { *(.strtab) } > ram
+ /* .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  } > ram
+  */
+   __start___ex_table = .;
+    __ex_table : { *(__ex_table) } > ram
+    __stop___ex_table = .;
+
+
+  .ppcenv      :
+  {
+    common/environment.o (.ppcenv)
+  } > ram
+
+  _end = . ;
+  PROVIDE (end = .);
+}
+
diff --git a/board/sandpoint/early_init.S b/board/sandpoint/early_init.S
new file mode 100644 (file)
index 0000000..127bd37
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * (C) Copyright 2001
+ * Thomas Koeller, tkoeller@gmx.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef        __ASSEMBLY__
+#define __ASSEMBLY__   1
+#endif
+
+#include <config.h>
+#include <asm/processor.h>
+#include <mpc824x.h>
+#include <ppc_asm.tmpl>
+
+#if defined(USE_DINK32)
+  /* We are running from RAM, so do not clear the MCCR1_MEMGO bit! */
+  #define MCCR1VAL ((CFG_ROMNAL << MCCR1_ROMNAL_SHIFT) | (CFG_ROMFAL << MCCR1_ROMFAL_SHIFT) | MCCR1_MEMGO)
+#else
+  #define MCCR1VAL (CFG_ROMNAL << MCCR1_ROMNAL_SHIFT) | (CFG_ROMFAL << MCCR1_ROMFAL_SHIFT)
+#endif
+
+       .text
+
+       /* Values to program into memory controller registers */
+tbl:   .long   MCCR1, MCCR1VAL
+       .long   MCCR2, CFG_REFINT << MCCR2_REFINT_SHIFT
+       .long   MCCR3
+       .long   (((CFG_BSTOPRE & 0x000000f0) >> 4) << MCCR3_BSTOPRE2TO5_SHIFT) | \
+               (CFG_REFREC << MCCR3_REFREC_SHIFT) | \
+               (CFG_RDLAT  << MCCR3_RDLAT_SHIFT)
+       .long   MCCR4
+        .long  (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) | (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) | \
+               (CFG_REGISTERD_TYPE_BUFFER << 20) | \
+               (((CFG_BSTOPRE & 0x00000300) >> 8) << MCCR4_BSTOPRE0TO1_SHIFT ) | \
+               ((CFG_SDMODE_CAS_LAT << 4) | (CFG_SDMODE_WRAP << 3) | \
+               (CFG_SDMODE_BURSTLEN) << MCCR4_SDMODE_SHIFT) | \
+               (CFG_ACTTORW << MCCR4_ACTTORW_SHIFT) | \
+               ((CFG_BSTOPRE & 0x0000000f) << MCCR4_BSTOPRE6TO9_SHIFT )
+       .long   MSAR1
+        .long  (((CFG_BANK0_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) <<  0) | \
+               (((CFG_BANK1_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) <<  8) | \
+               (((CFG_BANK2_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | \
+               (((CFG_BANK3_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24)
+       .long   EMSAR1
+       .long   (((CFG_BANK0_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) <<  0) | \
+               (((CFG_BANK1_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) <<  8) | \
+               (((CFG_BANK2_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | \
+               (((CFG_BANK3_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24)
+       .long   MSAR2
+        .long  (((CFG_BANK4_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) <<  0) | \
+               (((CFG_BANK5_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) <<  8) | \
+               (((CFG_BANK6_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | \
+               (((CFG_BANK7_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24)
+       .long   EMSAR2
+       .long   (((CFG_BANK4_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) <<  0) | \
+               (((CFG_BANK5_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) <<  8) | \
+               (((CFG_BANK6_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | \
+               (((CFG_BANK7_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24)
+       .long   MEAR1
+        .long  (((CFG_BANK0_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) <<  0) | \
+               (((CFG_BANK1_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) <<  8) | \
+               (((CFG_BANK2_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | \
+               (((CFG_BANK3_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24)
+       .long   EMEAR1
+       .long   (((CFG_BANK0_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) <<  0) | \
+               (((CFG_BANK1_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) <<  8) | \
+               (((CFG_BANK2_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | \
+               (((CFG_BANK3_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24)
+       .long   MEAR2
+        .long  (((CFG_BANK4_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) <<  0) | \
+               (((CFG_BANK5_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) <<  8) | \
+               (((CFG_BANK6_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | \
+               (((CFG_BANK7_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24)
+       .long   EMEAR2
+       .long   (((CFG_BANK4_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) <<  0) | \
+               (((CFG_BANK5_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) <<  8) | \
+               (((CFG_BANK6_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | \
+               (((CFG_BANK7_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24)
+       .long   0
+
+
+
+       /*
+        * Early CPU initialization. Set up memory controller, so we can access any RAM at all. This
+        * must be done in assembly, since we have no stack at this point.
+        */
+       .global early_init_f
+early_init_f:
+       mflr    r10
+
+       /* basic memory controller configuration */
+       lis     r3, CONFIG_ADDR_HIGH
+       lis     r4, CONFIG_DATA_HIGH
+       bl      lab
+lab:   mflr    r5
+       lwzu    r0, tbl - lab(r5)
+loop:  lwz     r1, 4(r5)
+       stwbrx  r0, 0, r3
+       eieio
+       stwbrx  r1, 0, r4
+       eieio
+       lwzu    r0, 8(r5)
+       cmpli   cr0, 0, r0, 0
+       bne     cr0, loop
+
+       /* set bank enable bits */
+       lis     r0, MBER@h
+       ori     r0, 0, MBER@l
+       li      r1, CFG_BANK_ENABLE
+       stwbrx  r0, 0, r3
+       eieio
+       stb     r1, 0(r4)
+       eieio
+
+       /* delay loop */
+       lis     r0, 0x0003
+       mtctr   r0
+delay: bdnz    delay
+
+       /* enable memory controller */
+       lis     r0, MCCR1@h
+       ori     r0, 0, MCCR1@l
+       stwbrx  r0, 0, r3
+       eieio
+       lwbrx   r0, 0, r4
+       oris    r0, 0, MCCR1_MEMGO@h
+       stwbrx  r0, 0, r4
+       eieio
+
+       /* set up stack pointer */
+       lis     r1, CFG_INIT_SP_OFFSET@h
+       ori     r1, r1, CFG_INIT_SP_OFFSET@l
+
+       mtlr    r10
+       blr
+
diff --git a/board/sandpoint/u-boot.lds.mw.debug b/board/sandpoint/u-boot.lds.mw.debug
new file mode 100644 (file)
index 0000000..a0378cb
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * (C) Copyright 2000
+ * Rob Taylor, Flying Pig Systems Ltd. robt@flyingpig.com
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+
+MEMORY {
+       ram  (!rx) : org = 0x00000000 , LENGTH = 8M
+       code (!rx) : org = 0x00002000 , LENGTH = (4M - 0x2000)
+       rom   (rx) : org = 0xfe000000 , LENGTH = (0x100000000 - 0xfe000000)
+}
+
+SECTIONS
+{
+  _f_init = .;
+  PROVIDE(_f_init = .);
+  _f_init_rom = .;
+  PROVIDE(_f_init_rom = .);
+
+  .init : {
+      cpu/mpc824x/start.o      (.text)
+      *(.init)
+  } > ram
+  _init_size = SIZEOF(.init);
+  PROVIDE(_init_size = SIZEOF(.init));
+
+  ENTRY(_start)
+
+/*  _ftext = .;
+  _ftext_rom = .;
+  _text_size = SIZEOF(.text);
+ */
+  .text : {
+      *(.text)
+      *(.got1)
+      } > ram
+  .rodata : { *(.rodata) } > ram
+  .dtors : { *(.dtors) } > ram
+  .data : { *(.data) } > ram
+  .sdata : { *(.sdata) } > ram
+  .sdata2 : { *(.sdata2)
+      *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+    } > ram
+  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2;
+  __fixup_entries = (. - _FIXUP_TABLE_)>>2;
+
+  .sbss : { *(.sbss) } > ram
+  .sbss2 : { *(.sbss2) } > ram
+  .bss : { *(.bss) } > ram
+  .debug : { *(.debug) } > ram
+  .line : { *(.line) } > ram
+  .symtab : { *(.symtab) } > ram
+  .shrstrtab : { *(.shstrtab) } > ram
+  .strtab : { *(.strtab) } > ram
+ /* .reloc   :
+  {
+    *(.got)
+    _GOT2_TABLE_ = .;
+    *(.got2)
+    _FIXUP_TABLE_ = .;
+    *(.fixup)
+  } > ram
+  */
+   __start___ex_table = .;
+    __ex_table : { *(__ex_table) } > ram
+    __stop___ex_table = .;
+
+
+  .ppcenv      :
+  {
+    common/environment.o (.ppcenv)
+  } > ram
+
+  _end = . ;
+  PROVIDE (end = .);
+}
+
diff --git a/cpu/mpc824x/drivers/dma/Makefile b/cpu/mpc824x/drivers/dma/Makefile
new file mode 100644 (file)
index 0000000..59e2fac
--- /dev/null
@@ -0,0 +1,83 @@
+##########################################################################
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and
+#       distribute the SOFTWARE so long as this entire notice is retained
+#       without alteration in any modified and/or redistributed versions,
+#       and that such modified versions are clearly identified as such.
+#       No licenses are granted by implication, estoppel or otherwise under
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS.
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR
+#       INABILITY TO USE THE SOFTWARE.
+#
+############################################################################
+TARGET = libdma.a
+
+DEBUG   = -DDMADBG
+LST     = -Hanno -S
+OPTIM   =
+CC      = /risc/tools/pkgs/metaware/bin/hcppc
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG = -l -fm
+AS      = /risc/tools/pkgs/metaware/bin/asppc
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -q -r -Qn
+LKCMD   =
+LINK    =  /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = dma1.o dma2.o
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+objects: dma1.o
+
+clean:
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+
+.s.o:
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+dma1.o: dma_export.h dma.h dma1.c
+
+dma2.o: dma.h dma2.s
diff --git a/cpu/mpc824x/drivers/dma/Makefile_pc b/cpu/mpc824x/drivers/dma/Makefile_pc
new file mode 100644 (file)
index 0000000..8df2a3c
--- /dev/null
@@ -0,0 +1,89 @@
+##########################################################################
+#
+#   makefile_pc  for use with mksnt tools   drivers/dma
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and
+#       distribute the SOFTWARE so long as this entire notice is retained
+#       without alteration in any modified and/or redistributed versions,
+#       and that such modified versions are clearly identified as such.
+#       No licenses are granted by implication, estoppel or otherwise under
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS.
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR
+#       INABILITY TO USE THE SOFTWARE.
+#
+############################################################################
+TARGET = libdma.a
+
+DEBUG   = -DDMADBG
+LST     = -Hanno -S
+OPTIM   =
+CC      = m:/old_tools/tools/hcppc/bin/hcppc
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG = -l -fm
+AS      = m:/old_tools/tools/hcppc/bin/asppc
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -q -r -Qn
+LKCMD   =
+LINK    = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = dma1.o dma2.o
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+objects: dma1.o
+
+clean:
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+
+.s.o:
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+dma1.o: dma_export.h dma.h dma1.c
+       $(CCobj) $<
+
+dma2.o: dma.h dma2.s
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
diff --git a/cpu/mpc824x/drivers/dma/README b/cpu/mpc824x/drivers/dma/README
new file mode 100644 (file)
index 0000000..ab4b68b
--- /dev/null
@@ -0,0 +1,102 @@
+CONTENT:
+
+   dma.h
+   dma1.c
+   dma2.s
+
+WHAT ARE THESE FILES:
+
+These files contain MPC8240 (Kahlua) DMA controller
+driver routines. The driver routines are not
+written for any specific operating system.
+They serves the purpose of code sample, and
+jump-start for using the MPC8240 DMA controller.
+
+For the reason of correctness of C language
+syntax, these files are compiled by Metaware
+C compiler and assembler.
+
+ENDIAN NOTATION:
+
+The algorithm is designed for big-endian mode,
+software is responsible for byte swapping.
+
+USAGE:
+
+1. The host system that is running on MPC8240
+   or using MPC8240 as I/O device shall link
+   the files listed here. The memory location
+   of driver routines shall take into account of
+   that driver routines need to run in supervisor
+   mode and they process DMA controller interrupt.
+
+2. The host system is responsible for configuring
+   the MPC8240 including Embedded Utilities Memory
+   Block. Since the DMA controller on MPC8240 can
+   be accessed by either local 603e core or the host
+   that MPC8240 serves as I/O processor through host
+   PCI configuration, it is important that the local
+   processor uses EUMBBAR to access its local DMA
+   controller while the PCI master uses I/O
+   processor's PCSRBAR to access the DMA controller
+   on I/O device.
+
+   To qualify whether is EUMBBAR or PCSRBAR, one
+   additional parameter is requied from the host
+   system, LOCAL or REMOTE so that the base value
+   can be correctly interpreted.
+
+3. If the host system is also using the EPIC unit
+   on MPC8240, the system can register the
+   DMA_ISR with the EPIC including other
+   desired resources.
+
+   If the host system does not using the EPIC unit
+   on MPC8240, DMA_ISR function can be called for
+   each desired time interval.
+
+   In both cases, the host system is free to
+   provide its own interrupt service routine.
+
+4. To start a direct mode DMA transaction,
+   use DMA_Bld_Curr with the start parameter
+   set to 1.
+
+   To start a chaining mode DMA transaction,
+   the application shall build descriptors
+   in memory first, next, use DMA_Bld_Desp
+   with the start parameter set to 1.
+
+5. DMA_Start function clears, then sets the CS
+   bit of DMA mode register.
+
+   DMA_Halt function clears the CS bit of DMA
+   mode register.
+
+   These functions can be used to start and
+   halt the DMA transaction.
+
+   If the chaining descriptors has been
+   modified since the last time a DMA
+   transaction started, use DMA_Chn_Cnt
+   function to let DMA controller process
+   the modified descriptor chain without
+   stopping or disturbing the current DMA
+   transaction.
+
+   It is the host system's responsibility of
+   setting up the correct DMA transfer mode
+   and pass the correct memory address parameters.
+
+6. It is the host system's responsibility of
+   queueing the DMA I/O request. The host
+   system can call the DMA_ISR with its own
+   desired interrupt service subroutines to
+   handle each individual interrupt and queued
+   DMA I/O requests.
+
+7. The DMA driver routines contains a set
+   of utilities, Set and Get, for host system
+   to query and modify the desired DMA registers.
+
+
diff --git a/cpu/mpc824x/drivers/dma/dma.h b/cpu/mpc824x/drivers/dma/dma.h
new file mode 100644 (file)
index 0000000..a21be74
--- /dev/null
@@ -0,0 +1,326 @@
+#ifndef DMA_H
+#define DMA_H
+/*******************************************************
+ *
+ * copyright @ Motorola 1999
+ *
+ *******************************************************/
+#define NUM_DMA_REG   7
+#define DMA_MR_REG    0
+#define DMA_SR_REG    1
+#define DMA_CDAR_REG  2
+#define DMA_SAR_REG   3
+#define DMA_DAR_REG   4
+#define DMA_BCR_REG   5
+#define DMA_NDAR_REG  6
+
+typedef enum _dmastatus
+{
+       DMASUCCESS = 0x1000,
+       DMALMERROR,
+       DMAPERROR,
+       DMACHNBUSY,
+       DMAEOSINT,
+       DMAEOCAINT,
+       DMAINVALID,
+       DMANOEVENT,
+} DMAStatus;
+
+typedef enum _location
+{
+       LOCAL = 0,     /* local processor accesses on board DMA,
+                                 local processor's eumbbar is required */
+       REMOTE = 1,    /* PCI master accesses DMA on I/O board,
+                                 I/O processor's pcsrbar is required */
+} LOCATION;
+
+typedef enum dma_mr_bit
+{
+       IRQS    = 0x00080000,
+    PDE     = 0x00040000,
+       DAHTS   = 0x00030000,
+       SAHTS   = 0x0000c000,
+       DAHE    = 0x00002000,
+       SAHE    = 0x00001000,
+       PRC     = 0x00000c00,
+       EIE     = 0x00000080,
+       EOTIE   = 0x00000040,
+       DL      = 0x00000008,
+       CTM     = 0x00000004,
+       CC      = 0x00000002,
+       CS      = 0x00000001,
+} DMA_MR_BIT;
+
+typedef enum dma_sr_bit
+{
+       LME     = 0x00000080,
+       PE      = 0x00000010,
+       CB      = 0x00000004,
+       EOSI    = 0x00000002,
+       EOCAI   = 0x00000001,
+} DMA_SR_BIT;
+
+/* structure for DMA Mode Register */
+typedef struct _dma_mr
+{
+       unsigned int  reserved0 : 12;
+       unsigned int  irqs      : 1;
+       unsigned int  pde       : 1;
+       unsigned int  dahts     : 2;
+    unsigned int  sahts     : 2;
+       unsigned int  dahe      : 1;
+       unsigned int  sahe      : 1;
+       unsigned int  prc       : 2;
+       unsigned int  reserved1 : 1;
+       unsigned int  eie       : 1;
+       unsigned int  eotie     : 1;
+       unsigned int  reserved2 : 3;
+       unsigned int  dl        : 1;
+       unsigned int  ctm       : 1;
+       /* if chaining mode is enabled, any time, user can modify the
+        * descriptor and does not need to halt the current DMA transaction.
+        * Set CC bit, enable DMA to process the modified descriptors
+        * Hardware will clear this bit each time, DMA starts.
+        */
+       unsigned int  cc        : 1;
+       /* cs bit has dua role, halt the current DMA transaction and
+        * (re)start DMA transaction. In chaining mode, if the descriptor
+        * needs modification, cs bit shall be used not the cc bit.
+        * Hardware will not set/clear this bit each time DMA transaction
+        * stops or starts. Software shall do it.
+        *
+        * cs bit shall not be used to halt chaining DMA transaction for
+        * modifying the descriptor. That is the role of CC bit.
+        */
+       unsigned int  cs        : 1;
+} DMA_MR;
+
+/* structure for DMA Status register */
+typedef struct _dma_sr
+{
+       unsigned int  reserved0 : 24;
+       unsigned int  lme       : 1;
+       unsigned int  reserved1 : 2;
+       unsigned int  pe        : 1;
+       unsigned int  reserved2 : 1;
+       unsigned int  cb        : 1;
+       unsigned int  eosi      : 1;
+       unsigned int  eocai     : 1;
+} DMA_SR;
+
+/* structure for DMA current descriptor address register */
+typedef struct _dma_cdar
+{
+       unsigned int  cda    : 27;
+       unsigned int snen    : 1;
+       unsigned int eosie   : 1;
+       unsigned int ctt     : 2;
+       unsigned int eotd    : 1;
+} DMA_CDAR;
+
+/* structure for DMA byte count register */
+typedef struct _dma_bcr
+{
+       unsigned int reserved : 6;
+       unsigned int  bcr      : 26;
+} DMA_BCR;
+
+/* structure for DMA Next Descriptor Address register */
+typedef struct _dma_ndar
+{
+       unsigned int nda    : 27;
+       unsigned int ndsnen : 1;
+       unsigned int ndeosie: 1;
+       unsigned int ndctt  : 2;
+       unsigned int eotd   : 1;
+} DMA_NDAR;
+
+/* structure for DMA current transaction info */
+typedef struct _dma_curr
+{
+       unsigned int src_addr;
+       unsigned int dest_addr;
+       unsigned int byte_cnt;
+} DMA_CURR;
+
+/************************* Kernel API********************
+ * Kernel APIs are used to interface with O.S. kernel.
+ * They are the functions required by O.S. kernel to
+ * provide I/O service.
+ ********************************************************/
+
+/**************DMA Device Control Functions ********/
+
+/**
+ * Note:
+ *
+ * In all following functions, the host (KAHLUA) processor has a
+ * choice of accessing on board local DMA (LOCAL),
+ * or DMA on a distributed KAHLUA (REMOTE). In either case,
+ * the caller shall pass the configured embedded utility memory
+ * block base address relative to the DMA. If LOCAL DMA is used,
+ * this parameter shall be EUMBBAR, if REMOTE is used, the
+ * parameter shall be the corresponding PCSRBAR.
+ **/
+
+/**************************************************************
+ * function: DMA_Get_Stat
+ *
+ * description: return the content of status register of
+ *              the given DMA channel
+ *              if error, return DMAINVALID. Otherwise return
+ *              DMASUCCESS.
+ *
+ **************************************************************/
+static DMAStatus DMA_Get_Stat( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_SR * );
+
+/**************************************************************
+ * function: DMA_Get_Mode
+ *
+ * description: return the content of mode register of the
+ *              given DMA channel
+ *              if error, return DMAINVALID. Otherwise return DMASUCCESS.
+ *
+ **************************************************************/
+static DMAStatus DMA_Get_Mode( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_MR * );
+
+/**************************************************************
+ * function: DMA_Set_Mode
+ *
+ * description: Set a new mode to a given DMA channel
+ *              return DMASUCCESS if success, otherwise return DMACHNINVALID
+ *
+ * note: It is not a good idea of changing the DMA mode during
+ *       the middle of a transaction.
+ **************************************************************/
+static DMAStatus DMA_Set_Mode( LOCATION, unsigned int eumbbar, unsigned int channel, DMA_MR mode );
+
+/*************************************************************
+ * function: DMA_ISR
+ *
+ * description: DMA interrupt service routine
+ *              return DMAStatus based on the status
+ *
+ *************************************************************/
+static DMAStatus    DMA_ISR( unsigned int eumbbar,
+                                                        unsigned int channel,
+                                                    DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ),
+                                                DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ),
+                                                DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ),
+                                                DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus ));
+
+static DMAStatus dma_error_func( unsigned int, unsigned int, DMAStatus );
+
+/********************* DMA I/O function ********************/
+
+/************************************************************
+ * function: DMA_Start
+ *
+ * description: start a given DMA channel transaction
+ *              return DMASUCCESS if success, otherwise return DMACHNINVALID
+ *
+ * note: this function will clear DMA_MR(CC) first, then
+ *       set DMA_MR(CC).
+ ***********************************************************/
+static DMAStatus DMA_Start( LOCATION, unsigned int eumbbar,unsigned int channel );
+
+/***********************************************************
+ * function: DMA_Halt
+ *
+ * description: halt the current dma transaction on the specified
+ *              channel.
+ *              return DMASUCCESS if success, otherwise return DMACHNINVALID
+ *
+ * note: if the specified DMA channel is idle, nothing happens
+ *************************************************************/
+static DMAStatus DMA_Halt( LOCATION, unsigned int eumbbar,unsigned int channel );
+
+/*************************************************************
+ * function: DMA_Chn_Cnt
+ *
+ * description: set the DMA_MR(CC) bit for a given channel
+ *              that is in chaining mode.
+ *              return DMASUCCESS if successfule, otherwise return DMACHNINVALID
+ *
+ * note: if the given channel is not in chaining mode, nothing
+ *       happen.
+ *
+ *************************************************************/
+static DMAStatus DMA_Chn_Cnt( LOCATION, unsigned int eumbbar,unsigned int channel );
+
+/*********************** App. API ***************************
+ * App. API are the APIs Kernel provides for the application
+ * level program
+ ************************************************************/
+/**************************************************************
+ * function: DMA_Bld_Curr
+ *
+ * description: set current src, dest, byte count registers
+ *              according to the desp for a given channel
+ *
+ *              if the given channel is busy,  no change made,
+ *              return DMACHNBUSY.
+ *
+ *              otherwise return DMASUCCESS.
+ *
+ * note:
+ **************************************************************/
+static DMAStatus DMA_Bld_Curr( LOCATION,
+                                                                 unsigned int eumbbar,
+                                                                 unsigned int channel,
+                                                             DMA_CURR     desp );
+
+/**************************************************************
+ * function: DMA_Poke_Curr
+ *
+ * description: poke the current src, dest, byte count registers
+ *              for a given channel.
+ *
+ *              return DMASUCCESS if no error otherwise return DMACHNERROR
+ *
+ * note:        Due to the undeterministic parallelism, in chaining
+ *              mode, the value returned by this function shall
+ *              be taken as reference when the query is made rather
+ *              than the absolute snapshot when the value is returned.
+ **************************************************************/
+static DMAStatus DMA_Poke_Curr( LOCATION,
+                                                          unsigned int eumbbar,
+                                                          unsigned int channel,
+                                                      DMA_CURR*    desp );
+
+/**************************************************************
+ * function: DMA_Bld_Desp
+ *
+ * description: set current descriptor address register
+ *              according to the desp for a given channel
+ *
+ *              if the given channel is busy return DMACHNBUSY
+ *              and no change made, otherwise return DMASUCCESS.
+ *
+ * note:
+ **************************************************************/
+static DMAStatus DMA_Bld_Desp( LOCATION host,
+                                                 unsigned int eumbbar,
+                                                 unsigned int channel,
+                                                 DMA_CDAR     desp );
+
+/**************************************************************
+ * function: DMA_Poke_Desp
+ *
+ * description: poke the current descriptor address register
+ *              for a given channel
+ *
+ *              return DMASUCCESS if no error otherwise return
+ *              DMAINVALID
+ *
+ * note: Due to the undeterministic parallellism of DMA operation,
+ *       the value returned by this function shall be taken as
+ *       the most recently used descriptor when the last time
+ *       DMA starts a chaining mode operation.
+ **************************************************************/
+static DMAStatus DMA_Poke_Desp( LOCATION,
+                                                          unsigned int eumbbar,
+                                                          unsigned int channel,
+                                                      DMA_CDAR     *desp );
+
+#endif
diff --git a/cpu/mpc824x/drivers/dma/dma1.c b/cpu/mpc824x/drivers/dma/dma1.c
new file mode 100644 (file)
index 0000000..8c3834e
--- /dev/null
@@ -0,0 +1,801 @@
+/************************************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ * App. API
+ *
+ * App. API are the APIs Kernel provides for the application
+ * level program
+ *
+ ************************************************************/
+#include "dma_export.h"
+#include "dma.h"
+
+/* Define a macro to use an optional application-layer print function, if
+ * one was passed to the library during initialization.  If there was no
+ * function pointer passed, this protects against referencing a NULL pointer.
+ * Also define The global variable that holds the passed pointer.
+ */
+#define PRINT if ( app_print ) app_print
+static int (*app_print)(char *,...);
+
+/* Set by call to get_eumbbar during DMA_Initialize.
+ * This could be globally available to the library, but there is
+ * an advantage to passing it as a parameter: it is already in a register
+ * and doesn't have to be loaded from memory.  Also, that is the way the
+ * library was already implemented and I don't want to change it without
+ * a more detailed analysis.
+ * It is being set as a global variable during initialization to hide it from
+ * the DINK application layer, because it is Kahlua-specific.  I think that
+ * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in
+ * a Kahlua-specific library dealing with the embedded utilities memory block.
+ * Right now, get_eumbbar is defined in dink32/kahlua.s.  The other two are
+ * defined in dink32/drivers/i2c/i2c2.s, drivers/dma/dma2.s, etc.
+ */
+static unsigned int Global_eumbbar = 0;
+extern unsigned int get_eumbbar();
+
+
+extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
+#pragma Alias( load_runtime_reg, "load_runtime_reg" );
+
+extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
+#pragma Alias( store_runtime_reg, "store_runtime_reg" );
+
+unsigned int dma_reg_tb[][14] = {
+       /* local DMA registers */
+       {
+      /* DMA_0_MR   */  0x00001100,
+      /* DMA_0_SR   */  0x00001104,
+      /* DMA_0_CDAR */  0x00001108,
+      /* DMA_0_SAR  */  0x00001110,
+      /* DMA_0_DAR  */  0x00001118,
+      /* DMA_0_BCR  */  0x00001120,
+      /* DMA_0_NDAR */  0x00001124,
+      /* DMA_1_MR   */  0x00001200,
+      /* DMA_1_SR   */  0x00001204,
+      /* DMA_1_CDAR */  0x00001208,
+      /* DMA_1_SAR  */  0x00001210,
+      /* DMA_1_DAR  */  0x00001218,
+      /* DMA_1_BCR  */  0x00001220,
+      /* DMA_1_NDAR */  0x00001224,
+       },
+       /* remote DMA registers */
+       {
+      /* DMA_0_MR   */  0x00000100,
+      /* DMA_0_SR   */  0x00000104,
+      /* DMA_0_CDAR */  0x00000108,
+      /* DMA_0_SAR  */  0x00000110,
+      /* DMA_0_DAR  */  0x00000118,
+      /* DMA_0_BCR  */  0x00000120,
+      /* DMA_0_NDAR */  0x00000124,
+      /* DMA_1_MR   */  0x00000200,
+      /* DMA_1_SR   */  0x00000204,
+      /* DMA_1_CDAR */  0x00000208,
+      /* DMA_1_SAR  */  0x00000210,
+      /* DMA_1_DAR  */  0x00000218,
+      /* DMA_1_BCR  */  0x00000220,
+      /* DMA_1_NDAR */  0x00000224,
+       },
+};
+
+/* API functions */
+
+/*  Initialize DMA unit with the following:
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  ???
+ *  Interrupt enables, modes, etc. are set for each transfer.
+ *
+ *  This function must be called before DMA unit can be used.
+ */
+extern
+DMA_Status DMA_Initialize( int (*p)(char *,...))
+{
+  DMAStatus status;
+  /* establish the pointer, if there is one, to the application's "printf" */
+  app_print = p;
+
+  /* If this is the first call, get the embedded utilities memory block
+   * base address.  I'm not sure what to do about error handling here:
+   * if a non-zero value is returned, accept it.
+   */
+  if ( Global_eumbbar == 0)
+     Global_eumbbar = get_eumbbar();
+  if ( Global_eumbbar == 0)
+  {
+    PRINT( "DMA_Initialize: can't find EUMBBAR\n" );
+    return DMA_ERROR;
+  }
+
+  return DMA_SUCCESS;
+}
+
+
+/* Perform the DMA transfer, only direct mode is currently implemented.
+ * At this point, I think it would be better to define a different
+ * function for chaining mode.
+ * Also, I'm not sure if it is appropriate to have the "generic" API
+ * accept snoop and int_steer parameters.  The DINK user interface allows
+ * them, so for now I'll leave them.
+ *
+ * int_steer controls DMA interrupt steering to PCI or local processor
+ * type is the type of transfer: M2M, M2P, P2M, P2P
+ * source is the source address of the data
+ * dest is the destination address of the data
+ * len is the length of data to transfer
+ * channel is the DMA channel to use for the transfer
+ * snoop is the snoop enable control
+ */
+extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer,
+                                       DMA_TRANSFER_TYPE type,
+                                       unsigned int source,
+                                       unsigned int dest,
+                                       unsigned int len,
+                                       DMA_CHANNEL channel,
+                                       DMA_SNOOP_MODE snoop)
+{
+    DMA_MR md;
+    DMA_CDAR cdar;
+    /* it's inappropriate for curr to be a struct, but I'll leave it */
+    DMA_CURR curr;
+
+    DMAStatus stat;
+
+       /* The rest of this code was moved from device.c test_dma to here.
+        * It needs to be cleaned up and validated, but at least it is removed
+        * from the application and API.  Most of the mode is left hard coded.
+        * This should be changed after the final API is defined and the user
+        * application has a way to control the transfer.
+        *
+        */
+
+       if ( DMA_Get_Mode( LOCAL, Global_eumbbar, channel, &md ) != DMASUCCESS )
+       {
+               return DMA_ERROR;
+       }
+
+       md.irqs = int_steer;
+       md.pde = 0;
+       md.dahts = 3; /* 8 - byte */
+       md.sahts = 3; /* 8 - byte */
+       md.dahe = 0;
+       md.sahe = 0;
+       md.prc = 0;
+       /* if steering interrupts to local processor, use polling mode */
+       if ( int_steer == DMA_INT_STEER_PCI )
+       {
+               md.eie = 1;
+               md.eotie = 1;
+       } else {
+               md.eie = 0;
+               md.eotie = 0;
+       }
+       md.dl = 0;
+       md.ctm = 1;   /* direct mode */
+    md.cc = 0;
+
+       /* validate the length range */
+       if (len > 0x3ffffff )
+       {
+               PRINT( "dev DMA: length of transfer too large: %d\n", len );
+               return DMA_ERROR;
+       }
+
+       /* inappropriate to use a struct, but leave as is for now */
+       curr.src_addr = source;
+       curr.dest_addr = dest;
+       curr.byte_cnt = len;
+
+       (void)DMA_Poke_Desp( LOCAL, Global_eumbbar, channel, &cdar );
+       cdar.snen = snoop;
+       cdar.ctt = type;
+
+       if ( ( stat = DMA_Bld_Desp( LOCAL, Global_eumbbar, channel, cdar ))
+                       != DMASUCCESS ||
+                ( stat = DMA_Bld_Curr( LOCAL, Global_eumbbar, channel, curr ))
+                       != DMASUCCESS ||
+            ( stat = DMA_Set_Mode( LOCAL, Global_eumbbar, channel, md ))
+                       != DMASUCCESS ||
+                ( stat = DMA_Start( LOCAL, Global_eumbbar, channel ))
+                       != DMASUCCESS )
+       {
+               if ( stat == DMACHNBUSY )
+               {
+                       PRINT( "dev DMA: channel %d busy.\n", channel );
+               }
+               else
+               {
+                       PRINT( "dev DMA: invalid channel request.\n", channel );
+               }
+
+               return DMA_ERROR;
+       }
+
+/* Since we are interested at the DMA performace right now,
+   we are going to do as less as possible to burden the
+   603e core.
+
+   if you have epic enabled or don't care the return from
+   DMA operation, you can just return SUCCESS.
+
+   if you don't have epic enabled and care the DMA result,
+   you can use the polling method below.
+
+   Note: I'll attempt to activate the code for handling polling.
+ */
+
+#if 0
+       /* if steering interrupt to local processor, let it handle results */
+       if ( int_steer == DMA_INT_STEER_LOCAL )
+       {
+           return DMA_SUCCESS;
+       }
+
+       /* polling since interrupt goes to PCI */
+       do
+       {
+               stat = DMA_ISR( Global_eumbbar, channel, dma_error_func,
+                       dma_error_func, dma_error_func, dma_error_func );
+       }
+       while ( stat == DMANOEVENT );
+#endif
+
+    return DMA_SUCCESS;
+}
+
+/* DMA library internal functions */
+
+/**
+ * Note:
+ *
+ * In all following functions, the host (KAHLUA) processor has a
+ * choice of accessing on board local DMA (LOCAL),
+ * or DMA on a distributed KAHLUA (REMOTE). In either case,
+ * the caller shall pass the configured embedded utility memory
+ * block base address relative to the DMA. If LOCAL DMA is used,
+ * this parameter shall be EUMBBAR, if REMOTE is used, the
+ * parameter shall be the corresponding PCSRBAR.
+ **/
+
+/**************************************************************
+ * function: DMA_Get_Stat
+ *
+ * description: return the content of status register of
+ *              the given DMA channel
+ *
+ *              if error, reserved0 field all 1s.
+ **************************************************************/
+static
+DMAStatus DMA_Get_Stat( LOCATION host, unsigned int eumbbar, unsigned int channel, DMA_SR *stat )
+{
+    unsigned int tmp;
+
+   if ( channel != 0 && channel != 1 || stat == 0 )
+   {
+       return DMAINVALID;
+   }
+
+    tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG] );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) stat = 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SR_REG], tmp );
+#endif
+
+        stat->reserved0 = ( tmp & 0xffffff00 ) >> 8;
+        stat->lme       = ( tmp & 0x00000080 ) >> 7;
+        stat->reserved1 = ( tmp & 0x00000060 ) >> 5;
+        stat->pe        = ( tmp & 0x00000010 ) >> 4;
+        stat->reserved2 = ( tmp & 0x00000008 ) >> 3;
+        stat->cb        = ( tmp & 0x00000004 ) >> 2;
+        stat->eosi      = ( tmp & 0x00000002 ) >> 1;
+        stat->eocai     = ( tmp & 0x00000001 );
+
+   return DMASUCCESS;
+}
+
+/**************************************************************
+ * function: DMA_Get_Mode
+ *
+ * description: return the content of mode register of the
+ *              given DMA channel
+ *
+ *              if error, return DMAINVALID, otherwise return
+ *              DMASUCCESS
+ **************************************************************/
+static
+DMAStatus DMA_Get_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR *mode )
+{
+    unsigned int tmp;
+   if ( channel != 0 && channel != 1 || mode == 0 )
+   {
+     return DMAINVALID;
+   }
+
+    tmp = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG] );
+
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) mode = 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_MR_REG], tmp );
+#endif
+
+        mode->reserved0 = (tmp & 0xfff00000) >> 20;
+        mode->irqs      = (tmp & 0x00080000) >> 19;
+        mode->pde       = (tmp & 0x00040000) >> 18;
+        mode->dahts     = (tmp & 0x00030000) >> 16;
+     mode->sahts     = (tmp & 0x0000c000) >> 14;
+        mode->dahe      = (tmp & 0x00002000) >> 13;
+        mode->sahe      = (tmp & 0x00001000) >> 12;
+        mode->prc       = (tmp & 0x00000c00) >> 10;
+        mode->reserved1 = (tmp & 0x00000200) >> 9;
+        mode->eie       = (tmp & 0x00000100) >> 8;
+        mode->eotie     = (tmp & 0x00000080) >> 7;
+        mode->reserved2 = (tmp & 0x00000070) >> 4;
+        mode->dl        = (tmp & 0x00000008) >> 3;
+        mode->ctm       = (tmp & 0x00000004) >> 2;
+        mode->cc        = (tmp & 0x00000002) >> 1;
+        mode->cs        = (tmp & 0x00000001);
+
+   return DMASUCCESS;
+}
+
+/**************************************************************
+ * function: DMA_Set_Mode
+ *
+ * description: Set a new mode to a given DMA channel
+ *
+ * note: It is not a good idea of changing the DMA mode during
+ *       the middle of a transaction.
+ **************************************************************/
+static
+DMAStatus DMA_Set_Mode( LOCATION host, unsigned eumbbar, unsigned int channel, DMA_MR mode )
+{
+    unsigned int tmp;
+   if ( channel != 0 && channel != 1 )
+   {
+          return DMAINVALID;
+   }
+
+   tmp = ( mode.reserved0 & 0xfff ) << 20;
+   tmp |= ( ( mode.irqs  & 0x1 ) << 19);
+   tmp |= ( ( mode.pde   & 0x1 ) << 18 );
+   tmp |= ( ( mode.dahts & 0x3 ) << 16 );
+   tmp |= ( ( mode.sahts & 0x3 ) << 14 );
+   tmp |= ( ( mode.dahe  & 0x1 ) << 13 );
+   tmp |= ( ( mode.sahe  & 0x1 ) << 12 );
+   tmp |= ( ( mode.prc   & 0x3 ) << 10 );
+   tmp |= ( ( mode.reserved1 & 0x1 ) << 9 );
+   tmp |= ( ( mode.eie   & 0x1 ) << 8 );
+   tmp |= ( ( mode.eotie & 0x1 ) << 7 );
+   tmp |= ( ( mode.reserved2 & 0x7 ) << 4 );
+   tmp |= ( ( mode.dl    & 0x1 ) << 3 );
+   tmp |= ( ( mode.ctm   & 0x1 ) << 2 );
+   tmp |= ( ( mode.cc    & 0x1 ) << 1 ) ;
+   tmp |= ( mode.cs    & 0x1 );
+
+   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], tmp );
+   return DMASUCCESS;
+}
+
+/************************************************************
+ * function: DMA_Start
+ *
+ * description: start a given DMA channel transaction
+ *              return DMASUCCESS if success otherwise return
+ *              DMAStatus value
+ *
+ * note: this function will clear DMA_MR(CC) first, then
+ *       set DMA_MR(CC).
+ ***********************************************************/
+static
+DMAStatus DMA_Start( LOCATION host, unsigned int eumbbar, unsigned int channel )
+{
+   DMA_SR stat;
+   unsigned int mode;
+
+   if ( channel != 0 && channel != 1 )
+   {
+          return DMAINVALID;
+   }
+
+   if ( DMA_Get_Stat( host, eumbbar, channel, &stat ) != DMASUCCESS )
+   {
+                  return DMAINVALID;
+   }
+
+   if ( stat.cb == 1 )
+   {
+          /* DMA is not free */
+          return DMACHNBUSY;
+   }
+
+   mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG] );
+   /* clear DMA_MR(CS) */
+   mode &= 0xfffffffe;
+   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
+
+   /* set DMA_MR(CS) */
+   mode |= CS;
+   store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
+   return DMASUCCESS;
+}
+
+/***********************************************************
+ * function: DMA_Halt
+ *
+ * description: halt the current dma transaction on the specified
+ *              channel.
+ *              return DMASUCCESS if success otherwise return DMAINVALID
+ *
+ * note: if the specified DMA channel is idle, nothing happens
+ *************************************************************/
+static
+DMAStatus DMA_Halt( LOCATION host, unsigned int eumbbar, unsigned int channel )
+{
+   unsigned int mode;
+   if ( channel != 0 && channel != 1 )
+   {
+          return DMAINVALID;
+   }
+
+   mode = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG]);
+
+   /* clear DMA_MR(CS) */
+   mode &= 0xfffffffe;
+   store_runtime_reg(eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG + DMA_MR_REG], mode );
+   return DMASUCCESS;
+}
+
+/*************************************************************
+ * function: DMA_Chn_Cnt
+ *
+ * description: set the DMA_MR(CC) bit for a given channel
+ *              that is in chaining mode.
+ *              return DMASUCCESS if successfule, otherwise return
+ *              DMAINVALID.
+ *
+ * note: if the given channel is not in chaining mode, nothing
+ *       happen.
+ *
+ *************************************************************/
+static
+DMAStatus DMA_Chn_Cnt( LOCATION host, unsigned int eumbbar, unsigned int channel )
+{
+       DMA_MR mode;
+       if ( channel != 0 && channel != 1 )
+       {
+               return DMAINVALID;
+       }
+
+       if ( DMA_Get_Mode( host, eumbbar, channel, &mode ) != DMASUCCESS )
+       {
+                       return DMAINVALID;
+       }
+
+       if ( mode.ctm == 0 )
+       {
+               /* either illegal mode or not chaining mode */
+               return DMAINVALID;
+       }
+
+       mode.cc = 1;
+       return DMA_Set_Mode( host, eumbbar, channel, mode );
+}
+
+/**************************************************************
+ * function: DMA_Bld_Desp
+ *
+ * description: set current descriptor address register
+ *              according to the desp for a given channel
+ *
+ *              if the given channel is busy return DMACHNBUSY
+ *              and no change made, otherwise return DMASUCCESS.
+ *
+ * note:
+ **************************************************************/
+static
+DMAStatus DMA_Bld_Desp( LOCATION host,
+                                                  unsigned int eumbbar,
+                                                  unsigned int channel,
+                                                  DMA_CDAR     desp )
+{
+       DMA_SR status;
+       unsigned int temp;
+
+       if ( channel != 0 && channel != 1 )
+       {
+               /* channel number out of range */
+               return DMAINVALID;
+       }
+
+       if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
+       {
+                       return DMAINVALID;
+       }
+
+       if ( status.cb == 1 )
+       {
+               /* channel busy */
+               return DMACHNBUSY;
+       }
+
+       temp = ( desp.cda & 0x7ffffff ) << 5;
+       temp |= (( desp.snen & 0x1 ) << 4 );
+       temp |= (( desp.eosie & 0x1 ) << 3 );
+       temp |= (( desp.ctt   & 0x3 ) << 1 );
+    temp |= ( desp.eotd  & 0x1 );
+
+    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
+
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) cdar := 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], temp );
+#endif
+
+       return DMASUCCESS;
+}
+
+/**************************************************************
+ * function: DMA_Poke_Desp
+ *
+ * description: poke the current descriptor address register
+ *              for a given channel
+ *
+ *              return DMASUCCESS if no error
+ *
+ * note: Due to the undeterministic parallellism of DMA operation,
+ *       the value returned by this function shall be taken as
+ *       the most recently used descriptor when the last time
+ *       DMA starts a chaining mode operation.
+ **************************************************************/
+static
+DMAStatus DMA_Poke_Desp( LOCATION host,
+                                                   unsigned int eumbbar,
+                                                   unsigned int channel,
+                                                   DMA_CDAR     *desp )
+{
+       unsigned int cdar;
+       if ( channel != 0 && channel != 1 || desp == 0 )
+       {
+                       return DMAINVALID;
+       }
+
+    cdar = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG] );
+
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) cdar : 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], cdar );
+#endif
+
+
+       desp->cda   = ( cdar & 0xffffffe0 ) >> 5;
+       desp->snen  = ( cdar & 0x00000010 ) >> 4;
+       desp->eosie = ( cdar & 0x00000008 ) >> 3;
+       desp->ctt   = ( cdar & 0x00000006 ) >> 1;
+       desp->eotd  = ( cdar & 0x00000001 );
+
+       return DMASUCCESS;
+}
+
+/**************************************************************
+ * function: DMA_Bld_Curr
+ *
+ * description: set current src, dest, byte count registers
+ *              according to the desp for a given channel
+ *              return DMASUCCESS if no error.
+ *
+ * note:
+ **************************************************************/
+static
+DMAStatus DMA_Bld_Curr( LOCATION host,
+                                          unsigned int eumbbar,
+                                          unsigned int channel,
+                                          DMA_CURR     desp )
+{
+       DMA_SR status;
+       if ( channel != 0 && channel != 1 )
+       {
+               /* channel number out of range */
+               return DMAINVALID;
+       }
+
+       if ( DMA_Get_Stat( host, eumbbar, channel, &status ) != DMASUCCESS )
+       {
+                return DMAINVALID;
+       }
+
+       if ( status.cb == 1  )
+       {
+               /* channel busy */
+               return DMACHNBUSY;
+       }
+
+       desp.byte_cnt &= 0x03ffffff; /* upper 6-bits are 0s */
+
+    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG], desp.src_addr );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) src := 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.src_addr );
+#endif
+
+    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG], desp.dest_addr );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) dest := 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.dest_addr );
+#endif
+
+    store_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG], desp.byte_cnt );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) count := 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp.byte_cnt );
+#endif
+
+
+       return DMASUCCESS;
+
+}
+
+/**************************************************************
+ * function: DMA_Poke_Curr
+ *
+ * description: poke the current src, dest, byte count registers
+ *              for a given channel.
+ *
+ *              return DMASUCCESS if no error
+ *
+ * note:        Due to the undeterministic parallelism, in chaining
+ *              mode, the value returned by this function shall
+ *              be taken as reference when the query is made rather
+ *              than the absolute snapshot when the value is returned.
+ **************************************************************/
+static
+DMAStatus DMA_Poke_Curr( LOCATION host,
+                                           unsigned int eumbbar,
+                                           unsigned int channel,
+                                           DMA_CURR*    desp )
+{
+       if ( channel != 0 && channel != 1 || desp == 0 )
+       {
+                       return DMAINVALID;
+       }
+
+       desp->src_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_SAR_REG] );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) src : 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->src_addr );
+#endif
+
+       desp->dest_addr = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_DAR_REG] );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) dest : 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->dest_addr );
+#endif
+
+    desp->byte_cnt = load_runtime_reg( eumbbar, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_BCR_REG] );
+#ifdef DMADBG0
+   PRINT( "%s(%d): %s DMA %d (0x%08x) count : 0x%08x\n", __FILE__, __LINE__,
+                 ( host == LOCAL ? "local" : "remote" ), channel, dma_reg_tb[host][channel*NUM_DMA_REG+DMA_CDAR_REG], desp->byte_cnt );
+#endif
+
+
+       return DMASUCCESS;
+}
+
+/*****************************************************************
+ * function: dma_error_func
+ *
+ * description: display the error information
+ *
+ * note: This seems like a highly convoluted way to handle messages,
+ * but I'll leave it as it was in device.c when I moved it into the
+ * DMA library source.
+ ****************************************************************/
+static
+DMAStatus dma_error_func( unsigned int eumbbar, unsigned int chn, DMAStatus err)
+{
+       unsigned char *msg[] =
+               {
+                       "Local Memory Error",
+                       "PCI Error",
+                       "Channel Busy",
+                       "End-of-Segment Interrupt",
+                       "End-of-Chain/Direct Interrupt",
+               };
+
+          if ( err >= DMALMERROR && err <= DMAEOCAINT )
+          {
+            PRINT( "DMA Status: channel %d  %s\n", chn, msg[err-DMASUCCESS-1] );
+          }
+
+          return err;
+
+}
+
+/*************************************************************
+ * function: DMA_ISR
+ *
+ * description: DMA interrupt service routine
+ *              return DMAStatus value based on
+ *              the status
+ *
+ *************************************************************/
+static
+DMAStatus DMA_ISR( unsigned int eumbbar,
+                                 unsigned int channel,
+                                 DMAStatus (*lme_func)( unsigned int, unsigned int, DMAStatus ),
+                                 DMAStatus (*pe_func) ( unsigned int, unsigned int, DMAStatus ),
+                                 DMAStatus (*eosi_func)( unsigned int, unsigned int, DMAStatus ),
+                                 DMAStatus (*eocai_func)(unsigned int, unsigned int, DMAStatus ))
+{
+
+       DMA_SR stat;
+       DMAStatus rval = DMANOEVENT;
+    unsigned int temp;
+
+       if ( channel != 0 && channel != 1 )
+       {
+               return DMAINVALID;
+       }
+
+       if ( DMA_Get_Stat( LOCAL, eumbbar, channel, &stat ) != DMASUCCESS )
+       {
+                       return DMAINVALID;
+       }
+
+       if ( stat.lme == 1 )
+       {
+               /* local memory error */
+               rval = DMALMERROR;
+               if ( lme_func != 0 )
+               {
+                 rval = (*lme_func)(eumbbar, channel, DMALMERROR );
+           }
+
+       }
+       else if ( stat.pe == 1 )
+       {
+        /* PCI error */
+               rval = DMAPERROR;
+               if ( pe_func != 0 )
+               {
+                 rval = (*pe_func)(eumbbar, channel, DMAPERROR );
+           }
+
+       }
+       else if ( stat.eosi == 1 )
+       {
+               /* end-of-segment interrupt */
+               rval = DMAEOSINT;
+               if ( eosi_func != 0 )
+               {
+                 rval = (*eosi_func)(eumbbar, channel, DMAEOSINT );
+           }
+       }
+       else
+       {
+               /* End-of-chain/direct interrupt */
+               rval = DMAEOCAINT;
+               if ( eocai_func != 0 )
+               {
+                 rval = (*eocai_func)(eumbbar, channel, DMAEOCAINT );
+           }
+       }
+
+    temp = ( stat.reserved0 & 0xffffff ) << 8;
+       temp |= ( ( stat.lme       & 0x1 ) << 7 );  /* write one to clear */
+       temp |= ( ( stat.reserved1 & 0x3 ) << 5 );
+    temp |= ( ( stat.pe        & 0x1 ) << 4 );  /* write one to clear */
+    temp |= ( ( stat.reserved2 & 0x1 ) << 3 );
+       temp |= ( ( stat.cb        & 0x1 ) << 2 );  /* write one to clear */
+    temp |= ( ( stat.eosi      & 0x1 ) << 1 );  /* write one to clear */
+    temp |= ( stat.eocai & 0x1 );               /* write one to clear */
+
+    store_runtime_reg( eumbbar, dma_reg_tb[LOCAL][channel*NUM_DMA_REG + DMA_SR_REG], temp );
+
+#ifdef DMADBG0
+       PRINT( "%s(%d): DMA channel %d SR := 0x%08x\n", __FILE__, __LINE__, channel, temp );
+#endif
+
+       return rval;
+}
diff --git a/cpu/mpc824x/drivers/dma/dma2.S b/cpu/mpc824x/drivers/dma/dma2.S
new file mode 100644 (file)
index 0000000..dab1de3
--- /dev/null
@@ -0,0 +1,45 @@
+/**************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ **************************************/
+
+/**********************************************************
+ * function: load_runtime_reg
+ *
+ * input:  r3 - value of eumbbar
+ *         r4 - register offset in embedded utility space
+ *
+ * output: r3 - register content
+ **********************************************************/
+      .text
+      .align 2
+      .global load_runtime_reg
+
+load_runtime_reg:
+
+             lwbrx     r3,r4,r3
+             sync
+
+             bclr 20, 0
+
+/****************************************************************
+ * function: store_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ *        r4 - register offset in embedded utility space
+ *        r5 - new value to be stored
+ *
+ ****************************************************************/
+           .text
+           .align 2
+           .global store_runtime_reg
+store_runtime_reg:
+
+             stwbrx r5,  r4, r3
+             sync
+
+                 bclr   20,0
+
+
+
diff --git a/cpu/mpc824x/drivers/dma/dma_export.h b/cpu/mpc824x/drivers/dma/dma_export.h
new file mode 100644 (file)
index 0000000..cb750dd
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef DMA_EXPORT_H
+#define DMA_EXPORT_H
+
+/****************************************************
+ * $Id:
+ *
+ * Copyright Motorola 1999
+ *
+ * $Log:
+ *
+ ****************************************************/
+
+/* These are the defined return values for the DMA_* functions.
+ * Any non-zero value indicates failure.  Failure modes can be added for
+ * more detailed error reporting.
+ */
+typedef enum _dma_status
+{
+ DMA_SUCCESS     = 0,
+ DMA_ERROR,
+} DMA_Status;
+
+/* These are the defined channel transfer types.  */
+typedef enum _dma_transfer_types
+{
+       DMA_M2M =  0,   /* local memory to local memory */
+       DMA_M2P =  1,   /* local memory to PCI */
+       DMA_P2M =  2,   /* PCI to local memory */
+       DMA_P2P =  3,   /* PCI to PCI */
+} DMA_TRANSFER_TYPE;
+
+typedef enum _dma_interrupt_steer
+{
+       DMA_INT_STEER_LOCAL =  0, /* steer DMA int to local processor */
+       DMA_INT_STEER_PCI = 1,    /* steer DMA int to PCI bus through INTA_ */
+} DMA_INTERRUPT_STEER;
+
+typedef enum _dma_channel
+{
+       DMA_CHN_0 =  0, /* kahlua has two dma channels: 0 and 1 */
+       DMA_CHN_1 =  1,
+} DMA_CHANNEL;
+
+typedef enum _dma_snoop_mode
+{
+       DMA_SNOOP_DISABLE =  0,
+       DMA_SNOOP_ENABLE = 1,
+} DMA_SNOOP_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application
+ * to use the functionality provided by DMA driver.
+ * This is a "generic" DMA interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ *
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we currently transfer whatever
+ *       we are given - Big/Little Endian.  This could
+ *       become part of the DMA config, though.
+ **************************************************/
+
+
+/*  Initialize DMA unit with the following:
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  ???
+ *  Interrupt enables, modes, etc. are set for each transfer.
+ *
+ *  This function must be called before DMA unit can be used.
+ */
+extern DMA_Status DMA_Initialize(
+        int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+                                                 * provided by application
+                                                 */
+
+/* Perform the DMA transfer, only direct mode is currently implemented.
+ * At this point, I think it would be better to define a different
+ * function for chaining mode.
+ * Also, I'm not sure if it is appropriate to have the "generic" API
+ * accept snoop and int_steer parameters.  The DINK user interface allows
+ * them, so for now I'll leave them.
+ *
+ * int_steer controls DMA interrupt steering to PCI or local processor
+ * type is the type of transfer: M2M, M2P, P2M, P2P
+ * source is the source address of the data
+ * dest is the destination address of the data
+ * len is the length of data to transfer
+ * channel is the DMA channel to use for the transfer
+ * snoop is the snoop enable control
+ */
+extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer,
+                                       DMA_TRANSFER_TYPE type,
+                                       unsigned int source,
+                                       unsigned int dest,
+                                       unsigned int len,
+                                       DMA_CHANNEL channel,
+                                       DMA_SNOOP_MODE snoop);
+#endif
diff --git a/cpu/mpc824x/drivers/dma_export.h b/cpu/mpc824x/drivers/dma_export.h
new file mode 100644 (file)
index 0000000..cb750dd
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef DMA_EXPORT_H
+#define DMA_EXPORT_H
+
+/****************************************************
+ * $Id:
+ *
+ * Copyright Motorola 1999
+ *
+ * $Log:
+ *
+ ****************************************************/
+
+/* These are the defined return values for the DMA_* functions.
+ * Any non-zero value indicates failure.  Failure modes can be added for
+ * more detailed error reporting.
+ */
+typedef enum _dma_status
+{
+ DMA_SUCCESS     = 0,
+ DMA_ERROR,
+} DMA_Status;
+
+/* These are the defined channel transfer types.  */
+typedef enum _dma_transfer_types
+{
+       DMA_M2M =  0,   /* local memory to local memory */
+       DMA_M2P =  1,   /* local memory to PCI */
+       DMA_P2M =  2,   /* PCI to local memory */
+       DMA_P2P =  3,   /* PCI to PCI */
+} DMA_TRANSFER_TYPE;
+
+typedef enum _dma_interrupt_steer
+{
+       DMA_INT_STEER_LOCAL =  0, /* steer DMA int to local processor */
+       DMA_INT_STEER_PCI = 1,    /* steer DMA int to PCI bus through INTA_ */
+} DMA_INTERRUPT_STEER;
+
+typedef enum _dma_channel
+{
+       DMA_CHN_0 =  0, /* kahlua has two dma channels: 0 and 1 */
+       DMA_CHN_1 =  1,
+} DMA_CHANNEL;
+
+typedef enum _dma_snoop_mode
+{
+       DMA_SNOOP_DISABLE =  0,
+       DMA_SNOOP_ENABLE = 1,
+} DMA_SNOOP_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application
+ * to use the functionality provided by DMA driver.
+ * This is a "generic" DMA interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ *
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we currently transfer whatever
+ *       we are given - Big/Little Endian.  This could
+ *       become part of the DMA config, though.
+ **************************************************/
+
+
+/*  Initialize DMA unit with the following:
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  ???
+ *  Interrupt enables, modes, etc. are set for each transfer.
+ *
+ *  This function must be called before DMA unit can be used.
+ */
+extern DMA_Status DMA_Initialize(
+        int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+                                                 * provided by application
+                                                 */
+
+/* Perform the DMA transfer, only direct mode is currently implemented.
+ * At this point, I think it would be better to define a different
+ * function for chaining mode.
+ * Also, I'm not sure if it is appropriate to have the "generic" API
+ * accept snoop and int_steer parameters.  The DINK user interface allows
+ * them, so for now I'll leave them.
+ *
+ * int_steer controls DMA interrupt steering to PCI or local processor
+ * type is the type of transfer: M2M, M2P, P2M, P2P
+ * source is the source address of the data
+ * dest is the destination address of the data
+ * len is the length of data to transfer
+ * channel is the DMA channel to use for the transfer
+ * snoop is the snoop enable control
+ */
+extern DMA_Status DMA_direct_transfer( DMA_INTERRUPT_STEER int_steer,
+                                       DMA_TRANSFER_TYPE type,
+                                       unsigned int source,
+                                       unsigned int dest,
+                                       unsigned int len,
+                                       DMA_CHANNEL channel,
+                                       DMA_SNOOP_MODE snoop);
+#endif
diff --git a/cpu/mpc824x/drivers/epic.h b/cpu/mpc824x/drivers/epic.h
new file mode 100644 (file)
index 0000000..2803f63
--- /dev/null
@@ -0,0 +1 @@
+#include "epic/epic.h"
diff --git a/cpu/mpc824x/drivers/epic/README b/cpu/mpc824x/drivers/epic/README
new file mode 100644 (file)
index 0000000..ae95b88
--- /dev/null
@@ -0,0 +1,104 @@
+CONTENT:
+
+   epic.h
+   epic1.c
+   epic2.s
+
+WHAT ARE THESE FILES:
+
+These files contain MPC8240 (Kahlua) EPIC
+driver routines. The driver routines are not
+written for any specific operating system.
+They serves the purpose of code sample, and
+jump-start for using the MPC8240 EPIC unit.
+
+For the reason of correctness of C language
+syntax, these files are compiled by Metaware
+C compiler and assembler.
+
+ENDIAN NOTATION:
+
+The algorithm is designed for big-endian mode,
+software is responsible for byte swapping.
+
+USAGE:
+
+1. The host system that is running on MPC8240
+   shall link the files listed here. The memory
+   location of driver routines shall take into
+   account of that driver routines need to run
+   in supervisor mode and they process external
+   interrupts.
+
+   The routine epic_exception shall be called by
+   exception vector at location 0x500, i.e.,
+   603e core external exception vector.
+
+2. The host system is responsible for configuring
+   the MPC8240 including Embedded Utilities Memory
+   Block. All EPIC driver functions require the
+   content of Embedded Utilities Memory Block
+   Base Address Register, EUMBBAR, as the first
+   parameter.
+
+3. Before EPIC unit of MPC8240 can be used,
+   initialize EPIC unit by calling epicInit
+   with the corresponding parameters.
+
+   The initialization shall disable the 603e
+   core External Exception by calling CoreExtIntDisable( ).
+   Next, call epicInit( ). Last, enable the 603e core
+   External Exception by calling CoreExtIntEnable( ).
+
+4. After EPIC unit has been successfully initialized,
+   epicIntSourceSet( ) shall be used to register each
+   external interrupt source. Anytime, an external
+   interrupt source can be disabled or enabled by
+   calling corresponding function, epicIntDisable( ),
+   or epicIntEnable( ).
+
+   Global Timers' resource, base count and frequency,
+   can be changed by calling epicTmFrequencySet( )
+   and epicTmBaseSet( ).
+
+   To stop counting a specific global timer, use
+   the function, epicTmInhibit while epicTmEnable
+   can be used to start counting a timer.
+
+5. To mask a set of external interrupts that are
+   are certain level below, epicIntPrioritySet( )
+   can be used. For example, if the processor's
+   current task priority register is set to 0x7,
+   only interrupts of priority 0x8 or higher will
+   be passed to the processor.
+
+   Be careful when using this function. It may
+   corrupt the current interrupt pending, selector,
+   and request registers, resulting an invalid vetor.
+
+   After enabling an interrupt, disable it may also
+   cause an invalid vector. User may consider using
+   the spurious vector interrupt service routine to
+   handle this case.
+
+6. The EPIC driver routines contains a set
+   of utilities, Set and Get, for host system
+   to query and modify the desired EPIC source
+   registers.
+
+7. Each external interrupt source shall register
+   its interrupt service routine. The routine
+   shall contain all interrupt source specific
+   processes and keep as short as possible.
+
+   Special customized end of interrupt routine
+   is optional. If it is needed, it shall contain
+   the external interrupt source specific end of
+   interrupt process.
+
+   External interrupt exception vector at 0x500
+   shall always call the epicEOI just before
+   rfi instruction. Refer to the routine,
+   epic_exception, for a code sample.
+
+
diff --git a/cpu/mpc824x/drivers/epic/epic2.S b/cpu/mpc824x/drivers/epic/epic2.S
new file mode 100644 (file)
index 0000000..8979f88
--- /dev/null
@@ -0,0 +1,196 @@
+/**************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ **************************************/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/processor.h>
+
+/*********************************************
+ * function: CoreExtIntEnable
+ *
+ * description: Enable 603e core external interrupt
+ *
+ * note: mtmsr is context-synchronization
+ **********************************************/
+               .text
+               .align 2
+        .global CoreExtIntEnable
+CoreExtIntEnable:
+         mfmsr    r3
+
+         ori      r3,r3,0x8000         /* enable external interrupt */
+         mtmsr    r3
+
+         bclr 20, 0
+
+/*******************************************
+ * function: CoreExtIntDisable
+ *
+ * description: Disable 603e core external interrupt
+ *
+ * note:
+ *******************************************/
+               .text
+               .align 2
+        .global CoreExtIntDisable
+CoreExtIntDisable:
+        mfmsr    r4
+
+       xor     r3,r3,r3
+       or      r3,r3,r4
+
+       andis.  r4,r4,0xffff
+        andi.   r3,r3,0x7fff         /* disable external interrupt */
+
+       or      r3,r3,r4
+        mtmsr    r3
+
+        bclr 20, 0
+
+/*********************************************************
+ * function: epicEOI
+ *
+ * description: signal the EOI and restore machine status
+ *       Input: r3 - value of eumbbar
+ *       Output: r3 - value of eumbbar
+ *               r4 - ISR vector value
+ * note:
+ ********************************************************/
+               .text
+               .align 2
+        .global epicEOI
+epicEOI:
+       lis     r5,0x0006               /* Build End Of Interrupt Register offset */
+       ori     r5,r5,0x00b0
+       xor     r7,r7,r7                /* Clear r7 */
+       stwbrx  r7,r5,r3            /* Save r7, writing to this register will
+                                            * intidate the end of processing the
+                                            * highest interrupt.
+                             */
+       sync
+
+       /* ---RESTORE MACHINE STATE */
+       mfmsr   r13                     /* Clear Recoverable Interrupt bit in MSR */
+        or      r7,r7,r13
+
+       andis.  r7,r7,0xffff
+       andi.   r13,r13,0x7ffd  /* (and disable interrupts) */
+       or      r13,r13,r7
+       mtmsr   r13
+
+       lwz   r13,0x1c(r1)      /* pull ctr */
+       mtctr r13
+
+       lwz   r13,0x18(r1)      /* pull xer */
+       mtctr r13
+
+       lwz   r13,0x14(r1)      /* pull lr */
+       mtctr r13
+
+       lwz         r13,0x10(r1)        /* Pull SRR1 from stack */
+       mtspr   SRR1,r13            /* Restore SRR1 */
+
+       lwz         r13,0xc(r1)     /* Pull SRR0 from stack */
+       mtspr   SRR0,r13            /* Restore SRR0 */
+
+       lwz         r13,0x8(r1)     /* Pull User stack pointer from stack */
+       mtspr   SPRG1,r13           /* Restore SPRG1 */
+
+       lwz     r4,0x4(r1)          /* vector value */
+       lwz     r3,0x0(r1)          /* eumbbar */
+       sync
+
+       addi    r1,r1,0x20      /* Deallocate stack */
+       mtspr   SPRG0,r1        /* Save updated Supervisor stack pointer */
+       mfspr   r1,SPRG1        /* Restore User stack pointer */
+
+       bclr     20,0
+
+/***********************************************************
+ * function: exception routine called by exception vector
+ *           at 0x500, external interrupt
+ *
+ * description: Kahlua EPIC controller
+ *
+ * input:  r3 - content of eumbbar
+ * output: r3 - ISR return value
+ *         r4 - Interrupt vector number
+ * note:
+ ***********************************************************/
+
+       .text
+          .align 2
+       .global epic_exception
+
+epic_exception:
+
+       /*---SAVE MACHINE STATE TO A STACK */
+       mtspr   SPRG1,r1        /* Save User stack pointer to SPRG1 */
+       mfspr   r1,SPRG0        /* Load Supervisor stack pointer into r1 */
+
+       stwu    r3,-0x20(r1)    /* Push the value of eumbbar onto stack */
+
+       mfspr   r3,SPRG1        /* Push User stack pointer onto stack */
+       stw         r3,0x8(r1)
+       mfspr   r3,SRR0     /* Push SRR0 onto stack */
+       stw         r1,0xc(r1)
+       mfspr   r3,SRR1     /* Push SRR1 onto stack */
+       stw         r3,0x10(r1)
+       mflr    r3
+       stw     r3,0x14(r1) /* Push LR */
+       mfxer   r3
+       stw     r3,0x18(r1) /* Push Xer */
+       mfctr   r3
+       stw     r3,0x1c(r1) /* Push CTR */
+
+       mtspr   SPRG0,r1        /* Save updated Supervisor stack pointer
+                                        * value to SPRG0
+                         */
+       mfmsr   r3
+       ori         r3,r3,0x0002        /* Set Recoverable Interrupt bit in MSR */
+       mtmsr   r3
+
+       /* ---READ IN THE EUMBAR REGISTER */
+    lwz     r6,0(r1)       /* this is eumbbar */
+    sync
+
+       /* ---READ EPIC REGISTER:       PROCESSOR INTERRUPT ACKNOWLEDGE REGISTER */
+       lis     r5,0x0006               /* Build Interrupt Acknowledge Register
+                                            * offset
+                             */
+       ori     r5,r5,0x00a0
+       lwbrx   r7,r5,r6    /* Load interrupt vector into r7 */
+       sync
+
+       /* --MASK OFF ALL BITS EXCEPT THE VECTOR */
+       xor     r3,r3,r3
+    xor r4,r4,r4
+       or    r3, r3, r6        /*  eumbbar in r3 */
+       andi. r4,r7,0x00ff      /* Mask off bits, vector in r4 */
+
+    stw     r4,0x04(r1)     /* save the vector value */
+
+    lis     r5,epicISR@ha
+       ori     r5,r5,epicISR@l
+       mtlr    r5
+       blrl
+
+    xor   r30,r30,r30
+       or    r30,r30,r3        /* save the r3 which containts the return value from epicISR */
+
+       /* ---READ IN THE EUMBAR REGISTER */
+    lwz     r3,0(r1)
+    sync
+
+    lis     r5,epicEOI@ha
+       ori     r5,r5,epicEOI@l
+       mtlr    r5
+       blrl
+
+    xor  r3,r3,r3
+       or   r3,r3,r30           /* restore the ISR return value  */
+
+       bclr     20,0
diff --git a/cpu/mpc824x/drivers/epic/epicutil.S b/cpu/mpc824x/drivers/epic/epicutil.S
new file mode 100644 (file)
index 0000000..a83fbd8
--- /dev/null
@@ -0,0 +1,58 @@
+/**************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ *
+ * This file contains two commonly used
+ * lower level utility routines.
+ *
+ * The utility routines are also in other
+ * Kahlua device driver libraries. The
+ * need to be linked in only once.
+ **************************************/
+
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+
+/**********************************************************
+ * function: load_runtime_reg
+ *
+ * input:  r3 - value of eumbbar
+ *         r4 - register offset in embedded utility space
+ *
+ * output: r3 - register content
+ **********************************************************/
+      .text
+      .align 2
+      .global load_runtime_reg
+
+load_runtime_reg:
+
+                 xor r5,r5,r5
+          or  r5,r5,r3       /* save eumbbar */
+
+             lwbrx     r3,r4,r5
+             sync
+
+             bclr 20, 0
+
+/****************************************************************
+ * function: store_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ *        r4 - register offset in embedded utility space
+ *        r5 - new value to be stored
+ *
+ ****************************************************************/
+           .text
+           .align 2
+           .global store_runtime_reg
+store_runtime_reg:
+
+                 xor r0,r0,r0
+
+             stwbrx r5,  r4, r3
+             sync
+
+                 bclr   20,0
+
diff --git a/cpu/mpc824x/drivers/errors.h b/cpu/mpc824x/drivers/errors.h
new file mode 100644 (file)
index 0000000..1435188
--- /dev/null
@@ -0,0 +1,218 @@
+/*     Copyright Motorola, Inc. 1993, 1994
+       ALL RIGHTS RESERVED
+
+       You are hereby granted a copyright license to use, modify, and
+       distribute the SOFTWARE so long as this entire notice is retained
+       without alteration in any modified and/or redistributed versions,
+       and that such modified versions are clearly identified as such.
+       No licenses are granted by implication, estoppel or otherwise under
+       any patents or trademarks of Motorola, Inc.
+
+       The SOFTWARE is provided on an "AS IS" basis and without warranty.
+       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS
+       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED
+       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
+       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS
+       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS.
+
+       To the maximum extent permitted by applicable law, IN NO EVENT SHALL
+       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
+       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR
+       INABILITY TO USE THE SOFTWARE.   Motorola assumes no responsibility
+       for the maintenance and support of the SOFTWARE.
+
+*/
+
+
+#include "config.h"
+
+/*
+         1         2         3         4         5         6         7         8
+01234567890123456789012345678901234567890123456789012345678901234567890123456789
+*/
+/* List define statements here */
+
+/* These are for all the toolboxes and functions to use. These will help
+to standardize the error handling in the current project */
+
+                               /* this is the "data type" for the error
+                               messages in the system */
+#define STATUS unsigned int
+
+                               /* this is a success status code */
+#define SUCCESS 1
+
+                               /* likewise this is failure */
+#define FAILURE 0
+
+#define NUM_ERRORS 47
+
+/* This first section of "defines" are for error codes ONLY.  The called
+   routine will return one of these error codes to the caller.  If the final
+   returned code is "VALID", then everything is a-okay.  However, if one
+   of the functions returns a non-valid status, that error code should be
+   propogated back to all the callers.  At the end, the last caller will
+   call an error_processing function, and send in the status which was
+   returned.  It's up to the error_processing function to determine which
+   error occured (as indicated by the status), and print an appropriate
+   message back to the user.
+*/
+/*----------------------------------------------------------------------*/
+/* these are specifically for the parser routines                      */
+
+#define UNKNOWN_COMMAND                0xfb00 /* "unrecognized command " */
+#define UNKNOWN_REGISTER       0xfb01 /* "unknown register "*/
+#define ILLEGAL_RD_STAGE       0xfb02 /* cannot specify reg. family in range*/
+#define ILLEGAL_REG_FAMILY     0xfb03 /* "cannot specify a range of special
+                                       or miscellaneous registers"*/
+#define RANGE_CROSS_FAMILY     0xfb04 /* "cannot specify a range across
+                                       register families" */
+#define UNIMPLEMENTED_STAGE    0xfb05 /* invalid rd or rmm parameter format */
+#define REG_NOT_WRITEABLE      0xfb06 /* "unknown operator in arguements"*/
+#define INVALID_FILENAME       0xfb07 /* "invalid download filename" */
+#define INVALID_BAUD_RATE      0xfb08  /* invalid baud rate from sb command */
+#define UNSUPPORTED_REGISTER   0xfb09  /* Special register is not supported */
+#define FOR_BOARD_ONLY         0xfb0a  /* "Not available for Unix." */
+
+
+
+/*----------------------------------------------------------------------*/
+/* these are for the error checking toolbox                            */
+
+#define INVALID                        0xfd00 /* NOT valid */
+#define VALID                  0xfd01 /* valid */
+
+                                       /* This error is found in the fcn:
+                                       is_right_size_input() to indicate
+                                       that the input was not 8 characters
+                                       long.  */
+#define INVALID_SIZE           0xfd02
+
+                                       /* This error is found in the fcn:
+                                       is_valid_address_range() to indicate
+                                       that the address given falls outside
+                                       of valid memory defined by MEM_START
+                                       to MEM_END.
+                                       */
+#define OUT_OF_BOUNDS_ADDRESS  0xfd03
+
+                                       /* This error is found in the fcn:
+                                       is_valid_hex_input() to indicate that
+                                       one of more of the characters entered
+                                       are not valid hex characters.  Valid
+                                       hex characters are 0-9, A-F, a-f.
+                                       */
+#define INVALID_HEX_INPUT      0xfd04
+
+                                       /* This error is found in the fcn:
+                                       is_valid_register_number() to indicate
+                                       that a given register does not exist.
+                                       */
+#define REG_NOT_READABLE       0xfd05
+
+                                       /* This error is found in the fcn:
+                                       is_word_aligned_address() to indicate
+                                       that the given address is not word-
+                                       aligned.  A word-aligned address ends
+                                       in 0x0,0x4,0x8,0xc.
+                                       */
+#define        NOT_WORD_ALIGNED        0xfd07
+
+                                       /* This error is found in the fcn:
+                                       is_valid_address_range() to indicate
+                                       that the starting address is greater
+                                       than the ending address.
+                                       */
+#define REVERSED_ADDRESS       0xfd08
+
+                                       /* this error tells us that the address
+                                       specified as the destination is within
+                                       the source addresses  */
+#define RANGE_OVERLAP          0xfd09
+
+
+#define        ERROR                   0xfd0a /* An error occured */
+#define INVALID_PARAM          0xfd0b /* "invalid input parameter " */
+
+
+#define INVALID_FLAG           0xfd0c  /* invalid flag */
+
+/*----------------------------------------------------------------------*/
+/* these are for the getarg toolbox                                    */
+
+#define INVALID_NUMBER_ARGS    0xFE00 /* invalid number of commd arguements */
+#define UNKNOWN_PARAMETER      0xFE01 /* "unknown type of parameter "*/
+
+
+
+
+
+/*----------------------------------------------------------------------*/
+/* these are for the tokenizer toolbox                                         */
+
+#define ILLEGAL_CHARACTER      0xFF00 /* unrecognized char. in input stream*/
+#define TTL_NOT_SORTED                 0xFF01 /* token translation list not sorted */
+#define TTL_NOT_DEFINED        0xFF02 /* token translation list not assigned*/
+#define INVALID_STRING                 0xFF03 /* unable to extract string from input */
+#define BUFFER_EMPTY           0xFF04 /* "input buffer is empty" */
+#define INVALID_MODE           0xFF05 /* input buf is in an unrecognized mode*/
+#define TOK_INTERNAL_ERROR     0xFF06 /* "internal tokenizer error" */
+#define TOO_MANY_IBS           0xFF07 /* "too many open input buffers" */
+#define NO_OPEN_IBS            0xFF08 /* "no open input buffers" */
+
+
+
+/* these are for the read from screen toolbox */
+
+#define RESERVED_WORD          0xFC00 /* used a reserved word as an arguement*/
+
+
+/* these are for the breakpoint routines */
+
+#define FULL_BPDS              0xFA00 /* breakpoint data structure is full */
+
+
+
+/* THESE are for the downloader */
+
+#define NOT_IN_S_RECORD_FORMAT         0xf900 /* "not in S-Record Format" */
+#define UNREC_RECORD_TYPE      0xf901 /* "unrecognized record type" */
+#define CONVERSION_ERROR       0xf902 /* "ascii to int conversion error" */
+#define INVALID_MEMORY         0xf903 /* "bad s-record memory address " */
+
+
+/* these are for the compression and decompression stuff */
+
+#define COMP_UNK_CHARACTER     0xf800 /* "unknown compressed character " */
+
+#define COMP_UNKNOWN_STATE     0xf801 /* "unknown binary state" */
+
+#define NOT_IN_COMPRESSED_FORMAT 0xf802 /* not in compressed S-Record format */
+
+
+/* these are for the DUART handling things */
+
+                                       /* "unrecognized serial port configuration" */
+#define UNKNOWN_PORT_STATE     0xf700
+
+
+/* these are for the register toolbox */
+
+                                       /* "cannot find register in special
+                                        purpose register file " */
+#define SPR_NOT_FOUND          0xf600
+
+
+/* these are for the duart specific stuff */
+
+                                       /* "transparent mode needs access to
+                                               two serial ports" */
+#define TM_NEEDS_BOTH_PORTS    0xf500
+
+
+/*----------------------------------------------------------------------*/
+/* these are specifically for the flash routines                       */
+#define FLASH_ERROR            0xf100          /* general flash error */
diff --git a/cpu/mpc824x/drivers/i2c/Makefile b/cpu/mpc824x/drivers/i2c/Makefile
new file mode 100644 (file)
index 0000000..ae1a94c
--- /dev/null
@@ -0,0 +1,84 @@
+##########################################################################
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and
+#       distribute the SOFTWARE so long as this entire notice is retained
+#       without alteration in any modified and/or redistributed versions,
+#       and that such modified versions are clearly identified as such.
+#       No licenses are granted by implication, estoppel or otherwise under
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS.
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR
+#       INABILITY TO USE THE SOFTWARE.
+#
+############################################################################
+TARGET = libi2c.a
+
+#DEBUG  = -g
+DEBUG   = -DI2CDBG
+LST     = -Hanno -S
+OPTIM   =
+CC      = /risc/tools/pkgs/metaware/bin/hcppc
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG = -l -fm
+AS      = /risc/tools/pkgs/metaware/bin/asppc
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -q -Qn -r
+LKCMD   =
+LINK    =  /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = i2c1.o i2c2.o
+
+all: $(TARGET)
+
+objects: $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+clean:
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+
+.s.o:
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+i2c1.o: i2c_export.h i2c.h i2c1.c
+
+i2c2.o: i2c.h i2c2.s
diff --git a/cpu/mpc824x/drivers/i2c/Makefile_pc b/cpu/mpc824x/drivers/i2c/Makefile_pc
new file mode 100644 (file)
index 0000000..4d42c7b
--- /dev/null
@@ -0,0 +1,91 @@
+##########################################################################
+#
+#       makefile_pc for use with PC mksnt tools  dink32/drivers/i2c
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and
+#       distribute the SOFTWARE so long as this entire notice is retained
+#       without alteration in any modified and/or redistributed versions,
+#       and that such modified versions are clearly identified as such.
+#       No licenses are granted by implication, estoppel or otherwise under
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS.
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR
+#       INABILITY TO USE THE SOFTWARE.
+#
+############################################################################
+TARGET = libi2c.a
+
+#DEBUG  = -g
+DEBUG   = -DI2CDBG
+LST     = -Hanno -S
+OPTIM   =
+CC      = m:/old_tools/tools/hcppc/bin/hcppc
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG = -l -fm
+AS      = m:/old_tools/tools/hcppc/bin/asppc
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -q -Qn -r
+LKCMD   =
+LINK    = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = i2c1.o i2c2.o
+
+all: $(TARGET)
+
+objects: $(OBJECTS)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+clean:
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+
+.s.o:
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+i2c1.o: i2c_export.h i2c.h i2c1.c
+       $(CCobj) $<
+
+
+i2c2.o: i2c.h i2c2.s
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
diff --git a/cpu/mpc824x/drivers/i2c/README b/cpu/mpc824x/drivers/i2c/README
new file mode 100644 (file)
index 0000000..8d82df3
--- /dev/null
@@ -0,0 +1,105 @@
+CONTENT:
+
+   i2c.h
+   i2c1.c
+   i2c2.s
+
+WHAT ARE THESE FILES:
+
+These files contain MPC8240 (Kahlua) I2C
+driver routines. The driver routines are not
+written for any specific operating system.
+They serves the purpose of code sample, and
+jump-start for using the MPC8240 I2C unit.
+
+For the reason of correctness of C language
+syntax, these files are compiled by Metaware
+C compiler and assembler.
+
+ENDIAN NOTATION:
+
+The algorithm is designed for big-endian mode,
+software is responsible for byte swapping.
+
+USAGE:
+
+1. The host system that is running on MPC8240
+   shall link the files listed here. The memory
+   location of driver routines shall take into
+   account of that driver routines need to run
+   in supervisor mode and they process I2C
+   interrupt.
+
+2. The host system is responsible for configuring
+   the MPC8240 including Embedded Utilities Memory
+   Block. All I2C driver functions require the
+   content of Embedded Utilities Memory Block
+   Base Address Register, EUMBBAR, as the first
+   parameter.
+
+3. Before I2C unit of MPC8240 can be used,
+   initialize I2C unit by calling I2C_Init
+   with the corresponding parameters.
+
+   Note that the I2CFDR register shall be written
+   once during the initialization. If it is written
+   in the midst of transers, or after I2C STOPs or
+   REPEAT STATRs, depending on the data written,
+   a long reset time may be encountered.
+
+4. After I2C unit has been successfully initialized,
+   use the Application level API to send data or
+   receive data upon the desired mode, Master or
+   Slave.
+
+5. If the host system is also using the EPIC unit
+   on MPC8240, the system can register the
+   I2C_ISR with the EPIC including other
+   desired resources.
+
+   If the host system does not using the EPIC unit
+   on MPC8240, I2C_Timer_Event function can
+   be called for each desired time interval.
+
+   In both cases, the host system is free to provide
+   its own timer event handler and interrupt service
+   routine.
+
+6. The I2C driver routines contains a set
+   of utilities, Set and Get, for host system
+   to query and modify the desired I2C registers.
+
+7. It is the host system's responsibility of
+   queueing the I2C I/O request. The host
+   system shall check the I2C_ISR return code
+   for I2C I/O status. If I2C_ISR returns
+   I2CBUFFEMPTY or I2CBUFFFULL, it means
+   I2C unit has completed a I/O request
+   stated by the Application API.
+
+8. If the host system has more than one master
+   mode I2C unit I/O requests but doesn't want
+   to be intervented by being addressed as slave,
+   the host system can use the master mode
+   Application API with stop_flag set to 0 in
+   conjunction with is_cnt flag set to 1.
+   The first API call sets both stop_flag and
+   is_cnt to 0, indicating a START condition
+   shall be generated but when the end of
+   transaction is reached, do not generate a
+   STOP condition. Once the host system is
+   informed that the transaction has been
+   completed, the next Application API call
+   shall set is_cnt flag to 1, indicating a
+   repeated START condition shall be generated.
+   The last Application API call shall set
+   stop_flag
+   to 1.
+
+9. The I2C_Timer_Event function containes
+   a user defined function pointer. It
+   serves the purpose of providing the
+   host system a way to use its own event
+   handler instead of the I2C_ISR provided
+   here.
+
diff --git a/cpu/mpc824x/drivers/i2c/i2c_export.h b/cpu/mpc824x/drivers/i2c/i2c_export.h
new file mode 100644 (file)
index 0000000..17403ea
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef I2C_EXPORT_H
+#define I2C_EXPORT_H
+
+/****************************************************
+ *
+ * Copyright Motrola 1999
+ *
+ ****************************************************/
+
+/* These are the defined return values for the I2C_do_transaction function.
+ * Any non-zero value indicates failure.  Failure modes can be added for
+ * more detailed error reporting.
+ */
+typedef enum _i2c_status
+{
+ I2C_SUCCESS     = 0,
+ I2C_ERROR,
+} I2C_Status;
+
+/* These are the defined tasks for I2C_do_transaction.
+ * Modes for SLAVE_RCV and SLAVE_XMIT will be added.
+ */
+typedef enum _i2c_transaction_mode
+{
+       I2C_MASTER_RCV =  0,
+       I2C_MASTER_XMIT = 1,
+} I2C_TRANSACTION_MODE;
+
+typedef enum _i2c_interrupt_mode
+{
+       I2C_INT_DISABLE =  0,
+       I2C_INT_ENABLE = 1,
+} I2C_INTERRUPT_MODE;
+
+typedef enum _i2c_stop
+{
+       I2C_NO_STOP =  0,
+       I2C_STOP = 1,
+} I2C_STOP_MODE;
+
+typedef enum _i2c_restart
+{
+       I2C_NO_RESTART =  0,
+       I2C_RESTART = 1,
+} I2C_RESTART_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application
+ * to use the functionality provided by I2C driver.
+ * This is a "generic" I2C interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ *
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we just transfer whatever
+ *       we are given
+ **************************************************/
+
+
+/*  Initialize I2C unit with the following:
+ *  driver's slave address
+ *  interrupt enabled
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  desired clock rate
+ *  digital filter frequency sampling rate
+ *
+ *  This function must be called before I2C unit can be used.
+ */
+extern I2C_Status I2C_Initialize(
+       unsigned char addr,            /* driver's I2C slave address */
+       I2C_INTERRUPT_MODE en_int,     /* 1 - enable I2C interrupt
+                                       * 0 - disable I2C interrupt
+                                       */
+        int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+                                                 * provided by application
+                                                 */
+
+/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV
+ * are implemented.  Both are only in polling mode.
+ *
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * addr is the I2C address of the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int,
+                                      I2C_TRANSACTION_MODE act,
+                                      unsigned char i2c_addr,
+                                      unsigned char data_addr,
+                                      int len,
+                                      char *buffer,
+                                      I2C_STOP_MODE stop,
+                                      int retry,
+                                      I2C_RESTART_MODE rsta);
+#endif
diff --git a/cpu/mpc824x/drivers/i2c_export.h b/cpu/mpc824x/drivers/i2c_export.h
new file mode 100644 (file)
index 0000000..17403ea
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef I2C_EXPORT_H
+#define I2C_EXPORT_H
+
+/****************************************************
+ *
+ * Copyright Motrola 1999
+ *
+ ****************************************************/
+
+/* These are the defined return values for the I2C_do_transaction function.
+ * Any non-zero value indicates failure.  Failure modes can be added for
+ * more detailed error reporting.
+ */
+typedef enum _i2c_status
+{
+ I2C_SUCCESS     = 0,
+ I2C_ERROR,
+} I2C_Status;
+
+/* These are the defined tasks for I2C_do_transaction.
+ * Modes for SLAVE_RCV and SLAVE_XMIT will be added.
+ */
+typedef enum _i2c_transaction_mode
+{
+       I2C_MASTER_RCV =  0,
+       I2C_MASTER_XMIT = 1,
+} I2C_TRANSACTION_MODE;
+
+typedef enum _i2c_interrupt_mode
+{
+       I2C_INT_DISABLE =  0,
+       I2C_INT_ENABLE = 1,
+} I2C_INTERRUPT_MODE;
+
+typedef enum _i2c_stop
+{
+       I2C_NO_STOP =  0,
+       I2C_STOP = 1,
+} I2C_STOP_MODE;
+
+typedef enum _i2c_restart
+{
+       I2C_NO_RESTART =  0,
+       I2C_RESTART = 1,
+} I2C_RESTART_MODE;
+
+/******************** App. API ********************
+ * The application API is for user level application
+ * to use the functionality provided by I2C driver.
+ * This is a "generic" I2C interface, it should contain
+ * nothing specific to the Kahlua implementation.
+ * Only the generic functions are exported by the library.
+ *
+ * Note: Its App.s responsibility to swap the data
+ *       byte. In our API, we just transfer whatever
+ *       we are given
+ **************************************************/
+
+
+/*  Initialize I2C unit with the following:
+ *  driver's slave address
+ *  interrupt enabled
+ *  optional pointer to application layer print function
+ *
+ *  These parameters may be added:
+ *  desired clock rate
+ *  digital filter frequency sampling rate
+ *
+ *  This function must be called before I2C unit can be used.
+ */
+extern I2C_Status I2C_Initialize(
+       unsigned char addr,            /* driver's I2C slave address */
+       I2C_INTERRUPT_MODE en_int,     /* 1 - enable I2C interrupt
+                                       * 0 - disable I2C interrupt
+                                       */
+        int (*app_print_function)(char *,...)); /* pointer to optional "printf"
+                                                 * provided by application
+                                                 */
+
+/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV
+ * are implemented.  Both are only in polling mode.
+ *
+ * en_int controls interrupt/polling mode
+ * act is the type of transaction
+ * addr is the I2C address of the slave device
+ * len is the length of data to send or receive
+ * buffer is the address of the data buffer
+ * stop = I2C_NO_STOP, don't signal STOP at end of transaction
+ *        I2C_STOP, signal STOP at end of transaction
+ * retry is the timeout retry value, currently ignored
+ * rsta = I2C_NO_RESTART, this is not continuation of existing transaction
+ *        I2C_RESTART, this is a continuation of existing transaction
+ */
+extern I2C_Status I2C_do_transaction( I2C_INTERRUPT_MODE en_int,
+                                      I2C_TRANSACTION_MODE act,
+                                      unsigned char i2c_addr,
+                                      unsigned char data_addr,
+                                      int len,
+                                      char *buffer,
+                                      I2C_STOP_MODE stop,
+                                      int retry,
+                                      I2C_RESTART_MODE rsta);
+#endif
diff --git a/cpu/mpc824x/drivers/i2o.h b/cpu/mpc824x/drivers/i2o.h
new file mode 100644 (file)
index 0000000..87225ab
--- /dev/null
@@ -0,0 +1,344 @@
+#ifndef I2O_H
+#define I2O_H
+/*********************************************************
+ *
+ * copyright @ Motorola, 1999
+ *********************************************************/
+
+#define I2O_REG_OFFSET 0x0004
+
+#define PCI_CFG_CLA    0x0B
+#define PCI_CFG_SCL    0x0A
+#define PCI_CFG_PIC    0x09
+
+#define I2O_IMR0 0x0050
+#define I2O_IMR1 0x0054
+#define I2O_OMR0 0x0058
+#define I2O_OMR1 0x005C
+
+#define I2O_ODBR 0x0060
+#define I2O_IDBR 0x0068
+
+#define I2O_OMISR  0x0030
+#define I2O_OMIMR  0x0034
+#define I2O_IMISR  0x0100
+#define I2O_IMIMR  0x0104
+
+/* accessable to PCI master but local processor */
+#define I2O_IFQPR  0x0040
+#define I2O_OFQPR  0x0044
+
+/* accessable to local processor */
+#define I2O_IFHPR  0x0120
+#define I2O_IFTPR  0x0128
+#define I2O_IPHPR  0x0130
+#define I2O_IPTPR  0x0138
+#define I2O_OFHPR  0x0140
+#define I2O_OFTPR  0x0148
+#define I2O_OPHPR  0x0150
+#define I2O_OPTPR  0x0158
+#define I2O_MUCR   0x0164
+#define I2O_QBAR   0x0170
+
+#define I2O_NUM_MSG 2
+
+typedef enum _i2o_status
+{
+       I2OSUCCESS = 0,
+       I2OINVALID,
+       I2OMSGINVALID,
+       I2ODBINVALID,
+       I2OQUEINVALID,
+       I2OQUEEMPTY,
+       I2OQUEFULL,
+       I2ONOEVENT,
+} I2OSTATUS;
+
+typedef enum _queue_size
+{
+    QSIZE_4K = 0x02,
+    QSIZE_8K = 0x04,
+    QSIZE_16K = 0x08,
+    QSIZE_32K = 0x10,
+    QSIZe_64K = 0x20,
+} QUEUE_SIZE;
+
+typedef enum _location
+{
+    LOCAL = 0,     /* used by local processor to access its own on board device,
+                     local processor's eumbbar is required */
+    REMOTE,        /* used by PCI master to access the devices on its PCI device,
+                     device's pcsrbar is required */
+} LOCATION;
+
+/* door bell */
+typedef enum _i2o_in_db
+{
+  IN_DB = 1,
+  MC,         /* machine check */
+} I2O_IN_DB;
+
+/* I2O PCI configuration identification */
+typedef struct _i2o_iop
+{
+       unsigned int base_class : 8;
+       unsigned int sub_class  : 8;
+       unsigned int prg_code   : 8;
+} I2OIOP;
+
+/* I2O Outbound Message Interrupt Status Register */
+typedef struct _i2o_om_stat
+{
+       unsigned int rsvd0 : 26;
+       unsigned int opqi  : 1;
+       unsigned int rsvd1 : 1;
+       unsigned int odi   : 1;
+       unsigned int rsvd2 : 1;
+       unsigned int om1i  : 1;
+       unsigned int om0i  : 1;
+} I2OOMSTAT;
+
+/* I2O inbound Message Interrupt Status Register */
+typedef struct _i2o_im_stat
+{
+       unsigned int rsvd0 : 23;
+       unsigned int ofoi  : 1;
+       unsigned int ipoi  : 1;
+       unsigned int rsvd1 : 1;
+       unsigned int ipqi  : 1;
+       unsigned int mci   : 1;
+       unsigned int idi   : 1;
+       unsigned int rsvd2 : 1;
+       unsigned int im1i  : 1;
+       unsigned int im0i  : 1;
+} I2OIMSTAT;
+
+/**
+ Enable the interrupt associated with in/out bound msg
+
+ Inbound message interrupt generated by PCI master and serviced by local processor
+ local processor needs to enable its inbound interrupts it wants to handle (LOCAL)
+
+ Outbound message interrupt generated by local processor and serviced by PCI master
+ PCI master needs to enable the devices' outbound interrupts it wants to handle (REMOTE)
+ **/
+extern I2OSTATUS I2OMsgEnable( LOCATION,            /*  REMOTE/LOCAL   */
+                               unsigned int base,   /* pcsrbar/eumbbar */
+                               unsigned char n );   /* b'1' - msg 0
+                                                                            * b'10'- msg 1
+                                                                            * b'11'- both
+                                                                            */
+
+/**
+ Disable the interrupt associated with in/out bound msg
+
+ local processor needs to disable its inbound interrupts it is not interested (LOCAL)
+
+ PCI master needs to disable outbound interrupts of devices it is not interested (REMOTE)
+ **/
+extern I2OSTATUS I2OMsgDisable( LOCATION,          /*  REMOTE/LOCAL   */
+                                unsigned int base, /* pcsrbar/eumbbar */
+                                unsigned char n ); /* b'1' - msg 0
+                                                                           * b'10'- msg 1
+                                                                           * b'11'- both
+                                                                           */
+
+/**
+ Read the msg register either from local inbound msg 0/1,
+ or an outbound msg 0/1 of devices.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, outbound msg of the device is read.
+ Otherwise local inbound msg is read.
+ **/
+extern I2OSTATUS I2OMsgGet ( LOCATION,                 /* REMOTE/LOCAL */
+                             unsigned int base,        /*pcsrbar/eumbbar */
+                             unsigned int n,           /* 0 or 1 */
+                             unsigned int *msg );
+
+/**
+ Write to nth Msg register either on local outbound msg 0/1,
+ or aninbound msg 0/1 of devices
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, inbound msg on the device is written.
+ Otherwise local outbound msg is written.
+ **/
+extern I2OSTATUS I2OMsgPost( LOCATION,                 /* REMOTE/LOCAL */
+                                unsigned int base,        /*pcsrbar/eumbbar */
+                                unsigned int n,           /* 0 or 1 */
+                                unsigned int msg );
+
+/**
+ Enable the In/Out DoorBell Interrupt
+
+ InDoorBell interrupt is generated by PCI master and serviced by local processor
+ local processor needs to enable its inbound doorbell interrupts it wants to handle
+
+ OutDoorbell interrupt is generated by local processor and serviced by PCI master
+ PCI master needs to enable outbound doorbell interrupts of the devices it wants to handle
+ **/
+extern I2OSTATUS I2ODBEnable( LOCATION,            /*  REMOTE/LOCAL   */
+                              unsigned int base,   /* pcsrbar/eumbbar */
+                              unsigned int in_db );/* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+
+/**
+ Disable the In/Out DoorBell Interrupt
+
+ local processor needs to disable its inbound doorbell interrupts it is not interested
+
+ PCI master needs to disable outbound doorbell interrupts of devices it is not interested
+
+ **/
+extern I2OSTATUS I2ODBDisable( LOCATION,              /*  REMOTE/LOCAL   */
+                               unsigned int base,     /* pcsrbar/eumbbar */
+                               unsigned int in_db );  /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+
+/**
+ Read a local indoorbell register, or an outdoorbell of devices.
+ Reading a doorbell register, the register will be cleared.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, outdoorbell register on the device is read.
+ Otherwise local in doorbell is read
+ **/
+extern unsigned int I2ODBGet( LOCATION,             /*  REMOTE/LOCAL   */
+                              unsigned int base);   /* pcsrbar/eumbbar */
+
+/**
+ Write to a local outdoorbell register, or an indoorbell register of devices.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, in doorbell register on the device is written.
+ Otherwise local out doorbell is written
+ **/
+extern void I2ODBPost( LOCATION,                 /*  REMOTE/LOCAL   */
+                       unsigned int base,        /* pcsrbar/eumbbar */
+                       unsigned int msg );       /*   in   / out    */
+
+/**
+ Read the outbound msg unit interrupt status of devices. Reading an interrupt status register,
+ the register will be cleared.
+
+ The outbound interrupt status is AND with the outbound
+ interrupt mask. The result is returned.
+
+ PCI master must pass the pcsrbar to the function.
+ **/
+extern I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT * );
+
+/**
+ Read the inbound msg unit interrupt status. Reading an interrupt status register,
+ the register will be cleared.
+
+ The inbound interrupt status is AND with the inbound
+ interrupt mask. The result is returned.
+
+ Local process must pass its eumbbar to the function.
+**/
+extern I2OSTATUS I2OInMsgStatGet( unsigned int eumbbar, I2OIMSTAT * );
+
+/**
+ Configure the I2O FIFO, including QBAR, IFHPR/IFTPR,IPHPR/IPTPR,OFHPR/OFTPR, OPHPR/OPTPR,
+ MUCR.
+ **/
+extern I2OSTATUS I2OFIFOInit( unsigned int eumbbar,
+                                             QUEUE_SIZE,
+                                             unsigned int qba);/* queue base address that must be aligned at 1M */
+/**
+ Enable the circular queue
+ **/
+extern I2OSTATUS I2OFIFOEnable( unsigned int eumbbar );
+
+/**
+ Disable the circular queue
+ **/
+extern void I2OFIFODisable( unsigned int eumbbar );
+
+/**
+ Enable the circular queue interrupt
+ PCI master enables outbound FIFO interrupt of device
+ Device enables its inbound FIFO interrupt
+ **/
+extern void I2OFIFOIntEnable( LOCATION, unsigned int base  );
+
+/**
+ Disable the circular queue interrupt
+ PCI master disables outbound FIFO interrupt of device
+ Device disables its inbound FIFO interrupt
+ **/
+extern void I2OFIFOIntDisable( LOCATION, unsigned int base );
+
+/**
+ Enable the circular queue overflow interrupt
+ **/
+extern void I2OFIFOOverflowIntEnable( unsigned int eumbbar );
+
+/**
+ Disable the circular queue overflow interrupt
+ **/
+extern void I2OFIFOOverflowIntDisable( unsigned int eumbbar );
+
+/**
+ Allocate a free msg frame from free FIFO.
+
+ PCI Master allocates a free msg frame through inbound queue port of device(IFQPR)
+ while local processor allocates a free msg frame from outbound free queue(OFTPR)
+
+ Unless both free queues are initialized, allocating a free MF will return 0xffffffff
+ **/
+extern I2OSTATUS I2OFIFOAlloc( LOCATION,
+                                              unsigned int base,
+                                              void         **pMsg);
+/**
+ Free a used msg frame back to free queue
+ PCI Master frees a MFA through outbound queue port of device(OFQPR)
+ while local processor frees a MFA into its inbound free queue(IFHPR)
+
+ Used msg frame does not need to be recycled in the order they
+ read
+
+ This function has to be called by PCI master to initialize Inbound free queue
+ and by device to initialize Outbound free queue before I2OFIFOAlloc can be used.
+ **/
+extern I2OSTATUS I2OFIFOFree( LOCATION,
+                                         unsigned int base,
+                                         void        *pMsg );
+
+/**
+ Post a msg into FIFO
+ PCI Master posts a msg through inbound queue port of device(IFQPR)
+ while local processor post a msg into its outbound post queue(OPHPR)
+
+ The total number of msg must be less than the max size of the queue
+ Otherwise queue overflow interrupt will assert.
+ **/
+extern I2OSTATUS I2OFIFOPost( LOCATION,
+                                     unsigned int base,
+                                     void         *pMsg );
+
+/**
+ Read a msg from FIFO
+ PCI Master reads a msg through outbound queue port of device(OFQPR)
+ while local processor reads a msg from its inbound post queue(IPTPR)
+ **/
+extern I2OSTATUS I2OFIFOGet( LOCATION,
+                                         unsigned int base,
+                                                         void     **pMsg );
+
+/**
+ Get the I2O PCI configuration identification register
+ **/
+extern I2OSTATUS I2OPCIConfigGet( LOCATION,
+                                          unsigned int base,
+                                                          I2OIOP *);
+
+#endif
diff --git a/cpu/mpc824x/drivers/i2o/Makefile b/cpu/mpc824x/drivers/i2o/Makefile
new file mode 100644 (file)
index 0000000..3f5ca26
--- /dev/null
@@ -0,0 +1,84 @@
+##########################################################################
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and
+#       distribute the SOFTWARE so long as this entire notice is retained
+#       without alteration in any modified and/or redistributed versions,
+#       and that such modified versions are clearly identified as such.
+#       No licenses are granted by implication, estoppel or otherwise under
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS.
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR
+#       INABILITY TO USE THE SOFTWARE.
+#
+############################################################################
+TARGET = libi2o.a
+
+#DEBUG  = -g
+DEBUG   =
+LST     = -Hanno -S
+OPTIM   =
+CC      = /risc/tools/pkgs/metaware/bin/hcppc
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG  = -l -fm
+AS      = /risc/tools/pkgs/metaware/bin/asppc
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -Qn -q -r
+LKCMD    =
+LINK    =  /risc/tools/pkgs/metaware/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = i2o1.o i2o2.o
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+objects: i2o1.o
+
+clean:
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+
+.s.o:
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+i2o1.o: i2o.h i2o1.c
+
+i2o2.o: i2o.h i2o2.s
diff --git a/cpu/mpc824x/drivers/i2o/Makefile_pc b/cpu/mpc824x/drivers/i2o/Makefile_pc
new file mode 100644 (file)
index 0000000..6867f58
--- /dev/null
@@ -0,0 +1,90 @@
+##########################################################################
+#
+#      makefile_pc for use with PC mksnt tools   dink32/drivers/i2o
+#
+#       Copyright Motorola, Inc. 1997
+#       ALL RIGHTS RESERVED
+#
+#       You are hereby granted a copyright license to use, modify, and
+#       distribute the SOFTWARE so long as this entire notice is retained
+#       without alteration in any modified and/or redistributed versions,
+#       and that such modified versions are clearly identified as such.
+#       No licenses are granted by implication, estoppel or otherwise under
+#       any patents or trademarks of Motorola, Inc.
+#
+#       The SOFTWARE is provided on an "AS IS" basis and without warranty.
+#       To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS
+#       ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED
+#       WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+#       PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH
+#       REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS
+#       THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS.
+#
+#       To the maximum extent permitted by applicable law, IN NO EVENT SHALL
+#       MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER
+#       (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
+#       BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
+#       INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR
+#       INABILITY TO USE THE SOFTWARE.
+#
+############################################################################
+TARGET = libi2o.a
+
+#DEBUG  = -g
+DEBUG   =
+LST     = -Hanno -S
+OPTIM   =
+CC      = m:/old_tools/tools/hcppc/bin/hcppc
+CFLAGS  = -Hnocopyr -c -Hsds -Hon=Char_default_unsigned -Hon=Char_is_rep -I../inc -I/risc/tools/pkgs/metaware/inc
+CCobj   = $(CC) $(CFLAGS) $(DEBUG) $(OPTIM)
+PREP    = $(CC) $(CFLAGS) -P
+
+# Assembler used to build the .s files (for the board version)
+
+ASOPT   = -big_si -c
+ASDEBUG  = -l -fm
+AS      = m:/old_tools/tools/hcppc/bin/asppc
+
+# Linker to bring .o files together into an executable.
+
+LKOPT  =  -Bbase=0 -Qn -q -r
+LKCMD    =
+LINK    = m:/old_tools/tools/hcppc/bin/ldppc $(LKCMD) $(LKOPT)
+
+# DOS Utilities
+
+DEL     = rm
+COPY    = cp
+LIST    = ls
+
+OBJECTS = i2o1.o i2o2.o
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(LINK) $(OBJECTS) -o $@
+
+objects: i2o1.o
+
+clean:
+       $(DEL) -f *.o *.i *.map *.lst $(TARGET) $(OBJECTS)
+
+.s.o:
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
+#      $(AS) $(ASOPT) $(ASDEBUG) $*.i > $*.lst
+
+.c.o:
+       $(CCobj) $<
+
+.c.s:
+       $(CCobj) $(LST) $<
+
+i2o1.o: i2o.h i2o1.c
+       $(CCobj) $<
+
+i2o2.o: i2o.h i2o2.s
+       $(DEL) -f $*.i
+       $(PREP) -Hasmcpp $<
+       $(AS) $(ASOPT) $*.i
diff --git a/cpu/mpc824x/drivers/i2o/i2o.h b/cpu/mpc824x/drivers/i2o/i2o.h
new file mode 100644 (file)
index 0000000..26f7c5c
--- /dev/null
@@ -0,0 +1,345 @@
+#ifndef I2O_H
+#define I2O_H
+/*********************************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ *********************************************************/
+
+#define I2O_REG_OFFSET 0x0004
+
+#define PCI_CFG_CLA    0x0B
+#define PCI_CFG_SCL    0x0A
+#define PCI_CFG_PIC    0x09
+
+#define I2O_IMR0 0x0050
+#define I2O_IMR1 0x0054
+#define I2O_OMR0 0x0058
+#define I2O_OMR1 0x005C
+
+#define I2O_ODBR 0x0060
+#define I2O_IDBR 0x0068
+
+#define I2O_OMISR  0x0030
+#define I2O_OMIMR  0x0034
+#define I2O_IMISR  0x0100
+#define I2O_IMIMR  0x0104
+
+/* accessable to PCI master but local processor */
+#define I2O_IFQPR  0x0040
+#define I2O_OFQPR  0x0044
+
+/* accessable to local processor */
+#define I2O_IFHPR  0x0120
+#define I2O_IFTPR  0x0128
+#define I2O_IPHPR  0x0130
+#define I2O_IPTPR  0x0138
+#define I2O_OFHPR  0x0140
+#define I2O_OFTPR  0x0148
+#define I2O_OPHPR  0x0150
+#define I2O_OPTPR  0x0158
+#define I2O_MUCR   0x0164
+#define I2O_QBAR   0x0170
+
+#define I2O_NUM_MSG 2
+
+typedef enum _i2o_status
+{
+       I2OSUCCESS = 0,
+       I2OINVALID,
+       I2OMSGINVALID,
+       I2ODBINVALID,
+       I2OQUEINVALID,
+       I2OQUEEMPTY,
+       I2OQUEFULL,
+       I2ONOEVENT,
+} I2OSTATUS;
+
+typedef enum _queue_size
+{
+    QSIZE_4K = 0x02,
+    QSIZE_8K = 0x04,
+    QSIZE_16K = 0x08,
+    QSIZE_32K = 0x10,
+    QSIZe_64K = 0x20,
+} QUEUE_SIZE;
+
+typedef enum _location
+{
+    LOCAL = 0,     /* used by local processor to access its own on board device,
+                     local processor's eumbbar is required */
+    REMOTE,        /* used by PCI master to access the devices on its PCI device,
+                     device's pcsrbar is required */
+} LOCATION;
+
+/* door bell */
+typedef enum _i2o_in_db
+{
+  IN_DB = 1,
+  MC,         /* machine check */
+} I2O_IN_DB;
+
+/* I2O PCI configuration identification */
+typedef struct _i2o_iop
+{
+       unsigned int base_class : 8;
+       unsigned int sub_class  : 8;
+       unsigned int prg_code   : 8;
+} I2OIOP;
+
+/* I2O Outbound Message Interrupt Status Register */
+typedef struct _i2o_om_stat
+{
+       unsigned int rsvd0 : 26;
+       unsigned int opqi  : 1;
+       unsigned int rsvd1 : 1;
+       unsigned int odi   : 1;
+       unsigned int rsvd2 : 1;
+       unsigned int om1i  : 1;
+       unsigned int om0i  : 1;
+} I2OOMSTAT;
+
+/* I2O inbound Message Interrupt Status Register */
+typedef struct _i2o_im_stat
+{
+       unsigned int rsvd0 : 23;
+       unsigned int ofoi  : 1;
+       unsigned int ipoi  : 1;
+       unsigned int rsvd1 : 1;
+       unsigned int ipqi  : 1;
+       unsigned int mci   : 1;
+       unsigned int idi   : 1;
+       unsigned int rsvd2 : 1;
+       unsigned int im1i  : 1;
+       unsigned int im0i  : 1;
+} I2OIMSTAT;
+
+/**
+ Enable the interrupt associated with in/out bound msg
+
+ Inbound message interrupt generated by PCI master and serviced by local processor
+ local processor needs to enable its inbound interrupts it wants to handle (LOCAL)
+
+ Outbound message interrupt generated by local processor and serviced by PCI master
+ PCI master needs to enable the devices' outbound interrupts it wants to handle (REMOTE)
+ **/
+extern I2OSTATUS I2OMsgEnable( LOCATION,            /*  REMOTE/LOCAL   */
+                               unsigned int base,   /* pcsrbar/eumbbar */
+                               unsigned char n );   /* b'1' - msg 0
+                                                                            * b'10'- msg 1
+                                                                            * b'11'- both
+                                                                            */
+
+/**
+ Disable the interrupt associated with in/out bound msg
+
+ local processor needs to disable its inbound interrupts it is not interested (LOCAL)
+
+ PCI master needs to disable outbound interrupts of devices it is not interested (REMOTE)
+ **/
+extern I2OSTATUS I2OMsgDisable( LOCATION,          /*  REMOTE/LOCAL   */
+                                unsigned int base, /* pcsrbar/eumbbar */
+                                unsigned char n ); /* b'1' - msg 0
+                                                                           * b'10'- msg 1
+                                                                           * b'11'- both
+                                                                           */
+
+/**
+ Read the msg register either from local inbound msg 0/1,
+ or an outbound msg 0/1 of devices.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, outbound msg of the device is read.
+ Otherwise local inbound msg is read.
+ **/
+extern I2OSTATUS I2OMsgGet ( LOCATION,                 /* REMOTE/LOCAL */
+                             unsigned int base,        /*pcsrbar/eumbbar */
+                             unsigned int n,           /* 0 or 1 */
+                             unsigned int *msg );
+
+/**
+ Write to nth Msg register either on local outbound msg 0/1,
+ or aninbound msg 0/1 of devices
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, inbound msg on the device is written.
+ Otherwise local outbound msg is written.
+ **/
+extern I2OSTATUS I2OMsgPost( LOCATION,                 /* REMOTE/LOCAL */
+                                unsigned int base,        /*pcsrbar/eumbbar */
+                                unsigned int n,           /* 0 or 1 */
+                                unsigned int msg );
+
+/**
+ Enable the In/Out DoorBell Interrupt
+
+ InDoorBell interrupt is generated by PCI master and serviced by local processor
+ local processor needs to enable its inbound doorbell interrupts it wants to handle
+
+ OutDoorbell interrupt is generated by local processor and serviced by PCI master
+ PCI master needs to enable outbound doorbell interrupts of the devices it wants to handle
+ **/
+extern I2OSTATUS I2ODBEnable( LOCATION,            /*  REMOTE/LOCAL   */
+                              unsigned int base,   /* pcsrbar/eumbbar */
+                              unsigned int in_db );/* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+
+/**
+ Disable the In/Out DoorBell Interrupt
+
+ local processor needs to disable its inbound doorbell interrupts it is not interested
+
+ PCI master needs to disable outbound doorbell interrupts of devices it is not interested
+
+ **/
+extern I2OSTATUS I2ODBDisable( LOCATION,              /*  REMOTE/LOCAL   */
+                               unsigned int base,     /* pcsrbar/eumbbar */
+                               unsigned int in_db );  /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+
+/**
+ Read a local indoorbell register, or an outdoorbell of devices.
+ Reading a doorbell register, the register will be cleared.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, outdoorbell register on the device is read.
+ Otherwise local in doorbell is read
+ **/
+extern unsigned int I2ODBGet( LOCATION,             /*  REMOTE/LOCAL   */
+                              unsigned int base);   /* pcsrbar/eumbbar */
+
+/**
+ Write to a local outdoorbell register, or an indoorbell register of devices.
+
+ If it is not local, pcsrbar must be passed to the function.
+ Otherwise eumbbar is passed.
+
+ If it is remote, in doorbell register on the device is written.
+ Otherwise local out doorbell is written
+ **/
+extern void I2ODBPost( LOCATION,                 /*  REMOTE/LOCAL   */
+                       unsigned int base,        /* pcsrbar/eumbbar */
+                       unsigned int msg );       /*   in   / out    */
+
+/**
+ Read the outbound msg unit interrupt status of devices. Reading an interrupt status register,
+ the register will be cleared.
+
+ The outbound interrupt status is AND with the outbound
+ interrupt mask. The result is returned.
+
+ PCI master must pass the pcsrbar to the function.
+ **/
+extern I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT * );
+
+/**
+ Read the inbound msg unit interrupt status. Reading an interrupt status register,
+ the register will be cleared.
+
+ The inbound interrupt status is AND with the inbound
+ interrupt mask. The result is returned.
+
+ Local process must pass its eumbbar to the function.
+**/
+extern I2OSTATUS I2OInMsgStatGet( unsigned int eumbbar, I2OIMSTAT * );
+
+/**
+ Configure the I2O FIFO, including QBAR, IFHPR/IFTPR,IPHPR/IPTPR,OFHPR/OFTPR, OPHPR/OPTPR,
+ MUCR.
+ **/
+extern I2OSTATUS I2OFIFOInit( unsigned int eumbbar,
+                                             QUEUE_SIZE,
+                                             unsigned int qba);/* queue base address that must be aligned at 1M */
+/**
+ Enable the circular queue
+ **/
+extern I2OSTATUS I2OFIFOEnable( unsigned int eumbbar );
+
+/**
+ Disable the circular queue
+ **/
+extern void I2OFIFODisable( unsigned int eumbbar );
+
+/**
+ Enable the circular queue interrupt
+ PCI master enables outbound FIFO interrupt of device
+ Device enables its inbound FIFO interrupt
+ **/
+extern void I2OFIFOIntEnable( LOCATION, unsigned int base  );
+
+/**
+ Disable the circular queue interrupt
+ PCI master disables outbound FIFO interrupt of device
+ Device disables its inbound FIFO interrupt
+ **/
+extern void I2OFIFOIntDisable( LOCATION, unsigned int base );
+
+/**
+ Enable the circular queue overflow interrupt
+ **/
+extern void I2OFIFOOverflowIntEnable( unsigned int eumbbar );
+
+/**
+ Disable the circular queue overflow interrupt
+ **/
+extern void I2OFIFOOverflowIntDisable( unsigned int eumbbar );
+
+/**
+ Allocate a free msg frame from free FIFO.
+
+ PCI Master allocates a free msg frame through inbound queue port of device(IFQPR)
+ while local processor allocates a free msg frame from outbound free queue(OFTPR)
+
+ Unless both free queues are initialized, allocating a free MF will return 0xffffffff
+ **/
+extern I2OSTATUS I2OFIFOAlloc( LOCATION,
+                                              unsigned int base,
+                                              void         **pMsg);
+/**
+ Free a used msg frame back to free queue
+ PCI Master frees a MFA through outbound queue port of device(OFQPR)
+ while local processor frees a MFA into its inbound free queue(IFHPR)
+
+ Used msg frame does not need to be recycled in the order they
+ read
+
+ This function has to be called by PCI master to initialize Inbound free queue
+ and by device to initialize Outbound free queue before I2OFIFOAlloc can be used.
+ **/
+extern I2OSTATUS I2OFIFOFree( LOCATION,
+                                         unsigned int base,
+                                         void        *pMsg );
+
+/**
+ Post a msg into FIFO
+ PCI Master posts a msg through inbound queue port of device(IFQPR)
+ while local processor post a msg into its outbound post queue(OPHPR)
+
+ The total number of msg must be less than the max size of the queue
+ Otherwise queue overflow interrupt will assert.
+ **/
+extern I2OSTATUS I2OFIFOPost( LOCATION,
+                                     unsigned int base,
+                                     void         *pMsg );
+
+/**
+ Read a msg from FIFO
+ PCI Master reads a msg through outbound queue port of device(OFQPR)
+ while local processor reads a msg from its inbound post queue(IPTPR)
+ **/
+extern I2OSTATUS I2OFIFOGet( LOCATION,
+                                         unsigned int base,
+                                                         void     **pMsg );
+
+/**
+ Get the I2O PCI configuration identification register
+ **/
+extern I2OSTATUS I2OPCIConfigGet( LOCATION,
+                                          unsigned int base,
+                                                          I2OIOP *);
+
+#endif
diff --git a/cpu/mpc824x/drivers/i2o/i2o1.c b/cpu/mpc824x/drivers/i2o/i2o1.c
new file mode 100644 (file)
index 0000000..d840af0
--- /dev/null
@@ -0,0 +1,890 @@
+/*********************************************************
+ * $Id
+ *
+ * copyright @ Motorola, 1999
+ *********************************************************/
+#include "i2o.h"
+
+extern unsigned int load_runtime_reg( unsigned int eumbbar, unsigned int reg );
+#pragma Alias( load_runtime_reg, "load_runtime_reg" );
+
+extern void store_runtime_reg( unsigned int eumbbar, unsigned int reg, unsigned int val );
+#pragma Alias( store_runtime_reg, "store_runtime_reg" );
+
+typedef struct _fifo_stat
+{
+    QUEUE_SIZE   qsz;
+    unsigned int qba;
+} FIFOSTAT;
+
+FIFOSTAT fifo_stat = { QSIZE_4K, 0xffffffff };
+
+/**********************************************************************************
+ * function: I2OMsgEnable
+ *
+ * description: Enable the interrupt associated with in/out bound msg
+ *              return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
+ *
+ *              All previously enabled interrupts are preserved.
+ * note:
+ * Inbound message interrupt generated by PCI master and serviced by local processor
+ * Outbound message interrupt generated by local processor and serviced by PCI master
+ *
+ * local processor needs to enable its inbound interrupts it wants to handle(LOCAL)
+ * PCI master needs to enable the outbound interrupts of devices it wants to handle(REMOTE)
+ ************************************************************************************/
+I2OSTATUS I2OMsgEnable ( LOCATION loc,        /*  REMOTE/LOCAL   */
+                         unsigned int base,   /* pcsrbar/eumbbar */
+                         unsigned char n )    /* b'1' - msg 0
+                                              * b'10'- msg 1
+                                              * b'11'- both
+                                              */
+{
+    unsigned int reg, val;
+    if ( ( n & 0x3 ) == 0 )
+    {
+       /* neither msg 0, nor msg 1 */
+       return I2OMSGINVALID;
+    }
+
+    n = (~n) & 0x3;
+    /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base
+     *            LOCAL  : enable local inbound message, eumbbar as base
+     */
+    reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
+    val = load_runtime_reg( base, reg );
+
+    val &= 0xfffffffc; /* masked out the msg interrupt bits */
+    val |= n;          /* LSB are the one we want */
+    store_runtime_reg( base, reg, val );
+
+    return I2OSUCCESS;
+}
+
+/*********************************************************************************
+ * function: I2OMsgDisable
+ *
+ * description: Disable the interrupt associated with in/out bound msg
+ *              Other previously enabled interrupts are preserved.
+ *              return I2OSUCCESS if no error otherwise return I2OMSGINVALID
+ *
+ * note:
+ *  local processor needs to disable its inbound interrupts it is not interested(LOCAL)
+ *  PCI master needs to disable outbound interrupts of devices it is not interested(REMOTE)
+ *********************************************************************************/
+I2OSTATUS I2OMsgDisable( LOCATION loc,      /*  REMOTE/LOCAL   */
+                         unsigned int base, /* pcsrbar/eumbbar */
+                         unsigned char n )  /* b'1' - msg 0
+                                            * b'10'- msg 1
+                                            * b'11'- both
+                                            */
+{
+    unsigned int reg, val;
+
+    if ( ( n & 0x3 ) == 0 )
+    {
+       /* neither msg 0, nor msg 1 */
+       return I2OMSGINVALID;
+    }
+
+    /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base
+     *            LOCAL  : disable local inbound message interrupt, eumbbar as base
+     */
+    reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
+    val = load_runtime_reg( base, reg );
+
+    val &= 0xfffffffc; /* masked out the msg interrupt bits */
+    val |= ( n & 0x3 );
+    store_runtime_reg( base, reg, val );
+
+    return I2OSUCCESS;
+
+}
+
+/**************************************************************************
+ * function: I2OMsgGet
+ *
+ * description: Local processor reads the nth Msg register from its inbound msg,
+ *              or a PCI Master reads nth outbound msg from device
+ *
+ *              return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
+ *
+ * note:
+ * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed.
+ * If it is remote, outbound msg on the device is read; otherwise local inbound msg is read
+ *************************************************************************/
+I2OSTATUS I2OMsgGet ( LOCATION loc,             /* REMOTE/LOCAL */
+                         unsigned int base,        /*pcsrbar/eumbbar */
+                         unsigned int n,           /* 0 or 1 */
+                         unsigned int *msg )
+{
+    if ( n >= I2O_NUM_MSG || msg == 0 )
+    {
+       return I2OMSGINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* read the outbound msg of the device, pcsrbar as base */
+       *msg = load_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET );
+    }
+    else
+    {
+       /* read the inbound msg sent by PCI master, eumbbar as base */
+       *msg = load_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET );
+    }
+
+    return I2OSUCCESS;
+}
+
+/***************************************************************
+ * function: I2OMsgPost
+ *
+ * description: Kahlua  writes to its nth outbound msg register
+ *              PCI master writes to nth inbound msg register of device
+ *
+ *              return I2OSUCCESS if no error, otherwise return I2OMSGINVALID.
+ *
+ * note:
+ * If it is not local, pcsrbar must be passed to the function. Otherwise eumbbar is passed.
+ *
+ * If it is remote, inbound msg on the device is written; otherwise local outbound msg is written
+ ***************************************************************/
+I2OSTATUS I2OMsgPost( LOCATION loc,             /* REMOTE/LOCAL */
+                      unsigned int base,        /*pcsrbar/eumbbar */
+                      unsigned int n,           /* 0 or 1 */
+                      unsigned int msg )
+{
+    if ( n >= I2O_NUM_MSG )
+    {
+       return I2OMSGINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* write to the inbound msg register of the device, pcsrbar as base  */
+       store_runtime_reg( base, I2O_IMR0+n*I2O_REG_OFFSET, msg );
+    }
+    else
+    {
+       /* write to the outbound msg register for PCI master to read, eumbbar as base */
+       store_runtime_reg( base, I2O_OMR0+n*I2O_REG_OFFSET, msg );
+    }
+
+    return I2OSUCCESS;
+}
+
+/***********************************************************************
+ * function: I2ODBEnable
+ *
+ * description: Local processor enables it's inbound doorbell interrupt
+ *              PCI master enables outbound doorbell interrupt of devices
+ *              Other previously enabled interrupts are preserved.
+ *              Return I2OSUCCESS if no error otherwise return I2ODBINVALID
+ *
+ * note:
+ * In DoorBell interrupt is generated by PCI master and serviced by local processor
+ * Out Doorbell interrupt is generated by local processor and serviced by PCI master
+ *
+ * Out Doorbell interrupt is generated by local processor and serviced by PCI master
+ * PCI master needs to enable the outbound doorbell interrupts of device it wants to handle
+ **********************************************************************/
+I2OSTATUS I2ODBEnable( LOCATION loc,        /*  REMOTE/LOCAL   */
+                  unsigned int base,   /* pcsrbar/eumbbar */
+                  unsigned int in_db ) /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+{
+
+    /* LOCATION - REMOTE : PCI master initializes outbound doorbell message of device
+     *            LOCAL  : Kahlua initializes its inbound doorbell message
+     */
+    unsigned int val;
+
+    if ( loc == LOCAL && ( in_db & 0x3 ) == 0 )
+    {
+       return I2ODBINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is base */
+       val = load_runtime_reg( base, I2O_OMIMR );
+       val &= 0xfffffff7;
+        store_runtime_reg( base, I2O_OMIMR , val );
+    }
+    else
+    {
+       /* eumbbar is base */
+       val = load_runtime_reg( base, I2O_IMIMR);
+        in_db = ( (~in_db) & 0x3 ) << 3;
+        val = ( val & 0xffffffe7) | in_db;
+        store_runtime_reg( base,  I2O_IMIMR, val );
+    }
+
+    return I2OSUCCESS;
+}
+
+/**********************************************************************************
+ * function: I2ODBDisable
+ *
+ * description: local processor disables its inbound DoorBell Interrupt
+ *              PCI master disables outbound DoorBell interrupt of device
+ *              Other previously enabled interrupts are preserved.
+ *              return I2OSUCCESS if no error.Otherwise return I2ODBINVALID
+ *
+ * note:
+ * local processor needs to disable its inbound doorbell interrupts it is not interested
+ *
+ * PCI master needs to disable outbound doorbell interrupts of device it is not interested
+ ************************************************************************************/
+I2OSTATUS I2ODBDisable( LOCATION loc,          /*  REMOTE/LOCAL   */
+                        unsigned int base,     /* pcsrbar/eumbbar */
+                        unsigned int in_db )   /* when LOCAL, I2O_IN_DB, MC, I2O_IN_DB|MC */
+{
+    /* LOCATION - REMOTE : handle device's out bound message initialization
+     *            LOCAL  : handle local in bound message initialization
+     */
+    unsigned int val;
+
+    if ( loc == LOCAL && ( in_db & 0x3 ) == 0 )
+    {
+           return I2ODBINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base */
+       val = load_runtime_reg( base, I2O_OMIMR );
+       val |= 0x8;
+        store_runtime_reg( base, I2O_OMIMR, val );
+    }
+    else
+    {
+           val = load_runtime_reg( base, I2O_IMIMR);
+            in_db = ( in_db & 0x3 ) << 3;
+            val |= in_db;
+            store_runtime_reg( base, I2O_IMIMR, val );
+    }
+
+    return I2OSUCCESS;
+}
+
+/**********************************************************************************
+ * function: I2ODBGet
+ *
+ * description: Local processor reads its in doorbell register,
+ *              PCI master reads the outdoorbell register of device.
+ *              After a doorbell register is read, the whole register will be cleared.
+ *              Otherwise, HW keeps generating interrupt.
+ *
+ * note:
+ * If it is not local, pcsrbar must be passed to the function.
+ * Otherwise eumbbar is passed.
+ *
+ * If it is remote, out doorbell register on the device is read.
+ * Otherwise local in doorbell is read
+ *
+ * If the register is not cleared by write to it, any remaining bit of b'1's
+ * will cause interrupt pending.
+ *********************************************************************************/
+unsigned int I2ODBGet( LOCATION loc,         /*  REMOTE/LOCAL   */
+                       unsigned int base)    /* pcsrbar/eumbbar */
+{
+    unsigned int msg, val;
+
+    if ( loc == REMOTE )
+    {
+       /* read outbound doorbell register of device, pcsrbar is the base */
+        val = load_runtime_reg( base, I2O_ODBR );
+        msg = val & 0xe0000000;
+        store_runtime_reg( base, I2O_ODBR, val ); /* clear the register */
+    }
+    else
+    {
+       /* read the inbound doorbell register, eumbbar is the base */
+        val = load_runtime_reg( base, I2O_IDBR );
+        store_runtime_reg( base, I2O_IDBR, val ); /* clear the register */
+       msg = val;
+    }
+
+    return msg;
+}
+
+/**********************************************************************
+ * function: I2ODBPost
+ *
+ * description: local processor writes to a outbound doorbell register,
+ *              PCI master writes to the inbound doorbell register of device
+ *
+ * note:
+ * If it is not local, pcsrbar must be passed to the function.
+ * Otherwise eumbbar is passed.
+ *
+ * If it is remote, in doorbell register on the device is written.
+ * Otherwise local out doorbell is written
+ *********************************************************************/
+void I2ODBPost( LOCATION loc,             /*  REMOTE/LOCAL   */
+                unsigned int base,        /* pcsrbar/eumbbar */
+                unsigned int msg )        /*   in   / out    */
+{
+    if ( loc == REMOTE )
+    {
+       /* write to inbound doorbell register of device, pcsrbar is the base */
+       store_runtime_reg( base, I2O_IDBR, msg );
+    }
+    else
+    {
+       /* write to local outbound doorbell register, eumbbar is the base */
+       store_runtime_reg( base, I2O_ODBR, msg & 0x1fffffff );
+    }
+
+}
+
+/********************************************************************
+ * function: I2OOutMsgStatGet
+ *
+ * description: PCI master reads device's outbound msg unit interrupt status.
+ *              Reading an interrupt status register,
+ *              the register will be cleared.
+ *
+ *              The value of the status register is AND with the outbound
+ *              interrupt mask and result is returned.
+ *
+ * note:
+ * pcsrbar must be passed to the function.
+ ********************************************************************/
+I2OSTATUS I2OOutMsgStatGet( unsigned int pcsrbar, I2OOMSTAT *val )
+{
+    unsigned int stat;
+    unsigned int mask;
+
+    if ( val == 0 )
+    {
+           return I2OINVALID;
+    }
+
+    /* read device's outbound status */
+    stat = load_runtime_reg( pcsrbar, I2O_OMISR );
+    mask = load_runtime_reg( pcsrbar, I2O_OMIMR );
+    store_runtime_reg( pcsrbar, I2O_OMISR, stat & 0xffffffd7);
+
+    stat &= mask;
+    val->rsvd0 = ( stat & 0xffffffc0 ) >> 6;
+    val->opqi  = ( stat & 0x00000020 ) >> 5;
+    val->rsvd1 = ( stat & 0x00000010 ) >> 4;
+    val->odi   = ( stat & 0x00000008 ) >> 3;
+    val->rsvd2 = ( stat & 0x00000004 ) >> 2;
+    val->om1i  = ( stat & 0x00000002 ) >> 1;
+    val->om0i  = ( stat & 0x00000001 );
+
+    return I2OSUCCESS;
+}
+
+/********************************************************************
+ * function: I2OInMsgStatGet
+ *
+ * description: Local processor reads its inbound msg unit interrupt status.
+ *              Reading an interrupt status register,
+ *              the register will be cleared.
+ *
+ *              The inbound msg interrupt status is AND with the inbound
+ *              msg interrupt mask and result is returned.
+ *
+ * note:
+ * eumbbar must be passed to the function.
+ ********************************************************************/
+I2OSTATUS I2OInMsgStatGet(unsigned int eumbbar, I2OIMSTAT *val)
+{
+    unsigned int stat;
+    unsigned int mask;
+
+    if ( val == 0 )
+    {
+           return I2OINVALID;
+    }
+
+    /* read device's outbound status */
+    stat = load_runtime_reg( eumbbar, I2O_OMISR );
+    mask = load_runtime_reg( eumbbar, I2O_OMIMR );
+    store_runtime_reg( eumbbar, I2O_OMISR, stat & 0xffffffe7 );
+
+    stat &= mask;
+    val->rsvd0 = ( stat & 0xfffffe00 ) >> 9;
+    val->ofoi  = ( stat & 0x00000100 ) >> 8;
+    val->ipoi  = ( stat & 0x00000080 ) >> 7;
+    val->rsvd1 = ( stat & 0x00000040 ) >> 6;
+    val->ipqi  = ( stat & 0x00000020 ) >> 5;
+    val->mci   = ( stat & 0x00000010 ) >> 4;
+    val->idi   = ( stat & 0x00000008 ) >> 3;
+    val->rsvd2 = ( stat & 0x00000004 ) >> 2;
+    val->im1i  = ( stat & 0x00000002 ) >> 1;
+    val->im0i  = ( stat & 0x00000001 );
+
+    return I2OSUCCESS;
+
+}
+
+/***********************************************************
+ * function: I2OFIFOInit
+ *
+ * description: Configure the I2O FIFO, including QBAR,
+ *              IFHPR/IFTPR, IPHPR/IPTPR, OFHPR/OFTPR,
+ *              OPHPR/OPTPR, MUCR.
+ *
+ *              return I2OSUCCESS if no error,
+ *              otherwise return I2OQUEINVALID
+ *
+ * note: It is NOT this driver's responsibility of initializing
+ *       MFA blocks, i.e., FIFO queue itself. The MFA blocks
+ *       must be initialized before I2O unit can be used.
+ ***********************************************************/
+I2OSTATUS I2OFIFOInit( unsigned int eumbbar,
+                      QUEUE_SIZE   sz,      /* value of CQS of MUCR */
+                      unsigned int qba)     /* queue base address that must be aligned at 1M */
+{
+
+    if ( ( qba & 0xfffff ) != 0 )
+    {
+       /* QBA must be aligned at 1Mbyte boundary */
+       return I2OQUEINVALID;
+    }
+
+    store_runtime_reg( eumbbar, I2O_QBAR, qba );
+    store_runtime_reg( eumbbar, I2O_MUCR, (unsigned int)sz );
+    store_runtime_reg( eumbbar, I2O_IFHPR, qba );
+    store_runtime_reg( eumbbar, I2O_IFTPR, qba );
+    store_runtime_reg( eumbbar, I2O_IPHPR, qba + 1 * ( sz << 11 ));
+    store_runtime_reg( eumbbar, I2O_IPTPR, qba + 1 * ( sz << 11 ));
+    store_runtime_reg( eumbbar, I2O_OFHPR, qba + 2 * ( sz << 11 ));
+    store_runtime_reg( eumbbar, I2O_OFTPR, qba + 2 * ( sz << 11 ));
+    store_runtime_reg( eumbbar, I2O_OPHPR, qba + 3 * ( sz << 11 ));
+    store_runtime_reg( eumbbar, I2O_OPTPR, qba + 3 * ( sz << 11 ));
+
+    fifo_stat.qsz = sz;
+    fifo_stat.qba = qba;
+
+    return I2OSUCCESS;
+}
+
+/**************************************************
+ * function: I2OFIFOEnable
+ *
+ * description: Enable the circular queue
+ *              return I2OSUCCESS if no error.
+ *              Otherwise I2OQUEINVALID is returned.
+ *
+ * note:
+ *************************************************/
+I2OSTATUS I2OFIFOEnable( unsigned int eumbbar )
+{
+    unsigned int val;
+
+    if ( fifo_stat.qba == 0xfffffff )
+    {
+       return I2OQUEINVALID;
+    }
+
+    val = load_runtime_reg( eumbbar, I2O_MUCR );
+    store_runtime_reg( eumbbar, I2O_MUCR, val | 0x1 );
+
+    return I2OSUCCESS;
+}
+
+/**************************************************
+ * function: I2OFIFODisable
+ *
+ * description: Disable the circular queue
+ *
+ * note:
+ *************************************************/
+void I2OFIFODisable( unsigned int eumbbar )
+{
+    if ( fifo_stat.qba == 0xffffffff )
+    {
+       /* not enabled */
+       return;
+    }
+
+    unsigned int val = load_runtime_reg( eumbbar, I2O_MUCR );
+    store_runtime_reg( eumbbar, I2O_MUCR, val & 0xfffffffe );
+}
+
+/****************************************************
+ * function: I2OFIFOAlloc
+ *
+ * description: Allocate a free MFA from free FIFO.
+ *              return I2OSUCCESS if no error.
+ *              return I2OQUEEMPTY if no more free MFA.
+ *              return I2OINVALID on other errors.
+ *
+ *              A free MFA must be allocated before a
+ *              message can be posted.
+ *
+ * note:
+ * PCI Master allocates a free MFA from inbound queue of device
+ * (pcsrbar is the base,) through the inbound queue port of device
+ * while local processor allocates a free MFA from its outbound
+ * queue (eumbbar is the base.)
+ *
+ ****************************************************/
+I2OSTATUS I2OFIFOAlloc( LOCATION loc,
+                       unsigned int base,
+                       void         **pMsg )
+{
+    I2OSTATUS stat = I2OSUCCESS;
+    void *pHdr, *pTil;
+
+    if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff )
+    {
+       /* not configured */
+       return I2OQUEINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base and read the inbound free tail ptr */
+       pTil = (void *)load_runtime_reg( base, I2O_IFQPR );
+        if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF )
+        {
+           stat = I2OQUEEMPTY;
+        }
+       else
+        {
+           *pMsg = pTil;
+       }
+    }
+    else
+    {
+       /* eumbbar is the base and read the outbound free tail ptr */
+       pHdr = (void *)load_runtime_reg( base, I2O_OFHPR ); /* queue head */
+       pTil = (void *)load_runtime_reg( base, I2O_OFTPR ); /* queue tail */
+
+       /* check underflow */
+       if ( pHdr == pTil )
+       {
+           /* hdr and til point to the same fifo item, no free MFA */
+            stat = I2OQUEEMPTY;
+       }
+       else
+       {
+         /* update OFTPR */
+         *pMsg = (void *)(*(unsigned char *)pTil);
+         pTil = (void *)((unsigned int)pTil + 4);
+         if ( (unsigned int)pTil == fifo_stat.qba + ( 4 * ( fifo_stat.qsz << 11 ) ) )
+         {
+               /* reach the upper limit */
+               pTil = (void *)(fifo_stat.qba + ( 3 * (fifo_stat.qsz << 11) ));
+         }
+         store_runtime_reg( base, I2O_OFTPR, (unsigned int)pTil );
+       }
+    }
+
+    return stat;
+}
+
+/******************************************************
+ * function: I2OFIFOFree
+ *
+ * description: Free a used MFA back to free queue after
+ *              use.
+ *              return I2OSUCCESS if no error.
+ *              return I2OQUEFULL if inbound free queue
+ *              overflow
+ *
+ * note: PCI Master frees a MFA into device's outbound queue
+ *       (OFQPR) while local processor frees a MFA into its
+ *       inbound queue (IFHPR).
+ *****************************************************/
+I2OSTATUS I2OFIFOFree( LOCATION loc,
+                 unsigned int base,
+                 void *pMsg )
+{
+    void **pHdr, **pTil;
+    I2OSTATUS stat = I2OSUCCESS;
+
+    if ( fifo_stat.qba == 0xffffffff || pMsg == 0 )
+    {
+           return I2OQUEINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base */
+       store_runtime_reg( base, I2O_OFQPR, (unsigned int)pMsg );
+    }
+    else
+    {
+       /* eumbbar is the base */
+       pHdr = (void **)load_runtime_reg( base, I2O_IFHPR );
+        pTil = (void **)load_runtime_reg( base, I2O_IFTPR );
+
+       /* store MFA */
+       *pHdr = pMsg;
+
+       /* update IFHPR */
+       pHdr += 4;
+
+       if ( (unsigned int)pHdr == fifo_stat.qba + ( fifo_stat.qsz << 11 ) )
+       {
+         /* reach the upper limit */
+         pHdr = (void **)fifo_stat.qba;
+       }
+
+       /* check inbound free queue overflow */
+       if ( pHdr != pTil )
+       {
+          store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr);
+        }
+       else
+       {
+           stat = I2OQUEFULL;
+       }
+
+    }
+
+    return stat;
+
+}
+
+/*********************************************
+ * function: I2OFIFOPost
+ *
+ * description: Post a msg into FIFO post queue
+ *              the value of msg must be the one
+ *              returned by I2OFIFOAlloc
+ *
+ * note: PCI Master posts a msg into device's inbound queue
+ *       (IFQPR) while local processor post a msg into device's
+ *       outbound queue (OPHPR)
+ *********************************************/
+I2OSTATUS I2OFIFOPost( LOCATION loc,
+                      unsigned int base,
+                      void *pMsg )
+{
+    void **pHdr, **pTil;
+    I2OSTATUS stat = I2OSUCCESS;
+
+    if ( fifo_stat.qba == 0xffffffff || pMsg == 0 )
+    {
+       return I2OQUEINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base */
+       store_runtime_reg( base, I2O_IFQPR, (unsigned int)pMsg );
+    }
+    else
+    {
+       /* eumbbar is the base */
+       pHdr = (void **)load_runtime_reg( base, I2O_OPHPR );
+        pTil = (void **)load_runtime_reg( base, I2O_OPTPR );
+
+       /* store MFA */
+       *pHdr = pMsg;
+
+       /* update IFHPR */
+       pHdr += 4;
+
+       if ( (unsigned int)pHdr == fifo_stat.qba + 3 * ( fifo_stat.qsz << 11 ) )
+       {
+         /* reach the upper limit */
+         pHdr = (void **)(fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) );
+       }
+
+       /* check post queue overflow */
+       if ( pHdr != pTil )
+       {
+          store_runtime_reg( base, I2O_OPHPR, (unsigned int)pHdr);
+        }
+       else
+       {
+           stat = I2OQUEFULL;
+       }
+    }
+
+    return stat;
+}
+
+/************************************************
+ * function: I2OFIFOGet
+ *
+ * description:  Read a msg from FIFO
+ *               This function should be called
+ *               only when there is a corresponding
+ *               msg interrupt.
+ *
+ * note: PCI Master reads a msg from device's outbound queue
+ *       (OFQPR) while local processor reads a msg from device's
+ *       inbound queue (IPTPR)
+ ************************************************/
+I2OSTATUS I2OFIFOGet( LOCATION loc,
+                      unsigned int base,
+                      void **pMsg )
+{
+    I2OSTATUS stat = I2OSUCCESS;
+    void *pHdr, *pTil;
+
+    if ( pMsg == 0 || *pMsg == 0 || fifo_stat.qba == 0xffffffff )
+    {
+       /* not configured */
+       return I2OQUEINVALID;
+    }
+
+    if ( loc == REMOTE )
+    {
+       /* pcsrbar is the base */
+       pTil = (void *)load_runtime_reg( base, I2O_OFQPR );
+        if ( ( (unsigned int)pTil & 0xFFFFFFF ) == 0xFFFFFFFF )
+        {
+           stat = I2OQUEEMPTY;
+        }
+       else
+        {
+           *pMsg = pTil;
+       }
+    }
+    else
+    {
+       /* eumbbar is the base and read the outbound free tail ptr */
+       pHdr = (void *)load_runtime_reg( base, I2O_IPHPR ); /* queue head */
+       pTil = (void *)load_runtime_reg( base, I2O_IPTPR ); /* queue tail */
+
+       /* check underflow */
+       if ( pHdr == pTil )
+       {
+           /* no free MFA */
+            stat = I2OQUEEMPTY;
+       }
+       else
+       {
+         /* update OFTPR */
+         *pMsg = (void *)(*(unsigned char *)pTil);
+         pTil = (void *)((unsigned int)pTil + 4);
+         if ( (unsigned int)pTil == fifo_stat.qba + 2 * ( fifo_stat.qsz << 11 ) )
+         {
+               /* reach the upper limit */
+               pTil = (void *)(fifo_stat.qba + 1 * (fifo_stat.qsz << 11) );
+         }
+
+         store_runtime_reg( base, I2O_IPTPR, (unsigned int)pTil );
+       }
+    }
+
+    return stat;
+}
+
+/********************************************************
+ * function: I2OIOP
+ *
+ * description: Get the I2O PCI configuration identification
+ *              register.
+ *
+ * note: PCI master should pass pcsrbar while local processor
+ *       should pass eumbbar.
+ *********************************************************/
+I2OSTATUS I2OPCIConfigGet( LOCATION loc,
+                       unsigned int base,
+                       I2OIOP * val)
+{
+    unsigned int tmp;
+    if ( val == 0 )
+    {
+           return I2OINVALID;
+    }
+    tmp = load_runtime_reg( base, PCI_CFG_CLA );
+    val->base_class = ( tmp & 0xFF) << 16;
+    tmp = load_runtime_reg( base, PCI_CFG_SCL );
+    val->sub_class= ( (tmp & 0xFF) << 8 );
+    tmp = load_runtime_reg( base, PCI_CFG_PIC );
+    val->prg_code = (tmp & 0xFF);
+    return I2OSUCCESS;
+}
+
+/*********************************************************
+ * function: I2OFIFOIntEnable
+ *
+ * description: Enable the circular post queue interrupt
+ *
+ * note:
+ * PCI master enables outbound FIFO interrupt of device
+ * pscrbar is the base
+ * Device enables its inbound FIFO interrupt
+ * eumbbar is the base
+ *******************************************************/
+void I2OFIFOIntEnable( LOCATION loc, unsigned int base  )
+{
+    unsigned int reg, val;
+
+    /* LOCATION - REMOTE : enable outbound message of device, pcsrbar as base
+     *            LOCAL  : enable local inbound message, eumbbar as base
+     */
+    reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
+    val = load_runtime_reg( base, reg );
+
+    val &= 0xffffffdf; /* clear the msg interrupt bits */
+    store_runtime_reg( base, reg, val );
+
+}
+
+/****************************************************
+ * function: I2OFIFOIntDisable
+ *
+ * description: Disable the circular post queue interrupt
+ *
+ * note:
+ * PCI master disables outbound FIFO interrupt of device
+ * (pscrbar is the base)
+ * Device disables its inbound FIFO interrupt
+ * (eumbbar is the base)
+ *****************************************************/
+void I2OFIFOIntDisable( LOCATION loc, unsigned int base )
+{
+
+    /* LOCATION - REMOTE : disable outbound message interrupt of device, pcsrbar as base
+     *            LOCAL  : disable local inbound message interrupt, eumbbar as base
+     */
+    unsigned int reg = ( loc == REMOTE ? I2O_OMIMR : I2O_IMIMR );
+    unsigned int val = load_runtime_reg( base, reg );
+
+    val |= 0x00000020; /* masked out the msg interrupt bits */
+    store_runtime_reg( base, reg, val );
+
+}
+
+/*********************************************************
+ * function: I2OFIFOOverflowIntEnable
+ *
+ * description: Enable the circular queue overflow interrupt
+ *
+ * note:
+ * Device enables its inbound FIFO post overflow interrupt
+ * and outbound free overflow interrupt.
+ * eumbbar is the base
+ *******************************************************/
+void I2OFIFOOverflowIntEnable( unsigned int eumbbar  )
+{
+    unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR );
+
+    val &= 0xfffffe7f; /* clear the two overflow interrupt bits */
+    store_runtime_reg( eumbbar, I2O_IMIMR, val );
+
+}
+
+/****************************************************
+ * function: I2OFIFOOverflowIntDisable
+ *
+ * description: Disable the circular queue overflow interrupt
+ *
+ * note:
+ * Device disables its inbound post FIFO overflow interrupt
+ * and outbound free FIFO overflow interrupt
+ * (eumbbar is the base)
+ *****************************************************/
+void I2OFIFOOverflowIntDisable( unsigned int eumbbar )
+{
+
+    unsigned int val = load_runtime_reg( eumbbar, I2O_IMIMR );
+
+    val |= 0x00000180; /* masked out the msg overflow interrupt bits */
+    store_runtime_reg( eumbbar, I2O_IMIMR, val );
+}
diff --git a/cpu/mpc824x/drivers/i2o/i2o2.S b/cpu/mpc824x/drivers/i2o/i2o2.S
new file mode 100644 (file)
index 0000000..1033979
--- /dev/null
@@ -0,0 +1,48 @@
+/**************************************
+ *
+ * copyright @ Motorola, 1999
+ *
+ **************************************/
+
+/**********************************************************
+ * function: load_runtime_reg
+ *
+ * input:  r3 - value of eumbbar
+ *         r4 - register offset in embedded utility space
+ *
+ * output: r3 - register content
+ **********************************************************/
+      .text
+      .align 2
+      .global load_runtime_reg
+
+load_runtime_reg:
+
+                 xor r5,r5,r5
+          or  r5,r5,r3       /* save eumbbar */
+
+             lwbrx     r3,r4,r5
+             sync
+
+             bclr 20, 0
+
+/****************************************************************
+ * function: store_runtime_reg
+ *
+ * input: r3 - value of eumbbar
+ *        r4 - register offset in embedded utility space
+ *        r5 - new value to be stored
+ *
+ ****************************************************************/
+           .text
+           .align 2
+           .global store_runtime_reg
+store_runtime_reg:
+
+                 xor r0,r0,r0
+
+             stwbrx r5,  r4, r3
+             sync
+
+                 bclr   20,0
+