URL
https://opencores.org/ocsvn/pcie_ds_dma/pcie_ds_dma/trunk
Subversion Repositories pcie_ds_dma
Compare Revisions
- This comparison shows the changes necessary to convert path
/pcie_ds_dma/trunk/soft/linux/driver
- from Rev 44 to Rev 54
- ↔ Reverse comparison
Rev 44 → Rev 54
/pexdrv/dmachan.c
9,6 → 9,8
#include <linux/pagemap.h> |
#include <linux/interrupt.h> |
#include <linux/proc_fs.h> |
#include <linux/delay.h> |
#include <linux/wait.h> |
#include <asm/io.h> |
|
#ifndef _EVENT_H_ |
24,6 → 26,7
//----------------------------------------------------------------------------- |
|
struct CDmaChannel* CDmaChannelCreate( u32 NumberOfChannel, |
TASKLET_ROUTINE dpc, |
void *brd, |
struct device *dev, |
u32 cbMaxTransferLength, |
34,7 → 37,7
|
dma = kzalloc(sizeof(struct CDmaChannel), GFP_KERNEL); |
if(!dma) { |
printk("<0>%s(): Error allocate memory for CDmaChannel object\n", __FUNCTION__); |
printk("%s(): Error allocate memory for CDmaChannel object\n", __FUNCTION__); |
return NULL; |
} |
|
42,7 → 45,7
dma->m_Board = brd; |
dma->m_dev = dev; |
dma->m_UseCount = 0; |
dma->m_DpcForIsr = DmaDpcForIsr; |
dma->m_DpcForIsr = dpc; |
dma->m_idBlockFifo = idBlockFifo; |
|
spin_lock_init( &dma->m_DmaLock ); |
51,7 → 54,7
InitKevent( &dma->m_BlockEndEvent ); |
InitKevent( &dma->m_BufferEndEvent ); |
|
//printk("<0>%s(%d): COMPLETE.\n", __FUNCTION__, dma->m_NumberOfChannel); |
//printk("%s(%d): COMPLETE.\n", __FUNCTION__, dma->m_NumberOfChannel); |
|
return dma; |
} |
60,7 → 63,7
|
void CDmaChannelDelete(struct CDmaChannel *dma) |
{ |
//printk("<0>%s()\n", __FUNCTION__); |
//printk("%s()\n", __FUNCTION__); |
if (dma) { |
tasklet_kill( &dma->m_Dpc ); |
kfree(dma); |
73,11 → 76,11
{ |
int Status = -ENOMEM; |
|
//printk("<0>%s(): Channel = %d\n", __FUNCTION__, dma->m_NumberOfChannel); |
//printk("%s(): Channel = %d\n", __FUNCTION__, dma->m_NumberOfChannel); |
|
// при первом обращении действительно выделяем память, |
// а при повторных только отображаем выделенную память на пользовательское пространство |
if(!dma->m_UseCount) |
if(dma->m_UseCount == 0) |
{ |
dma_addr_t pa = (dma_addr_t)0; |
|
91,7 → 94,7
&pa, GFP_KERNEL); |
if(!dma->m_pBufDscr.SystemAddress) |
{ |
printk("<0>%s(): Not memory for buffer descriptions\n", __FUNCTION__); |
printk("%s(): Not memory for buffer descriptions\n", __FUNCTION__); |
return -ENOMEM; |
} |
|
112,22 → 115,21
dma->m_pBufDscr.LogicalAddress); |
dma->m_pBufDscr.SystemAddress = NULL; |
dma->m_pBufDscr.LogicalAddress = 0; |
printk("<0>%s(): Invalid memory type for DMA data blocks\n", __FUNCTION__); |
printk("%s(): Invalid memory type for DMA data blocks\n", __FUNCTION__); |
return -EINVAL; |
} |
|
if(Status == 0) |
{ |
if(!dma->m_UseCount) |
if(dma->m_UseCount == 0) |
{ |
//printk("<0>%s(): Scatter/Gather Table Entry is %d\n", __FUNCTION__, dma->m_ScatterGatherTableEntryCnt); |
//printk("%s(): Scatter/Gather Table Entry is %d\n", __FUNCTION__, dma->m_ScatterGatherTableEntryCnt); |
if(dma->m_idBlockFifo == PE_EXT_FIFO_ID) |
SetScatterGatherListExt(dma); |
else { |
printk("<0>%s(): Scatter/Gather Table Entry not created\n", __FUNCTION__); |
printk("%s(): Scatter/Gather Table Entry not created\n", __FUNCTION__); |
//SetScatterGatherList(dma); |
} |
*pCount = dma->m_BlockCount; |
dma->m_pStub = (PAMB_STUB)dma->m_StubDscr.SystemAddress; |
dma->m_pStub->lastBlock = -1; |
dma->m_pStub->totalCounter = 0; |
134,6 → 136,9
dma->m_pStub->offset = 0; |
dma->m_pStub->state = STATE_STOP; |
} |
|
*pCount = dma->m_BlockCount; |
|
dma->m_UseCount++; |
} |
else |
143,34 → 148,36
dma->m_pBufDscr.SystemAddress, dma->m_pBufDscr.LogicalAddress); |
dma->m_pBufDscr.SystemAddress = NULL; |
dma->m_pBufDscr.LogicalAddress = 0; |
printk("<0>%s(): Error allocate memory\n", __FUNCTION__); |
printk("%s(): Error allocate memory\n", __FUNCTION__); |
return -EINVAL; |
} |
} |
else |
{ |
if(!dma->m_UseCount) { |
dma_free_coherent(dma->m_dev, |
dma->m_BlockCount * sizeof(SHARED_MEMORY_DESCRIPTION), |
dma->m_pBufDscr.SystemAddress, dma->m_pBufDscr.LogicalAddress); |
dma->m_pBufDscr.SystemAddress = NULL; |
dma->m_pBufDscr.LogicalAddress = 0; |
{ |
if(dma->m_UseCount == 0) { |
dma_free_coherent(dma->m_dev, |
dma->m_BlockCount * sizeof(SHARED_MEMORY_DESCRIPTION), |
dma->m_pBufDscr.SystemAddress, dma->m_pBufDscr.LogicalAddress); |
dma->m_pBufDscr.SystemAddress = NULL; |
dma->m_pBufDscr.LogicalAddress = 0; |
} |
} |
return Status; |
} |
return Status; |
} |
|
//----------------------------------------------------------------------------- |
|
void ReleaseMemory(struct CDmaChannel *dma) |
int ReleaseMemory(struct CDmaChannel *dma) |
{ |
//printk("<0>%s(): Entered. Channel = %d\n", __FUNCTION__, dma->m_NumberOfChannel); |
printk("%s(): Entered. Channel = %d\n", __FUNCTION__, dma->m_NumberOfChannel); |
|
if(!dma->m_UseCount) { |
printk("<0> %s: Memory not allocated.\n", __FUNCTION__); |
return; |
if(dma->m_UseCount == 0) { |
printk("%s(): Memory not allocated. m_UseCount = %d\n", __FUNCTION__, dma->m_UseCount); |
return -1; |
} |
|
dma->m_UseCount--; |
|
ReleaseStub( dma ); |
ReleaseSGList( dma ); |
ReleaseSysBuf( dma ); |
181,7 → 188,7
|
dma->m_pBufDscr.SystemAddress = NULL; |
dma->m_pBufDscr.LogicalAddress = 0; |
dma->m_UseCount--; |
return 0; |
} |
|
//----------------------------------------------------------------------------- |
199,7 → 206,7
SHARED_MEMORY_DESCRIPTION *pMemDscr = (SHARED_MEMORY_DESCRIPTION*)dma->m_pBufDscr.SystemAddress; |
DMA_CHAINING_DESCR_EXT *pSGTEx = NULL; |
|
//printk("<0>%s()\n", __FUNCTION__); |
//printk("%s()\n", __FUNCTION__); |
|
Status = RequestSGList(dma); |
if(Status < 0) |
214,8 → 221,8
//обнулим таблицу дескрипторов DMA |
memset(pSGTEx, 0, dma->m_ScatterGatherBlockCnt*DscrSize); |
|
//printk("<0>%s(): m_SGTableDscr.SystemAddress = %p\n", __FUNCTION__, dma->m_SGTableDscr.SystemAddress ); |
//printk("<0>%s(): m_SGTableDscr.LogicalAddress = %zx\n", __FUNCTION__, dma->m_SGTableDscr.LogicalAddress ); |
printk("%s(): m_SGTableDscr.SystemAddress = %p\n", __FUNCTION__, dma->m_SGTableDscr.SystemAddress ); |
printk("%s(): m_SGTableDscr.LogicalAddress = 0x%llx\n", __FUNCTION__, dma->m_SGTableDscr.LogicalAddress ); |
|
//заполним значениями таблицу цепочек DMA |
for(iBlock=0, iEntry=0; iBlock < dma->m_BlockCount; iBlock++) { |
224,7 → 231,6
u64 address = pMemDscr[iBlock].LogicalAddress; |
u64 DmaSize = dma->m_BlockSize - 0x1000; |
|
|
//заполним поля элментов таблицы дескрипторов |
pSGTEx[iEntry].AddrByte1 = (u8)((address >> 8) & 0xFF); |
pSGTEx[iEntry].AddrByte2 = (u8)((address >> 16) & 0xFF); |
243,7 → 249,7
|
{ |
//u32 *ptr=(u32*)&pSGTEx[iEntry]; |
//printk("<0>%s(): %d: Entry Addr: %p, Data Addr: %llx %.8X %.8X\n", |
//printk("%s(): %d: Entry Addr: %p, Data Addr: %llx %.8X %.8X\n", |
// __FUNCTION__, iEntry, &pSGTEx[iEntry], address, ptr[1], ptr[0]); |
} |
|
258,12 → 264,12
//NextDscrBlockAddr = virt_to_bus((void*)&pSGTEx[iEntry+2]); |
NextDscrBlockAddr = (size_t)((u8*)dma->m_SGTableDscr.LogicalAddress + sizeof(DMA_CHAINING_DESCR_EXT)*(iEntry +2)); |
|
//printk("<0>%s(): NextDscrBlock [PA]: %x\n", __FUNCTION__, NextDscrBlockAddr); |
//printk("<0>%s(): NextDscrBlock [VA]: %p\n", __FUNCTION__, &pSGTEx[iEntry+2]); |
//printk("%s(): NextDscrBlock [PA]: 0x%lx\n", __FUNCTION__, NextDscrBlockAddr); |
//printk("%s(): NextDscrBlock [VA]: %p\n", __FUNCTION__, &pSGTEx[iEntry+2]); |
|
pNextBlock = (DMA_NEXT_BLOCK*)&pSGTEx[iEntry+1]; |
|
//printk("<0>%s(): pNextBlock: %p\n", __FUNCTION__, pNextBlock); |
//printk("%s(): pNextBlock: %p\n", __FUNCTION__, pNextBlock); |
|
pNextBlock->NextBlkAddr = (NextDscrBlockAddr >> 8) & 0xFFFFFF; |
pNextBlock->Signature = 0x4953; |
273,7 → 279,7
iEntry++; |
} |
|
//printk("<0>%s(): iEntry = %d\n", __FUNCTION__, iEntry); |
//printk("%s(): iEntry = %d\n", __FUNCTION__, iEntry); |
|
if(((iEntry % DSCR_BLOCK_SIZE)) != 0) |
{ |
288,7 → 294,7
i = (DSCR_BLOCK_SIZE * dma->m_ScatterGatherBlockCnt) - 1; |
pNextBlock = (DMA_NEXT_BLOCK*)(&pSGTEx[i]); |
|
//printk("<0>%s(): %d: pNextBlock: %p\n", __FUNCTION__, i, pNextBlock ); |
//printk("%s(): %d: pNextBlock: %p\n", __FUNCTION__, i, pNextBlock ); |
|
pNextBlock->NextBlkAddr = 0; |
pNextBlock->Signature = 0x4953; |
295,13 → 301,176
pNextBlock->Crc = 0; |
} |
|
//printk("<0>%s(): DmaDirection = %d, DmaLocalAddress = 0x%X\n", __FUNCTION__, dma->m_DmaDirection, dma->m_DmaLocalAddress); |
printk("%s(): DmaDirection = %d, DmaLocalAddress = 0x%X\n", __FUNCTION__, dma->m_DmaDirection, dma->m_DmaLocalAddress); |
|
//for( ii=0; ii<dma->m_ScatterGatherBlockCnt*DSCR_BLOCK_SIZE; ii++ ) |
//{ |
//u32 *ptr=(u32*)&pSGTEx[ii]; |
//printk("<0>%s(): %d: %.8X %.8X\n", __FUNCTION__, ii, ptr[1], ptr[0]); |
// u32 *ptr=(u32*)&pSGTEx[ii]; |
// printk("%s(): %02d: %08X %08X\n", __FUNCTION__, ii, ptr[1], ptr[0]); |
//} |
|
pDscrBuf = (u64*)dma->m_pScatterGatherTableExt; |
|
for(iBlkEntry = 0; iBlkEntry < dma->m_ScatterGatherBlockCnt; iBlkEntry++) |
{ |
u32 ctrl_code = 0xFFFFFFFF; |
|
for(iBlock = 0; iBlock < DSCR_BLOCK_SIZE; iBlock++) |
{ |
u16 data0 = (u16)(pDscrBuf[iBlock] & 0xFFFF); |
u16 data1 = (u16)((pDscrBuf[iBlock] >> 16) & 0xFFFF); |
u16 data2 = (u16)((pDscrBuf[iBlock] >> 32) & 0xFFFF); |
u16 data3 = (u16)((pDscrBuf[iBlock] >> 48) & 0xFFFF); |
if(iBlock == DSCR_BLOCK_SIZE-1) |
{ |
ctrl_code = ctrl_code ^ data0 ^ data1 ^ data2 ^ data3; |
|
//printk("%s(): DSCR_BLCK[%02d] - NextBlkAddr = 0x%08X, Signature = 0x%04X, Crc = 0x%04X\n", __FUNCTION__, |
// iBlkEntry, |
// (u32)(pDscrBuf[iBlock] << 8), |
// (u16)((pDscrBuf[iBlock] >> 32) & 0xFFFF), |
// (u16)ctrl_code); |
} |
else |
{ |
u32 ctrl_tmp = 0; |
ctrl_code = ctrl_code ^ data0 ^ data1 ^ data2 ^ data3; |
ctrl_tmp = ctrl_code << 1; |
ctrl_tmp |= (ctrl_code & 0x8000) ? 0: 1; |
ctrl_code = ctrl_tmp; |
|
//printk("%s(): %02d(%02d) - PciAddr = 0x%08X, Cmd = 0x%04X, DmaLength = 0x%08X (%02X %02X %02X)\n", __FUNCTION__, |
// iBlock, iBlkEntry, |
// (u32)(pDscrBuf[iBlock] << 8), |
// (u8)(pDscrBuf[iBlock] >> 32), |
// (u32)((pDscrBuf[iBlock] >> 41) << 9), |
// (u8)(pDscrBuf[iBlock] >> 56), |
// (u8)(pDscrBuf[iBlock] >> 48), |
// (u8)(pDscrBuf[iBlock] >> 40)); |
} |
} |
pNextDscr = (u16*)pDscrBuf; |
pNextDscr[255] |= (u16)ctrl_code; |
pDscrBuf += DSCR_BLOCK_SIZE; |
} |
return 0; |
} |
|
int SetScatterGatherListExtUser(struct CDmaChannel *dma) |
{ |
int Status = 0; |
u32 iBlock = 0; |
//u32 ii = 0; |
u32 iEntry = 0; |
u32 iBlkEntry = 0; |
u64 *pDscrBuf = NULL; |
u16* pNextDscr = NULL; |
u32 DscrSize = 0; |
SHARED_MEMORY_DESCRIPTION *pMemDscr = (SHARED_MEMORY_DESCRIPTION*)&dma->m_BufDscrVA; |
DMA_CHAINING_DESCR_EXT *pSGTEx = NULL; |
|
printk("%s()\n", __FUNCTION__); |
|
Status = RequestSGList(dma); |
if(Status < 0) |
return Status; |
|
//получим адрес таблицы для хранения цепочек DMA |
dma->m_pScatterGatherTableExt = (DMA_CHAINING_DESCR_EXT*)dma->m_SGTableDscr.SystemAddress; |
pSGTEx = dma->m_pScatterGatherTableExt; |
|
DscrSize = DSCR_BLOCK_SIZE*sizeof(DMA_CHAINING_DESCR_EXT); |
|
//обнулим таблицу дескрипторов DMA |
memset(pSGTEx, 0, dma->m_ScatterGatherBlockCnt*DscrSize); |
|
printk("%s(): m_SGTableDscr.SystemAddress = %p\n", __FUNCTION__, dma->m_SGTableDscr.SystemAddress ); |
printk("%s(): m_SGTableDscr.LogicalAddress = 0x%llx\n", __FUNCTION__, dma->m_SGTableDscr.LogicalAddress ); |
|
//заполним значениями таблицу цепочек DMA |
for(iBlock=0, iEntry=0; iBlock < pMemDscr->PageCount; iBlock++) { |
|
//адрес и размер DMA блока |
u64 address = page_to_phys(pMemDscr->LockedPages[iBlock]); |
u64 DmaSize = dma->m_BlockSize - 0x1000; |
|
|
//заполним поля элментов таблицы дескрипторов |
pSGTEx[iEntry].AddrByte1 = (u8)((address >> 8) & 0xFF); |
pSGTEx[iEntry].AddrByte2 = (u8)((address >> 16) & 0xFF); |
pSGTEx[iEntry].AddrByte3 = (u8)((address >> 24) & 0xFF); |
pSGTEx[iEntry].AddrByte4 = (u8)((address >> 32) & 0xFF); |
pSGTEx[iEntry].SizeByte1 = (u8)((DmaSize >> 8) & 0xFF); |
pSGTEx[iEntry].SizeByte2 = (u8)((DmaSize >> 16) & 0xFF); |
pSGTEx[iEntry].SizeByte3 = (u8)((DmaSize >> 24) & 0xFF); |
pSGTEx[iEntry].Cmd.JumpNextDescr = 1; //перейти к следующему дескриптору |
pSGTEx[iEntry].Cmd.JumpNextBlock = 0; //перейти к следующему блоку дескрипторов |
pSGTEx[iEntry].Cmd.JumpDescr0 = 0; |
pSGTEx[iEntry].Cmd.Res0 = 0; |
pSGTEx[iEntry].Cmd.EndOfTrans = 1; |
pSGTEx[iEntry].Cmd.Res = 0; |
pSGTEx[iEntry].SizeByte1 |= dma->m_DmaDirection; |
|
{ |
u32 *ptr=(u32*)&pSGTEx[iEntry]; |
printk("%s(): %d: Entry Addr: %p, Data Addr: %llx %.8X %.8X\n", |
__FUNCTION__, iEntry, &pSGTEx[iEntry], address, ptr[1], ptr[0]); |
} |
|
if(((iEntry+2)%DSCR_BLOCK_SIZE) == 0) |
{ |
size_t NextDscrBlockAddr = 0; |
DMA_NEXT_BLOCK *pNextBlock = NULL; |
|
pSGTEx[iEntry].Cmd.JumpNextBlock = 1; |
pSGTEx[iEntry].Cmd.JumpNextDescr = 0; |
|
NextDscrBlockAddr = virt_to_phys((void*)&pSGTEx[iEntry+2]); |
//NextDscrBlockAddr = (size_t)((u8*)dma->m_SGTableDscr.LogicalAddress + sizeof(DMA_CHAINING_DESCR_EXT)*(iEntry +2)); |
|
printk("%s(): NextDscrBlock [PA]: 0x%lx\n", __FUNCTION__, NextDscrBlockAddr); |
printk("%s(): NextDscrBlock [VA]: %p\n", __FUNCTION__, &pSGTEx[iEntry+2]); |
|
pNextBlock = (DMA_NEXT_BLOCK*)&pSGTEx[iEntry+1]; |
|
printk("%s(): pNextBlock: %p\n", __FUNCTION__, pNextBlock); |
|
pNextBlock->NextBlkAddr = (NextDscrBlockAddr >> 8) & 0xFFFFFF; |
pNextBlock->Signature = 0x4953; |
pNextBlock->Crc = 0; |
iEntry++; |
} |
iEntry++; |
} |
|
printk("%s(): iEntry = %d\n", __FUNCTION__, iEntry); |
|
if(((iEntry % DSCR_BLOCK_SIZE)) != 0) |
{ |
DMA_NEXT_BLOCK *pNextBlock = NULL; |
u32 i = 0; |
|
pSGTEx[iEntry-1].Cmd.JumpNextDescr = 0; |
|
pNextBlock = (DMA_NEXT_BLOCK*)(&pSGTEx[iEntry]); |
pNextBlock->NextBlkAddr = (dma->m_SGTableDscr.LogicalAddress >> 8); |
|
i = (DSCR_BLOCK_SIZE * dma->m_ScatterGatherBlockCnt) - 1; |
pNextBlock = (DMA_NEXT_BLOCK*)(&pSGTEx[i]); |
|
printk("%s(): %d: pNextBlock: %p\n", __FUNCTION__, i, pNextBlock ); |
|
pNextBlock->NextBlkAddr = 0; |
pNextBlock->Signature = 0x4953; |
pNextBlock->Crc = 0; |
} |
|
printk("%s(): DmaDirection = %d, DmaLocalAddress = 0x%X\n", __FUNCTION__, dma->m_DmaDirection, dma->m_DmaLocalAddress); |
|
//for( ii=0; ii<dma->m_ScatterGatherBlockCnt*DSCR_BLOCK_SIZE; ii++ ) |
//{ |
// u32 *ptr=(u32*)&pSGTEx[ii]; |
// printk("%s(): %d: %.8X %.8X\n", __FUNCTION__, ii, ptr[1], ptr[0]); |
//} |
|
pDscrBuf = (u64*)dma->m_pScatterGatherTableExt; |
319,13 → 488,11
if(iBlock == DSCR_BLOCK_SIZE-1) |
{ |
ctrl_code = ctrl_code ^ data0 ^ data1 ^ data2 ^ data3; |
/* |
printk("<0>%s(): DSCR_BLCK[%d] - NextBlkAddr = 0x%8X, Signature = 0x%4X, Crc = 0x%4X\n", __FUNCTION__, |
printk("%s(): DSCR_BLCK[%d] - NextBlkAddr = 0x%8X, Signature = 0x%4X, Crc = 0x%4X\n", __FUNCTION__, |
iBlkEntry, |
(u32)(pDscrBuf[iBlock] << 8), |
(u16)((pDscrBuf[iBlock] >> 32) & 0xFFFF), |
(u16)ctrl_code); |
*/ |
} |
else |
{ |
335,20 → 502,19
ctrl_tmp |= (ctrl_code & 0x8000) ? 0: 1; |
ctrl_code = ctrl_tmp; |
|
//printk("<0>%s(): %d(%d) - PciAddr = 0x%8X, Cmd = 0x%2X, DmaLength = %d(%2X %2X %2X)\n", __FUNCTION__, |
// iBlock, iBlkEntry, |
// (u32)(pDscrBuf[iBlock] << 8), |
// (u8)(pDscrBuf[iBlock] >> 32), |
// (u32)((pDscrBuf[iBlock] >> 41) << 9), |
// (u8)(pDscrBuf[iBlock] >> 56), |
// (u8)(pDscrBuf[iBlock] >> 48), |
// (u8)(pDscrBuf[iBlock] >> 40)); |
//printk("<0>%s(): JumpNextDescr = %d, JumpNextBlock = %d, JumpDescr0 = %d, EndOfTrans = %d, Signature = 0x%08X, Crc = 0x%08X\n", |
// __FUNCTION__, m_pScatterGatherTable[iEntry].Cmd.EndOfChain, |
// m_pScatterGatherTable[iEntry].Cmd.EndOfTrans, |
// m_pScatterGatherTable[iEntry].Signature, |
// m_pScatterGatherTable[iEntry].Crc |
// ); |
printk("%s(): %d(%d) - PciAddr = 0x%8X, Cmd = 0x%2X, DmaLength = %d(%2X %2X %2X)\n", __FUNCTION__, |
iBlock, iBlkEntry, |
(u32)(pDscrBuf[iBlock] << 8), |
(u8)(pDscrBuf[iBlock] >> 32), |
(u32)((pDscrBuf[iBlock] >> 41) << 9), |
(u8)(pDscrBuf[iBlock] >> 56), |
(u8)(pDscrBuf[iBlock] >> 48), |
(u8)(pDscrBuf[iBlock] >> 40)); |
//printk("%s(): JumpNextDescr = %d, JumpNextBlock = %d, JumpDescr0 = %d, EndOfTrans = %d, Signature = 0x%08X, Crc = 0x%08X\n", |
// __FUNCTION__, dma->m_pScatterGatherTableExt[iEntry].Cmd.EndOfChain, |
// dma->m_pScatterGatherTableExt[iEntry].Cmd.EndOfTrans, |
// dma->m_pScatterGatherTableExt[iEntry].Signature, |
// dma->m_pScatterGatherTableExt[iEntry].Crc ); |
} |
} |
pNextDscr = (u16*)pDscrBuf; |
373,42 → 539,46
int RequestSysBuf(struct CDmaChannel *dma, void **pMemPhysAddr) |
{ |
u32 iBlock = 0; |
u32 order = 0; |
SHARED_MEMORY_DESCRIPTION *pMemDscr = (SHARED_MEMORY_DESCRIPTION*)dma->m_pBufDscr.SystemAddress; |
//u32 order = get_order(dma->m_BlockSize); |
|
//printk("<0>%s()\n", __FUNCTION__); |
printk("%s()\n", __FUNCTION__); |
|
order = get_order(dma->m_BlockSize); |
|
for(iBlock = 0; iBlock < dma->m_BlockCount; iBlock++) |
{ |
dma_addr_t LogicalAddress; |
void *pSystemAddress = NULL; |
u32 *buffer = NULL; |
int iii=0; |
|
pSystemAddress = dma_alloc_coherent( dma->m_dev, dma->m_BlockSize, &LogicalAddress, GFP_KERNEL ); |
//pSystemAddress = (void*)__get_free_pages(GFP_KERNEL, order); |
if(!pSystemAddress) { |
printk("<0>%s(): Not enought memory for %i block location. m_BlockSize = %X, BlockOrder = %d\n", |
__FUNCTION__, (int)iBlock, (int)dma->m_BlockSize, (int)order ); |
return -ENOMEM; |
} |
// if buffer not allocated - allocate memory |
if(dma->m_UseCount == 0) { |
pSystemAddress = dma_alloc_coherent( dma->m_dev, dma->m_BlockSize, &LogicalAddress, GFP_KERNEL ); |
//pSystemAddress = (void*)__get_free_pages(GFP_KERNEL, order); |
if(!pSystemAddress) { |
printk("%s(): Not enought memory for %i block location. m_BlockSize = %X\n", |
__FUNCTION__, (int)iBlock, (int)dma->m_BlockSize ); |
return -ENOMEM; |
} |
|
pMemDscr[iBlock].SystemAddress = pSystemAddress; |
pMemDscr[iBlock].LogicalAddress = LogicalAddress; |
//pMemDscr[iBlock].LogicalAddress = virt_to_bus(pSystemAddress); |
pMemDscr[iBlock].SystemAddress = pSystemAddress; |
pMemDscr[iBlock].LogicalAddress = LogicalAddress; |
//pMemDscr[iBlock].LogicalAddress = virt_to_bus(pSystemAddress); |
|
lock_pages( pMemDscr[iBlock].SystemAddress, dma->m_BlockSize ); |
lock_pages( pMemDscr[iBlock].SystemAddress, dma->m_BlockSize ); |
} |
|
// if buffer allocated - copy memory block addresses |
pMemPhysAddr[iBlock] = (void*)pMemDscr[iBlock].LogicalAddress; |
|
buffer = (u32*)pMemDscr[iBlock].SystemAddress; |
for(iii=0; iii<dma->m_BlockSize/4; iii++) { |
buffer[iii] = 0x12345678; |
{ |
// fill memory block |
//int iii=0; |
//u32 *buffer = (u32*)pMemDscr[iBlock].SystemAddress; |
//for(iii=0; iii<dma->m_BlockSize/4; iii++) { |
// buffer[iii] = 0x12345678; |
//} |
} |
|
//printk("<0>%s(): %i: %p\n", __FUNCTION__, iBlock, pMemPhysAddr[iBlock]); |
printk("%s(): %i: %p\n", __FUNCTION__, iBlock, pMemPhysAddr[iBlock]); |
} |
|
dma->m_BlockCount = iBlock; |
419,21 → 589,19
|
//----------------------------------------------------------------------------- |
|
void ReleaseSysBuf(struct CDmaChannel *dma) |
int ReleaseSysBuf(struct CDmaChannel *dma) |
{ |
u32 iBlock = 0; |
//u32 order = 0; |
SHARED_MEMORY_DESCRIPTION *pMemDscr = (SHARED_MEMORY_DESCRIPTION*)dma->m_pBufDscr.SystemAddress; |
//u32 order = get_order(dma->m_BlockSize); |
|
//printk("<0>%s()\n", __FUNCTION__); |
if(dma->m_UseCount != 0) { |
printk("%s(): Memory may be used in another process! m_UseCount = %d.\n", __FUNCTION__, dma->m_UseCount); |
return -1; |
} |
|
//order = get_order(dma->m_BlockSize); |
printk("%s()\n", __FUNCTION__); |
|
if(!dma->m_UseCount) { |
printk("<0> ReleaseSysBuf(): Memory not allocated.\n"); |
return; |
} |
|
for(iBlock = 0; iBlock < dma->m_BlockCount; iBlock++) |
{ |
unlock_pages( pMemDscr[iBlock].SystemAddress, dma->m_BlockSize ); |
444,6 → 612,8
pMemDscr[iBlock].SystemAddress = NULL; |
pMemDscr[iBlock].LogicalAddress = 0; |
} |
|
return 0; |
} |
|
//----------------------------------------------------------------------------- |
453,7 → 623,7
dma_addr_t LogicalAddress = 0; |
u32 StubSize = 0; |
|
//printk("<0>%s()\n", __FUNCTION__ ); |
//printk("%s()\n", __FUNCTION__ ); |
|
if(!dma) |
return -EINVAL; |
460,20 → 630,20
|
StubSize = sizeof(AMB_STUB) > PAGE_SIZE ? sizeof(AMB_STUB) : PAGE_SIZE; |
|
//printk("<0>%s() 0\n", __FUNCTION__ ); |
//printk("%s() 0\n", __FUNCTION__ ); |
|
if(!dma->m_UseCount) |
if(dma->m_UseCount == 0) |
{ |
void *pStub = dma_alloc_coherent( dma->m_dev, StubSize, &LogicalAddress, GFP_KERNEL ); |
if(!pStub) |
{ |
printk("<0>%s(): Not enought memory for stub\n", __FUNCTION__); |
printk("%s(): Not enought memory for stub\n", __FUNCTION__); |
return -ENOMEM; |
} |
|
lock_pages( pStub, StubSize ); |
|
//printk("<0>%s() 1\n", __FUNCTION__ ); |
//printk("%s() 1\n", __FUNCTION__ ); |
|
dma->m_StubDscr.SystemAddress = pStub; |
dma->m_StubDscr.LogicalAddress = LogicalAddress; |
481,12 → 651,12
//но в дальнейшем в модуле используется dma->m_pStub |
} |
|
//printk("<0>%s() 2\n", __FUNCTION__ ); |
//printk("%s() 2\n", __FUNCTION__ ); |
|
pStubPhysAddr[0] = (void*)dma->m_StubDscr.LogicalAddress; |
|
//printk("<0>%s(): Stub physical address: %zx\n", __FUNCTION__, dma->m_StubDscr.LogicalAddress); |
//printk("<0>%s(): Stub virtual address: %p\n", __FUNCTION__, dma->m_StubDscr.SystemAddress); |
printk("%s(): Stub physical address: %llx\n", __FUNCTION__, dma->m_StubDscr.LogicalAddress); |
printk("%s(): Stub virtual address: %p\n", __FUNCTION__, dma->m_StubDscr.SystemAddress); |
|
return 0; |
} |
497,9 → 667,7
{ |
u32 StubSize = sizeof(AMB_STUB) > PAGE_SIZE ? sizeof(AMB_STUB) : PAGE_SIZE; |
|
//printk("<0>%s()\n", __FUNCTION__); |
|
if(!dma->m_UseCount) |
if(dma->m_UseCount == 0) |
{ |
unlock_pages(dma->m_StubDscr.SystemAddress, StubSize); |
|
509,6 → 677,8
dma->m_pStub = NULL; |
dma->m_StubDscr.SystemAddress = NULL; |
dma->m_StubDscr.LogicalAddress = 0; |
|
printk("%s()\n", __FUNCTION__); |
} |
} |
|
522,7 → 692,7
u32 SGListSize = 0; |
dma_addr_t PhysicalAddress; |
|
//printk("<0>%s()\n", __FUNCTION__); |
printk("%s()\n", __FUNCTION__); |
|
if(dma->m_idBlockFifo == PE_EXT_FIFO_ID) |
{ |
529,7 → 699,7
dma->m_ScatterGatherBlockCnt = dma->m_ScatterGatherTableEntryCnt / (DSCR_BLOCK_SIZE-1); |
dma->m_ScatterGatherBlockCnt = (dma->m_ScatterGatherTableEntryCnt % (DSCR_BLOCK_SIZE-1)) ? (dma->m_ScatterGatherBlockCnt+1) : dma->m_ScatterGatherBlockCnt; |
SGListSize = sizeof(DMA_CHAINING_DESCR_EXT) * DSCR_BLOCK_SIZE * dma->m_ScatterGatherBlockCnt; |
//printk("<0>%s(): SGBlockCnt = %d, SGListSize = %d.\n", __FUNCTION__, dma->m_ScatterGatherBlockCnt, SGListSize); |
printk("%s(): SGBlockCnt = %d, SGListSize = %d.\n", __FUNCTION__, dma->m_ScatterGatherBlockCnt, SGListSize); |
} |
|
SGListMemSize = (SGListSize >= PAGE_SIZE) ? SGListSize : PAGE_SIZE; |
538,7 → 708,7
dma->m_SGTableDscr.SystemAddress = dma_alloc_coherent( dma->m_dev, SGListMemSize, &PhysicalAddress, GFP_KERNEL); |
if(!dma->m_SGTableDscr.SystemAddress) |
{ |
printk("<0>%s(): Not enought memory for scatter/gather list\n", __FUNCTION__); |
printk("%s(): Not enought memory for scatter/gather list\n", __FUNCTION__); |
return -ENOMEM; |
} |
|
552,21 → 722,25
|
//----------------------------------------------------------------------------- |
|
void ReleaseSGList(struct CDmaChannel *dma) |
int ReleaseSGList(struct CDmaChannel *dma) |
{ |
u32 SGListMemSize = 0; |
u32 SGListSize = 0; |
|
//printk("<0>%s()\n", __FUNCTION__); |
if(dma->m_UseCount != 0) { |
printk("%s(): Memory may be used in anoether process. m_UseCount = %d\n", __FUNCTION__, dma->m_UseCount); |
return -1; |
} |
|
if(dma->m_idBlockFifo == PE_EXT_FIFO_ID) |
{ |
printk("%s()\n", __FUNCTION__); |
|
if(dma->m_idBlockFifo == PE_EXT_FIFO_ID) { |
SGListSize = sizeof(DMA_CHAINING_DESCR_EXT) * DSCR_BLOCK_SIZE * dma->m_ScatterGatherBlockCnt; |
} |
|
SGListMemSize = (SGListSize >= PAGE_SIZE) ? SGListSize : PAGE_SIZE; |
|
// закрепляем список в физической памяти |
// освободим страницы списока из физической памяти |
unlock_pages(dma->m_SGTableDscr.SystemAddress, SGListMemSize); |
|
dma_free_coherent( dma->m_dev, SGListMemSize, |
575,6 → 749,8
|
dma->m_SGTableDscr.SystemAddress = NULL; |
dma->m_SGTableDscr.LogicalAddress = 0; |
|
return 0; |
} |
|
//----------------------------------------------------------------------------- |
581,7 → 757,7
|
int StartDmaTransfer(struct CDmaChannel *dma, u32 IsCycling) |
{ |
//printk("<0>%s()\n", __FUNCTION__); |
printk("%s()\n", __FUNCTION__); |
|
dma->m_DmaCycling = IsCycling; |
dma->m_DoneBlock = -1; |
599,6 → 775,9
u32 ctrl_code = ~0; |
u16* pDscr = NULL; |
int iEntry = 0; |
int ii=0; |
DMA_CHAINING_DESCR_EXT *pSGTEx = dma->m_pScatterGatherTableExt; |
|
u32 iLastEntry = dma->m_ScatterGatherTableEntryCnt + dma->m_ScatterGatherBlockCnt - 1; |
if(dma->m_ScatterGatherBlockCnt == 1) |
dma->m_pScatterGatherTableExt[iLastEntry - 1].Cmd.JumpDescr0 = dma->m_DmaCycling; |
605,7 → 784,7
else |
dma->m_pScatterGatherTableExt[iLastEntry - 1].Cmd.JumpNextBlock = dma->m_DmaCycling; |
|
//printk("<0>%s(): m_DmaCycling = %d\n", __FUNCTION__, dma->m_DmaCycling); |
printk("%s(): m_DmaCycling = %d\n", __FUNCTION__, dma->m_DmaCycling); |
|
pDscrBuf = (u64*)dma->m_pScatterGatherTableExt + DSCR_BLOCK_SIZE * (dma->m_ScatterGatherBlockCnt - 1); |
ctrl_code = 0xFFFFFFFF; |
620,14 → 799,15
if(iEntry == DSCR_BLOCK_SIZE-1) |
{ |
ctrl_code = ctrl_code ^ data0 ^ data1 ^ data2 ^ data3; |
/* |
printk("<0>%s(): DSCR_BLK[%d] - NextBlkAddr = 0x%08X, Signature = 0x%04X, Crc = 0x%04X\n", |
__FUNCTION__, |
dma->m_ScatterGatherBlockCnt-1, |
(u32)(pDscrBuf[iEntry] << 8), |
(u16)((pDscrBuf[iEntry] >> 32) & 0xFFFF), |
(u16)ctrl_code); |
*/ |
|
//printk("%s(): DSCR_BLK[%d] - NextBlkAddr = 0x%08X, Signature = 0x%04X, Crc = 0x%04X\n", |
// __FUNCTION__, |
// dma->m_ScatterGatherBlockCnt-1, |
// (u32)(pDscrBuf[iEntry] << 8), |
// (u16)((pDscrBuf[iEntry] >> 32) & 0xFFFF), |
// (u16)ctrl_code); |
|
printk("%s(): ENTRY[%d] - SIGN = 0x%04X, CRC = 0x%04X\n", __FUNCTION__, iEntry, (u16)((pDscrBuf[iEntry] >> 32) & 0xFFFF), (u16)ctrl_code); |
} |
else |
{ |
645,16 → 825,24
// rol ctrl_code,1 |
//} |
|
//printk("<0>%s(): %d(%d) - PciAddr = 0x%08X, Cmd = 0x%02X, DmaLength = %d(%02X %02X %02X)\n", |
// __FUNCTION__, |
// iEntry, dma->m_ScatterGatherBlockCnt-1, |
// (u32)(pDscrBuf[iEntry] << 8), |
// (u16)(pDscrBuf[iEntry] >> 32), |
// (u32)((pDscrBuf[iEntry] >> 41) << 9), |
// (u8)(pDscrBuf[iEntry] >> 56), (u8)(pDscrBuf[iEntry] >> 48), (u8)(pDscrBuf[iEntry] >> 40)); |
//printk("%s(): %02d(%02d) - PciAddr = 0x%08X, Cmd = 0x%04X, DmaLength = 0x%08X (%02X %02X %02X)\n", |
// __FUNCTION__, |
// iEntry, dma->m_ScatterGatherBlockCnt-1, |
// (u32)(pDscrBuf[iEntry] << 8), |
// (u16)(pDscrBuf[iEntry] >> 32), |
// (u32)((pDscrBuf[iEntry] >> 41) << 9), |
// (u8)(pDscrBuf[iEntry] >> 56), (u8)(pDscrBuf[iEntry] >> 48), (u8)(pDscrBuf[iEntry] >> 40)); |
} |
} |
pDscr[255] |= (u16)ctrl_code; |
|
printk("%s(): S/G LIST\n",__FUNCTION__); |
for( ii=0; ii<dma->m_ScatterGatherBlockCnt*DSCR_BLOCK_SIZE; ii++ ) |
{ |
u32 *ptr=(u32*)&pSGTEx[ii]; |
printk("%s(): %02d: %08X %08X\n", __FUNCTION__, ii, ptr[1], ptr[0]); |
} |
printk("%s()\n",__FUNCTION__); |
} |
|
dma->m_pStub->lastBlock = -1; |
668,7 → 856,7
|
u32 NextDmaTransfer(struct CDmaChannel *dma) |
{ |
//printk("<0>%s(): - last block = %d, cycle counter = %d\n", __FUNCTION__, dma->m_pStub->lastBlock, dma->m_CycleNum); |
printk("%s(): - last block = %d, cycle counter = %d\n", __FUNCTION__, dma->m_pStub->lastBlock, dma->m_CycleNum); |
|
if(dma->m_pStub->lastBlock + 1 >= (long)dma->m_BlockCount) |
dma->m_pStub->lastBlock = 0; |
681,8 → 869,8
|
tasklet_hi_schedule(&dma->m_Dpc); |
|
//printk("<0>%s(): tasklet_hi_schedule()\n", __FUNCTION__); |
/* |
//printk("%s(): tasklet_hi_schedule()\n", __FUNCTION__); |
/* |
if(dma->m_AdjustMode && dma->m_DmaCycling) |
{ |
u32 next_done_blk = (dma->m_DoneBlock == dma->m_BlockCount-1) ? 0 : (dma->m_DoneBlock + 1); |
729,7 → 917,7
{ |
if(((dma->m_preBlockCount3 == 0)&&(dma->m_DoneBlock == -1)) || (dma->m_preBlockCount3 == dma->m_DoneBlock)) { |
dma->m_DoneFlag = 0; |
//printk("<0>%s(): m_preBlockCount = %d, m_DoneBlock = %d\n", __FUNCTION__, dma->m_preBlockCount3, dma->m_DoneBlock); |
printk("%s(): m_preBlockCount = %d, m_DoneBlock = %d\n", __FUNCTION__, dma->m_preBlockCount3, dma->m_DoneBlock); |
} |
} |
|
753,7 → 941,7
} |
} |
|
//printk("<0>%s(): DoneBlock = %d, DoneFlag = %d\n", __FUNCTION__, dma->m_DoneBlock, dma->m_DoneFlag); |
printk("%s(): DoneBlock = %d, DoneFlag = %d\n", __FUNCTION__, dma->m_DoneBlock, dma->m_DoneFlag); |
|
return dma->m_DoneFlag; |
} |
762,7 → 950,7
|
void GetState(struct CDmaChannel *dma, u32 *BlockNum, u32 *BlockNumTotal, u32 *OffsetInBlock, u32 *DmaChanState) |
{ |
//printk("<0>%s(): - last block = %d, cycle counter = %d\n", __FUNCTION__, dma->m_pStub->lastBlock, dma->m_CycleNum); |
//printk("%s(): - last block = %d, cycle counter = %d\n", __FUNCTION__, dma->m_pStub->lastBlock, dma->m_CycleNum); |
|
*BlockNum = dma->m_State.lastBlock; |
*BlockNumTotal = dma->m_State.totalCounter; |
774,7 → 962,7
|
void FreezeState(struct CDmaChannel *dma) |
{ |
//printk("<0>%s()\n", __FUNCTION__); |
//printk("%s()\n", __FUNCTION__); |
} |
|
//----------------------------------------------------------------------------- |
783,7 → 971,7
{ |
int status = -ETIMEDOUT; |
|
//printk("<0>%s(): DMA%d\n", __FUNCTION__, dma->m_NumberOfChannel); |
//printk("%s(): DMA%d\n", __FUNCTION__, dma->m_NumberOfChannel); |
|
if( msTimeout < 0 ) { |
status = GrabEvent( &dma->m_BlockEndEvent, -1 ); |
799,7 → 987,7
{ |
int status = -ETIMEDOUT; |
|
//printk("<0>%s(): DMA%d\n", __FUNCTION__, dma->m_NumberOfChannel); |
//printk("%s(): DMA%d\n", __FUNCTION__, dma->m_NumberOfChannel); |
|
if( msTimeout < 0 ) { |
status = GrabEvent( &dma->m_BufferEndEvent, -1 ); |
814,7 → 1002,7
|
int CompleteDmaTransfer(struct CDmaChannel *dma) |
{ |
//printk("<0> %s(): DMA%d\n", __FUNCTION__, dma->m_NumberOfChannel); |
//printk("%s(): DMA%d\n", __FUNCTION__, dma->m_NumberOfChannel); |
dma->m_pStub->state = STATE_STOP; |
return 0; |
} |
850,7 → 1038,7
|
void Adjust(struct CDmaChannel *dma, u32 mode) |
{ |
//printk("<0>%s()\n", __FUNCTION__); |
//printk("%s()\n", __FUNCTION__); |
dma->m_AdjustMode = mode; |
} |
|
858,7 → 1046,7
|
void SetAdmTetr(struct CDmaChannel *dma, u32 AdmNum, u32 TetrNum) |
{ |
//printk("<0>%s()\n", __FUNCTION__); |
//printk("%s()\n", __FUNCTION__); |
dma->m_AdmNum = AdmNum; |
dma->m_TetrNum = TetrNum; |
} |
867,7 → 1055,7
|
void SetDmaLocalAddress(struct CDmaChannel *dma, u32 Address) |
{ |
//printk("<0>%s()\n", __FUNCTION__); |
//printk("%s()\n", __FUNCTION__); |
dma->m_DmaLocalAddress = Address; |
} |
|
875,7 → 1063,7
|
int SetDmaDirection(struct CDmaChannel *dma, u32 DmaDirection) |
{ |
printk("<0>%s()\n", __FUNCTION__); |
printk("%s()\n", __FUNCTION__); |
switch(DmaDirection) |
{ |
case 1: |
906,7 → 1094,7
} |
|
//----------------------------------------------------------------------------- |
|
/* |
void DmaDpcForIsr( unsigned long Context ) |
{ |
struct CDmaChannel *DmaChannel = (struct CDmaChannel *)Context; |
914,8 → 1102,8
|
spin_lock_irqsave(&DmaChannel->m_DmaLock, flags); |
|
//printk("<0>%s(): [DMA%d] m_CurBlockNum = %d, m_BlockCount = %d\n", |
// __FUNCTION__, DmaChannel->m_NumberOfChannel, DmaChannel->m_CurBlockNum, DmaChannel->m_BlockCount ); |
printk("%s(): [DMA%d] m_CurBlockNum = %d, m_BlockCount = %d\n", |
__FUNCTION__, DmaChannel->m_NumberOfChannel, DmaChannel->m_CurBlockNum, DmaChannel->m_BlockCount ); |
DmaChannel->m_State = *DmaChannel->m_pStub; |
|
SetEvent( &DmaChannel->m_BlockEndEvent ); |
924,7 → 1112,10
{ |
HwCompleteDmaTransfer(DmaChannel->m_Board,DmaChannel->m_NumberOfChannel); |
SetEvent( &DmaChannel->m_BufferEndEvent ); |
wake_up_interruptible(&DmaChannel->m_DmaWq); |
printk("%s(): Wake up!\n", __FUNCTION__); |
} |
|
spin_unlock_irqrestore(&DmaChannel->m_DmaLock, flags); |
} |
*/ |
/pexdrv/dmachan.h
13,6 → 13,7
#define _DMA_CHAN_H_ |
|
#include "pexioctl.h" |
#include "memory.h" |
|
#define PE_EXT_FIFO_ID 0x0018 |
|
24,15 → 25,15
u16 m_idBlockFifo; |
|
void *m_Board; // PCI device object |
struct device *m_dev; // PCI device object |
struct tasklet_struct m_Dpc; // the DPC object |
wait_queue_head_t m_DmaWq; |
spinlock_t m_DmaLock; // spinlock |
struct device *m_dev; // PCI device object |
struct tasklet_struct m_Dpc; // the DPC object |
wait_queue_head_t m_DmaWq; |
spinlock_t m_DmaLock; // spinlock |
|
KEVENT m_BlockEndEvent; |
KEVENT m_BufferEndEvent; |
|
AMB_STUB m_State; |
AMB_STUB m_State; |
|
u32 m_AdmNum; |
u32 m_TetrNum; |
55,7 → 56,7
u32 m_preBlockCount3; |
|
u32 m_MemType; |
AMB_STUB *m_pStub; |
AMB_STUB *m_pStub; |
|
SHARED_MEMORY_DESCRIPTION m_StubDscr; //Содержит описатель управляющего блока |
|
62,8 → 63,17
u32 m_BlockCount; //Количество блоков для DMA |
u32 m_BlockSize; //Размер одного блока DMA |
|
SHARED_MEMORY_DESCRIPTION m_pBufDscr; //Описатель для адресов блоков DMA каждый элемент содержит |
SHARED_MEMORY_DESCRIPTION m_pBufDscr; //Описатель для адресов блоков DMA каждый элемент содержит |
SHARED_MEMORY_DESCRIPTION m_BufDscrVA; |
dma_addr_t m_BufDscrPA; |
/* |
DMA_CHAINING_DESCRIPTOR *m_pScatterGatherTableVA; |
dma_addr_t m_pScatterGatherTablePA; |
|
DMA_CHAINING_DESCRIPTOR *m_SGTableDscrVA; |
dma_addr_t m_SGTableDscrPA; |
*/ |
|
DMA_CHAINING_DESCR_EXT *m_pScatterGatherTableExt; //Содержит массив для организации цепочек DMA (v2) |
u32 m_ScatterGatherBlockCnt; //Количество элементов-дескрипторов цепочек DMA |
SHARED_MEMORY_DESCRIPTION m_SGTableDscr; //Описатель массива цепочек DMA |
73,6 → 83,7
}; |
|
struct CDmaChannel* CDmaChannelCreate( u32 NumberOfChannel, |
TASKLET_ROUTINE dpc, |
void *m_Board, |
struct device *dev, |
u32 cbMaxTransferLength, |
80,14 → 91,15
int bScatterGather ); |
void CDmaChannelDelete(struct CDmaChannel *dma); |
int RequestMemory(struct CDmaChannel *dma, void **ppMemPhysAddr, u32 size, u32 *pCount, void **pStubPhysAddr, u32 bMemType); |
void ReleaseMemory(struct CDmaChannel *dma); |
int ReleaseMemory(struct CDmaChannel *dma); |
int RequestSysBuf(struct CDmaChannel *dma, void **pMemPhysAddr); |
void ReleaseSysBuf(struct CDmaChannel *dma); |
int ReleaseSysBuf(struct CDmaChannel *dma); |
int RequestSGList(struct CDmaChannel *dma); |
void ReleaseSGList(struct CDmaChannel *dma); |
int ReleaseSGList(struct CDmaChannel *dma); |
int RequestStub(struct CDmaChannel *dma, void **pStubPhysAddr); |
void ReleaseStub(struct CDmaChannel *dma); |
int SetScatterGatherListExt(struct CDmaChannel *dma); |
int SetScatterGatherListExtUser(struct CDmaChannel *dma); |
void FreeUserAddress(struct CDmaChannel *dma); |
u32 NextDmaTransfer(struct CDmaChannel *dma); |
int SetScatterGatherList(struct CDmaChannel *dma); |
107,7 → 119,7
void GetSGStartParams(struct CDmaChannel *dma, u64* SGTableAddress, u32* LocalAddress, u32* DmaDirection); |
int StartDmaTransfer(struct CDmaChannel *dma, u32 IsCycling); |
u32 SetDoneBlock(struct CDmaChannel *dma, long numBlk); |
void DmaDpcForIsr( unsigned long Context ); |
//void DmaDpcForIsr( unsigned long Context ); |
|
#endif //_DMA_CHANNEL_H_ |
|
/pexdrv/event.c
41,7 → 41,7
// |
int ResetEvent ( KEVENT * event ) |
{ |
//printk("<0>%s() %p\n", __FUNCTION__, event); |
//printk("%s() %p\n", __FUNCTION__, event); |
atomic_set ( &event->m_flag, 0 ); |
return 0; |
} |
53,7 → 53,7
|
wake_up_interruptible( &event->m_wq ); |
|
//printk("<0>%s(): %p\n", __FUNCTION__, event); |
//printk("%s(): %p\n", __FUNCTION__, event); |
|
//if (event->m_async) |
// kill_fasync(&event->m_async, SIGIO, POLL_IN|POLL_OUT); |
64,7 → 64,7
// |
int CheckEventFlag ( KEVENT * event ) |
{ |
//printk("<0>%s(): %p\n", __FUNCTION__, event); |
//printk("%s(): %p\n", __FUNCTION__, event); |
|
if ( atomic_read ( &event->m_flag ) ) |
{ |
85,7 → 85,7
{ |
int status = -1; |
|
//printk("<0>%s()\n", __FUNCTION__); |
//printk("%s()\n", __FUNCTION__); |
|
#ifdef DZYTOOLS_2_4_X |
status = interruptible_sleep_on_timeout( &event->m_wq, ms_to_jiffies(timeout) ); |
94,7 → 94,7
#endif |
|
if(!status) { |
printk("<0>%s(): TIMEOUT\n", __FUNCTION__); |
printk("%s(): TIMEOUT\n", __FUNCTION__); |
return -ETIMEDOUT; |
} |
|
107,7 → 107,7
// |
int GrabEvent( KEVENT * event, u32 timeout ) |
{ |
//printk ( "<0>%s(): E %p, T %d\n", __FUNCTION__, event, timeout ); |
//printk ( "%s(): E %p, T %d\n", __FUNCTION__, event, timeout ); |
|
if( CheckEventFlag( event ) ) { |
ResetEvent(event); |
/pexdrv/exam/Makefile
13,10 → 13,10
LD = $(CROSS_COMPILE)g++ |
|
CFLAGS := -D__LINUX__ -g -Wall -I.. -I../../../common/utils -I../../../common/board |
LFLAGS = -Wl |
LFLAGS = |
|
$(TARGET_NAME): $(patsubst %.cpp,%.o, $(wildcard *.cpp)) |
$(LD) $(LFLAGS) $(notdir $^) -o $(TARGET_NAME) |
$(LD) $(notdir $^) -o $(TARGET_NAME) $(LFLAGS) |
rm -f *.o *~ core |
|
%.o: %.cpp |
/pexdrv/hardware.c
79,8 → 79,8
|
dbg_msg(dbg_trace, "%s(): DeviceID = 0x%X, DeviceRev = 0x%X.\n", __FUNCTION__, deviceID, deviceRev); |
|
pci_set_dma_mask(brd->m_pci, DMA_BIT_MASK(32)); |
|
|
temp = ReadOperationWordReg(brd, PEMAINadr_PLD_VER); |
|
dbg_msg(dbg_trace, "%s(): PldVER = 0x%X.\n", __FUNCTION__, temp); |
446,11 → 446,11
int DmaEnable(struct pex_device *brd, u32 AdmNumber, u32 TetrNumber) |
{ |
int Status = 0; |
//u32 Value = 0; |
//Status = ReadRegData(brd, AdmNumber, TetrNumber, 0, &Value); |
//if(Status != 0) return Status; |
//Value |= 0x8; // DRQ enable |
//Status = WriteRegData(brd, AdmNumber, TetrNumber, 0, Value); |
u32 Value = 0; |
Status = ReadRegData(brd, AdmNumber, TetrNumber, 0, &Value); |
if(Status != 0) return Status; |
Value |= 0x8; // DRQ enable |
Status = WriteRegData(brd, AdmNumber, TetrNumber, 0, Value); |
//err_msg(err_trace, "%s: MODE0 = 0x%X.\n", __FUNCTION__, Value); |
return Status; |
} |
460,11 → 460,11
int DmaDisable(struct pex_device *brd, u32 AdmNumber, u32 TetrNumber) |
{ |
int Status = 0; |
//u32 Value = 0; |
//Status = ReadRegData(brd, AdmNumber, TetrNumber, 0, &Value); |
//if(Status != 0) return Status; |
//Value &= 0xfff7; // DRQ disable |
//Status = WriteRegData(brd, AdmNumber, TetrNumber, 0, Value); |
u32 Value = 0; |
Status = ReadRegData(brd, AdmNumber, TetrNumber, 0, &Value); |
if(Status != 0) return Status; |
Value &= 0xfff7; // DRQ disable |
Status = WriteRegData(brd, AdmNumber, TetrNumber, 0, Value); |
return Status; |
} |
|
505,7 → 505,7
CtrlExt.AsWhole = ReadOperationWordReg(brd, PEFIFOadr_DMA_CTRL + FifoAddr); |
CtrlExt.ByBits.Pause = 0; |
|
//printk("<0>%s(): CtrlExt.AsWhole = 0x%x\n", __FUNCTION__, CtrlExt.AsWhole); |
//printk("%s(): CtrlExt.AsWhole = 0x%x\n", __FUNCTION__, CtrlExt.AsWhole); |
|
WriteOperationWordReg(brd, PEFIFOadr_DMA_CTRL + FifoAddr, CtrlExt.AsWhole); |
|
522,7 → 522,7
u32 adm_num, tetr_num; |
u32 FifoAddr = brd->m_FifoAddr[NumberOfChannel]; |
|
dbg_msg(dbg_trace, "%s(): channel = %d, FifoAddr = 0x%04X.\n",__FUNCTION__, NumberOfChannel, FifoAddr); |
dbg_msg(err_trace, "%s(): channel = %d, FifoAddr = 0x%04X.\n",__FUNCTION__, NumberOfChannel, FifoAddr); |
|
DmaCtrl.AsWhole = 0; |
WriteOperationWordReg(brd, PEFIFOadr_DMA_CTRL + FifoAddr, DmaCtrl.AsWhole); |
568,7 → 568,7
|
adm_num = GetAdmNum(brd->m_DmaChannel[NumberOfChannel]); |
tetr_num = GetTetrNum(brd->m_DmaChannel[NumberOfChannel]); |
//Status = DmaEnable(brd, adm_num, tetr_num); |
Status = DmaEnable(brd, adm_num, tetr_num); |
|
return Status; |
} |
583,6 → 583,8
int i = 0; |
u32 tetr_num; |
|
dbg_msg(err_trace, "%s(): channel = %d, FifoAddr = 0x%04X.\n",__FUNCTION__, NumberOfChannel, FifoAddr); |
|
if(brd->m_BlockFifoId[NumberOfChannel] == PE_EXT_FIFO_ID) |
{ |
DMA_CTRL_EXT CtrlExt; |
604,7 → 606,7
brd->m_DmaIrqEnbl = enbl; |
|
tetr_num = GetTetrNum(brd->m_DmaChannel[NumberOfChannel]); |
//Status = DmaDisable(brd, 0, tetr_num); |
Status = DmaDisable(brd, 0, tetr_num); |
CompleteDmaTransfer(brd->m_DmaChannel[NumberOfChannel]); |
|
return Status; |
/pexdrv/insert
53,10 → 53,9
echo -n " Remove loaded module : " |
/sbin/rmmod $device |
status $? 0 |
else |
echo -n " Loading pexdrv module : " |
fi |
|
echo -n " Loading pexdrv module : " |
insmod ./${module} |
|
until [ -e /dev/pexdrv0 ] |
/pexdrv/ioctlrw.c
291,9 → 291,9
TetrNumber = pKernMemDscr->LocalAddr & 0xff; |
Address = AdmNumber*ADM_SIZE + TetrNumber*TETRAD_SIZE + TRDadr_DATA*REG_SIZE; |
|
//SetDmaLocalAddress(dma, Address); |
//SetAdmTetr(dma, AdmNumber, TetrNumber); |
//error = SetDmaMode(brd, i, AdmNumber, TetrNumber); |
SetDmaLocalAddress(dma, Address); |
SetAdmTetr(dma, AdmNumber, TetrNumber); |
error = SetDmaMode(brd, i, AdmNumber, TetrNumber); |
|
dbg_msg(dbg_trace, "%s(): 4\n", __FUNCTION__); |
|
325,7 → 325,6
|
int ioctl_free_mem(struct pex_device *brd, size_t arg) |
{ |
u32 i = 0; |
int error = 0; |
AMB_MEM_DMA_CHANNEL MemDscr = {0}; |
PAMB_MEM_DMA_CHANNEL pMemDscr = &MemDscr; |
344,14 → 343,13
goto do_exit; |
} |
|
i = pMemDscr->DmaChanNum; |
ReleaseMemory(brd->m_DmaChannel[i]); |
error = ReleaseMemory(brd->m_DmaChannel[pMemDscr->DmaChanNum]); |
|
if(copy_to_user (( void *)arg, (void *)&MemDscr, sizeof(AMB_MEM_DMA_CHANNEL) + (pMemDscr->BlockCnt - 1) * sizeof(void*) )) { |
err_msg(err_trace, "%s(): Error copy descriptor to user space\n", __FUNCTION__); |
error = -EFAULT; |
goto do_exit; |
} |
//if(copy_to_user (( void *)arg, (void *)&MemDscr, sizeof(AMB_MEM_DMA_CHANNEL) + (pMemDscr->BlockCnt - 1) * sizeof(void*) )) { |
// err_msg(err_trace, "%s(): Error copy descriptor to user space\n", __FUNCTION__); |
// error = -EFAULT; |
// goto do_exit; |
//} |
|
do_exit: |
up(&brd->m_BoardSem); |
367,7 → 365,7
AMB_START_DMA_CHANNEL StartDscr; |
PAMB_START_DMA_CHANNEL pStartDscr = &StartDscr; |
|
printk("<0>ioctl_start_mem: Entered.\n"); |
printk("%s(): Entered.\n", __FUNCTION__); |
down(&brd->m_BoardSem); |
|
if( copy_from_user((void *)&StartDscr, (void *)arg, sizeof(AMB_START_DMA_CHANNEL))) { |
377,13 → 375,13
} |
|
if(pStartDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) { |
printk("<0>%s(): too large stream number\n", __FUNCTION__); |
printk("%s(): too large stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
|
if(!(brd->m_DmaChanMask & (1 << pStartDscr->DmaChanNum))) { |
printk("<0>%s(): invalid stream number\n", __FUNCTION__); |
printk("%s(): invalid stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
392,7 → 390,7
Status = HwStartDmaTransfer(brd, pStartDscr->DmaChanNum); |
|
up(&brd->m_BoardSem); |
printk("<0>ioctl_start_mem: exit Status=0x%.8X \n", Status ); |
printk("%s(): exit Status=0x%.8X \n", __FUNCTION__, Status); |
|
return Status; |
} |
415,11 → 413,11
return -EFAULT; |
} |
|
//printk("<0>IoctlStopMem: Entered.\n"); |
//printk("%s()\n", __FUNCTION__); |
|
if(pStopDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>IoctlStopMem: too large stream number\n"); |
printk("IoctlStopMem: too large stream number\n"); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
469,11 → 467,11
return -EFAULT; |
} |
|
//printk("<0>IoctlStateMem: Entered.\n"); |
//printk("%s()\n", __FUNCTION__); |
|
if(pStateDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>IoctlStateMem: too large stream number\n"); |
printk("IoctlStateMem: too large stream number\n"); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
510,7 → 508,7
AMB_SET_DMA_CHANNEL MemDscr; |
PAMB_SET_DMA_CHANNEL pMemDscr = &MemDscr; |
|
printk("<0>IoctlSetDirMem: Entered.\n"); |
printk("%s()\n", __FUNCTION__); |
down(&brd->m_BoardSem); |
|
// get the user buffer |
522,7 → 520,7
|
if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>IoctlSetDirMem: too large stream number\n"); |
printk("%s(): too large stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
547,7 → 545,7
AMB_SET_DMA_CHANNEL MemDscr; |
PAMB_SET_DMA_CHANNEL pMemDscr = &MemDscr; |
|
printk("<0>IoctlSetSrcMem: Entered.\n"); |
printk("%s()\n", __FUNCTION__); |
down(&brd->m_BoardSem); |
|
// get the user buffer |
559,23 → 557,18
|
if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>IoctlSetSrcMem: too large stream number\n"); |
printk("%s(): too large stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
|
i = pMemDscr->DmaChanNum; |
//AdmNumber = pMemDscr->Param >> 16; |
//TetrNumber = pMemDscr->Param & 0xff; |
//Address = AdmNumber * ADM_SIZE + TetrNumber * TETRAD_SIZE + TRDadr_DATA * REG_SIZE; |
|
AdmNumber=0; |
TetrNumber=0; |
Address = pMemDscr->Param; |
AdmNumber = pMemDscr->Param >> 16; |
TetrNumber = pMemDscr->Param & 0xff; |
Address = AdmNumber * ADM_SIZE + TetrNumber * TETRAD_SIZE + TRDadr_DATA * REG_SIZE; |
SetDmaLocalAddress(brd->m_DmaChannel[i], Address); |
SetAdmTetr(brd->m_DmaChannel[i], AdmNumber, TetrNumber); |
//Status = SetDmaMode(brd, i, AdmNumber, TetrNumber); |
Status=0; |
Status = SetDmaMode(brd, i, AdmNumber, TetrNumber); |
|
up(&brd->m_BoardSem); |
|
595,7 → 588,7
|
down(&brd->m_BoardSem); |
|
//printk("<0>IoctlSetSrcMem: Entered.\n"); |
//printk("%s()\n", __FUNCTION__); |
|
// get the user buffer |
if( copy_from_user((void *)&MemDscr, (void *)arg, sizeof(AMB_SET_DMA_CHANNEL))) { |
606,7 → 599,7
|
if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>IoctlSetDrqMem: too large stream number\n"); |
printk("IoctlSetDrqMem: too large stream number\n"); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
631,7 → 624,7
|
down(&brd->m_BoardSem); |
|
//printk("<0>%s()\n", __FUNCTION__); |
//printk("%s()\n", __FUNCTION__); |
|
if( copy_from_user((void *)&MemDscr, (void *)arg, sizeof(AMB_SET_DMA_CHANNEL))) { |
err_msg(err_trace, "%s(): Error copy data from userspace\n", __FUNCTION__ ); |
641,13 → 634,13
|
if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>IoctlSetDrqMem: too large stream number\n"); |
printk("IoctlSetDrqMem: too large stream number\n"); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
if(!(brd->m_DmaChanMask & (1 << pMemDscr->DmaChanNum))) |
{ |
printk("<0>%s(): invalid stream number\n", __FUNCTION__); |
printk("%s(): invalid stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
672,7 → 665,7
|
down(&brd->m_BoardSem); |
|
//printk("<0>%s()\n", __FUNCTION__); |
//printk("%s()\n", __FUNCTION__); |
|
// get the user buffer |
if( copy_from_user((void *)&MemDscr, (void *)arg, sizeof(AMB_SET_DMA_CHANNEL))) { |
683,13 → 676,13
|
if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>IoctlSetDrqMem: too large stream number\n"); |
printk("IoctlSetDrqMem: too large stream number\n"); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
if(!(brd->m_DmaChanMask & (1 << pMemDscr->DmaChanNum))) |
{ |
printk("<0>%s(): invalid stream number\n", __FUNCTION__); |
printk("%s(): invalid stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
723,13 → 716,13
|
if(pMemDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>%s(): too large stream number\n", __FUNCTION__); |
printk("%s(): too large stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
if(!(brd->m_DmaChanMask & (1 << pMemDscr->DmaChanNum))) |
{ |
printk("<0>%s(): invalid stream number\n", __FUNCTION__); |
printk("%s(): invalid stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
758,13 → 751,13
|
if(DmaInfo.DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>%s(): too large stream number\n", __FUNCTION__); |
printk("%s(): too large stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
if(!(brd->m_DmaChanMask & (1 << DmaInfo.DmaChanNum))) |
{ |
printk("<0>%s(): invalid stream number\n", __FUNCTION__); |
printk("%s(): invalid stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
802,11 → 795,11
return -EFAULT; |
} |
|
//printk("<0>%s(): DMA %d\n", __FUNCTION__, pStateDscr->DmaChanNum); |
//printk("%s(): DMA %d\n", __FUNCTION__, pStateDscr->DmaChanNum); |
|
if(pStateDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>%s(): too large stream number\n", __FUNCTION__); |
printk("%s(): too large stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
849,11 → 842,11
return -EFAULT; |
} |
|
printk("<0>%s(): DMA %d\n", __FUNCTION__, pStateDscr->DmaChanNum); |
printk("%s(): DMA %d\n", __FUNCTION__, pStateDscr->DmaChanNum); |
|
if(pStateDscr->DmaChanNum >= MAX_NUMBER_OF_DMACHANNELS) |
{ |
printk("<0>%s(): too large stream number\n", __FUNCTION__); |
printk("%s(): too large stream number\n", __FUNCTION__); |
up(&brd->m_BoardSem); |
return -EINVAL; |
} |
/pexdrv/memory.c
1,6 → 1,6
|
#include <linux/kernel.h> |
#define __NO_VERSION__ |
#include <linux/version.h> |
#include <linux/module.h> |
#include <linux/types.h> |
#include <linux/ioport.h> |
8,10 → 8,13
#include <linux/pagemap.h> |
#include <linux/interrupt.h> |
#include <linux/proc_fs.h> |
#include <linux/sched.h> |
|
#include <asm/io.h> |
|
|
#include "pexmodule.h" |
#include "memory.h" |
#include "pexmodule.h" |
|
//-------------------------------------------------------------------- |
|
20,7 → 23,7
struct page *start_page_addr = virt_to_page(va); |
int i = 0; |
|
for (i=0; i < (size >> PAGE_CACHE_SHIFT); i++) { |
for (i=0; i < (size >> PAGE_SHIFT); i++) { |
SetPageReserved(start_page_addr+i); |
//dbg_msg(dbg_trace, "%s(): page_addr[%d] = 0x%x\n", __FUNCTION__, i, (int)(start_page_addr+i)); |
} |
35,7 → 38,7
struct page *start_page_addr = virt_to_page(va); |
int i = 0; |
|
for (i=0; i < (size >> PAGE_CACHE_SHIFT); i++) { |
for (i=0; i < (size >> PAGE_SHIFT); i++) { |
ClearPageReserved(start_page_addr+i); |
//dbg_msg(dbg_trace, "%s(): page_addr[%d] = 0x%x\n", __FUNCTION__, i, (int)(start_page_addr+i)); |
} |
45,62 → 48,151
|
//-------------------------------------------------------------------- |
|
//-------------------------------------------------------------------- |
/* |
static int copy_memory_descriptors(unsigned long arg, struct memory_descriptor *md, struct memory_block **mb) |
int check_address( void *pMemUserAddr ) |
{ |
struct memory_block *mblocks = NULL; |
int error = 0; |
//int i = 0; |
size_t addr = (size_t)pMemUserAddr; |
size_t mask = (size_t)~PAGE_MASK; |
|
if(copy_from_user((void*)md, (void*)arg, sizeof(struct memory_descriptor))) { |
err_msg(err_trace, "%s(): Error copy memory descriptor from user space\n", __FUNCTION__); |
error = -EINVAL; |
goto do_exit; |
} |
printk("%s()\n", __FUNCTION__); |
|
dbg_msg(dbg_trace, "%s(): md.total_blocks = %zd\n", __FUNCTION__, md->total_blocks ); |
dbg_msg(dbg_trace, "%s(): md.blocks = %p\n", __FUNCTION__, md->blocks ); |
// адрес пользовательского буфера должен быть выровнен на страницу |
if(addr & mask) { |
printk("%s(): %p - Error! Address must be aling at PAGE_SIZE border\n", __FUNCTION__, pMemUserAddr ); |
return 1; |
} |
|
mblocks = kzalloc(md->total_blocks*sizeof(struct memory_block), GFP_KERNEL); |
if(!mblocks) { |
err_msg(err_trace, "%s(): Error allocate memory for memory descriptors\n", __FUNCTION__); |
error = -ENOMEM; |
goto do_exit; |
return 0; |
} |
|
if(copy_from_user((void*)mblocks, (void*)md->blocks, md->total_blocks*sizeof(struct memory_block))) { |
err_msg(err_trace, "%s(): Error copy memory blocks from user space\n", __FUNCTION__); |
error = -EINVAL; |
goto do_free_mem; |
} |
//-------------------------------------------------------------------- |
|
//for(i=0; i<md->total_blocks; i++) { |
// dbg_msg(dbg_trace, "%s(): mb[%d].size = 0x%x\n", __FUNCTION__, i, mblocks[i].size ); |
//} |
int check_size( size_t userSize ) |
{ |
printk("%s()\n", __FUNCTION__); |
|
*mb = mblocks; |
// размер пользовательского буфера должен быть кратен размеру страницы |
if((userSize % PAGE_SIZE) != 0) { |
printk("%s(): Invalid user memory block size - 0x%lX.\n", __FUNCTION__, userSize); |
return 1; |
} |
|
return 0; |
return 0; |
} |
|
do_free_mem: |
kfree(mb); |
//-------------------------------------------------------------------- |
|
do_exit: |
return error; |
int lock_user_memory( SHARED_MEMORY_DESCRIPTION *MemDscr, void* userSpaceAddress, size_t userSpaceSize ) |
{ |
int i = 0; |
int requested_page_count = 0; |
int allocated_page_count = 0; |
|
printk("%s()\n", __FUNCTION__); |
|
if(!MemDscr) { |
printk("%s(): Invalid memory descriptor.\n", __FUNCTION__); |
return -EINVAL; |
} |
|
requested_page_count = (userSpaceSize >> PAGE_SHIFT); |
|
MemDscr->LockedPages = (struct page**)kmalloc(requested_page_count*sizeof(struct page*), GFP_KERNEL); |
if(!MemDscr->LockedPages) { |
printk("%s(): Cant allocate memory for locked pages pointers.\n", __FUNCTION__); |
return -ENOMEM; |
} |
|
memset(MemDscr->LockedPages,0,requested_page_count*sizeof(struct page*)); |
|
down_read(¤t->mm->mmap_sem); |
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0) |
allocated_page_count = get_user_pages(current, |
current->mm, |
(size_t)userSpaceAddress, |
requested_page_count, |
1, |
0, |
MemDscr->LockedPages, |
0); |
#endif |
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(4,9,0)) |
allocated_page_count = get_user_pages((size_t)userSpaceAddress, |
requested_page_count, |
1, |
0, |
MemDscr->LockedPages, |
0); |
#endif |
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,9,0)) |
allocated_page_count = get_user_pages((size_t)userSpaceAddress, |
requested_page_count, |
1, |
MemDscr->LockedPages, |
0); |
#endif |
|
up_read(¤t->mm->mmap_sem); |
|
// если все ok то result содержит число страниц в массиве struct page *pages |
if(MemDscr->PageCount <= 0) { |
printk("%s(): Error to lock memory pages.\n", __FUNCTION__); |
kfree(MemDscr->LockedPages); |
MemDscr->LockedPages = NULL; |
MemDscr->PageCount = 0; |
return -ENOMEM; |
} |
|
printk("%s(): MemDscr->PageCount = %ld\n", __FUNCTION__, MemDscr->PageCount); |
printk("%s(): MemDscr->LockedPages = %p\n", __FUNCTION__, MemDscr->LockedPages); |
|
for(i=0; i<MemDscr->PageCount; i++) { |
|
printk("%s(): LockedPages[%d] = %p\n", __FUNCTION__, i, MemDscr->LockedPages[i]); |
printk("%s(): PhysicalAddress = %p\n", __FUNCTION__, (void*)page_to_phys(MemDscr->LockedPages[i])); |
|
if(!PageReserved(MemDscr->LockedPages[i])) { |
SetPageReserved(MemDscr->LockedPages[i]); |
} |
} |
|
printk("%s(): Lock %ld memory pages\n", __FUNCTION__, MemDscr->PageCount); |
|
return 0; |
} |
*/ |
//----------------------------------------------------------------------------- |
|
int lock_user_pages(unsigned long addr, int size) |
//-------------------------------------------------------------------- |
|
int unlock_user_memory( SHARED_MEMORY_DESCRIPTION *MemDscr ) |
{ |
//int res = 0; |
//res = get_user_pages(current, current->mm, unsigned long start, int nr_pages, int write, int force, |
// struct page **pages, struct vm_area_struct **vmas); |
return -1; |
int i = 0; |
|
printk("%s()\n", __FUNCTION__); |
|
if(!MemDscr) { |
printk("%s(): Invalid parameter MemDscr = %p\n", __FUNCTION__, MemDscr); |
return -EINVAL; |
} |
|
printk("%s(): MemDscr = %p\n", __FUNCTION__, MemDscr); |
|
if(MemDscr->LockedPages) |
printk("%s(): MemDscr->LockedPages = %p\n", __FUNCTION__, MemDscr->LockedPages); |
|
for(i=0; i<MemDscr->PageCount; i++) { |
if(MemDscr->LockedPages[i]) { |
ClearPageReserved(MemDscr->LockedPages[i]); |
//page_cache_release(MemDscr->LockedPages[i]); |
printk("%s(): Unlock page %p\n", __FUNCTION__, MemDscr->LockedPages[i]); |
} |
} |
|
if(MemDscr->LockedPages) |
kfree(MemDscr->LockedPages); |
|
return 0; |
} |
|
//----------------------------------------------------------------------------- |
//-------------------------------------------------------------------- |
|
void* allocate_memory_block(struct pex_device *brd, size_t block_size, dma_addr_t *dma_addr) |
{ |
/pexdrv/memory.h
36,8 → 36,30
}; |
|
//----------------------------------------------------------------------------- |
|
typedef struct _SHARED_PHYSMEMORY_DESCRIPTION { |
void *PhysAddress; // OUT - user memory address |
void *KernAddress; // OUT - user memory address |
void *UserAddress; // OUT - user memory address |
} SHARED_PHYSMEMORY_DESCRIPTION, *PSHARED_PHYSMEMORY_DESCRIPTION; |
|
//----------------------------------------------------------------------------- |
|
typedef struct _SHARED_MEMORY_DESCRIPTION { |
|
void* SystemAddress; // адрес блока памяти выделенного в пространстве ядра |
dma_addr_t LogicalAddress; // физический адрес блока памяти выделенного в пространстве ядра |
struct page** LockedPages; // указатели на страницы блока памяти выделенного в пространстве пользователя |
size_t PageCount; // количество страниц составляющи блок памяти выделенный в пространстве пользователя |
|
} SHARED_MEMORY_DESCRIPTION, *PSHARED_MEMORY_DESCRIPTION; |
|
//----------------------------------------------------------------------------- |
|
struct pex_device; |
struct memory_block; |
struct CDmaChannel; |
|
//----------------------------------------------------------------------------- |
|
int lock_pages( void *va, u32 size ); |
44,6 → 66,8
int unlock_pages( void *va, u32 size ); |
void* allocate_memory_block(struct pex_device *brd, size_t block_size, dma_addr_t *dma_addr); |
int free_memory_block(struct pex_device *brd, struct memory_block mb); |
int lock_user_memory( SHARED_MEMORY_DESCRIPTION *MemDscr, void* userSpaceAddress, size_t userSpaceSize ); |
int unlock_user_memory( SHARED_MEMORY_DESCRIPTION *MemDscr ); |
|
//-------------------------------------------------------------------- |
|
/pexdrv/pexioctl.h
154,14 → 154,6
#define PAGES_SPANNED(Size) (((Size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT) |
|
//----------------------------------------------------------------------------- |
// Shared Memory between kernel and user mode description |
typedef struct _SHARED_MEMORY_DESCRIPTION { |
void* SystemAddress; // INOUT - system memory address |
size_t LogicalAddress; // OUT - logical memory address |
size_t dummy; // OUT - logical memory address |
} SHARED_MEMORY_DESCRIPTION, *PSHARED_MEMORY_DESCRIPTION; |
|
//----------------------------------------------------------------------------- |
// Stub Structure |
typedef struct _AMB_STUB { |
u32 lastBlock; // Number of Block which was filled last Time |
/pexdrv/pexmodule.c
16,7 → 16,7
#include <linux/ioport.h> |
#include <linux/poll.h> |
#include <linux/pci.h> |
#include <linux/interrupt.h> |
#include <linux/delay.h> |
|
#include "pexmodule.h" |
#include "hardware.h" |
24,6 → 24,7
#include "ioctlrw.h" |
#include "ambpexregs.h" |
#include "pexproc.h" |
#include "memory.h" |
|
//----------------------------------------------------------------------------- |
|
100,7 → 101,71
#endif |
|
//----------------------------------------------------------------------------- |
/* |
static ssize_t pex_device_read(struct file *file, char __user *data, size_t count, loff_t *ppos) |
{ |
int error = 0; |
u32 AdmNumber = 0; |
u32 TetrNumber = 0; |
u32 Address = 0; |
struct CDmaChannel *dma = NULL; |
|
struct pex_device *pDevice = file_to_device(file); |
if(!pDevice) { |
err_msg(err_trace, "%s(): No such device\n", __FUNCTION__); |
return -ENODEV; |
} |
|
dma = pDevice->m_DmaChannel[0]; |
|
printk("%s(): data = %p\n", __FUNCTION__, data); |
printk("%s(): size = 0x%lx\n", __FUNCTION__, count); |
printk("%s(): ppos = %p\n", __FUNCTION__, ppos); |
|
error = lock_user_memory( &dma->m_BufDscrVA, data, count); |
if(error < 0) { |
err_msg(err_trace, "%s(): Error in lock_user_memory()\n", __FUNCTION__); |
return -EINVAL; |
} |
|
dma->m_BlockCount = dma->m_BufDscrVA.PageCount; |
dma->m_ScatterGatherTableEntryCnt = dma->m_BufDscrVA.PageCount; |
dma->m_BlockSize = PAGE_SIZE; |
|
AdmNumber = 0; |
TetrNumber = 0; |
Address = AdmNumber*ADM_SIZE + TetrNumber*TETRAD_SIZE + TRDadr_DATA*REG_SIZE; |
|
SetDmaDirection(dma, 1); |
Adjust(dma, 0); |
SetDmaLocalAddress(dma, Address); |
SetAdmTetr(dma, AdmNumber, TetrNumber); |
SetDmaMode(pDevice, 0, AdmNumber, TetrNumber); |
|
RequestStub(dma,NULL); |
SetScatterGatherListExtUser(dma); |
StartDmaTransfer(dma, 0); |
HwStartDmaTransfer(pDevice, 0); |
|
error = WaitEvent(&dma->m_BufferEndEvent, 1000); |
if(error < 0) { |
err_msg(err_trace, "%s(): Timeout read operation\n", __FUNCTION__); |
} |
|
error = unlock_user_memory( &dma->m_BufDscrVA ); |
if(error < 0) { |
err_msg(err_trace, "%s(): Error in lock_user_memory()\n", __FUNCTION__); |
return -EINVAL; |
} |
|
ReleaseStub( dma ); |
ReleaseSGList( dma ); |
|
return 0; |
} |
*/ |
//----------------------------------------------------------------------------- |
|
static int pex_device_fasync(int fd, struct file *file, int mode) |
{ |
struct pex_device *pDevice = file->private_data; |
276,26 → 341,28
|
//----------------------------------------------------------------------------- |
|
static ssize_t pex_device_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long count, loff_t off) |
void tasklet_isr( unsigned long Context ) |
{ |
struct pex_device *pDevice = file_to_device(iocb->ki_filp); |
if(!pDevice) { |
err_msg(err_trace, "%s(): ioctl device failed\n", __FUNCTION__); |
return -ENODEV; |
} |
return -ENOSYS; |
} |
struct CDmaChannel *DmaChannel = (struct CDmaChannel *)Context; |
unsigned long flags = 0; |
|
//----------------------------------------------------------------------------- |
spin_lock_irqsave(&DmaChannel->m_DmaLock, flags); |
|
static ssize_t pex_device_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long count, loff_t off) |
{ |
struct pex_device *pDevice = file_to_device(iocb->ki_filp); |
if(!pDevice) { |
err_msg(err_trace, "%s(): ioctl device failed\n", __FUNCTION__); |
return -ENODEV; |
printk("%s(): [DMA%d] m_CurBlockNum = %d, m_BlockCount = %d\n", |
__FUNCTION__, DmaChannel->m_NumberOfChannel, DmaChannel->m_CurBlockNum, DmaChannel->m_BlockCount ); |
DmaChannel->m_State = *DmaChannel->m_pStub; |
|
SetEvent( &DmaChannel->m_BlockEndEvent ); |
|
if(DmaChannel->m_CurBlockNum >= DmaChannel->m_BlockCount) |
{ |
HwCompleteDmaTransfer(DmaChannel->m_Board,DmaChannel->m_NumberOfChannel); |
SetEvent( &DmaChannel->m_BufferEndEvent ); |
wake_up_interruptible(&DmaChannel->m_DmaWq); |
printk("%s(): Wake up!\n", __FUNCTION__); |
} |
return -ENOSYS; |
|
spin_unlock_irqrestore(&DmaChannel->m_DmaLock, flags); |
} |
|
//----------------------------------------------------------------------------- |
364,7 → 431,7
FifoStatus.AsWhole = ReadOperationWordReg(pDevice, PEFIFOadr_FIFO_STATUS + FifoAddr); |
if(FifoStatus.ByBits.IntRql) |
{ |
//err_msg(err_trace, "%s(): - Channel = %d, Fifo Status = 0x%X\n", __FUNCTION__, iChan, FifoStatus.AsWhole); |
err_msg(err_trace, "%s(): - Channel = %d, Fifo Status = 0x%X\n", __FUNCTION__, iChan, FifoStatus.AsWhole); |
NumberOfChannel = iChan; |
pDevice->m_primChan = ((pDevice->m_primChan+1) >= MAX_NUMBER_OF_DMACHANNELS) ? 0 : pDevice->m_primChan+1; |
break; |
377,11 → 444,10
{ |
u32 flag = 0; |
|
//err_msg(err_trace, "%s(%d)\n", __FUNCTION__, atomic_read(&pDevice->m_TotalIRQ)); |
err_msg(err_trace, "%s(%d)\n", __FUNCTION__, atomic_read(&pDevice->m_TotalIRQ)); |
|
flag = NextDmaTransfer(pDevice->m_DmaChannel[NumberOfChannel]); |
//if(!flag) |
if( 0 ) |
if(!flag) |
{ |
DMA_CTRL_EXT CtrlExt; |
CtrlExt.AsWhole = 0; |
426,8 → 492,6
.release = pex_device_close, |
.fasync = pex_device_fasync, |
.poll = pex_device_poll, |
.aio_read = pex_device_aio_read, |
.aio_write = pex_device_aio_write, |
}; |
|
//----------------------------------------------------------------------------- |
557,6 → 621,14
|
brd->m_BoardIndex = boards_count; |
|
if(pci_set_dma_mask(brd->m_pci, DMA_BIT_MASK(32))) { |
dbg_msg(dbg_trace, "%s(): Error in dma_set_mask_and_coherent() - no suitable DMA available\n", __FUNCTION__); |
} |
|
if (dma_set_mask_and_coherent(&brd->m_pci->dev, DMA_BIT_MASK(32))) { |
dbg_msg(dbg_trace, "%s(): Error in dma_set_mask_and_coherent() - no suitable DMA available\n", __FUNCTION__); |
} |
|
InitializeBoard(brd); |
|
for(i = 0; i < MAX_NUMBER_OF_DMACHANNELS; i++) { |
563,7 → 635,7
|
if(brd->m_DmaChanMask & (1 << i)) { |
|
brd->m_DmaChannel[i] = CDmaChannelCreate( i, brd, |
brd->m_DmaChannel[i] = CDmaChannelCreate( i, tasklet_isr, brd, |
&brd->m_pci->dev, |
brd->m_MaxDmaSize[i], |
brd->m_BlockFifoId[i], 1 ); |
570,7 → 642,7
} |
} |
|
pex_register_proc(brd->m_name, pex_proc_info, brd); |
pex_register_proc(brd->m_name, 0, brd); |
|
list_add_tail(&brd->m_list, &device_list); |
|
/pexdrv/pexproc.c
2,6 → 2,7
#include <linux/kernel.h> |
#define __NO_VERSION__ |
#include <linux/module.h> |
#include <linux/version.h> |
#include <linux/types.h> |
#include <linux/ioport.h> |
#include <linux/pci.h> |
8,8 → 9,10
#include <linux/pagemap.h> |
#include <linux/interrupt.h> |
#include <linux/proc_fs.h> |
#include <linux/seq_file.h> |
#include <asm/io.h> |
|
|
#include "pexmodule.h" |
#include "pexproc.h" |
#include "ambpexregs.h" |
17,25 → 20,14
|
//-------------------------------------------------------------------- |
|
void pex_register_proc( char *name, void *fptr, void *data ) |
{ |
create_proc_read_entry( name, 0, NULL, fptr, data ); |
} |
#define print_info(p, S...) seq_printf(p, S) |
|
//-------------------------------------------------------------------- |
|
void pex_remove_proc( char *name ) |
void pex_brd_capabilities(struct pex_device *brd, struct seq_file *p) |
{ |
remove_proc_entry( name, NULL ); |
} |
|
//-------------------------------------------------------------------- |
|
int pex_show_capabilities( char *buf, struct pex_device *brd ) |
{ |
int i = 0; |
int res = 0; |
char *p = buf; |
u8 cap = 0; |
u32 cap_id = 0; |
|
44,29 → 36,25
goto err_exit; |
} |
|
if(!buf) { |
goto err_exit; |
} |
print_info(p,"\n" ); |
|
p += sprintf(p,"\n" ); |
|
res = pci_read_config_byte(m_pci, 0x34, &cap); |
if(res < 0) { |
p += sprintf(p, " Error read capabilities pointer\n"); |
print_info(p, " Error read capabilities pointer\n"); |
goto err_exit; |
} |
|
p += sprintf(p, " Capability pointer: 0x%x\n", cap); |
print_info(p, " Capability pointer: 0x%x\n", cap); |
|
while(1) { |
|
res = pci_read_config_dword(m_pci, cap, &cap_id); |
if(res < 0) { |
p += sprintf(p, " Error read capabilities id\n"); |
print_info(p, " Error read capabilities id\n"); |
goto err_exit; |
} |
|
p += sprintf(p, " Capability ID: 0x%x\n", cap_id); |
print_info(p, " Capability ID: 0x%x\n", cap_id); |
|
if((cap_id & 0xff) == 0x10) { |
break; |
78,13 → 66,13
} |
|
if((cap_id & 0xff) != 0x10) { |
p += sprintf(p, " Can't find PCI Express capabilities\n"); |
print_info(p, " Can't find PCI Express capabilities\n"); |
goto err_exit; |
} |
|
p += sprintf(p,"\n" ); |
p += sprintf(p, " PCI Express Capability Register Set\n"); |
p += sprintf(p,"\n" ); |
print_info(p,"\n" ); |
print_info(p, " PCI Express Capability Register Set\n"); |
print_info(p,"\n" ); |
|
for(i=0; i<9; i++) { |
u32 reg = 0; |
91,43 → 79,34
int j = cap + 4*i; |
res = pci_read_config_dword(m_pci, j, ®); |
if(res < 0) { |
p += sprintf(p, " Error read capabilities sructure: offset %x\n", j); |
print_info(p, " Error read capabilities sructure: offset %x\n", j); |
goto err_exit; |
} |
p += sprintf(p, " 0x%x: 0x%X\n", j, reg); |
print_info(p, " 0x%x: 0x%X\n", j, reg); |
} |
|
return; |
|
err_exit: |
|
return (p-buf); |
print_info(p, " Error print info\n"); |
} |
|
int pex_proc_info( char *buf, |
char **start, |
off_t off, |
int count, |
int *eof, |
void *data ) |
//-------------------------------------------------------------------- |
|
void pex_brd_info(struct pex_device *brd, struct seq_file *p) |
{ |
int iBlock = 0; |
char *p = buf; |
struct pex_device *brd = (struct pex_device*)data; |
|
if(!brd) { |
p += sprintf(p," Invalid device pointer\n" ); |
*eof = 1; |
return p - buf; |
print_info(p," Invalid device pointer\n" ); |
return; |
} |
|
p += pex_show_capabilities(p, brd); |
pex_brd_capabilities(brd, p); |
|
p += sprintf(p,"\n" ); |
p += sprintf(p," Device information\n" ); |
print_info(p,"\n" ); |
print_info(p," Device information\n" ); |
print_info(p, " m_TotalIRQ = %d\n", atomic_read(&brd->m_TotalIRQ)); |
|
p += sprintf(p, " m_TotalIRQ = %d\n", atomic_read(&brd->m_TotalIRQ)); |
|
|
|
for(iBlock = 0; iBlock < brd->m_BlockCnt; iBlock++) |
{ |
u32 FifoAddr = 0; |
139,38 → 118,98
if((val & 0x0FFF) != PE_EXT_FIFO_ID) |
continue; |
|
p += sprintf(p,"\n" ); |
p += sprintf(p," PE_EXT_FIFO %d\n", iBlock+1 ); |
p += sprintf(p,"\n" ); |
print_info(p,"\n" ); |
print_info(p," PE_EXT_FIFO %d\n", iBlock+1 ); |
print_info(p,"\n" ); |
|
p += sprintf(p," BLOCK_ID = %x\n", (val & 0x0FFF) ); |
print_info(p," BLOCK_ID = %x\n", (val & 0x0FFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_BLOCK_VER + FifoAddr); |
p += sprintf(p," BLOCK_VER = %x\n", (val & 0xFFFF) ); |
print_info(p," BLOCK_VER = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_FIFO_ID + FifoAddr); |
p += sprintf(p," FIFO_ID = %x\n", (val & 0xFFFF) ); |
print_info(p," FIFO_ID = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_FIFO_NUM + FifoAddr); |
p += sprintf(p," FIFO_NUMBER = %x\n", (val & 0xFFFF) ); |
print_info(p," FIFO_NUMBER = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_DMA_SIZE + FifoAddr); |
p += sprintf(p," RESOURCE = %x\n", (val & 0xFFFF) ); |
print_info(p," RESOURCE = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_FIFO_CTRL + FifoAddr); |
p += sprintf(p," DMA_MODE = %x\n", (val & 0xFFFF) ); |
print_info(p," DMA_MODE = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_DMA_CTRL + FifoAddr); |
p += sprintf(p," DMA_CTRL = %x\n", (val & 0xFFFF) ); |
print_info(p," DMA_CTRL = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_FIFO_STATUS + FifoAddr); |
p += sprintf(p," FIFO_STATUS = %x\n", (val & 0xFFFF) ); |
print_info(p," FIFO_STATUS = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_FLAG_CLR + FifoAddr); |
p += sprintf(p," FLAG_CLR = %x\n", (val & 0xFFFF) ); |
print_info(p," FLAG_CLR = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_PCI_ADDRL + FifoAddr); |
p += sprintf(p," PCI_ADRL = %x\n", (val & 0xFFFF) ); |
print_info(p," PCI_ADRL = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_PCI_ADDRH + FifoAddr); |
p += sprintf(p," PCI_ADRH = %x\n", (val & 0xFFFF) ); |
print_info(p," PCI_ADRH = %x\n", (val & 0xFFFF) ); |
val = ReadOperationWordReg(brd, PEFIFOadr_LOCAL_ADR + FifoAddr); |
p += sprintf(p," LOCAL_ADR = %x\n", (val & 0xFFFF) ); |
print_info(p," LOCAL_ADR = %x\n", (val & 0xFFFF) ); |
} |
} |
|
*eof = 1; |
//-------------------------------------------------------------------- |
|
return p - buf; |
static int pex_proc_show(struct seq_file *m, void *v) |
{ |
struct pex_device *brd = m->private; |
|
pex_brd_info(brd, m); |
|
return 0; |
} |
|
//-------------------------------------------------------------------- |
|
static int pex_proc_open(struct inode *inode, struct file *file) |
{ |
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) |
struct pex_device* brd = PDE_DATA(inode); |
#else |
struct pex_device* brd = PDE(inode)->data; |
#endif |
|
return single_open(file, pex_proc_show, brd); |
} |
|
//-------------------------------------------------------------------- |
|
static int pex_proc_release(struct inode *inode, struct file *file) |
{ |
return single_release(inode, file); |
} |
|
//-------------------------------------------------------------------- |
|
static const struct file_operations pex_proc_fops = { |
.owner = THIS_MODULE, |
.open = pex_proc_open, |
.read = seq_read, |
.llseek = seq_lseek, |
.release = pex_proc_release, |
}; |
|
//-------------------------------------------------------------------- |
|
void pex_register_proc( char *name, void *fptr, void *data ) |
{ |
struct pex_device *brd = (struct pex_device *)data; |
|
if(!brd) { |
dbg_msg( dbg_trace, "%s(): Invalid driver pointer\n", __FUNCTION__ ); |
return; |
} |
|
if(!proc_create_data(name, S_IRUGO, NULL, &pex_proc_fops, brd)) { |
dbg_msg(1, "%s(): Error register proc entry: /proc/%s\n", __FUNCTION__, name); |
} |
} |
|
//-------------------------------------------------------------------- |
|
void pex_remove_proc( char *name ) |
{ |
remove_proc_entry(name, NULL); |
} |
|
//-------------------------------------------------------------------- |
/pexdrv/pexproc.h
2,12 → 2,6
#ifndef __PEXPROC_H__ |
#define __PEXPROC_H__ |
|
int pex_proc_info(char *buf, |
char **start, |
off_t off, |
int count, |
int *eof, |
void *data ); |
void pex_register_proc(char *name, void *fptr, void *data); |
void pex_remove_proc(char *name); |
|