📄 pci.c
字号:
* resources of the device. */ for (i = 0; i <= PCI_ROM_RESOURCE; i++) { struct resource *rp = &dev->resource[i]; int flags = rp->flags; /* treat ROM as memory (should be already) */ if (i == PCI_ROM_RESOURCE) flags |= IORESOURCE_MEM; /* Active and same type? */ if ((flags & res_bit) == 0) continue; /* In the range of this resource? */ if (offset < (rp->start & PAGE_MASK) || offset > rp->end) continue; /* found it! construct the final physical address */ if (mmap_state == pci_mmap_io) offset += hose->io_base_phys - io_offset; vma->vm_pgoff = offset >> PAGE_SHIFT; return 0; } return -EINVAL;}/* * Set vm_flags of VMA, as appropriate for this architecture, for a pci device * mapping. */static __inline__ void__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state){ vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;}/* * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci * device mapping. */static __inline__ void__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine){ long prot = pgprot_val(vma->vm_page_prot); /* XXX would be nice to have a way to ask for write-through */ prot |= _PAGE_NO_CACHE; prot |= _PAGE_GUARDED; vma->vm_page_prot = __pgprot(prot);}/* * Perform the actual remap of the pages for a PCI device mapping, as * appropriate for this architecture. The region in the process to map * is described by vm_start and vm_end members of VMA, the base physical * address is found in vm_pgoff. * The pci device structure is provided so that architectures may make mapping * decisions on a per-device or per-bus basis. * * Returns a negative error code on failure, zero on success. */int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine){ int ret; ret = __pci_mmap_make_offset(dev, vma, mmap_state); if (ret < 0) return ret; __pci_mmap_set_flags(dev, vma, mmap_state); __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine); ret = remap_page_range(vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); return ret;}/* Provide information on locations of various I/O regions in physical * memory. Do this on a per-card basis so that we choose the right * root bridge. * Note that the returned IO or memory base is a physical address */longsys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn){ struct pci_controller* hose = pci_bus_to_hose(bus); long result = -EOPNOTSUPP; if (!hose) return -ENODEV; switch (which) { case IOBASE_BRIDGE_NUMBER: return (long)hose->first_busno; case IOBASE_MEMORY: return (long)hose->pci_mem_offset; case IOBASE_IO: return (long)hose->io_base_phys; case IOBASE_ISA_IO: return (long)isa_io_base; case IOBASE_ISA_MEM: return (long)isa_mem_base; } return result;}/************************************************************************//* Formats the device information and location for service. *//* - Pass in pci_dev* pointer to the device. *//* - Pass in buffer to place the data. Danger here is the buffer must *//* be as big as the client says it is. Should be at least 128 bytes.*//* Return will the length of the string data put in the buffer. *//* The brand specific method device_Location is called. *//* Format: *//* PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet *//* PCI: Bus 0, Device 26, Vendor 0x12AE Location U0.3-P1-I8 Ethernet *//* For pSeries, see the Product Topology in the RS/6000 Architecture. *//* For iSeries, see the Service Manuals. *//************************************************************************/int format_device_location(struct pci_dev* PciDev,char* BufPtr, int BufferSize){ struct device_node* DevNode = (struct device_node*)PciDev->sysdata; int LineLen = 0; if (DevNode != NULL && BufferSize >= 128) { LineLen += device_Location(PciDev,BufPtr+LineLen); LineLen += sprintf(BufPtr+LineLen," %12s",pci_class_name(PciDev->class >> 8) ); } return LineLen;}/************************************************************************ * Saves the config registers for a device. * ************************************************************************ * Note: This does byte reads so the data may appear byte swapped, * * The data returned in the pci_config_reg_save_area structure can be * * used to the restore of the data. If the save failed, the data * * will not be restore. Yes I know, you are most likey toast. * ************************************************************************/int pci_save_config_regs(struct pci_dev* PciDev,struct pci_config_reg_save_area* SaveArea){ memset(SaveArea,0x00,sizeof(struct pci_config_reg_save_area) ); SaveArea->PciDev = PciDev; SaveArea->RCode = 0; SaveArea->Register = 0; /****************************************************************** * Save All the Regs, NOTE: restore skips the first 16 bytes. * ******************************************************************/ while (SaveArea->Register < REG_SAVE_SIZE && SaveArea->RCode == 0) { SaveArea->RCode = pci_read_config_byte(PciDev, SaveArea->Register, &SaveArea->Regs[SaveArea->Register]); ++SaveArea->Register; } if (SaveArea->RCode != 0) { /* Ouch */ SaveArea->Flags = 0x80; printk("PCI: pci_restore_save_regs failed! %p\n 0x%04X",PciDev,SaveArea->RCode); PCIFR( "pci_restore_save_regs failed! %p\n 0x%04X",PciDev,SaveArea->RCode); } else { SaveArea->Flags = 0x01; } return SaveArea->RCode;}/************************************************************************ * Restores the registers saved via the save function. See the save * * function for details. * ************************************************************************/int pci_restore_config_regs(struct pci_dev* PciDev,struct pci_config_reg_save_area* SaveArea){ if (SaveArea->PciDev != PciDev || SaveArea->Flags == 0x80 || SaveArea->RCode != 0) { printk("PCI: pci_restore_config_regs failed! %p\n",PciDev); return -1; } /****************************************************************** * Don't touch the Cmd or BIST regs, user must restore those. * * Restore PCI_VENDOR_ID & PCI_DEVICE_ID * * Restore PCI_CACHE_LINE_SIZE & PCI_LATENCY_TIMER * * Restore Saved Regs from 0x10 to 0x3F * ******************************************************************/ SaveArea->Register = 0; while(SaveArea->Register < REG_SAVE_SIZE && SaveArea->RCode == 0) { SaveArea->RCode = pci_write_config_byte(PciDev,SaveArea->Register,SaveArea->Regs[SaveArea->Register]); ++SaveArea->Register; if ( SaveArea->Register == PCI_COMMAND) SaveArea->Register = PCI_CACHE_LINE_SIZE; else if (SaveArea->Register == PCI_HEADER_TYPE) SaveArea->Register = PCI_BASE_ADDRESS_0; } if (SaveArea->RCode != 0) { printk("PCI: pci_restore_config_regs failed! %p\n 0x%04X",PciDev,SaveArea->RCode); PCIFR( "pci_restore_config_regs failed! %p\n 0x%04X",PciDev,SaveArea->RCode); } return SaveArea->RCode;}/************************************************************************//* Interface to toggle the reset line *//* Time is in .1 seconds, need for seconds. *//************************************************************************/int pci_reset_device(struct pci_dev* PciDev, int AssertTime, int DelayTime){ unsigned long AssertDelay, WaitDelay; int RtnCode; /******************************************************************** * Set defaults, Assert is .5 second, Wait is 3 seconds. ********************************************************************/ if (AssertTime == 0) AssertDelay = ( 5 * HZ)/10; else AssertDelay = (AssertTime*HZ)/10; if (WaitDelay == 0) WaitDelay = (30 * HZ)/10; else WaitDelay = (DelayTime* HZ)/10; /******************************************************************** * Assert reset, wait, de-assert reset, wait for IOA to reset. * - Don't waste the CPU time on jiffies. ********************************************************************/ RtnCode = pci_set_reset(PciDev,1); if (RtnCode == 0) { set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(AssertDelay); /* Sleep for the time */ RtnCode = pci_set_reset(PciDev,0); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(WaitDelay); } if (RtnCode == 0) { PCIFR( "Bus%3d, Device%3d, Reset\n",PciDev->bus->number,PCI_SLOT(PciDev->devfn) ); } else { printk("PCI: Bus%3d, Device%3d, Reset Failed:0x%04X\n",PciDev->bus->number,PCI_SLOT(PciDev->devfn),RtnCode ); PCIFR( "Bus%3d, Device%3d, Reset Failed:0x%04X\n",PciDev->bus->number,PCI_SLOT(PciDev->devfn),RtnCode ); } return RtnCode;}/***************************************************** * Dump Resource information *****************************************************/void dumpResources(struct resource* Resource){ if(Resource != NULL) { int Flags = 0x00000F00 & Resource->flags; if(Resource->start == 0 && Resource->end == 0) return; else if(Resource->start == Resource->end ) return; else { if (Flags == IORESOURCE_IO) udbg_printf("IO.:"); else if(Flags == IORESOURCE_MEM) udbg_printf("MEM:"); else if(Flags == IORESOURCE_IRQ) udbg_printf("IRQ:"); else udbg_printf("0x%02X:",Resource->flags); } udbg_printf("0x%016LX / 0x%016LX (0x%08X)\n", Resource->start, Resource->end, Resource->end - Resource->start); }}int resourceSize(struct resource* Resource){ if(Resource->start == 0 && Resource->end == 0) return 0; else if(Resource->start == Resource->end ) return 0; else return (Resource->end-1)-Resource->start;}/***************************************************** * Dump PHB information for Debug *****************************************************/void dumpPci_Controller(struct pci_controller* phb){ udbg_printf("\tpci_controller= 0x%016LX\n", phb); if (phb != NULL) { udbg_printf("\twhat & type = %s 0x%02X\n ",phb->what,phb->type); udbg_printf("\tbus = "); if (phb->bus != NULL) udbg_printf("0x%02X\n", phb->bus->number); else udbg_printf("<NULL>\n"); udbg_printf("\tarch_data = 0x%016LX\n", phb->arch_data); udbg_printf("\tfirst_busno = 0x%02X\n", phb->first_busno); udbg_printf("\tlast_busno = 0x%02X\n", phb->last_busno); udbg_printf("\tio_base_virt* = 0x%016LX\n", phb->io_base_virt); udbg_printf("\tio_base_phys = 0x%016LX\n", phb->io_base_phys); udbg_printf("\tpci_mem_offset= 0x%016LX\n", phb->pci_mem_offset); udbg_printf("\tpci_io_offset = 0x%016LX\n", phb->pci_io_offset); udbg_printf("\tcfg_addr = 0x%016LX\n", phb->cfg_addr); udbg_printf("\tcfg_data = 0x%016LX\n", phb->cfg_data); udbg_printf("\tphb_regs = 0x%016LX\n", phb->phb_regs); udbg_printf("\tchip_regs = 0x%016LX\n", phb->chip_regs); udbg_printf("\tResources\n"); dumpResources(&phb->io_resource); if (phb->mem_resource_count > 0) dumpResources(&phb->mem_resources[0]); if (phb->mem_resource_count > 1) dumpResources(&phb->mem_resources[1]); if (phb->mem_resource_count > 2) dumpResources(&phb->mem_resources[2]); udbg_printf("\tglobal_num = 0x%02X\n", phb->global_number); udbg_printf("\tlocal_num = 0x%02X\n", phb->local_number); }}/***************************************************** * Dump PHB information for Debug *****************************************************/void dumpPci_Bus(struct pci_bus* Pci_Bus){ int i; udbg_printf("\tpci_bus = 0x%016LX \n",Pci_Bus); if (Pci_Bus != NULL) { udbg_printf("\tnumber = 0x%02X \n",Pci_Bus->number); udbg_printf("\tprimary = 0x%02X \n",Pci_Bus->primary); udbg_printf("\tsecondary = 0x%02X \n",Pci_Bus->secondary); udbg_printf("\tsubordinate = 0x%02X \n",Pci_Bus->subordinate); for (i=0;i<4;++i) { if(Pci_Bus->resource[i] == NULL) continue; if(Pci_Bus->resource[i]->start == 0 && Pci_Bus->resource[i]->end == 0) break; udbg_printf("\tResources[%d]",i); dumpResources(Pci_Bus->resource[i]); } }}/***************************************************** * Dump Device information for Debug *****************************************************/void dumpPci_Dev(struct pci_dev* Pci_Dev){ int i; udbg_printf("\tpci_dev* = 0x%p\n",Pci_Dev); if ( Pci_Dev == NULL ) return; udbg_printf("\tname = %s \n",Pci_Dev->name); udbg_printf("\tbus* = 0x%p\n",Pci_Dev->bus); udbg_printf("\tsysdata* = 0x%p\n",Pci_Dev->sysdata); udbg_printf("\tDevice = 0x%4X%02X:%02X.%02X 0x%04X:%04X\n", PCI_GET_PHB_NUMBER(Pci_Dev), PCI_GET_BUS_NUMBER(Pci_Dev), PCI_SLOT(Pci_Dev->devfn), PCI_FUNC(Pci_Dev->devfn), Pci_Dev->vendor, Pci_Dev->device); udbg_printf("\tHdr/Irq = 0x%02X/0x%02X \n",Pci_Dev->hdr_type,Pci_Dev->irq); for (i=0;i<DEVICE_COUNT_RESOURCE;++i) { if (Pci_Dev->resource[i].start == 0 && Pci_Dev->resource[i].end == 0) continue; udbg_printf("\tResources[%d] ",i); dumpResources(&Pci_Dev->resource[i]); } dumpResources(&Pci_Dev->resource[i]);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -