阅读:4814回复:23
请教linux pci driver问题!?
请问那位大侠能提供一份关于linux下通用pci卡的driver 的编程框架. :)
[编辑 - 4/10/02 作者: speedwave] |
|
沙发#
发布于:2003-08-21 09:46
最近我在调DS3131,系统大体框架搭好了,对PCI板子操作没有问题,剩下的只是DS3131的具体问题了。一个人摸索,进展很慢。好在上网方便,搜索了很多资料,很多没有仔细看。我的思路是让系统自动找到PCI卡,然后将卡注册为字符设备,对其操作。目前进展到在用户模式下通过IOCTL读写板子的寄存器。欢迎大家一块交流,互相学习。程序还不完善,很多地方我还在修改。完了我会继续跟贴,欢迎大家指正。谢谢!!
static void pci3131_interrupt(int irq, void *dev_id, struct pt_regs *regs){ drvDev *card= (drvDev *)dev_id; int sm, sdma, sv54; outb(0x03, card->base+0x02); wake_up_interruptible(&interrupt_wq); inb(card->base+0x05); ////////////////////////////////////////////////////////////////////////////// /* * In order to acknowledge interrupt we have to read * three status registers from DS3134: SM (offset 0x20), * SDMA(offset 0x28) and SV54 (offset 0x30) */ sm = 0; sv54 = 0; sdma = sysDevRdReg16 ((int)card->base, CHAT_REG_GEN_SDMA); if (sdma) { drvIntCallback(card, sm, sdma, sv54); } //////////////////////////////////////////////////////////////////////////// } //------------------------------------------------------- // pci probe µÇåh static int __init pci3131_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id){ int minor=0; drvDev *card; u32 len; u32 pcmd1; u32 pci3131_base; if(pci_enable_device(pci_dev)){ // printk(\"<0>pci3131 drive failed to enable PCI3131 hardware\"); return(-EIO); } if (pci_set_dma_mask(pci_dev, 0xffffffff)) printk(\"<0>drive DMA address limits not supported for PCI ds3131 hardware\"); pci_read_config_dword(pci_dev,0x008,&pcmd1); // printk(\"<0>pci3131 008 %X\\n\",pcmd1); if((pcmd1>>24&0xff)==6) return (0); // pci_read_config_dword(pci_dev,0x010,&pcmd1); // printk(\"<0>pci3131 010 %X\\n\",pcmd1); pci3131_base = pci_resource_start(pci_dev, 0); printk(\"<0>pci3131 driver at %X\\n\",pci3131_base); len = pci_resource_len(pci_dev, 0); printk(\"<0>pci3131 resoure len %X\\n\",len); card = kmalloc(sizeof(drvDev),GFP_KERNEL); if (card == NULL) { printk(\"PCI3131: Can\'t allocate memory. minor=%d.\\n\", minor); return( -ENOMEM); } memset(card,0,sizeof(drvDev)); card->minor=minor; card->irq=pci_dev->irq; card->pci_dev = pci_dev; if( !request_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0),DRIVER_NAME)){ printk(\"<0>Unable to reserve I/O space\\n\"); goto out_free; } card->base = (unsigned long) ioremap(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); if(card->base==NULL) { printk(KERN_ERR \"PCI 3131: unable to map registers\\n\"); goto out_release_region; } pci_set_drvdata(pci_dev, card); // if(request_irq(pci_dev->irq, pci3131_interrupt, SA_INTERRUPT, pci_dev->name, card)){ printk(\"<0>Unable to allocate irq %d\\n\",pci_dev->irq); goto out_unmap; } if(gDrvDevDesc){ goto out_free_irq; } // gDrvDevDesc=card; // for test // readreg(card->base); //come from DS3134_Open /* Set PCMD0 */ pci_read_config_dword(pci_dev,0x004,&pcmd1); pcmd1 &=~(0x100); pci_write_config_dword(pci_dev,0x004,pcmd1); pci_read_config_dword(pci_dev,0x004,&pcmd1); BossdrvDevInit(pci_dev, 0); // readreg(card->base); return(0); out_free_irq: free_irq(pci_dev->irq, card); out_unmap: iounmap((void *)((unsigned long)card->base)); out_release_region: release_mem_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); out_free: kfree(card); return -ENODEV; } static void pci3131_remove(struct pci_dev *dev_id){ drvDev *card; int minor; u32 base,len; u32 pcmd1; pci_read_config_dword(dev_id,0x008,&pcmd1); // printk(\"<0>pci3131 008 %X\\n\",pcmd1); if((pcmd1>>24&0xff)==6) return; card = (drvDev *)pci_get_drvdata(dev_id); assert (card != NULL); minor = card->minor; gDrvDevDesc=NULL; base = pci_resource_start(dev_id, 0); printk(\"<0>pci3131 driver at %X\\n\",base); len = pci_resource_len(dev_id, 0); printk(\"<0>pci3131 resoure len %X\\n\",len); gDrvDevDesc=NULL; free_irq(dev_id->irq, card); iounmap((void *)((unsigned long)card->base)); release_mem_region(base, len); kfree(card); // pci_set_drvdata (dev_id, NULL); } //-------------------------------------------------------- static int pci3131_open(struct inode *inode, struct file * file){ // MOD_INC_USE_COUNT; return(0); } static ssize_t pci3131_read(struct file * file, char * buffer, size_t count, loff_t *ppos){ return(0); } static ssize_t pci3131_write(struct file * file, const char * buffer, size_t count, loff_t *ppos){ return(count); } static int pci3131_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ unsigned char ch, inputSpec, triggerPolarity, intMask, data_low, data_high, busy, int_status; unsigned short data; struct int_wait_and_get_ad_t intWait; int minor; drvDev *card; minor = MINOR(inode->i_rdev); // card=gDrvDevDesc; // switch(cmd){ // ioctl case PCI3131_IOC_HARDRESET: /* * reset the counter to 1, to allow unloading in case * of problems. Use 1, not 0, because the invoking * process has the device open. */ while (MOD_IN_USE) MOD_DEC_USE_COUNT; MOD_INC_USE_COUNT; /* don\'t break: fall through and reset things */ // ³ö case PCI3131_IOC_SETREG: copy_from_user(&ch, (void *)arg, sizeof(ch)); // printk(\"<0>.....................................set reg 0x10,%X of base %X\\n\",ch,card->base); writew(ch, card->base+0x10); break; case PCI3131_IOC_CONFIG: ConfigureDevice(); break; case PCI3131_IOC_RESET: ResetDevice(); break; case PCI3131_IOC_STARTTEST: StartDeviceTest(); break; case SET_CHANNEL: copy_from_user(&ch, (void *)arg, sizeof(ch)); // ch &= 0x0f; ch |= 0x80; outb(ch, card->base); break; case SET_CH_AND_START: copy_from_user(&ch, (void *)arg, sizeof(ch)); ch &= 0x0f; outb(ch, card->base); break; case SET_INPUT_SPEC: copy_from_user(&inputSpec, (void *)arg, sizeof(inputSpec)); outb(inputSpec, card->base+0x01); break; case SET_TRIGGER_POLARITY: copy_from_user(&triggerPolarity, (void *)arg, sizeof(triggerPolarity)); outb(triggerPolarity, card->base+0x04); break; case SET_INT_MASK: copy_from_user(&intMask, (void *)arg, sizeof(intMask)); outb(intMask, card->base+0x05); break; case SET_DO: copy_from_user(&data, (void *)arg, sizeof(data)); outb(data & 0x03,card->base+0x02); break; // ÈëÁ¦ case GET_DATA: /* data_high=inb(card->base+0x01); if((data_high & 0x80)!=0){ return(-BUSY); } data_low=inb(card->base); data=(((data_high)&0x0f)<<8) + data_low; copy_to_user((void *)arg, &data, sizeof(data)); */ if(card) readreg(card->base); break; case GET_BUSY: // busy=inb(card->base+0x01) & 0x80; copy_to_user((void *)arg, &busy, sizeof(busy)); // break; case GET_INT_STATUS: // int_status=inb(card->base+0x05); copy_to_user((void *)arg, &int_status, sizeof(int_status)); break; case WAIT_INTERRUPT: outb(0x00,card->base+0x02); copy_from_user(&intWait, (void *)arg, sizeof(intWait)); intWait.err=0; // if ( interruptible_sleep_on_timeout(&interrupt_wq, HZ*intWait.timeOut/1000 ) != 0) { // udelay(intWait.adSettringTime); // outb(0x00,card->base+0x02); // // AD data_high=inb(card->base+0x01); if(!(data_high & 0x80)){ // intWait.err=BUSY; // copy_to_user((void *)arg, &intWait, sizeof(intWait)); return(-BUSY); } data_low=inb(gDrvDevDesc->base); // intWait.adData=(((data_high)&0x0f)<<8) + data_low; copy_to_user((void *)arg, &intWait, sizeof(intWait)); }else{ intWait.err=INTWAITTIMEOUT; copy_to_user((void *)arg, &intWait, sizeof(intWait)); return( -INTWAITTIMEOUT ); } break; default: return(-ENOTSUPP); // break; } return(0); } //------------------------------------------------------- static int pci3131_close(struct inode * inode, struct file * file){ return(0); } //--------------------------------------------------- static struct pci_driver pci3131_pci_driver = { name : DRIVER_NAME, id_table : pci3131_id_table, probe : pci3131_probe, remove : pci3131_remove, }; static struct file_operations pci3131_ops={ read : pci3131_read, write : pci3131_write, ioctl : pci3131_ioctl, open : pci3131_open, release : pci3131_close, }; // ----------------------------------------------------- static void __exit pci3131_cleanup_module(void){ unregister_chrdev(pci3131_major, DEVICE_NAME); pci_unregister_driver(&pci3131_pci_driver); } static int __init pci3131_init_module(void){ int retVal; if(!pci_register_driver( &pci3131_pci_driver )){ printk(\"<0> init ds3131 error\\n\"); pci_unregister_driver( &pci3131_pci_driver); return(-ENODEV); } retVal = register_chrdev(pci3131_major , DEVICE_NAME, &pci3131_ops); if(pci3131_major==0){ // printk(\"<0> candidate of major = %d\\n\",pci3131_major); pci3131_cleanup_module(); return(-ENODEV); } if(retVal){ pci_unregister_driver(&pci3131_pci_driver); return(-ENODEV); } return(0); } module_init(pci3131_init_module); module_exit(pci3131_cleanup_module); ;) |
|
板凳#
发布于:2003-08-18 12:15
spark7@21cn.com
兄弟给我一份,谢谢! |
|
地板#
发布于:2003-06-10 16:54
兄弟,也给我一份吧:dcdu@wtwh.com.cn
|
|
地下室#
发布于:2003-06-04 10:54
我一直没有收到,你们呢?
|
|
5楼#
发布于:2003-06-04 10:22
我也想要,请也给我一份吧
nofer@21cn.com 谢谢! :D |
|
|
6楼#
发布于:2003-06-02 13:50
呵呵,我也想看一下。
多谢了。 sufengtiger@163.net |
|
7楼#
发布于:2003-05-29 12:30
也给我一份吧,谢谢!!!!!!!!
xdbupt@163.com |
|
8楼#
发布于:2003-05-15 15:47
发给我一份吧,我是新手,老板催的紧,多谢了!
邮箱:ypzhang@cdyw.com |
|
9楼#
发布于:2003-03-26 10:52
也给我一份吧,谢谢
mail :wzxghost@yahoo.com.cn |
|
10楼#
发布于:2003-03-26 10:44
我也要,我也要
robin-fox@sohu.com 谢谢了 |
|
11楼#
发布于:2002-07-15 17:02
请问你贴的那个源码在哪?如何找到?
|
|
12楼#
发布于:2002-05-28 18:28
如果是内核2.4的,偶也要一份,sirroom@163.com 3ks
如果是内核2.2下的,偶不是已经贴了一个源码出来了吗?是偶自已写的.hehe |
|
|
13楼#
发布于:2002-05-27 20:50
各位,不至于吧,linux source code 里面有的是,一下就刨到了
|
|
14楼#
发布于:2002-05-27 16:44
写完了没有?能否给我一份.谢谢。agri1234@163.net
|
|
15楼#
发布于:2002-05-27 16:44
写完了没有?能否给我一份.谢谢
|
|
16楼#
发布于:2002-05-04 13:59
给我发一份.谢谢!!!
shenhd@21cn.com |
|
17楼#
发布于:2002-04-22 16:08
真是不好意思,有这么多人感兴趣。但我还没写完呢。
最近一个月公司的事情特别多,我就有四个项目在跑,没日没夜地干。我会继续写,但可能还要在等几天才能发出去,总要测试一下吧。 |
|
18楼#
发布于:2002-04-22 15:37
给我发一个行吗?谢谢!(jiahs@neusoft.com)
|
|
19楼#
发布于:2002-04-20 19:19
给我一个行吗? 谢谢
hkcompuman@sinaman.com :P |
|
上一页
下一页