新聞中心

        EEPW首頁(yè) > 模擬技術(shù) > 設(shè)計(jì)應(yīng)用 > Linux下PCI設(shè)備驅(qū)動(dòng)程序開(kāi)發(fā)

        Linux下PCI設(shè)備驅(qū)動(dòng)程序開(kāi)發(fā)

        作者:肖文鵬 碩士研究生, 北京理工大學(xué)計(jì)算機(jī)系 時(shí)間:2008-08-25 來(lái)源:21IC 中國(guó)電子網(wǎng) 收藏
          4. 打開(kāi)設(shè)備模塊

          在這個(gè)模塊里主要實(shí)現(xiàn)申請(qǐng)中斷、檢查讀寫模式以及申請(qǐng)對(duì)設(shè)備的控制權(quán)等。在申請(qǐng)控制權(quán)的時(shí)候,非阻塞方式遇忙返回,否則進(jìn)程主動(dòng)接受調(diào)度,進(jìn)入睡眠狀態(tài),等待其它進(jìn)程釋放對(duì)設(shè)備的控制權(quán)。 

        本文引用地址:http://www.104case.com/article/87319.htm

          static int demo_open(struct inode *inode, struct file *file)
          {
            /* 申請(qǐng)中斷,注冊(cè)中斷處理程序 */
            request_irq(card->irq, &demo_interrupt, SA_SHIRQ,
                card_names[pci_id->driver_data], card)) {
            /* 檢查讀寫模式 */
            if(file->f_mode & FMODE_READ) {
                /* ... */
            }
            if(file->f_mode & FMODE_WRITE) {
               /* ... */
            }
            
            /* 申請(qǐng)對(duì)設(shè)備的控制權(quán) */
            down(&card->open_sem);
            while(card->open_mode & file->f_mode) {
                if (file->f_flags & O_NONBLOCK) {
                    /* NONBLOCK模式,返回-EBUSY */
                    up(&card->open_sem);
                    return -EBUSY;
                } else {
                    /* 等待調(diào)度,獲得控制權(quán) */
                    card->open_mode |= f_mode & (FMODE_READ | FMODE_WRITE);
                    up(&card->open_sem);
                    /* 設(shè)備打開(kāi)計(jì)數(shù)增1 */
                    MOD_INC_USE_COUNT;
                    /* ... */
                }
            }
          } 
         
          5. 數(shù)據(jù)讀寫和控制信息模塊

          設(shè)備驅(qū)動(dòng)程序可以通過(guò)demo_fops 結(jié)構(gòu)中的函數(shù)demo_ioctl( ),向應(yīng)用程序提供對(duì)硬件進(jìn)行控制的接口。例如,通過(guò)它可以從I/O寄存器里讀取一個(gè)數(shù)據(jù),并傳送到用戶空間里: 

          static int demo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
          {
            /* ... */
            
            switch(cmd) {
                case DEMO_RDATA:
                    /* 從I/O端口讀取4字節(jié)的數(shù)據(jù) */
                    val = inl(card->iobae + 0x10);
                    
          /* 將讀取的數(shù)據(jù)傳輸?shù)接脩艨臻g */
                    return 0;
            }
            
            /* ... */
          } 
         
          事實(shí)上,在demo_fops里還可以實(shí)現(xiàn)諸如demo_read( )、demo_mmap( )等操作,內(nèi)核源碼中的driver目錄里提供了許多設(shè)備驅(qū)動(dòng)程序的源代碼,找那里可以找到類似的例子。在對(duì)資源的訪問(wèn)方式上,除了有I/O指令以外,還有對(duì)外設(shè)I/O內(nèi)存的訪問(wèn)。對(duì)這些內(nèi)存的操作一方面可以通過(guò)把I/O內(nèi)存重新映射后作為普通內(nèi)存進(jìn)行操作,另一方面也可以通過(guò)主DMA(Bus Master DMA)的方式讓設(shè)備把數(shù)據(jù)通過(guò)DMA傳送到系統(tǒng)內(nèi)存中。 

          6. 中斷處理模塊

          PC的中斷資源比較有限,只有0~15的中斷號(hào),因此大部分外部設(shè)備都是以共享的形式申請(qǐng)中斷號(hào)的。當(dāng)中斷發(fā)生的時(shí)候,中斷處理程序首先負(fù)責(zé)對(duì)中斷進(jìn)行識(shí)別,然后再做進(jìn)一步的處理。 

          static void demo_interrupt(int irq, void *dev_id, struct pt_regs *regs)
          {
            struct demo_card *card = (struct demo_card *)dev_id;
            u32 status;
            spin_lock(&card->lock);
            /* 識(shí)別中斷 */
            status = inl(card->iobase + GLOB_STA);
            if(!(status & INT_MASK)) 
            {
                spin_unlock(&card->lock);
                return;  /* not for us */
            }
            /* 告訴設(shè)備已經(jīng)收到中斷 */
            outl(status & INT_MASK, card->iobase + GLOB_STA);
            spin_unlock(&card->lock);
            
            /* 其它進(jìn)一步的處理,如更新DMA緩沖區(qū)指針等 */
          } 
         

          7. 釋放設(shè)備模塊

          釋放設(shè)備模塊主要負(fù)責(zé)釋放對(duì)設(shè)備的控制權(quán),釋放占用的內(nèi)存和中斷等,所做的事情正好與打開(kāi)設(shè)備模塊相反:

          static int demo_release(struct inode *inode, struct file *file)
          {
            /* ... */
            
            /* 釋放對(duì)設(shè)備的控制權(quán) */
            card->open_mode &= (FMODE_READ | FMODE_WRITE);
            
            /* 喚醒其它等待獲取控制權(quán)的進(jìn)程 */
            wake_up(&card->open_wait);
            up(&card->open_sem);
            
            /* 釋放中斷 */
            free_irq(card->irq, card);
            
            /* 設(shè)備打開(kāi)計(jì)數(shù)增1 */
            MOD_DEC_USE_COUNT;
            
            /* ... */  
          } 
         
          8. 卸載設(shè)備模塊

          卸載設(shè)備模塊與初始化設(shè)備模塊是相對(duì)應(yīng)的,實(shí)現(xiàn)起來(lái)相對(duì)比較簡(jiǎn)單,主要是調(diào)用函數(shù)pci_unregister_driver( )從內(nèi)核中注銷設(shè)備驅(qū)動(dòng)程序: 

          static void __exit demo_cleanup_module (void)
          {
            pci_unregister_driver(&demo_pci_driver);
          }
         
          四、小結(jié)

          不僅是目前應(yīng)用廣泛的計(jì)算機(jī)標(biāo)準(zhǔn),而且是一種兼容性最強(qiáng)、功能最全的計(jì)算機(jī)總線。而作為一種新的操作系統(tǒng),其發(fā)展前景是無(wú)法估量的,同時(shí)也為總線與各種新型設(shè)備互連成為可能。由于Linux源碼開(kāi)放,因此給連接到PCI總線上的任何設(shè)備編寫驅(qū)動(dòng)程序變得相對(duì)容易。本文介紹如何編譯Linux下的PCI驅(qū)動(dòng)程序,針對(duì)的內(nèi)核版本是2.4。 

        linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

        c++相關(guān)文章:c++教程



        上一頁(yè) 1 2 3 下一頁(yè)

        關(guān)鍵詞: PCI 總線 Linux Alpha

        評(píng)論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 古蔺县| 色达县| 巫山县| 江山市| 宜城市| 河西区| 丹东市| 汾西县| 斗六市| 琼中| 揭东县| 临沧市| 高淳县| 泰安市| 崇明县| 红河县| 黑龙江省| 青海省| 乃东县| 卢氏县| 开阳县| 右玉县| 台江县| 伊吾县| 凌源市| 根河市| 昌乐县| 汝城县| 云龙县| 宜宾市| 乐至县| 澄迈县| 泸西县| 汝城县| 渝北区| 松江区| 平山县| 新源县| 赤壁市| 霸州市| 博兴县|