📄 pci.c
字号:
/****************************************************************
** File: pci.c
*
*
* Description: This file contains all the routines to perform
* the DMA transfer from AI to MB either in direct mode or in
* chaining mode
*****************************************************************/
#include "std.h"
#include "MMapPQII.h"
#include <string.h>
#include <stdlib.h>
#include "pci.h"
/** pointers to memory map of host and agent*/
extern POWERQUICCII *IMMR_ptr;
/** data structure for dma chaining mode*/
t_DmaChainBuffer *pDmaChainBuffer;
/** function prototypes related to intialization* and DMA*/
void DmaDirectTansfer(void);
/** external PCI API functions*/
extern void PCI_MaskNoResponse(t_PCI_MAP *pci_memory_map);
extern ulong PCI_ReadLong (ulong address);
extern void PCI_WriteLong (ulng address, ulng value);
extern void PCI_CfgWriteLong(ulng BusNum, ulng DevNum, e_CfgReg RegNum, t_PCI_MAP *pPCIMap, ulng value);
extern void PCI_CfgWriteShort (ulng BusNum,ulng DevNum,e_CfgReg configuration_register_offset,word value);
extern void PCI_CfgWriteByte (ulng BusNum,ulng DevNum, e_CfgReg configuration_register_offset,word value);
extern ulng PCI_CfgReadLong(ulng BusNum, ulng DevNum, e_CfgReg RegNum, t_PCI_MAP *pPCIMap);
extern ulng PCI_CalcWindowSize(ulng);
extern void PCI_InsertRelevantBitsInPciRegister(ulng register_address, ulng new_val, ulng mask);
extern ulng ConstructConfigWord (ulng BusNum,ulng DevNum,e_CfgReg RegNum);
#if (DMA_DIRECT == 1)
/*******************************************************
* routine: DmaDirectTansfer ]
*
* description:
* does AI to MB dma transfer on a block by block basis
* * arguments: * none *
* return code:
* none
*********************************************************/
void DmaDirectTansfer()
{
ulng channel_mode;
ulng channel_status;
ulng Flag;
ulng i,j;
byte *ptr_byte;
byte *ptr_source;
bool is_busy;
t_PCI_MAP *pPCIMap;
volatile t_PciDmaChannel *dma_channel;
/*
* pointer to PCI memory mapped registers */
pPCIMap = (t_PCI_MAP *)&IMMR_ptr->PCI_MAP;
dma_channel = (volatile t_PciDmaChannel *)&pPCIMap->pci_dma_ch_1;
/* * use dma engine 1 to move data from MB to AI on
* a block by block basis. there are total
* NUM_OF_DMA_BLOCKS blocks that would be
* transferred sequentially
*/
for (i=0;i<NUM_OF_DMA_BLOCKS;i++)
{
/*
* poll for the channel to become free
*/
do{
channel_status = PCI_ReadLong((ulng)&dma_channel->pci_dsr);
is_busy = (bool)(channel_status & CHANNEL_BUSY);
}while(is_busy);
/*
* reset the interrupt status to make dma channel
* stop interrupting
*/
PCI_WriteLong((ulng)&dma_channel->pci_dsr, channel_status);
/*
* check whether there is a transfer error
*/
if (channel_status & TRANSFER_ERROR)
{
printf("Err:transfer error...\n\r");
return;
}
/*---
* program dma 1 engine related registers
* -mode register
* -status register
* -source address register
* -destination address register
* -block count register
*---/
/*
* mode register; clear the mode register and then program
*/
channel_mode = 0x0;
PCI_WriteLong((ulng)&dma_channel->pci_dmr, channel_mode);
channel_mode |= CHANNEL_DIRECT_TRANSFER_MODE;
if(i == (NUM_OF_DMA_BLOCKS - 1))
channel_mode |= END_OF_TRANSFER_INT;
/*last block would generate interrupt*/
PCI_WriteLong((ulng)&dma_channel->pci_dmr, channel_mode);
PCI_WriteLong((ulng)&dma_channel->pci_dsar, (BASE_OF_DMA_SOURCE_BLOCKS + i*DMA_BLOCK_SIZE));
PCI_WriteLong((ulng)&dma_channel->pci_ddar, (BASE_OF_DMA_DEST_BLOCKS + i*DMA_BLOCK_SIZE));
PCI_WriteLong((ulng)&dma_channel->pci_dbcr, DMA_BLOCK_SIZE);
/*
* start channel; clear and then set the channel start bit
*/
PCI_InsertRelevantBitsInPciRegister((ulng)&dma_channel->pci_dmr,
0,
(ulng)~CHANNEL_START);
PCI_InsertRelevantBitsInPciRegister((ulng)&dma_channel->pci_dmr,
CHANNEL_START,
(ulng)~CHANNEL_START);
}
}
#else
/********************************************************
* routine: DmaChainingMode
*
* description:
* does AI to MB multiple block dma transfer on a single go
*
* arguments:
* none
*
* return code:
* none
*
********************************************************/
void DmaChainingMode ()
{
ulng value;
ulng channel_mode;
ulng channel_status;
ulng i,j;
byte *ptr_byte;
byte *ptr_source;
bool is_busy;
t_PCI_MAP *pPCIMap;
volatile t_PciDmaChannel *dma_channel;
/*
* pointer to PCI memory mapped registers
*/
pPCIMap = (t_PCI_MAP *)&IMMR_ptr->PCI_MAP;
dma_channel = (volatile t_PciDmaChannel *)&pPCIMap->pci_dma_ch_1;
/*
* program the cdar
*/
pDmaChainBuffer = (t_DmaChainBuffer *)0xe00000;
PCI_WriteLong((ulng)&dma_channel->pci_dcdar,0xe00000);
/*
* create 4 segments; starting address of the descriptor
* segement is 0xe00000
*/
/*1st segment*/
PCI_WriteLong((ulng)&pDmaChainBuffer->source_address , BASE_OF_DMA_SOURCE_BLOCKS);
PCI_WriteLong((ulng)&pDmaChainBuffer->destination_address , BASE_OF_DMA_DEST_BLOCKS);
value = (ulng)((ulng)pDmaChainBuffer + ((ulng)sizeof(t_DmaChainBuffer)));
PCI_WriteLong((ulng)&pDmaChainBuffer->next_descriptor_address,value); /*NDAR*/
PCI_WriteLong((ulng)&pDmaChainBuffer->size , DMA_BLOCK_SIZE);
/*2nd segment*/
PCI_WriteLong((ulng)&((pDmaChainBuffer + 1)->source_address) , (BASE_OF_DMA_SOURCE_BLOCKS + DMA_BLOCK_SIZE));
PCI_WriteLong((ulng)&((pDmaChainBuffer + 1)->destination_address) , (BASE_OF_DMA_DEST_BLOCKS + DMA_BLOCK_SIZE));
value = (ulng)((ulng)(pDmaChainBuffer + 1) + ((ulng)sizeof(t_DmaChainBuffer)));
PCI_WriteLong((ulng)&((pDmaChainBuffer + 1)->next_descriptor_address),value); /*NDAR*/
PCI_WriteLong((ulng)&((pDmaChainBuffer + 1)->size) , DMA_BLOCK_SIZE);
/*3rd segment*/
PCI_WriteLong((ulng)&((pDmaChainBuffer + 2)->source_address) , (BASE_OF_DMA_SOURCE_BLOCKS + 2*DMA_BLOCK_SIZE));
PCI_WriteLong((ulng)&((pDmaChainBuffer + 2)->destination_address) , (BASE_OF_DMA_DEST_BLOCKS + 2*DMA_BLOCK_SIZE));
value = (ulng)((ulng)(pDmaChainBuffer + 2) + ((ulng)sizeof(t_DmaChainBuffer)));
PCI_WriteLong((ulng)&((pDmaChainBuffer + 2)->next_descriptor_address),value); /*NDAR*/
PCI_WriteLong((ulng)&((pDmaChainBuffer + 2)->size) , DMA_BLOCK_SIZE);
/*4th segment*/
PCI_WriteLong((ulng)&((pDmaChainBuffer + 3)->source_address) , (BASE_OF_DMA_SOURCE_BLOCKS + 3*DMA_BLOCK_SIZE));
PCI_WriteLong((ulng)&((pDmaChainBuffer + 3)->destination_address) , (BASE_OF_DMA_DEST_BLOCKS + 3*DMA_BLOCK_SIZE));
value = (ulng)((ulng)(pDmaChainBuffer + 3) + ((ulng)sizeof(t_DmaChainBuffer)));
value |= EOTD; /*indicates last descriptor in the chain*/
PCI_WriteLong((ulng)&((pDmaChainBuffer + 3)->next_descriptor_address),value); /*NDAR*/
PCI_WriteLong((ulng)&((pDmaChainBuffer + 3)->size) , DMA_BLOCK_SIZE);
/*
* poll for the channel to become free
*/
do{
channel_status = PCI_ReadLong((ulng)&dma_channel->pci_dsr);
is_busy = (bool)(channel_status & CHANNEL_BUSY);
}while(is_busy);
/*
* reset the interrupt status to make it stop interrupting.
*/
PCI_WriteLong((ulng)&dma_channel->pci_dsr, channel_status);
/*
* check whether there is a transfer error
*/
if (channel_status & TRANSFER_ERROR)
{
printf("got a transfer error.\n\r");
return;
}
/*---
* program dma 1 engine related registers
* -mode register
* -status register
* -source address register
* -destination address register
* -block count register
*---/
/*
* mode register; clear the mode register and then program
*/
channel_mode = 0x0;
PCI_WriteLong((ulng)&dma_channel->pci_dmr, channel_mode);
channel_mode &= ~CHANNEL_DIRECT_TRANSFER_MODE;/*chaining mode*/
channel_mode |= END_OF_TRANSFER_INT;/*after transferring last block in the */
/* chain interrupt would be generated */
PCI_WriteLong((ulng)&dma_channel->pci_dmr, channel_mode);
/*
* start channel; clear and then set the channel start bit
*/
PCI_InsertRelevantBitsInPciRegister((ulng)&dma_channel->pci_dmr,
0, (ulng)~CHANNEL_START);
PCI_InsertRelevantBitsInPciRegister((ulng)&dma_channel->pci_dmr,
CHANNEL_START,
(ulng)~CHANNEL_START);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -