Linux下PCI IO記憶體讀寫

來源:互聯網
上載者:User

本文連結自:

http://qikee.blogbus.com/logs/37072405.html

I/O連接埠是驅動程式與許多裝置之間的通訊方式,Linux的核心為我們提供了I/O連接埠分配的操作介面,但對PCI裝置來講,它的配置地址空間已經為其指定了I/O連接埠範圍,不需要額外的分配操作。Linux核心 
提供了如下一些訪問I/O連接埠的內嵌函式: 
unsigned inb(unsigned port); 
void outb(unsigned char byte, unsigned port); 
unsigned inw(unsigned port); 
void outw(unsigned short word, unsigned port); 
unsigned inl(unsigned port); 
void outl(unsigned longword, unsigned port); 
下面我們重點來看一下2.6核心引入的ioport_map函數: 
void *ioport_map( unsigned long port, unsigned int count ); 
通過這個函數,可以把port開始的count個連續連接埠重新對應為一段“記憶體空間”。然後就可以在其返回的地址上象訪問I/O記憶體一樣訪問這幾個I/O連接埠。當不需要這種映射時,需要調用下面的函數來撤消: 
void iport_unmap(void *addr); 
除了I/O連接埠之外,和裝置通訊的另一種主要機制是通過使用映射到記憶體的寄存器或裝置記憶體。這兩種都稱為I/O記憶體,因為寄存器和記憶體的差別對軟體是透明的。 
對於分配好的I/O記憶體,一般不鼓勵直接使用指向I/O記憶體的指標進行訪問,最好通過頁表,用封裝函數訪問。要通過頁表訪問,那麼需要對分配好的I/O記憶體進行映射,確保該I/O記憶體對核心而言是可訪問的。完成I/O記憶體映射的函數是ioremap. 
#include <asm/io.h> 
void *ioremap(unsigned long phys_addr, unsigned long size); 
註冊驅動程式成功後,rtl8139_init_one會被調用,在這個函數中,我們可以通過插入一些列印輸出語句看到PCI的配置地址空間和I/O地址地區的一些情況。 
首先,插入以下語句: 
u16 vendor, device; 
pci_read_config_word(pdev, 0, &vendor); 
pci_read_config_word(pdev, 2, &device); 
printk(KERN_INFO "%x, %x/n", vendor, device); 
下面通過在 rtl8139_init_one在插入代碼,以四種不同方式訪問裝置記憶體。第一種是通過訪問I/O記憶體實現,後三種則是通過訪問I/O連接埠的形式實現。 
第一種: 
unsigned long mmio_start, addr1, addr2; 
void __iomem *ioaddr; 
mmio_start = pci_resource_start( pdev, 1); 
ioaddr = pci_iomap(pdev, 1, 0); 
addr1 = ioread32( ioaddr ); 
addr2 = ioread32( ioaddr + 4 ); 
printk(KERN_INFO "mmio start: %lX/n", mmio_start); 
printk(KERN_INFO "ioaddr: %p/n", ioaddr); 
第二種: 
unsigned long pio_start, pio_len, addr1, addr2; 
void __iomem *ioaddr; 
pio_start = pci_resource_start( pdev, 0); 
pio_len = pci_resource_len (pdev, 0); 
ioaddr = ioport_map(pio_start, pio_len); 
addr1 = ioread32( ioaddr ); 
addr2 = ioread32( ioaddr + 4 ); 
printk(KERN_INFO "pio start: %lX/n", pio_start); 
printk(KERN_INFO "ioaddr: %p/n", ioaddr); 
第三種: 
unsigned long pio_start, addr1, addr2; 
pio_start = pci_resource_start( pdev, 0 ); 
addr1 = inl( pio_start ); 
addr2 = inl( pio_start + 4 ); 
printk(KERN_INFO "port io start: %lX/n", pio_start); 
第四種: 
unsigned long pio_start; 
u8 addr1, addr2, addr3, addr4, addr5, addr6; 
pio_start = pci_resource_start( pdev, 0 ); 
addr1 = inb( pio_start ); 
addr2 = inb( pio_start + 1 ); 
addr3 = inb( pio_start + 2 ); 
addr4 = inb( pio_start + 3 ); 
addr5 = inb( pio_start + 4 ); 
addr6 = inb( pio_start + 5 ); 
printk(KERN_INFO "port io start: %lX/n", pio_start);

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.