summaryrefslogtreecommitdiff
path: root/cpu/mpc824x/drivers/i2o
diff options
context:
space:
mode:
authorwdenk <wdenk>2001-11-28 17:49:55 +0000
committerwdenk <wdenk>2001-11-28 17:49:55 +0000
commit327f7a020a3037ae8ef6c94488d5e9a3aa772943 (patch)
treee9cdb59ef86fef010d1133a2589577509afe7523 /cpu/mpc824x/drivers/i2o
parent12e4407c6a42284671bbcb4acceeedc00df04cb5 (diff)
downloadu-boot-imx-327f7a020a3037ae8ef6c94488d5e9a3aa772943.zip
u-boot-imx-327f7a020a3037ae8ef6c94488d5e9a3aa772943.tar.gz
u-boot-imx-327f7a020a3037ae8ef6c94488d5e9a3aa772943.tar.bz2
Initial revision
Diffstat (limited to 'cpu/mpc824x/drivers/i2o')
-rw-r--r--cpu/mpc824x/drivers/i2o/Makefile84
-rw-r--r--cpu/mpc824x/drivers/i2o/Makefile_pc90
-rw-r--r--cpu/mpc824x/drivers/i2o/i2o.h345
-rw-r--r--cpu/mpc824x/drivers/i2o/i2o1.c890
-rw-r--r--cpu/mpc824x/drivers/i2o/i2o2.S48
5 files changed, 1457 insertions, 0 deletions
diff --git a/cpu/mpc824x/drivers/i2o/Makefile b/cpu/mpc824x/drivers/i2o/Makefile
new file mode 100644
index 0000000..3f5ca26
--- /dev/null
+++ b/cpu/mpc824x/drivers/i2o/Makefile
@@ -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
index 0000000..6867f58
--- /dev/null
+++ b/cpu/mpc824x/drivers/i2o/Makefile_pc
@@ -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
index 0000000..26f7c5c
--- /dev/null
+++ b/cpu/mpc824x/drivers/i2o/i2o.h
@@ -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
index 0000000..d840af0
--- /dev/null
+++ b/cpu/mpc824x/drivers/i2o/i2o1.c
@@ -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
index 0000000..1033979
--- /dev/null
+++ b/cpu/mpc824x/drivers/i2o/i2o2.S
@@ -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
+