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;ipci_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