Line 14... |
Line 14... |
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
#include <linux/types.h>
|
#include <linux/types.h>
|
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
#include <linux/poll.h>
|
#include <linux/poll.h>
|
#include <linux/pci.h>
|
#include <linux/pci.h>
|
#include <linux/interrupt.h>
|
#include <linux/delay.h>
|
|
|
#include "pexmodule.h"
|
#include "pexmodule.h"
|
#include "hardware.h"
|
#include "hardware.h"
|
#include "pexioctl.h"
|
#include "pexioctl.h"
|
#include "ioctlrw.h"
|
#include "ioctlrw.h"
|
#include "ambpexregs.h"
|
#include "ambpexregs.h"
|
#include "pexproc.h"
|
#include "pexproc.h"
|
|
#include "memory.h"
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
MODULE_AUTHOR("Vladimir Karakozov. karakozov@gmail.com");
|
MODULE_AUTHOR("Vladimir Karakozov. karakozov@gmail.com");
|
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
Line 98... |
Line 99... |
return NULL;
|
return NULL;
|
}
|
}
|
#endif
|
#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)
|
static int pex_device_fasync(int fd, struct file *file, int mode)
|
{
|
{
|
struct pex_device *pDevice = file->private_data;
|
struct pex_device *pDevice = file->private_data;
|
if(!pDevice)
|
if(!pDevice)
|
Line 274... |
Line 339... |
return 0;
|
return 0;
|
}
|
}
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
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);
|
struct CDmaChannel *DmaChannel = (struct CDmaChannel *)Context;
|
if(!pDevice) {
|
unsigned long flags = 0;
|
err_msg(err_trace, "%s(): ioctl device failed\n", __FUNCTION__);
|
|
return -ENODEV;
|
|
}
|
|
return -ENOSYS;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
spin_lock_irqsave(&DmaChannel->m_DmaLock, flags);
|
|
|
|
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;
|
|
|
static ssize_t pex_device_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long count, loff_t off)
|
SetEvent( &DmaChannel->m_BlockEndEvent );
|
|
|
|
if(DmaChannel->m_CurBlockNum >= DmaChannel->m_BlockCount)
|
{
|
{
|
struct pex_device *pDevice = file_to_device(iocb->ki_filp);
|
HwCompleteDmaTransfer(DmaChannel->m_Board,DmaChannel->m_NumberOfChannel);
|
if(!pDevice) {
|
SetEvent( &DmaChannel->m_BufferEndEvent );
|
err_msg(err_trace, "%s(): ioctl device failed\n", __FUNCTION__);
|
wake_up_interruptible(&DmaChannel->m_DmaWq);
|
return -ENODEV;
|
printk("%s(): Wake up!\n", __FUNCTION__);
|
}
|
}
|
return -ENOSYS;
|
|
|
spin_unlock_irqrestore(&DmaChannel->m_DmaLock, flags);
|
}
|
}
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
|
|
static irqreturn_t pex_device_isr( int irq, void *pContext )
|
static irqreturn_t pex_device_isr( int irq, void *pContext )
|
Line 362... |
Line 429... |
{
|
{
|
FifoAddr = pDevice->m_FifoAddr[iChan];
|
FifoAddr = pDevice->m_FifoAddr[iChan];
|
FifoStatus.AsWhole = ReadOperationWordReg(pDevice, PEFIFOadr_FIFO_STATUS + FifoAddr);
|
FifoStatus.AsWhole = ReadOperationWordReg(pDevice, PEFIFOadr_FIFO_STATUS + FifoAddr);
|
if(FifoStatus.ByBits.IntRql)
|
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;
|
NumberOfChannel = iChan;
|
pDevice->m_primChan = ((pDevice->m_primChan+1) >= MAX_NUMBER_OF_DMACHANNELS) ? 0 : pDevice->m_primChan+1;
|
pDevice->m_primChan = ((pDevice->m_primChan+1) >= MAX_NUMBER_OF_DMACHANNELS) ? 0 : pDevice->m_primChan+1;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
Line 375... |
Line 442... |
|
|
if(NumberOfChannel != -1)
|
if(NumberOfChannel != -1)
|
{
|
{
|
u32 flag = 0;
|
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]);
|
flag = NextDmaTransfer(pDevice->m_DmaChannel[NumberOfChannel]);
|
//if(!flag)
|
if(!flag)
|
if( 0 )
|
|
{
|
{
|
DMA_CTRL_EXT CtrlExt;
|
DMA_CTRL_EXT CtrlExt;
|
CtrlExt.AsWhole = 0;
|
CtrlExt.AsWhole = 0;
|
CtrlExt.ByBits.Pause = 1;
|
CtrlExt.ByBits.Pause = 1;
|
CtrlExt.ByBits.Start = 1;
|
CtrlExt.ByBits.Start = 1;
|
Line 424... |
Line 490... |
.mmap = pex_device_mmap,
|
.mmap = pex_device_mmap,
|
.open = pex_device_open,
|
.open = pex_device_open,
|
.release = pex_device_close,
|
.release = pex_device_close,
|
.fasync = pex_device_fasync,
|
.fasync = pex_device_fasync,
|
.poll = pex_device_poll,
|
.poll = pex_device_poll,
|
.aio_read = pex_device_aio_read,
|
|
.aio_write = pex_device_aio_write,
|
|
};
|
};
|
|
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
Line 555... |
Line 619... |
|
|
dbg_msg(dbg_trace, "%s(): Create device file for board: %s\n", __FUNCTION__, brd->m_name);
|
dbg_msg(dbg_trace, "%s(): Create device file for board: %s\n", __FUNCTION__, brd->m_name);
|
|
|
brd->m_BoardIndex = boards_count;
|
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);
|
InitializeBoard(brd);
|
|
|
for(i = 0; i < MAX_NUMBER_OF_DMACHANNELS; i++) {
|
for(i = 0; i < MAX_NUMBER_OF_DMACHANNELS; i++) {
|
|
|
if(brd->m_DmaChanMask & (1 << i)) {
|
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_pci->dev,
|
brd->m_MaxDmaSize[i],
|
brd->m_MaxDmaSize[i],
|
brd->m_BlockFifoId[i], 1 );
|
brd->m_BlockFifoId[i], 1 );
|
}
|
}
|
}
|
}
|
|
|
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);
|
list_add_tail(&brd->m_list, &device_list);
|
|
|
boards_count++;
|
boards_count++;
|
|
|