以下是我根據(jù)工作需要編寫的基于RTLinux系統(tǒng)的CH365芯片驅(qū)動(dòng)程序,經(jīng)測(cè)試可以讀寫端口和響應(yīng)中斷,但是去掉了和工作實(shí)質(zhì)內(nèi)容相關(guān)的部分。Linux的芯片驅(qū)動(dòng)程序應(yīng)該與此基本相同,只是有一些函數(shù)不一樣罷了。分享給看到的人,希望對(duì)大家能有所幫助。

另外,我也希望能夠獲得CH365的Windows驅(qū)動(dòng)程序源代碼。主要是確實(shí)有這方面的興趣和基礎(chǔ),而且哪一天真的需要也說不定。不知版主能否開恩許可下載呢?^_^

我開始寫驅(qū)動(dòng)程序的時(shí)間還非常短,而且主要工作也不是做這個(gè)的。程序有難以入法眼的地方,請(qǐng)不吝指正!謝謝。

#include #include #include #include #include

//設(shè)備相關(guān) #define MY_VENDOR_ID 0x4348 #define MY_DEVICE_ID 0x5049 #define MY_PCI_NAME "PCI-365"

//端口讀寫變量 static int io; static long range;

//中斷申請(qǐng) static int irq; unsigned long oldaffinity; unsigned long affinity = 1;

//中斷測(cè)試用計(jì)數(shù) long tcount = 0;

/* 設(shè)備中斷服務(wù) */ 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 ; }

/* 探測(cè)PCI設(shè)備 */ static int __init mypci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { int retval, intport, intmask;

//啟動(dòng)設(shè)備 if ( pci_enable_device (dev) ) { rtl_printf (KERN_ERR "IO Error.\n"); return -EIO; } //設(shè)定端口地址及其范 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);

//申請(qǐng)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);

//申請(qǐng)中斷IRQ并設(shè)定 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; }

/* 指明驅(qū)動(dòng)程序適用的PCI設(shè)備ID */ static struct pci_device_id mypci_table[] __initdata = { { MY_VENDOR_ID, //廠商ID MY_DEVICE_ID, //設(shè)備ID PCI_ANY_ID, //子廠商ID PCI_ANY_ID, //子設(shè)備ID }, {0, }, }; MODULE_DEVICE_TABLE(pci, mypci_table);

/* 設(shè)備模塊信息 */ static struct pci_driver mypci_driver_ops = { name: MY_PCI_NAME, //設(shè)備模塊名稱 id_table: mypci_table, //驅(qū)動(dòng)設(shè)備表 probe: mypci_probe, //查找并初始化設(shè)備 remove: mypci_remove //卸載設(shè)備模塊 };

static int __init mypci_init(void) { //檢查系統(tǒng)是否支持PCI總線 if ( !pci_present() ) { rtl_printf ("The system DONOT support PCI!\n"); return -ENODEV; }

//注冊(cè)硬件驅(qū)動(dòng)程序 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 //如果要單獨(dú)測(cè)試CH365中斷的話,可以把BitAction置1 rtl_outb_p (0xfa, io + 0xf8);

rtl_hard_enable_irq (irq);

//延時(shí)一會(huì)兒,觀察效果 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");