⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (ppc_md.pcibios_enable_device_hook(dev, 0))			return -EINVAL;			pci_read_config_word(dev, PCI_COMMAND, &cmd);	old_cmd = cmd;	for (idx=0; idx<6; idx++) {		r = &dev->resource[idx];		if (r->flags & IORESOURCE_UNSET) {			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));			return -EINVAL;		}		if (r->flags & IORESOURCE_IO)			cmd |= PCI_COMMAND_IO;		if (r->flags & IORESOURCE_MEM)			cmd |= PCI_COMMAND_MEMORY;	}	if (cmd != old_cmd) {		printk("PCI: Enabling device %s (%04x -> %04x)\n",		       pci_name(dev), old_cmd, cmd);		pci_write_config_word(dev, PCI_COMMAND, cmd);	}	return 0;}struct pci_controller*pci_bus_to_hose(int bus){	struct pci_controller* hose = hose_head;	for (; hose; hose = hose->next)		if (bus >= hose->first_busno && bus <= hose->last_busno)			return hose;	return NULL;}void __iomem *pci_bus_io_base(unsigned int bus){	struct pci_controller *hose;	hose = pci_bus_to_hose(bus);	if (!hose)		return NULL;	return hose->io_base_virt;}unsigned longpci_bus_io_base_phys(unsigned int bus){	struct pci_controller *hose;	hose = pci_bus_to_hose(bus);	if (!hose)		return 0;	return hose->io_base_phys;}unsigned longpci_bus_mem_base_phys(unsigned int bus){	struct pci_controller *hose;	hose = pci_bus_to_hose(bus);	if (!hose)		return 0;	return hose->pci_mem_offset;}unsigned longpci_resource_to_bus(struct pci_dev *pdev, struct resource *res){	/* Hack alert again ! See comments in chrp_pci.c	 */	struct pci_controller* hose =		(struct pci_controller *)pdev->sysdata;	if (hose && res->flags & IORESOURCE_MEM)		return res->start - hose->pci_mem_offset;	/* We may want to do something with IOs here... */	return res->start;}static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,					       unsigned long *offset,					       enum pci_mmap_state mmap_state){	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);	unsigned long io_offset = 0;	int i, res_bit;	if (hose == 0)		return NULL;		/* should never happen */	/* If memory, add on the PCI bridge address offset */	if (mmap_state == pci_mmap_mem) {		*offset += hose->pci_mem_offset;		res_bit = IORESOURCE_MEM;	} else {		io_offset = hose->io_base_virt - ___IO_BASE;		*offset += io_offset;		res_bit = IORESOURCE_IO;	}	/*	 * Check that the offset requested corresponds to one of the	 * 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;		return rp;	}	return NULL;}/* * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci * device mapping. */static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp,				      pgprot_t protection,				      enum pci_mmap_state mmap_state,				      int write_combine){	unsigned long prot = pgprot_val(protection);	/* Write combine is always 0 on non-memory space mappings. On	 * memory space, if the user didn't pass 1, we check for a	 * "prefetchable" resource. This is a bit hackish, but we use	 * this to workaround the inability of /sysfs to provide a write	 * combine bit	 */	if (mmap_state != pci_mmap_mem)		write_combine = 0;	else if (write_combine == 0) {		if (rp->flags & IORESOURCE_PREFETCH)			write_combine = 1;	}	/* XXX would be nice to have a way to ask for write-through */	prot |= _PAGE_NO_CACHE;	if (write_combine)		prot &= ~_PAGE_GUARDED;	else		prot |= _PAGE_GUARDED;	printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,	       prot);	return __pgprot(prot);}/* * This one is used by /dev/mem and fbdev who have no clue about the * PCI device, it tries to find the PCI device first and calls the * above routine */pgprot_t pci_phys_mem_access_prot(struct file *file,				  unsigned long offset,				  unsigned long size,				  pgprot_t protection){	struct pci_dev *pdev = NULL;	struct resource *found = NULL;	unsigned long prot = pgprot_val(protection);	int i;	if (page_is_ram(offset >> PAGE_SHIFT))		return prot;	prot |= _PAGE_NO_CACHE | _PAGE_GUARDED;	for_each_pci_dev(pdev) {		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {			struct resource *rp = &pdev->resource[i];			int flags = rp->flags;			/* Active and same type? */			if ((flags & IORESOURCE_MEM) == 0)				continue;			/* In the range of this resource? */			if (offset < (rp->start & PAGE_MASK) ||			    offset > rp->end)				continue;			found = rp;			break;		}		if (found)			break;	}	if (found) {		if (found->flags & IORESOURCE_PREFETCH)			prot &= ~_PAGE_GUARDED;		pci_dev_put(pdev);	}	DBG("non-PCI map for %lx, prot: %lx\n", offset, prot);	return __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){	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;	struct resource *rp;	int ret;	rp = __pci_mmap_make_offset(dev, &offset, mmap_state);	if (rp == NULL)		return -EINVAL;	vma->vm_pgoff = offset >> PAGE_SHIFT;	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,						  vma->vm_page_prot,						  mmap_state, write_combine);	ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,			       vma->vm_end - vma->vm_start, vma->vm_page_prot);	return ret;}/* Obsolete functions. Should be removed once the symbios driver * is fixed */unsigned longphys_to_bus(unsigned long pa){	struct pci_controller *hose;	int i;	for (hose = hose_head; hose; hose = hose->next) {		for (i = 0; i < 3; ++i) {			if (pa >= hose->mem_resources[i].start			    && pa <= hose->mem_resources[i].end) {				/*				 * XXX the hose->pci_mem_offset really				 * only applies to mem_resources[0].				 * We need a way to store an offset for				 * the others.  -- paulus				 */				if (i == 0)					pa -= hose->pci_mem_offset;				return pa;			}		}	}	/* hmmm, didn't find it */	return 0;}unsigned longpci_phys_to_bus(unsigned long pa, int busnr){	struct pci_controller* hose = pci_bus_to_hose(busnr);	if (!hose)		return pa;	return pa - hose->pci_mem_offset;}unsigned longpci_bus_to_phys(unsigned int ba, int busnr){	struct pci_controller* hose = pci_bus_to_hose(busnr);	if (!hose)		return ba;	return ba + hose->pci_mem_offset;}/* 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 */long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn){	struct pci_controller* hose;	long result = -EOPNOTSUPP;	/* Argh ! Please forgive me for that hack, but that's the	 * simplest way to get existing XFree to not lockup on some	 * G5 machines... So when something asks for bus 0 io base	 * (bus 0 is HT root), we return the AGP one instead.	 */#ifdef CONFIG_PPC_PMAC	if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4"))		if (bus == 0)			bus = 0xf0;#endif /* CONFIG_PPC_PMAC */	hose = pci_bus_to_hose(bus);	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;}void pci_resource_to_user(const struct pci_dev *dev, int bar,			  const struct resource *rsrc,			  u64 *start, u64 *end){	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);	unsigned long offset = 0;	if (hose == NULL)		return;	if (rsrc->flags & IORESOURCE_IO)		offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;	*start = rsrc->start + offset;	*end = rsrc->end + offset;}void __initpci_init_resource(struct resource *res, unsigned long start, unsigned long end,		  int flags, char *name){	res->start = start;	res->end = end;	res->flags = flags;	res->name = name;	res->parent = NULL;	res->sibling = NULL;	res->child = NULL;}void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max){	unsigned long start = pci_resource_start(dev, bar);	unsigned long len = pci_resource_len(dev, bar);	unsigned long flags = pci_resource_flags(dev, bar);	if (!len)		return NULL;	if (max && len > max)		len = max;	if (flags & IORESOURCE_IO)		return ioport_map(start, len);	if (flags & IORESOURCE_MEM)		/* Not checking IORESOURCE_CACHEABLE because PPC does		 * not currently distinguish between ioremap and		 * ioremap_nocache.		 */		return ioremap(start, len);	/* What? */	return NULL;}void pci_iounmap(struct pci_dev *dev, void __iomem *addr){	/* Nothing to do */}EXPORT_SYMBOL(pci_iomap);EXPORT_SYMBOL(pci_iounmap);/* * Null PCI config access functions, for the case when we can't * find a hose. */#define NULL_PCI_OP(rw, size, type)					\static int								\null_##rw##_config_##size(struct pci_dev *dev, int offset, type val)	\{									\	return PCIBIOS_DEVICE_NOT_FOUND;    				\}static intnull_read_config(struct pci_bus *bus, unsigned int devfn, int offset,		 int len, u32 *val){	return PCIBIOS_DEVICE_NOT_FOUND;}static intnull_write_config(struct pci_bus *bus, unsigned int devfn, int offset,		  int len, u32 val){	return PCIBIOS_DEVICE_NOT_FOUND;}static struct pci_ops null_pci_ops ={	null_read_config,	null_write_config};/* * These functions are used early on before PCI scanning is done * and all of the pci_dev and pci_bus structures have been created. */static struct pci_bus *fake_pci_bus(struct pci_controller *hose, int busnr){	static struct pci_bus bus;	if (hose == 0) {		hose = pci_bus_to_hose(busnr);		if (hose == 0)			printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);	}	bus.number = busnr;	bus.sysdata = hose;	bus.ops = hose? hose->ops: &null_pci_ops;	return &bus;}#define EARLY_PCI_OP(rw, size, type)					\int early_##rw##_config_##size(struct pci_controller *hose, int bus,	\			       int devfn, int offset, type value)	\{									\	return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus),	\					    devfn, offset, value);	\}EARLY_PCI_OP(read, byte, u8 *)EARLY_PCI_OP(read, word, u16 *)EARLY_PCI_OP(read, dword, u32 *)EARLY_PCI_OP(write, byte, u8)EARLY_PCI_OP(write, word, u16)EARLY_PCI_OP(write, dword, u32)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -