📄 pmc9054.c
字号:
#define DRV_NAME "pmc9054"#define DRV_VERSION "0.2"#define VUINT volatile unsigned int#ifndef __KERNEL__#define __KERNEL__#endif //#ifndef CONFIG_PROC_FS//#define CONFIG_PROC_FS//#endif#define RELOAD 29#define U32 unsigned int#define U16 unsigned short#define S32 int#define S16 short int#define U8 unsigned char#define S8 char#define DMAENABLE (1<<31)#define APDCEN (1<<0)#include <linux/pci.h>#include <linux/module.h>//#include <asm/uaccess.h>#include <linux/interrupt.h>#include <linux/config.h>#include <linux/ioctl.h>#include <linux/poll.h>#include <asm/dma.h>#include <asm/io.h>#include <linux/slab.h>#include "myvalues.h"#include<asm/delay.h>#include <linux/mm.h>#include <asm/page.h>// GLOBAL DEFINITIONSstruct pci_dev *pdev = NULL;char arm[]="Xscale";int irqdma0=9;int irqdma1=10;unsigned long ulPciRegister = 0;unsigned long ulPciRegLen = 0;unsigned long ulFpgaRegister = 0;unsigned long ulFpgaRegLen = 0;unsigned long ulIOMem = 0;unsigned long ulIOMemLen = 0;void *fpgaMem = NULL;void *pciMem = NULL;//extern unsigned long base;unsigned char bufFlag = 0; // 0 for send, 1 for receiveunsigned char sendHappened = 0; // to represent that send interrupt has occuredunsigned char recvHappened = 0; // to represent that receive interrupt has occuredunsigned long ulRecvSize = 0x4000;//16kstatic DECLARE_WAIT_QUEUE_HEAD(pci9054_wqs);static DECLARE_WAIT_QUEUE_HEAD(pci9054_wqr);void *kernBuffer = NULL;unsigned int order = 0;dma_addr_t dmaSendAddr = 0;//unsigned long SendSize = 0x4000; // 16kunsigned long RecvSize = 0x4000;// 16kstatic const struct pci_device_id pci9054_ids[] = { {VENDORID, DEVICEID},{ 0, },};//for debugint *a;short *b;int tt;MODULE_DEVICE_TABLE(pci, pci9054_ids);/****************************************\|* Driver "pci9054.o"`s entries *|\****************************************/voidXscale_do_tasklet(unsigned long unused){ /* if (bufFlag == 0) { sendHappened = 1; wake_up_interruptible(&pci9054_wqs); PDEBUG( "Send Over!\n"); } else if (bufFlag == 1) { recvHappened = 1; wake_up_interruptible(&pci9054_wqr); PDEBUG( "Receive Over!\n"); } else PDEBUG( "error!\n");*/ return;}DECLARE_TASKLET(Xscale_tasklet, Xscale_do_tasklet, 0);void Xscale_Isr(int irqn, void *dev_id, struct pt_regs *regs){ printk(KERN_ALERT "ENTERING DMA CH0 Interrupt\n"); if(PCI_DMACTRL&(1<<3)) printk(KERN_ALERT "ATPDMA CH0 COMPLETE Interrupt\n"); if(PCI_DMACTRL&(1<<4)) printk(KERN_ALERT "ATPDMA CH0 ERROR Interrupt\n"); if(PCI_DMACTRL&(1<<5)) printk(KERN_ALERT "ATPDMA CH1 COMPLETE Interrupt\n"); if(PCI_DMACTRL&(1<<6)) printk(KERN_ALERT "ATPDMA CH1 ERROR Interrupt\n"); if(PCI_ISR&(1<<3)) pci_unmap_single(pdev, a, 1024*4, PCI_DMA_TODEVICE); if(PCI_DMACTRL&(1<<11)) printk(KERN_ALERT "PTADMA CH0 COMPLETE Interrupt\n"); if(PCI_DMACTRL&(1<<12)) printk(KERN_ALERT "PTADMA CH0 ERROR Interrupt\n"); if(PCI_DMACTRL&(1<<13)) printk(KERN_ALERT "PTADMA CH1 COMPLETE Interrupt\n"); if(PCI_DMACTRL&(1<<14)) printk(KERN_ALERT "PTADMA CH1 ERROR Interrupt\n"); if(PCI_ISR&(1<<3)) pci_unmap_single(pdev, a, 1024*4, PCI_DMA_FROMDEVICE); /* u32 intcsr=0; u32 dmactrl=0; u32 pcinten=0; pcinten|=(1<<3); *PCI_INTEN|=pcinten; intcsr = readl((unsigned long)pciMem + 0x0068); if (! intcsr & (1 << 21) ) printk(KERN_ALERT "DMA CH0 Interrupt\n"); if (*PCI_DMACTRL && (1<<5)) { printk(KERN_ALERT "DMA CH1 COMPLETE Interrupt\n"); } else if (*PCI_DMACTRL && (1<<6)) { printk(KERN_ALERT "DMA CH1 ERROR Interrupt\n"); } // request dpc...that's tasklet under linux */ tasklet_schedule(&Xscale_tasklet); }int pci9054_probe(struct pci_dev *dev, const struct pci_device_id *id){ int status = -1; status = pci_enable_device(dev); //pci_set_master(dev); pdev = dev; // save it for later use return status;}voidpci9054_remove(struct pci_dev *dev){ pci_disable_device(dev); return;}/* device module information */static struct pci_driver pci9054_driver = { .name = DRV_NAME, .id_table = pci9054_ids, .probe = pci9054_probe, .remove = pci9054_remove,};int pci9054_open(struct inode *inode, struct file *filp){ // setup the irq interrupt handler // request_irq(pdev->irq, pci9054_Isr, SA_SHIRQ, "da9054", (void *)pci9054_ids); request_irq(irqdma1, Xscale_Isr, SA_SHIRQ, "Xscale", (void *)arm); return 0;}int pci9054_release(struct inode *inode, struct file *filp){ // free_irq(pdev->irq, (void *)pci9054_ids); free_irq(irqdma1, (void *)arm); iounmap((unsigned long *)ulPciRegister); iounmap((unsigned long *)ulFpgaRegister); return 0;} int pci9054_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){ struct FpgaRegister *preg = (struct FpgaRegister *)arg; struct iomem *p1reg =(struct iomem *)arg; //u32 lregvalue; u32 bregvalue; u32 dmactl=0; unsigned long i; switch (cmd) { case RD_IOMEM: PDEBUG("READ"); // memcpy_fromio(p1reg->value,fpgaMem,p1reg->len); for(i=0;i<p1reg->len;i++) *(long *)((int)(p1reg->value)+i)= readl((unsigned long)fpgaMem+p1reg->offset+i); break; case WR_IOMEM: // PDEBUG("WRITE"); // memcpy_toio(fpgaMem,p1reg->value,p1reg->len); for(i=0;i<p1reg->len;i++) writel(*(long *)((int)p1reg->value+i),(unsigned long)fpgaMem+p1reg->offset+i); break; case RD_REG: preg->value=readl((unsigned long)pciMem+preg->offset); break; case WR_EEPROM: EepromWrite(preg->value, preg->offset); break; case RD_EEPROM: preg->value = EepromRead(preg->offset); break; case WR_FPGA_REGISTER: writel(preg->value, (unsigned long)ulFpgaRegister+preg->offset); break; case RD_FPGA_REGISTER: preg->value = readl((unsigned long)ulFpgaRegister + preg->offset); break; case DMA_CH0_RECV_CTRL: printk(KERN_ALERT "6.1 DMA start!1 \n"); // map the kernBuffer into dma address //bufFlag = 1;// for (page = virt_to_page(kernBuffer); page < virt_to_page(kernBuffer + BUF_SIZE); page++)// SetPageReserved(page); a=kmalloc(1024,__GFP_DMA); for(tt=0;tt<20;tt++) { *(a+tt)=tt; printk(KERN_ALERT "before dma a=0x%x \n",*(a+tt)); } printk(KERN_ALERT "phy addr a =0x%x \n",a); printk(KERN_ALERT "pci register addr=0x%x \n",pciMem); printk(KERN_ALERT "fpga mem=0x%x \n",fpgaMem); dmaSendAddr = pci_map_single(pdev, a,1024, PCI_DMA_FROMDEVICE); // dmactl|=APDCEN; // writel(dmactl,PCI_DMACTRL)//dmactl channel 1 enable // printk(KERN_ALERT "before dma a=0x%x \n",*a); printk(KERN_ALERT "dmasendaddr =0x%x \n", dmaSendAddr); printk(KERN_ALERT "a before dma addr =0x%x \n", a); for(tt=0;tt<20;tt++) printk(KERN_ALERT "pci register before dma=0x%x \n",dmactl=readl(ulPciRegister+4*tt)); *PCI_PTADMA0_PCIADDR=(unsigned long )ulPciRegister; * PCI_PTADMA0_AHBADDR=dmaSendAddr; printk(KERN_ALERT " *PCI_PTADMA0_AHBADDR=0x%x \n", *PCI_PTADMA0_AHBADDR); //Set pointer to the right array address before the first transfer //writel((unsigned long)ulFpgaRegister,(unsigned long)PCI_ATPDMA0_AHBADDR); // CH1 PCI address // CH0 local address offset //*PCI_PTADMA0_PCIADDR=(unsigned long)ulPciRegister; printk(KERN_ALERT "PCI_PTADMA0_PCIADDR=0x%x \n",*PCI_PTADMA0_PCIADDR); // *PCI_PTADMA0_PCIADDR=(unsigned long)ulFpgaRegister; // Enable CH0 *PCI_PTADMA0_LENADDR=5; printk(KERN_ALERT "ATPDMA0LEN value after size =0x%x \n", *PCI_PTADMA0_LENADDR); // bregvalue |= 1 << 27; //writel(bregvalue,(unsigned long)PCI_ATPDMA0_LENADDR); //data swap //*PCI_ATPDMA0_LENADDR|=bregvalue; printk(KERN_ALERT "*PCI_PTADMA0_LENADDR before dma =0x%x \n",*PCI_PTADMA0_LENADDR); *PCI_PTADMA0_LENADDR|= (1<<31);// Start DMA CH1 udelay(100); printk(KERN_ALERT "DMA END \n *PCI_PTADMA0_LENADDR =0x%x \n",*PCI_PTADMA0_LENADDR); pci_unmap_single(pdev, a,1024 , PCI_DMA_FROMDEVICE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -