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

📄 pci-linux.c

📁 linux环境下,PCI接口通用驱动程序原代码.
💻 C
字号:
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/io.h>

//设备相关
#define MY_VENDOR_ID 0x4348
#define MY_DEVICE_ID 0x5049
#define MY_PCI_NAME "PCI-365"

//端口读写变量
static int io;
static long range;

//中断申请
static int irq;
unsigned long oldaffinity;
unsigned long affinity = 1;

//中断测试用计数
long tcount = 0;

/* 设备中断服务
*/
unsigned int mypci_interrupt(unsigned int irq, struct pt_regs *regs)
{
 unsigned int mIntCtl, u16reg;

 mIntCtl = rtl_inb_p (io + 0xf8);
 if (mIntCtl & 0x04)
 {
  rtl_outb_p (0, io + 0xf1);

  // TO DO
  tcount++;

  rtl_outb_p (mIntCtl & ~0x04, io + 0xf8);

  if (irq >= 8)
  {
   rtl_outb_p (0x20, 0xa0);
   if (rtl_inb_p(0xa0) == 0) rtl_outb_p (0x20, 0x20);
  }
  else rtl_outb_p (0x20, 0x20);
 }

 rtl_hard_enable_irq (irq);
 return 0 ;
}

/* 探测PCI设备 
*/
static int __init mypci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
{
 int retval, intport, intmask;

 //启动设备
 if ( pci_enable_device (dev) ) 
 {
  rtl_printf (KERN_ERR "IO Error.\n");
  return -EIO;
 }
 
 //设定端口地址及其范
 irq = dev->irq;
 io = pci_resource_start(dev, 0);
 range = pci_resource_end(dev, 0) - io;
 rtl_printf ("PCI Driver at %X, and Interrupt %d.\n", io, irq);

 //申请IO端口
 if ( check_region(io, range) ) 
 {
  rtl_printf ("I/O %X is not free.\n", io);
  return -EBUSY;
 }
 request_region (io, range, MY_PCI_NAME);

 //申请中断IRQ并设定
 retval = rtl_request_irq (irq, mypci_interrupt);
 if (retval)
 {
  rtl_printf ("Can't get IRQ %d.\n", irq);
  return -EIO;
 }
 
 rtl_irq_set_affinity (irq, &affinity, &oldaffinity);
 rtl_hard_enable_irq (irq);
 
 //使能中断
 intport = irq < 8 ? 0x21 : 0xa1;  
 intmask = rtl_inb_p (intport); 

  rtl_outb_p (intmask & ~( 0x01 << (irq & 0x07) ), intport);

 return 0;
}

/* 移除PCI
*/
static void __devexit mypci_remove(struct pci_dev *dev)
{
 rtl_irq_set_affinity (irq, &oldaffinity, NULL);
 rtl_free_irq (irq);
 release_region (io, range);
 
 return;
}

/* 指明驱动程序适用的PCI设备ID 
*/
static struct pci_device_id mypci_table[] __initdata = 
{
 {
  MY_VENDOR_ID,  //厂商ID
  MY_DEVICE_ID,  //设备ID
  PCI_ANY_ID,   //子厂商ID
  PCI_ANY_ID,   //子设备ID
 },
 {0, },
};
MODULE_DEVICE_TABLE(pci, mypci_table);

/* 设备模块信息 
*/
static struct pci_driver mypci_driver_ops = 
{
 name: MY_PCI_NAME,   //设备模块名称
 id_table: mypci_table, //驱动设备表
 probe: mypci_probe,   //查找并初始化设备
 remove: mypci_remove  //卸载设备模块
};

static int __init mypci_init(void) 
{
 //检查系统是否支持PCI总线
 if ( !pci_present() )
 {
  rtl_printf ("The system DONOT support PCI!\n");
  return -ENODEV;
 }

 //注册硬件驱动程序
 if ( !pci_register_driver(&mypci_driver_ops) ) 
 {
  rtl_printf ("Can't register driver!\n");
  return -ENODEV;
 }

 rtl_printf ("The PCI driver is loaded successfully.\n"); 

 //Ch365 BitAction & LED
 //如果要单独测试CH365中断的话,可以把BitAction置1
 rtl_outb_p (0xfa, io + 0xf8);

 rtl_hard_enable_irq (irq);

 //延时一会儿,观察效果
 mdelay (1000);

 rtl_printf ("TCount: %ld\n", tcount);
 return 0;
}

static void __exit mypci_exit(void)
{
 pci_unregister_driver(&mypci_driver_ops);
}

module_init(mypci_init);
module_exit(mypci_exit);
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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