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