QNX 4.25设备驱动程序的编写
printf("Error reading interrupt");
exit(EXIT_FAILURE);
}
//侦测设备I/O基地址
if_CA_PCI_Read_Config_DWord(busnum,devfuncnum,offsetof(struct_pci_config_r
本文链接地址:http://www.oyaya.net/fanwen/view/168007.html
egs,Base_[2]), 1,(char *)&address)!=PCI_SUCCESS){ printf("Error reading address"); exit(EXIT_FAILURE); } io_base=PCI_IO_ADDR(adress); printf("IO address:%x",io_base); printf("IRQ:"%x",irq); exit(EXIT_SUCCESS); } 注意:各种设备的Base_Address_Regs[x],x可能不尽相同,需要查看具体的硬件手册决定。 2 进入硬件 一旦获得了系统分配给某个硬件设备的资源信息,就可以同这个设备进行通信了。至于如何做取决于需要访问的硬件资源。 2.1 I/O资源 一个进程试图进行I/O操作,必须具有正确的权限等级。你必须是超及用户(root),在编译的时候加上适当参数T1,以确何该进程拥有访问I/O口的权限。若忽视这一点,该运行进程将获得一个口的权限。若忽视这一点,该运行进行将获得一个SIGSEGV信号,表示一个非法的内存引用,并结束进程运行。 现在就可以利用inp()、inpd()、inpw(),outp(),inpd(),inpw(0等函数,对I/O基地址(I/O base address)加上寄存器偏移量(offset)处的I/O进行操作了。例如: outpw(baseaddress+offset_reg,0xdeadbeef); 此外,对于一些设备,其I/O口是固定、众所皆知的,例如,一块VGA兼容的设备,并无上述所谓基地址。通过0x3c0、0x3d4、0x3d5,可以直接进入这些VGA的控制器。例如: outp(0x3d4,0x11); outp(0x3d5,inp(0x3d5)& ~0x80); 2.2 存储映射资源 某些设备,可以通过一般的内存操作进入寄存器,这就需要获得内存基地址(memory base address)。为了能够获进入此类设备的寄存器,需要将其映射到驱动程序虚拟地址空间。QNX下的技术资料/etc/readme/technotes/shmem.txt描述了如何创建一个共享内存对象,然后将这个内存对象的一段内存映射到PCI卡中,以便能够进入这个PCI设备。(接着上面的代码)可以利用mmap(): char *mem_base; if(PCI_IS_MEM(address)){ //判断内存基地址 int fd; char *page_ptr; fd=shm_open("Physical",O_RDWR,0777);//创建一个共享内存对象 if(fd= =-1){ perror("Error shm_open:"); exit(EXIT_FAILURE); } page_ptr=mmap(0,4096,PROT_READ|PROT_WRITE, MAP_SHARED,fd,PCI_MEM_ADDR(address)&~0xfff);//将内存基地址映射 if(page_ptr= =(char *) perror("Error mmap:"); exit(EXIT_FAILURE); } mem_base=page_ptr+(PCI_MEM_ADDR(address)&0xfff); close(fd); } printf("MEM" address:%lx",PCI_MEM_ADDR(address)); if(PCI_IS_MEM(address)) printf("mapped at : %lx",mem_base); 现在可以使用指针mem_base来进入设备寄存器了。例如: mem_base[SHUTDOWN_REGISTER]=0x0xdeadbeef; 2.3 中断资源 超级用户(root)可以调用qnx_hint_attach()将一个中断处理程序绑定到一个设备上。中断处理程序作为一个远程调用(far),在进程空间(Localdescriptor Table set)运行。该函数最后一个参数设置数据段。寄存器SS为一个特别的内核栈,这不同于数据段(DS)。因此,需要在中断处理程序及其调用的函数中关断栈检查。大部分系统库中的函数在编译的时候都关断了栈检查,然而,对于需要使用大量内存的函数可能并非如此。后者即是那些在中断处理程序中不可调用的函数,如printf()、open()。通过QNX具体函数在线资源的Safety→Interrupt handler项进行判断该函数是否可以调用。如果函数中包括任何自动(auto)变量,强烈建议将中断函数放在自身文件中,然后利用参 《QNX 4.25设备驱动程序的编写(第2页)》