www.pudn.com > Demo C.rar > 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#include #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 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