9
0
Fork 0

Merge with /home/m8/git/u-boot

This commit is contained in:
Wolfgang Denk 2006-09-09 22:53:06 +02:00
commit 98e43917dc
18 changed files with 50 additions and 3443 deletions

View File

@ -2,6 +2,14 @@
Changes since U-Boot 1.1.4:
======================================================================
* Add documentation on the latest build environment extensions to
the README file.
* Remove dead code (i2o and dma) from cpu/mpc824x/drivers/ directory.
* Fix LOG_DIR directory creation error.
Add support for automatic creation of BUILD_DIR directory.
* Fix build problem cpu/ppc4xx/ndfc.c
Patch by Stefan Roese, 07 Sep 2006
@ -49,7 +57,6 @@ Changes since U-Boot 1.1.4:
* Fix tools/easylogo build error.
* Fixed problems on PRS200 board caused by adding splash screen on MCC200
* Extended README entry on coding style

View File

@ -18,7 +18,7 @@ if [ ! "${BUILD_DIR}" ] ; then
BUILD_DIR="."
fi
[ -d ${MAKEALL_LOGDIR} ] || mkdir ${MAKEALL_LOGDIR} || exit 1
[ -d ${LOG_DIR} ] || mkdir ${LOG_DIR} || exit 1
LIST=""

View File

@ -74,6 +74,11 @@ endif
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
# Verify if it was successful.
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
endif # ifneq ($(BUILD_DIR),)

36
README
View File

@ -2323,6 +2323,26 @@ images ready for download to / installation on your system:
- "u-boot" is an image in ELF binary format
- "u-boot.srec" is in Motorola S-Record format
By default the build is performed locally and the objects are saved
in the source directory. One of the two methods can be used to change
this behavior and build U-Boot to some external directory:
1. Add O= to the make command line invocations:
make O=/tmp/build distclean
make O=/tmp/build NAME_config
make O=/tmp/build all
2. Set environment variable BUILD_DIR to point to the desired location:
export BUILD_DIR=/tmp/build
make distclean
make NAME_config
make all
Note that the command line "O=" setting overrides the BUILD_DIR environment
variable.
Please be aware that the Makefiles assume you are using GNU make, so
for instance on NetBSD you might need to use "gmake" instead of
@ -2376,6 +2396,22 @@ or to build on a native PowerPC system you can type
CROSS_COMPILE=' ' MAKEALL
When using the MAKEALL script, the default behaviour is to build U-Boot
in the source directory. This location can be changed by setting the
BUILD_DIR environment variable. Also, for each target built, the MAKEALL
script saves two log files (<target>.ERR and <target>.MAKEALL) in the
<source dir>/LOG directory. This default location can be changed by
setting the MAKEALL_LOGDIR environment variable. For example:
export BUILD_DIR=/tmp/build
export MAKEALL_LOGDIR=/tmp/log
CROSS_COMPILE=ppc_8xx- MAKEALL
With the above settings build objects are saved in the /tmp/build, log
files are saved in the /tmp/log and the source tree remains clean during
the whole build process.
See also "U-Boot Porting Guide" below.

View File

@ -1,83 +0,0 @@
##########################################################################
#
# 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

View File

@ -1,89 +0,0 @@
##########################################################################
#
# 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

View File

@ -1,100 +0,0 @@
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.

View File

@ -1,326 +0,0 @@
#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

View File

@ -1,801 +0,0 @@
/************************************************************
*
* 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;
}

View File

@ -1,42 +0,0 @@
/**************************************
*
* 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

View File

@ -1,100 +0,0 @@
#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

View File

@ -1,100 +0,0 @@
#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

View File

@ -1,344 +0,0 @@
#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

View File

@ -1,84 +0,0 @@
##########################################################################
#
# 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

View File

@ -1,90 +0,0 @@
##########################################################################
#
# 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

View File

@ -1,345 +0,0 @@
#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

View File

@ -1,890 +0,0 @@
/*********************************************************
* $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 );
}

View File

@ -1,47 +0,0 @@
/**************************************
*
* 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