📄 ca91c042.c
字号:
//------------------------------------------------------------------------------ //title: Tundra Universe PCI-VME Kernel Driver//version: Linux 1.1//date: March 1999 //designer: Michael Wyrick //programmer: Michael Wyrick //platform: Linux 2.4.x//language: GCC 2.95 and 3.0//module: ca91c042//------------------------------------------------------------------------------ // Purpose: Provide a Kernel Driver to Linux for the Universe I and II // Universe model number ca91c042// Docs: // This driver supports both the Universe and Universe II chips //------------------------------------------------------------------------------ // RCS:// $Id: ca91c042.c,v 1.5 2001/10/27 03:50:07 jhuggins Exp $// $Log: ca91c042.c,v $// Revision 1.5 2001/10/27 03:50:07 jhuggins// These changes add support for the extra images offered by the Universe II.// CVS : ----------------------------------------------------------------------//// Revision 1.6 2001/10/16 15:16:53 wyrick// Minor Cleanup of Comments//////-----------------------------------------------------------------------------#define MODULEstatic char Version[] = "1.2 2001Oct17";#include <linux/config.h>#include <linux/version.h>#ifdef CONFIG_MODVERSIONS #define MODVERSIONS #include <linux/modversions.h>#endif#include <linux/module.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/proc_fs.h>#include <linux/pci.h>#include <linux/poll.h>#include <asm/io.h>#include <asm/uaccess.h>#include "ca91c042.h"//----------------------------------------------------------------------------// Prototypes//----------------------------------------------------------------------------static int uni_open(struct inode *, struct file *);static int uni_release(struct inode *, struct file *);static ssize_t uni_read(struct file *,char *, size_t, loff_t *);static ssize_t uni_write(struct file *,const char *, size_t, loff_t *);static unsigned int uni_poll(struct file *, poll_table *);static int uni_ioctl(struct inode *, struct file *, unsigned int, unsigned long);static long long uni_llseek(struct file *,loff_t,int);//static int uni_mmap(struct inode *inode,struct file *file,struct vm_area_struct *vma);//static int uni_select(struct inode *inode,struct file *file,int mode, select_table *table);static int uni_procinfo(char *, char **, off_t, int, int *,void *);//----------------------------------------------------------------------------// Types//----------------------------------------------------------------------------static struct proc_dir_entry *uni_procdir;static struct file_operations uni_fops = { llseek: uni_llseek, read: uni_read, write: uni_write, poll: uni_poll, // uni_poll ioctl: uni_ioctl, open: uni_open, release: uni_release };static int aCTL[] = {LSI0_CTL, LSI1_CTL, LSI2_CTL, LSI3_CTL, LSI4_CTL, LSI5_CTL, LSI6_CTL, LSI7_CTL}; static int aBS[] = {LSI0_BS, LSI1_BS, LSI2_BS, LSI3_BS, LSI4_BS, LSI5_BS, LSI6_BS, LSI7_BS}; static int aBD[] = {LSI0_BD, LSI1_BD, LSI2_BD, LSI3_BD, LSI4_BD, LSI5_BD, LSI6_BD, LSI7_BD}; static int aTO[] = {LSI0_TO, LSI1_TO, LSI2_TO, LSI3_TO, LSI4_TO, LSI5_TO, LSI6_TO, LSI7_TO}; //----------------------------------------------------------------------------// Vars and Defines//----------------------------------------------------------------------------#define UNI_MAJOR 221#define MAX_MINOR 8#define CONTROL_MINOR 8#define MODE_UNDEFINED 0#define MODE_PROGRAMMED 1#define MODE_DMA 2#define DMATYPE_SINGLE 1#define DMATYPE_LLIST 2static int OkToWrite[MAX_MINOR + 1]; // Can I write to the Hardwarestatic int opened[MAX_MINOR + 1];static int mode[MAX_MINOR + 1]; // DMA or Programmed I/Ostatic unsigned long DMA[MAX_MINOR + 1]; // DMA Control Regstatic int status;static int DMAType = 0;static int irq = 0;static char *baseaddr = 0;static char *image_ba[MAX_MINOR+1]; // Base PCI Addressstatic unsigned int image_ptr[MAX_MINOR+1];static unsigned int image_va[MAX_MINOR+1];// Hold the VME Irq Handlersstatic TirqHandler vmeirqs[7] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL};static short vmeirqbit[7] = {IRQ_VIRQ1, IRQ_VIRQ2, IRQ_VIRQ3, IRQ_VIRQ4, IRQ_VIRQ5, IRQ_VIRQ6, IRQ_VIRQ7}; static int vmevec[7] = {V1_STATID, V2_STATID, V3_STATID, V4_STATID, V5_STATID, V6_STATID, V7_STATID};// Status Varsstatic unsigned int reads = 0;static unsigned int writes = 0;static unsigned int ioctls = 0;static TDMAcallback DMACallBackFunc = NULL;static void *debugptr = NULL;// Timersstruct timer_list DMA_timer; // This is a timer for returning status//----------------------------------------------------------------------------// uni_procinfo()//----------------------------------------------------------------------------static int uni_procinfo(char *buf, char **start, off_t fpos, int lenght, int *eof, void *data){ char *p; unsigned int temp1,temp2,x; p = buf; p += sprintf(p,"Universe driver %s\n",Version); p += sprintf(p," baseaddr = %08X\n",(int)baseaddr); p += sprintf(p," Stats reads = %i writes = %i ioctls = %i\n", reads,writes,ioctls); for (x=0;x<8;x+=2) { temp1 = readl(baseaddr+aCTL[x]); temp2 = readl(baseaddr+aCTL[x+1]); p += sprintf(p," LSI%i_CTL = %08X LSI%i_CTL = %08X\n",x,temp1,x+1,temp2); temp1 = readl(baseaddr+aBS[x]); temp2 = readl(baseaddr+aBS[x+1]); p += sprintf(p," LSI%i_BS = %08X LSI%i_BS = %08X\n",x,temp1,x+1,temp2); temp1 = readl(baseaddr+aBD[x]); temp2 = readl(baseaddr+aBD[x+1]); p += sprintf(p," LSI%i_BD = %08X LSI%i_BD = %08X\n",x,temp1,x+1,temp2); temp1 = readl(baseaddr+aTO[x]); temp2 = readl(baseaddr+aTO[x+1]); p += sprintf(p," LSI%i_TO = %08X LSI%i_TO = %08X\n",x,temp1,x+1,temp2); } for (x=0;x<8;x+=2) p += sprintf(p," image_va%i = %08X image_va%i = %08X\n", x,image_va[x],x+1,image_va[x+1]); p += sprintf(p,"\nDriver Program Status:\n"); for (x=0;x<8;x+=2) p += sprintf(p," DMACTL %i = %08lX DMACTL %i = %08lX\n", x,DMA[x],x+1,DMA[x+1]); for (x=0;x<8;x+=2) p += sprintf(p," OkToWrite %i = %1X OkToWrite %i = %1X\n", x,OkToWrite[x],x+1,OkToWrite[x+1]); for (x=0;x<8;x+=2) p += sprintf(p," Mode %i = %1X Mode %i = %1X\n", x,mode[x],x+1,mode[x+1]); p += sprintf(p,"\n"); temp1 = 0; p += sprintf(p, "VMEIrqs Assigned: "); for (x=0;x<7;x++) { if (vmeirqs[x] != NULL) { p += sprintf(p, "%i ",x+1); temp1++; } } if (temp1 == 0) p += sprintf(p, "none\n"); else p += sprintf(p,"\n"); *eof = 1; return p - buf;}//----------------------------------------------------------------------------// register_proc()//----------------------------------------------------------------------------static void register_proc(){ uni_procdir = create_proc_entry("ca91c042", S_IFREG | S_IRUGO, 0); uni_procdir->read_proc = uni_procinfo;}//----------------------------------------------------------------------------// unregister_proc()//----------------------------------------------------------------------------static void unregister_proc(){ remove_proc_entry("ca91c042",0);}//----------------------------------------------------------------------------//// uni_poll()////----------------------------------------------------------------------------static unsigned int uni_poll(struct file* file, poll_table* wait){ return 0;}//----------------------------------------------------------------------------//// uni_open()////----------------------------------------------------------------------------static int uni_open(struct inode *inode,struct file *file){ unsigned int minor = MINOR(inode->i_rdev); if (minor > MAX_MINOR) { return(-ENODEV); } if (minor == CONTROL_MINOR) { opened[minor]++; return(0); } if (!opened[minor]) { opened[minor] = 1; return(0); } else return(-EBUSY);}//----------------------------------------------------------------------------//// uni_release()////----------------------------------------------------------------------------static int uni_release(struct inode *inode,struct file *file){ unsigned int minor = MINOR(inode->i_rdev); opened[minor]--; return 0;}//----------------------------------------------------------------------------//// uni_lseek()////----------------------------------------------------------------------------static long long uni_llseek(struct file *file,loff_t offset,int whence){ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); unsigned int toffset,base,paddr; if (whence == SEEK_SET) { if (minor == CONTROL_MINOR) { image_ptr[minor] = offset; } else { toffset = readl(baseaddr+aTO[minor]); base = readl(baseaddr+aBS[minor]); paddr = offset-toffset; image_ptr[minor] = (int)(image_ba[minor]+(paddr-base)); } return 0; } else if (whence == SEEK_CUR) { image_ptr[minor] += offset; return 0; } else return -1; }//----------------------------------------------------------------------------//// uni_read()////----------------------------------------------------------------------------static ssize_t uni_read(struct file *file, char *buf, size_t count, loff_t *ppos){ int x = 0; unsigned int v,numt,remain,tmp; char *temp = buf; unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); int p; unsigned char vc; unsigned short vs; unsigned int vl; char *DMA_Buffer; unsigned int DMA_Buffer_Size = 0, order = 0, a_size = 0, dma_align = 0, timeout = 0; int val = 0, pci = 0, vme = 0, okcount = 0; if (minor == CONTROL_MINOR) { p = (int)image_ptr[minor]; v = readl(baseaddr+p); __copy_to_user(temp,&v,4); } else { reads++; if (OkToWrite[minor]) { if (mode[minor] == MODE_PROGRAMMED) { numt = count; remain = count; // Calc the number of longs we need numt = count / 4; remain = count % 4; for (x=0;x<numt;x++) { vl = readl(image_ptr[minor]); // Lets Check for a Bus Error tmp = readl(baseaddr+PCI_CSR); if (tmp & 0x08000000) { writel(tmp,baseaddr+PCI_CSR); return(okcount); } else okcount += 4; __copy_to_user(temp,&vl,4); image_ptr[minor]+=4; temp+=4; } // Calc the number of Words we need numt = remain / 2; remain = remain % 2; for (x=0;x<numt;x++) { vs = readw(image_ptr[minor]); // Lets Check for a Bus Error tmp = readl(baseaddr+PCI_CSR); if (tmp & 0x08000000) { writel(tmp,baseaddr+PCI_CSR); return(okcount); } else okcount += 2; __copy_to_user(temp,&vs,2); image_ptr[minor]+=2; temp+=2; } for (x=0;x<remain;x++) { vc = readb(image_ptr[minor]); // Lets Check for a Bus Error tmp = readl(baseaddr+PCI_CSR); if (tmp & 0x08000000) { writel(tmp,baseaddr+PCI_CSR); return(okcount); } else okcount++; __copy_to_user(temp,&vc,1); image_ptr[minor]+=1; temp+=1; } } else if (mode[minor] == MODE_DMA) { // ------------------------------------------------------------------ // // ------------------------------------------------------------------ // Wait for DMA to finish, This needs to be changed val = readl(baseaddr+DGCS); while ((val & 0x00008000) && (timeout++ < 1000000)) val = readl(baseaddr+DGCS); // VME Address vme = image_va[minor] + (image_ptr[minor] - (unsigned int)image_ba[minor]); dma_align = vme % 8; // Setup DMA Buffer to read data into DMA_Buffer_Size = count + ((int)image_ptr % 8) + dma_align; a_size = PAGE_SIZE; while (a_size < DMA_Buffer_Size) { order++; a_size <<= 1; } DMA_Buffer = (char *)__get_dma_pages(GFP_KERNEL,order); // PCI Address pci = virt_to_bus(DMA_Buffer) + dma_align; // Setup DMA regs writel(DMA[minor],baseaddr+DCTL); // Setup Control Reg writel(count,baseaddr+DTBC); // Count writel(pci,baseaddr+DLA); // PCI Address writel(vme,baseaddr+DVA); // VME Address // Start DMA writel(0x80006F00,baseaddr+DGCS); // GO // Wait for DMA to finish, This needs to be changed val = readl(baseaddr+DGCS); while ((val & 0x00008000) && (timeout++ < 100000)) val = readl(baseaddr+DGCS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -