Sync from Fredi's source tree 13/05/2017

This commit is contained in:
David Gálvez
2018-04-09 16:26:54 +02:00
parent c1e31dcdf0
commit 030afcd535
59 changed files with 13625 additions and 1139 deletions

Binary file not shown.

View File

@@ -6,7 +6,7 @@
<targetprocessor>5474</targetprocessor>
<connection>PEMICRO_USB</connection>
<usetargetinit>true</usetargetinit>
<targetinitfile>C:\FireBee\codewarrior\firebeeV1\cfg\mem.cfg</targetinitfile>
<targetinitfile></targetinitfile>
<targetmembuffaddr>0x00000000</targetmembuffaddr>
<targetmembuffsize>0x00006000</targetmembuffsize>
<enablelogging>true</enablelogging>

362
headers/MCD_dma.h Normal file
View File

@@ -0,0 +1,362 @@
/*
* File: MCD_dma.h
* Purpose: Main header file for multi-channel DMA API.
*
* Notes:
*/
#ifndef _MCD_API_H
#define _MCD_API_H
/*
* Turn Execution Unit tasks ON (#define) or OFF (#undef)
*/
#undef MCD_INCLUDE_EU
/*
* Number of DMA channels
*/
#define NCHANNELS 16
/*
* Total number of variants
*/
#ifdef MCD_INCLUDE_EU
#define NUMOFVARIANTS 6
#else
#define NUMOFVARIANTS 4
#endif
/*
* Define sizes of the various tables
*/
#define TASK_TABLE_SIZE (NCHANNELS*32)
#define VAR_TAB_SIZE (128)
#define CONTEXT_SAVE_SIZE (128)
#define FUNCDESC_TAB_SIZE (256)
#ifdef MCD_INCLUDE_EU
#define FUNCDESC_TAB_NUM 16
#else
#define FUNCDESC_TAB_NUM 1
#endif
#ifndef DEFINESONLY
/*
* Portability typedefs
*/
typedef int s32;
typedef unsigned int u32;
typedef short s16;
typedef unsigned short u16;
typedef char s8;
typedef unsigned char u8;
/*
* These structures represent the internal registers of the
* multi-channel DMA
*/
struct dmaRegs_s {
u32 taskbar; /* task table base address register */
u32 currPtr;
u32 endPtr;
u32 varTablePtr;
u16 dma_rsvd0;
u16 ptdControl; /* ptd control */
u32 intPending; /* interrupt pending register */
u32 intMask; /* interrupt mask register */
u16 taskControl[16]; /* task control registers */
u8 priority[32]; /* priority registers */
u32 initiatorMux; /* initiator mux control */
u32 taskSize0; /* task size control register 0. */
u32 taskSize1; /* task size control register 1. */
u32 dma_rsvd1; /* reserved */
u32 dma_rsvd2; /* reserved */
u32 debugComp1; /* debug comparator 1 */
u32 debugComp2; /* debug comparator 2 */
u32 debugControl; /* debug control */
u32 debugStatus; /* debug status */
u32 ptdDebug; /* priority task decode debug */
u32 dma_rsvd3[31]; /* reserved */
};
typedef volatile struct dmaRegs_s dmaRegs;
#endif
/*
* PTD contrl reg bits
*/
#define PTD_CTL_TSK_PRI 0x8000
#define PTD_CTL_COMM_PREFETCH 0x0001
/*
* Task Control reg bits and field masks
*/
#define TASK_CTL_EN 0x8000
#define TASK_CTL_VALID 0x4000
#define TASK_CTL_ALWAYS 0x2000
#define TASK_CTL_INIT_MASK 0x1f00
#define TASK_CTL_ASTRT 0x0080
#define TASK_CTL_HIPRITSKEN 0x0040
#define TASK_CTL_HLDINITNUM 0x0020
#define TASK_CTL_ASTSKNUM_MASK 0x000f
/*
* Priority reg bits and field masks
*/
#define PRIORITY_HLD 0x80
#define PRIORITY_PRI_MASK 0x07
/*
* Debug Control reg bits and field masks
*/
#define DBG_CTL_BLOCK_TASKS_MASK 0xffff0000
#define DBG_CTL_AUTO_ARM 0x00008000
#define DBG_CTL_BREAK 0x00004000
#define DBG_CTL_COMP1_TYP_MASK 0x00003800
#define DBG_CTL_COMP2_TYP_MASK 0x00000070
#define DBG_CTL_EXT_BREAK 0x00000004
#define DBG_CTL_INT_BREAK 0x00000002
/*
* PTD Debug reg selector addresses
* This reg must be written with a value to show the contents of
* one of the desired internal register.
*/
#define PTD_DBG_REQ 0x00 /* shows the state of 31 initiators */
#define PTD_DBG_TSK_VLD_INIT 0x01 /* shows which 16 tasks are valid and
have initiators asserted */
/*
* General return values
*/
#define MCD_OK 0
#define MCD_ERROR -1
#define MCD_TABLE_UNALIGNED -2
#define MCD_CHANNEL_INVALID -3
/*
* MCD_initDma input flags
*/
#define MCD_RELOC_TASKS 0x00000001
#define MCD_NO_RELOC_TASKS 0x00000000
#define MCD_COMM_PREFETCH_EN 0x00000002 /* Commbus Prefetching - MCF547x/548x ONLY */
/*
* MCD_dmaStatus Status Values for each channel
*/
#define MCD_NO_DMA 1 /* No DMA has been requested since reset */
#define MCD_IDLE 2 /* DMA active, but the initiator is currently inactive */
#define MCD_RUNNING 3 /* DMA active, and the initiator is currently active */
#define MCD_PAUSED 4 /* DMA active but it is currently paused */
#define MCD_HALTED 5 /* the most recent DMA has been killed with MCD_killTask() */
#define MCD_DONE 6 /* the most recent DMA has completed. */
/*
* MCD_startDma parameter defines
*/
/*
* Constants for the funcDesc parameter
*/
/* Byte swapping: */
#define MCD_NO_BYTE_SWAP 0x00045670 /* to disable byte swapping. */
#define MCD_BYTE_REVERSE 0x00076540 /* to reverse the bytes of each u32 of the DMAed data. */
#define MCD_U16_REVERSE 0x00067450 /* to reverse the 16-bit halves of
each 32-bit data value being DMAed.*/
#define MCD_U16_BYTE_REVERSE 0x00054760 /* to reverse the byte halves of each
16-bit half of each 32-bit data value DMAed */
#define MCD_NO_BIT_REV 0x00000000 /* do not reverse the bits of each byte DMAed. */
#define MCD_BIT_REV 0x00088880 /* reverse the bits of each byte DMAed */
/* CRCing: */
#define MCD_CRC16 0xc0100000 /* to perform CRC-16 on DMAed data. */
#define MCD_CRCCCITT 0xc0200000 /* to perform CRC-CCITT on DMAed data. */
#define MCD_CRC32 0xc0300000 /* to perform CRC-32 on DMAed data. */
#define MCD_CSUMINET 0xc0400000 /* to perform internet checksums on DMAed data.*/
#define MCD_NO_CSUM 0xa0000000 /* to perform no checksumming. */
#define MCD_FUNC_NOEU1 (MCD_NO_BYTE_SWAP | MCD_NO_BIT_REV | MCD_NO_CSUM)
#define MCD_FUNC_NOEU2 (MCD_NO_BYTE_SWAP | MCD_NO_CSUM)
/*
* Constants for the flags parameter
*/
#define MCD_TT_FLAGS_RL 0x00000001 /* Read line */
#define MCD_TT_FLAGS_CW 0x00000002 /* Combine Writes */
#define MCD_TT_FLAGS_SP 0x00000004 /* Speculative prefetch(XLB) MCF547x/548x ONLY */
#define MCD_TT_FLAGS_MASK 0x000000ff
#define MCD_TT_FLAGS_DEF (MCD_TT_FLAGS_RL | MCD_TT_FLAGS_CW)
#define MCD_SINGLE_DMA 0x00000100 /* Unchained DMA */
#define MCD_CHAIN_DMA /* TBD */
#define MCD_EU_DMA /* TBD */
#define MCD_FECTX_DMA 0x00001000 /* FEC TX ring DMA */
#define MCD_FECRX_DMA 0x00002000 /* FEC RX ring DMA */
/* these flags are valid for MCD_startDma and the chained buffer descriptors */
#define MCD_BUF_READY 0x80000000 /* indicates that this buffer is now under the DMA's control */
#define MCD_WRAP 0x20000000 /* to tell the FEC Dmas to wrap to the first BD */
#define MCD_INTERRUPT 0x10000000 /* to generate an interrupt after completion of the DMA. */
#define MCD_END_FRAME 0x08000000 /* tell the DMA to end the frame when transferring
last byte of data in buffer */
#define MCD_CRC_RESTART 0x40000000 /* to empty out the accumulated checksum
prior to performing the DMA. */
/* Defines for the FEC buffer descriptor control/status word*/
#define MCD_FEC_BUF_READY 0x8000
#define MCD_FEC_WRAP 0x2000
#define MCD_FEC_INTERRUPT 0x1000
#define MCD_FEC_END_FRAME 0x0800
/*
* Defines for general intuitiveness
*/
#define MCD_TRUE 1
#define MCD_FALSE 0
/*
* Three different cases for destination and source.
*/
#define MINUS1 -1
#define ZERO 0
#define PLUS1 1
#ifndef DEFINESONLY
/* Task Table Entry struct*/
typedef struct {
u32 TDTstart; /* task descriptor table start */
u32 TDTend; /* task descriptor table end */
u32 varTab; /* variable table start */
u32 FDTandFlags; /* function descriptor table start and flags */
volatile u32 descAddrAndStatus;
volatile u32 modifiedVarTab;
u32 contextSaveSpace; /* context save space start */
u32 literalBases;
} TaskTableEntry;
/* Chained buffer descriptor */
typedef volatile struct MCD_bufDesc_struct MCD_bufDesc;
struct MCD_bufDesc_struct {
u32 flags; /* flags describing the DMA */
u32 csumResult; /* checksum from checksumming performed since last checksum reset */
s8 *srcAddr; /* the address to move data from */
s8 *destAddr; /* the address to move data to */
s8 *lastDestAddr; /* the last address written to */
u32 dmaSize; /* the number of bytes to transfer independent of the transfer size */
MCD_bufDesc *next; /* next buffer descriptor in chain */
u32 info; /* private information about this descriptor; DMA does not affect it */
};
/* Progress Query struct */
typedef volatile struct MCD_XferProg_struct {
s8 *lastSrcAddr; /* the most-recent or last, post-increment source address */
s8 *lastDestAddr; /* the most-recent or last, post-increment destination address */
u32 dmaSize; /* the amount of data transferred for the current buffer */
MCD_bufDesc *currBufDesc;/* pointer to the current buffer descriptor being DMAed */
} MCD_XferProg;
/* FEC buffer descriptor */
typedef volatile struct MCD_bufDescFec_struct {
u16 statCtrl;
u16 length;
u32 dataPointer;
} MCD_bufDescFec;
/*************************************************************************/
/*
* API function Prototypes - see MCD_dmaApi.c for further notes
*/
/*
* MCD_startDma starts a particular kind of DMA .
*/
int MCD_startDma (
int channel, /* the channel on which to run the DMA */
s8 *srcAddr, /* the address to move data from, or buffer-descriptor address */
s16 srcIncr, /* the amount to increment the source address per transfer */
s8 *destAddr, /* the address to move data to */
s16 destIncr, /* the amount to increment the destination address per transfer */
u32 dmaSize, /* the number of bytes to transfer independent of the transfer size */
u32 xferSize, /* the number bytes in of each data movement (1, 2, or 4) */
u32 initiator, /* what device initiates the DMA */
int priority, /* priority of the DMA */
u32 flags, /* flags describing the DMA */
u32 funcDesc /* a description of byte swapping, bit swapping, and CRC actions */
);
/*
* MCD_initDma() initializes the DMA API by setting up a pointer to the DMA
* registers, relocating and creating the appropriate task structures, and
* setting up some global settings
*/
int MCD_initDma (dmaRegs *sDmaBarAddr, void *taskTableDest, u32 flags);
/*
* MCD_dmaStatus() returns the status of the DMA on the requested channel.
*/
int MCD_dmaStatus (int channel);
/*
* MCD_XferProgrQuery() returns progress of DMA on requested channel
*/
int MCD_XferProgrQuery (int channel, MCD_XferProg *progRep);
/*
* MCD_killDma() halts the DMA on the requested channel, without any
* intention of resuming the DMA.
*/
int MCD_killDma (int channel);
/*
* MCD_continDma() continues a DMA which as stopped due to encountering an
* unready buffer descriptor.
*/
int MCD_continDma (int channel);
/*
* MCD_pauseDma() pauses the DMA on the given channel ( if any DMA is
* running on that channel).
*/
int MCD_pauseDma (int channel);
/*
* MCD_resumeDma() resumes the DMA on a given channel (if any DMA is
* running on that channel).
*/
int MCD_resumeDma (int channel);
/*
* MCD_csumQuery provides the checksum/CRC after performing a non-chained DMA
*/
int MCD_csumQuery (int channel, u32 *csum);
/*
* MCD_getCodeSize provides the packed size required by the microcoded task
* and structures.
*/
int MCD_getCodeSize(void);
/*
* MCD_getVersion provides a pointer to a version string and returns a
* version number.
*/
int MCD_getVersion(char **longVersion);
/* macro for setting a location in the variable table */
#define MCD_SET_VAR(taskTab,idx,value) ((u32 *)(taskTab)->varTab)[idx] = value
/* Note that MCD_SET_VAR() is invoked many times in firing up a DMA function,
so I'm avoiding surrounding it with "do {} while(0)" */
#endif /* DEFINESONLY */
#endif /* _MCD_API_H */

938
headers/MCD_dmaApi.c Normal file
View File

@@ -0,0 +1,938 @@
/*
* File: MCD_dmaApi.c
* Purpose: Main C file for multi-channel DMA API.
*
* Notes:
*/
#include "MCD_dma.h"
#include "MCD_tasksInit.h"
#include "MCD_progCheck.h"
/********************************************************************/
/*
* This is an API-internal pointer to the DMA's registers
*/
dmaRegs *MCD_dmaBar;
/*
* These are the real and model task tables as generated by the
* build process
*/
extern TaskTableEntry MCD_realTaskTableSrc[NCHANNELS];
extern TaskTableEntry MCD_modelTaskTableSrc[NUMOFVARIANTS];
/*
* However, this (usually) gets relocated to on-chip SRAM, at which
* point we access them as these tables
*/
volatile TaskTableEntry *MCD_taskTable;
TaskTableEntry *MCD_modelTaskTable;
/*
* MCD_chStatus[] is an array of status indicators for remembering
* whether a DMA has ever been attempted on each channel, pausing
* status, etc.
*/
static int MCD_chStatus[NCHANNELS] =
{
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA
};
/*
* Prototypes for local functions
*/
static void MCD_memcpy (int *dest, int *src, u32 size);
static void MCD_resmActions (int channel);
/*
* Buffer descriptors used for storage of progress info for single Dmas
* Also used as storage for the DMA for CRCs for single DMAs
* Otherwise, the DMA does not parse these buffer descriptors
*/
#ifdef MCD_INCLUDE_EU
extern MCD_bufDesc MCD_singleBufDescs[NCHANNELS];
#else
MCD_bufDesc MCD_singleBufDescs[NCHANNELS];
#endif
MCD_bufDesc *MCD_relocBuffDesc;
/*
* Defines for the debug control register's functions
*/
#define DBG_CTL_COMP1_TASK (0x00002000) /* have comparator 1 look for a task # */
#define DBG_CTL_ENABLE (DBG_CTL_AUTO_ARM | \
DBG_CTL_BREAK | \
DBG_CTL_INT_BREAK | \
DBG_CTL_COMP1_TASK)
#define DBG_CTL_DISABLE (DBG_CTL_AUTO_ARM | \
DBG_CTL_INT_BREAK | \
DBG_CTL_COMP1_TASK)
#define DBG_KILL_ALL_STAT (0xFFFFFFFF)
/*
* Offset to context save area where progress info is stored
*/
#define CSAVE_OFFSET 10
/*
* Defines for Byte Swapping
*/
#define MCD_BYTE_SWAP_KILLER 0xFFF8888F
#define MCD_NO_BYTE_SWAP_ATALL 0x00040000
/*
* Execution Unit Identifiers
*/
#define MAC 0 /* legacy - not used */
#define LUAC 1 /* legacy - not used */
#define CRC 2 /* legacy - not used */
#define LURC 3 /* Logic Unit with CRC */
/*
* Task Identifiers
*/
#define TASK_CHAINNOEU 0
#define TASK_SINGLENOEU 1
#ifdef MCD_INCLUDE_EU
#define TASK_CHAINEU 2
#define TASK_SINGLEEU 3
#define TASK_FECRX 4
#define TASK_FECTX 5
#else
#define TASK_CHAINEU 0
#define TASK_SINGLEEU 1
#define TASK_FECRX 2
#define TASK_FECTX 3
#endif
/*
* Structure to remember which variant is on which channel
* TBD- need this?
*/
typedef struct MCD_remVariants_struct MCD_remVariant;
struct MCD_remVariants_struct
{
int remDestRsdIncr[NCHANNELS]; /* -1,0,1 */
int remSrcRsdIncr[NCHANNELS]; /* -1,0,1 */
s16 remDestIncr[NCHANNELS]; /* DestIncr */
s16 remSrcIncr[NCHANNELS]; /* srcIncr */
u32 remXferSize[NCHANNELS]; /* xferSize */
};
/*
* Structure to remember the startDma parameters for each channel
*/
MCD_remVariant MCD_remVariants;
/********************************************************************/
/*
* Function: MCD_initDma
* Purpose: Initializes the DMA API by setting up a pointer to the DMA
* registers, relocating and creating the appropriate task
* structures, and setting up some global settings
* Arguments:
* dmaBarAddr - pointer to the multichannel DMA registers
* taskTableDest - location to move DMA task code and structs to
* flags - operational parameters
* Return Value:
* MCD_TABLE_UNALIGNED if taskTableDest is not 512-byte aligned
* MCD_OK otherwise
*/
extern u32 MCD_funcDescTab0[];
int MCD_initDma (dmaRegs *dmaBarAddr, void *taskTableDest, u32 flags)
{
int marker;
int i;
TaskTableEntry *entryPtr;
/* setup the local pointer to register set */
MCD_dmaBar = dmaBarAddr;
/* do we need to move/create a task table */
if ((flags & MCD_RELOC_TASKS) != 0)
{
int fixedSize;
u32 *fixedPtr;
/*int *tablePtr = taskTableDest;TBD*/
int varTabsOffset, funcDescTabsOffset, contextSavesOffset;
int taskDescTabsOffset;
int taskTableSize, varTabsSize, funcDescTabsSize, contextSavesSize;
int taskDescTabSize;
int i;
/* check if physical address is aligned on 512 byte boundary */
if (((u32)taskTableDest & 0x000001ff) != 0)
return(MCD_TABLE_UNALIGNED);
MCD_taskTable = taskTableDest; /* set up local pointer to task Table */
/*
* Create a task table:
* - compute aligned base offsets for variable tables and
* function descriptor tables, then
* - loop through the task table and setup the pointers
* - copy over model task table with the the actual task descriptor
* tables
*/
taskTableSize = NCHANNELS * sizeof(TaskTableEntry);
/* align variable tables to size */
varTabsOffset = taskTableSize + (u32)taskTableDest;
if ((varTabsOffset & (VAR_TAB_SIZE - 1)) != 0)
varTabsOffset = (varTabsOffset + VAR_TAB_SIZE) & (~VAR_TAB_SIZE);
/* align function descriptor tables */
varTabsSize = NCHANNELS * VAR_TAB_SIZE;
funcDescTabsOffset = varTabsOffset + varTabsSize;
if ((funcDescTabsOffset & (FUNCDESC_TAB_SIZE - 1)) != 0)
funcDescTabsOffset = (funcDescTabsOffset + FUNCDESC_TAB_SIZE) &
(~FUNCDESC_TAB_SIZE);
funcDescTabsSize = FUNCDESC_TAB_NUM * FUNCDESC_TAB_SIZE;
contextSavesOffset = funcDescTabsOffset + funcDescTabsSize;
contextSavesSize = (NCHANNELS * CONTEXT_SAVE_SIZE);
fixedSize = taskTableSize + varTabsSize + funcDescTabsSize +
contextSavesSize;
/* zero the thing out */
fixedPtr = (u32 *)taskTableDest;
for (i = 0;i<(fixedSize/4);i++)
fixedPtr[i] = 0;
entryPtr = (TaskTableEntry*)MCD_taskTable;
/* set up fixed pointers */
for (i = 0; i < NCHANNELS; i++)
{
entryPtr[i].varTab = (u32)varTabsOffset; /* update ptr to local value */
entryPtr[i].FDTandFlags = (u32)funcDescTabsOffset | MCD_TT_FLAGS_DEF;
entryPtr[i].contextSaveSpace = (u32)contextSavesOffset;
varTabsOffset += VAR_TAB_SIZE;
#ifdef MCD_INCLUDE_EU /* if not there is only one, just point to the same one */
funcDescTabsOffset += FUNCDESC_TAB_SIZE;
#endif
contextSavesOffset += CONTEXT_SAVE_SIZE;
}
/* copy over the function descriptor table */
for ( i = 0; i < FUNCDESC_TAB_NUM; i++)
{
MCD_memcpy((void*)(entryPtr[i].FDTandFlags & ~MCD_TT_FLAGS_MASK),
(void*)MCD_funcDescTab0, FUNCDESC_TAB_SIZE);
}
/* copy model task table to where the context saves stuff leaves off*/
MCD_modelTaskTable = (TaskTableEntry*)contextSavesOffset;
MCD_memcpy ((void*)MCD_modelTaskTable, (void*)MCD_modelTaskTableSrc,
NUMOFVARIANTS * sizeof(TaskTableEntry));
entryPtr = MCD_modelTaskTable; /* point to local version of
model task table */
taskDescTabsOffset = (u32)MCD_modelTaskTable +
(NUMOFVARIANTS * sizeof(TaskTableEntry));
/* copy actual task code and update TDT ptrs in local model task table */
for (i = 0; i < NUMOFVARIANTS; i++)
{
asm
{
move.l #0x77777777,d0
}
taskDescTabSize = entryPtr[i].TDTend - entryPtr[i].TDTstart + 4;
MCD_memcpy ((void*)taskDescTabsOffset, (void*)entryPtr[i].TDTstart, taskDescTabSize);
entryPtr[i].TDTstart = (u32)taskDescTabsOffset;
taskDescTabsOffset += taskDescTabSize;
entryPtr[i].TDTend = (u32)taskDescTabsOffset - 4;
}
#ifdef MCD_INCLUDE_EU /* Tack single DMA BDs onto end of code so API controls
where they are since DMA might write to them */
MCD_relocBuffDesc = (MCD_bufDesc*)(entryPtr[NUMOFVARIANTS - 1].TDTend + 4);
#else /* DMA does not touch them so they can be wherever and we don't need to
waste SRAM on them */
MCD_relocBuffDesc = MCD_singleBufDescs;
#endif
}
else
{
/* point the would-be relocated task tables and the
buffer descriptors to the ones the linker generated */
if (((u32)MCD_realTaskTableSrc & 0x000001ff) != 0)
return(MCD_TABLE_UNALIGNED);
/* need to add code to make sure that every thing else is aligned properly TBD*/
/* this is problematic if we init more than once or after running tasks,
need to add variable to see if we have aleady init'd */
entryPtr = MCD_realTaskTableSrc;
for (i = 0; i < NCHANNELS; i++)
{
if (((entryPtr[i].varTab & (VAR_TAB_SIZE - 1)) != 0) ||
((entryPtr[i].FDTandFlags & (FUNCDESC_TAB_SIZE - 1)) != 0))
return(MCD_TABLE_UNALIGNED);
}
MCD_taskTable = MCD_realTaskTableSrc;
MCD_modelTaskTable = MCD_modelTaskTableSrc;
MCD_relocBuffDesc = MCD_singleBufDescs;
}
/* Make all channels as totally inactive, and remember them as such: */
MCD_dmaBar->taskbar = (u32) MCD_taskTable;
for (i = 0; i < NCHANNELS; i++)
{
MCD_dmaBar->taskControl[i] = 0x0;
MCD_chStatus[i] = MCD_NO_DMA;
}
/* Set up pausing mechanism to inactive state: */
MCD_dmaBar->debugComp1 = 0; /* no particular values yet for either comparator registers */
MCD_dmaBar->debugComp2 = 0;
MCD_dmaBar->debugControl = DBG_CTL_DISABLE;
MCD_dmaBar->debugStatus = DBG_KILL_ALL_STAT;
/* enable or disable commbus prefetch, really need an ifdef or
something to keep from trying to set this in the 8220 */
if ((flags & MCD_COMM_PREFETCH_EN) != 0)
MCD_dmaBar->ptdControl &= ~PTD_CTL_COMM_PREFETCH;
else
MCD_dmaBar->ptdControl |= PTD_CTL_COMM_PREFETCH;
return(MCD_OK);
}
/*********************** End of MCD_initDma() ***********************/
/********************************************************************/
/* Function: MCD_dmaStatus
* Purpose: Returns the status of the DMA on the requested channel
* Arguments: channel - channel number
* Returns: Predefined status indicators
*/
int MCD_dmaStatus (int channel)
{
u16 tcrValue;
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
tcrValue = MCD_dmaBar->taskControl[channel];
if ((tcrValue & TASK_CTL_EN) == 0)
{ /* nothing running */
/* if last reported with task enabled */
if ( MCD_chStatus[channel] == MCD_RUNNING
|| MCD_chStatus[channel] == MCD_IDLE)
MCD_chStatus[channel] = MCD_DONE;
}
else /* something is running */
{
/* There are three possibilities: paused, running or idle. */
if ( MCD_chStatus[channel] == MCD_RUNNING
|| MCD_chStatus[channel] == MCD_IDLE)
{
MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT;
/* This register is selected to know which initiator is
actually asserted. */
if ((MCD_dmaBar->ptdDebug >> channel ) & 0x1 )
MCD_chStatus[channel] = MCD_RUNNING;
else
MCD_chStatus[channel] = MCD_IDLE;
/* do not change the status if it is already paused. */
}
}
return MCD_chStatus[channel];
}
/******************** End of MCD_dmaStatus() ************************/
/********************************************************************/
/* Function: MCD_startDma
* Ppurpose: Starts a particular kind of DMA
* Arguments: see below
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*/
int MCD_startDma (
int channel, /* the channel on which to run the DMA */
s8 *srcAddr, /* the address to move data from, or physical buffer-descriptor address */
s16 srcIncr, /* the amount to increment the source address per transfer */
s8 *destAddr, /* the address to move data to */
s16 destIncr, /* the amount to increment the destination address per transfer */
u32 dmaSize, /* the number of bytes to transfer independent of the transfer size */
u32 xferSize, /* the number bytes in of each data movement (1, 2, or 4) */
u32 initiator, /* what device initiates the DMA */
int priority, /* priority of the DMA */
u32 flags, /* flags describing the DMA */
u32 funcDesc /* a description of byte swapping, bit swapping, and CRC actions */
#ifdef MCD_NEED_ADDR_TRANS
s8 *srcAddrVirt /* virtual buffer descriptor address TBD*/
#endif
)
{
int srcRsdIncr, destRsdIncr;
int *cSave;
short xferSizeIncr;
int tcrCount = 0;
#ifdef MCD_INCLUDE_EU
u32 *realFuncArray;
#endif
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
/* tbd - need to determine the proper response to a bad funcDesc when not
including EU functions, for now, assign a benign funcDesc, but maybe
should return an error */
#ifndef MCD_INCLUDE_EU
funcDesc = MCD_FUNC_NOEU1;
#endif
#ifdef MCD_DEBUG
printf("startDma:Setting up params\n");
#endif
/* Set us up for task-wise priority. We don't technically need to do this on every start, but
since the register involved is in the same longword as other registers that users are in control
of, setting it more than once is probably preferable. That since the documentation doesn't seem
to be completely consistent about the nature of the PTD control register. */
MCD_dmaBar->ptdControl |= (u16) 0x8000;
#if 1 /* Not sure what we need to keep here rtm TBD */
/* Calculate additional parameters to the regular DMA calls. */
srcRsdIncr = srcIncr < 0 ? -1 : (srcIncr > 0 ? 1 : 0);
destRsdIncr = destIncr < 0 ? -1 : (destIncr > 0 ? 1 : 0);
xferSizeIncr = (xferSize & 0xffff) | 0x20000000;
/* Remember for each channel which variant is running. */
MCD_remVariants.remSrcRsdIncr[channel] = srcRsdIncr;
MCD_remVariants.remDestRsdIncr[channel] = destRsdIncr;
MCD_remVariants.remDestIncr[channel] = destIncr;
MCD_remVariants.remSrcIncr[channel] = srcIncr;
MCD_remVariants.remXferSize[channel] = xferSize;
#endif
cSave = (int*)(MCD_taskTable[channel].contextSaveSpace) + CSAVE_OFFSET + CURRBD;
#ifdef MCD_INCLUDE_EU /* may move this to EU specific calls */
realFuncArray = (u32 *) (MCD_taskTable[channel].FDTandFlags & 0xffffff00);
/* Modify the LURC's normal and byte-residue-loop functions according to parameter. */
realFuncArray[(LURC*16)] = xferSize == 4 ?
funcDesc : xferSize == 2 ?
funcDesc & 0xfffff00f : funcDesc & 0xffff000f;
realFuncArray[(LURC*16+1)] = (funcDesc & MCD_BYTE_SWAP_KILLER) | MCD_NO_BYTE_SWAP_ATALL;
#endif
/* Write the initiator field in the TCR, and also set the initiator-hold
bit. Note that,due to a hardware quirk, this could collide with an
MDE access to the initiator-register file, so we have to verify that the write
reads back correctly. */
MCD_dmaBar->taskControl[channel] =
(initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM;
while(((MCD_dmaBar->taskControl[channel] & 0x1fff) !=
((initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM)) &&
(tcrCount < 1000))
{
tcrCount++;
/*MCD_dmaBar->ptd_tcr[channel] = (initiator << 8) | 0x0020;*/
MCD_dmaBar->taskControl[channel] =
(initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM;
}
MCD_dmaBar->priority[channel] = (u8)priority & PRIORITY_PRI_MASK;
/* should be albe to handle this stuff with only one write to ts reg - tbd */
if (channel < 8 && channel >= 0)
{
MCD_dmaBar->taskSize0 &= ~(0xf << (7-channel)*4);
MCD_dmaBar->taskSize0 |= (xferSize & 3) << (((7 - channel)*4) + 2);
MCD_dmaBar->taskSize0 |= (xferSize & 3) << ((7 - channel)*4);
}
else
{
MCD_dmaBar->taskSize1 &= ~(0xf << (15-channel)*4);
MCD_dmaBar->taskSize1 |= (xferSize & 3) << (((15 - channel)*4) + 2);
MCD_dmaBar->taskSize1 |= (xferSize & 3) << ((15 - channel)*4);
}
/* setup task table flags/options which mostly control the line buffers */
MCD_taskTable[channel].FDTandFlags &= ~MCD_TT_FLAGS_MASK;
MCD_taskTable[channel].FDTandFlags |= (MCD_TT_FLAGS_MASK & flags);
if (flags & MCD_FECTX_DMA)
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_FECTX].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_FECTX].TDTend;
MCD_startDmaENetXmit(srcAddr, srcAddr, destAddr, MCD_taskTable, channel);
}
else if (flags & MCD_FECRX_DMA)
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_FECRX].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_FECRX].TDTend;
MCD_startDmaENetRcv(srcAddr, srcAddr, destAddr, MCD_taskTable, channel);
}
else if(flags & MCD_SINGLE_DMA)
{
/* this buffer descriptor is used for storing off initial parameters for later
progress query calculation and for the DMA to write the resulting checksum
The DMA does not use this to determine how to operate, that info is passed
with the init routine*/
MCD_relocBuffDesc[channel].srcAddr = srcAddr;
MCD_relocBuffDesc[channel].destAddr = destAddr;
MCD_relocBuffDesc[channel].lastDestAddr = destAddr; /* definitely not its final value */
MCD_relocBuffDesc[channel].dmaSize = dmaSize;
MCD_relocBuffDesc[channel].flags = 0; /* not used */
MCD_relocBuffDesc[channel].csumResult = 0; /* not used */
MCD_relocBuffDesc[channel].next = 0; /* not used */
/* Initialize the progress-querying stuff to show no progress:*/
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET] = (int)srcAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET] = (int)destAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET] =
(u32) &(MCD_relocBuffDesc[channel]);
/* tbd - need to keep the user from trying to call the EU routine
when MCD_INCLUDE_EU is not defined */
if( funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2)
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_SINGLENOEU].TDTend;
MCD_startDmaSingleNoEu(srcAddr, srcIncr, destAddr, destIncr, dmaSize,
xferSizeIncr, flags, (int *)&(MCD_relocBuffDesc[channel]), cSave,
MCD_taskTable, channel);
}
else
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_SINGLEEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_SINGLEEU].TDTend;
MCD_startDmaSingleEu(srcAddr, srcIncr, destAddr, destIncr, dmaSize,
xferSizeIncr, flags, (int *)&(MCD_relocBuffDesc[channel]), cSave,
MCD_taskTable, channel);
}
}
else
{ /* chained DMAS */
/* Initialize the progress-querying stuff to show no progress:*/
#if 1 /* (!defined(MCD_NEED_ADDR_TRANS)) */
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddr)->srcAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddr)->destAddr;
#else /* if using address translation, need the virtual addr of the first buffdesc */
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddrVirt)->srcAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddrVirt)->destAddr;
#endif
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET] = (u32) srcAddr;
if( funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2)
{
/*TDTStart and TDTEnd*/
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_CHAINNOEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_CHAINNOEU].TDTend;
MCD_startDmaChainNoEu((int *)srcAddr, srcIncr, destIncr, xferSize,
xferSizeIncr, cSave, MCD_taskTable, channel);
}
else
{
/*TDTStart and TDTEnd*/
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_CHAINEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_CHAINEU].TDTend;
MCD_startDmaChainEu((int *)srcAddr, srcIncr, destIncr, xferSize,
xferSizeIncr, cSave, MCD_taskTable, channel);
}
}
MCD_chStatus[channel] = MCD_IDLE;
return(MCD_OK);
}
/************************ End of MCD_startDma() *********************/
/********************************************************************/
/* Function: MCD_XferProgrQuery
* Purpose: Returns progress of DMA on requested channel
* Arguments: channel - channel to retrieve progress for
* progRep - pointer to user supplied MCD_XferProg struct
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*
* Notes:
* MCD_XferProgrQuery() upon completing or after aborting a DMA, or
* while the DMA is in progress, this function returns the first
* DMA-destination address not (or not yet) used in the DMA. When
* encountering a non-ready buffer descriptor, the information for
* the last completed descriptor is returned.
*
* MCD_XferProgQuery() has to avoid the possibility of getting
* partially-updated information in the event that we should happen
* to query DMA progress just as the DMA is updating it. It does that
* by taking advantage of the fact context is not saved frequently for
* the most part. We therefore read it at least twice until we get the
* same information twice in a row.
*
* Because a small, but not insignificant, amount of time is required
* to write out the progress-query information, especially upon
* completion of the DMA, it would be wise to guarantee some time lag
* between successive readings of the progress-query information.
*/
/*
* How many iterations of the loop below to execute to stabilize values
*/
#define STABTIME 0
int MCD_XferProgrQuery (int channel, MCD_XferProg *progRep)
{
MCD_XferProg prevRep;
int again; /* true if we are to try again to get consistent results */
int i; /* used as a time-waste counter */
int destDiffBytes; /* Total number of bytes that we think actually got xfered. */
int numIterations; /* number of iterations */
int bytesNotXfered; /* bytes that did not get xfered. */
s8 *LWAlignedInitDestAddr, *LWAlignedCurrDestAddr;
int subModVal, addModVal; /* Mode values to added and subtracted from the
final destAddr */
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
/* Read a trial value for the progress-reporting values*/
prevRep.lastSrcAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET];
prevRep.lastDestAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET];
prevRep.dmaSize = ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET];
prevRep.currBufDesc =
(MCD_bufDesc*) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET];
/* Repeatedly reread those values until they match previous values: */
do {
/* Waste a little bit of time to ensure stability: */
for (i = 0; i < STABTIME; i++)
i += i >> 2; /* make sure this loop does something so that it doesn't get optimized out */
/* Check them again: */
progRep->lastSrcAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET];
progRep->lastDestAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET];
progRep->dmaSize = ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET];
progRep->currBufDesc =
(MCD_bufDesc*) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET];
/* See if they match: */
if ( prevRep.lastSrcAddr != progRep->lastSrcAddr
|| prevRep.lastDestAddr != progRep->lastDestAddr
|| prevRep.dmaSize != progRep->dmaSize
|| prevRep.currBufDesc != progRep->currBufDesc)
{
/* If they don't match, remember previous values and try again:*/
prevRep.lastSrcAddr = progRep->lastSrcAddr;
prevRep.lastDestAddr = progRep->lastDestAddr;
prevRep.dmaSize = progRep->dmaSize;
prevRep.currBufDesc = progRep->currBufDesc;
again = MCD_TRUE;
}
else
again = MCD_FALSE;
} while (again == MCD_TRUE);
/* Update the dCount, srcAddr and destAddr */
/* To calculate dmaCount, we consider destination address. C
overs M1,P1,Z for destination */
switch(MCD_remVariants.remDestRsdIncr[channel]) {
case MINUS1:
subModVal = ((int)progRep->lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
addModVal = ((int)progRep->currBufDesc->destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - addModVal;
LWAlignedCurrDestAddr = (progRep->lastDestAddr) - subModVal;
destDiffBytes = LWAlignedInitDestAddr - LWAlignedCurrDestAddr;
bytesNotXfered = (destDiffBytes/MCD_remVariants.remDestIncr[channel]) *
( MCD_remVariants.remDestIncr[channel]
+ MCD_remVariants.remXferSize[channel]);
progRep->dmaSize = destDiffBytes - bytesNotXfered + addModVal - subModVal;
break;
case ZERO:
progRep->lastDestAddr = progRep->currBufDesc->destAddr;
break;
case PLUS1:
/* This value has to be subtracted from the final calculated dCount. */
subModVal = ((int)progRep->currBufDesc->destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
/* These bytes are already in lastDestAddr. */
addModVal = ((int)progRep->lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - subModVal;
LWAlignedCurrDestAddr = (progRep->lastDestAddr) - addModVal;
destDiffBytes = (progRep->lastDestAddr - LWAlignedInitDestAddr);
numIterations = ( LWAlignedCurrDestAddr - LWAlignedInitDestAddr)/MCD_remVariants.remDestIncr[channel];
bytesNotXfered = numIterations *
( MCD_remVariants.remDestIncr[channel]
- MCD_remVariants.remXferSize[channel]);
progRep->dmaSize = destDiffBytes - bytesNotXfered - subModVal;
break;
default:
break;
}
/* This covers M1,P1,Z for source */
switch(MCD_remVariants.remSrcRsdIncr[channel]) {
case MINUS1:
progRep->lastSrcAddr =
progRep->currBufDesc->srcAddr +
( MCD_remVariants.remSrcIncr[channel] *
(progRep->dmaSize/MCD_remVariants.remXferSize[channel]));
break;
case ZERO:
progRep->lastSrcAddr = progRep->currBufDesc->srcAddr;
break;
case PLUS1:
progRep->lastSrcAddr =
progRep->currBufDesc->srcAddr +
( MCD_remVariants.remSrcIncr[channel] *
(progRep->dmaSize/MCD_remVariants.remXferSize[channel]));
break;
default: break;
}
return(MCD_OK);
}
/******************* End of MCD_XferProgrQuery() ********************/
/********************************************************************/
/* MCD_resmActions() does the majority of the actions of a DMA resume.
* It is called from MCD_killDma() and MCD_resumeDma(). It has to be
* a separate function because the kill function has to negate the task
* enable before resuming it, but the resume function has to do nothing
* if there is no DMA on that channel (i.e., if the enable bit is 0).
*/
static void MCD_resmActions (int channel)
{
MCD_dmaBar->debugControl = DBG_CTL_DISABLE;
MCD_dmaBar->debugStatus = MCD_dmaBar->debugStatus;
MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; /* This register is selected to know
which initiator is actually asserted. */
if((MCD_dmaBar->ptdDebug >> channel ) & 0x1)
MCD_chStatus[channel] = MCD_RUNNING;
else
MCD_chStatus[channel] = MCD_IDLE;
}
/********************* End of MCD_resmActions() *********************/
/********************************************************************/
/* Function: MCD_killDma
* Purpose: Halt the DMA on the requested channel, without any
* intention of resuming the DMA.
* Arguments: channel - requested channel
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*
* Notes:
* A DMA may be killed from any state, including paused state, and it
* always goes to the MCD_HALTED state even if it is killed while in
* the MCD_NO_DMA or MCD_IDLE states.
*/
int MCD_killDma (int channel)
{
/* MCD_XferProg progRep; */
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
MCD_dmaBar->taskControl[channel] = 0x0;
MCD_resumeDma (channel);
/*
* This must be after the write to the TCR so that the task doesn't
* start up again momentarily, and before the status assignment so
* as to override whatever MCD_resumeDma() may do to the channel
* status.
*/
MCD_chStatus[channel] = MCD_HALTED;
/*
* Update the current buffer descriptor's lastDestAddr field
*
* MCD_XferProgrQuery (channel, &progRep);
* progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr;
*/
return(MCD_OK);
}
/************************ End of MCD_killDma() **********************/
/********************************************************************/
/* Function: MCD_continDma
* Purpose: Continue a DMA which as stopped due to encountering an
* unready buffer descriptor.
* Arguments: channel - channel to continue the DMA on
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*
* Notes:
* This routine does not check to see if there is a task which can
* be continued. Also this routine should not be used with single DMAs.
*/
int MCD_continDma (int channel)
{
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
MCD_dmaBar->taskControl[channel] |= TASK_CTL_EN;
MCD_chStatus[channel] = MCD_RUNNING;
return(MCD_OK);
}
/********************** End of MCD_continDma() **********************/
/*********************************************************************
* MCD_pauseDma() and MCD_resumeDma() below use the DMA's debug unit
* to freeze a task and resume it. We freeze a task by breakpointing
* on the stated task. That is, not any specific place in the task,
* but any time that task executes. In particular, when that task
* executes, we want to freeze that task and only that task.
*
* The bits of the debug control register influence interrupts vs.
* breakpoints as follows:
* - Bits 14 and 0 enable or disable debug functions. If enabled, you
* will get the interrupt but you may or may not get a breakpoint.
* - Bits 2 and 1 decide whether you also get a breakpoint in addition
* to an interrupt.
*
* The debug unit can do these actions in response to either internally
* detected breakpoint conditions from the comparators, or in response
* to the external breakpoint pin, or both.
* - Bits 14 and 1 perform the above-described functions for
* internally-generated conditions, i.e., the debug comparators.
* - Bits 0 and 2 perform the above-described functions for external
* conditions, i.e., the breakpoint external pin.
*
* Note that, although you "always" get the interrupt when you turn
* the debug functions, the interrupt can nevertheless, if desired, be
* masked by the corresponding bit in the PTD's IMR. Note also that
* this means that bits 14 and 0 must enable debug functions before
* bits 1 and 2, respectively, have any effect.
*
* NOTE: It's extremely important to not pause more than one DMA channel
* at a time.
********************************************************************/
/********************************************************************/
/* Function: MCD_pauseDma
* Purpose: Pauses the DMA on a given channel (if any DMA is running
* on that channel).
* Arguments: channel
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*/
int MCD_pauseDma (int channel)
{
/* MCD_XferProg progRep; */
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN)
{
MCD_dmaBar->debugComp1 = channel;
MCD_dmaBar->debugControl = DBG_CTL_ENABLE | (1 << (channel + 16));
MCD_chStatus[channel] = MCD_PAUSED;
/*
* Update the current buffer descriptor's lastDestAddr field
*
* MCD_XferProgrQuery (channel, &progRep);
* progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr;
*/
}
return(MCD_OK);
}
/************************* End of MCD_pauseDma() ********************/
/********************************************************************/
/* Function: MCD_resumeDma
* Purpose: Resumes the DMA on a given channel (if any DMA is
* running on that channel).
* Arguments: channel - channel on which to resume DMA
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*/
int MCD_resumeDma (int channel)
{
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN)
MCD_resmActions (channel);
return(MCD_OK);
}
/************************ End of MCD_resumeDma() ********************/
/********************************************************************/
/* Function: MCD_csumQuery
* Purpose: Provide the checksum after performing a non-chained DMA
* Arguments: channel - channel to report on
* csum - pointer to where to write the checksum/CRC
* Returns: MCD_ERROR if the channel is invalid, else MCD_OK
*
* Notes:
*
*/
int MCD_csumQuery (int channel, u32 *csum)
{
#ifdef MCD_INCLUDE_EU
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
*csum = MCD_relocBuffDesc[channel].csumResult;
return(MCD_OK);
#else
return(MCD_ERROR);
#endif
}
/*********************** End of MCD_resumeDma() *********************/
/********************************************************************/
/* Function: MCD_getCodeSize
* Purpose: Provide the size requirements of the microcoded tasks
* Returns: Size in bytes
*/
int MCD_getCodeSize(void)
{
#ifdef MCD_INCLUDE_EU
return(0x2b5c);
#else
return(0x173c);
#endif
}
/********************** End of MCD_getCodeSize() ********************/
/********************************************************************/
/* Function: MCD_getVersion
* Purpose: Provide the version string and number
* Arguments: longVersion - user supplied pointer to a pointer to a char
* which points to the version string
* Returns: Version number and version string (by reference)
*/
char MCD_versionString[] = "Multi-channel DMA API Alpha v0.3 (2004-04-26)";
#define MCD_REV_MAJOR 0x00
#define MCD_REV_MINOR 0x03
int MCD_getVersion(char **longVersion)
{
*longVersion = MCD_versionString;
return((MCD_REV_MAJOR << 8) | MCD_REV_MINOR);
}
/********************** End of MCD_getVersion() *********************/
/********************************************************************/
/* Private version of memcpy()
* Note that everything this is used for is longword-aligned.
*/
static void MCD_memcpy (int *dest, int *src, u32 size)
{
u32 i;
for (i = 0; i < size; i += sizeof(int), dest++, src++)
*dest = *src;
}
/********************************************************************/

5
headers/MCD_progCheck.h Normal file
View File

@@ -0,0 +1,5 @@
/* This file is autogenerated. Do not change */
#define CURRBD 4
#define DCOUNT 6
#define DESTPTR 5
#define SRCPTR 7

2449
headers/MCD_tasks.c Normal file

File diff suppressed because it is too large Load Diff

224
headers/MCD_tasksInit.c Normal file
View File

@@ -0,0 +1,224 @@
/*
* File: MCD_tasksInit.c
* Purpose: Functions for initializing variable tables of different
* types of tasks.
*
* Notes:
*/
/*
* Do not edit!
*/
#include "MCD_dma.h"
extern dmaRegs *MCD_dmaBar;
/*
* Task 0
*/
void MCD_startDmaChainNoEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 2, (u32)currBD); /* var[2] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 11, (u32)xferSize); /* var[11] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 3, (u32)0x00000000); /* var[3] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000000); /* var[12] */
MCD_SET_VAR(taskTable+channel, 13, (u32)0x80000000); /* var[13] */
MCD_SET_VAR(taskTable+channel, 14, (u32)0x00000010); /* var[14] */
MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000004); /* var[15] */
MCD_SET_VAR(taskTable+channel, 16, (u32)0x08000000); /* var[16] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000000); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000001); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x40000000); /* inc[6] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 1
*/
void MCD_startDmaSingleNoEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 7, (u32)srcAddr); /* var[7] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)destAddr); /* var[2] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 3, (u32)dmaSize); /* var[3] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 5, (u32)flags); /* var[5] */
MCD_SET_VAR(taskTable+channel, 1, (u32)currBD); /* var[1] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000004); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x08000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000001); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x40000000); /* inc[5] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 2
*/
void MCD_startDmaChainEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 12, (u32)xferSize); /* var[12] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 11, (u32)0x00000000); /* var[11] */
MCD_SET_VAR(taskTable+channel, 13, (u32)0x00000000); /* var[13] */
MCD_SET_VAR(taskTable+channel, 14, (u32)0x80000000); /* var[14] */
MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000010); /* var[15] */
MCD_SET_VAR(taskTable+channel, 16, (u32)0x00000001); /* var[16] */
MCD_SET_VAR(taskTable+channel, 17, (u32)0x00000004); /* var[17] */
MCD_SET_VAR(taskTable+channel, 18, (u32)0x08000000); /* var[18] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000000); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0xc0000000); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x80000001); /* inc[6] */
MCD_SET_VAR(taskTable+channel, 31, (u32)0x40000000); /* inc[7] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 3
*/
void MCD_startDmaSingleEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 8, (u32)srcAddr); /* var[8] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 3, (u32)destAddr); /* var[3] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 4, (u32)dmaSize); /* var[4] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 6, (u32)flags); /* var[6] */
MCD_SET_VAR(taskTable+channel, 2, (u32)currBD); /* var[2] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000001); /* var[10] */
MCD_SET_VAR(taskTable+channel, 11, (u32)0x00000004); /* var[11] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x08000000); /* var[12] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0xc0000000); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000000); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x80000001); /* inc[6] */
MCD_SET_VAR(taskTable+channel, 31, (u32)0x40000000); /* inc[7] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 4
*/
void MCD_startDmaENetRcv(char *bDBase, char *currBD, char *rcvFifoPtr, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 0, (u32)bDBase); /* var[0] */
MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */
MCD_SET_VAR(taskTable+channel, 6, (u32)rcvFifoPtr); /* var[6] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x0000ffff); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x30000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 11, (u32)0x0fffffff); /* var[11] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000008); /* var[12] */
MCD_SET_VAR(taskTable+channel, 24, (u32)0x00000000); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 25, (u32)0x60000000); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 26, (u32)0x20000004); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x40000000); /* inc[3] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 5
*/
void MCD_startDmaENetXmit(char *bDBase, char *currBD, char *xmitFifoPtr, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 0, (u32)bDBase); /* var[0] */
MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */
MCD_SET_VAR(taskTable+channel, 11, (u32)xmitFifoPtr); /* var[11] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000000); /* var[12] */
MCD_SET_VAR(taskTable+channel, 13, (u32)0x0000ffff); /* var[13] */
MCD_SET_VAR(taskTable+channel, 14, (u32)0xffffffff); /* var[14] */
MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000004); /* var[15] */
MCD_SET_VAR(taskTable+channel, 16, (u32)0x00000008); /* var[16] */
MCD_SET_VAR(taskTable+channel, 24, (u32)0x00000000); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 25, (u32)0x60000000); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 26, (u32)0x40000000); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0xc000fffc); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0xe0000004); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000000); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x4000ffff); /* inc[6] */
MCD_SET_VAR(taskTable+channel, 31, (u32)0xe0000001); /* inc[7] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}

44
headers/MCD_tasksInit.h Normal file
View File

@@ -0,0 +1,44 @@
#ifndef MCD_TSK_INIT_H
#define MCD_TSK_INIT_H 1
/*
* Do not edit!
*/
/*
* Task 0
*/
void MCD_startDmaChainNoEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel);
/*
* Task 1
*/
void MCD_startDmaSingleNoEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel);
/*
* Task 2
*/
void MCD_startDmaChainEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel);
/*
* Task 3
*/
void MCD_startDmaSingleEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel);
/*
* Task 4
*/
void MCD_startDmaENetRcv(char *bDBase, char *currBD, char *rcvFifoPtr, volatile TaskTableEntry *taskTable, int channel);
/*
* Task 5
*/
void MCD_startDmaENetXmit(char *bDBase, char *currBD, char *xmitFifoPtr, volatile TaskTableEntry *taskTable, int channel);
#endif /* MCD_TSK_INIT_H */

View File

@@ -372,3 +372,4 @@ mmmr_na6\@:
mmmr_na7\@:
ii_end
.endm

View File

@@ -20,10 +20,8 @@
*/
/********************************************************************************/
#ifdef ii_on
#define cf_stack
//#define ii_on
#define halten
#define halten_dbcc
#define halten_and
@@ -40,6 +38,8 @@
#define halten_movep
#define halten_ewf
#endif
#define DIP_SWITCH (*(vuint8 *)(&__MBAR[0xA2C]))
#define DIP_SWITCHa ___MBAR + 0xA2C

View File

@@ -68,8 +68,8 @@ _rt_mbar = ___RAMBAR0 + 0x844; # (c)0f
# 32KB on-chip System SRAM
___SYS_SRAM = 0xFF010000;
___SYS_SRAM_SIZE = 0x00008000;
.text :
{
startcf.c(.text)
@@ -79,10 +79,13 @@ _rt_mbar = ___RAMBAR0 + 0x844; # (c)0f
mmu.s(.text)
exceptions.s(.text)
supervisor.s(.text)
ewf.s(.text)
illegal_instruction.s(.text)
MCD_dmaApi.c(.*)
MCD_tasksInit.c(.*)
MCD_tasks.c(.*)
last.c(.text)
. = ALIGN (0x4);
__SDA_BASE = .;
# . = ALIGN (0x4);
} > code
}

View File

@@ -5,13 +5,15 @@ KEEP_SECTION {.vectortable}
# Memory ranges
MEMORY {
code (RX) : ORIGIN = 0xE0000000, LENGTH = 0x00200000
userram (RWX) : ORIGIN = 0x00010000, LENGTH = 0x10000000
code (RX) : ORIGIN = 0xE0000000, LENGTH = 0x00100000
}
SECTIONS {
#BaS Basis adresse
___Bas_base = 0x1FE00000;
# Heap and Stack sizes definition
___heap_size = 0x10000;
___stack_size = 0x10000;
# Board Memory map definitions from linker command files:
# __SDRAM,__SDRAM_SIZE, __CODE_FLASH, __CODE_FLASH_SIZE
@@ -37,13 +39,11 @@ SECTIONS {
# 4KB on-chip Core SRAM0: -> exception table and exception stack
___RAMBAR0 = 0xFF100000;
___RAMBAR0_SIZE = 0x00001000;
___SUP_SP = ___RAMBAR0 + ___RAMBAR0_SIZE - 4;
# 4KB on-chip Core SRAM1: -> modified code
___RAMBAR1 = 0xFF101000;
___RAMBAR1_SIZE = 0x00001000;
# Systemveriablem:******************************************
# RAMBAR0 0 bis 0x7FF -> exception vectoren
_rt_mod = ___RAMBAR0 + 0x800;
@@ -69,20 +69,86 @@ _rt_mbar = ___RAMBAR0 + 0x844; # (c)0f
___SYS_SRAM = 0xFF010000;
___SYS_SRAM_SIZE = 0x00008000;
___SUP_SP = ___RAMBAR0 + ___RAMBAR0_SIZE - 4;
.userram : {} > userram
.code : {} > code
.text :
{
startcf.c(.text)
sysinit.c(.text)
BaS.c(.text)
sd_card.c(.text)
mmu.s(.text)
exceptions.s(.text)
supervisor.s(.text)
ewf.s(.text)
illegal_instruction.s(.text)
last.c(.text)
*(.text)
. = ALIGN (0x4);
*(.rodata)
. = ALIGN (0x4);
___ROM_AT = .;
___DATA_ROM = .;
} >> code
}
.data : AT(___ROM_AT)
{
___DATA_RAM = .;
. = ALIGN(0x4);
*(.exception)
. = ALIGN(0x4);
__exception_table_start__ = .;
EXCEPTION
__exception_table_end__ = .;
___sinit__ = .;
STATICINIT
__START_DATA = .;
*(.data)
. = ALIGN (0x4);
__END_DATA = .;
__START_SDATA = .;
*(.sdata)
. = ALIGN (0x4);
__END_SDATA = .;
___DATA_END = .;
__SDA_BASE = .;
. = ALIGN (0x4);
} >> userram
.bss :
{
___BSS_START = .;
__START_SBSS = .;
*(.sbss)
. = ALIGN (0x4);
*(SCOMMON)
__END_SBSS = .;
__START_BSS = .;
*(.bss)
. = ALIGN (0x4);
*(COMMON)
__END_BSS = .;
___BSS_END = .;
. = ALIGN(0x4);
} >> userram
.custom :
{
___HEAP_START = .;
___heap_addr = ___HEAP_START;
___HEAP_END = ___HEAP_START + ___heap_size;
___SP_END = ___HEAP_END;
___SP_INIT = ___SP_END + ___stack_size;
. = ALIGN (0x4);
} >> userram
__SP_INIT = ___SP_INIT;
_romp_at = ___ROM_AT + SIZEOF(.data);
.romp : AT(_romp_at)
{
__S_romp = _romp_at;
WRITEW(___ROM_AT);
WRITEW(ADDR(.data));
WRITEW(SIZEOF(.data));
WRITEW(0);
WRITEW(0);
WRITEW(0);
}
}

933
mcdapirev0p3/MCD_dmaApi.c Normal file
View File

@@ -0,0 +1,933 @@
/*
* File: MCD_dmaApi.c
* Purpose: Main C file for multi-channel DMA API.
*
* Notes:
*/
#include "MCD_dma.h"
#include "MCD_tasksInit.h"
#include "MCD_progCheck.h"
/********************************************************************/
/*
* This is an API-internal pointer to the DMA's registers
*/
dmaRegs *MCD_dmaBar;
/*
* These are the real and model task tables as generated by the
* build process
*/
extern TaskTableEntry MCD_realTaskTableSrc[NCHANNELS];
extern TaskTableEntry MCD_modelTaskTableSrc[NUMOFVARIANTS];
/*
* However, this (usually) gets relocated to on-chip SRAM, at which
* point we access them as these tables
*/
volatile TaskTableEntry *MCD_taskTable;
TaskTableEntry *MCD_modelTaskTable;
/*
* MCD_chStatus[] is an array of status indicators for remembering
* whether a DMA has ever been attempted on each channel, pausing
* status, etc.
*/
static int MCD_chStatus[NCHANNELS] =
{
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA
};
/*
* Prototypes for local functions
*/
static void MCD_memcpy (int *dest, int *src, u32 size);
static void MCD_resmActions (int channel);
/*
* Buffer descriptors used for storage of progress info for single Dmas
* Also used as storage for the DMA for CRCs for single DMAs
* Otherwise, the DMA does not parse these buffer descriptors
*/
#ifdef MCD_INCLUDE_EU
extern MCD_bufDesc MCD_singleBufDescs[NCHANNELS];
#else
MCD_bufDesc MCD_singleBufDescs[NCHANNELS];
#endif
MCD_bufDesc *MCD_relocBuffDesc;
/*
* Defines for the debug control register's functions
*/
#define DBG_CTL_COMP1_TASK (0x00002000) /* have comparator 1 look for a task # */
#define DBG_CTL_ENABLE (DBG_CTL_AUTO_ARM | \
DBG_CTL_BREAK | \
DBG_CTL_INT_BREAK | \
DBG_CTL_COMP1_TASK)
#define DBG_CTL_DISABLE (DBG_CTL_AUTO_ARM | \
DBG_CTL_INT_BREAK | \
DBG_CTL_COMP1_TASK)
#define DBG_KILL_ALL_STAT (0xFFFFFFFF)
/*
* Offset to context save area where progress info is stored
*/
#define CSAVE_OFFSET 10
/*
* Defines for Byte Swapping
*/
#define MCD_BYTE_SWAP_KILLER 0xFFF8888F
#define MCD_NO_BYTE_SWAP_ATALL 0x00040000
/*
* Execution Unit Identifiers
*/
#define MAC 0 /* legacy - not used */
#define LUAC 1 /* legacy - not used */
#define CRC 2 /* legacy - not used */
#define LURC 3 /* Logic Unit with CRC */
/*
* Task Identifiers
*/
#define TASK_CHAINNOEU 0
#define TASK_SINGLENOEU 1
#ifdef MCD_INCLUDE_EU
#define TASK_CHAINEU 2
#define TASK_SINGLEEU 3
#define TASK_FECRX 4
#define TASK_FECTX 5
#else
#define TASK_CHAINEU 0
#define TASK_SINGLEEU 1
#define TASK_FECRX 2
#define TASK_FECTX 3
#endif
/*
* Structure to remember which variant is on which channel
* TBD- need this?
*/
typedef struct MCD_remVariants_struct MCD_remVariant;
struct MCD_remVariants_struct
{
int remDestRsdIncr[NCHANNELS]; /* -1,0,1 */
int remSrcRsdIncr[NCHANNELS]; /* -1,0,1 */
s16 remDestIncr[NCHANNELS]; /* DestIncr */
s16 remSrcIncr[NCHANNELS]; /* srcIncr */
u32 remXferSize[NCHANNELS]; /* xferSize */
};
/*
* Structure to remember the startDma parameters for each channel
*/
MCD_remVariant MCD_remVariants;
/********************************************************************/
/*
* Function: MCD_initDma
* Purpose: Initializes the DMA API by setting up a pointer to the DMA
* registers, relocating and creating the appropriate task
* structures, and setting up some global settings
* Arguments:
* dmaBarAddr - pointer to the multichannel DMA registers
* taskTableDest - location to move DMA task code and structs to
* flags - operational parameters
* Return Value:
* MCD_TABLE_UNALIGNED if taskTableDest is not 512-byte aligned
* MCD_OK otherwise
*/
extern u32 MCD_funcDescTab0[];
int MCD_initDma (dmaRegs *dmaBarAddr, void *taskTableDest, u32 flags)
{
int i;
TaskTableEntry *entryPtr;
/* setup the local pointer to register set */
MCD_dmaBar = dmaBarAddr;
/* do we need to move/create a task table */
if ((flags & MCD_RELOC_TASKS) != 0)
{
int fixedSize;
u32 *fixedPtr;
/*int *tablePtr = taskTableDest;TBD*/
int varTabsOffset, funcDescTabsOffset, contextSavesOffset;
int taskDescTabsOffset;
int taskTableSize, varTabsSize, funcDescTabsSize, contextSavesSize;
int taskDescTabSize;
int i;
/* check if physical address is aligned on 512 byte boundary */
if (((u32)taskTableDest & 0x000001ff) != 0)
return(MCD_TABLE_UNALIGNED);
MCD_taskTable = taskTableDest; /* set up local pointer to task Table */
/*
* Create a task table:
* - compute aligned base offsets for variable tables and
* function descriptor tables, then
* - loop through the task table and setup the pointers
* - copy over model task table with the the actual task descriptor
* tables
*/
taskTableSize = NCHANNELS * sizeof(TaskTableEntry);
/* align variable tables to size */
varTabsOffset = taskTableSize + (u32)taskTableDest;
if ((varTabsOffset & (VAR_TAB_SIZE - 1)) != 0)
varTabsOffset = (varTabsOffset + VAR_TAB_SIZE) & (~VAR_TAB_SIZE);
/* align function descriptor tables */
varTabsSize = NCHANNELS * VAR_TAB_SIZE;
funcDescTabsOffset = varTabsOffset + varTabsSize;
if ((funcDescTabsOffset & (FUNCDESC_TAB_SIZE - 1)) != 0)
funcDescTabsOffset = (funcDescTabsOffset + FUNCDESC_TAB_SIZE) &
(~FUNCDESC_TAB_SIZE);
funcDescTabsSize = FUNCDESC_TAB_NUM * FUNCDESC_TAB_SIZE;
contextSavesOffset = funcDescTabsOffset + funcDescTabsSize;
contextSavesSize = (NCHANNELS * CONTEXT_SAVE_SIZE);
fixedSize = taskTableSize + varTabsSize + funcDescTabsSize +
contextSavesSize;
/* zero the thing out */
fixedPtr = (u32 *)taskTableDest;
for (i = 0;i<(fixedSize/4);i++)
fixedPtr[i] = 0;
entryPtr = (TaskTableEntry*)MCD_taskTable;
/* set up fixed pointers */
for (i = 0; i < NCHANNELS; i++)
{
entryPtr[i].varTab = (u32)varTabsOffset; /* update ptr to local value */
entryPtr[i].FDTandFlags = (u32)funcDescTabsOffset | MCD_TT_FLAGS_DEF;
entryPtr[i].contextSaveSpace = (u32)contextSavesOffset;
varTabsOffset += VAR_TAB_SIZE;
#ifdef MCD_INCLUDE_EU /* if not there is only one, just point to the same one */
funcDescTabsOffset += FUNCDESC_TAB_SIZE;
#endif
contextSavesOffset += CONTEXT_SAVE_SIZE;
}
/* copy over the function descriptor table */
for ( i = 0; i < FUNCDESC_TAB_NUM; i++)
{
MCD_memcpy((void*)(entryPtr[i].FDTandFlags & ~MCD_TT_FLAGS_MASK),
(void*)MCD_funcDescTab0, FUNCDESC_TAB_SIZE);
}
/* copy model task table to where the context saves stuff leaves off*/
MCD_modelTaskTable = (TaskTableEntry*)contextSavesOffset;
MCD_memcpy ((void*)MCD_modelTaskTable, (void*)MCD_modelTaskTableSrc,
NUMOFVARIANTS * sizeof(TaskTableEntry));
entryPtr = MCD_modelTaskTable; /* point to local version of
model task table */
taskDescTabsOffset = (u32)MCD_modelTaskTable +
(NUMOFVARIANTS * sizeof(TaskTableEntry));
/* copy actual task code and update TDT ptrs in local model task table */
for (i = 0; i < NUMOFVARIANTS; i++)
{
taskDescTabSize = entryPtr[i].TDTend - entryPtr[i].TDTstart + 4;
MCD_memcpy ((void*)taskDescTabsOffset, (void*)entryPtr[i].TDTstart, taskDescTabSize);
entryPtr[i].TDTstart = (u32)taskDescTabsOffset;
taskDescTabsOffset += taskDescTabSize;
entryPtr[i].TDTend = (u32)taskDescTabsOffset - 4;
}
#ifdef MCD_INCLUDE_EU /* Tack single DMA BDs onto end of code so API controls
where they are since DMA might write to them */
MCD_relocBuffDesc = (MCD_bufDesc*)(entryPtr[NUMOFVARIANTS - 1].TDTend + 4);
#else /* DMA does not touch them so they can be wherever and we don't need to
waste SRAM on them */
MCD_relocBuffDesc = MCD_singleBufDescs;
#endif
}
else
{
/* point the would-be relocated task tables and the
buffer descriptors to the ones the linker generated */
if (((u32)MCD_realTaskTableSrc & 0x000001ff) != 0)
return(MCD_TABLE_UNALIGNED);
/* need to add code to make sure that every thing else is aligned properly TBD*/
/* this is problematic if we init more than once or after running tasks,
need to add variable to see if we have aleady init'd */
entryPtr = MCD_realTaskTableSrc;
for (i = 0; i < NCHANNELS; i++)
{
if (((entryPtr[i].varTab & (VAR_TAB_SIZE - 1)) != 0) ||
((entryPtr[i].FDTandFlags & (FUNCDESC_TAB_SIZE - 1)) != 0))
return(MCD_TABLE_UNALIGNED);
}
MCD_taskTable = MCD_realTaskTableSrc;
MCD_modelTaskTable = MCD_modelTaskTableSrc;
MCD_relocBuffDesc = MCD_singleBufDescs;
}
/* Make all channels as totally inactive, and remember them as such: */
MCD_dmaBar->taskbar = (u32) MCD_taskTable;
for (i = 0; i < NCHANNELS; i++)
{
MCD_dmaBar->taskControl[i] = 0x0;
MCD_chStatus[i] = MCD_NO_DMA;
}
/* Set up pausing mechanism to inactive state: */
MCD_dmaBar->debugComp1 = 0; /* no particular values yet for either comparator registers */
MCD_dmaBar->debugComp2 = 0;
MCD_dmaBar->debugControl = DBG_CTL_DISABLE;
MCD_dmaBar->debugStatus = DBG_KILL_ALL_STAT;
/* enable or disable commbus prefetch, really need an ifdef or
something to keep from trying to set this in the 8220 */
if ((flags & MCD_COMM_PREFETCH_EN) != 0)
MCD_dmaBar->ptdControl &= ~PTD_CTL_COMM_PREFETCH;
else
MCD_dmaBar->ptdControl |= PTD_CTL_COMM_PREFETCH;
return(MCD_OK);
}
/*********************** End of MCD_initDma() ***********************/
/********************************************************************/
/* Function: MCD_dmaStatus
* Purpose: Returns the status of the DMA on the requested channel
* Arguments: channel - channel number
* Returns: Predefined status indicators
*/
int MCD_dmaStatus (int channel)
{
u16 tcrValue;
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
tcrValue = MCD_dmaBar->taskControl[channel];
if ((tcrValue & TASK_CTL_EN) == 0)
{ /* nothing running */
/* if last reported with task enabled */
if ( MCD_chStatus[channel] == MCD_RUNNING
|| MCD_chStatus[channel] == MCD_IDLE)
MCD_chStatus[channel] = MCD_DONE;
}
else /* something is running */
{
/* There are three possibilities: paused, running or idle. */
if ( MCD_chStatus[channel] == MCD_RUNNING
|| MCD_chStatus[channel] == MCD_IDLE)
{
MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT;
/* This register is selected to know which initiator is
actually asserted. */
if ((MCD_dmaBar->ptdDebug >> channel ) & 0x1 )
MCD_chStatus[channel] = MCD_RUNNING;
else
MCD_chStatus[channel] = MCD_IDLE;
/* do not change the status if it is already paused. */
}
}
return MCD_chStatus[channel];
}
/******************** End of MCD_dmaStatus() ************************/
/********************************************************************/
/* Function: MCD_startDma
* Ppurpose: Starts a particular kind of DMA
* Arguments: see below
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*/
int MCD_startDma (
int channel, /* the channel on which to run the DMA */
s8 *srcAddr, /* the address to move data from, or physical buffer-descriptor address */
s16 srcIncr, /* the amount to increment the source address per transfer */
s8 *destAddr, /* the address to move data to */
s16 destIncr, /* the amount to increment the destination address per transfer */
u32 dmaSize, /* the number of bytes to transfer independent of the transfer size */
u32 xferSize, /* the number bytes in of each data movement (1, 2, or 4) */
u32 initiator, /* what device initiates the DMA */
int priority, /* priority of the DMA */
u32 flags, /* flags describing the DMA */
u32 funcDesc /* a description of byte swapping, bit swapping, and CRC actions */
#ifdef MCD_NEED_ADDR_TRANS
s8 *srcAddrVirt /* virtual buffer descriptor address TBD*/
#endif
)
{
int srcRsdIncr, destRsdIncr;
int *cSave;
short xferSizeIncr;
int tcrCount = 0;
#ifdef MCD_INCLUDE_EU
u32 *realFuncArray;
#endif
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
/* tbd - need to determine the proper response to a bad funcDesc when not
including EU functions, for now, assign a benign funcDesc, but maybe
should return an error */
#ifndef MCD_INCLUDE_EU
funcDesc = MCD_FUNC_NOEU1;
#endif
#ifdef MCD_DEBUG
printf("startDma:Setting up params\n");
#endif
/* Set us up for task-wise priority. We don't technically need to do this on every start, but
since the register involved is in the same longword as other registers that users are in control
of, setting it more than once is probably preferable. That since the documentation doesn't seem
to be completely consistent about the nature of the PTD control register. */
MCD_dmaBar->ptdControl |= (u16) 0x8000;
#if 1 /* Not sure what we need to keep here rtm TBD */
/* Calculate additional parameters to the regular DMA calls. */
srcRsdIncr = srcIncr < 0 ? -1 : (srcIncr > 0 ? 1 : 0);
destRsdIncr = destIncr < 0 ? -1 : (destIncr > 0 ? 1 : 0);
xferSizeIncr = (xferSize & 0xffff) | 0x20000000;
/* Remember for each channel which variant is running. */
MCD_remVariants.remSrcRsdIncr[channel] = srcRsdIncr;
MCD_remVariants.remDestRsdIncr[channel] = destRsdIncr;
MCD_remVariants.remDestIncr[channel] = destIncr;
MCD_remVariants.remSrcIncr[channel] = srcIncr;
MCD_remVariants.remXferSize[channel] = xferSize;
#endif
cSave = (int*)(MCD_taskTable[channel].contextSaveSpace) + CSAVE_OFFSET + CURRBD;
#ifdef MCD_INCLUDE_EU /* may move this to EU specific calls */
realFuncArray = (u32 *) (MCD_taskTable[channel].FDTandFlags & 0xffffff00);
/* Modify the LURC's normal and byte-residue-loop functions according to parameter. */
realFuncArray[(LURC*16)] = xferSize == 4 ?
funcDesc : xferSize == 2 ?
funcDesc & 0xfffff00f : funcDesc & 0xffff000f;
realFuncArray[(LURC*16+1)] = (funcDesc & MCD_BYTE_SWAP_KILLER) | MCD_NO_BYTE_SWAP_ATALL;
#endif
/* Write the initiator field in the TCR, and also set the initiator-hold
bit. Note that,due to a hardware quirk, this could collide with an
MDE access to the initiator-register file, so we have to verify that the write
reads back correctly. */
MCD_dmaBar->taskControl[channel] =
(initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM;
while(((MCD_dmaBar->taskControl[channel] & 0x1fff) !=
((initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM)) &&
(tcrCount < 1000))
{
tcrCount++;
/*MCD_dmaBar->ptd_tcr[channel] = (initiator << 8) | 0x0020;*/
MCD_dmaBar->taskControl[channel] =
(initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM;
}
MCD_dmaBar->priority[channel] = (u8)priority & PRIORITY_PRI_MASK;
/* should be albe to handle this stuff with only one write to ts reg - tbd */
if (channel < 8 && channel >= 0)
{
MCD_dmaBar->taskSize0 &= ~(0xf << (7-channel)*4);
MCD_dmaBar->taskSize0 |= (xferSize & 3) << (((7 - channel)*4) + 2);
MCD_dmaBar->taskSize0 |= (xferSize & 3) << ((7 - channel)*4);
}
else
{
MCD_dmaBar->taskSize1 &= ~(0xf << (15-channel)*4);
MCD_dmaBar->taskSize1 |= (xferSize & 3) << (((15 - channel)*4) + 2);
MCD_dmaBar->taskSize1 |= (xferSize & 3) << ((15 - channel)*4);
}
/* setup task table flags/options which mostly control the line buffers */
MCD_taskTable[channel].FDTandFlags &= ~MCD_TT_FLAGS_MASK;
MCD_taskTable[channel].FDTandFlags |= (MCD_TT_FLAGS_MASK & flags);
if (flags & MCD_FECTX_DMA)
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_FECTX].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_FECTX].TDTend;
MCD_startDmaENetXmit(srcAddr, srcAddr, destAddr, MCD_taskTable, channel);
}
else if (flags & MCD_FECRX_DMA)
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_FECRX].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_FECRX].TDTend;
MCD_startDmaENetRcv(srcAddr, srcAddr, destAddr, MCD_taskTable, channel);
}
else if(flags & MCD_SINGLE_DMA)
{
/* this buffer descriptor is used for storing off initial parameters for later
progress query calculation and for the DMA to write the resulting checksum
The DMA does not use this to determine how to operate, that info is passed
with the init routine*/
MCD_relocBuffDesc[channel].srcAddr = srcAddr;
MCD_relocBuffDesc[channel].destAddr = destAddr;
MCD_relocBuffDesc[channel].lastDestAddr = destAddr; /* definitely not its final value */
MCD_relocBuffDesc[channel].dmaSize = dmaSize;
MCD_relocBuffDesc[channel].flags = 0; /* not used */
MCD_relocBuffDesc[channel].csumResult = 0; /* not used */
MCD_relocBuffDesc[channel].next = 0; /* not used */
/* Initialize the progress-querying stuff to show no progress:*/
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET] = (int)srcAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET] = (int)destAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET] =
(u32) &(MCD_relocBuffDesc[channel]);
/* tbd - need to keep the user from trying to call the EU routine
when MCD_INCLUDE_EU is not defined */
if( funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2)
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_SINGLENOEU].TDTend;
MCD_startDmaSingleNoEu(srcAddr, srcIncr, destAddr, destIncr, dmaSize,
xferSizeIncr, flags, (int *)&(MCD_relocBuffDesc[channel]), cSave,
MCD_taskTable, channel);
}
else
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_SINGLEEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_SINGLEEU].TDTend;
MCD_startDmaSingleEu(srcAddr, srcIncr, destAddr, destIncr, dmaSize,
xferSizeIncr, flags, (int *)&(MCD_relocBuffDesc[channel]), cSave,
MCD_taskTable, channel);
}
}
else
{ /* chained DMAS */
/* Initialize the progress-querying stuff to show no progress:*/
#if 1 /* (!defined(MCD_NEED_ADDR_TRANS)) */
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddr)->srcAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddr)->destAddr;
#else /* if using address translation, need the virtual addr of the first buffdesc */
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddrVirt)->srcAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddrVirt)->destAddr;
#endif
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET] = (u32) srcAddr;
if( funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2)
{
/*TDTStart and TDTEnd*/
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_CHAINNOEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_CHAINNOEU].TDTend;
MCD_startDmaChainNoEu((int *)srcAddr, srcIncr, destIncr, xferSize,
xferSizeIncr, cSave, MCD_taskTable, channel);
}
else
{
/*TDTStart and TDTEnd*/
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_CHAINEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_CHAINEU].TDTend;
MCD_startDmaChainEu((int *)srcAddr, srcIncr, destIncr, xferSize,
xferSizeIncr, cSave, MCD_taskTable, channel);
}
}
MCD_chStatus[channel] = MCD_IDLE;
return(MCD_OK);
}
/************************ End of MCD_startDma() *********************/
/********************************************************************/
/* Function: MCD_XferProgrQuery
* Purpose: Returns progress of DMA on requested channel
* Arguments: channel - channel to retrieve progress for
* progRep - pointer to user supplied MCD_XferProg struct
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*
* Notes:
* MCD_XferProgrQuery() upon completing or after aborting a DMA, or
* while the DMA is in progress, this function returns the first
* DMA-destination address not (or not yet) used in the DMA. When
* encountering a non-ready buffer descriptor, the information for
* the last completed descriptor is returned.
*
* MCD_XferProgQuery() has to avoid the possibility of getting
* partially-updated information in the event that we should happen
* to query DMA progress just as the DMA is updating it. It does that
* by taking advantage of the fact context is not saved frequently for
* the most part. We therefore read it at least twice until we get the
* same information twice in a row.
*
* Because a small, but not insignificant, amount of time is required
* to write out the progress-query information, especially upon
* completion of the DMA, it would be wise to guarantee some time lag
* between successive readings of the progress-query information.
*/
/*
* How many iterations of the loop below to execute to stabilize values
*/
#define STABTIME 0
int MCD_XferProgrQuery (int channel, MCD_XferProg *progRep)
{
MCD_XferProg prevRep;
int again; /* true if we are to try again to get consistent results */
int i; /* used as a time-waste counter */
int destDiffBytes; /* Total number of bytes that we think actually got xfered. */
int numIterations; /* number of iterations */
int bytesNotXfered; /* bytes that did not get xfered. */
s8 *LWAlignedInitDestAddr, *LWAlignedCurrDestAddr;
int subModVal, addModVal; /* Mode values to added and subtracted from the
final destAddr */
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
/* Read a trial value for the progress-reporting values*/
prevRep.lastSrcAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET];
prevRep.lastDestAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET];
prevRep.dmaSize = ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET];
prevRep.currBufDesc =
(MCD_bufDesc*) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET];
/* Repeatedly reread those values until they match previous values: */
do {
/* Waste a little bit of time to ensure stability: */
for (i = 0; i < STABTIME; i++)
i += i >> 2; /* make sure this loop does something so that it doesn't get optimized out */
/* Check them again: */
progRep->lastSrcAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET];
progRep->lastDestAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET];
progRep->dmaSize = ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET];
progRep->currBufDesc =
(MCD_bufDesc*) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET];
/* See if they match: */
if ( prevRep.lastSrcAddr != progRep->lastSrcAddr
|| prevRep.lastDestAddr != progRep->lastDestAddr
|| prevRep.dmaSize != progRep->dmaSize
|| prevRep.currBufDesc != progRep->currBufDesc)
{
/* If they don't match, remember previous values and try again:*/
prevRep.lastSrcAddr = progRep->lastSrcAddr;
prevRep.lastDestAddr = progRep->lastDestAddr;
prevRep.dmaSize = progRep->dmaSize;
prevRep.currBufDesc = progRep->currBufDesc;
again = MCD_TRUE;
}
else
again = MCD_FALSE;
} while (again == MCD_TRUE);
/* Update the dCount, srcAddr and destAddr */
/* To calculate dmaCount, we consider destination address. C
overs M1,P1,Z for destination */
switch(MCD_remVariants.remDestRsdIncr[channel]) {
case MINUS1:
subModVal = ((int)progRep->lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
addModVal = ((int)progRep->currBufDesc->destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - addModVal;
LWAlignedCurrDestAddr = (progRep->lastDestAddr) - subModVal;
destDiffBytes = LWAlignedInitDestAddr - LWAlignedCurrDestAddr;
bytesNotXfered = (destDiffBytes/MCD_remVariants.remDestIncr[channel]) *
( MCD_remVariants.remDestIncr[channel]
+ MCD_remVariants.remXferSize[channel]);
progRep->dmaSize = destDiffBytes - bytesNotXfered + addModVal - subModVal;
break;
case ZERO:
progRep->lastDestAddr = progRep->currBufDesc->destAddr;
break;
case PLUS1:
/* This value has to be subtracted from the final calculated dCount. */
subModVal = ((int)progRep->currBufDesc->destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
/* These bytes are already in lastDestAddr. */
addModVal = ((int)progRep->lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - subModVal;
LWAlignedCurrDestAddr = (progRep->lastDestAddr) - addModVal;
destDiffBytes = (progRep->lastDestAddr - LWAlignedInitDestAddr);
numIterations = ( LWAlignedCurrDestAddr - LWAlignedInitDestAddr)/MCD_remVariants.remDestIncr[channel];
bytesNotXfered = numIterations *
( MCD_remVariants.remDestIncr[channel]
- MCD_remVariants.remXferSize[channel]);
progRep->dmaSize = destDiffBytes - bytesNotXfered - subModVal;
break;
default:
break;
}
/* This covers M1,P1,Z for source */
switch(MCD_remVariants.remSrcRsdIncr[channel]) {
case MINUS1:
progRep->lastSrcAddr =
progRep->currBufDesc->srcAddr +
( MCD_remVariants.remSrcIncr[channel] *
(progRep->dmaSize/MCD_remVariants.remXferSize[channel]));
break;
case ZERO:
progRep->lastSrcAddr = progRep->currBufDesc->srcAddr;
break;
case PLUS1:
progRep->lastSrcAddr =
progRep->currBufDesc->srcAddr +
( MCD_remVariants.remSrcIncr[channel] *
(progRep->dmaSize/MCD_remVariants.remXferSize[channel]));
break;
default: break;
}
return(MCD_OK);
}
/******************* End of MCD_XferProgrQuery() ********************/
/********************************************************************/
/* MCD_resmActions() does the majority of the actions of a DMA resume.
* It is called from MCD_killDma() and MCD_resumeDma(). It has to be
* a separate function because the kill function has to negate the task
* enable before resuming it, but the resume function has to do nothing
* if there is no DMA on that channel (i.e., if the enable bit is 0).
*/
static void MCD_resmActions (int channel)
{
MCD_dmaBar->debugControl = DBG_CTL_DISABLE;
MCD_dmaBar->debugStatus = MCD_dmaBar->debugStatus;
MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; /* This register is selected to know
which initiator is actually asserted. */
if((MCD_dmaBar->ptdDebug >> channel ) & 0x1)
MCD_chStatus[channel] = MCD_RUNNING;
else
MCD_chStatus[channel] = MCD_IDLE;
}
/********************* End of MCD_resmActions() *********************/
/********************************************************************/
/* Function: MCD_killDma
* Purpose: Halt the DMA on the requested channel, without any
* intention of resuming the DMA.
* Arguments: channel - requested channel
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*
* Notes:
* A DMA may be killed from any state, including paused state, and it
* always goes to the MCD_HALTED state even if it is killed while in
* the MCD_NO_DMA or MCD_IDLE states.
*/
int MCD_killDma (int channel)
{
/* MCD_XferProg progRep; */
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
MCD_dmaBar->taskControl[channel] = 0x0;
MCD_resumeDma (channel);
/*
* This must be after the write to the TCR so that the task doesn't
* start up again momentarily, and before the status assignment so
* as to override whatever MCD_resumeDma() may do to the channel
* status.
*/
MCD_chStatus[channel] = MCD_HALTED;
/*
* Update the current buffer descriptor's lastDestAddr field
*
* MCD_XferProgrQuery (channel, &progRep);
* progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr;
*/
return(MCD_OK);
}
/************************ End of MCD_killDma() **********************/
/********************************************************************/
/* Function: MCD_continDma
* Purpose: Continue a DMA which as stopped due to encountering an
* unready buffer descriptor.
* Arguments: channel - channel to continue the DMA on
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*
* Notes:
* This routine does not check to see if there is a task which can
* be continued. Also this routine should not be used with single DMAs.
*/
int MCD_continDma (int channel)
{
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
MCD_dmaBar->taskControl[channel] |= TASK_CTL_EN;
MCD_chStatus[channel] = MCD_RUNNING;
return(MCD_OK);
}
/********************** End of MCD_continDma() **********************/
/*********************************************************************
* MCD_pauseDma() and MCD_resumeDma() below use the DMA's debug unit
* to freeze a task and resume it. We freeze a task by breakpointing
* on the stated task. That is, not any specific place in the task,
* but any time that task executes. In particular, when that task
* executes, we want to freeze that task and only that task.
*
* The bits of the debug control register influence interrupts vs.
* breakpoints as follows:
* - Bits 14 and 0 enable or disable debug functions. If enabled, you
* will get the interrupt but you may or may not get a breakpoint.
* - Bits 2 and 1 decide whether you also get a breakpoint in addition
* to an interrupt.
*
* The debug unit can do these actions in response to either internally
* detected breakpoint conditions from the comparators, or in response
* to the external breakpoint pin, or both.
* - Bits 14 and 1 perform the above-described functions for
* internally-generated conditions, i.e., the debug comparators.
* - Bits 0 and 2 perform the above-described functions for external
* conditions, i.e., the breakpoint external pin.
*
* Note that, although you "always" get the interrupt when you turn
* the debug functions, the interrupt can nevertheless, if desired, be
* masked by the corresponding bit in the PTD's IMR. Note also that
* this means that bits 14 and 0 must enable debug functions before
* bits 1 and 2, respectively, have any effect.
*
* NOTE: It's extremely important to not pause more than one DMA channel
* at a time.
********************************************************************/
/********************************************************************/
/* Function: MCD_pauseDma
* Purpose: Pauses the DMA on a given channel (if any DMA is running
* on that channel).
* Arguments: channel
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*/
int MCD_pauseDma (int channel)
{
/* MCD_XferProg progRep; */
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN)
{
MCD_dmaBar->debugComp1 = channel;
MCD_dmaBar->debugControl = DBG_CTL_ENABLE | (1 << (channel + 16));
MCD_chStatus[channel] = MCD_PAUSED;
/*
* Update the current buffer descriptor's lastDestAddr field
*
* MCD_XferProgrQuery (channel, &progRep);
* progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr;
*/
}
return(MCD_OK);
}
/************************* End of MCD_pauseDma() ********************/
/********************************************************************/
/* Function: MCD_resumeDma
* Purpose: Resumes the DMA on a given channel (if any DMA is
* running on that channel).
* Arguments: channel - channel on which to resume DMA
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*/
int MCD_resumeDma (int channel)
{
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN)
MCD_resmActions (channel);
return(MCD_OK);
}
/************************ End of MCD_resumeDma() ********************/
/********************************************************************/
/* Function: MCD_csumQuery
* Purpose: Provide the checksum after performing a non-chained DMA
* Arguments: channel - channel to report on
* csum - pointer to where to write the checksum/CRC
* Returns: MCD_ERROR if the channel is invalid, else MCD_OK
*
* Notes:
*
*/
int MCD_csumQuery (int channel, u32 *csum)
{
#ifdef MCD_INCLUDE_EU
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
*csum = MCD_relocBuffDesc[channel].csumResult;
return(MCD_OK);
#else
return(MCD_ERROR);
#endif
}
/*********************** End of MCD_resumeDma() *********************/
/********************************************************************/
/* Function: MCD_getCodeSize
* Purpose: Provide the size requirements of the microcoded tasks
* Returns: Size in bytes
*/
int MCD_getCodeSize(void)
{
#ifdef MCD_INCLUDE_EU
return(0x2b5c);
#else
return(0x173c);
#endif
}
/********************** End of MCD_getCodeSize() ********************/
/********************************************************************/
/* Function: MCD_getVersion
* Purpose: Provide the version string and number
* Arguments: longVersion - user supplied pointer to a pointer to a char
* which points to the version string
* Returns: Version number and version string (by reference)
*/
char MCD_versionString[] = "Multi-channel DMA API Alpha v0.3 (2004-04-26)";
#define MCD_REV_MAJOR 0x00
#define MCD_REV_MINOR 0x03
int MCD_getVersion(char **longVersion)
{
*longVersion = MCD_versionString;
return((MCD_REV_MAJOR << 8) | MCD_REV_MINOR);
}
/********************** End of MCD_getVersion() *********************/
/********************************************************************/
/* Private version of memcpy()
* Note that everything this is used for is longword-aligned.
*/
static void MCD_memcpy (int *dest, int *src, u32 size)
{
u32 i;
for (i = 0; i < size; i += sizeof(int), dest++, src++)
*dest = *src;
}
/********************************************************************/

2449
mcdapirev0p3/MCD_tasks.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,224 @@
/*
* File: MCD_tasksInit.c
* Purpose: Functions for initializing variable tables of different
* types of tasks.
*
* Notes:
*/
/*
* Do not edit!
*/
#include "MCD_dma.h"
extern dmaRegs *MCD_dmaBar;
/*
* Task 0
*/
void MCD_startDmaChainNoEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 2, (u32)currBD); /* var[2] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 11, (u32)xferSize); /* var[11] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 3, (u32)0x00000000); /* var[3] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000000); /* var[12] */
MCD_SET_VAR(taskTable+channel, 13, (u32)0x80000000); /* var[13] */
MCD_SET_VAR(taskTable+channel, 14, (u32)0x00000010); /* var[14] */
MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000004); /* var[15] */
MCD_SET_VAR(taskTable+channel, 16, (u32)0x08000000); /* var[16] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000000); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000001); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x40000000); /* inc[6] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 1
*/
void MCD_startDmaSingleNoEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 7, (u32)srcAddr); /* var[7] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)destAddr); /* var[2] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 3, (u32)dmaSize); /* var[3] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 5, (u32)flags); /* var[5] */
MCD_SET_VAR(taskTable+channel, 1, (u32)currBD); /* var[1] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000004); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x08000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000001); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x40000000); /* inc[5] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 2
*/
void MCD_startDmaChainEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 12, (u32)xferSize); /* var[12] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 11, (u32)0x00000000); /* var[11] */
MCD_SET_VAR(taskTable+channel, 13, (u32)0x00000000); /* var[13] */
MCD_SET_VAR(taskTable+channel, 14, (u32)0x80000000); /* var[14] */
MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000010); /* var[15] */
MCD_SET_VAR(taskTable+channel, 16, (u32)0x00000001); /* var[16] */
MCD_SET_VAR(taskTable+channel, 17, (u32)0x00000004); /* var[17] */
MCD_SET_VAR(taskTable+channel, 18, (u32)0x08000000); /* var[18] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000000); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0xc0000000); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x80000001); /* inc[6] */
MCD_SET_VAR(taskTable+channel, 31, (u32)0x40000000); /* inc[7] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 3
*/
void MCD_startDmaSingleEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 8, (u32)srcAddr); /* var[8] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 3, (u32)destAddr); /* var[3] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 4, (u32)dmaSize); /* var[4] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 6, (u32)flags); /* var[6] */
MCD_SET_VAR(taskTable+channel, 2, (u32)currBD); /* var[2] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000001); /* var[10] */
MCD_SET_VAR(taskTable+channel, 11, (u32)0x00000004); /* var[11] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x08000000); /* var[12] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0xc0000000); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000000); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x80000001); /* inc[6] */
MCD_SET_VAR(taskTable+channel, 31, (u32)0x40000000); /* inc[7] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 4
*/
void MCD_startDmaENetRcv(char *bDBase, char *currBD, char *rcvFifoPtr, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 0, (u32)bDBase); /* var[0] */
MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */
MCD_SET_VAR(taskTable+channel, 6, (u32)rcvFifoPtr); /* var[6] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x0000ffff); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x30000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 11, (u32)0x0fffffff); /* var[11] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000008); /* var[12] */
MCD_SET_VAR(taskTable+channel, 24, (u32)0x00000000); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 25, (u32)0x60000000); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 26, (u32)0x20000004); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x40000000); /* inc[3] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 5
*/
void MCD_startDmaENetXmit(char *bDBase, char *currBD, char *xmitFifoPtr, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 0, (u32)bDBase); /* var[0] */
MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */
MCD_SET_VAR(taskTable+channel, 11, (u32)xmitFifoPtr); /* var[11] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000000); /* var[12] */
MCD_SET_VAR(taskTable+channel, 13, (u32)0x0000ffff); /* var[13] */
MCD_SET_VAR(taskTable+channel, 14, (u32)0xffffffff); /* var[14] */
MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000004); /* var[15] */
MCD_SET_VAR(taskTable+channel, 16, (u32)0x00000008); /* var[16] */
MCD_SET_VAR(taskTable+channel, 24, (u32)0x00000000); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 25, (u32)0x60000000); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 26, (u32)0x40000000); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0xc000fffc); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0xe0000004); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000000); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x4000ffff); /* inc[6] */
MCD_SET_VAR(taskTable+channel, 31, (u32)0xe0000001); /* inc[7] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}

Binary file not shown.

View File

@@ -0,0 +1,26 @@
Multi-channel DMA API Release Notes
Version 0.3
* MCD_INCLUDE_EU functionality supported(microcode changes for all tasks
except ethernet).
* Fixed bug when using MCD_END_FRAME which would cause the DMA to transfer
zero bytes and then complete.
* Code cleanup.
Version 0.2 (Slight Update)
* Modified casts and task table implementations that were causing
warnings (and even errors on certain compilers)
* Cosmetic changes to clean up MCD_dmaApi.c and MCD_dma.h
* Fixed table declarations so that MCD_tasks.c will compile if
MCD_INCLUDE_EU is defined (Note: EU functionality still not supported)
Version 0.1 (Initial release)
Alpha version
MCD_INCLUDE_EU functionality not supported.
MCD_INCLUDE_JBIG not supported.

152
readme.txt Normal file
View File

@@ -0,0 +1,152 @@
//------------------------------------------------------------------------
// Readme.txt
//------------------------------------------------------------------------
This project is configure to get you up and running quickly using
CodeWarrior with the Freescale MCF5475 board.
This project provides full support for the selected board.
The created project provides Standard IO Support through console and terminal window.
Sample code for the following language:
- C
//------------------------------------------------------------------------
// Memory Maps
//------------------------------------------------------------------------
The Hardware has the following memory map:
# MCF5484 Derivative Memory map definitions from linker command files:
# __MBAR, __MMUBAR, __RAMBAR0, __RAMBAR0_SIZE, __RAMBAR1, __RAMBAR1_SIZE
# linker symbols must be defined in the linker command file.
# Memory mapped registers
___MBAR = 0x10000000;
___MMUBAR = 0x11000000;
# 4KB on-chip Core SRAM0
___RAMBAR0 = 0x20000000;
___RAMBAR0_SIZE = 0x00001000;
# 4KB on-chip Core SRAM1
___RAMBAR1 = 0x20001000;
___RAMBAR1_SIZE = 0x00001000;
# 32KB on-chip System SRAM
___SYS_SRAM = 0x10010000;
___SYS_SRAM_SIZE = 0x00008000;
//------------------------------------------------------------------------
// Project Structure
//------------------------------------------------------------------------
The project generated contains various files/groups:
- readme.txt: information for this project
- Sources: application source codes, user customizable startup
code, uart library, exception table
- Includes: derivative and board header files, ...
- Libs: runtime and libs
- Project Settings: linker command files for the different build
targets, the initialization and memory configuration files for
the hardware debugging, the common startup code, etc...
//------------------------------------------------------------------------
// Build Targets
//------------------------------------------------------------------------
- INTERNAL_RAM:
This project target is setup to load and debug code from internal RAM.
It should be used during your application development.
This is the very basic project that outputs to the UART.
You needs to connect a Terminal Program to see the output.
===================================================================
WARNING regarding debugging new project wizard code with CCS-SIM
===================================================================
The CCS-SIM is an instruction set simulator, it does not implement
any peripherals.
The new project generated by the wizard are using startup code
performing some hardware peripheral initializations.
When debugging with the CCS-SIM it might happen that the simulation
stuck on loop using non implemented peripheral register flag as
condition (PLL initialization as example).
In this case, you should either:
- move the PC to next statement
- use a skip point
- define a simulator specific macro which used when define allos you
to comment out the unwanted code in order to debug with CCS-SIM
===================================================================
WARNING regarding code located in RAM
===================================================================
Many possible ColdFire target processors have an external bus, so
you can use large external RAM devices for debugging applications
during development. But some processors do not have an external
bus, so you must accommodate applications in on-chip memory.
Although this on-chip RAM accommodates this CodeWarrior project,
it probably is too small for full development of your application.
Accordingly, for a processor without external bus, you should locate
your applications in flash memory.
//------------------------------------------------------------------------
// Flashing the code
//------------------------------------------------------------------------
1. Select the appropriate project target and build it
2. Make sure the correct remote connection is selected in the Remote
Connection debugger panel
3. In the CodeWarrior IDE menu, select Project > Set Default Project
and select your project
4. In the CodeWarrior IDE menu, select Project > Set Default Target
and select the project target that has the code you want to flash
5. In the CodeWarrior IDE menu, select Tools > Flash Programmer
6. Go to the flash programmer Target Configuration panel, click Load
Settings
7. Browse to the <your project location>\cfg sub folder and
select the flash settings xml file matching your build target
8. Check that Use Custom Settings checkbox is not selected
9. Go to the Erase/Blank Check panel, select the All Sectors option and
click Erase
10. Go to Program/Verify panel, click Program
11. Your code should now be flashed
//------------------------------------------------------------------------
// Terminal Settings
//------------------------------------------------------------------------
In case the UART is supported, the terminal should be setup with:
- 19200 bauds,
- 8 data bits,
- no parity,
- 1 stop bit,
- no flow control.
Please check this file in the project.
//------------------------------------------------------------------------
// Getting Started
//------------------------------------------------------------------------
To build/debug your project, use the CodeWarrior IDE menu Project > Debug
or press F5. This will launch the debugger. Press again F5 in the
debugger (or the CodeWarrior IDE menu Project > Run) to start the
application. The CodeWarrior IDE menu Project > Break stops the
application.
//------------------------------------------------------------------------
// Adding your own code
//------------------------------------------------------------------------
Once everything is working as expected, you can begin adding your own code
to the project. Keep in mind that we provide this as an example of how to
get up and running quickly with CodeWarrior. There are certainly other
ways to handle interrupts and set up your linker command file. Feel free
to modify any of the source files provided.
//------------------------------------------------------------------------
// Additional documentation
//------------------------------------------------------------------------
Read the online documentation provided. In CodeWarrior IDE menu, select
Help > CodeWarrior Help.
//------------------------------------------------------------------------
// Contacting Freescale
//------------------------------------------------------------------------
For bug reports, technical questions, and suggestions, please use the
forms installed in the Release_Notes folder.

View File

@@ -7,8 +7,12 @@
#include "MCF5475.h"
#include "startcf.h"
extern unsigned long far __SP_AFTER_RESET[];
extern unsigned long far __Bas_base[];
#include "MCD_dma.h"
#define MBAR_BASE_ADRS 0xff000000
#define MMAP_DMA 0x00008000
#define MMAP_SRAM 0x00010000
extern unsigned long far __SDRAM_SIZE;
/* imported routines */
extern int mmu_init();
@@ -27,11 +31,12 @@ void warte_10ms(void)
{
warte_10ms:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #1320000,d0
move.l #1330000,d0
move.l d0,MCF_SLT0_STCNT
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.b MCF_SLT0_SSR,d0
btst.b #0,d0
beq warte_d6
move.l (sp)+,d0
}
}
@@ -42,11 +47,12 @@ void warte_1ms(void)
{
warte_1ms:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #132000,d0
move.l #133000,d0
move.l d0,MCF_SLT0_STCNT
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.b MCF_SLT0_SSR,d0
btst.b #0,d0
beq warte_d6
move.l (sp)+,d0
}
}
@@ -57,11 +63,12 @@ void warte_100us(void)
{
warte_100us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #13200,d0
move.l #13300,d0
move.l d0,MCF_SLT0_STCNT
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.b MCF_SLT0_SSR,d0
btst.b #0,d0
beq warte_d6
move.l (sp)+,d0
}
}
@@ -72,11 +79,12 @@ void warte_50us(void)
{
warte_50us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #6600,d0
move.l #6650,d0
move.l d0,MCF_SLT0_STCNT
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.b MCF_SLT0_SSR,d0
btst.b #0,d0
beq warte_d6
move.l (sp)+,d0
}
}
@@ -86,11 +94,12 @@ void warte_10us(void)
{
warte_10us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #1320,d0
move.l #1330,d0
move.l d0,MCF_SLT0_STCNT
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.b MCF_SLT0_SSR,d0
btst.b #0,d0
beq warte_d6
move.l (sp)+,d0
}
}
@@ -101,20 +110,27 @@ void warte_1us(void)
{
warte_1us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #132,d0
move.l #133,d0
move.l d0,MCF_SLT0_STCNT
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.b MCF_SLT0_SSR,d0
btst.b #0,d0
beq warte_d6
move.l (sp)+,d0
}
}
/********************************************************************/
#define ide_dma_tnr 7
void BaS(void)
{
/*********************************************/
// SD-Card abfragen
int az_sectors;
int sd_status,i;
int dma_init_status,dma_run_status,dma_status;
az_sectors = sd_card_init();
@@ -122,12 +138,15 @@ void BaS(void)
{
sd_card_idle();
}
/*********************************************/
// FireTOS laden?
asm
{
move.b DIP_SWITCH,d0 // dip schalter adresse
{
move.b DIP_SWITCH,d0
btst.b #6,d0
beq firetos_kopieren
/**************************************/
// PIC initieren und daten anfordern
lea MCF_PSC0_PSCTB_8BIT,a6
lea MCF_PSC3_PSCTB_8BIT,a3
lea MCF_PSC3_PSCRB_8BIT,a4
@@ -141,8 +160,10 @@ void BaS(void)
move.b d1,(a6)
move.b (a4),d2
move.b d2,(a6)
move.l #0x0a0d,(a6)
move.b #0x01,(a3) // RTC DATEN ANFORDERN
move.l #'OK!',(a6)
move.l #0x0a0d,(a6)
/**************************************/
// TOS kopieren
lea 0x00e00000,a0
lea 0xe0600000,a1 // default tos
@@ -155,6 +176,13 @@ firetos_kopieren:
lea 0xe0400000,a1
lea 0xe0500000,a2 // 1MB
cptos_loop:
move.l (a1)+,(a0)+
move.l (a1)+,(a0)+
move.l (a1)+,(a0)+
move.l (a1)+,(a0)+
move.l (a1)+,(a0)+
move.l (a1)+,(a0)+
move.l (a1)+,(a0)+
move.l (a1)+,(a0)+
cmp.l a2,a1
blt cptos_loop
@@ -165,7 +193,7 @@ div_inits:
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
beq video_setup
// rtc daten, mmu set, etc nur wenn switch 6 = off
// rtc daten laden, mmu set, etc nur wenn switch 6 = off -> kein init wenn FireTOS
lea 0xffff8961,a0
clr.l d1
moveq #64,d2
@@ -179,13 +207,11 @@ loop_sr:
addq.l #1,d1
cmp.b d1,d2
bne loop_sr
/*
// Set the NVRAM checksum as invalid
move.b #63,(a0)
move.b 2(a0),d0
add #1,d0
move.b d0,2(a0)
*/
not_rtc:
bsr mmu_init
bsr vec_init
@@ -221,33 +247,9 @@ not_rtc:
nop
nop
/********************************************************************/
/* IDE reset
/********************************************************************/
lea 0xffff8802,a0
move.b #14,-2(a0)
move.b #0x80,(a0)
bsr warte_1ms
clr.b (a0)
/********************************************************************/
/* video setup
/********************************************************************/
video_setup:
lea 0xf0000410,a0
// 25MHz
move.l #0x032002ba,(a0)+ // horizontal 640x480
move.l #0x020c020a,(a0)+ // vertikal 640x480
move.l #0x0190015d,(a0)+ // horizontal 320x240
move.l #0x020C020A,(a0)+ // vertikal 320x240 */
/*
// 32MHz
move.l #0x037002ba,(a0)+ // horizontal 640x480
move.l #0x020d020a,(a0)+ // vertikal 640x480
move.l #0x02A001e0,(a0)+ // horizontal 320x240
move.l #0x05a00160,(a0)+ // vertikal 320x240
*/
lea -0x20(a0),a0
move.l #0x01070002,(a0) // fifo on, refresh on, ddrcs und cke on, video dac on,
/********************************************************************/
// nichts
/*******************************************************************/
/* memory setup
/********************************************************************/
lea 0x400,a0
@@ -272,7 +274,7 @@ mem_clr_loop:
move.l #0x5555aaaa,d0 // memval3
move.l d0,0x51a
// ttram
move.l #__Bas_base,d0 // ende ttram
move.l #__SDRAM_SIZE,d0 // ende ttram
move.l d0,0x5a4
move.l #0x1357bd13,d0 // ramvalid
move.l d0,0x5a8
@@ -292,13 +294,69 @@ mem_clr_loop:
move.b d0,0xfffffa11
nop
}
/*
// init_dma:
dma_init_status =
MCD_initDma(
(dmaRegs*) (MBAR_BASE_ADRS + MMAP_DMA),
(void*) (MBAR_BASE_ADRS + MMAP_SRAM),
(MCD_RELOC_TASKS)
);
for (i=0; i<64; i++)
{
dma_run_status =
MCD_startDma(ide_dma_tnr, //int channel, the channel on which to run the DMA
(char*) (0x60004000), //s8 *srcAddr, the address to move data from, or physical buffer-descriptor address
4, //s16 srcIncr, the amount to increment the source address per transfer
(char*) (0x60000000), //s8 *destAddr, the address to move data to
4, //s16 destIncr, the amount to increment the destination address per transfer
4*389120, //u32 dmaSize, the number of bytes to transfer independent of the transfer size
4, //u32 xferSize, the number bytes in of each data movement (1, 2, or 4)
0, //u32 initiator, what device initiates the DMA
5, //int priority, priority of the DMA
MCD_SINGLE_DMA+
MCD_TT_FLAGS_CW+ //u32 flags, flags describing the DMA
MCD_TT_FLAGS_RL+
MCD_TT_FLAGS_SP,
MCD_NO_BYTE_SWAP+
MCD_NO_BIT_REV //u32 funcDesc a description of byte swapping, bit swapping, and CRC actions
);
while (MCD_dmaStatus(ide_dma_tnr)!=6);
}
dma_status =
MCD_dmaStatus(ide_dma_tnr);
MCD_killDma(ide_dma_tnr);
*/
asm
{
// test auf protect mode ---------------------
move.b DIP_SWITCH,d0
btst #7,d0
beq no_protect // nein->
move.w #0x0700,sr
no_protect:
}
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
MCF_PSC0_PSCTB_8BIT = 'BaS ';
MCF_PSC0_PSCTB_8BIT = 'comp';
MCF_PSC0_PSCTB_8BIT = 'lete';
MCF_PSC0_PSCTB_8BIT = 'd';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
MCF_PSC0_PSCTB_8BIT = '----';
MCF_PSC0_PSCTB_8BIT = '----';
MCF_PSC0_PSCTB_8BIT = '----';
MCF_PSC0_PSCTB_8BIT = '-';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
asm
{
nop
bsr warte_10ms
jmp 0xe00030
}
}
}

933
sources/MCD_dmaApi.c Normal file
View File

@@ -0,0 +1,933 @@
/*
* File: MCD_dmaApi.c
* Purpose: Main C file for multi-channel DMA API.
*
* Notes:
*/
#include "MCD_dma.h"
#include "MCD_tasksInit.h"
#include "MCD_progCheck.h"
/********************************************************************/
/*
* This is an API-internal pointer to the DMA's registers
*/
dmaRegs *MCD_dmaBar;
/*
* These are the real and model task tables as generated by the
* build process
*/
extern TaskTableEntry MCD_realTaskTableSrc[NCHANNELS];
extern TaskTableEntry MCD_modelTaskTableSrc[NUMOFVARIANTS];
/*
* However, this (usually) gets relocated to on-chip SRAM, at which
* point we access them as these tables
*/
volatile TaskTableEntry *MCD_taskTable;
TaskTableEntry *MCD_modelTaskTable;
/*
* MCD_chStatus[] is an array of status indicators for remembering
* whether a DMA has ever been attempted on each channel, pausing
* status, etc.
*/
static int MCD_chStatus[NCHANNELS] =
{
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA,
MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA
};
/*
* Prototypes for local functions
*/
static void MCD_memcpy (int *dest, int *src, u32 size);
static void MCD_resmActions (int channel);
/*
* Buffer descriptors used for storage of progress info for single Dmas
* Also used as storage for the DMA for CRCs for single DMAs
* Otherwise, the DMA does not parse these buffer descriptors
*/
#ifdef MCD_INCLUDE_EU
extern MCD_bufDesc MCD_singleBufDescs[NCHANNELS];
#else
MCD_bufDesc MCD_singleBufDescs[NCHANNELS];
#endif
MCD_bufDesc *MCD_relocBuffDesc;
/*
* Defines for the debug control register's functions
*/
#define DBG_CTL_COMP1_TASK (0x00002000) /* have comparator 1 look for a task # */
#define DBG_CTL_ENABLE (DBG_CTL_AUTO_ARM | \
DBG_CTL_BREAK | \
DBG_CTL_INT_BREAK | \
DBG_CTL_COMP1_TASK)
#define DBG_CTL_DISABLE (DBG_CTL_AUTO_ARM | \
DBG_CTL_INT_BREAK | \
DBG_CTL_COMP1_TASK)
#define DBG_KILL_ALL_STAT (0xFFFFFFFF)
/*
* Offset to context save area where progress info is stored
*/
#define CSAVE_OFFSET 10
/*
* Defines for Byte Swapping
*/
#define MCD_BYTE_SWAP_KILLER 0xFFF8888F
#define MCD_NO_BYTE_SWAP_ATALL 0x00040000
/*
* Execution Unit Identifiers
*/
#define MAC 0 /* legacy - not used */
#define LUAC 1 /* legacy - not used */
#define CRC 2 /* legacy - not used */
#define LURC 3 /* Logic Unit with CRC */
/*
* Task Identifiers
*/
#define TASK_CHAINNOEU 0
#define TASK_SINGLENOEU 1
#ifdef MCD_INCLUDE_EU
#define TASK_CHAINEU 2
#define TASK_SINGLEEU 3
#define TASK_FECRX 4
#define TASK_FECTX 5
#else
#define TASK_CHAINEU 0
#define TASK_SINGLEEU 1
#define TASK_FECRX 2
#define TASK_FECTX 3
#endif
/*
* Structure to remember which variant is on which channel
* TBD- need this?
*/
typedef struct MCD_remVariants_struct MCD_remVariant;
struct MCD_remVariants_struct
{
int remDestRsdIncr[NCHANNELS]; /* -1,0,1 */
int remSrcRsdIncr[NCHANNELS]; /* -1,0,1 */
s16 remDestIncr[NCHANNELS]; /* DestIncr */
s16 remSrcIncr[NCHANNELS]; /* srcIncr */
u32 remXferSize[NCHANNELS]; /* xferSize */
};
/*
* Structure to remember the startDma parameters for each channel
*/
MCD_remVariant MCD_remVariants;
/********************************************************************/
/*
* Function: MCD_initDma
* Purpose: Initializes the DMA API by setting up a pointer to the DMA
* registers, relocating and creating the appropriate task
* structures, and setting up some global settings
* Arguments:
* dmaBarAddr - pointer to the multichannel DMA registers
* taskTableDest - location to move DMA task code and structs to
* flags - operational parameters
* Return Value:
* MCD_TABLE_UNALIGNED if taskTableDest is not 512-byte aligned
* MCD_OK otherwise
*/
extern u32 MCD_funcDescTab0[];
int MCD_initDma (dmaRegs *dmaBarAddr, void *taskTableDest, u32 flags)
{
int i;
TaskTableEntry *entryPtr;
/* setup the local pointer to register set */
MCD_dmaBar = dmaBarAddr;
/* do we need to move/create a task table */
if ((flags & MCD_RELOC_TASKS) != 0)
{
int fixedSize;
u32 *fixedPtr;
/*int *tablePtr = taskTableDest;TBD*/
int varTabsOffset, funcDescTabsOffset, contextSavesOffset;
int taskDescTabsOffset;
int taskTableSize, varTabsSize, funcDescTabsSize, contextSavesSize;
int taskDescTabSize;
int i;
/* check if physical address is aligned on 512 byte boundary */
if (((u32)taskTableDest & 0x000001ff) != 0)
return(MCD_TABLE_UNALIGNED);
MCD_taskTable = taskTableDest; /* set up local pointer to task Table */
/*
* Create a task table:
* - compute aligned base offsets for variable tables and
* function descriptor tables, then
* - loop through the task table and setup the pointers
* - copy over model task table with the the actual task descriptor
* tables
*/
taskTableSize = NCHANNELS * sizeof(TaskTableEntry);
/* align variable tables to size */
varTabsOffset = taskTableSize + (u32)taskTableDest;
if ((varTabsOffset & (VAR_TAB_SIZE - 1)) != 0)
varTabsOffset = (varTabsOffset + VAR_TAB_SIZE) & (~VAR_TAB_SIZE);
/* align function descriptor tables */
varTabsSize = NCHANNELS * VAR_TAB_SIZE;
funcDescTabsOffset = varTabsOffset + varTabsSize;
if ((funcDescTabsOffset & (FUNCDESC_TAB_SIZE - 1)) != 0)
funcDescTabsOffset = (funcDescTabsOffset + FUNCDESC_TAB_SIZE) &
(~FUNCDESC_TAB_SIZE);
funcDescTabsSize = FUNCDESC_TAB_NUM * FUNCDESC_TAB_SIZE;
contextSavesOffset = funcDescTabsOffset + funcDescTabsSize;
contextSavesSize = (NCHANNELS * CONTEXT_SAVE_SIZE);
fixedSize = taskTableSize + varTabsSize + funcDescTabsSize +
contextSavesSize;
/* zero the thing out */
fixedPtr = (u32 *)taskTableDest;
for (i = 0;i<(fixedSize/4);i++)
fixedPtr[i] = 0;
entryPtr = (TaskTableEntry*)MCD_taskTable;
/* set up fixed pointers */
for (i = 0; i < NCHANNELS; i++)
{
entryPtr[i].varTab = (u32)varTabsOffset; /* update ptr to local value */
entryPtr[i].FDTandFlags = (u32)funcDescTabsOffset | MCD_TT_FLAGS_DEF;
entryPtr[i].contextSaveSpace = (u32)contextSavesOffset;
varTabsOffset += VAR_TAB_SIZE;
#ifdef MCD_INCLUDE_EU /* if not there is only one, just point to the same one */
funcDescTabsOffset += FUNCDESC_TAB_SIZE;
#endif
contextSavesOffset += CONTEXT_SAVE_SIZE;
}
/* copy over the function descriptor table */
for ( i = 0; i < FUNCDESC_TAB_NUM; i++)
{
MCD_memcpy((void*)(entryPtr[i].FDTandFlags & ~MCD_TT_FLAGS_MASK),
(void*)MCD_funcDescTab0, FUNCDESC_TAB_SIZE);
}
/* copy model task table to where the context saves stuff leaves off*/
MCD_modelTaskTable = (TaskTableEntry*)contextSavesOffset;
MCD_memcpy ((void*)MCD_modelTaskTable, (void*)MCD_modelTaskTableSrc,
NUMOFVARIANTS * sizeof(TaskTableEntry));
entryPtr = MCD_modelTaskTable; /* point to local version of
model task table */
taskDescTabsOffset = (u32)MCD_modelTaskTable +
(NUMOFVARIANTS * sizeof(TaskTableEntry));
/* copy actual task code and update TDT ptrs in local model task table */
for (i = 0; i < NUMOFVARIANTS; i++)
{
taskDescTabSize = entryPtr[i].TDTend - entryPtr[i].TDTstart + 4;
MCD_memcpy ((void*)taskDescTabsOffset, (void*)entryPtr[i].TDTstart, taskDescTabSize);
entryPtr[i].TDTstart = (u32)taskDescTabsOffset;
taskDescTabsOffset += taskDescTabSize;
entryPtr[i].TDTend = (u32)taskDescTabsOffset - 4;
}
#ifdef MCD_INCLUDE_EU /* Tack single DMA BDs onto end of code so API controls
where they are since DMA might write to them */
MCD_relocBuffDesc = (MCD_bufDesc*)(entryPtr[NUMOFVARIANTS - 1].TDTend + 4);
#else /* DMA does not touch them so they can be wherever and we don't need to
waste SRAM on them */
MCD_relocBuffDesc = MCD_singleBufDescs;
#endif
}
else
{
/* point the would-be relocated task tables and the
buffer descriptors to the ones the linker generated */
if (((u32)MCD_realTaskTableSrc & 0x000001ff) != 0)
return(MCD_TABLE_UNALIGNED);
/* need to add code to make sure that every thing else is aligned properly TBD*/
/* this is problematic if we init more than once or after running tasks,
need to add variable to see if we have aleady init'd */
entryPtr = MCD_realTaskTableSrc;
for (i = 0; i < NCHANNELS; i++)
{
if (((entryPtr[i].varTab & (VAR_TAB_SIZE - 1)) != 0) ||
((entryPtr[i].FDTandFlags & (FUNCDESC_TAB_SIZE - 1)) != 0))
return(MCD_TABLE_UNALIGNED);
}
MCD_taskTable = MCD_realTaskTableSrc;
MCD_modelTaskTable = MCD_modelTaskTableSrc;
MCD_relocBuffDesc = MCD_singleBufDescs;
}
/* Make all channels as totally inactive, and remember them as such: */
MCD_dmaBar->taskbar = (u32) MCD_taskTable;
for (i = 0; i < NCHANNELS; i++)
{
MCD_dmaBar->taskControl[i] = 0x0;
MCD_chStatus[i] = MCD_NO_DMA;
}
/* Set up pausing mechanism to inactive state: */
MCD_dmaBar->debugComp1 = 0; /* no particular values yet for either comparator registers */
MCD_dmaBar->debugComp2 = 0;
MCD_dmaBar->debugControl = DBG_CTL_DISABLE;
MCD_dmaBar->debugStatus = DBG_KILL_ALL_STAT;
/* enable or disable commbus prefetch, really need an ifdef or
something to keep from trying to set this in the 8220 */
if ((flags & MCD_COMM_PREFETCH_EN) != 0)
MCD_dmaBar->ptdControl &= ~PTD_CTL_COMM_PREFETCH;
else
MCD_dmaBar->ptdControl |= PTD_CTL_COMM_PREFETCH;
return(MCD_OK);
}
/*********************** End of MCD_initDma() ***********************/
/********************************************************************/
/* Function: MCD_dmaStatus
* Purpose: Returns the status of the DMA on the requested channel
* Arguments: channel - channel number
* Returns: Predefined status indicators
*/
int MCD_dmaStatus (int channel)
{
u16 tcrValue;
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
tcrValue = MCD_dmaBar->taskControl[channel];
if ((tcrValue & TASK_CTL_EN) == 0)
{ /* nothing running */
/* if last reported with task enabled */
if ( MCD_chStatus[channel] == MCD_RUNNING
|| MCD_chStatus[channel] == MCD_IDLE)
MCD_chStatus[channel] = MCD_DONE;
}
else /* something is running */
{
/* There are three possibilities: paused, running or idle. */
if ( MCD_chStatus[channel] == MCD_RUNNING
|| MCD_chStatus[channel] == MCD_IDLE)
{
MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT;
/* This register is selected to know which initiator is
actually asserted. */
if ((MCD_dmaBar->ptdDebug >> channel ) & 0x1 )
MCD_chStatus[channel] = MCD_RUNNING;
else
MCD_chStatus[channel] = MCD_IDLE;
/* do not change the status if it is already paused. */
}
}
return MCD_chStatus[channel];
}
/******************** End of MCD_dmaStatus() ************************/
/********************************************************************/
/* Function: MCD_startDma
* Ppurpose: Starts a particular kind of DMA
* Arguments: see below
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*/
int MCD_startDma (
int channel, /* the channel on which to run the DMA */
s8 *srcAddr, /* the address to move data from, or physical buffer-descriptor address */
s16 srcIncr, /* the amount to increment the source address per transfer */
s8 *destAddr, /* the address to move data to */
s16 destIncr, /* the amount to increment the destination address per transfer */
u32 dmaSize, /* the number of bytes to transfer independent of the transfer size */
u32 xferSize, /* the number bytes in of each data movement (1, 2, or 4) */
u32 initiator, /* what device initiates the DMA */
int priority, /* priority of the DMA */
u32 flags, /* flags describing the DMA */
u32 funcDesc /* a description of byte swapping, bit swapping, and CRC actions */
#ifdef MCD_NEED_ADDR_TRANS
s8 *srcAddrVirt /* virtual buffer descriptor address TBD*/
#endif
)
{
int srcRsdIncr, destRsdIncr;
int *cSave;
short xferSizeIncr;
int tcrCount = 0;
#ifdef MCD_INCLUDE_EU
u32 *realFuncArray;
#endif
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
/* tbd - need to determine the proper response to a bad funcDesc when not
including EU functions, for now, assign a benign funcDesc, but maybe
should return an error */
#ifndef MCD_INCLUDE_EU
funcDesc = MCD_FUNC_NOEU1;
#endif
#ifdef MCD_DEBUG
printf("startDma:Setting up params\n");
#endif
/* Set us up for task-wise priority. We don't technically need to do this on every start, but
since the register involved is in the same longword as other registers that users are in control
of, setting it more than once is probably preferable. That since the documentation doesn't seem
to be completely consistent about the nature of the PTD control register. */
MCD_dmaBar->ptdControl |= (u16) 0x8000;
#if 1 /* Not sure what we need to keep here rtm TBD */
/* Calculate additional parameters to the regular DMA calls. */
srcRsdIncr = srcIncr < 0 ? -1 : (srcIncr > 0 ? 1 : 0);
destRsdIncr = destIncr < 0 ? -1 : (destIncr > 0 ? 1 : 0);
xferSizeIncr = (xferSize & 0xffff) | 0x20000000;
/* Remember for each channel which variant is running. */
MCD_remVariants.remSrcRsdIncr[channel] = srcRsdIncr;
MCD_remVariants.remDestRsdIncr[channel] = destRsdIncr;
MCD_remVariants.remDestIncr[channel] = destIncr;
MCD_remVariants.remSrcIncr[channel] = srcIncr;
MCD_remVariants.remXferSize[channel] = xferSize;
#endif
cSave = (int*)(MCD_taskTable[channel].contextSaveSpace) + CSAVE_OFFSET + CURRBD;
#ifdef MCD_INCLUDE_EU /* may move this to EU specific calls */
realFuncArray = (u32 *) (MCD_taskTable[channel].FDTandFlags & 0xffffff00);
/* Modify the LURC's normal and byte-residue-loop functions according to parameter. */
realFuncArray[(LURC*16)] = xferSize == 4 ?
funcDesc : xferSize == 2 ?
funcDesc & 0xfffff00f : funcDesc & 0xffff000f;
realFuncArray[(LURC*16+1)] = (funcDesc & MCD_BYTE_SWAP_KILLER) | MCD_NO_BYTE_SWAP_ATALL;
#endif
/* Write the initiator field in the TCR, and also set the initiator-hold
bit. Note that,due to a hardware quirk, this could collide with an
MDE access to the initiator-register file, so we have to verify that the write
reads back correctly. */
MCD_dmaBar->taskControl[channel] =
(initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM;
while(((MCD_dmaBar->taskControl[channel] & 0x1fff) !=
((initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM)) &&
(tcrCount < 1000))
{
tcrCount++;
/*MCD_dmaBar->ptd_tcr[channel] = (initiator << 8) | 0x0020;*/
MCD_dmaBar->taskControl[channel] =
(initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM;
}
MCD_dmaBar->priority[channel] = (u8)priority & PRIORITY_PRI_MASK;
/* should be albe to handle this stuff with only one write to ts reg - tbd */
if (channel < 8 && channel >= 0)
{
MCD_dmaBar->taskSize0 &= ~(0xf << (7-channel)*4);
MCD_dmaBar->taskSize0 |= (xferSize & 3) << (((7 - channel)*4) + 2);
MCD_dmaBar->taskSize0 |= (xferSize & 3) << ((7 - channel)*4);
}
else
{
MCD_dmaBar->taskSize1 &= ~(0xf << (15-channel)*4);
MCD_dmaBar->taskSize1 |= (xferSize & 3) << (((15 - channel)*4) + 2);
MCD_dmaBar->taskSize1 |= (xferSize & 3) << ((15 - channel)*4);
}
/* setup task table flags/options which mostly control the line buffers */
MCD_taskTable[channel].FDTandFlags &= ~MCD_TT_FLAGS_MASK;
MCD_taskTable[channel].FDTandFlags |= (MCD_TT_FLAGS_MASK & flags);
if (flags & MCD_FECTX_DMA)
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_FECTX].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_FECTX].TDTend;
MCD_startDmaENetXmit(srcAddr, srcAddr, destAddr, MCD_taskTable, channel);
}
else if (flags & MCD_FECRX_DMA)
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_FECRX].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_FECRX].TDTend;
MCD_startDmaENetRcv(srcAddr, srcAddr, destAddr, MCD_taskTable, channel);
}
else if(flags & MCD_SINGLE_DMA)
{
/* this buffer descriptor is used for storing off initial parameters for later
progress query calculation and for the DMA to write the resulting checksum
The DMA does not use this to determine how to operate, that info is passed
with the init routine*/
MCD_relocBuffDesc[channel].srcAddr = srcAddr;
MCD_relocBuffDesc[channel].destAddr = destAddr;
MCD_relocBuffDesc[channel].lastDestAddr = destAddr; /* definitely not its final value */
MCD_relocBuffDesc[channel].dmaSize = dmaSize;
MCD_relocBuffDesc[channel].flags = 0; /* not used */
MCD_relocBuffDesc[channel].csumResult = 0; /* not used */
MCD_relocBuffDesc[channel].next = 0; /* not used */
/* Initialize the progress-querying stuff to show no progress:*/
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET] = (int)srcAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET] = (int)destAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET] =
(u32) &(MCD_relocBuffDesc[channel]);
/* tbd - need to keep the user from trying to call the EU routine
when MCD_INCLUDE_EU is not defined */
if( funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2)
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_SINGLENOEU].TDTend;
MCD_startDmaSingleNoEu(srcAddr, srcIncr, destAddr, destIncr, dmaSize,
xferSizeIncr, flags, (int *)&(MCD_relocBuffDesc[channel]), cSave,
MCD_taskTable, channel);
}
else
{
/* TDTStart and TDTEnd */
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_SINGLEEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_SINGLEEU].TDTend;
MCD_startDmaSingleEu(srcAddr, srcIncr, destAddr, destIncr, dmaSize,
xferSizeIncr, flags, (int *)&(MCD_relocBuffDesc[channel]), cSave,
MCD_taskTable, channel);
}
}
else
{ /* chained DMAS */
/* Initialize the progress-querying stuff to show no progress:*/
#if 1 /* (!defined(MCD_NEED_ADDR_TRANS)) */
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddr)->srcAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddr)->destAddr;
#else /* if using address translation, need the virtual addr of the first buffdesc */
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddrVirt)->srcAddr;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET]
= (int)((MCD_bufDesc*) srcAddrVirt)->destAddr;
#endif
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0;
((volatile int *)MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET] = (u32) srcAddr;
if( funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2)
{
/*TDTStart and TDTEnd*/
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_CHAINNOEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_CHAINNOEU].TDTend;
MCD_startDmaChainNoEu((int *)srcAddr, srcIncr, destIncr, xferSize,
xferSizeIncr, cSave, MCD_taskTable, channel);
}
else
{
/*TDTStart and TDTEnd*/
MCD_taskTable[channel].TDTstart = MCD_modelTaskTable[TASK_CHAINEU].TDTstart;
MCD_taskTable[channel].TDTend = MCD_modelTaskTable[TASK_CHAINEU].TDTend;
MCD_startDmaChainEu((int *)srcAddr, srcIncr, destIncr, xferSize,
xferSizeIncr, cSave, MCD_taskTable, channel);
}
}
MCD_chStatus[channel] = MCD_IDLE;
return(MCD_OK);
}
/************************ End of MCD_startDma() *********************/
/********************************************************************/
/* Function: MCD_XferProgrQuery
* Purpose: Returns progress of DMA on requested channel
* Arguments: channel - channel to retrieve progress for
* progRep - pointer to user supplied MCD_XferProg struct
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*
* Notes:
* MCD_XferProgrQuery() upon completing or after aborting a DMA, or
* while the DMA is in progress, this function returns the first
* DMA-destination address not (or not yet) used in the DMA. When
* encountering a non-ready buffer descriptor, the information for
* the last completed descriptor is returned.
*
* MCD_XferProgQuery() has to avoid the possibility of getting
* partially-updated information in the event that we should happen
* to query DMA progress just as the DMA is updating it. It does that
* by taking advantage of the fact context is not saved frequently for
* the most part. We therefore read it at least twice until we get the
* same information twice in a row.
*
* Because a small, but not insignificant, amount of time is required
* to write out the progress-query information, especially upon
* completion of the DMA, it would be wise to guarantee some time lag
* between successive readings of the progress-query information.
*/
/*
* How many iterations of the loop below to execute to stabilize values
*/
#define STABTIME 0
int MCD_XferProgrQuery (int channel, MCD_XferProg *progRep)
{
MCD_XferProg prevRep;
int again; /* true if we are to try again to get consistent results */
int i; /* used as a time-waste counter */
int destDiffBytes; /* Total number of bytes that we think actually got xfered. */
int numIterations; /* number of iterations */
int bytesNotXfered; /* bytes that did not get xfered. */
s8 *LWAlignedInitDestAddr, *LWAlignedCurrDestAddr;
int subModVal, addModVal; /* Mode values to added and subtracted from the
final destAddr */
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
/* Read a trial value for the progress-reporting values*/
prevRep.lastSrcAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET];
prevRep.lastDestAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET];
prevRep.dmaSize = ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET];
prevRep.currBufDesc =
(MCD_bufDesc*) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET];
/* Repeatedly reread those values until they match previous values: */
do {
/* Waste a little bit of time to ensure stability: */
for (i = 0; i < STABTIME; i++)
i += i >> 2; /* make sure this loop does something so that it doesn't get optimized out */
/* Check them again: */
progRep->lastSrcAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[SRCPTR + CSAVE_OFFSET];
progRep->lastDestAddr =
(s8 *) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DESTPTR + CSAVE_OFFSET];
progRep->dmaSize = ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[DCOUNT + CSAVE_OFFSET];
progRep->currBufDesc =
(MCD_bufDesc*) ((volatile int*) MCD_taskTable[channel].contextSaveSpace)[CURRBD + CSAVE_OFFSET];
/* See if they match: */
if ( prevRep.lastSrcAddr != progRep->lastSrcAddr
|| prevRep.lastDestAddr != progRep->lastDestAddr
|| prevRep.dmaSize != progRep->dmaSize
|| prevRep.currBufDesc != progRep->currBufDesc)
{
/* If they don't match, remember previous values and try again:*/
prevRep.lastSrcAddr = progRep->lastSrcAddr;
prevRep.lastDestAddr = progRep->lastDestAddr;
prevRep.dmaSize = progRep->dmaSize;
prevRep.currBufDesc = progRep->currBufDesc;
again = MCD_TRUE;
}
else
again = MCD_FALSE;
} while (again == MCD_TRUE);
/* Update the dCount, srcAddr and destAddr */
/* To calculate dmaCount, we consider destination address. C
overs M1,P1,Z for destination */
switch(MCD_remVariants.remDestRsdIncr[channel]) {
case MINUS1:
subModVal = ((int)progRep->lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
addModVal = ((int)progRep->currBufDesc->destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - addModVal;
LWAlignedCurrDestAddr = (progRep->lastDestAddr) - subModVal;
destDiffBytes = LWAlignedInitDestAddr - LWAlignedCurrDestAddr;
bytesNotXfered = (destDiffBytes/MCD_remVariants.remDestIncr[channel]) *
( MCD_remVariants.remDestIncr[channel]
+ MCD_remVariants.remXferSize[channel]);
progRep->dmaSize = destDiffBytes - bytesNotXfered + addModVal - subModVal;
break;
case ZERO:
progRep->lastDestAddr = progRep->currBufDesc->destAddr;
break;
case PLUS1:
/* This value has to be subtracted from the final calculated dCount. */
subModVal = ((int)progRep->currBufDesc->destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
/* These bytes are already in lastDestAddr. */
addModVal = ((int)progRep->lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - 1);
LWAlignedInitDestAddr = (progRep->currBufDesc->destAddr) - subModVal;
LWAlignedCurrDestAddr = (progRep->lastDestAddr) - addModVal;
destDiffBytes = (progRep->lastDestAddr - LWAlignedInitDestAddr);
numIterations = ( LWAlignedCurrDestAddr - LWAlignedInitDestAddr)/MCD_remVariants.remDestIncr[channel];
bytesNotXfered = numIterations *
( MCD_remVariants.remDestIncr[channel]
- MCD_remVariants.remXferSize[channel]);
progRep->dmaSize = destDiffBytes - bytesNotXfered - subModVal;
break;
default:
break;
}
/* This covers M1,P1,Z for source */
switch(MCD_remVariants.remSrcRsdIncr[channel]) {
case MINUS1:
progRep->lastSrcAddr =
progRep->currBufDesc->srcAddr +
( MCD_remVariants.remSrcIncr[channel] *
(progRep->dmaSize/MCD_remVariants.remXferSize[channel]));
break;
case ZERO:
progRep->lastSrcAddr = progRep->currBufDesc->srcAddr;
break;
case PLUS1:
progRep->lastSrcAddr =
progRep->currBufDesc->srcAddr +
( MCD_remVariants.remSrcIncr[channel] *
(progRep->dmaSize/MCD_remVariants.remXferSize[channel]));
break;
default: break;
}
return(MCD_OK);
}
/******************* End of MCD_XferProgrQuery() ********************/
/********************************************************************/
/* MCD_resmActions() does the majority of the actions of a DMA resume.
* It is called from MCD_killDma() and MCD_resumeDma(). It has to be
* a separate function because the kill function has to negate the task
* enable before resuming it, but the resume function has to do nothing
* if there is no DMA on that channel (i.e., if the enable bit is 0).
*/
static void MCD_resmActions (int channel)
{
MCD_dmaBar->debugControl = DBG_CTL_DISABLE;
MCD_dmaBar->debugStatus = MCD_dmaBar->debugStatus;
MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; /* This register is selected to know
which initiator is actually asserted. */
if((MCD_dmaBar->ptdDebug >> channel ) & 0x1)
MCD_chStatus[channel] = MCD_RUNNING;
else
MCD_chStatus[channel] = MCD_IDLE;
}
/********************* End of MCD_resmActions() *********************/
/********************************************************************/
/* Function: MCD_killDma
* Purpose: Halt the DMA on the requested channel, without any
* intention of resuming the DMA.
* Arguments: channel - requested channel
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*
* Notes:
* A DMA may be killed from any state, including paused state, and it
* always goes to the MCD_HALTED state even if it is killed while in
* the MCD_NO_DMA or MCD_IDLE states.
*/
int MCD_killDma (int channel)
{
/* MCD_XferProg progRep; */
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
MCD_dmaBar->taskControl[channel] = 0x0;
MCD_resumeDma (channel);
/*
* This must be after the write to the TCR so that the task doesn't
* start up again momentarily, and before the status assignment so
* as to override whatever MCD_resumeDma() may do to the channel
* status.
*/
MCD_chStatus[channel] = MCD_HALTED;
/*
* Update the current buffer descriptor's lastDestAddr field
*
* MCD_XferProgrQuery (channel, &progRep);
* progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr;
*/
return(MCD_OK);
}
/************************ End of MCD_killDma() **********************/
/********************************************************************/
/* Function: MCD_continDma
* Purpose: Continue a DMA which as stopped due to encountering an
* unready buffer descriptor.
* Arguments: channel - channel to continue the DMA on
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*
* Notes:
* This routine does not check to see if there is a task which can
* be continued. Also this routine should not be used with single DMAs.
*/
int MCD_continDma (int channel)
{
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
MCD_dmaBar->taskControl[channel] |= TASK_CTL_EN;
MCD_chStatus[channel] = MCD_RUNNING;
return(MCD_OK);
}
/********************** End of MCD_continDma() **********************/
/*********************************************************************
* MCD_pauseDma() and MCD_resumeDma() below use the DMA's debug unit
* to freeze a task and resume it. We freeze a task by breakpointing
* on the stated task. That is, not any specific place in the task,
* but any time that task executes. In particular, when that task
* executes, we want to freeze that task and only that task.
*
* The bits of the debug control register influence interrupts vs.
* breakpoints as follows:
* - Bits 14 and 0 enable or disable debug functions. If enabled, you
* will get the interrupt but you may or may not get a breakpoint.
* - Bits 2 and 1 decide whether you also get a breakpoint in addition
* to an interrupt.
*
* The debug unit can do these actions in response to either internally
* detected breakpoint conditions from the comparators, or in response
* to the external breakpoint pin, or both.
* - Bits 14 and 1 perform the above-described functions for
* internally-generated conditions, i.e., the debug comparators.
* - Bits 0 and 2 perform the above-described functions for external
* conditions, i.e., the breakpoint external pin.
*
* Note that, although you "always" get the interrupt when you turn
* the debug functions, the interrupt can nevertheless, if desired, be
* masked by the corresponding bit in the PTD's IMR. Note also that
* this means that bits 14 and 0 must enable debug functions before
* bits 1 and 2, respectively, have any effect.
*
* NOTE: It's extremely important to not pause more than one DMA channel
* at a time.
********************************************************************/
/********************************************************************/
/* Function: MCD_pauseDma
* Purpose: Pauses the DMA on a given channel (if any DMA is running
* on that channel).
* Arguments: channel
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*/
int MCD_pauseDma (int channel)
{
/* MCD_XferProg progRep; */
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN)
{
MCD_dmaBar->debugComp1 = channel;
MCD_dmaBar->debugControl = DBG_CTL_ENABLE | (1 << (channel + 16));
MCD_chStatus[channel] = MCD_PAUSED;
/*
* Update the current buffer descriptor's lastDestAddr field
*
* MCD_XferProgrQuery (channel, &progRep);
* progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr;
*/
}
return(MCD_OK);
}
/************************* End of MCD_pauseDma() ********************/
/********************************************************************/
/* Function: MCD_resumeDma
* Purpose: Resumes the DMA on a given channel (if any DMA is
* running on that channel).
* Arguments: channel - channel on which to resume DMA
* Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK
*/
int MCD_resumeDma (int channel)
{
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN)
MCD_resmActions (channel);
return(MCD_OK);
}
/************************ End of MCD_resumeDma() ********************/
/********************************************************************/
/* Function: MCD_csumQuery
* Purpose: Provide the checksum after performing a non-chained DMA
* Arguments: channel - channel to report on
* csum - pointer to where to write the checksum/CRC
* Returns: MCD_ERROR if the channel is invalid, else MCD_OK
*
* Notes:
*
*/
int MCD_csumQuery (int channel, u32 *csum)
{
#ifdef MCD_INCLUDE_EU
if((channel < 0) || (channel >= NCHANNELS))
return(MCD_CHANNEL_INVALID);
*csum = MCD_relocBuffDesc[channel].csumResult;
return(MCD_OK);
#else
return(MCD_ERROR);
#endif
}
/*********************** End of MCD_resumeDma() *********************/
/********************************************************************/
/* Function: MCD_getCodeSize
* Purpose: Provide the size requirements of the microcoded tasks
* Returns: Size in bytes
*/
int MCD_getCodeSize(void)
{
#ifdef MCD_INCLUDE_EU
return(0x2b5c);
#else
return(0x173c);
#endif
}
/********************** End of MCD_getCodeSize() ********************/
/********************************************************************/
/* Function: MCD_getVersion
* Purpose: Provide the version string and number
* Arguments: longVersion - user supplied pointer to a pointer to a char
* which points to the version string
* Returns: Version number and version string (by reference)
*/
char MCD_versionString[] = "Multi-channel DMA API Alpha v0.3 (2004-04-26)";
#define MCD_REV_MAJOR 0x00
#define MCD_REV_MINOR 0x03
int MCD_getVersion(char **longVersion)
{
*longVersion = MCD_versionString;
return((MCD_REV_MAJOR << 8) | MCD_REV_MINOR);
}
/********************** End of MCD_getVersion() *********************/
/********************************************************************/
/* Private version of memcpy()
* Note that everything this is used for is longword-aligned.
*/
static void MCD_memcpy (int *dest, int *src, u32 size)
{
u32 i;
for (i = 0; i < size; i += sizeof(int), dest++, src++)
*dest = *src;
}
/********************************************************************/

2449
sources/MCD_tasks.c Normal file

File diff suppressed because it is too large Load Diff

224
sources/MCD_tasksInit.c Normal file
View File

@@ -0,0 +1,224 @@
/*
* File: MCD_tasksInit.c
* Purpose: Functions for initializing variable tables of different
* types of tasks.
*
* Notes:
*/
/*
* Do not edit!
*/
#include "MCD_dma.h"
extern dmaRegs *MCD_dmaBar;
/*
* Task 0
*/
void MCD_startDmaChainNoEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 2, (u32)currBD); /* var[2] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 11, (u32)xferSize); /* var[11] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 3, (u32)0x00000000); /* var[3] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000000); /* var[12] */
MCD_SET_VAR(taskTable+channel, 13, (u32)0x80000000); /* var[13] */
MCD_SET_VAR(taskTable+channel, 14, (u32)0x00000010); /* var[14] */
MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000004); /* var[15] */
MCD_SET_VAR(taskTable+channel, 16, (u32)0x08000000); /* var[16] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000000); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000001); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x40000000); /* inc[6] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 1
*/
void MCD_startDmaSingleNoEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 7, (u32)srcAddr); /* var[7] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)destAddr); /* var[2] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 3, (u32)dmaSize); /* var[3] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 5, (u32)flags); /* var[5] */
MCD_SET_VAR(taskTable+channel, 1, (u32)currBD); /* var[1] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000004); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x08000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000001); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x40000000); /* inc[5] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 2
*/
void MCD_startDmaChainEu(int *currBD, short srcIncr, short destIncr, int xferSize, short xferSizeIncr, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 12, (u32)xferSize); /* var[12] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 11, (u32)0x00000000); /* var[11] */
MCD_SET_VAR(taskTable+channel, 13, (u32)0x00000000); /* var[13] */
MCD_SET_VAR(taskTable+channel, 14, (u32)0x80000000); /* var[14] */
MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000010); /* var[15] */
MCD_SET_VAR(taskTable+channel, 16, (u32)0x00000001); /* var[16] */
MCD_SET_VAR(taskTable+channel, 17, (u32)0x00000004); /* var[17] */
MCD_SET_VAR(taskTable+channel, 18, (u32)0x08000000); /* var[18] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0x80000000); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0xc0000000); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x80000001); /* inc[6] */
MCD_SET_VAR(taskTable+channel, 31, (u32)0x40000000); /* inc[7] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 3
*/
void MCD_startDmaSingleEu(char *srcAddr, short srcIncr, char *destAddr, short destIncr, int dmaSize, short xferSizeIncr, int flags, int *currBD, int *cSave, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 8, (u32)srcAddr); /* var[8] */
MCD_SET_VAR(taskTable+channel, 25, (u32)(0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 3, (u32)destAddr); /* var[3] */
MCD_SET_VAR(taskTable+channel, 24, (u32)(0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 4, (u32)dmaSize); /* var[4] */
MCD_SET_VAR(taskTable+channel, 26, (u32)(0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 6, (u32)flags); /* var[6] */
MCD_SET_VAR(taskTable+channel, 2, (u32)currBD); /* var[2] */
MCD_SET_VAR(taskTable+channel, 0, (u32)cSave); /* var[0] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000001); /* var[10] */
MCD_SET_VAR(taskTable+channel, 11, (u32)0x00000004); /* var[11] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x08000000); /* var[12] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x00000000); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0xc0000000); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000000); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x80000001); /* inc[6] */
MCD_SET_VAR(taskTable+channel, 31, (u32)0x40000000); /* inc[7] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 4
*/
void MCD_startDmaENetRcv(char *bDBase, char *currBD, char *rcvFifoPtr, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 0, (u32)bDBase); /* var[0] */
MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */
MCD_SET_VAR(taskTable+channel, 6, (u32)rcvFifoPtr); /* var[6] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x0000ffff); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x30000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 11, (u32)0x0fffffff); /* var[11] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000008); /* var[12] */
MCD_SET_VAR(taskTable+channel, 24, (u32)0x00000000); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 25, (u32)0x60000000); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 26, (u32)0x20000004); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0x40000000); /* inc[3] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}
/*
* Task 5
*/
void MCD_startDmaENetXmit(char *bDBase, char *currBD, char *xmitFifoPtr, volatile TaskTableEntry *taskTable, int channel)
{
MCD_SET_VAR(taskTable+channel, 0, (u32)bDBase); /* var[0] */
MCD_SET_VAR(taskTable+channel, 3, (u32)currBD); /* var[3] */
MCD_SET_VAR(taskTable+channel, 11, (u32)xmitFifoPtr); /* var[11] */
MCD_SET_VAR(taskTable+channel, 1, (u32)0x00000000); /* var[1] */
MCD_SET_VAR(taskTable+channel, 2, (u32)0x00000000); /* var[2] */
MCD_SET_VAR(taskTable+channel, 4, (u32)0x00000000); /* var[4] */
MCD_SET_VAR(taskTable+channel, 5, (u32)0x00000000); /* var[5] */
MCD_SET_VAR(taskTable+channel, 6, (u32)0x00000000); /* var[6] */
MCD_SET_VAR(taskTable+channel, 7, (u32)0x00000000); /* var[7] */
MCD_SET_VAR(taskTable+channel, 8, (u32)0x00000000); /* var[8] */
MCD_SET_VAR(taskTable+channel, 9, (u32)0x00000000); /* var[9] */
MCD_SET_VAR(taskTable+channel, 10, (u32)0x00000000); /* var[10] */
MCD_SET_VAR(taskTable+channel, 12, (u32)0x00000000); /* var[12] */
MCD_SET_VAR(taskTable+channel, 13, (u32)0x0000ffff); /* var[13] */
MCD_SET_VAR(taskTable+channel, 14, (u32)0xffffffff); /* var[14] */
MCD_SET_VAR(taskTable+channel, 15, (u32)0x00000004); /* var[15] */
MCD_SET_VAR(taskTable+channel, 16, (u32)0x00000008); /* var[16] */
MCD_SET_VAR(taskTable+channel, 24, (u32)0x00000000); /* inc[0] */
MCD_SET_VAR(taskTable+channel, 25, (u32)0x60000000); /* inc[1] */
MCD_SET_VAR(taskTable+channel, 26, (u32)0x40000000); /* inc[2] */
MCD_SET_VAR(taskTable+channel, 27, (u32)0xc000fffc); /* inc[3] */
MCD_SET_VAR(taskTable+channel, 28, (u32)0xe0000004); /* inc[4] */
MCD_SET_VAR(taskTable+channel, 29, (u32)0x80000000); /* inc[5] */
MCD_SET_VAR(taskTable+channel, 30, (u32)0x4000ffff); /* inc[6] */
MCD_SET_VAR(taskTable+channel, 31, (u32)0xe0000001); /* inc[7] */
/* Set the task's Enable bit in its Task Control Register */
MCD_dmaBar->taskControl[channel] |= (u16)0x8000;
}

View File

@@ -0,0 +1,350 @@
/*
* BaS
*
*/
#include "MCF5475.h"
#include "startcf.h"
#include "MCD_dma.h"
#define MBAR_BASE_ADRS 0xff000000
#define MMAP_DMA 0x00008000
#define MMAP_SRAM 0x00010000
extern unsigned long far __SP_AFTER_RESET[];
extern unsigned long far __Bas_base[];
/* imported routines */
extern int mmu_init();
extern int mmutr_miss();
extern int vec_init();
extern int illegal_table_make();
extern int cf68k_initialize();
/********************************************************************/
/* warte_routinen /*
********************************************************************/
void warte_10ms(void)
{
asm
{
warte_10ms:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #1320000,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_1ms(void)
{
asm
{
warte_1ms:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #132000,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_100us(void)
{
asm
{
warte_100us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #13200,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_50us(void)
{
asm
{
warte_50us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #6600,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_10us(void)
{
asm
{
warte_10us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #1320,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_1us(void)
{
asm
{
warte_1us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #132,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
/********************************************************************/
void BaS(void)
{
int az_sectors;
int sd_status,i;
int status;
int dma_task_nr = 0;
az_sectors = sd_card_init();
if(az_sectors>0)
{
sd_card_idle();
}
/* variablenbereich setzen*/
asm
{
lea 0x1fc00000,a5
lea 0x1fd00000,a6
}
init_dma:
status =
MCD_initDma(
(dmaRegs*) (MBAR_BASE_ADRS + MMAP_DMA),
(void*) (MBAR_BASE_ADRS + MMAP_SRAM),
(MCD_RELOC_TASKS)
);
status = MCD_startDma(0, /*int channel, /* the channel on which to run the DMA */
(char*) (0xfff00000), /*s8 *srcAddr, /* the address to move data from, or physical buffer-descriptor address */
0, /*s16 srcIncr, /* the amount to increment the source address per transfer */
(char*) (0x12345678), /*s8 *destAddr, /* the address to move data to */
2, /*s16 destIncr, /* the amount to increment the destination address per transfer */
512, /*u32 dmaSize, /* the number of bytes to transfer independent of the transfer size */
2, /*u32 xferSize, /* the number bytes in of each data movement (1, 2, or 4) */
3, /*u32 initiator, /* what device initiates the DMA */
4, /*int priority, /* priority of the DMA */
MCD_SINGLE_DMA+
MCD_TT_FLAGS_CW+
MCD_TT_FLAGS_RL+
MCD_TT_FLAGS_SP, /*u32 flags, /* flags describing the DMA */
MCD_NO_BYTE_SWAP+
MCD_NO_BIT_REV /*u32 funcDesc /* a description of byte swapping, bit swapping, and CRC actions */
);
status =
MCD_dmaStatus(0);
MCD_killDma(0);
asm
{
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
beq firetos_kopieren
lea MCF_PSC0_PSCTB_8BIT,a6
lea MCF_PSC3_PSCTB_8BIT,a3
lea MCF_PSC3_PSCRB_8BIT,a4
lea MCF_PSC3_PSCRFCNT,a5
move.l #'ACPF',(a3) // SEND SYNC MARKE, MCF BEREIT
bsr warte_10ms
move.l #'PIC ',(a6)
move.b (a4),d0
move.b d0,(a6)
move.b (a4),d1
move.b d1,(a6)
move.b (a4),d2
move.b d2,(a6)
move.l #0x0a0d,(a6)
move.b #0x01,(a3) // RTC DATEN ANFORDERN
// TOS kopieren
lea 0x00e00000,a0
lea 0xe0600000,a1 // default tos
lea 0xe0700000,a2 // 1MB
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
bne cptos_loop
firetos_kopieren:
lea 0x00e00000,a0
lea 0xe0400000,a1
lea 0xe0500000,a2 // 1MB
cptos_loop:
move.l (a1)+,(a0)+
cmp.l a2,a1
blt cptos_loop
/***************************************************************/
/* div inits
/***************************************************************/
div_inits:
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
beq video_setup
// rtc daten, mmu set, etc nur wenn switch 6 = off
lea 0xffff8961,a0
clr.l d1
moveq #64,d2
move.b (a4),d0
cmp.b #0x81,d0
bne not_rtc
loop_sr:
move.b (a4),d0
move.b d1,(a0)
move.b d0,2(a0)
addq.l #1,d1
cmp.b d1,d2
bne loop_sr
move.b #63,(a0)
move.b 2(a0),d0
add #1,d0
move.b d0,2(a0)
not_rtc:
bsr mmu_init
bsr vec_init
bsr illegal_table_make
// interrupts
clr.l 0xf0010004 // disable all interrupts
lea MCF_EPORT_EPPAR,a0
move.w #0xaaa8,(a0) // falling edge all,
// timer 0 on mit int -> video change -------------------------------------------
move.l #MCF_GPT_GMS_ICT(1)|MCF_GPT_GMS_IEN|MCF_GPT_GMS_TMS(1),d0 //caputre mit int on rising edge
move.l d0,MCF_GPT0_GMS
moveq.l #0x3f,d0 // max prority interrutp
move.b d0,MCF_INTC_ICR62 // setzen
// -------------------------------------------------
move.b #0xfe,d0
move.b d0,0xf0010004 // enable int 1-7
nop
lea MCF_EPORT_EPIER,a0
move.b #0xfe,(a0) // int 1-7 on
nop
lea MCF_EPORT_EPFR,a0
move.b #0xff,(a0) // alle pending interrupts l<>schen
nop
lea MCF_INTC_IMRL,a0
move.l #0xFFFFFF00,(a0) // int 1-7 on
lea MCF_INTC_IMRH,a0
move.l #0xBFFFFFFE,(a0) // psc3 and timer 0 int on
move.l #MCF_MMU_MMUCR_EN,d0
move.l d0,MCF_MMU_MMUCR // mmu on
nop
nop
/********************************************************************/
/* IDE reset
/********************************************************************/
lea 0xffff8802,a0
move.b #14,-2(a0)
move.b #0x80,(a0)
bsr warte_1ms
clr.b (a0)
/********************************************************************/
/* video setup
/********************************************************************/
video_setup:
lea 0xf0000410,a0
// 25MHz
move.l #0x032002ba,(a0)+ // horizontal 640x480
move.l #0x020c020a,(a0)+ // vertikal 640x480
move.l #0x0190015d,(a0)+ // horizontal 320x240
move.l #0x020C020A,(a0)+ // vertikal 320x240 */
/*
// 32MHz
move.l #0x037002ba,(a0)+ // horizontal 640x480
move.l #0x020d020a,(a0)+ // vertikal 640x480
move.l #0x02A001e0,(a0)+ // horizontal 320x240
move.l #0x05a00160,(a0)+ // vertikal 320x240
*/
lea -0x20(a0),a0
move.l #0x01070002,(a0) // fifo on, refresh on, ddrcs und cke on, video dac on,
/********************************************************************/
/* memory setup
/********************************************************************/
lea 0x400,a0
lea 0x800,a1
mem_clr_loop:
clr.l (a0)+
clr.l (a0)+
clr.l (a0)+
clr.l (a0)+
cmp.l a0,a1
bgt mem_clr_loop
moveq #0x48,d0
move.b d0,0xffff8007
// stram
move.l #0xe00000,d0 // ende stram
move.l d0,0x42e
move.l #0x752019f3,d0 // memvalid
move.l d0,0x420
move.l #0x237698aa,d0 // memval2
move.l d0,0x43a
move.l #0x5555aaaa,d0 // memval3
move.l d0,0x51a
// ttram
move.l #__Bas_base,d0 // ende ttram
move.l d0,0x5a4
move.l #0x1357bd13,d0 // ramvalid
move.l d0,0x5a8
// init acia
moveq #3,d0
move.b d0,0xfffffc00
nop
move.b d0,0xfffffc04
nop
moveq #0x96,d0
move.b d0,0xfffffc00
moveq #-1,d0
nop
move.b d0,0xfffffa0f
nop
move.b d0,0xfffffa11
nop
// test auf protect mode ---------------------
move.b DIP_SWITCH,d0
btst #7,d0
beq no_protect // nein->
move.w #0x0700,sr
no_protect:
jmp 0xe00030
}
}

View File

@@ -0,0 +1,312 @@
/*
* BaS
*
*/
#include "MCF5475.h"
#include "startcf.h"
#include "MCD_dma.h"
#define MBAR_BASE_ADRS 0xff000000
#define MMAP_DMA 0x00008000
#define MMAP_SRAM 0x00010000
extern unsigned long far __SP_AFTER_RESET[];
extern unsigned long far __Bas_base[];
/* imported routines */
extern int mmu_init();
extern int mmutr_miss();
extern int vec_init();
extern int illegal_table_make();
extern int cf68k_initialize();
/********************************************************************/
/* warte_routinen /*
********************************************************************/
void warte_10ms(void)
{
asm
{
warte_10ms:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #1320000,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_1ms(void)
{
asm
{
warte_1ms:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #132000,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_100us(void)
{
asm
{
warte_100us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #13200,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_50us(void)
{
asm
{
warte_50us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #6600,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_10us(void)
{
asm
{
warte_10us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #1320,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
void warte_1us(void)
{
asm
{
warte_1us:
move.l d0,-(sp)
move.l MCF_SLT0_SCNT,d0
sub.l #132,d0
warte_d6:
cmp.l MCF_SLT0_SCNT,d0
bcs warte_d6
move.l (sp)+,d0
}
}
/********************************************************************/
void BaS(void)
{
int az_sectors;
int sd_status,i;
int status;
int dma_task_nr = 0;
az_sectors = sd_card_init();
if(az_sectors>0)
{
sd_card_idle();
}
asm
{
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
beq firetos_kopieren
lea MCF_PSC0_PSCTB_8BIT,a6
lea MCF_PSC3_PSCTB_8BIT,a3
lea MCF_PSC3_PSCRB_8BIT,a4
lea MCF_PSC3_PSCRFCNT,a5
move.l #'ACPF',(a3) // SEND SYNC MARKE, MCF BEREIT
bsr warte_10ms
move.l #'PIC ',(a6)
move.b (a4),d0
move.b d0,(a6)
move.b (a4),d1
move.b d1,(a6)
move.b (a4),d2
move.b d2,(a6)
move.l #0x0a0d,(a6)
move.b #0x01,(a3) // RTC DATEN ANFORDERN
// TOS kopieren
lea 0x00e00000,a0
lea 0xe0600000,a1 // default tos
lea 0xe0700000,a2 // 1MB
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
bne cptos_loop
firetos_kopieren:
lea 0x00e00000,a0
lea 0xe0400000,a1
lea 0xe0500000,a2 // 1MB
cptos_loop:
move.l (a1)+,(a0)+
cmp.l a2,a1
blt cptos_loop
/***************************************************************/
/* div inits
/***************************************************************/
div_inits:
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
beq video_setup
// rtc daten, mmu set, etc nur wenn switch 6 = off
lea 0xffff8961,a0
clr.l d1
moveq #64,d2
move.b (a4),d0
cmp.b #0x81,d0
bne not_rtc
loop_sr:
move.b (a4),d0
move.b d1,(a0)
move.b d0,2(a0)
addq.l #1,d1
cmp.b d1,d2
bne loop_sr
move.b #63,(a0)
move.b 2(a0),d0
add #1,d0
move.b d0,2(a0)
not_rtc:
bsr mmu_init
bsr vec_init
bsr illegal_table_make
// interrupts
clr.l 0xf0010004 // disable all interrupts
lea MCF_EPORT_EPPAR,a0
move.w #0xaaa8,(a0) // falling edge all,
// timer 0 on mit int -> video change -------------------------------------------
move.l #MCF_GPT_GMS_ICT(1)|MCF_GPT_GMS_IEN|MCF_GPT_GMS_TMS(1),d0 //caputre mit int on rising edge
move.l d0,MCF_GPT0_GMS
moveq.l #0x3f,d0 // max prority interrutp
move.b d0,MCF_INTC_ICR62 // setzen
// -------------------------------------------------
move.b #0xfe,d0
move.b d0,0xf0010004 // enable int 1-7
nop
lea MCF_EPORT_EPIER,a0
move.b #0xfe,(a0) // int 1-7 on
nop
lea MCF_EPORT_EPFR,a0
move.b #0xff,(a0) // alle pending interrupts l<>schen
nop
lea MCF_INTC_IMRL,a0
move.l #0xFFFFFF00,(a0) // int 1-7 on
lea MCF_INTC_IMRH,a0
move.l #0xBFFFFFFE,(a0) // psc3 and timer 0 int on
move.l #MCF_MMU_MMUCR_EN,d0
move.l d0,MCF_MMU_MMUCR // mmu on
nop
nop
/********************************************************************/
/* IDE reset
/********************************************************************/
lea 0xffff8802,a0
move.b #14,-2(a0)
move.b #0x80,(a0)
bsr warte_1ms
clr.b (a0)
/********************************************************************/
/* video setup
/********************************************************************/
video_setup:
lea 0xf0000410,a0
// 25MHz
move.l #0x032002ba,(a0)+ // horizontal 640x480
move.l #0x020c020a,(a0)+ // vertikal 640x480
move.l #0x0190015d,(a0)+ // horizontal 320x240
move.l #0x020C020A,(a0)+ // vertikal 320x240 */
/*
// 32MHz
move.l #0x037002ba,(a0)+ // horizontal 640x480
move.l #0x020d020a,(a0)+ // vertikal 640x480
move.l #0x02A001e0,(a0)+ // horizontal 320x240
move.l #0x05a00160,(a0)+ // vertikal 320x240
*/
lea -0x20(a0),a0
move.l #0x01070002,(a0) // fifo on, refresh on, ddrcs und cke on, video dac on,
/********************************************************************/
/* memory setup
/********************************************************************/
lea 0x400,a0
lea 0x800,a1
mem_clr_loop:
clr.l (a0)+
clr.l (a0)+
clr.l (a0)+
clr.l (a0)+
cmp.l a0,a1
bgt mem_clr_loop
moveq #0x48,d0
move.b d0,0xffff8007
// stram
move.l #0xe00000,d0 // ende stram
move.l d0,0x42e
move.l #0x752019f3,d0 // memvalid
move.l d0,0x420
move.l #0x237698aa,d0 // memval2
move.l d0,0x43a
move.l #0x5555aaaa,d0 // memval3
move.l d0,0x51a
// ttram
move.l #__Bas_base,d0 // ende ttram
move.l d0,0x5a4
move.l #0x1357bd13,d0 // ramvalid
move.l d0,0x5a8
// init acia
moveq #3,d0
move.b d0,0xfffffc00
nop
move.b d0,0xfffffc04
nop
moveq #0x96,d0
move.b d0,0xfffffc00
moveq #-1,d0
nop
move.b d0,0xfffffa0f
nop
move.b d0,0xfffffa11
nop
// test auf protect mode ---------------------
move.b DIP_SWITCH,d0
btst #7,d0
beq no_protect // nein->
move.w #0x0700,sr
no_protect:
jmp 0xe00030
}
}

View File

@@ -1,6 +1,7 @@
/*************************************************************************************************/
// extension word format: a0 zeigt auf code, in a1 ist ay, d0/d1 wird zerst<EFBFBD>rt
//------------------------------------------------------------------------------
#ifdef ii_on
.include "ii_macro.h"
@@ -1561,5 +1562,5 @@ ewff_lln:
add.l d0,a1
add.l d0,a1
rts
/****************************************************************************************************************
/************************************************************************/
#endif

View File

@@ -4,7 +4,7 @@
.include "startcf.h"
.extern ___Bas_base
.extern ___SDRAM_SIZE
.extern ___SUP_SP
.extern ___BOOT_FLASH
.extern ___RAMBAR0
@@ -362,7 +362,7 @@ access_mmu:
btst #1,d0
bne bus_error
move.l MCF_MMU_MMUAR,d0
cmp.l #___Bas_base,d0 // max User RAM Bereich
cmp.l #___SDRAM_SIZE,d0 // max User RAM Bereich
bge bus_error // gr<EFBFBD>sser -> bus error
bra _mmutr_miss
bus_error:
@@ -421,13 +421,13 @@ flpoow:
nop
irq1:
irq 0x64,1,0x02
irq2: // hbl
irq2: //vsync
// move.b #3,2(a7)
// rte
irq 0x68,2,0x04
irq3:
irq 0x6c,3,0x08
irq4: // vbl
irq4: // vsync
irq 0x70,4,0x10
irq5: // acp
irq 0x74,5,0x20

View File

@@ -1,7 +1,9 @@
.public _illegal_instruction
.public _illegal_table_make
.include "startcf.h"
#ifdef ii_on
.include "ii_macro.h"
.include "ii_func.h"
.include "ii_op.h"
@@ -19,6 +21,7 @@
.include "ii_movep.h"
.include "ii_ewf.h"
.include "ii_move.h"
#endif
.extern _ii_shift_vec
.extern ewf

View File

@@ -1,11 +0,0 @@
// letztes file der liste
// wichtig als endpunkt des kopierens
void copy_end(void)
{
asm
{
copy_end:
nop
}
}

View File

@@ -1,10 +0,0 @@
// letztes file der liste
// wichtig als endpunkt des kopierens
.global copy_end
.text
nop
copy_end:
nop
.asciz 'ende copy';

View File

@@ -5,7 +5,7 @@
#define __MBAR 0xff000000
#define MCF_SLT0_SCNT __MBAR + 0x908
#define MCF_PSC0_PSCTB_8BIT __MBAR + 0x860C
#define MCF_PAD_PAR_DSPI __MBAR + 0xA50
#define MCF_PAD_PAR_DSPI __MBAR + 0xa30
#define MCF_DSPI_DMCR __MBAR + 0x8A00 //dspi control
#define dspi_dtar0 0x0c
@@ -115,7 +115,7 @@ int sd_card_init(void)
move.l #'SD-C',(a1)
move.l #'ard ',(a1)
move.l buffer,a5 // basis addresse (diesen bereich brauchen wir nicht mehr!)
move.l buffer,a3 // basis addresse (diesen bereich brauchen wir nicht mehr!)
move.l #0x1fffffff,d0 // normal dspi
move.l d0,MCF_PAD_PAR_DSPI
lea MCF_DSPI_DMCR,a0
@@ -301,11 +301,11 @@ read_cid:
move.b #0x95,d4
bsr sd_com
move.l a5,a2 // adresse setzen
move.l a3,a2 // adresse setzen
bsr sd_rcv_info
// name ausgeben
lea 1(a5),a2
lea 1(a3),a2
moveq #7,d7
sd_nam_loop:
move.b (a2)+,(a1)
@@ -330,19 +330,19 @@ read_csd:
move.b #0x01,d4
bsr sd_com
move.l a5,a2 // adresse setzen
move.l a3,a2 // adresse setzen
bsr sd_rcv_info
mvz.b (a5),d0
mvz.b (a3),d0
lsr.l #6,d0
bne sd_csd2 // format v2
move.l 6(a5),d1
move.l 6(a3),d1
moveq #14,d0 // bit 73..62 c_size
lsr.l d0,d1 // bits extrahieren
and.l #0xfff,d1 // 12 bits
addq.l #1,d1
mvz.w 9(a5),d0
mvz.w 9(a3),d0
lsr.l #7,d0 // bits 49..47
and.l #0x7,d0 // 3 bits
moveq.l #8,d2 // x256 (dif v1 v2)
@@ -350,7 +350,7 @@ read_csd:
lsr.l d2,d1
bra sd_print_size
sd_csd2:
mvz.w 8(a5),d1
mvz.w 8(a3),d1
addq.l #1,d1
sd_print_size:
swap d1
@@ -468,7 +468,7 @@ sd_rs_end:
int sd_card_sector_read(long sec_nr,long buf_adr)
{
int status ;
int status=0 ;
asm
{
lea MCF_DSPI_DMCR,a0
@@ -554,7 +554,7 @@ sd_send_end:
int sd_card_sector_write(long sec_nr,long buf_adr)
{
int status;
int status=0;
asm
{
lea MCF_DSPI_DMCR,a0

View File

@@ -1,406 +0,0 @@
/********************************************************************/
// sd card
/********************************************************************/
#define dspi_dtar0 0x0c
#define dspi_dsr 0x2c
#define dspi_dtfr 0x34
#define dspi_drfr 0x38
.text
sd_test:
lea MCF_PSC0_PSCTB_8BIT,a6
move.l #'SD-C',(a6)
move.l #'ard ',(a6)
move.l #__Bas_base,a5 // basis addresse (diesen bereich brauchen wir nicht mehr!)
move.l #0x1fffffff,d0 // normal dspi
move.l d0,MCF_PAD_PAR_DSPI
lea MCF_DSPI_DMCR,a0
move.l #0x800d3c00,(a0) // 8 bit cs5 on
move.l #0x38558897,d0
move.l d0,dspi_dtar0(a0) // 400kHz
move.l #0x082000ff,d4 // tx vorbesetzen
mov3q.l #-1,dspi_dsr(a0)
bsr warte_1ms
move.l #0xc00d3c00,(a0) // 8 bit 4MHz clocken cs off
bsr warte_10ms
move.l #0x800d3c00,(a0) // 8 bit 4MHz normal cs on
bsr sd_com
bsr sd_com
bsr sd_com
bsr sd_com
bsr sd_com
bsr sd_com
bsr sd_com
bsr sd_com
bsr sd_com
bsr sd_com
move.l #0x802d3c00,(a0) // 8 bit 4MHz normal cs off
clr.b d4
bsr sd_com
bsr sd_com
move.l #0x800d3c00,(a0) // 8 bit 4MHz normal cs on
move.b #0xff,d4
bsr sd_com
bsr sd_com
move.l #0x802d3c00,(a0) // 8 bit 4MHz normal cs off
bsr warte_10ms
// sd idle
move.l #100,d6 // 100 versuche
move.l #10,d3 // 10 versuche
sd_idle:
move.b #0xff,d4 // receive byt
bsr sd_com
move.b #0x40,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #0x95,d4
bsr sd_com
move.b #0xff,d4 // receive byt
bsr sd_com
cmp.b #0x01,d5
beq idle_end
bsr sd_com
cmp.b #0x01,d5
beq idle_end
bsr sd_com
cmp.b #0x01,d5
beq idle_end
bsr sd_com
cmp.b #0x01,d5
beq idle_end
bsr sd_com
cmp.b #0x01,d5
beq idle_end
bsr sd_com
cmp.b #0x01,d5
beq idle_end
subq.l #1,d6
beq sd_not
bra sd_idle
idle_end:
// cdm 8
read_ic:
move.b #0xff,d4 // receive byt
bsr sd_com
move.b #0x48,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #0x01,d4
bsr sd_com
move.b #0xaa,d4
bsr sd_com
move.b #0x87,d4
bsr sd_com
bsr sd_get_status
cmp.b #5,d5
beq sd_v1
cmp.b #1,d5
bne read_ic
move.b #0xff,d4
bsr sd_com
move.b d5,d0
bsr sd_com
move.b d5,d1
bsr sd_com
move.b d5,d2
bsr sd_com
cmp.b #0xaa,d5
bne sd_testd3
move.l #'SDHC',(a6)
move.b #' ',(a6)
sd_v1:
// cdm 58
read_ocr:
move.b #0xff,d4 // receive byt
bsr sd_com
move.b #0x7a,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #0x00,d4
bsr sd_com
move.b #0x00,d4
bsr sd_com
move.b #0x01,d4
bsr sd_com
bsr sd_get_status
move.l #'Ver1',d6
cmp.b #5,d5
beq read_ocr
cmp.b #1,d5
bne read_ocr
move.b #0xff,d4
bsr sd_com
move.b d5,d0
bsr sd_com
move.b d5,d1
bsr sd_com
move.b d5,d2
bsr sd_com
// acdm 41
move.l #20000,d6 // 20000 versuche ready can bis 1 sec gehen
wait_of_aktiv:
move.b #0xff,d4 // receive byt
bsr sd_com
move.b #0x77,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #0x95,d4
bsr sd_com
bsr sd_get_status
cmp.b #0x05,d5
beq wait_of_aktiv
wait_of_aktiv2:
move.b #0xff,d4 // receive byt
bsr sd_com
move.b #0x69,d4
bsr sd_com
move.b #0x40,d4
bsr sd_com
move.b #0x00,d4
bsr sd_com
move.b #0x00,d4
bsr sd_com
move.b #0x00,d4
bsr sd_com
move.b #0x95,d4
bsr sd_com
bsr sd_get_status
tst.b d5
beq sd_init_ok
cmp.b #0x05,d5
beq wait_of_aktiv2
subq.l #1,d6
bne wait_of_aktiv
sd_testd3:
subq.l #1,d3
bne sd_idle
bra sd_error
sd_init_ok:
// cdm 10
read_cid:
move.b #0xff,d4 // receive byt
bsr sd_com
move.b #0x4a,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #0x00,d4
bsr sd_com
move.b #0x00,d4
bsr sd_com
move.b #0x95,d4
bsr sd_com
move.l a5,a4 // adresse setzen
bsr sd_rcv_info
// name ausgeben
lea 1(a5),a4
moveq #7,d7
sd_nam_loop:
move.b (a4)+,(a6)
subq.l #1,d7
bne sd_nam_loop
move.b #' ',(a6)
// cdm 9
read_csd:
move.b #0xff,d4 // receive byt
bsr sd_com
move.b #0x49,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #00,d4
bsr sd_com
move.b #0x00,d4
bsr sd_com
move.b #0x00,d4
bsr sd_com
move.b #0x01,d4
bsr sd_com
move.l a5,a4 // adresse setzen
bsr sd_rcv_info
mvz.b (a5),d0
lsr.l #6,d0
bne sd_csd2 // format v2
move.l 6(a5),d1
moveq #14,d0 // bit 73..62 c_size
lsr.l d0,d1 // bits extrahieren
and.l #0xfff,d1 // 12 bits
addq.l #1,d1
mvz.w 9(a5),d0
lsr.l #7,d0 // bits 49..47
and.l #0x7,d0 // 3 bits
moveq.l #8,d2 // x256 (dif v1 v2)
sub.l d0,d2
lsr.l d2,d1
bra sd_print_size
sd_csd2:
mvz.w 8(a5),d1
addq.l #1,d1
sd_print_size:
swap d1
lsl.l #1,d1
bcc sd_16G
move.l #'32GB',(a6)
bra sd_ok
sd_16G:
lsl.l #1,d1
bcc sd_8G
move.l #'16GB',(a6)
bra sd_ok
sd_8G:
lsl.l #1,d1
bcc sd_4G
move.l #' 8GB',(a6)
bra sd_ok
sd_4G:
lsl.l #1,d1
bcc sd_2G
move.l #' 4GB',(a6)
bra sd_ok
sd_2G:
lsl.l #1,d1
bcc sd_1G
move.l #' 2GB',(a6)
bra sd_ok
sd_1G:
lsl.l #1,d1
bcc sd_512M
move.l #' 1GB',(a6)
bra sd_ok
sd_512M:
lsl.l #1,d1
bcc sd_256M
move.b #'5',(a6)
move.l #'12MB',(a6)
bra sd_ok
sd_256M:
lsl.l #1,d1
bcc sd_128M
move.b #'2',(a6)
move.l #'56MB',(a6)
bra sd_ok
sd_128M:
lsl.l #1,d1
bcc sd_64M
move.b #'1',(a6)
move.l #'28MB',(a6)
bra sd_ok
sd_64M:
lsl.l #1,d1
bcc sd_32M
move.l #'64MB',(a6)
bra sd_ok
sd_32M:
lsl.l #1,d1
bcc sd_16M
move.l #'32MB',(a6)
bra sd_ok
sd_16M:
lsl.l #1,d1
bcc sd_8M
move.l #'16MB',(a6)
bra sd_ok
sd_8M:
move.l #'<9MB',(a6)
sd_ok:
move.l #' OK!',(a6)
move.l #0x0a0d,(a6)
halt
halt
rts
// subs ende -------------------------------
sd_V1:
move.l #'non!',(a6)
move.l #0x0a0d,(a6)
halt
halt
rts
sd_error:
move.l #'Erro',(a6)
move.l #'r!',(a6)
move.l #0x0a0d,(a6)
halt
halt
rts
sd_not:
move.l #'non!',(a6)
move.l #0x0a0d,(a6)
halt
halt
rts
// status holen -------------------------------
sd_get_status:
move.b #0xff,d4
bsr sd_com
cmp.b #0xff,d5
beq sd_get_status
rts
// byt senden und holen ---------------------
sd_com:
move.l d4,dspi_dtfr(a0)
wait_auf_complett:
btst.b #7,dspi_dsr(a0)
beq wait_auf_complett
move.l dspi_drfr(a0),d5
mov3q.l #-1,dspi_dsr(a0) // clr status register
rts
// daten holen ----------------------------
sd_rcv_info:
moveq #18,d3 // 16 byts + 2 byts crc
move.b #0xff,d4
sd_rcv_rb_w:
bsr sd_get_status
cmp.b #0xfe,d5 // daten bereit?
bne sd_rcv_rb_w // nein->
sd_rcv_rd_rb:
bsr sd_com
move.b d5,(a4)+
subq.l #1,d3
bne sd_rcv_rd_rb
rts
/******************************************/

View File

@@ -1,458 +0,0 @@
//.include "startcf.h"
//.extern ___MBAR
//#define MCF_SLT0_SCNT ___MBAR+0x908
//.global ide_test
.text
/*
sd_test:
clr.w MCF_PAD_PAR_DSPI
lea MCF_GPIO_PPDSDR_DSPI,a2 // data in
lea MCF_GPIO_PODR_DSPI,a1 // data out
move.b #0x00,(a1) // alle auf 0
lea MCF_GPIO_PDDR_DSPI,a0
move.b #0x7d,(a0) // din = input rest output
bsr warten_20ms
move.b #0x7f,(a1) // alle auf 1
bsr sd_16clk
bsr sd_16clk
bsr sd_16clk
bsr sd_16clk
bsr sd_16clk
bsr sd_16clk
bsr sd_16clk
bsr sd_16clk
// sd idle
sd_idle:
bsr sd_16clk
moveq #0x40,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #0x95,d4
bsr sd_com
bsr sd_receive
cmp.b #0x05,d5
beq sd_test
cmp.b #0x01,d5
beq wait_of_aktiv
cmp.b #0x04,d5
beq sd_init_ok
cmp.b #0x00,d5
beq sd_init_ok
bra sd_idle
// acdm 41
wait_of_aktiv:
bsr sd_16clk
moveq #0x77,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #0x01,d4
bsr sd_com
bsr sd_receive
bsr sd_16clk
move.l #0xff,d6
moveq #0x69,d4
bsr sd_com
and d5,d6
moveq #00,d4
bsr sd_com
and d5,d6
moveq #00,d4
bsr sd_com
and d5,d6
moveq #0x02,d4
bsr sd_com
and d5,d6
moveq #00,d4
bsr sd_com
and d5,d6
moveq #0x01,d4
bsr sd_com
and d5,d6
bsr sd_receive
cmp.b #0x00,d5
beq sd_init_ok
cmp.b #0x05,d5
beq sd_test
bra wait_of_aktiv
sd_init_ok:
// blockgr<EFBFBD>sse 512byt
sd_bg:
bsr sd_16clk
moveq #0x50,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #02,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #0x01,d4
bsr sd_com
bsr sd_receive
cmp.b #0x00,d5
bne sd_bg
// read block
sd_rb:
bsr sd_16clk
moveq #0x51,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #0x08,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #0x01,d4
bsr sd_com
bsr sd_receive
cmp.b #0x00,d5
bne sd_rb
lea 0xc00000,a4
move.l #513,d7
rd_rb:
bsr sd_receive
move.b d5,(a4)+
subq.l #1,d7
bne rd_rb
// write block
sd_wb:
bsr sd_16clk
moveq #0x58,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #0x08,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #0x01,d4
bsr sd_com
bsr sd_receive
cmp.b #0x00,d5
bne sd_wb
lea 0xc00000,a4
move.l #513,d7
moveq.l #0x66,d4
wr_wb:
bsr sd_com
// subq.l #1,d4
moveq #0x66,d4
subq.l #1,d7
bne wr_wb
bsr sd_receive
wr_wb_el:
moveq #0xff,d4
bsr sd_com
cmp.b #0xff,d5
bne wr_wb_el
// read block 2
sd_rb2:
bsr sd_16clk
moveq #0x51,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #0x08,d4
bsr sd_com
moveq #00,d4
bsr sd_com
moveq #0x01,d4
bsr sd_com
bsr sd_receive
cmp.b #0x00,d5
bne sd_rb2
lea 0xc00400,a4
move.l #513,d7
rd_rb2:
bsr sd_receive
move.b d5,(a4)+
subq.l #1,d7
bne rd_rb2
nop
nop
rts
sd_receive:
moveq #0xff,d4
bsr sd_com
cmp.b #0xff,d5
beq sd_receive
rts
sd_com:
bclr.b #6,(a1)
sd_comb:
bsr warten_10us
moveq #7,d2
clr.l d5
sd_com_loop:
btst d2,d4
beq sd_com2
bset.b #0,(a1)
bra sd_com2_1
sd_com2:
bclr.b #0,(a1)
sd_com2_1:
bsr sd_clk
and.l #0x02,d3
beq sd_com3
bset.b d2,d5
sd_com3:
subq.l #1,d2
bge sd_com_loop
bsr warten_10us
bset.b #6,(a1)
bset.b #0,(a1)
bsr warten_200us
rts
sd_clk:
tst.b 0xfffff700
tst.b 0xfffff700
bset.b #2,(a1)
tst.b 0xfffff700
tst.b 0xfffff700
move.b (a2),d3
tst.b 0xfffff700
bclr.b #2,(a1)
rts
sd_15clk:
move #15,d0
bra sd_16clk
sd_16clk:
moveq #16,d0
sd_16clk1:
bsr sd_clk
subq.l #1,d0
bne sd_16clk1
bsr warten_10us
rts
// warteschleife ca. 20ms
warten_20ms:
move.l a0,-(sp)
move.l d6,-(sp)
move.l d1,-(sp)
move.l d0,-(sp)
lea MCF_SLT0_SCNT,a0
move.l (a0),d0
move.l #700000,d6
bra warten_loop
// warteschleife ca. 200us
warten_200us:
move.l a0,-(sp)
move.l d6,-(sp)
move.l d1,-(sp)
move.l d0,-(sp)
lea MCF_SLT0_SCNT,a0
move.l (a0),d0
move.l #7000,d6
bra warten_loop
// warteschleife ca. 10us
warten_10us:
move.l a0,-(sp)
move.l d6,-(sp)
move.l d1,-(sp)
move.l d0,-(sp)
lea MCF_SLT0_SCNT,a0
move.l (a0),d0
move.l #333,d6
warten_loop:
move.l (a0),d1
sub.l d0,d1
add.l d6,d1
bpl warten_loop
move.l (sp)+,d0
move.l (sp)+,d1
move.l (sp)+,d6
move.l (sp)+,a0
rts;
/********************************************************************/
#define cmd_reg (0x1d)
#define status_reg (0x1d)
#define seccnt (0x09)
ide_test:
lea 0xfff00040,a0
lea 0xc00000,a1
move.b #0xec,cmd_reg(a0) //identify devcie cmd
bsr wait_int
bsr ds_rx
// read sector normal
move.b #1,seccnt(a0) // 1 sector
move.b #0x20,cmd_reg(a0) // read cmd
bsr wait_int
bsr ds_rx
// write testpattern sector
move.b #1,seccnt(a0) // 1 sector
move.b #0x30,cmd_reg(a0) // write cmd
bsr drq_wait
// write pattern
move.l #256,d0
ide_test_loop3:
move.w #0xa55a,(a0)
subq.l #1,d0
bne ide_test_loop3
bsr wait_int
// read testpattern sector
move.b #1,seccnt(a0) // 1 sector
move.b #0x20,cmd_reg(a0) // read
bsr wait_int
bsr ds_rx
// sector restauriern
move.b #1,seccnt(a0) // 1 sector
move.b #0x30,cmd_reg(a0) // write
lea -0x400(a1),a1 // vorletzer
bsr drq_wait
bsr ds_tx
bsr wait_int
// fertig und zur<EFBFBD>ck
nop
rts
// wait auf int
wait_int:
move.b 0xfffffa01,d0
btst #5,d0
bne wait_int
move.b status_reg(a0),d0
rts
// wait auf drq
drq_wait:
move.b status_reg(a0),d0
btst #3,d0
beq drq_wait
rts
// 1 sector lesen word
ds_rx:
move.l #256,d0
ds_rx_loop:
move.w (a0),(a1)+
subq.l #1,d0
bne ds_rx_loop
rts
// 1 sector lesen long
ds_rxl:
move.l #128,d0
ds_rxl_loop:
move.l (a0),(a1)+
subq.l #1,d0
bne ds_rxl_loop
rts
// 1 sector schreiben word
ds_tx:
move.l #256,d0
ds_tx_loop:
move.w (a1)+,(a0)
subq.l #1,d0
bne ds_tx_loop
rts
// 1 sector schreiben word
ds_txl:
move.l #128,d0
ds_txl_loop:
move.l (a1)+,(a0)
subq.l #1,d0
bne ds_txl_loop
rts
// warteschleife ca. 20ms
warten_20ms:
move.l a0,-(sp)
move.l d6,-(sp)
move.l d1,-(sp)
move.l d0,-(sp)
lea MCF_SLT0_SCNT,a0
move.l (a0),d0
move.l #700000,d6
bra warten_loop
// warteschleife ca. 200us
warten_200us:
move.l a0,-(sp)
move.l d6,-(sp)
move.l d1,-(sp)
move.l d0,-(sp)
lea MCF_SLT0_SCNT,a0
move.l (a0),d0
move.l #7000,d6
bra warten_loop
// warteschleife ca. 10us
warten_10us:
move.l a0,-(sp)
move.l d6,-(sp)
move.l d1,-(sp)
move.l d0,-(sp)
lea MCF_SLT0_SCNT,a0
move.l (a0),d0
move.l #333,d6
warten_loop:
move.l (a0),d1
sub.l d0,d1
add.l d6,d1
bpl warten_loop
move.l (sp)+,d0
move.l (sp)+,d1
move.l (sp)+,d6
move.l (sp)+,a0
rts;
/********************************************************************/

View File

@@ -0,0 +1,134 @@
/******************************************
// setze zugriffsgeschwindigkeit cf card
/********************************************************************/
#include "MCF5475.h"
#define error_reg (0x05)
#define seccnt (0x09)
#define stasec (0x0d)
#define cmd_reg (0x1d)
#define status_reg (0x1d)
#define wati (200)
extern void warte_10ms();
extern void warte_10us();
void ds_rx(void)
{
asm
{
// 1 sector lesen word
ds_rx:
move.l #128,d0
move.l a1,a0
ds_rx_loop:
move.l (a2),(a0)+
subq.l #1,d0
bne ds_rx_loop
}
};
void test_drive(void)
{
asm
{
moveq.l #11,d1 // default access (3) mode not wait (+8)
// reset
ide_reset:
clr.b 0x19(a2)
move.b #0x8,cmd_reg(a2) // device reset
move.l #wati,d0 // max. 2s warten
wait_ready:
tst.b status_reg(a2) // comando fertig?
bpl ide_ready // nein
subq.l #1,d0
bmi dam_nok // nicht da -> default werwenden
bsr warte_10ms
bra wait_ready
ide_ready:
clr.b 0x19(a2)
move.b #0xec,cmd_reg(a2) // identify devcie
move.l #wati,d0 // max. 2s warten
wait_busy:
tst.b status_reg(a2) // laufwerk bereit?
bpl ide_busy
subq.l #1,d0
bmi dam_nok // nicht da -> default werwenden
bsr warte_10ms
bra wait_busy
ide_busy:
clr.l (a1)
btst #3,status_reg(a2)
beq non_data
bsr ds_rx
tst.l (a1)
bne dam_ok
non_data:
subq.l #1,d3
bmi dam_nok
bra ide_ready
dam_ok:
tst.b status_reg(a2) // interrupt r<>ckstellen
lea MCF_PSC0_PSCTB_8BIT,a2 // name ausgeben
lea 54(a1),a0
moveq.l #40,d0
name_loop:
move.b (a0)+,(a2)
subq.l #1,d0
bne name_loop
move.l #' OK!',(a2)
move.l #0x0a0d,(a2)
moveq.l #3,d1
clr.l d0
move.w 2*68(a1),d0 // pio cycle time
lsr.l #5,d0 // :32(ns)
subq.l #1,d0
bmi siam_fertig
move.w d0,d1
siam_fertig:
cmp.w #3,d1 // gr<67>sser als max?
ble dam_nok
moveq.l #3,d1 // sonst default
dam_nok:
}
};
void set_ide_access_mode(void)
{
asm
{
lea 0xf0040000,a3
bset.b #1,(a3) // ide reset
bsr warte_10ms
move.w #0x1033,(a3) // 1.cf 2.ide, ide int activ, scsi int disable, speed = min
bsr warte_10ms
lea 0xfff00000,a2
lea 0xc00000,a1
}
test_drive();
asm
{
move.b d1,d2
}
asm
{
lea 0xfff00040,a2
lea 0xc00000,a1
}
test_drive();
asm
{
lsl.l #4,d1
or.l d1,d2
move.b d2,1(a3)
}
/********************************************************************/
};

View File

@@ -19,11 +19,12 @@
#ifdef __cplusplus
#pragma cplusplus off
#endif
#pragma PID off
#pragma PID off
#pragma PIC off
#include "MCF5475.h"
#include "startcf.h"
#include "RuntimeConfig.h"
/* imported data */
@@ -31,53 +32,99 @@ extern unsigned long far _SP_INIT, _SDA_BASE;
extern unsigned long far _START_BSS, _END_BSS;
extern unsigned long far _START_SBSS, _END_SBSS;
extern unsigned long far __DATA_RAM, __DATA_ROM, __DATA_END;
extern unsigned long far __Bas_base;
extern unsigned long far __SUP_SP,__BOOT_FLASH;
extern unsigned long far rt_mbar;
extern unsigned long far _S_romp;
/* imported routines */
extern int BaS(int, char **);
/* exported routines */
extern void __initialize_hardware(void);
extern void init_slt(void);
extern void BaS(void);
void _startup(void)
{
asm
{
bra warmstart
jmp __BOOT_FLASH + 8 // ist zugleich reset vector
/* disable interrupts */
warmstart:
// disable interrupts
move.w #0x2700,sr
// Initialize MBAR
MOVE.L #__MBAR,D0
MOVEC D0,MBAR
move.l d0,rt_mbar
// mmu off
move.l #__MMUBAR+1,d0
movec d0,MMUBAR //mmubar setzen
clr.l d0
move.l d0,MCF_MMU_MMUCR // mmu off
/* Initialize RAMBARs: locate SRAM and validate it */ \
move.l #__RAMBAR0 + 0x7,d0 // supervisor only
movec d0,RAMBAR0
move.l #__RAMBAR1 + 0x1,d0 // on for all
movec d0,RAMBAR1
{
bra warmstart
jmp __BOOT_FLASH + 8 // ist zugleich reset vector
/* disable interrupts */
warmstart:
// disable interrupts
move.w #0x2700,sr
// Initialize MBAR
MOVE.L #__MBAR,D0
MOVEC D0,MBAR
move.l d0,rt_mbar
// mmu off
move.l #__MMUBAR+1,d0
movec d0,MMUBAR //mmubar setzen
clr.l d0
move.l d0,MCF_MMU_MMUCR // mmu off
/* Initialize RAMBARs: locate SRAM and validate it */ \
move.l #__RAMBAR0 + 0x7,d0 // supervisor only
movec d0,RAMBAR0
move.l #__RAMBAR1 + 0x1,d0 // on for all
movec d0,RAMBAR1
// STACKPOINTER AUF ENDE SRAM1
lea __SUP_SP,a7
// STACKPOINTER AUF ENDE SRAM1
lea __SUP_SP,a7
// hardware initieren
jsr __initialize_hardware
// STACKPOINTER AUF ENDE SRAM1
lea __SUP_SP,a7
/* setup A6 dummy stackframe */
movea.l #0,a6
link a6,#0
/* setup A5 */
lea _SDA_BASE,a5
/* copy all ROM sections to their RAM locations ... */
/*
* _S_romp is a null terminated array of
* typedef struct RomInfo {
* unsigned long Source;
* unsigned long Target;
* unsigned long Size;
* } RomInfo;
*
* Watch out if you're rebasing using _PICPID_DELTA
*/
lea _S_romp, a0
move.l (a0),a1
move.l 4(a0),a2
move.l 8(a0),d0
lsr.l #2,d0
crr_loop:
move.l (a1)+,(a2)+
subq.l #1,d0
bne crr_loop
/* call main(int, char **) */
pea __argv
clr.l -(sp) /* clearing a long is ok since it's caller cleanup */
jsr BaS
addq.l #8, sp
// instruction cache on
move.l #0x000C8100,d0
movec d0,cacr
nop
// initialize any hardware specific issues
bra __initialize_hardware
unlk a6
/* should never reach here but just in case */
jsr warmstart
illegal
rts
/* exit will never return */
__argv:
dc.l 0
};
}
}

View File

@@ -7,18 +7,20 @@
*/
#include "MCF5475.h"
#include "startcf.h"
#include "RuntimeConfig.h"
extern unsigned long far __VRAM;
extern unsigned long far __Bas_base;
extern unsigned long far BaS;
extern unsigned long far __BOOT_FLASH[];
extern int copy_end();
extern int warte_10us();
extern int warte_1ms();
extern int warte_10ms();
extern int warte_50us();
extern void warte_10us();
extern void warte_1ms();
extern void set_ide_access_mode();
extern unsigned long far rt_cacr;
extern unsigned long far rt_acr0;
extern unsigned long far rt_acr1;
extern unsigned long far rt_acr2;
extern unsigned long far rt_acr3;
extern unsigned long far rt_mmubar;
/********************************************************************/
// init SLICE TIMER 0
@@ -119,7 +121,17 @@ void init_seriel(void)
MCF_PSC3_PSCCR = 0x05;
MCF_INTC_ICR32 = 0x3F; //MAXIMALE PRIORITY/**********/
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
MCF_PSC0_PSCTB_8BIT = 0x0a0a0a0d;
MCF_PSC0_PSCTB_8BIT = 'BaS ';
MCF_PSC0_PSCTB_8BIT = '13.0';
MCF_PSC0_PSCTB_8BIT = '5.20';
MCF_PSC0_PSCTB_8BIT = '17';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
MCF_PSC0_PSCTB_8BIT = '====';
MCF_PSC0_PSCTB_8BIT = '====';
MCF_PSC0_PSCTB_8BIT = '====';
MCF_PSC0_PSCTB_8BIT = '==';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
MCF_PSC0_PSCTB_8BIT = 'SERI';
MCF_PSC0_PSCTB_8BIT = 'AL O';
MCF_PSC0_PSCTB_8BIT = 'K! ';
@@ -175,39 +187,43 @@ void init_ddram(void)
/********************************************************************/
void init_fbcs()
{
MCF_PSC0_PSCTB_8BIT = 'FBCS';
/* Flash */
MCF_FBCS0_CSAR = 0xE0000000; // FLASH ADRESS
MCF_FBCS0_CSCR = 0x00001180; // 16 bit 4ws aa
MCF_FBCS0_CSMR = 0x007F0001; // 8MB on
MCF_PSC0_PSCTB_8BIT = 'FBCS';
MCF_FBCS1_CSAR = 0xFFF00000; // ATARI I/O ADRESS
MCF_FBCS1_CSAR = 0xFFF80000; // FFF8'0000-FFFF'FFFF: ATARI I/O ADRESS
MCF_FBCS1_CSCR = MCF_FBCS_CSCR_PS_16 // 16BIT PORT
| MCF_FBCS_CSCR_WS(8) // DEFAULT 8WS
| MCF_FBCS_CSCR_AA; // AA
MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_1M
| MCF_FBCS_CSCR_WS(63) // DEFAULT 63WS
| MCF_FBCS_CSCR_AA; // AA
MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
| MCF_FBCS_CSMR_V);
MCF_FBCS2_CSAR = 0xF0000000; // NEUER I/O ADRESS-BEREICH
MCF_FBCS2_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT
| MCF_FBCS_CSCR_WS(8) // DEFAULT 4WS
| MCF_FBCS_CSCR_WS(8) // DEFAULT 8WS
| MCF_FBCS_CSCR_AA; // AA
MCF_FBCS2_CSMR = (MCF_FBCS_CSMR_BAM_128M // F000'0000-F7FF'FFFF
| MCF_FBCS_CSMR_V);
MCF_FBCS3_CSAR = 0xF8000000; // NEUER I/O ADRESS-BEREICH
MCF_FBCS3_CSAR = 0xFFF00000; // IDE I/O ADRESS-BEREICH BURST!
MCF_FBCS3_CSCR = MCF_FBCS_CSCR_PS_16 // 16BIT PORT
| MCF_FBCS_CSCR_WS(16) // DEFAULT 16WS
| MCF_FBCS_CSCR_BSTR // Burst read enable
| MCF_FBCS_CSCR_BSTW // Burst write enable
| MCF_FBCS_CSCR_AA; // AA
MCF_FBCS3_CSMR = (MCF_FBCS_CSMR_BAM_64M // F800'0000-FBFF'FFFF
MCF_FBCS3_CSMR = (MCF_FBCS_CSMR_BAM_512K // FFF0'0000-FFF7'FFFF
| MCF_FBCS_CSMR_V);
MCF_FBCS4_CSAR = 0x40000000; // VIDEO RAM BEREICH, #FB_CS3 WIRD NICHT BEN<45>TZT, DECODE DIREKT AUF DEM FPGA
MCF_FBCS4_CSAR = 0x40000000; // VIDEO RAM BEREICH,
MCF_FBCS4_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT
| MCF_FBCS_CSCR_BSTR // BURST READ ENABLE
| MCF_FBCS_CSCR_BSTW; // BURST WRITE ENABLE
MCF_FBCS4_CSMR = (MCF_FBCS_CSMR_BAM_1G // 4000'0000-7FFF'FFFF
| MCF_FBCS_CSMR_V);
/* Flash */
MCF_FBCS0_CSAR = 0xE0000000; // FLASH ADRESS
MCF_FBCS0_CSCR = 0x00001180; // 16 bit 4ws aa
MCF_FBCS0_CSMR = 0x007F0001; // 8MB on
MCF_PSC0_PSCTB_8BIT = ' OK!';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
}
@@ -241,23 +257,87 @@ test_STATUS:
jsr warte_10us // warten
lea 0xE0700000,a0 // startadresse fpga daten
moveq #0x4,d2
moveq #0x6,d3
moveq #0xc,d4
moveq #0xe,d5
word_send_loop:
cmp.l #0xE0800000,a0
bgt fpga_error
move.b (a0)+,d0 // 32 bit holen
moveq #8,d1 // 32 bit ausgeben
bit_send_loop:
lsr.l #1,d0 // bit rausschieben
bcs bit_is_1
bclr #3,(a1)
bra bit_send
bit_is_1:
bset #3,(a1)
bit_send:
bset #1,(a1) // clock=high
bclr #1,(a1) // clock=low
subq.l #1,d1
bne bit_send_loop // wiederholen bis fertig
bcs bit_is_10 // data bit3, #config bit2, clock bit1
move.b d2,(a1) // data low, config high, clk low
move.b d3,(a1) // data low, config high, clk high
bra bit_send0
bit_is_10:
move.b d4,(a1) // clk low, config high, data high
move.b d5,(a1) // clk high, config high, data high
bit_send0:
lsr.l #1,d0 // bit rausschieben
bcs bit_is_11 // data bit3, #config bit2, clock bit1
move.b d2,(a1) // data low, config high, clk low
move.b d3,(a1) // data low, config high, clk high
bra bit_send1
bit_is_11:
move.b d4,(a1) // clk low, config high, data high
move.b d5,(a1) // clk high, config high, data high
bit_send1:
lsr.l #1,d0 // bit rausschieben
bcs bit_is_12 // data bit3, #config bit2, clock bit1
move.b d2,(a1) // data low, config high, clk low
move.b d3,(a1) // data low, config high, clk high
bra bit_send2
bit_is_12:
move.b d4,(a1) // clk low, config high, data high
move.b d5,(a1) // clk high, config high, data high
bit_send2:
lsr.l #1,d0 // bit rausschieben
bcs bit_is_13 // data bit3, #config bit2, clock bit1
move.b d2,(a1) // data low, config high, clk low
move.b d3,(a1) // data low, config high, clk high
bra bit_send3
bit_is_13:
move.b d4,(a1) // clk low, config high, data high
move.b d5,(a1) // clk high, config high, data high
bit_send3:
lsr.l #1,d0 // bit rausschieben
bcs bit_is_14 // data bit3, #config bit2, clock bit1
move.b d2,(a1) // data low, config high, clk low
move.b d3,(a1) // data low, config high, clk high
bra bit_send4
bit_is_14:
move.b d4,(a1) // clk low, config high, data high
move.b d5,(a1) // clk high, config high, data high
bit_send4:
lsr.l #1,d0 // bit rausschieben
bcs bit_is_15 // data bit3, #config bit2, clock bit1
move.b d2,(a1) // data low, config high, clk low
move.b d3,(a1) // data low, config high, clk high
bra bit_send5
bit_is_15:
move.b d4,(a1) // clk low, config high, data high
move.b d5,(a1) // clk high, config high, data high
bit_send5:
lsr.l #1,d0 // bit rausschieben
bcs bit_is_16 // data bit3, #config bit2, clock bit1
move.b d2,(a1) // data low, config high, clk low
move.b d3,(a1) // data low, config high, clk high
bra bit_send6
bit_is_16:
move.b d4,(a1) // clk low, config high, data high
move.b d5,(a1) // clk high, config high, data high
bit_send6:
lsr.l #1,d0 // bit rausschieben
bcs bit_is_17 // data bit3, #config bit2, clock bit1
move.b d2,(a1) // data low, config high, clk low
move.b d3,(a1) // data low, config high, clk high
bra bit_send7
bit_is_17:
move.b d4,(a1) // clk low, config high, data high
move.b d5,(a1) // clk high, config high, data high
bit_send7:
// test auf fertig
btst #5,(a2) // fpga fertig, conf_done=high?
beq word_send_loop // nein, next word->
move.l #4000,d1
@@ -267,8 +347,31 @@ overclk:
bclr #1,(a1) // clock=low
subq.l #1,d1
bne overclk // weiter bis fertig
// datum des FPGA files ausgeben
jsr warte_10us // warten
lea MCF_PSC0_PSCTB_8BIT,a3
move.l #': Da',(a3)
move.l #'te: ',(a3)
move.l 0xf0040100,d1
moveq #8,d0
date_loop:
btst #0,d0
bne kein_punkt
btst #2,d0
beq kein_punkt
move.b #'.',(a3)
kein_punkt:
move.l d0,d3 // index
subq.l #1,d3 // -1
lsl.l #2,d3 // *2
move.l d1,d2
lsr.l d3,d2 // und schieben
and.l #0x0f,d2
add.l #'0',d2
move.b d2,(a3)
subq.l #1,d0
bgt date_loop
bra init_fpga_end
//---------------------------------------------------------
wait_pll:
lea MCF_SLT0_SCNT,a3
@@ -322,7 +425,7 @@ asm
move.w #1,0x44(a0) // M low = 1
bsr wait_pll
move.w #145,0x04(a0) // M high = 145 = 146MHz
move.w #65,0x04(a0) // M high = 65 = 65MHz
bsr wait_pll
clr.b (a1) // set
@@ -368,7 +471,7 @@ void init_video_ddr(void)
/********************************************************************/
/* video mit aufl<66>sung 1280x1000 137MHz /*
/********************************************************************/
/*
void video_1280_1024(void)
{
extern int wait_pll;
@@ -381,7 +484,7 @@ extern int wait_pll;
//testmuster 1
lea __VRAM,a2
lea __VRAM+0x600000,a3
lea __VRAM+0x120000,a3
clr.l d0
move.l #0x1000102,d1
loop5: move.l d0,(a2)+
@@ -409,35 +512,48 @@ flo6: cmp.l a2,a3
bgt loop5
// screen setzen
//horizontal 1280
//horizontal 1024
lea 0xffff8282,a0
move.w #1800,(a0)+
move.w #1380,(a0)+
move.w #99,(a0)+
move.w #100,(a0)+
move.w #1379,(a0)+
move.w #1500,(a0)
//vertical 1024
move.w #1344,(a0)+
move.w #1184,(a0)+
move.w #159,(a0)+
move.w #160,(a0)+
move.w #1183,(a0)+
move.w #1208,(a0)
//vertical 768
lea 0xffff82a2,a0
move.w #1150,(a0)+
move.w #1074,(a0)+
move.w #49,(a0)+
move.w #50,(a0)+
move.w #1073,(a0)+
move.w #1100,(a0)+
move.w #806,(a0)+
move.w #797,(a0)+
move.w #28,(a0)+
move.w #29,(a0)+
move.w #796,(a0)+
move.w #800,(a0)+
// acp video on
move.l #0x01070207,d0
move.l #0x0107820b,d0 // acp video, color1, pll pixelclk, dac on
move.l d0,0xf0000400
lea 0xffff8200,a0
clr.w (a0)
clr.b 3(a0)
clr.b 0xd(a0)
move.w #0x400,10(a0)
move.w #0x182,0xc0(a0)
clr.w 0xc2(a0)
// clut setzen
lea 0xf0000000,a0
move.l #0xffffffff,(a0)+
move.l #0xff,(a0)+
move.l #0xff00,(a0)+
move.l #0xff0000,(a0)
// halt
/*
lea 0xffff8200,a0
move.w #6,0xc0(a0)
move.w #7,0x40(a0)
move.w #7,0x42(a0)
move.w #7,0x44(a0)
move.w #7,0x46(a0)
move.b #1,0x60(a0)
halt
}
@@ -767,70 +883,64 @@ ac97_end:
}
/********************************************************************/
void __initialize_hardware(void)
{
_init_hardware:
asm
{
// instruction cache on
move.l #0x000C8120,d0
init_ddram();
asm
{
// instruction cache on
move.l #0x007fe000,d0
movec d0,acr0
move.l d0,rt_acr0
movec d0,acr2
move.l d0,rt_acr2
clr.l d0
movec d0,acr1
move.l d0,rt_acr1
movec d0,acr3
move.l d0,rt_acr3
move.l d0,MCF_MMU_MMUCR
move.l #0x050c8120,d0
move.l d0,rt_cacr
movec d0,cacr
nop
}
init_gpio();
init_seriel();
init_slt();
init_fbcs();
init_ddram();
// Ports nicht initialisieren wenn DIP Switch 5 = on
asm
{
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
beq not_init_ports
}
}
init_gpio();
init_seriel();
init_slt();
init_fbcs();
init_fpga();
init_video_ddr();
vdi_on();
// Ports nicht initialisieren wenn DIP Switch 6 = on
asm
{
// IDE reset
lea 0xffff8802,a0 // IDE reset
move.b #14,-2(a0)
move.b #0x80,(a0)
bsr warte_1ms
clr.b (a0)
// dip switch
move.b DIP_SWITCH,d0 // dip schalter adresse
move.b d0,0xF0040002 // acp conf +2
// ACP_CONF setzen und Ports nicht initialisieren wenn DIP Switch 6 = on
btst.b #6,d0
beq not_init_ports
}
init_PCI(); //pci braucht zeit
not_init_ports:
init_fpga();
init_video_ddr();
vdi_on();
// Ports nicht initialisieren wenn DIP Switch 5 = on
asm
{
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
beq not_init_ports2
}
test_upd720101();
// video_1280_1024();
init_ac97();
not_init_ports2:
test_upd720101();
// video_1280_1024();
asm
{
not_init_ports:
}
set_ide_access_mode();
asm
{
/*****************************************************/
/* BaS kopieren
/*****************************************************/
lea copy_start,a0
lea BaS,a1
sub.l a0,a1
move.l #__Bas_base,a2
move.l a2,a3
add.l a1,a3
lea copy_end,a4
BaS_kopieren_loop: // immer 16 bytes
move.l (a0)+,(a2)+
move.l (a0)+,(a2)+
move.l (a0)+,(a2)+
move.l (a0)+,(a2)+
cmp.l a4,a0
blt BaS_kopieren_loop
/*****************************************************/
jmp (a3)
copy_start:
/********************************************************************/
}
}

874
sources/sysinit.c.alt Normal file
View File

@@ -0,0 +1,874 @@
/*
* File: sysinit.c
* Purpose: Power-on Reset configuration of the COLDARI board.
*
* Notes:
*
*/
#include "MCF5475.h"
#include "startcf.h"
#include "RuntimeConfig.h"
extern unsigned long far __VRAM;
extern unsigned long far __BOOT_FLASH[];
extern void warte_10us();
extern void set_ide_access_mode();
extern unsigned long far rt_cacr;
extern unsigned long far rt_acr0;
extern unsigned long far rt_acr1;
extern unsigned long far rt_acr2;
extern unsigned long far rt_acr3;
extern unsigned long far rt_mmubar;
/********************************************************************/
// init SLICE TIMER 0
// all = 32.538 sec = 30.736mHz
// BYT0 = 127.1ms/tick = 7.876Hz offset 0
// BYT1 = 496.5us/tick = 2.014kHz offset 1
// BYT2 = 1.939us/tick = 515.6kHz offset 2
// BYT3 = 7.576ns/tick = 132.00MHz offset 3
// count down!!! 132MHz!!!
/********************************************************************/
void init_slt(void)
{
asm
{
lea MCF_SLT0_STCNT,a0
move.l #0xffffffff,(a0)
lea MCF_SLT0_SCR,a0
move.b #0x05,(a0)
}
MCF_PSC0_PSCTB_8BIT = 'SLT ';
MCF_PSC0_PSCTB_8BIT = 'OK! ';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
}
/********************************************************************/
// init GPIO ETC.
/********************************************************************/
void init_gpio(void)
{
// PAD REGISTER P.S.:FBCTL UND FBCS WERDEN RICHTIG GESETZT BEIM RESET
MCF_PAD_PAR_DMA = 0b11111111; // NORMAL ALS DREQ DACK
MCF_PAD_PAR_FECI2CIRQ = 0b1111001111001111; // FEC0 NORMAL, FEC1 ALS I/O, I2C, #INT5..6
MCF_PAD_PAR_PCIBG = 0b0000001000111111; // #PCI_BG4=#TBST,#PIC_BG3=I/O,#PCI_BG2..0=NORMAL
MCF_PAD_PAR_PCIBR = 0b0000001000111111; // #PCI_BR4=#INT4,#PIC_BR3=INPUT,#PCI_BR2..0=NORMAL
MCF_PAD_PAR_PSC3 = 0b00001100; // PSC3=TX,RX CTS+RTS=I/O
MCF_PAD_PAR_PSC1 = 0b11111100; // PSC1 NORMAL SERIELL
MCF_PAD_PAR_PSC0 = 0b11111100; // PSC0 NORMAL SERIELL
MCF_PAD_PAR_DSPI = 0b0001111111111111; // DSPI NORMAL
MCF_PAD_PAR_TIMER = 0b00101101; // TIN3..2=#IRQ3..2;TOUT3..2=NORMAL
// ALLE OUTPUTS NORMAL LOW
// ALLE DIR NORMAL INPUT = 0
MCF_GPIO_PDDR_FEC1L = 0b00011110; // OUT: 4=LED,3=PRG_DQ0,2=#FPGA_CONFIG,1=PRG_CLK(FPGA)
}
/********************************************************************/
// init seriel
/********************************************************************/
void init_seriel(void)
{
// PSC0: SER1 ----------
MCF_PSC0_PSCSICR = 0; // UART
MCF_PSC0_PSCCSR = 0xDD;
MCF_PSC0_PSCCTUR = 0x00;
MCF_PSC0_PSCCTLR = 36; // BAUD RATE = 115200
MCF_PSC0_PSCCR = 0x20;
MCF_PSC0_PSCCR = 0x30;
MCF_PSC0_PSCCR = 0x40;
MCF_PSC0_PSCCR = 0x50;
MCF_PSC0_PSCCR = 0x10;
MCF_PSC0_PSCIMR = 0x8700;
MCF_PSC0_PSCACR = 0x03;
MCF_PSC0_PSCMR1= 0xb3;
MCF_PSC0_PSCMR2= 0x07;
MCF_PSC0_PSCRFCR = 0x0F;
MCF_PSC0_PSCTFCR = 0x0F;
MCF_PSC0_PSCRFAR = 0x00F0;
MCF_PSC0_PSCTFAR = 0x00F0;
MCF_PSC0_PSCOPSET = 0x01;
MCF_PSC0_PSCCR = 0x05;
// PSC3: PIC ----------
MCF_PSC3_PSCSICR = 0; // UART
MCF_PSC3_PSCCSR = 0xDD;
MCF_PSC3_PSCCTUR = 0x00;
MCF_PSC3_PSCCTLR = 36; // BAUD RATE = 115200
MCF_PSC3_PSCCR = 0x20;
MCF_PSC3_PSCCR = 0x30;
MCF_PSC3_PSCCR = 0x40;
MCF_PSC3_PSCCR = 0x50;
MCF_PSC3_PSCCR = 0x10;
MCF_PSC3_PSCIMR = 0x0200; // receiver interrupt enable
MCF_PSC3_PSCACR = 0x03;
MCF_PSC3_PSCMR1= 0xb3;
MCF_PSC3_PSCMR2= 0x07;
MCF_PSC3_PSCRFCR = 0x0F;
MCF_PSC3_PSCTFCR = 0x0F;
MCF_PSC3_PSCRFAR = 0x00F0;
MCF_PSC3_PSCTFAR = 0x00F0;
MCF_PSC3_PSCOPSET = 0x01;
MCF_PSC3_PSCCR = 0x05;
MCF_INTC_ICR32 = 0x3F; //MAXIMALE PRIORITY/**********/
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
MCF_PSC0_PSCTB_8BIT = 'SERI';
MCF_PSC0_PSCTB_8BIT = 'AL O';
MCF_PSC0_PSCTB_8BIT = 'K! ';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
}
/********************************************************************/
/* Initialize DDR DIMMs on the EVB board */
/********************************************************************/
/*
* Check to see if the SDRAM has already been initialized
* by a run control tool
*/
void init_ddram(void)
{
MCF_PSC0_PSCTB_8BIT = 'DDRA';
if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF))
{
/* Basic configuration and initialization */
MCF_SDRAMC_SDRAMDS = 0x000002AA; // SDRAMDS configuration
MCF_SDRAMC_CS0CFG = 0x0000001A; // SDRAM CS0 configuration (128Mbytes 0000_0000 - 07FF_FFFF)
MCF_SDRAMC_CS1CFG = 0x0800001A; // SDRAM CS1 configuration (128Mbytes 0800_0000 - 0FFF_FFFF)
MCF_SDRAMC_CS2CFG = 0x1000001A; // SDRAM CS2 configuration (128Mbytes 1000_0000 - 07FF_FFFF)
MCF_SDRAMC_CS3CFG = 0x1800001A; // SDRAM CS3 configuration (128Mbytes 1800_0000 - 1FFF_FFFF)
// MCF_SDRAMC_SDCFG1 = 0x53722938; // SDCFG1
MCF_SDRAMC_SDCFG1 = 0x73622830; // SDCFG1
// MCF_SDRAMC_SDCFG2 = 0x24330000; // SDCFG2
MCF_SDRAMC_SDCFG2 = 0x46770000; // SDCFG2
// MCF_SDRAMC_SDCR = 0xE10F0002; // SDCR + IPALL
MCF_SDRAMC_SDCR = 0xE10D0002; // SDCR + IPALL
MCF_SDRAMC_SDMR = 0x40010000; // SDMR (write to LEMR)
// MCF_SDRAMC_SDMR = 0x05890000; // SDRM (write to LMR)
MCF_SDRAMC_SDMR = 0x048D0000; // SDRM (write to LMR)
// MCF_SDRAMC_SDCR = 0xE10F0002; // SDCR + IPALL
MCF_SDRAMC_SDCR = 0xE10D0002; // SDCR + IPALL
// MCF_SDRAMC_SDCR = 0xE10F0004; // SDCR + IREF (first refresh)
MCF_SDRAMC_SDCR = 0xE10D0004; // SDCR + IREF (first refresh)
// MCF_SDRAMC_SDCR = 0xE10F0004; // SDCR + IREF (second refresh)
MCF_SDRAMC_SDCR = 0xE10D0004; // SDCR + IREF (second refresh)
/// MCF_SDRAMC_SDMR = 0x01890000; // SDMR (write to LMR)
MCF_SDRAMC_SDMR = 0x008D0000; // SDMR (write to LMR)
// MCF_SDRAMC_SDCR = 0x710F0F00; // SDCR (lock SDMR and enable refresh)
MCF_SDRAMC_SDCR = 0x710D0F00; // SDCR (lock SDMR and enable refresh)
}
MCF_PSC0_PSCTB_8BIT = 'M OK';
MCF_PSC0_PSCTB_8BIT = '! ';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
}
/********************************************************************/
/* init FB_CSx /*
/********************************************************************/
void init_fbcs()
{
MCF_PSC0_PSCTB_8BIT = 'FBCS';
MCF_FBCS1_CSAR = 0xFFF00000; // ATARI I/O ADRESS
MCF_FBCS1_CSCR = MCF_FBCS_CSCR_PS_16 // 16BIT PORT
| MCF_FBCS_CSCR_WS(32) // DEFAULT 32WS
| MCF_FBCS_CSCR_BSTR // Burst read enable
| MCF_FBCS_CSCR_BSTW // Burst write enable
| MCF_FBCS_CSCR_AA; // AA
MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_1M
| MCF_FBCS_CSMR_V);
MCF_FBCS2_CSAR = 0xF0000000; // NEUER I/O ADRESS-BEREICH
MCF_FBCS2_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT
| MCF_FBCS_CSCR_WS(8) // DEFAULT 8WS
| MCF_FBCS_CSCR_AA; // AA
MCF_FBCS2_CSMR = (MCF_FBCS_CSMR_BAM_128M // F000'0000-F7FF'FFFF
| MCF_FBCS_CSMR_V);
MCF_FBCS3_CSAR = 0xF8000000; // NEUER I/O ADRESS-BEREICH
MCF_FBCS3_CSCR = MCF_FBCS_CSCR_PS_16 // 16BIT PORT
| MCF_FBCS_CSCR_WS(32) // DEFAULT 32WS
| MCF_FBCS_CSCR_BSTR // Burst read enable
| MCF_FBCS_CSCR_BSTW // Burst write enable
| MCF_FBCS_CSCR_AA; // AA
MCF_FBCS3_CSMR = (MCF_FBCS_CSMR_BAM_64M // F800'0000-FBFF'FFFF
| MCF_FBCS_CSMR_V);
MCF_FBCS4_CSAR = 0x40000000; // VIDEO RAM BEREICH,
MCF_FBCS4_CSCR = MCF_FBCS_CSCR_PS_32 // 32BIT PORT
| MCF_FBCS_CSCR_BSTR // BURST READ ENABLE
| MCF_FBCS_CSCR_BSTW; // BURST WRITE ENABLE
MCF_FBCS4_CSMR = (MCF_FBCS_CSMR_BAM_1G // 4000'0000-7FFF'FFFF
| MCF_FBCS_CSMR_V);
/* Flash */
MCF_FBCS0_CSAR = 0xE0000000; // FLASH ADRESS
MCF_FBCS0_CSCR = 0x00001180; // 16 bit 4ws aa
MCF_FBCS0_CSMR = 0x007F0001; // 8MB on
MCF_PSC0_PSCTB_8BIT = ' OK!';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
}
/********************************************************************/
/* FPGA LADEN /*
/********************************************************************/
void init_fpga(void)
{
MCF_PSC0_PSCTB_8BIT = 'FPGA';
asm
{
lea MCF_GPIO_PODR_FEC1L,a1 // register adresse:write
lea MCF_GPIO_PPDSDR_FEC1L,a2 // reads
bclr #1,(a1) // clk auf low
bclr #2,(a1) // #config=low
test_nSTATUS:
btst #0,(a2) // nSTATUS==0
bne test_nSTATUS // nein->
btst #5,(a2) // conf done==0
bne test_nSTATUS // nein->
jsr warte_10us // warten
bset #2,(a1) // #config=high
jsr warte_10us // warten
test_STATUS:
btst #0,(a2) // status high?
beq test_STATUS // nein->
jsr warte_10us // warten
lea 0xE0700000,a0 // startadresse fpga daten
word_send_loop:
cmp.l #0xE0800000,a0
bgt fpga_error
move.b (a0)+,d0 // 32 bit holen
moveq #8,d1 // 32 bit ausgeben
bit_send_loop:
lsr.l #1,d0 // bit rausschieben
bcs bit_is_1
bclr #3,(a1)
bra bit_send
bit_is_1:
bset #3,(a1)
bit_send:
bset #1,(a1) // clock=high
bclr #1,(a1) // clock=low
subq.l #1,d1
bne bit_send_loop // wiederholen bis fertig
btst #5,(a2) // fpga fertig, conf_done=high?
beq word_send_loop // nein, next word->
move.l #4000,d1
overclk:
bset #1,(a1) // clock=high
nop
bclr #1,(a1) // clock=low
subq.l #1,d1
bne overclk // weiter bis fertig
// datum des FPGA files ausgeben
jsr warte_10us // warten
lea MCF_PSC0_PSCTB_8BIT,a3
move.l #': Da',(a3)
move.l #'te: ',(a3)
move.l 0xf0040100,d1
moveq #8,d0
date_loop:
btst #0,d0
bne kein_punkt
btst #2,d0
beq kein_punkt
move.b #'.',(a3)
kein_punkt:
move.l d0,d3 // index
subq.l #1,d3 // -1
lsl.l #2,d3 // *2
move.l d1,d2
lsr.l d3,d2 // und schieben
and.l #0x0f,d2
add.l #'0',d2
move.b d2,(a3)
subq.l #1,d0
bgt date_loop
bra init_fpga_end
//---------------------------------------------------------
wait_pll:
lea MCF_SLT0_SCNT,a3
move.l (a3),d0
move.l #100000,d6 // ca 1ms
wait_pll_loop:
tst.w (a1)
bpl wait_pll_ok
move.l (a3),d1
sub.l d0,d1
add.l d6,d1
bpl wait_pll_loop
wait_pll_ok:
rts
// fertig
fpga_error:
}
MCF_PSC0_PSCTB_8BIT = ' NOT';
init_fpga_end:
MCF_PSC0_PSCTB_8BIT = ' OK!';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
// init pll
MCF_PSC0_PSCTB_8BIT = 'PLL ';
asm
{
lea 0xf0000600,a0
lea 0xf0000800,a1
bsr wait_pll
move.w #27,0x48(a0) // loopfilter r
bsr wait_pll
move.w #1,0x08(a0) // charge pump I
bsr wait_pll
move.w #12,0x0(a0) // N counter high = 12
bsr wait_pll
move.w #12,0x40(a0) // N counter low = 12
bsr wait_pll
move.w #1,0x114(a0) // ck1 bypass
bsr wait_pll
move.w #1,0x118(a0) // ck2 bypass
bsr wait_pll
move.w #1,0x11c(a0) // ck3 bypass
bsr wait_pll
move.w #1,0x10(a0) // ck0 high = 1
bsr wait_pll
move.w #1,0x50(a0) // ck0 low = 1
bsr wait_pll
move.w #1,0x144(a0) // M odd division
bsr wait_pll
move.w #1,0x44(a0) // M low = 1
bsr wait_pll
move.w #65,0x04(a0) // M high = 65 = 65MHz
bsr wait_pll
clr.b (a1) // set
}
MCF_PSC0_PSCTB_8BIT = 'SET!';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
}
/********************************************************************/
/* INIT VIDEO DDR RAM /*
/********************************************************************/
void init_video_ddr(void)
{
asm
{
// init video ram
moveq.l #0xB,d0
move.w d0,0xF0000400 //set cke=1, cs=1 config=1
nop
lea __VRAM,a0 //zeiger auf video ram
nop
move.l #0x00050400,(a0) //IPALL
nop
move.l #0x00072000,(a0) //load EMR pll on
nop
move.l #0x00070122,(a0) //load MR: reset pll, cl=2 BURST=4lw
nop
move.l #0x00050400,(a0) //IPALL
nop
move.l #0x00060000,(a0) //auto refresh
nop
move.l #0x00060000,(a0) //auto refresh
nop
move.l #0000070022,(a0) //load MR dll on
nop
move.l #0x01070002,d0 // fifo on, refresh on, ddrcs und cke on, video dac on,
move.l d0,0xf0000400
}
}
/********************************************************************/
/* video mit aufl<66>sung 1280x1000 137MHz /*
/********************************************************************/
void video_1280_1024(void)
{
extern int wait_pll;
asm
{
// SPEICHER F<>LLEM
//testmuster 1
lea __VRAM,a2
lea __VRAM+0x120000,a3
clr.l d0
move.l #0x1000102,d1
loop5: move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
move.l d0,(a2)+
add.l d1,d0
flo6: cmp.l a2,a3
bgt loop5
// screen setzen
//horizontal 1024
lea 0xffff8282,a0
move.w #1344,(a0)+
move.w #1184,(a0)+
move.w #159,(a0)+
move.w #160,(a0)+
move.w #1183,(a0)+
move.w #1208,(a0)
//vertical 768
lea 0xffff82a2,a0
move.w #806,(a0)+
move.w #797,(a0)+
move.w #28,(a0)+
move.w #29,(a0)+
move.w #796,(a0)+
move.w #800,(a0)+
// acp video on
move.l #0x0107820b,d0 // acp video, color1, pll pixelclk, dac on
move.l d0,0xf0000400
lea 0xffff8200,a0
clr.w (a0)
clr.b 3(a0)
clr.b 0xd(a0)
move.w #0x400,10(a0)
move.w #0x182,0xc0(a0)
clr.w 0xc2(a0)
// clut setzen
lea 0xf0000000,a0
move.l #0xffffffff,(a0)+
move.l #0xff,(a0)+
move.l #0xff00,(a0)+
move.l #0xff0000,(a0)
/*
lea 0xffff8200,a0
move.w #6,0xc0(a0)
move.w #7,0x40(a0)
move.w #7,0x42(a0)
move.w #7,0x44(a0)
move.w #7,0x46(a0)
move.b #1,0x60(a0)
*/
// halt
}
}
/********************************************************************/
/* INIT PCI /*
/********************************************************************/
#define PCI_MEMORY_OFFSET (0x80000000)
#define PCI_MEMORY_SIZE (0x40000000)
#define PCI_IO_OFFSET (0xD0000000)
#define PCI_IO_SIZE (0x10000000)
void init_PCI(void)
{
MCF_PSC0_PSCTB_8BIT = 'PCI ';
asm
{
// Setup the arbiter
move.l #MCF_PCIARB_PACR_INTMPRI \
+ MCF_PCIARB_PACR_EXTMPRI(0x1F) \
+ MCF_PCIARB_PACR_INTMINTEN \
+ MCF_PCIARB_PACR_EXTMINTEN(0x1F),D0
move.l D0,MCF_PCIARB_PACR
// Setup burst parameters
move.l #MCF_PCI_PCICR1_CACHELINESIZE(4) + MCF_PCI_PCICR1_LATTIMER(32),D0
move.l D0,MCF_PCI_PCICR1
move.l #MCF_PCI_PCICR2_MINGNT(16) + MCF_PCI_PCICR2_MAXLAT(16),D0
move.l D0,MCF_PCI_PCICR2
// Turn on error signaling
move.l #MCF_PCI_PCIICR_TAE + MCF_PCI_PCIICR_IAE + MCF_PCI_PCIICR_REE + 32,D0
move.l D0,MCF_PCI_PCIICR
move.l #MCF_PCI_PCIGSCR_SEE,D0
or.l D0,MCF_PCI_PCIGSCR
// Configure Initiator Windows */
move.l #PCI_MEMORY_OFFSET + ((PCI_MEMORY_SIZE - 1) >> 8),D0
clr.w D0
move.l D0,MCF_PCI_PCIIW0BTAR // Initiator Window 0 Base / Translation Address Register
move.l #PCI_IO_OFFSET+((PCI_IO_SIZE-1)>>8),D0
clr.w D0
move.l D0,MCF_PCI_PCIIW1BTAR // Initiator Window 1 Base / Translation Address Register
clr.l MCF_PCI_PCIIW2BTAR // not used
move.l #MCF_PCI_PCIIWCR_WINCTRL0_MEMRDLINE + MCF_PCI_PCIIWCR_WINCTRL1_IO,D0
move.l D0,MCF_PCI_PCIIWCR // Initiator Window Configuration Register
/* Clear PCI Reset and wait for devices to reset */
move.l #~MCF_PCI_PCIGSCR_PR,D0
and.l D0,MCF_PCI_PCIGSCR
}
MCF_PSC0_PSCTB_8BIT = 'OK! ';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
}
/********************************************************************/
/* test UPC720101 (USB) /*
/********************************************************************/
void test_upd720101(void)
{
MCF_PSC0_PSCTB_8BIT = 'NEC ';
asm
{
// SELECT UPD720101 AD17
MOVE.L #MCF_PCI_PCICAR_E+MCF_PCI_PCICAR_DEVNUM(17)+MCF_PCI_PCICAR_FUNCNUM(0)+MCF_PCI_PCICAR_DWORD(0),D0
MOVE.L D0,MCF_PCI_PCICAR
LEA PCI_IO_OFFSET,A0
MOVE.L (A0),D1
move.l #0x33103500,d0
cmp.l d0,d1
beq nec_ok
}
MCF_PSC0_PSCTB_8BIT = 'NOT ';
goto nec_not_ok;
nec_ok:
asm
{
MOVE.L #MCF_PCI_PCICAR_E+MCF_PCI_PCICAR_DEVNUM(17)+MCF_PCI_PCICAR_FUNCNUM(0)+MCF_PCI_PCICAR_DWORD(57),D0
MOVE.L D0,MCF_PCI_PCICAR
move.b #0x20,(a0)
}
nec_not_ok:
asm
{
MOVE.L #MCF_PCI_PCICAR_DEVNUM(17)+MCF_PCI_PCICAR_FUNCNUM(0)+MCF_PCI_PCICAR_DWORD(57),D0
MOVE.L D0,MCF_PCI_PCICAR
}
MCF_PSC0_PSCTB_8BIT = 'OK! ';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
}
/********************************************************************/
/* TFP410 (vdi) einschalten /*
/********************************************************************/
void vdi_on(void)
{
uint8 RBYT, DBYT;
int versuche, startzeit;
MCF_PSC0_PSCTB_8BIT = 'DVI ';
MCF_I2C_I2FDR = 0x3c; // 100kHz standard
versuche = 0;
loop_i2c:
if (versuche++>10) goto next;
MCF_I2C_I2ICR = 0x0;
MCF_I2C_I2CR = 0x0;
MCF_I2C_I2CR = 0xA;
RBYT = MCF_I2C_I2DR;
MCF_I2C_I2SR = 0x0;
MCF_I2C_I2CR = 0x0;
MCF_I2C_I2ICR = 0x01;
MCF_I2C_I2CR = 0xb0;
MCF_I2C_I2DR = 0x7a; // ADRESSE TFP410
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ; // warten auf fertig
MCF_I2C_I2SR &= 0xfd; // clear bit
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) goto loop_i2c; // ack erhalten? -> nein
tpf_410_ACK_OK:
MCF_I2C_I2DR = 0x00; // SUB ADRESS 0
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ;
MCF_I2C_I2SR &= 0xfd;
MCF_I2C_I2CR |= 0x4; // repeat start
MCF_I2C_I2DR = 0x7b; // beginn read
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ; // warten auf fertig
MCF_I2C_I2SR &= 0xfd; // clear bit
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) goto loop_i2c; // ack erhalten? -> nein
MCF_I2C_I2CR &= 0xef; // switch to rx
DBYT = MCF_I2C_I2DR; // dummy read
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ;
MCF_I2C_I2SR &= 0xfd;
MCF_I2C_I2CR |= 0x08; // txak=1
RBYT = MCF_I2C_I2DR;
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ;
MCF_I2C_I2SR &= 0xfd;
MCF_I2C_I2CR = 0x80; // stop
DBYT = MCF_I2C_I2DR; // dummy read
if (RBYT!=0x4c) goto loop_i2c;
i2c_ok:
MCF_I2C_I2CR = 0x0; // stop
MCF_I2C_I2SR = 0x0; // clear sr
while((MCF_I2C_I2SR & MCF_I2C_I2SR_IBB)) ; // wait auf bus free
MCF_I2C_I2CR = 0xb0; // on tx master
MCF_I2C_I2DR = 0x7A;
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ; // warten auf fertig
MCF_I2C_I2SR &= 0xfd; // clear bit
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) goto loop_i2c; // ack erhalten? -> nein
MCF_I2C_I2DR = 0x08; // SUB ADRESS 8
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ;
MCF_I2C_I2SR &= 0xfd;
MCF_I2C_I2DR = 0xbf; // ctl1: power on, T:M:D:S: enable
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ; // warten auf fertig
MCF_I2C_I2SR &= 0xfd; // clear bit
MCF_I2C_I2CR = 0x80; // stop
DBYT = MCF_I2C_I2DR; // dummy read
MCF_I2C_I2SR = 0x0; // clear sr
while((MCF_I2C_I2SR & MCF_I2C_I2SR_IBB)) ; // wait auf bus free
MCF_I2C_I2CR = 0xb0;
MCF_I2C_I2DR = 0x7A;
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ; // warten auf fertig
MCF_I2C_I2SR &= 0xfd; // clear bit
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) goto loop_i2c; // ack erhalten? -> nein
MCF_I2C_I2DR = 0x08; // SUB ADRESS 8
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ;
MCF_I2C_I2SR &= 0xfd;
MCF_I2C_I2CR |= 0x4; // repeat start
MCF_I2C_I2DR = 0x7b; // beginn read
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ; // warten auf fertig
MCF_I2C_I2SR &= 0xfd; // clear bit
if (MCF_I2C_I2SR & MCF_I2C_I2SR_RXAK) goto loop_i2c; // ack erhalten? -> nein
MCF_I2C_I2CR &= 0xef; // switch to rx
DBYT = MCF_I2C_I2DR; // dummy read
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ;
MCF_I2C_I2SR &= 0xfd;
MCF_I2C_I2CR |= 0x08; // txak=1
warte_50us();
RBYT = MCF_I2C_I2DR;
while(!(MCF_I2C_I2SR & MCF_I2C_I2SR_IIF)) ;
MCF_I2C_I2SR &= 0xfd;
MCF_I2C_I2CR = 0x80; // stop
DBYT = MCF_I2C_I2DR; // dummy read
if (RBYT!=0xbf) goto loop_i2c;
goto dvi_ok;
next:
MCF_PSC0_PSCTB_8BIT = 'NOT ';
dvi_ok:
MCF_PSC0_PSCTB_8BIT = 'OK! ';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
MCF_I2C_I2CR = 0x0; // i2c off
}
/********************************************************************/
/* AC97 /*
/********************************************************************/
void init_ac97(void)
{
// PSC2: AC97 ----------
int i,k,zm,x,va,vb,vc;
MCF_PSC0_PSCTB_8BIT = 'AC97';
MCF_PAD_PAR_PSC2 = MCF_PAD_PAR_PSC2_PAR_RTS2_RTS // PSC2=TX,RX BCLK,CTS->AC'97
| MCF_PAD_PAR_PSC2_PAR_CTS2_BCLK
| MCF_PAD_PAR_PSC2_PAR_TXD2
| MCF_PAD_PAR_PSC2_PAR_RXD2;
MCF_PSC2_PSCMR1 = 0x0;
MCF_PSC2_PSCMR2 = 0x0;
MCF_PSC2_PSCIMR = 0x0300;
MCF_PSC2_PSCSICR = 0x03; //AC97
MCF_PSC2_PSCRFCR = 0x0f000000;
MCF_PSC2_PSCTFCR = 0x0f000000;
MCF_PSC2_PSCRFAR = 0x00F0;
MCF_PSC2_PSCTFAR = 0x00F0;
for ( zm = 0; zm<100000; zm++) // wiederholen bis synchron
{
MCF_PSC2_PSCCR = 0x20;
MCF_PSC2_PSCCR = 0x30;
MCF_PSC2_PSCCR = 0x40;
MCF_PSC2_PSCCR = 0x05;
// MASTER VOLUME -0dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x02000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
for ( i = 2; i<13; i++ )
{
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
// read register
MCF_PSC2_PSCTB_AC97 = 0xc0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x82000000; //SLOT1:master volume
for ( i = 2; i<13; i++ )
{
MCF_PSC2_PSCTB_AC97 = 0x00000000; //SLOT2-12:RD REG ALLES 0
}
warte_50us();
va = MCF_PSC2_PSCTB_AC97;
if ((va & 0x80000fff)==0x80000800)
{
vb = MCF_PSC2_PSCTB_AC97;
vc = MCF_PSC2_PSCTB_AC97;
if ((va & 0xE0000fff)==0xE0000800 & vb==0x02000000 & vc==0x00000000)
{
goto livo;
}
}
}
MCF_PSC0_PSCTB_8BIT = ' NOT';
livo:
// AUX VOLUME ->-0dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x16000000; //SLOT1:WR REG AUX VOLUME adr 0x16
MCF_PSC2_PSCTB_AC97 = 0x06060000; //SLOT1:VOLUME
for ( i = 3; i<13; i++ )
{
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
// line in VOLUME +12dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x10000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
for ( i = 2; i<13; i++ )
{
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
// cd in VOLUME 0dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x12000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
for ( i = 2; i<13; i++ )
{
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
// mono out VOLUME 0dB
MCF_PSC2_PSCTB_AC97 = 0xE0000000; //START SLOT1 + SLOT2, FIRST FRAME
MCF_PSC2_PSCTB_AC97 = 0x06000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
MCF_PSC2_PSCTB_AC97 = 0x00000000; //SLOT1:WR REG MASTER VOLUME adr 0x02
for ( i = 3; i<13; i++ )
{
MCF_PSC2_PSCTB_AC97 = 0x0; //SLOT2-12:WR REG ALLES 0
}
MCF_PSC2_PSCTFCR |= MCF_PSC_PSCTFCR_WFR; //set EOF
MCF_PSC2_PSCTB_AC97 = 0x00000000; //last data
ac97_end:
MCF_PSC0_PSCTB_8BIT = ' OK!';
MCF_PSC0_PSCTB_8BIT = 0x0a0d;
}
/********************************************************************/
void __initialize_hardware(void)
{
_init_hardware:
init_ddram();
asm
{
// instruction cache on
move.l #0x007fe000,d0
movec d0,acr0
move.l d0,rt_acr0
movec d0,acr2
move.l d0,rt_acr2
clr.l d0
movec d0,acr1
move.l d0,rt_acr1
movec d0,acr3
move.l d0,rt_acr3
move.l d0,MCF_MMU_MMUCR
move.l #0x050c8120,d0
move.l d0,rt_cacr
movec d0,cacr
nop
}
init_gpio();
init_seriel();
init_slt();
init_fbcs();
// ACP_CONF setzen und Ports nicht initialisieren wenn DIP Switch 6 = on
asm
{
move.b DIP_SWITCH,d0 // dip schalter adresse
btst.b #6,d0
beq not_init_ports
}
init_PCI(); //pci braucht zeit
not_init_ports:
init_fpga();
init_video_ddr();
vdi_on();
// Ports nicht initialisieren wenn DIP Switch 6 = on
asm
{
move.b DIP_SWITCH,d0 // dip schalter adresse
move.b d0,0xF0040002 // acp conf +2
btst.b #6,d0
beq not_init_ports2
}
test_upd720101();
init_ac97();
asm
{
not_init_ports2:
}
// video_1280_1024();
set_ide_access_mode();
}