commit
98e43917dc
@ -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 |
@ -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 |
@ -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. |
@ -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 |
@ -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; |
||||
} |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 ); |
||||
} |
@ -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 |
Loading…
Reference in new issue