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

📄 pci.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
{	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;	unsigned long io_offset;	struct resource *res;	int i;	io_offset = (unsigned long)hose->io_base_virt - isa_io_base;	if (bus->parent == NULL) {		/* This is a host bridge - fill in its resources */		hose->bus = bus;		bus->resource[0] = res = &hose->io_resource;		if (!res->flags) {			if (io_offset)				printk(KERN_ERR "I/O resource not set for host"				       " bridge %d\n", hose->index);			res->start = 0;			res->end = IO_SPACE_LIMIT;			res->flags = IORESOURCE_IO;		}		res->start += io_offset;		res->end += io_offset;		for (i = 0; i < 3; ++i) {			res = &hose->mem_resources[i];			if (!res->flags) {				if (i > 0)					continue;				printk(KERN_ERR "Memory resource not set for "				       "host bridge %d\n", hose->index);				res->start = hose->pci_mem_offset;				res->end = ~0U;				res->flags = IORESOURCE_MEM;			}			bus->resource[i+1] = res;		}	} else {		/* This is a subordinate bridge */		pci_read_bridge_bases(bus);		for (i = 0; i < 4; ++i) {			if ((res = bus->resource[i]) == NULL)				continue;			if (!res->flags)				continue;			if (io_offset && (res->flags & IORESOURCE_IO)) {				res->start += io_offset;				res->end += io_offset;			} else if (hose->pci_mem_offset				   && (res->flags & IORESOURCE_MEM)) {				res->start += hose->pci_mem_offset;				res->end += hose->pci_mem_offset;			}		}	}	if (ppc_md.pcibios_fixup_bus)		ppc_md.pcibios_fixup_bus(bus);}char __init *pcibios_setup(char *str){	return str;}/* the next one is stolen from the alpha port... */void __initpcibios_update_irq(struct pci_dev *dev, int irq){	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);	/* XXX FIXME - update OF device tree node interrupt property */}int pcibios_enable_device(struct pci_dev *dev, int mask){	u16 cmd, old_cmd;	int idx;	struct resource *r;	if (ppc_md.pcibios_enable_device_hook)		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*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;}/* * Platform support for /proc/bus/pci/X/Y mmap()s, * modelled on the sparc64 implementation by Dave Miller. *  -- paulus. *//* * Adjust vm_pgoff of VMA such that it is the physical page offset * corresponding to the 32-bit pci bus offset for DEV requested by the user. * * Basically, the user finds the base address for his device which he wishes * to mmap.  They read the 32-bit value from the config space base register, * add whatever PAGE_SIZE multiple offset they wish, and feed this into the * offset parameter of mmap on /proc/bus/pci/XXX for that device. * * Returns negative error code on failure, zero on success. */static __inline__ int__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,		       enum pci_mmap_state mmap_state){	struct pci_controller *hose = (struct pci_controller *) dev->sysdata;	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;	unsigned long size = vma->vm_end - vma->vm_start;	unsigned long base;	struct resource *res;	int i;	int ret = -EINVAL;	if (hose == 0)		return -EINVAL;		/* should never happen */	if (offset + size <= offset)		return -EINVAL;	if (mmap_state == pci_mmap_mem) {		/* PCI memory space */		base = hose->pci_mem_offset;		for (i = 0; i < 3; ++i) {			res = &hose->mem_resources[i];			if (res->flags == 0)				continue;			if (offset >= res->start - base			    && offset + size - 1 <= res->end - base) {				ret = 0;				break;			}		}		offset += hose->pci_mem_offset;	} else {		/* PCI I/O space */		base = (unsigned long)hose->io_base_virt - isa_io_base;		res = &hose->io_resource;		if (offset >= res->start - base		    && offset + size - 1 <= res->end - base)			ret = 0;		offset += hose->io_base_phys;	}	vma->vm_pgoff = offset >> PAGE_SHIFT;	return ret;}/* * 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){	int prot = pgprot_val(vma->vm_page_prot);	/* XXX would be nice to have a way to ask for write-through */	prot |= _PAGE_NO_CACHE;	if (!write_combine)		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, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,			       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 __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;}/* * 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 + -