PCI Express设备驱动 (3)

时间:2021-10-08 12:20:05
//打开设备文件系统调用对应的操作
static int card_open(struct inode *inode, struct file *filp)
{
return 0;
}

//关闭设备文件系统调用对应的操作
static int card_release(struct inode *inode, struct file *filp)
{
return 0;
}

static ssize_t card_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
{

void* virt_addr = NULL;
dma_addr_t dma_write_addr;
u32
base, w_ddr2, w_addr,w_size,cst_32,w_counter,dma_cst;
u32 ddr2;
int i;
i
= 0;

pci_read_config_dword(adapter
->pci_dev, 0x10, &base);
printk(KERN_DEBUG
" pci_read_config_dword, base:%x\n",base);

printk(KERN_DEBUG
"adater -> pci_bar0 %lx\n",(unsigned long)(adapter -> pci_bar0));


/*********Request virt_addr(kernel) for Read(DMA write)********/

virt_addr
= kmalloc(count, GFP_KERNEL|__GFP_DMA);

if(unlikely(!virt_addr))
{
//PDEBUG("cannot alloc rx memory you want ... \n");
return -EIO;
}
printk(KERN_DEBUG
" virt_addr(kernel):%x\n",(u32)virt_addr);

/*********Request virt_addr(kernel) for Read(DMA write)********/

/**********************dma_write_addr************************/
//将存储器域的虚拟地址virt_addr转化为pci总线域的物理地址dma_write_addr,供card的DMA控制器使用。
dma_write_addr = pci_map_single(adapter->pci_dev, virt_addr, count, PCI_DMA_FROMDEVICE);

if(unlikely(pci_dma_mapping_error(adapter->pci_dev, dma_write_addr)))
{
//PDEBUG("RX DMA MAPPING FAIL...\n");
goto err_kmalloc;
}
printk(KERN_DEBUG
" dma_write_addr:%x\n",dma_write_addr);

/**********************dma_write_addr************************/


/**********************BAR0 kong jian ***********************/

// START, w_counter
w_counter = ioread32((adapter -> pci_bar0+WRITE_DMA_COUNTER_OFFSET));
printk(KERN_DEBUG
" START, w_counter: %x",w_counter);

// w_ddr2
iowrite32(*f_pos,(adapter -> pci_bar0 + WRITE_DDR2_SA_OFFSET));
ddr2
= ioread32((adapter -> pci_bar0 + WRITE_DDR2_SA_OFFSET));
printk(KERN_DEBUG
" WRITE_DDR2_SA_OFFSET: %x",ddr2);

// w_addr
// Lower 32-bit address of system memory buffer for DMA write operation.
iowrite32(dma_write_addr,(adapter -> pci_bar0 + WRITE_HOST_DA_L_OFFSET));

// w_size
// Write DMA TLP Size Register(from DDR2 to mm).
iowrite32(count,(adapter -> pci_bar0 + WRITE_SIZE_OFFSET));

// Write DMA Control && Status Register
dma_cst = 0;
dma_cst
= ioread32((adapter -> pci_bar0 + DMA_CST_OFFSET));
printk(KERN_DEBUG
"dma_cst1: %x",dma_cst);
dma_cst
= dma_cst | 0x1;
printk(KERN_DEBUG
"dma_cst2: %x",dma_cst);

// dma_cst
//writel(dma_cst,(void __iomem *) (unsigned long) (adapter -> pci_bar0 + DMA_CST_OFFSET));
iowrite32(dma_cst,(adapter -> pci_bar0 + DMA_CST_OFFSET));

dma_cst
= ioread32((adapter -> pci_bar0+DMA_CST_OFFSET));
printk(KERN_DEBUG
"dma_cst3: %x",dma_cst);


while( (!(dma_cst & 0x2))&&(i<1000) )
{
dma_cst
= ioread8((adapter -> pci_bar0 + DMA_CST_OFFSET));
i
++;
printk(KERN_DEBUG
"#########################################");
}

i
= 0;

dma_cst
= dma_cst | 0x2;
iowrite32(dma_cst,(adapter
-> pci_bar0 + DMA_CST_OFFSET));
dma_cst
= ioread8((adapter -> pci_bar0 + DMA_CST_OFFSET));
printk(KERN_DEBUG
"dma_cst4: %x",dma_cst);

//interruptible_sleep_on((adapter->dma_write_wait));
//wait_event_interruptible(dma_write_wait,flag);
//flag = 0;

//test (w_ddr2, w_addr,w_size,cst_32,w_counter)
w_ddr2 = ioread32((adapter -> pci_bar0 + WRITE_DDR2_SA_OFFSET));
w_addr
= ioread32((adapter -> pci_bar0 + WRITE_HOST_DA_L_OFFSET));
w_size
= ioread32((adapter -> pci_bar0 + WRITE_SIZE_OFFSET));
cst_32
= ioread32((adapter -> pci_bar0 + DMA_CST_OFFSET));

printk(KERN_DEBUG
"w_ddr2: %x; w_addr: %x; w_size: %u; w_cst:%x \n",w_ddr2,w_addr,w_size,cst_32);

//END, w_counter
w_counter = ioread32((adapter -> pci_bar0+WRITE_DMA_COUNTER_OFFSET));
printk(KERN_DEBUG
"END, w_counter: %x\n",w_counter);

/*************************BAR0 kong jian **************************/


/*************************copy_to_user****************************/

if(unlikely(copy_to_user(buf,virt_addr,count)))
goto err_pci_map;

/*************************copy_to_user****************************/

pci_unmap_single(adapter
->pci_dev, dma_write_addr, count, PCI_DMA_FROMDEVICE);
kfree(virt_addr);

printk(KERN_DEBUG
"Here I am: %s:%i\n",__FILE__,__LINE__);

return count;

err_pci_map:
//wake_up_interruptible(&adapter->dma_write_wait);
return -1;

err_kmalloc:
return -1;

}



static ssize_t card_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
{
//unsigned int dma_cst = 0;
int err = -EINVAL;
void * virt_addr = NULL;
dma_addr_t dma_read_addr;
u32
base, r_addr, r_ddr2, r_size, cst_32, r_counter,dma_cst;
struct timeval tv1;
struct timeval tv2;
spinlock_t write_lock;
int i;
i
= 0;


/************************BAR0****************************/

pci_read_config_dword(adapter
->pci_dev, 0x10, &base);
printk(KERN_DEBUG
" pci_read_config_dword, base:%x\n",base);

printk(KERN_DEBUG
"adater -> pci_bar0 %lx\n",(unsigned long)(adapter -> pci_bar0));

/************************BAR0****************************/

/***********Request virt_addr(kernel) for Write(DMA Read)*********/

virt_addr
= kmalloc(count, GFP_KERNEL|__GFP_DMA);

if(unlikely(copy_from_user(virt_addr, buf, count)))
return err;
printk(KERN_DEBUG
" virt_addr(kernel):%x\n",(u32)virt_addr);

/***********Request virt_addr(kernel) for Write(DMA Read)*********/

/************************dma_read_addr****************************/

dma_read_addr
= pci_map_single(adapter->pci_dev, virt_addr, count, PCI_DMA_TODEVICE);

if(unlikely(pci_dma_mapping_error(adapter->pci_dev, dma_read_addr)))
{
//PDEBUG("RX DMA MAPPING FAIL...\n");
goto err_kmalloc;
}
printk(KERN_DEBUG
" dma_read_addr:%x\n", dma_read_addr);

/************************dma_read_addr****************************/

spin_lock_init(
&write_lock);
/*************************BAR0 kong jian **************************/
spin_lock(
&write_lock);

// START, r_counter
r_counter = ioread32((adapter -> pci_bar0 + READ_DMA_COUNTER_OFFSET));
printk(KERN_DEBUG
" START, r_counter: %x",r_counter);

// r_addr
// Lower 32-bit address of system memory buffer for DMA READ operation.
iowrite32(dma_read_addr, (adapter -> pci_bar0 + READ_HOST_SA_L_OFFSET));

// r_ddr2
iowrite32(*f_pos,(adapter -> pci_bar0 + READ_DDR2_DA_OFFSET));

// r_size
// Read DMA TLP Size Register(from mm to DDR2).
iowrite32(count, (adapter -> pci_bar0 + READ_SIZE_OFFSET));

// dma_cst
// Read DMA Control and Status Register
dma_cst = ioread8((adapter -> pci_bar0 + DMA_CST_OFFSET));
printk(KERN_DEBUG
"dma_cst1: %x",dma_cst);

dma_cst
= dma_cst | 0x4;

iowrite8(dma_cst,(adapter
-> pci_bar0 + DMA_CST_OFFSET));

dma_cst
= ioread8((adapter -> pci_bar0 + DMA_CST_OFFSET));
printk(KERN_DEBUG
"dma_cst2: %x",dma_cst);

do_gettimeofday(
&tv1);

while( (!(dma_cst & 0x8)) && (i < 1000) )
{
dma_cst
= ioread8((adapter -> pci_bar0 + DMA_CST_OFFSET));
i
++;
//printk(KERN_DEBUG "******************%d \n",i);
}

do_gettimeofday(
&tv2);
printk(KERN_DEBUG
"time_time: %ld",(tv2.tv_usec-tv1.tv_usec));

i
= 0;

dma_cst
= ioread8((adapter -> pci_bar0 + DMA_CST_OFFSET));
printk(KERN_DEBUG
"dma_cst3: %x",dma_cst);

dma_cst
= dma_cst | 0x8;
iowrite8(dma_cst,(adapter
-> pci_bar0 + DMA_CST_OFFSET));
dma_cst
= ioread8((adapter -> pci_bar0 + DMA_CST_OFFSET));
printk(KERN_DEBUG
"dma_cst4: %x",dma_cst);

//adapter->dma_read_done = 0;

//if(unlikely(interruptible_sleep_on(adapter->dma_read_wait)))
// goto err_pci_map;
//interruptible_sleep_on(adapter->dma_read_wait);

//test (r_addr,r_ddr2,r_size,cst_32, r_counter)
r_ddr2 = ioread32((adapter -> pci_bar0 + READ_DDR2_DA_OFFSET));
r_addr
= ioread32((adapter -> pci_bar0 + READ_HOST_SA_L_OFFSET));
r_size
= ioread32((adapter -> pci_bar0 + READ_SIZE_OFFSET));
cst_32
= ioread32((adapter -> pci_bar0 + DMA_CST_OFFSET));

printk(KERN_DEBUG
"r_ddr2: %x; r_addr: %x; r_size: %u; r_cst:%x \n",r_ddr2,r_addr,r_size,cst_32);

//END, w_counter
r_counter = ioread32((adapter -> pci_bar0 + READ_DMA_COUNTER_OFFSET));
printk(KERN_DEBUG
"END, r_counter: %x\n",r_counter);

spin_unlock(
&write_lock);
/*************************BAR0 kong jian **************************/


pci_unmap_single(adapter
->pci_dev, dma_read_addr, count, PCI_DMA_TODEVICE);
kfree(virt_addr);

printk(KERN_DEBUG
"Here I am: %s:%i\n",__FILE__,__LINE__);

return count;

err_kmalloc:
return -1;
}



/*
static irqreturn_t card_interrupt(int irq, void * dev)
{
u8 status,abc;
status = 0;

printk(KERN_DEBUG "jinru zhonduan!!! Here I am: %s:%i\n",__FILE__,__LINE__);

//status = card_r32(INT_REG);
//pci_read_config_dword(adapter->pci_dev, DCSR_OFFSET, &status);
status = ioread8((adapter -> pci_bar0+DMA_CST_OFFSET));

//if(!(status & INT_ASSERT))
//{
// PDEBUG("irq_none ... \n");
// return IRQ_NONE;
//}

if(status & INT_ASSERT_W) //DMA Write Complete
{
//card_w32(status, INT_REG);
//clear ISR

//pci_read_config_dword(adapter->pci_dev, DCSR_OFFSET, status);
abc = status | INT_ASSERT_W;

iowrite8(abc,(adapter -> pci_bar0+DMA_CST_OFFSET));
//writel(status,(void __iomem *) (unsigned long) (adapter -> pci_bar0 + DMA_CST_OFFSET));
//i = 1;
//wake_up_interruptible(adapter->dma_write_wait);
flag = 1;
wake_up_interruptible(&dma_write_wait);

return IRQ_HANDLED;
}

if(status & INT_ASSERT_R) //DMA Read Complete
{
//card_w32(status, INT_REG);
//clear ISR
//pci_read_config_dword(adapter->pci_dev, DCSR_OFFSET, status);
status = status & ~INT_ASSERT_R;
writel(status,(void __iomem *) (unsigned long) (adapter -> pci_bar0 + DMA_CST_OFFSET));
//wake_up_interruptible(adapter->dma_read_wait);
return IRQ_HANDLED;
}

//PDEBUG("irq handled ... \n");

return IRQ_HANDLED;

}
*/