📄 linuxdsp.c
字号:
#ifndef __KERNEL__# define __KERNEL__#endif#ifndef MODULE# define MODULE#endif#include <asm/io.h>#include <asm/uaccess.h>#include <linux/init.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/pci.h>//#include <linux/malloc.h>#include <linux/ioport.h>#include <linux/timer.h>#include <linux/proc_fs.h>#include <linux/interrupt.h>#include <linux/tqueue.h>#include "sysdep.h"#define DSPIRQ#define LINUX_VERSION 0x2020C#define LINUX_MAGIC 'Q'#define PCI_VENDOR 0x104c#define PCI_DEVICE 0xa106#define DSP6205_MAJOR 80#define MY_MAJOR 0#define IO_SPACE_SIZE 0x10#define MEM_SPACE_SIZE 0x400000#define MAX_DMA_LENGTH 0x8000#define DMA_BUF_ORDER 1#define DMA_BUF_SIZE (PAGE_SIZE<<DMA_BUF_ORDER)#define SEND_DMA_SIZE 0x2000#define READ_DMA_SIZE 0x2000#define DSP_MEM_OFFSET 0x0#define DSP_OPERA_OFFST 0x8000#define DSP_DATA_OFFST 0x8004#define DSPMA_REG_OFFST 0x240010#define PCIMA_REG_OFFST 0x240014#define DMA_REG_OFFSET 0x240018#define DSP_ADDRESS 0x80008004#define DSP_IRQ_MASK 0xfffffffb#define DSP_RESET_FLAG 0x1#define SUCESS_FLAG 0xa5a5a5a5#define DSP_FLAG 0x5a5a5a5a#define HOST_FLAG 0xaaaa5555#define HSR 0x0#define HDCR 0x4#define DSPP 0x8#define FLASH_ADR_SLECT 0x5
#define DMA_ADR_SLECT 0x6#define DSP_ADR_SLECT 0x200#define DMA_READ 0x1#define DMA_WRITE 0x2#define DSP_RESET 0x1struct DBIO{ //dma,irq数据块 char *wbuf; char *rbuf; int off; int count;};
struct RWFLASH{
char buf;
int off;
int flag;
};
//Ioctl指令:start#define LINUX_DSPRESET _IOW(LINUX_MAGIC,1,0)#define LINUX_DMARANDW _IOWR(LINUX_MAGIC,2,sizeof(struct DBIO))#define LINUX_QUERYRAW _IOWR(LINUX_MAGIC,3,sizeof(struct DBIO))#define LINUX_INTQRYRAW _IOWR(LINUX_MAGIC,4,sizeof(struct DBIO))#define LINUX_INTDMARAW _IOWR(LINUX_MAGIC,5,sizeof(struct DBIO))#define LINUX_FLASHRAW _IOWR(LINUX_MAGIC,6,sizeof(struct DBIO))#define LINUX_UNLOCKROM _IOR(LINUX_MAGIC,7,0)#define LINUX_LOCKROM _IOR(LINUX_MAGIC,8,0)//Ioctl指令:endenum pci_chipsets{ DSP6205 = 0,};//static struct pci_device_id Dsp6205_pci_tbl[] __devinitdata ={// {PCI_VENDOR,PCI_DEVICE,PCI_ANY_ID,PCI_ANY_ID,0,0,DSP6205},// {0,}};//MODULE_DEVICE_TABLE(pci, Dsp6205_pci_tbl);struct TDspDev{ int bPresent; //准备好 volatile int bUsed; //使用与否 enum { IDLE,WAITING,TIME_OUT, DSP_DONE,DMA_WAITING, DMA_DONE } status; unsigned int IoMem; //IO寄存器地址 unsigned int PhyMem; //DSP物理地址 unsigned int virtualMem; //DSP虚拟地址 unsigned int Dma_buf; //DMA缓冲区 int Irq; //中断 char *rbuffer; //接收缓冲区 int rsize; //接收数量 int finish; //完成情况 };static struct TDspDev *dev6205;struct pci_dev *dev = NULL;struct timer_list wait_timer;unsigned int IO,PHY;unsigned int MEM;unsigned int Irq;unsigned long Dma_Buf;struct wait_queue *wait;//wait_queue_head_t wait;struct semaphore dsp6205_sem;static void DMA_Transfer(unsigned int count,int bRead);static void Reset(void);static int Dsp6205_open(struct inode *inode,struct file *file);static int Dsp6205_release(struct inode * inode, struct file * filp);static int Dsp6205_read(struct file *filp, char *buf,size_t count, loff_t *ppos);static int Dsp6205_write(struct file *filp, const char *buf,size_t count, loff_t *ppos);static int Dsp6205_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg);static int Dma_readwrite(unsigned long timeout,unsigned long arg);static int Irq_readwrite(unsigned long timeout,unsigned long arg);static int DMA_Send(const char *buf,int offset,int size);
static int DMA_receive(char *buf,int offset,int size);static int receive(char *buf,int offset,int size);
static int send(char *buf,int offset,int size);
static int Flash_readwrite(unsigned long arg);
static int Detect_Dsp6205();static int wait_flags(void);static int wait_flags(void){ unsigned int data; outl(DSP_ADR_SLECT,IO+DSPP); data=readl(MEM+DSP_OPERA_OFFST); while(data!=0x5a5a5a5a){ data=readl(MEM+DSP_OPERA_OFFST); } return 0;}static void Int_handler(int irq,void * dev_id,struct pt_regs * regs){// struct TDspDev *tDev; unsigned int data;// tDev=(struct TDspDev *) dev_id; outl(DSP_ADR_SLECT,IO+DSPP); data=readl(MEM+DSP_OPERA_OFFST); if(!(data&DSP_FLAG)) {// printk("Not DSP's IRQ occured!\n"); return; } writel(HOST_FLAG,MEM+DSP_OPERA_OFFST);// printk("write Flag!\n"); wake_up_interruptible(&wait); //唤醒读进程 // printk("DSP's IRQ received!\n"); return ;}static void Reset(void){ unsigned long flag;// printk("Dsp6205_Reset\n"); flag=inl(IO+DSPP); flag|=DSP_RESET; outl(flag,IO+HDCR);// printk("Dsp6205 Reset Sucess!\n");}static void DMA_Transfer(unsigned int count,int bRead){ unsigned int size; unsigned int data; printk("DMA_Transfer open\n"); outl(DMA_ADR_SLECT,IO+DSPP);
// printk("count = %d\n",count);// writel(DSP_ADDRESS,MEM+DSPMA_REG_OFFST);// printk("MEM+DSP_DATA_OFFST = 0x%x\n",MEM+DSP_DATA_OFFST); // writel(virt_to_bus((void*)Dma_Buf),MEM+PCIMA_REG_OFFST); if(!bRead) size=(count<<16)|DMA_WRITE; else size=(count<<16)|DMA_READ; printk("DMA_Transfer 1\n"); writel(size,MEM+DMA_REG_OFFSET); data = readl(MEM+DMA_REG_OFFSET);// printk("data =0x%x\n",data); while((data&0x3)!=0){ data = readl(MEM+DMA_REG_OFFSET); printk("data =0x%x\n",data); }// printk("DMA_Transfer 2\n"); if(!bRead){ outl(DSP_ADR_SLECT,IO+DSPP); writel(SUCESS_FLAG,MEM+DSP_OPERA_OFFST); printk("Write Dma flag!\n"); } printk("DMA_Transfer finished!\n");}static int DMA_receive(char *buf,int offset,int size){// printk("Dsp6205 DMA_receive Open\n"); DMA_Transfer(size,1);// printk("Dsp6205 DMA_receive 1\n"); memcpy(buf,(void*)Dma_Buf,size);// printk("Dsp6205 DMA_receive finished!\n"); return 0;}static int DMA_Send(const char *buf,int offset,int size){// printk("Dsp6205 DMA_Send open!\n"); memcpy((void*)Dma_Buf,buf,size);// printk("Dsp6205 DMA_Send 1\n"); DMA_Transfer(size,0);// printk("Dsp6205 DMA_Send finished!\n"); return 0;}static int send(char *buf,int offset,int size){// printk("Dsp6205_send Happen0!\n"); outl(DSP_ADR_SLECT,IO+DSPP);// printk("Dsp6205_send Happen1!\n"); memcpy((void*)MEM+DSP_DATA_OFFST,(void*)buf,size);// wmb();// printk("Dsp6205_send Happen2!\n"); writel(SUCESS_FLAG,MEM+DSP_OPERA_OFFST);// printk("Dsp6205_send finished!\n"); return 0;}static int receive(char *buf,int offset,int size){// printk("Dsp6205_receive Happen0!\n"); outl(DSP_ADR_SLECT,IO+DSPP); memcpy(buf,(char *)MEM+DSP_DATA_OFFST,size);// printk("Dsp6205_receive Sucess!\n"); return size;}static int Dma_readwrite(unsigned long timeout,unsigned long arg){ struct DBIO buf,*pbuf=&buf; unsigned long time; down(&dsp6205_sem); // printk("DSP6205 DMA READ WRITE!\n"); copy_from_user(pbuf,(char*)arg,sizeof(struct DBIO)); DMA_Send(pbuf->wbuf,0,pbuf->count); time=interruptible_sleep_on_timeout(&wait,timeout); if(!time){ up(&dsp6205_sem); return 1; }// printk("DSP6205 interrupt Pass! \n"); DMA_receive(pbuf->rbuf,0,pbuf->count);// printk("DSP6205 DMA Read finished!\n"); copy_to_user((char*)arg,pbuf,sizeof(struct DBIO)); // printk("DSP6205 DMA Read Sucess!\n"); up(&dsp6205_sem); return 0;}static int Irq_readwrite(unsigned long timeout,unsigned long arg){ struct DBIO buf,*pbuf=&buf; unsigned long time; down(&dsp6205_sem); // printk("DSP6205 Query READ WRITE!\n"); copy_from_user(pbuf,(char*)arg,sizeof(struct DBIO));// printk("DSP6205 Query WRITE Sucess!\n"); send(pbuf->wbuf,0,pbuf->count);// printk("DSP6205 Query Write 1! \n"); time=interruptible_sleep_on_timeout(&wait,timeout); if(!time){ up(&dsp6205_sem); return 1; }// printk("DSP6205 interrupt Pass! \n"); receive(pbuf->rbuf,0,pbuf->count);// printk("DSP6205 Query Read finished!\n"); copy_to_user((char*)arg,pbuf,sizeof(struct DBIO));// printk("DSP6205 Query Read Sucess!\n"); up(&dsp6205_sem); return 0;}static int Flash_readwrite(unsigned long arg){ struct RWFLASH buf,*pbuf=&buf; int flag; int offset; copy_from_user(pbuf,(char*)arg,sizeof(struct RWFLASH));// printk("DSP6205 Flash Read Write start!\n"); flag = pbuf->flag; offset = pbuf->off; if(offset>0x20000) return 1; outl(FLASH_ADR_SLECT,IO+DSPP);// printk("buf is %d!\n",pbuf->buf); if(flag) //write
writeb(pbuf->buf,MEM+pbuf->off); else pbuf->buf = readb(MEM+pbuf->off);// printk("data is %d!\n",pbuf->buf); copy_to_user((char*)arg,pbuf,sizeof(struct RWFLASH));// printk("DSP6205 Flash Read Write Sucess!\n"); return 0;}static struct file_operations Dsp6205_fops = {// owner: THIS_MODULE, read: Dsp6205_read, write: Dsp6205_write, ioctl: Dsp6205_ioctl, open: Dsp6205_open, release: Dsp6205_release,};static int Dsp6205_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg){ struct DBIO buf,*pbuf=&buf;
unsigned long data; switch(cmd){ case LINUX_DSPRESET:// printk("DSP6205 Reset!\n");// if (! capable (CAP_SYS_ADMIN))// return -EPERM; Reset(); break; case LINUX_DMARANDW:// if (! capable (CAP_SYS_ADMIN)) // return -EPERM;// printk("DSP6205 DMA READ WRITE!\n"); copy_from_user(pbuf,(char*)arg,sizeof(struct DBIO)); DMA_Send(pbuf->wbuf,0,pbuf->count); wait_flags(); DMA_receive(pbuf->rbuf,0,pbuf->count); copy_to_user((char*)arg,pbuf,sizeof(struct DBIO)); break; case LINUX_QUERYRAW:// if (! capable (CAP_SYS_ADMIN))// return -EPERM;// printk("DSP6205 Query READ WRITE!\n"); copy_from_user(pbuf,(char*)arg,sizeof(struct DBIO));// printk("DSP6205 Query WRITE Sucess!\n"); send(pbuf->wbuf,0,pbuf->count);// printk("DSP6205 Query READ 1! \n"); wait_flags(); receive(pbuf->rbuf,0,pbuf->count);// printk("DSP6205 Read finished!\n"); copy_to_user((char*)arg,pbuf,sizeof(struct DBIO));// printk("DSP6205 Query READ Sucess!\n"); break; case LINUX_INTQRYRAW:// if (! capable (CAP_SYS_ADMIN))// return -EPERM; if(Irq_readwrite(2000,arg)) return -ETIMEDOUT; break; case LINUX_INTDMARAW:// if (! capable (CAP_SYS_ADMIN))// return -EPERM; if(Dma_readwrite(2000,arg)) return -ETIMEDOUT; break; case LINUX_FLASHRAW:// printk("DSP6205 Flash READ WRITE!\n"); if(Flash_readwrite(arg)) return -EOVERFLOW; break; case LINUX_UNLOCKROM: outl(FLASH_ADR_SLECT,IO+DSPP); printk("DSP6205 UNLOCK ROM!\n"); data = readl(MEM+0x608c); data = readl(MEM+0x6080); data = readl(MEM+0x6088); data = readl(MEM+0x1060); data = readl(MEM+0x106c); data = readl(MEM+0x1064); data = readl(MEM+0x1068); printk("DSP6205 UNLOCK ROM! SUCESS!\n"); break; case LINUX_LOCKROM: outl(FLASH_ADR_SLECT,IO+DSPP); printk("DSP6205 LOCK ROM!\n"); data = readl(MEM+0x608c); data = readl(MEM+0x6080); data = readl(MEM+0x6088); data = readl(MEM+0x1060); data = readl(MEM+0x106c); data = readl(MEM+0x1064); data = readl(MEM+0x1028); printk("DSP6205 LOCK ROM! SUCESS!\n"); break; default: break; } return 0;}static int Dsp6205_open(struct inode *inode, struct file *file){// unsigned int data;// printk("Dsp6205_open0\n"); MOD_INC_USE_COUNT;// printk("Dsp6205_open\n"); return 0;}static int Detect_Dsp6205(){ unsigned int data; pci_read_config_dword(dev,0x10,&data); data&=PCI_BASE_ADDRESS_MEM_MASK; PHY=data;// printk("PHY %x!\n",PHY); pci_read_config_dword(dev,0x18,&data); data&=PCI_BASE_ADDRESS_IO_MASK; IO=data;// printk("IO %x!\n",IO); pci_read_config_dword(dev,0x3c,&data); data&=0xff; Irq=data;// printk("Irq %x!\n",Irq); if(check_region(IO,IO_SPACE_SIZE)<0) {// printk("Driver has been loaded,can't request IO!\n"); return 1; }// printk("check io region sucess!\n"); request_region(IO,IO_SPACE_SIZE,"DSPDev");// printk("request io region sucess!\n"); if(!(MEM=(unsigned long) ioremap_nocache(PHY,MEM_SPACE_SIZE))){// printk("Can't map the physical memory!\n"); goto err; }// printk("ioremap mem sucess!\n");// printk("MEM sucess 0x%x\n",MEM); if(request_irq(Irq,Int_handler,SA_SHIRQ,"DSPDev",&dev6205)<0){// printk("Can't request IRQ!\n"); goto err1; }// printk("request irq sucess!\n"); data=inl(IO+HSR)&0xfffffffbL; outl(data,IO+HSR); if(register_chrdev(DSP6205_MAJOR,"DSPDev",&Dsp6205_fops)<0) {// printk("Can't register DSP device driver!\n"); return -ENODEV; } Dma_Buf=__get_free_pages(GFP_DMA,DMA_BUF_ORDER); printk("Dma buf sucess!\n"); if(!Dma_Buf) { printk("Can't alloc DMA buffer!\n"); goto err2; } printk("Dma buf sucess!\n"); outl(DMA_ADR_SLECT,IO+DSPP);// printk("write sucess0!\n"); writel(DSP_ADDRESS,MEM+DSPMA_REG_OFFST);// printk("MEM+DSP_DATA_OFFST = 0x%x\n",MEM+DSP_DATA_OFFST);// data=readl(MEM+DSPMA_REG_OFFST);// printk("write sucess1! data=0x%x\n",data); writel(virt_to_bus((void*)Dma_Buf),MEM+PCIMA_REG_OFFST);// printk("Dma_Buf = 0x%x\n",Dma_Buf); init_waitqueue(&wait); // init_waitqueue_head (&wait);// printk("init_waitqueue_head sucess!\n"); sema_init(&dsp6205_sem, 1);// printk("sema_init sucess!\n"); return 0; err2: free_irq(Irq,&dev6205);// printk("fail 0!\n"); err1: iounmap((void*)MEM);// printk("fail 1!\n"); err:// release_mem_region(PHY,MEM_SPACE_SIZE); release_region(IO,IO_SPACE_SIZE);// printk("fail 2!\n"); return 1;}static int Dsp6205_release(struct inode * inode, struct file * filp){// printk("Dsp6205_release0\n"); MOD_DEC_USE_COUNT;// printk("Dsp6205_release\n"); return 0;}static int Dsp6205_read(struct file *filp, char *buf,size_t count, loff_t *ppos){// printk("Dsp6205_read0\ncount = %d\n",count); outl(DSP_ADR_SLECT,IO+DSPP); copy_to_user((char*)buf,(char*)MEM+DSP_DATA_OFFST,count);//问题// memcpy((char*)buf,(char*)MEM+DSP_DATA_OFFST,count);// printk("Dsp6205_read1\ncount = %d\n",count); return count;}static int Dsp6205_write(struct file *filp, const char *buf,size_t count, loff_t *ppos){ int len;// printk("Dsp6205_write0\n"); outl(DSP_ADR_SLECT,IO+DSPP); len = strlen(buf);// printk("len = %d\n",len); copy_from_user((void*)MEM+DSP_DATA_OFFST,(void*)buf,len); writel(SUCESS_FLAG,MEM+DSP_OPERA_OFFST);// printk("Dsp6205_write1\n"); return count;}int init_module(void)//static int __init Dsp6205_init_module(void){ memset(&dev6205,0,sizeof(struct TDspDev)); if (!pci_present()){ printk("No PCI bios present\n"); return -ENODEV; } dev=pci_find_device(PCI_VENDOR,PCI_DEVICE,dev); if (!dev) { printk("No find PCI device\n"); return -ENODEV; } Detect_Dsp6205(); printk("Sucess! DSP6205\n"); return 0;}void cleanup_module(void) //static void __exit Dsp6205_cleanup_module(void){// printk("Dsp6205 cleanup module\n"); unregister_chrdev(DSP6205_MAJOR,"DSPDev"); free_irq(Irq,&dev6205);// release_mem_region(PHY,MEM_SPACE_SIZE); release_region(IO,IO_SPACE_SIZE); iounmap((void *) MEM); free_pages(Dma_Buf,DMA_BUF_ORDER); printk("Goodbye DSP6205\n");}//module_init(Dsp6205_init_module);//module_exit(Dsp6205_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -