分享

pci-source

 昵称9961388 2012-05-21
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/ioport.h>



#define MY_VENDOR_ID    0X10B5//厂商号
#define MY_DEVICE_ID    0X8948//设备号
#define MY_DEVICE_NAME    "PCI_DRIVE"

unsigned long pio_start;
unsigned long pio_end;
unsigned long pio_flags;
unsigned long pio_len;

unsigned long mmio_start;
unsigned long mmio_end;
unsigned long mmio_flags;
unsigned long mmio_len;

//指明驱动程序适用的PCI设备ID
static struct pci_device_id ids[]=
{
    {
    PCI_DEVICE
        (
        //PCI_ANY_ID,
        //PCI_ANY_ID
        MY_VENDOR_ID,
        MY_DEVICE_ID
        ),
    },
    
    {
    0,
    }
};

MODULE_DEVICE_TABLE(pci,ids);

//读取vendor
static int get_pci_vendor(struct pci_dev *dev)
{
    u16 vendor;
    printk("读取vendor\n");
    pci_read_config_word(dev,  PCI_VENDOR_ID, &vendor);
    //printk("%d\n",vendor);
    return vendor;
}

//读取device
static int get_pci_device(struct pci_dev *dev)
{
    u16 device;
    printk("读取device\n");
    pci_read_config_word(dev, PCI_DEVICE_ID , &device);
    //printk("%d\n",device);
    return device;
}

//读取revision
static int get_pci_revision(struct pci_dev *dev)
{
    u8 revision;
    printk("读取revision\n");
    pci_read_config_byte(dev, PCI_REVISION_ID, &revision);
    //printk("%d\n",revision);
    return revision;
}

//读取 Header Type 寄存器
static int get_pci_header_type(struct pci_dev *dev)
{
     u8 header_type;
     printk("读取header_type:\n");
     pci_read_config_byte(dev,PCI_HEADER_TYPE,&header_type);
     return header_type;
}

static void pci_io_read_write(struct pci_dev *dev)
{
    unsigned long addr1;//, addr2;
    
    int i;
    
    void __iomem *ioaddr;
    
    //void __iomem *ioaddr;
        
    if(!(pci_enable_device_io(dev)))
    {
        printk("enable_device_io\n");
    }
    else
    {
        printk("can not enable_device_io\n");
    }
    if(!(pci_enable_device_mem(dev)))
    {
        printk("enable_device_mem\n");
    }
    else
    {
        printk("can not enable_device_mem\n");
    }

        
    pio_start = pci_resource_start (dev, 0);
    pio_end = pci_resource_end (dev, 0);
    
    pio_flags = pci_resource_flags (dev, 0);
    pio_len = pci_resource_len (dev, 0);
    
    mmio_start = pci_resource_start (dev, 3);
    mmio_end = pci_resource_end (dev, 3);

    mmio_flags = pci_resource_flags (dev, 3);
    mmio_len = pci_resource_len (dev, 3);    
    
    printk("pio_start=%lx\n",pio_start);
    printk("pio_end=%lx\n",pio_end);
    printk("pio_flags=%lx\n",pio_flags);
    printk("pio_len=%lx\n",pio_len);
    
    printk("mmio_start=%lX\n",mmio_start);
    printk("mmio_end=%lX\n",mmio_end);
    printk("mmio_flags=%lX\n",mmio_flags);
    printk("mmio_len=%lX\n",mmio_len);
    
//========================================================//
//ioaddr = (unsigned char*)ioremap(pio_start,pio_len);
    /*
May 21 09:36:53 ubuntu kernel: [ 4252.551833] pio_start=febffc00
May 21 09:36:53 ubuntu kernel: [ 4252.551835] pio_end=febfffff
May 21 09:36:53 ubuntu kernel: [ 4252.551836] pio_flags=40200
May 21 09:36:53 ubuntu kernel: [ 4252.551838] pio_len=400
May 21 09:36:53 ubuntu kernel: [ 4252.551839] mmio_start=EC00
May 21 09:36:53 ubuntu kernel: [ 4252.551841] mmio_end=EC1F
May 21 09:36:53 ubuntu kernel: [ 4252.551842] mmio_flags=40101
May 21 09:36:53 ubuntu kernel: [ 4252.551844] mmio_len=20
May 21 09:36:53 ubuntu kernel: [ 4252.551865] ioport = f8548c00
May 21 09:36:53 ubuntu kernel: [ 4252.551866] iddr1 = ffff
May 21 09:36:53 ubuntu kernel: [ 4252.551868] iddr2 = 0
    */
//========================================================//
    ioaddr = (unsigned char*)ioremap(mmio_start,mmio_len);
  /*
May 21 09:35:03 ubuntu kernel: [ 4143.198093] pio_start=febffc00
May 21 09:35:03 ubuntu kernel: [ 4143.198096] pio_end=febfffff
May 21 09:35:03 ubuntu kernel: [ 4143.198098] pio_flags=40200
May 21 09:35:03 ubuntu kernel: [ 4143.198101] pio_len=400
May 21 09:35:03 ubuntu kernel: [ 4143.198104] mmio_start=EC00
May 21 09:35:03 ubuntu kernel: [ 4143.198106] mmio_end=EC1F
May 21 09:35:03 ubuntu kernel: [ 4143.198109] mmio_flags=40101
May 21 09:35:03 ubuntu kernel: [ 4143.198112] mmio_len=20
May 21 09:35:03 ubuntu kernel: [ 4143.198136] ioport = f8546c00
May 21 09:35:03 ubuntu kernel: [ 4143.198139] iddr1 = 5f62
May 21 09:35:03 ubuntu kernel: [ 4143.198141] iddr2 = 0
  */
//========================================================//
//  ioaddr = ioport_map(pio_start,pio_len);
//        ioaddr = ioport_map(mmio_start,mmio_len);

//    ioaddr = pci_iomap(dev,0,0);
//    ioaddr = pci_iomap(dev,0,1);

//    ioaddr = pci_iomap(dev,3,0);
//    ioaddr = pci_iomap(dev,3,1);
    /*
        for(i=0 ; i<mmio_len ; i++)
        {
            
            iowrite32(0,ioaddr+i);
        }*/
        
        iowrite32(0,ioaddr+18);
        iowrite32(8224,ioaddr+18);
        
        //iowrite16(0x0000,ioaddr+18);
    //    iowrite16(0x2020,ioaddr+18);
    
        addr1 = ioread32(ioaddr);
    
    /*    printk("%x\r\n",inw(pio_start+18));
        outw(0,pio_start+18);
        outw(8224,pio_start+18);
        printk("%x\r\n",inw(pio_start));
        printk("%x\r\n",inw(pio_start+18));
        */

        printk("ioport = %p\n",ioaddr);
        printk("iddr1 = %lx\n",addr1);
        printk("=================================\n");
        printk("%lx\n",ioread32(ioaddr+18));
        printk("=================================\n");

        /*for(i=0 ; i<pio_len ; i++)
        {
            printk("%lx\n",ioread32(ioaddr+i));
            //printk("%lx\n",readl(ioaddr+i));
        }*/
        
    /*        
    {
    inline u16 inw(unsigned long addr)
    inline u16 outw(u16 b,unsigned long addr)
    
    }*/
    
    /*
    a1 = pci_resource_start (dev, 2);
    b1 = pci_resource_end (dev, 2);

    c1 = pci_resource_flags (dev, 2);
    d1 = pci_resource_len (dev, 2);    
    
    printk("a1=%lx\n",a1);
    printk("b1=%lx\n",b1);
    printk("c1=%lx\n",c1);
    printk("d1=%lx\n",d1);
    //
    a2 = pci_resource_start (dev, 3);
    b2 = pci_resource_end (dev, 3);

    c2 = pci_resource_flags (dev, 3);
    d2 = pci_resource_len (dev, 3);    
    
    printk("a2=%lx\n",a2);
    printk("b2=%lx\n",b2);
    printk("c2=%lx\n",c2);
    printk("d2=%lx\n",d2);
    //
    a3 = pci_resource_start (dev, 4);
    b3 = pci_resource_end (dev, 4);

    c3 = pci_resource_flags (dev, 4);
    d3 = pci_resource_len (dev, 4);    
    
    printk("a3=%lx\n",a3);
    printk("b3=%lx\n",b3);
    printk("c3=%lx\n",c3);
    printk("d3=%lx\n",d3);
    //
    a4 = pci_resource_start (dev, 5);
    b4 = pci_resource_end (dev, 5);

    c4 = pci_resource_flags (dev, 5);
    d4 = pci_resource_len (dev, 5);    
    
    printk("a3=%lx\n",a4);
    printk("b3=%lx\n",b4);
    printk("c3=%lx\n",c4);
    printk("d3=%lx\n",d4);
    //
    //
    a5 = pci_resource_start (dev, 6);
    b5 = pci_resource_end (dev, 6);

    c5 = pci_resource_flags (dev, 6);
    d5 = pci_resource_len (dev, 6);    
    
    printk("a3=%lx\n",a5);
    printk("b3=%lx\n",b5);
    printk("c3=%lx\n",c5);
    printk("d3=%lx\n",d5);
    */
    
    
    /*if(!(request_mem_region(a2,b2,MY_DEVICE_NAME)))
    {
        printk("地址申请成功\n");
    }
    else
    {
        printk("地址申请失败\n");
    }*/
    
    
    //unsigned long pio_start, pio_len, addr1, addr2;
    //void __iomem *ioaddr;
    //pio_start = pci_resource_start( dev, 0);
    //pio_len = pci_resource_len (pdev, 0);
    
    //printk("\n=====================================\n");    
//===================================================//    
/*
    ioaddr = ioport_map(pio_start, pio_len);
    
    iowrite16(0,ioaddr+18);
    iowrite16(8224,ioaddr+18);
        
    addr1 = ioread16(ioaddr);
    addr2 = ioread16(0x0000);
        
    printk(KERN_INFO "pio start: %lX\n", pio_start);
    printk(KERN_INFO "ioaddr: %p\n", ioaddr);
    printk(KERN_INFO "addr1 : %lx\n",addr1);
    printk(KERN_INFO "addr2 : %lx\n",addr2);
    ////////
    ioport_unmap(&pio_start);
    *///////
/*//===================================================//

    printk("\n=====================================\n");
//===================================================//    
    outw(0,pio_start+18);
    outw(8224,pio_start+18);
    addr1 = inw(pio_start+0);
    addr2 = inw(0x0000);
    
    printk(KERN_INFO "addr1 : %lx\n",addr1);
    printk(KERN_INFO "addr2 : %lx\n",addr2);
    //
    printk("=====================================\n");
    //
    outw(0,mmio_start+18);
    outw(8224,mmio_start+18);
    
    addr1 = inw(mmio_start+0);
    addr2 = inw(0x0000);
    
    printk(KERN_INFO "addr1 : %lx\n",addr1);
    printk(KERN_INFO "addr2 : %lx\n",addr2);

//===================================================//

    printk("\n=====================================\n");
//===================================================//
    ioaddr = pci_iomap(dev, 3, 1);
    
    iowrite16(0,ioaddr+18);
    iowrite16(8224,ioaddr+18);
    
    addr1 = ioread16( ioaddr );
    addr2 = ioread16( 0x0000);
    
    printk(KERN_INFO "mmio start: %lX\n", mmio_start);
    printk(KERN_INFO "ioaddr: %p\n", ioaddr);
    
    printk(KERN_INFO "addr1 : %lx\n",addr1);
    printk(KERN_INFO "addr2 : %lx\n",addr2);
//======================================================//
printk("\n=====================================\n");    */

    iounmap(ioaddr);
}

//检测
static int probe(struct pci_dev *dev, const struct pci_device_id *id)
{
    /* Do probing type stuff here.  
     * Like calling request_region();
     */
    
    printk("检测设备\n");
    if(!(pci_enable_device(dev)))
    {
        printk("设备开启成功\n");
    }
    else
    {
        printk("设备开启失败\n");
        return -ENODEV;
    }
    //开启设备
    
    if(get_pci_vendor(dev)==65535)
    {
        printk("没检测到设备\n");
        return -ENODEV;
    }
    else
    {
        printk("%d\n", get_pci_vendor(dev));
        
        printk("%d\n", get_pci_device(dev));
    
        printk("%d\n", get_pci_revision(dev));
        
        printk("%d\n", get_pci_header_type(dev));
    }
    
    pci_io_read_write(dev);
    
    return 0;
}

//移除
static void remove(struct pci_dev *dev)
{
    /* clean up any allocated resources and stuff here.
     * like call release_region();
     */
    printk("调用移除\n");
}


//设备模块信息
static struct pci_driver pci_driver =
{
    .name = MY_DEVICE_NAME,    //设备模块名称
    .id_table = ids,    //驱动设备表
    .probe = probe,        //查找并初始化设备
    .remove = remove,    //卸载设备模块
};

//初始化
static int __init pci_skel_init(void)
{
    printk("调用初始化函数\n");
    
    return pci_register_driver(&pci_driver);
}

//卸载
static void __exit pci_skel_exit(void)
{    
    printk("卸载设备\n");    
    //pci_disable_device(&pci_driver);
    pci_unregister_driver(&pci_driver);
}

MODULE_LICENSE("GPL");

module_init(pci_skel_init);
module_exit(pci_skel_exit);

//=======================================================================//
/*
#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);
*/

//=========================================//====================//==================//==============//


obj-m    := pci.o

KERNELDIR ?= /lib/modules/3.2.0-23-generic-pae/build
PWD       := $(shell pwd)

all:
    $(MAKE) -C $(KERNELDIR) M=$(PWD)

clean:
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多