📄 pci-linux.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 + -