⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ca91c042.c

📁 linux下vme总线驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
//-----------------------------------------------------------------------------// Function   : irq_handler// Inputs     : int irq, void *dev_id, struct pt_regs *regs// Outputs    : void// Description: // Remarks    : // History    : //-----------------------------------------------------------------------------static void irq_handler(int irq, void *dev_id, struct pt_regs *regs){  long stat, enable, i, vector;  enable = readl(baseaddr+LINT_EN);  stat = readl(baseaddr+LINT_STAT);  if (stat & 0x0100)    DMA_irq_handler();  if (stat & 0x0200)    LERR_irq_handler();  if (stat & 0x0400)    VERR_irq_handler();  for (i=0;i<7;i++) {    vector = readl(baseaddr+vmevec[i]);    if (stat & vmeirqbit[i] & enable) {      if (vmeirqs[i] != NULL) {        vmeirqs[i](i+1, vector, dev_id, regs);      }    }  }  writel(stat, baseaddr+LINT_STAT);                // Clear all pending ints}//-----------------------------------------------------------------------------// Function   : cleanup_module// Inputs     : void// Outputs    : void// Description: // Remarks    : // History    : //-----------------------------------------------------------------------------void cleanup_module(void){            int x;  int pcivector;  writel(0,baseaddr+LINT_EN);                   // Turn off Ints  pcivector = readl(baseaddr+PCI_MISC1) & 0x000000FF;   free_irq(pcivector,NULL);             // Free Vector  for (x=1;x<MAX_MINOR+1;x++) {    if (image_ba[x])      iounmap(image_ba[x]);  }      iounmap(baseaddr);  unregister_proc();  unregister_chrdev(UNI_MAJOR, "uni");}//----------------------------------------------------------------------------//  init_module()//----------------------------------------------------------------------------int init_module(void){  int x, result;  unsigned int temp, ba;  char vstr[80];  struct pci_dev *uni_pci_dev = NULL;  sprintf(vstr,"Tundra Universe PCI-VME Bridge Driver %s\n",Version);  printk(vstr);  printk("  Copyright 1997-2001, Michael J. Wyrick\n");  if ((uni_pci_dev = pci_find_device(PCI_VENDOR_ID_TUNDRA,                                     PCI_DEVICE_ID_TUNDRA_CA91C042,                                      uni_pci_dev))) {    printk("  Universe device found.");    // Lets turn Latency off    pci_write_config_dword(uni_pci_dev, PCI_MISC0, 0);    // Display PCI Registers      pci_read_config_dword(uni_pci_dev, PCI_CSR, &status);    printk("  Vendor = %04X  Device = %04X  Status = %08X\n",           uni_pci_dev->vendor,uni_pci_dev->device,status);    printk("  Class = %08X\n",uni_pci_dev->class);    pci_read_config_dword(uni_pci_dev, PCI_MISC0, &temp);    printk("  Misc0 = %08X\n",temp);          // Setup Universe Config Space    // This is a 4k wide memory area that need to be mapped into the kernel    // virtual memory space so we can access it.    pci_write_config_dword(uni_pci_dev, PCI_BS, CONFIG_REG_SPACE);    pci_read_config_dword(uni_pci_dev, PCI_BS, &ba);            baseaddr = (char *)ioremap(ba,4096);    if (!baseaddr) {      printk("  vremap failed to map Universe to Kernel Space.\r");      return 1;    }    // Check to see if the Mapping Worked out    temp = readl(baseaddr);    printk("  Read via mapping, PCI_ID = %08X\n",temp);           if (temp != 0x000010E3) {      printk("  Universe Chip Failed to Return PCI_ID in Memory Map.\n");      return 1;    }    // OK, Every this is ok so lets turn off the windows    writel(0x00800000,baseaddr+LSI0_CTL);         writel(0x00800000,baseaddr+LSI1_CTL);         writel(0x00800000,baseaddr+LSI2_CTL);         writel(0x00800000,baseaddr+LSI3_CTL);         // Write to Misc Register    // Set VME Bus Time-out    //   Arbitration Mode    //   DTACK Enable    writel(0x15060000,baseaddr+MISC_CTL);         // Lets turn off interrupts    writel(0x00000000,baseaddr+LINT_EN);   // Disable interrupts in the Universe first    writel(0x0000FFFF,baseaddr+LINT_STAT); // Clear Any Pending Interrupts    pci_read_config_dword(uni_pci_dev, PCI_INTERRUPT_LINE, &irq);    irq &= 0x000000FF;                    // Only a byte in size    result = request_irq(irq, irq_handler, SA_INTERRUPT, "VMEBus (ca91c042)", NULL);    if (result) {      printk("  ca91c042: can't get assigned pci irq vector %02X\n", irq);    } else {      writel(0x0000, baseaddr+LINT_MAP0);    // Map all ints to 0      writel(0x0000, baseaddr+LINT_MAP1);    // Map all ints to 0    }  } else {    printk("  Universe device not found on PCI Bus.\n");    return 1;  }  if (register_chrdev(UNI_MAJOR, "uni", &uni_fops)) {    printk("  Error getting Major Number for Drivers\n");    iounmap(baseaddr);    return(1);  } else {    printk("  Tundra Loaded.\n");   }  register_proc();  for (x=0;x<MAX_MINOR+1;x++) {    image_ba[x]  = 0;               // Not defined    image_ptr[x] = 0;               // Not defined    opened[x]    = 0;               // Closed    OkToWrite[x] = 0;               // Not OK    mode[x]      = MODE_UNDEFINED;  // Undefined  }    // Setup the DMA Timer  init_timer(&DMA_timer);  DMA_timer.function = DMA_status;  // Enable DMA Interrupts  writel(0x0700, baseaddr+LINT_EN);  return 0;}//-----------------------------------------------------------------------------////  Public Interface////-----------------------------------------------------------------------------//-----------------------------------------------------------------------------// Function   : Universe_BaseAddr// Inputs     : void// Outputs    : char*// Description: Returns the Base Address of the Universe// Remarks    : Used for direct access to the Universe for unsupported functions// History    : //-----------------------------------------------------------------------------char* Universe_BaseAddr(void) {  return baseaddr;}//-----------------------------------------------------------------------------// Function   : Universe_IRQ// Inputs     : void// Outputs    : int// Description: Returns the PCI IRQ that the Universe is on// Remarks    : Used mostly for Status and Debugging// History    : //-----------------------------------------------------------------------------int Universe_IRQ(void) {  return irq;}//-----------------------------------------------------------------------------// Function   : enable_vmeirq// Inputs     : int irq// Outputs    : int// Description: Enable a VME IRQ// Remarks    : // History    : //-----------------------------------------------------------------------------void enable_vmeirq(unsigned int irq){  int enable;  enable = readl(baseaddr+LINT_EN);  enable |= vmeirqbit[irq-1];  writel(enable, baseaddr+LINT_EN);}//-----------------------------------------------------------------------------// Function   : disable_vmeirq// Inputs     : unsigned int irq// Outputs    : void// Description: Disable a VME IRQ// Remarks    : // History    : //-----------------------------------------------------------------------------void disable_vmeirq(unsigned int irq){  int enable;  enable = readl(baseaddr+LINT_EN);  enable &= ~vmeirqbit[irq-1];  writel(enable, baseaddr+LINT_EN);}//-----------------------------------------------------------------------------// Function   : request_vmeirq// Inputs     : unsigned int irq, TirqHandler handler// Outputs    : int, 0 if successful// Description: assign a handler to a vme interrupt// Remarks    : uses a simple check to see if the interrupt is free, then//              assigns a handler for the Interrupt// History    : //-----------------------------------------------------------------------------int request_vmeirq(unsigned int irq, TirqHandler handler){  if ((irq >= 1) && (irq <= 7)) {    if (vmeirqs[irq-1] == NULL) {      vmeirqs[irq-1] = handler;      return 0;    }  }  return -1;                        // IRQ is already assigned or invalid}//-----------------------------------------------------------------------------// Function   : free_vmeirq// Inputs     : unsigned int irq// Outputs    : void// Description: release the vmeirq// Remarks    : This does not check that a module is freeing an interrupt it//              owns.  It is up to the programmer to make sure he knows what//              what he is doing// History    : //-----------------------------------------------------------------------------void free_vmeirq(unsigned int irq){  if ((irq >= 1) && (irq <= 7))    vmeirqs[irq-1] = NULL;}//-----------------------------------------------------------------------------// Function   : mapvme// Inputs     : unsigned int pci  - PCI Address of Image Map (See howto)//              unsigned int vme  - VME Address of Image (See howto)//              unsigned int size - Size of Image//              int image         - Image Number to Use (See howto)//              int ctl           - VME Address Space (See howto)// Outputs    : char*// Description: // Remarks    : // History    : //-----------------------------------------------------------------------------char* mapvme(unsigned int pci,unsigned int vme, unsigned int size,              int image, int ctl){  char *ptr;  unsigned int to;  if ((image >=0) && (image <=3)) {    if ((pci >= 0xB0000000) && (pci <= 0xE0000000)) {      to = vme-pci;      // Setup the Mapping in the Universe      writel(pci, baseaddr + aBS[image]);      writel(pci + size, baseaddr + aBD[image]);      writel(to, baseaddr + aTO[image]);      writel(ctl | 0x80000000, baseaddr + aCTL[image]);      // Get the Virtual address of the PCI Address map      ptr = (char *)ioremap(pci,size);      if (ptr == NULL) {        printk("<ca91c042> ioremap failed in mapvme\n");        return NULL;      } else {        return ptr;        // Everything went ok, return the address pointer      }    }  }  return NULL;}//-----------------------------------------------------------------------------// Function   : unmapvme// Inputs     : char *ptr, int image// Outputs    : void// Description: // Remarks    : // History    : //-----------------------------------------------------------------------------void unmapvme(char *ptr, int image){  if ((image >= 0) && (image <=3)) {    // Clear the Mapping in the Universe    writel(0x00000000, baseaddr + aCTL[image]);    writel(0x00000000, baseaddr + aBS[image]);    writel(0x00000000, baseaddr + aBD[image]);    writel(0x00000000, baseaddr + aTO[image]);  }  // Clear Mapping of PCI Memory  iounmap(ptr);}//-----------------------------------------------------------------------------// Function   : VME_DMA// Inputs     : unsigned int pci   - PCI Address of Image Map (See howto)//              unsigned int vme   - VME Address of Image (See howto)//              unsigned int count - Size of Image//              int image          - Image Number to Use (See howto)//              int ctl            - VME Address Space (See howto)// Outputs    : void// Description: // Remarks    : This is Like the CMD Packet Version but will do only one transfer// History    : //-----------------------------------------------------------------------------void VME_DMA(void* pci, void* vme, unsigned int count, int ctl, TDMAcallback cback){#ifdef __DEBUG__  char buf[256];  sprintf(buf,"<<ca91c042>> DMA Request of virtpci=0x%08X vme=0x%08X cnt=%i ctl=0x%08X\n",          pci,vme,count,ctl);  printk(buf);#endif  // Setup the DMA Transfer in the Universe  writel(ctl, baseaddr + DCTL);  writel(count, baseaddr + DTBC);  writel(virt_to_bus(pci), baseaddr + DLA);  writel((int)vme, baseaddr + DVA);  // We need to build a timer to timeout DMA access  DMA_timer.expires  = jiffies + DMATIMEOUT;       add_timer(&DMA_timer);  // Setup CallBack Function  DMACallBackFunc = cback;  // Start the Transfer,  // Interrupt on Stop,Halt,Done,LERR,VERR,Prot Error  DMAType = DMATYPE_SINGLE;  writel(0x80216F6F,baseaddr+DGCS);             // We are now all setup, so lets return to the calling function so it can  // sleep or what ever until the DMA is done}//-----------------------------------------------------------------------------// Function   : VME_DMA_LinkedList// Inputs     : void* CmdPacketList,TDMAcallback cback// Outputs    : int// Description: // Remarks    : CmdPacketList is a Phys Address// History    : //-----------------------------------------------------------------------------void VME_DMA_LinkedList(void* CmdPacketList,TDMAcallback cback){  debugptr = CmdPacketList;  // Setup a DMA Transfer and once the Transfer is complete call cback  writel(0x08316F00,baseaddr+DGCS);  writel(0x00000000,baseaddr+DTBC);  writel((int)CmdPacketList,baseaddr+DCPP);   // Command Packet Pointer  // We need to build a timer to timeout DMA access  DMA_timer.expires  = jiffies + DMATIMEOUT;       add_timer(&DMA_timer);  // Setup CallBack Function  DMACallBackFunc = cback;  // Start the Transfer,  // Interrupt on Stop,Halt,Done,LERR,VERR,Prot Error  DMAType = DMATYPE_LLIST;  writel(0x88216F6F,baseaddr+DGCS);             // We are now all setup, so lets return to the calling function so it can  // sleep or what ever until the DMA is done}//-----------------------------------------------------------------------------// Function   : VME_Bus_Error// Inputs     : // Outputs    : // Description: Returns 1 if a Bus Error is Pending// Remarks    : // History    : 10/30/2000 mjw Started//-------------------------------------------------------------------------mjw-int VME_Bus_Error(void){  int pci_csr;  pci_csr = readl(baseaddr+PCI_CSR);           // Check for Bus Error  writel(pci_csr,baseaddr+PCI_CSR);            // Clear the Error  return((pci_csr & 0x08000000) ? 1 : 0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -