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

📄 pci.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal * else, data is returned in Big Endian format. */static u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress){	u64 BarOffset;	u64 dsa;	int retry = 0;	struct HvCallPci_LoadReturn ret;	struct device_node *DevNode =		xlate_iomm_address(IoAddress, &dsa, &BarOffset);	if (DevNode == NULL) {		static unsigned long last_jiffies;		static int num_printed;		if ((jiffies - last_jiffies) > 60 * HZ) {			last_jiffies = jiffies;			num_printed = 0;		}		if (num_printed++ < 10)			printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n",			       IoAddress);		return 0xff;	}	do {		HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);	} while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);	return ret.value;}static u16 iSeries_Read_Word(const volatile void __iomem *IoAddress){	u64 BarOffset;	u64 dsa;	int retry = 0;	struct HvCallPci_LoadReturn ret;	struct device_node *DevNode =		xlate_iomm_address(IoAddress, &dsa, &BarOffset);	if (DevNode == NULL) {		static unsigned long last_jiffies;		static int num_printed;		if ((jiffies - last_jiffies) > 60 * HZ) {			last_jiffies = jiffies;			num_printed = 0;		}		if (num_printed++ < 10)			printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n",			       IoAddress);		return 0xffff;	}	do {		HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,				BarOffset, 0);	} while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);	return ret.value;}static u32 iSeries_Read_Long(const volatile void __iomem *IoAddress){	u64 BarOffset;	u64 dsa;	int retry = 0;	struct HvCallPci_LoadReturn ret;	struct device_node *DevNode =		xlate_iomm_address(IoAddress, &dsa, &BarOffset);	if (DevNode == NULL) {		static unsigned long last_jiffies;		static int num_printed;		if ((jiffies - last_jiffies) > 60 * HZ) {			last_jiffies = jiffies;			num_printed = 0;		}		if (num_printed++ < 10)			printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n",			       IoAddress);		return 0xffffffff;	}	do {		HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,				BarOffset, 0);	} while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);	return ret.value;}/* * Write MM I/O Instructions for the iSeries * */static void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress){	u64 BarOffset;	u64 dsa;	int retry = 0;	u64 rc;	struct device_node *DevNode =		xlate_iomm_address(IoAddress, &dsa, &BarOffset);	if (DevNode == NULL) {		static unsigned long last_jiffies;		static int num_printed;		if ((jiffies - last_jiffies) > 60 * HZ) {			last_jiffies = jiffies;			num_printed = 0;		}		if (num_printed++ < 10)			printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress);		return;	}	do {		rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);	} while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);}static void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress){	u64 BarOffset;	u64 dsa;	int retry = 0;	u64 rc;	struct device_node *DevNode =		xlate_iomm_address(IoAddress, &dsa, &BarOffset);	if (DevNode == NULL) {		static unsigned long last_jiffies;		static int num_printed;		if ((jiffies - last_jiffies) > 60 * HZ) {			last_jiffies = jiffies;			num_printed = 0;		}		if (num_printed++ < 10)			printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n",			       IoAddress);		return;	}	do {		rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, data, 0);	} while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);}static void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress){	u64 BarOffset;	u64 dsa;	int retry = 0;	u64 rc;	struct device_node *DevNode =		xlate_iomm_address(IoAddress, &dsa, &BarOffset);	if (DevNode == NULL) {		static unsigned long last_jiffies;		static int num_printed;		if ((jiffies - last_jiffies) > 60 * HZ) {			last_jiffies = jiffies;			num_printed = 0;		}		if (num_printed++ < 10)			printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n",			       IoAddress);		return;	}	do {		rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, data, 0);	} while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);}static u8 iseries_readb(const volatile void __iomem *addr){	return iSeries_Read_Byte(addr);}static u16 iseries_readw(const volatile void __iomem *addr){	return le16_to_cpu(iSeries_Read_Word(addr));}static u32 iseries_readl(const volatile void __iomem *addr){	return le32_to_cpu(iSeries_Read_Long(addr));}static u16 iseries_readw_be(const volatile void __iomem *addr){	return iSeries_Read_Word(addr);}static u32 iseries_readl_be(const volatile void __iomem *addr){	return iSeries_Read_Long(addr);}static void iseries_writeb(u8 data, volatile void __iomem *addr){	iSeries_Write_Byte(data, addr);}static void iseries_writew(u16 data, volatile void __iomem *addr){	iSeries_Write_Word(cpu_to_le16(data), addr);}static void iseries_writel(u32 data, volatile void __iomem *addr){	iSeries_Write_Long(cpu_to_le32(data), addr);}static void iseries_writew_be(u16 data, volatile void __iomem *addr){	iSeries_Write_Word(data, addr);}static void iseries_writel_be(u32 data, volatile void __iomem *addr){	iSeries_Write_Long(data, addr);}static void iseries_readsb(const volatile void __iomem *addr, void *buf,			   unsigned long count){	u8 *dst = buf;	while(count-- > 0)		*(dst++) = iSeries_Read_Byte(addr);}static void iseries_readsw(const volatile void __iomem *addr, void *buf,			   unsigned long count){	u16 *dst = buf;	while(count-- > 0)		*(dst++) = iSeries_Read_Word(addr);}static void iseries_readsl(const volatile void __iomem *addr, void *buf,			   unsigned long count){	u32 *dst = buf;	while(count-- > 0)		*(dst++) = iSeries_Read_Long(addr);}static void iseries_writesb(volatile void __iomem *addr, const void *buf,			    unsigned long count){	const u8 *src = buf;	while(count-- > 0)		iSeries_Write_Byte(*(src++), addr);}static void iseries_writesw(volatile void __iomem *addr, const void *buf,			    unsigned long count){	const u16 *src = buf;	while(count-- > 0)		iSeries_Write_Word(*(src++), addr);}static void iseries_writesl(volatile void __iomem *addr, const void *buf,			    unsigned long count){	const u32 *src = buf;	while(count-- > 0)		iSeries_Write_Long(*(src++), addr);}static void iseries_memset_io(volatile void __iomem *addr, int c,			      unsigned long n){	volatile char __iomem *d = addr;	while (n-- > 0)		iSeries_Write_Byte(c, d++);}static void iseries_memcpy_fromio(void *dest, const volatile void __iomem *src,				  unsigned long n){	char *d = dest;	const volatile char __iomem *s = src;	while (n-- > 0)		*d++ = iSeries_Read_Byte(s++);}static void iseries_memcpy_toio(volatile void __iomem *dest, const void *src,				unsigned long n){	const char *s = src;	volatile char __iomem *d = dest;	while (n-- > 0)		iSeries_Write_Byte(*s++, d++);}/* We only set MMIO ops. The default PIO ops will be default * to the MMIO ops + pci_io_base which is 0 on iSeries as * expected so both should work. * * Note that we don't implement the readq/writeq versions as * I don't know of an HV call for doing so. Thus, the default * operation will be used instead, which will fault a the value * return by iSeries for MMIO addresses always hits a non mapped * area. This is as good as the BUG() we used to have there. */static struct ppc_pci_io __initdata iseries_pci_io = {	.readb = iseries_readb,	.readw = iseries_readw,	.readl = iseries_readl,	.readw_be = iseries_readw_be,	.readl_be = iseries_readl_be,	.writeb = iseries_writeb,	.writew = iseries_writew,	.writel = iseries_writel,	.writew_be = iseries_writew_be,	.writel_be = iseries_writel_be,	.readsb = iseries_readsb,	.readsw = iseries_readsw,	.readsl = iseries_readsl,	.writesb = iseries_writesb,	.writesw = iseries_writesw,	.writesl = iseries_writesl,	.memset_io = iseries_memset_io,	.memcpy_fromio = iseries_memcpy_fromio,	.memcpy_toio = iseries_memcpy_toio,};/* * iSeries_pcibios_init * * Description: *   This function checks for all possible system PCI host bridges that connect *   PCI buses.  The system hypervisor is queried as to the guest partition *   ownership status.  A pci_controller is built for any bus which is partially *   owned or fully owned by this guest partition. */void __init iSeries_pcibios_init(void){	struct pci_controller *phb;	struct device_node *root = of_find_node_by_path("/");	struct device_node *node = NULL;	/* Install IO hooks */	ppc_pci_io = iseries_pci_io;	/* iSeries has no IO space in the common sense, it needs to set	 * the IO base to 0	 */	pci_io_base = 0;	if (root == NULL) {		printk(KERN_CRIT "iSeries_pcibios_init: can't find root "				"of device tree\n");		return;	}	while ((node = of_get_next_child(root, node)) != NULL) {		HvBusNumber bus;		const u32 *busp;		if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))			continue;		busp = of_get_property(node, "bus-range", NULL);		if (busp == NULL)			continue;		bus = *busp;		printk("bus %d appears to exist\n", bus);		phb = pcibios_alloc_controller(node);		if (phb == NULL)			continue;		phb->pci_mem_offset = bus;		phb->first_busno = bus;		phb->last_busno = bus;		phb->ops = &iSeries_pci_ops;	}	of_node_put(root);	pci_devs_phb_init();}

⌨️ 快捷键说明

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