以下是我根据工作需要编写的基于RTLinux系统的CH365芯片驱动程序,经测试可以读写端口和响应中断,但是去掉了和工作实质内容相关的部分。Linux的芯片驱动程序应该与此基本相同,只是有一些函数不一样罢了。分享给看到的人,希望对大家能有所帮助。
另外,我也希望能够获得CH365的Windows驱动程序源代码。主要是确实有这方面的兴趣和基础,而且哪一天真的需要也说不定。不知版主能否开恩许可下载呢?^_^
我开始写驱动程序的时间还非常短,而且主要工作也不是做这个的。程序有难以入法眼的地方,请不吝指正!谢谢。
#include #include #include #include #include
//设备相关 #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");