📄 spartan_drv.c
字号:
// memory mapped resource read functionssize_t spartan_read(struct file *filp, char *buf, size_t count, loff_t *offset_out ) { unsigned long current_address = pspartan_dev.page_addr + pspartan_dev.base_page_offset + pspartan_dev.offset ; unsigned long actual_count ; unsigned long offset = pspartan_dev.offset ; int resource_num = pspartan_dev.current_resource ; unsigned long size = pspartan_dev.base_size[resource_num] ; int result ; if (pspartan_dev.current_resource < 0) return -ENODEV ; if (offset == size) return 0 ; if ( (offset + count) > size ) actual_count = size - offset ; else actual_count = count ; // verify range if it is OK to copy from if ((result = verify_area(VERIFY_WRITE, buf, actual_count))) return result ; memcpy(buf, (void *)(current_address), actual_count); pspartan_dev.offset = pspartan_dev.offset + actual_count ; *(offset_out) = pspartan_dev.offset ; return actual_count ; } // memory mapped resource write functionssize_t spartan_write(struct file *filp, const char *buf, size_t count, loff_t *offset_out) { unsigned long current_address = pspartan_dev.page_addr + pspartan_dev.base_page_offset + pspartan_dev.offset ; unsigned long actual_count ; unsigned long offset = pspartan_dev.offset ; int resource_num = pspartan_dev.current_resource ; unsigned long size = pspartan_dev.base_size[resource_num] ; int result ; if (pspartan_dev.current_resource < 0) return -ENODEV ; if (offset == size) return 0 ; if ( (offset + count) > size ) actual_count = size - offset ; else actual_count = count ; // verify range if it is OK to copy from if ((result = verify_area(VERIFY_READ, buf, actual_count))) return result ; memcpy((void *)(current_address), buf, actual_count); pspartan_dev.offset = pspartan_dev.offset + actual_count ; *(offset_out) = pspartan_dev.offset ; return actual_count ; }// initialization function - different for 2.2 and 2.4 kernel because of different pci_dev structureint init_module(void){ int result ; u32 base_address ; unsigned long size ; unsigned short num_of_bases ; u16 wvalue ; struct pci_dev *ppci_spartan_dev = NULL ; if(!pci_present()) { printk("<1> Kernel reports no PCI bus support!\n " ); return -ENODEV; } if((ppci_spartan_dev = pci_find_device(OC_PCI_VENDOR, OC_PCI_DEVICE, ppci_spartan_dev))==NULL ) { printk("<1> Device not found!\n " ); return -ENODEV ; } pspartan_dev.ppci_spartan_dev = ppci_spartan_dev ;#ifdef KERNEL_VER_24 //printk("<1> Board found at address 0x%08X\n", ppci_spartan_dev->resource[0].start) ; // copy implemented base addresses to private structure struct resource spartan_resource ; spartan_resource = ppci_spartan_dev->resource[0] ; base_address = spartan_resource.start ; printk("<1> First base address register found at %08X \n ", base_address ); num_of_bases = 0 ; while ((base_address != 0x00000000) && (num_of_bases < 6)) { pspartan_dev.bases[num_of_bases] = spartan_resource.start ; pspartan_dev.base_size[num_of_bases] = spartan_resource.end - spartan_resource.start + 1 ; // check if resource is IO mapped if (spartan_resource.flags & IORESOURCE_IO) pspartan_dev.base_map[num_of_bases] = SPARTAN_IO_MAPPED ; else pspartan_dev.base_map[num_of_bases] = SPARTAN_MEM_MAPPED ; num_of_bases++ ; spartan_resource = ppci_spartan_dev->resource[num_of_bases] ; base_address = spartan_resource.start ; } result = pci_read_config_word(ppci_spartan_dev, PCI_COMMAND, &wvalue) ; if (result < 0) { printk("<1> Read from command register failed! \n " ); return result ; } result = pci_write_config_word(ppci_spartan_dev, PCI_COMMAND, wvalue | PCI_COMMAND_MEMORY | PCI_COMMAND_IO) ; if (result < 0) { printk("<1>Write to command register failed! \n " ); return result ; } #else printk("<1> Board found at address 0x%08X\n", ppci_spartan_dev->base_address[0]); // now go through base addresses of development board and see what size they are - first disable devices response result = pci_read_config_word(ppci_spartan_dev, PCI_COMMAND, &wvalue) ; if (result < 0) { printk("<1> Read from command register failed! \n " ); return result ; } // write masked config value back to command register to disable devices response! // mask value result = pci_write_config_word(ppci_spartan_dev, PCI_COMMAND, wvalue & ~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY) ; if (result < 0) { printk("<1>Write to command register failed! \n " ); return result ; } // write to base address registers and read back until all 0s are read base_address = ppci_spartan_dev->base_address[0] ; num_of_bases = 0 ; while ((base_address != 0x00000000) && (num_of_bases < 6)) { // copy non-zero base address to private structure pspartan_dev.bases[num_of_bases] = ppci_spartan_dev->base_address[num_of_bases] ; // write to current register result = pci_write_config_dword(ppci_spartan_dev, PCI_BASE_ADDRESS_0 + (num_of_bases * 4), 0xFFFFFFFF) ; if (result < 0) { printk("<1>Write to BAR%d failed! \n ", num_of_bases); return result ; } result = pci_read_config_dword(ppci_spartan_dev, PCI_BASE_ADDRESS_0 + (num_of_bases * 4), &base_address) ; if (result < 0) { printk("<1>Read from BAR%d failed! \n ", num_of_bases); return result ; } // calculate size of this base address register's range size = 0xFFFFFFFF - base_address ; // store size in structure pspartan_dev.base_size[num_of_bases] = size + 1; // set base address back to original value base_address = pspartan_dev.bases[num_of_bases] ; // now write original base address back to this register result = pci_write_config_dword(ppci_spartan_dev, PCI_BASE_ADDRESS_0 + (num_of_bases * 4), base_address) ; if (result < 0) { printk("<1>Write to BAR%d failed! \n ", num_of_bases); return result ; } num_of_bases++ ; // read new base address base_address = ppci_spartan_dev->base_address[num_of_bases] ; } // write original value back to command register! result = pci_write_config_word(ppci_spartan_dev, PCI_COMMAND, wvalue) ; if (result < 0) { printk("<1>Write to command register failed! \n " ); return result ; } #endif if (num_of_bases < 1) printk("<1>No implemented base address registers found! \n ") ; pspartan_dev.current_resource = - 1 ; // store number of bases in structure pspartan_dev.num_of_bases = num_of_bases ; // display information about all base addresses found in this procedure for (num_of_bases = 0; num_of_bases < pspartan_dev.num_of_bases; num_of_bases++) { printk("<1>BAR%d range from %08X to %08X \n ", num_of_bases, pspartan_dev.bases[num_of_bases], pspartan_dev.bases[num_of_bases] + pspartan_dev.base_size[num_of_bases]); } result = register_chrdev(REQUESTED_MAJOR, "spartan", &spartan_fops) ; if (result < 0) { printk(KERN_WARNING "spartan: can't get major number %d\n",REQUESTED_MAJOR) ; return result ; } printk("<1> Major number for spartan is %d \n", result ); pspartan_dev.major = result ; return 0 ; }// celanup - unregister devicevoid cleanup_module(void) { int result ; result = unregister_chrdev(pspartan_dev.major, "spartan") ; if (result < 0) { printk("<1> spartan device with major number %d unregistration failed \n", pspartan_dev.major); return ; } else { printk("<1> spartan device with major number %d unregistered succesfully \n", pspartan_dev.major); return ; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -