pm8001_pci_probe函数分析之pm8001_pci_alloc
来源:互联网 发布:会计出纳软件 编辑:程序博客网 时间:2024/05/16 06:31
接着分析pm8001_pci_probe中调用的pm8001_pci_alloc和scsi_scan_host。先分析pm8001_pci_alloc,在下一篇文章中分析scsi_scan_host
注意1:pm8001_ioremap - remap the pci high physical address to kernal virtual address so that we can access them.
pm8001_ioremap的代码如下:
pm8001_ioremap函数主要是调用ioremap将pci设备的物理地址映射到内核的逻辑地址,以便内核能够访问pci设备。
注意2:pm8001_alloc - initiate our hba structure and 6 DMAs area
pm8001_alloc的代码如下:
pm8001_alloc中首先将参数(调用实际的内存分配时使用)保存在region数组中,然后再调用pm8001_mem_alloc执行实际的内存分配。
注意3:pm8001_mem_alloc-alloc mem for pm8001
代码如下
至此,pm8001_pci_alloc函数分析结束。
后面会接着分析scsi_scan_host函数,待续。。。
先把pm8001_pci_alloc的代码贴在下面:
/** * pm8001_pci_alloc - initialize our ha card structure * @pdev: pci device. * @ent: ent * @shost: scsi host struct which has been initialized before. */static struct pm8001_hba_info *__devinitpm8001_pci_alloc(struct pci_dev *pdev, u32 chip_id, struct Scsi_Host *shost){struct pm8001_hba_info *pm8001_ha;//struct pm8001_hba_info represent HBA in lldd layerstruct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);//struct sas_ha_struct represent HBA in libsas layerpm8001_ha = sha->lldd_ha;//mem alloced in pm8001_prep_sas_ha_init with kzallocif (!pm8001_ha)return NULL; //init part of struct pm8001_hba_info pm8001_ha->pdev = pdev;pm8001_ha->dev = &pdev->dev;pm8001_ha->chip_id = chip_id;pm8001_ha->chip = &pm8001_chips[pm8001_ha->chip_id];pm8001_ha->irq = pdev->irq;pm8001_ha->sas = sha;pm8001_ha->shost = shost;pm8001_ha->id = pm8001_id++;pm8001_ha->logging_level = logging_level;pm8001_ha->ses = 0x0;sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id); //remap the pci high physical address to kernel virtual pm8001_ioremap(pm8001_ha);//注意1if (!pm8001_alloc(pm8001_ha))//注意2return pm8001_ha;pm8001_free(pm8001_ha);return NULL;}
注意1:pm8001_ioremap - remap the pci high physical address to kernal virtual address so that we can access them.
pm8001_ioremap的代码如下:
/** * pm8001_ioremap - remap the pci high physical address to kernal virtual * address so that we can access them. * @pm8001_ha:our hba structure. */static int pm8001_ioremap(struct pm8001_hba_info *pm8001_ha){u32 bar;u32 logicalBar = 0;struct pci_dev *pdev;pdev = pm8001_ha->pdev;/* map pci mem (PMC pci base 0-3)*/for (bar = 0; bar < 6; bar++) {/*** logical BARs for SPC:** bar 0 and 1 - logical BAR0** bar 2 and 3 - logical BAR1** bar4 - logical BAR2** bar5 - logical BAR3** Skip the appropriate assignments:*/if ((bar == 1) || (bar == 3))continue;if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {pm8001_ha->io_mem[logicalBar].membase =pci_resource_start(pdev, bar);pm8001_ha->io_mem[logicalBar].membase &=(u32)PCI_BASE_ADDRESS_MEM_MASK;pm8001_ha->io_mem[logicalBar].memsize =pci_resource_len(pdev, bar);pm8001_ha->io_mem[logicalBar].flags = pci_resource_flags(pdev, bar);if (pm8001_ha->io_mem[logicalBar].flags & IORESOURCE_CACHEABLE) { pm8001_ha->io_mem[logicalBar].memvirtaddr =ioremap(pm8001_ha->io_mem[logicalBar].membase,pm8001_ha->io_mem[logicalBar].memsize);}else {pm8001_ha->io_mem[logicalBar].memvirtaddr =ioremap_nocache(pm8001_ha->io_mem[logicalBar].membase,pm8001_ha->io_mem[logicalBar].memsize);}PM8001_INIT_DBG(pm8001_ha,pm8001_printk("PCI: bar %d, logicalBar %d ""virt_addr=%lx,len=%d\n", bar, logicalBar,(unsigned long)pm8001_ha->io_mem[logicalBar].memvirtaddr,pm8001_ha->io_mem[logicalBar].memsize));} else {pm8001_ha->io_mem[logicalBar].membase= 0;pm8001_ha->io_mem[logicalBar].memsize= 0;pm8001_ha->io_mem[logicalBar].memvirtaddr = 0;}logicalBar++;}return 0;}
pm8001_ioremap函数主要是调用ioremap将pci设备的物理地址映射到内核的逻辑地址,以便内核能够访问pci设备。
注意2:pm8001_alloc - initiate our hba structure and 6 DMAs area
pm8001_alloc的代码如下:
/** * pm8001_alloc - initiate our hba structure and 6 DMAs area. * @pm8001_ha:our hba structure. */static int __devinit pm8001_alloc(struct pm8001_hba_info *pm8001_ha){int i;int ccbs_count1 = 0;int ccbs_count2 = 0;int max_mem = USI_MAX_MEMCNT;spin_lock_init(&pm8001_ha->lock);for (i = 0; i < pm8001_ha->chip->n_phy; i++) {pm8001_phy_init(pm8001_ha, i);pm8001_ha->port[i].wide_port_phymap = 0;pm8001_ha->port[i].port_attached = 0;pm8001_ha->port[i].port_state = 0;}pm8001_ha->tags = kzalloc(sizeof(unsigned long) * BITS_TO_LONGS(max_ccbs), GFP_KERNEL);//alloc bitmap memif (!pm8001_ha->tags)goto err_out;pm8001_logging_size = ((pm8001_logging_size + 31) / 32) * 32;if (pm8001_logging_size < 64)pm8001_logging_size = 64;/* MPI Memory region 1 for AAP Event Log for fw */pm8001_ha->memoryMap.region[AAP1].num_elements = 1;pm8001_ha->memoryMap.region[AAP1].element_size = pm8001_logging_size;pm8001_ha->memoryMap.region[AAP1].total_len = pm8001_logging_size;pm8001_ha->memoryMap.region[AAP1].alignment = 32;/* MPI Memory region 2 for IOP Event Log for fw */pm8001_ha->memoryMap.region[IOP].num_elements = 1;pm8001_ha->memoryMap.region[IOP].element_size = pm8001_logging_size;pm8001_ha->memoryMap.region[IOP].total_len = pm8001_logging_size;pm8001_ha->memoryMap.region[IOP].alignment = 32;for(i = CI; i < (CI + PM8001_MAX_INB_NUM); i++){/* MPI Memory region 3 for consumer Index of inbound queues */pm8001_ha->memoryMap.region[i].num_elements = 1;pm8001_ha->memoryMap.region[i].element_size = 4;pm8001_ha->memoryMap.region[i].total_len = 4;pm8001_ha->memoryMap.region[i].alignment = 4;}for(i = PI; i < (PI + PM8001_MAX_OUTB_NUM); i++){/* MPI Memory region 4 for producer Index of outbound queues */pm8001_ha->memoryMap.region[i].num_elements = 1;pm8001_ha->memoryMap.region[i].element_size = 4;pm8001_ha->memoryMap.region[i].total_len = 4;pm8001_ha->memoryMap.region[i].alignment = 4;}for(i = IB; i < (IB + PM8001_MAX_INB_NUM); i++){/* MPI Memory region 5 inbound queues */pm8001_ha->memoryMap.region[i].num_elements = INBOUND_DEPTH_SIZE;pm8001_ha->memoryMap.region[i].element_size = IOMB_SIZE128;pm8001_ha->memoryMap.region[i].total_len = INBOUND_DEPTH_SIZE * IOMB_SIZE128;pm8001_ha->memoryMap.region[i].alignment = IOMB_SIZE128;}for(i = OB; i < (OB + PM8001_MAX_OUTB_NUM); i++){/* MPI Memory region 6 outbound queues */pm8001_ha->memoryMap.region[i].num_elements = OUTBOUND_DEPTH_SIZE;pm8001_ha->memoryMap.region[i].element_size = IOMB_SIZE64;pm8001_ha->memoryMap.region[i].total_len = OUTBOUND_DEPTH_SIZE * IOMB_SIZE64;pm8001_ha->memoryMap.region[i].alignment = IOMB_SIZE64;}/* Memory region write DMA*/pm8001_ha->memoryMap.region[NVMD].num_elements = 1;pm8001_ha->memoryMap.region[NVMD].element_size = 4096;pm8001_ha->memoryMap.region[NVMD].total_len = 4096;/* Memory region for devices*/pm8001_ha->memoryMap.region[DEV_MEM].num_elements = 1;pm8001_ha->memoryMap.region[DEV_MEM].element_size = PM8001_MAX_DEVICES *sizeof(struct pm8001_device);pm8001_ha->memoryMap.region[DEV_MEM].total_len = PM8001_MAX_DEVICES *sizeof(struct pm8001_device);/* Memory region for ccb_info*/if (max_ccbs > PM8001_MAX_CCB_UNIT) {//how can this hanppen??ccbs_count1 = PM8001_MAX_CCB_UNIT;ccbs_count2 = max_ccbs - ccbs_count1;} else {ccbs_count1 = max_ccbs;max_mem = max_mem -1;}pm8001_ha->memoryMap.region[CCB_MEM].num_elements = 1;pm8001_ha->memoryMap.region[CCB_MEM].element_size = ccbs_count1 *sizeof(struct pm8001_ccb_info);pm8001_ha->memoryMap.region[CCB_MEM].total_len = ccbs_count1 *sizeof(struct pm8001_ccb_info);/* Memory region for ccb_info*/pm8001_ha->memoryMap.region[CCB_MEM1].num_elements = 1;pm8001_ha->memoryMap.region[CCB_MEM1].element_size = ccbs_count2 *sizeof(struct pm8001_ccb_info);pm8001_ha->memoryMap.region[CCB_MEM1].total_len = ccbs_count2 *sizeof(struct pm8001_ccb_info); //alloc the memfor (i = 0; i < max_mem; i++) { //注意3 if (pm8001_mem_alloc(pm8001_ha->pdev,&pm8001_ha->memoryMap.region[i].virt_ptr,&pm8001_ha->memoryMap.region[i].phys_addr,&pm8001_ha->memoryMap.region[i].phys_addr_hi,&pm8001_ha->memoryMap.region[i].phys_addr_lo,pm8001_ha->memoryMap.region[i].total_len,pm8001_ha->memoryMap.region[i].alignment) != 0) {PM8001_FAIL_DBG(pm8001_ha,pm8001_printk("Mem%d alloc failed\n",i));goto err_out;}}pm8001_ha->devices = pm8001_ha->memoryMap.region[DEV_MEM].virt_ptr;for (i = 0; i < PM8001_MAX_DEVICES; i++) {pm8001_ha->devices[i].dev_type = NO_DEVICE;pm8001_ha->devices[i].sas_device = NULL;pm8001_ha->devices[i].attached_phy = 0;pm8001_ha->devices[i].id = i;pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;pm8001_ha->devices[i].dcompletion = NULL;pm8001_ha->devices[i].setds_completion = NULL;pm8001_ha->devices[i].running_req = 0;}pm8001_ha->ccb_info = pm8001_ha->memoryMap.region[CCB_MEM].virt_ptr;if (max_ccbs > PM8001_MAX_CCB_UNIT) {pm8001_ha->ccb_info1 = pm8001_ha->memoryMap.region[CCB_MEM1].virt_ptr;for (i = 0; i < ccbs_count1; i++) {pm8001_ha->ccb_info[i].ccb_dma_handle =pm8001_ha->memoryMap.region[CCB_MEM].phys_addr +i * sizeof(struct pm8001_ccb_info);pm8001_ha->ccb_info[i].task = NULL;pm8001_ha->ccb_info[i].ccb_tag = 0xffffffff;pm8001_ha->ccb_info[i].device = NULL;pm8001_ha->ccb_info[i].event_flag = 0x0;pm8001_ha->ccb_info[i].n_elem = 0x0;pm8001_ha->ccb_info[i].fw_control_context = NULL;memset(pm8001_ha->ccb_info[i].buf_prd, 0, sizeof(pm8001_ha->ccb_info[i].buf_prd));++pm8001_ha->tags_num;}for (i = 0; i < ccbs_count2; i++) {pm8001_ha->ccb_info1[i].ccb_dma_handle =pm8001_ha->memoryMap.region[CCB_MEM1].phys_addr +i * sizeof(struct pm8001_ccb_info);pm8001_ha->ccb_info1[i].task = NULL;pm8001_ha->ccb_info1[i].ccb_tag = 0xffffffff;pm8001_ha->ccb_info1[i].device = NULL;pm8001_ha->ccb_info1[i].event_flag = 0x0;pm8001_ha->ccb_info1[i].n_elem = 0x0;pm8001_ha->ccb_info1[i].fw_control_context = NULL;memset(pm8001_ha->ccb_info1[i].buf_prd, 0, sizeof(pm8001_ha->ccb_info1[i].buf_prd));++pm8001_ha->tags_num;}} else {for (i = 0; i < max_ccbs; i++) {pm8001_ha->ccb_info[i].ccb_dma_handle =pm8001_ha->memoryMap.region[CCB_MEM].phys_addr +i * sizeof(struct pm8001_ccb_info);pm8001_ha->ccb_info[i].task = NULL;pm8001_ha->ccb_info[i].ccb_tag = 0xffffffff;pm8001_ha->ccb_info[i].device = NULL;pm8001_ha->ccb_info[i].event_flag = 0x0;pm8001_ha->ccb_info[i].n_elem = 0x0;pm8001_ha->ccb_info[i].fw_control_context = NULL;memset(pm8001_ha->ccb_info[i].buf_prd, 0, sizeof(pm8001_ha->ccb_info[i].buf_prd));++pm8001_ha->tags_num;}}pm8001_ha->flags = PM8001F_INIT_TIME;/* Initialize tags */pm8001_tag_init(pm8001_ha);return 0;err_out:return 1;}
pm8001_alloc中首先将参数(调用实际的内存分配时使用)保存在region数组中,然后再调用pm8001_mem_alloc执行实际的内存分配。
注意3:pm8001_mem_alloc-alloc mem for pm8001
代码如下
/** * pm8001_mem_alloc - allocate memory for pm8001. * @pdev: pci device. * @virt_addr: the allocated virtual address * @pphys_addr_hi: the physical address high byte address. * @pphys_addr_lo: the physical address low byte address. * @mem_size: memory size. */int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,dma_addr_t *pphys_addr, u32 *pphys_addr_hi,u32 *pphys_addr_lo, u32 mem_size, u32 align){caddr_t mem_virt_alloc;dma_addr_t mem_dma_handle;u64 phys_align;u64 align_offset = 0;if (align)align_offset = (dma_addr_t)align - 1;mem_virt_alloc =pci_alloc_consistent(pdev, mem_size + align, &mem_dma_handle);if (!mem_virt_alloc) {pm8001_printk("memory allocation error\n");return -1;}memset((void *)mem_virt_alloc, 0, mem_size+align);*pphys_addr = mem_dma_handle; /*phy_align == *pphys_addr,*因为*pphys_addr的低12位为0,而align_offset<4k*/phys_align = (*pphys_addr + align_offset) & ~align_offset;*virt_addr = (void *)mem_virt_alloc + phys_align - *pphys_addr;*pphys_addr_hi = upper_32_bits(phys_align); *pphys_addr_lo = (u32)(phys_align);return 0;}
至此,pm8001_pci_alloc函数分析结束。
后面会接着分析scsi_scan_host函数,待续。。。
- pm8001_pci_probe函数分析之pm8001_pci_alloc
- pm8001_pci_probe函数分析之scsi_scan_host(一)
- pm8001_pci_probe分析(一)
- 函数之分析函数
- 分析函数之窗口函数
- 分析函数之窗口函数
- 函数分析之usb_submit_urb
- 函数分析之usb_submit_urb
- sql之分析函数
- Oracle之分析函数
- NVME driver分析之nvme_dev_start函数分析
- NVME Driver分析之nvme_dev_add函数分析
- STL 源码分析 之 rotate()函数分析
- webbench源码分析之bench函数分析
- slab函数分析之cache_grow
- slab函数分析之cache_alloc_refill
- slab函数分析之free_block
- VFS之mount函数分析
- 一个简单的Spring的AOP例子
- CIRCOS教程翻译 4.3——Label Margins
- JQuery为两个无关联对象同时指定相同操作
- android -- phone (二) 去电流程
- android 编译:classes-with-local.dex] Killed
- pm8001_pci_probe函数分析之pm8001_pci_alloc
- facebook SDK引用时出现NoClassDefFoundError和Resource R$Drawable错误
- contentprovider的学习实例总结
- xcode使用及字体设置
- 程序调试时的Log日志
- myeclipse的优化
- jsp发送email
- adb shell input 命令
- CodeIgniter集成Smarty