⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci.c

📁 Vxworks下的C例子程序
💻 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 + -