#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 |
|