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

📄 hpzx1_misc.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Misc. support for HP zx1 chipset support * * Copyright (C) 2002 Hewlett-Packard Co * Copyright (C) 2002 Alex Williamson <alex_williamson@hp.com> * Copyright (C) 2002 Bjorn Helgaas <bjorn_helgaas@hp.com> */#include <linux/config.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/pci.h>#include <linux/acpi.h>#include <asm/iosapic.h>#include <asm/efi.h>#include "../drivers/acpi/include/platform/acgcc.h"#include "../drivers/acpi/include/actypes.h"#include "../drivers/acpi/include/acexcep.h"#include "../drivers/acpi/include/acpixf.h"#include "../drivers/acpi/include/actbl.h"#include "../drivers/acpi/include/acconfig.h"#include "../drivers/acpi/include/acmacros.h"#include "../drivers/acpi/include/aclocal.h"#include "../drivers/acpi/include/acobject.h"#include "../drivers/acpi/include/acstruct.h"#include "../drivers/acpi/include/acnamesp.h"#include "../drivers/acpi/include/acutils.h"#define PFX "hpzx1: "struct fake_pci_dev {	struct fake_pci_dev *next;	unsigned char bus;	unsigned int devfn;	int sizing;		// in middle of BAR sizing operation?	unsigned long csr_base;	unsigned int csr_size;	unsigned long mapped_csrs;	// ioremapped};static struct fake_pci_dev *fake_pci_head, **fake_pci_tail = &fake_pci_head;static struct pci_ops orig_pci_ops;static inline struct fake_pci_dev *fake_pci_find_slot(unsigned char bus, unsigned int devfn){	struct fake_pci_dev *dev;	for (dev = fake_pci_head; dev; dev = dev->next)		if (dev->bus == bus && dev->devfn == devfn)			return dev;	return NULL;}static struct fake_pci_dev *alloc_fake_pci_dev(void){        struct fake_pci_dev *dev;        dev = kmalloc(sizeof(*dev), GFP_KERNEL);	if (!dev)		return NULL;	memset(dev, 0, sizeof(*dev));        *fake_pci_tail = dev;        fake_pci_tail = &dev->next;        return dev;}#define HP_CFG_RD(sz, bits, name) \static int hp_cfg_read##sz (struct pci_dev *dev, int where, u##bits *value) \{ \	struct fake_pci_dev *fake_dev; \	if (!(fake_dev = fake_pci_find_slot(dev->bus->number, dev->devfn))) \		return orig_pci_ops.name(dev, where, value); \	\	switch (where) { \	case PCI_COMMAND: \		*value = read##sz(fake_dev->mapped_csrs + where); \		*value |= PCI_COMMAND_MEMORY; /* SBA omits this */ \		break; \	case PCI_BASE_ADDRESS_0: \		if (fake_dev->sizing) \			*value = ~(fake_dev->csr_size - 1); \		else \			*value = (fake_dev->csr_base & \				    PCI_BASE_ADDRESS_MEM_MASK) | \				PCI_BASE_ADDRESS_SPACE_MEMORY; \		fake_dev->sizing = 0; \		break; \	default: \		*value = read##sz(fake_dev->mapped_csrs + where); \		break; \	} \	return PCIBIOS_SUCCESSFUL; \}#define HP_CFG_WR(sz, bits, name) \static int hp_cfg_write##sz (struct pci_dev *dev, int where, u##bits value) \{ \	struct fake_pci_dev *fake_dev; \	if (!(fake_dev = fake_pci_find_slot(dev->bus->number, dev->devfn))) \		return orig_pci_ops.name(dev, where, value); \	\	switch (where) { \	case PCI_BASE_ADDRESS_0: \		if (value == ~0) \			fake_dev->sizing = 1; \		break; \	default: \		write##sz(value, fake_dev->mapped_csrs + where); \		break; \	} \	return PCIBIOS_SUCCESSFUL; \}HP_CFG_RD(b,  8, read_byte)HP_CFG_RD(w, 16, read_word)HP_CFG_RD(l, 32, read_dword)HP_CFG_WR(b,  8, write_byte)HP_CFG_WR(w, 16, write_word)HP_CFG_WR(l, 32, write_dword)static struct pci_ops hp_pci_conf = {	hp_cfg_readb,	hp_cfg_readw,	hp_cfg_readl,	hp_cfg_writeb,	hp_cfg_writew,	hp_cfg_writel,};/* * Assume we'll never have a physical slot higher than 0x10, so we can * use slots above that for "fake" PCI devices to represent things * that only show up in the ACPI namespace. */#define HP_MAX_SLOT	0x10static struct fake_pci_dev *hpzx1_fake_pci_dev(unsigned long addr, unsigned int bus, unsigned int size){	struct fake_pci_dev *dev;	int slot;	// Note: lspci thinks 0x1f is invalid	for (slot = 0x1e; slot > HP_MAX_SLOT; slot--) {		if (!fake_pci_find_slot(bus, PCI_DEVFN(slot, 0)))			break;	}	if (slot == HP_MAX_SLOT) {		printk(KERN_ERR PFX			"no slot space for device (0x%p) on bus 0x%02x\n",			(void *) addr, bus);		return NULL;	}	dev = alloc_fake_pci_dev();	if (!dev) {		printk(KERN_ERR PFX			"no memory for device (0x%p) on bus 0x%02x\n",			(void *) addr, bus);		return NULL;	}	dev->bus = bus;	dev->devfn = PCI_DEVFN(slot, 0);	dev->csr_base = addr;	dev->csr_size = size;	/*	 * Drivers should ioremap what they need, but we have to do	 * it here, too, so PCI config accesses work.	 */	dev->mapped_csrs = ioremap(dev->csr_base, dev->csr_size);	return dev;}typedef struct {	u8	guid_id;	u8	guid[16];	u8	csr_base[8];	u8	csr_length[8];} acpi_hp_vendor_long;#define HP_CCSR_LENGTH 0x21#define HP_CCSR_TYPE 0x2#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f,			\			      0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)extern acpi_status acpi_get_crs(acpi_handle, acpi_buffer *);extern acpi_resource *acpi_get_crs_next(acpi_buffer *, int *);extern acpi_resource_data *acpi_get_crs_type(acpi_buffer *, int *, int);extern void acpi_dispose_crs(acpi_buffer *);extern acpi_status acpi_cf_evaluate_method(acpi_handle, UINT8 *, NATIVE_UINT *);static acpi_statushp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length){	int i, offset = 0;	acpi_status status;	acpi_buffer buf;	acpi_resource_vendor *res;	acpi_hp_vendor_long *hp_res;	efi_guid_t vendor_guid;	*csr_base = 0;	*csr_length = 0;	status = acpi_get_crs(obj, &buf);	if (status != AE_OK) {		printk(KERN_ERR PFX "Unable to get _CRS data on object\n");		return status;	}	res = (acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR);	if (!res) {		printk(KERN_ERR PFX "Failed to find config space for device\n");		acpi_dispose_crs(&buf);		return AE_NOT_FOUND;	}	hp_res = (acpi_hp_vendor_long *)(res->reserved);	if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) {		printk(KERN_ERR PFX "Unknown Vendor data\n");		acpi_dispose_crs(&buf);		return AE_TYPE; /* Revisit error? */	}	memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t));	if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) {		printk(KERN_ERR PFX "Vendor GUID does not match\n");		acpi_dispose_crs(&buf);		return AE_TYPE; /* Revisit error? */	}	for (i = 0 ; i < 8 ; i++) {		*csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8));		*csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8));	}	acpi_dispose_crs(&buf);	return AE_OK;}static acpi_statushpzx1_sba_probe(acpi_handle obj, u32 depth, void *context, void **ret){	u64 csr_base = 0, csr_length = 0;	char *name = context;	struct fake_pci_dev *dev;	acpi_status status;	status = hp_csr_space(obj, &csr_base, &csr_length);	if (status != AE_OK)		return status;	/*	 * Only SBA shows up in ACPI namespace, so its CSR space	 * includes both SBA and IOC.  Make SBA and IOC show up	 * separately in PCI space.	 */	if ((dev = hpzx1_fake_pci_dev(csr_base, 0, 0x1000)))		printk(KERN_INFO PFX "%s SBA at 0x%lx; pci dev %02x:%02x.%d\n",			name, csr_base, dev->bus,			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));	if ((dev = hpzx1_fake_pci_dev(csr_base + 0x1000, 0, 0x1000)))		printk(KERN_INFO PFX "%s IOC at 0x%lx; pci dev %02x:%02x.%d\n",			name, csr_base + 0x1000, dev->bus,			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));	return AE_OK;}static acpi_statushpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret){	acpi_status status;	u64 csr_base = 0, csr_length = 0;	char *name = context;	NATIVE_UINT busnum = 0;	struct fake_pci_dev *dev;	status = hp_csr_space(obj, &csr_base, &csr_length);	if (status != AE_OK)		return status;	status = acpi_cf_evaluate_method(obj, METHOD_NAME__BBN, &busnum);	if (ACPI_FAILURE(status)) {		printk(KERN_ERR PFX "evaluate _BBN fail=0x%x\n", status);		busnum = 0;	// no _BBN; stick it on bus 0	}	if ((dev = hpzx1_fake_pci_dev(csr_base, busnum, csr_length)))		printk(KERN_INFO PFX "%s LBA at 0x%lx, _BBN 0x%02x; "			"pci dev %02x:%02x.%d\n",			name, csr_base, busnum, dev->bus,			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));	return AE_OK;}static voidhpzx1_acpi_dev_init(void){	extern struct pci_ops pci_conf;	/*	 * Make fake PCI devices for the following hardware in the	 * ACPI namespace.  This makes it more convenient for drivers	 * because they can claim these devices based on PCI	 * information, rather than needing to know about ACPI.  The	 * 64-bit "HPA" space for this hardware is available as BAR	 * 0/1.	 *	 * HWP0001: Single IOC SBA w/o IOC in namespace	 * HWP0002: LBA device	 * HWP0003: AGP LBA device	 */	acpi_get_devices("HWP0001", hpzx1_sba_probe, "HWP0001", NULL);#ifdef CONFIG_IA64_HP_PROTO	if (fake_pci_tail != &fake_pci_head) {#endif	acpi_get_devices("HWP0002", hpzx1_lba_probe, "HWP0002", NULL);	acpi_get_devices("HWP0003", hpzx1_lba_probe, "HWP0003", NULL);#ifdef CONFIG_IA64_HP_PROTO	}#define ZX1_FUNC_ID_VALUE    (PCI_DEVICE_ID_HP_ZX1_SBA << 16) | PCI_VENDOR_ID_HP	/*	 * Early protos don't have bridges in the ACPI namespace, so	 * if we didn't find anything, add the things we know are	 * there.	 */	if (fake_pci_tail == &fake_pci_head) {		u64 hpa, csr_base;		struct fake_pci_dev *dev;		csr_base = 0xfed00000UL;		hpa = (u64) ioremap(csr_base, 0x1000);		if (__raw_readl(hpa) == ZX1_FUNC_ID_VALUE) {			if ((dev = hpzx1_fake_pci_dev(csr_base, 0, 0x1000)))				printk(KERN_INFO PFX "HWP0001 SBA at 0x%lx; "					"pci dev %02x:%02x.%d\n", csr_base,					dev->bus, PCI_SLOT(dev->devfn),					PCI_FUNC(dev->devfn));			if ((dev = hpzx1_fake_pci_dev(csr_base + 0x1000, 0,					0x1000)))				printk(KERN_INFO PFX "HWP0001 IOC at 0x%lx; "					"pci dev %02x:%02x.%d\n",					csr_base + 0x1000,					dev->bus, PCI_SLOT(dev->devfn),					PCI_FUNC(dev->devfn));			csr_base = 0xfed24000UL;			iounmap(hpa);			hpa = (u64) ioremap(csr_base, 0x1000);			if ((dev = hpzx1_fake_pci_dev(csr_base, 0x40, 0x1000)))				printk(KERN_INFO PFX "HWP0003 AGP LBA at "					"0x%lx; pci dev %02x:%02x.%d\n",					csr_base,					dev->bus, PCI_SLOT(dev->devfn),					PCI_FUNC(dev->devfn));		}		iounmap(hpa);	}#endif	if (fake_pci_tail == &fake_pci_head)		return;	/*	 * Replace PCI ops, but only if we made fake devices.	 */	orig_pci_ops = pci_conf;	pci_conf = hp_pci_conf;}extern void sba_init(void);	voidhpzx1_pci_fixup (int phase){	if (phase == 0)		hpzx1_acpi_dev_init();	iosapic_pci_fixup(phase);        if (phase == 1)		sba_init();}/*

⌨️ 快捷键说明

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