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

📄 shpchprm_acpi.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
			break; 		case ACPI_WRITE_COMBINING_MEMORY:			dbg("  Type Specific: Write-combining memory\n");			break; 		case ACPI_PREFETCHABLE_MEMORY:			aprh = &ab->p_mem_head;			dbg("  Type Specific: Prefetchable memory\n");			break; 		default:			dbg("  Type Specific: Invalid cache attribute\n");			break;		}		dbg("  Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only");		break;	case ACPI_IO_RANGE: 		dbg("  Resource Type: I/O Range\n");		aprh = &ab->io_head;		tprh = &ab->tio_head;		switch (data32->attribute.io.range_attribute) {		case ACPI_NON_ISA_ONLY_RANGES:			dbg("  Type Specific: Non-ISA Io Addresses\n");			break; 		case ACPI_ISA_ONLY_RANGES:			dbg("  Type Specific: ISA Io Addresses\n");			break; 		case ACPI_ENTIRE_RANGE:			dbg("  Type Specific: ISA and non-ISA Io Addresses\n");			break; 		default:			dbg("  Type Specific: Invalid range attribute\n");			break;		}		break;	case ACPI_BUS_NUMBER_RANGE: 		dbg("  Resource Type: Bus Number Range(fixed)\n");		/* fixup to be compatible with the rest of php driver */		data32->min_address_range++;		data32->address_length--;		aprh = &ab->bus_head;		tprh = &ab->tbus_head;		break; 	default: 		dbg("  Resource Type: Invalid resource type. Exiting.\n");		return;	}	dbg("  Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer");	dbg("  %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive");	dbg("  Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not");	dbg("  Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not");	dbg("  Granularity: %08X\n", data32->granularity);	dbg("  Address range min: %08X\n", data32->min_address_range);	dbg("  Address range max: %08X\n", data32->max_address_range);	dbg("  Address translation offset: %08X\n", data32->address_translation_offset);	dbg("  Address Length: %08X\n", data32->address_length);	if (0xFF != data32->resource_source.index) {		dbg("  Resource Source Index: %X\n", data32->resource_source.index);		/* dbg("  Resource Source: %s\n", data32->resource_source.string_ptr); */	}	shpchprm_add_resource(aprh, data32->min_address_range, data32->address_length);}static acpi_status acpi_parse_crs(	struct acpi_bridge	*ab,	struct acpi_resource	*crsbuf	){	acpi_status		status = AE_OK;	struct acpi_resource	*resource = crsbuf;	u8			count = 0;	u8			done = 0;	while (!done) {		dbg("acpi_shpchprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++);		switch (resource->id) {		case ACPI_RSTYPE_IRQ:			dbg("Irq -------- Resource\n");			break; 		case ACPI_RSTYPE_DMA:			dbg("DMA -------- Resource\n");			break; 		case ACPI_RSTYPE_START_DPF:			dbg("Start DPF -------- Resource\n");			break; 		case ACPI_RSTYPE_END_DPF:			dbg("End DPF -------- Resource\n");			break; 		case ACPI_RSTYPE_IO:			acpi_parse_io (ab, &resource->data);			break; 		case ACPI_RSTYPE_FIXED_IO:			acpi_parse_fixed_io (ab, &resource->data);			break; 		case ACPI_RSTYPE_VENDOR:			dbg("Vendor -------- Resource\n");			break; 		case ACPI_RSTYPE_END_TAG:			dbg("End_tag -------- Resource\n");			done = 1;			break; 		case ACPI_RSTYPE_MEM24:			dbg("Mem24 -------- Resource\n");			break; 		case ACPI_RSTYPE_MEM32:			dbg("Mem32 -------- Resource\n");			break; 		case ACPI_RSTYPE_FIXED_MEM32:			dbg("Fixed Mem32 -------- Resource\n");			break; 		case ACPI_RSTYPE_ADDRESS16:			acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16);			break; 		case ACPI_RSTYPE_ADDRESS32:			acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32);			break; 		case ACPI_RSTYPE_ADDRESS64:			info("Address64 -------- Resource unparsed\n");			break; 		case ACPI_RSTYPE_EXT_IRQ:			dbg("Ext Irq -------- Resource\n");			break; 		default:			dbg("Invalid -------- resource type 0x%x\n", resource->id);			break;		}		resource = (struct acpi_resource *) ((char *)resource + resource->length);	}	return status;}static acpi_status acpi_get_crs( struct acpi_bridge	*ab){	acpi_status		status;	struct acpi_resource	*crsbuf;	status = acpi_evaluate_crs(ab->handle, &crsbuf);	if (ACPI_SUCCESS(status)) {		status = acpi_parse_crs(ab, crsbuf);		kfree(crsbuf);		shpchp_resource_sort_and_combine(&ab->bus_head);		shpchp_resource_sort_and_combine(&ab->io_head);		shpchp_resource_sort_and_combine(&ab->mem_head);		shpchp_resource_sort_and_combine(&ab->p_mem_head);		shpchprm_add_resources (&ab->tbus_head, ab->bus_head);		shpchprm_add_resources (&ab->tio_head, ab->io_head);		shpchprm_add_resources (&ab->tmem_head, ab->mem_head);		shpchprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);	}	return status;}/* find acpi_bridge downword from ab.  */static struct acpi_bridge *find_acpi_bridge_by_bus(	struct acpi_bridge *ab,	int seg,	int bus		/* pdev->subordinate->number */	){	struct acpi_bridge	*lab = NULL;	if (!ab)		return NULL;	if ((ab->bus == bus) && (ab->seg == seg))		return ab;	if (ab->child)		lab = find_acpi_bridge_by_bus(ab->child, seg, bus);	if (!lab)	if (ab->next)		lab = find_acpi_bridge_by_bus(ab->next, seg, bus);	return lab;}/* * Build a device tree of ACPI PCI Bridges */static void shpchprm_acpi_register_a_bridge (	struct acpi_bridge	**head,	struct acpi_bridge	*pab,	/* parent bridge to which child bridge is added */	struct acpi_bridge	*cab	/* child bridge to add */	){	struct acpi_bridge	*lpab;	struct acpi_bridge	*lcab;	lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);	if (!lpab) {		if (!(pab->type & BRIDGE_TYPE_HOST))			warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);		pab->next = *head;		*head = pab;		lpab = pab;	}	if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))		return;	lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);	if (lcab) {		if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))			err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);		return;	} else		lcab = cab;	lcab->parent = lpab;	lcab->next = lpab->child;	lpab->child = lcab;}static acpi_status shpchprm_acpi_build_php_slots_callback(	acpi_handle	handle,	u32		Level,	void		*context,	void		**retval	){	ulong		bus_num;	ulong		seg_num;	ulong		sun, adr;	ulong		padr = 0;	acpi_handle		phandle = NULL;	struct acpi_bridge	*pab = (struct acpi_bridge *)context;	struct acpi_bridge	*lab;	acpi_status		status;	u8			*path_name = acpi_path_name(handle);	/* get _SUN */	status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun);	switch(status) {	case AE_NOT_FOUND:		return AE_OK;	default:		if (ACPI_FAILURE(status)) {			err("acpi_shpchprm:%s _SUN fail=0x%x\n", path_name, status);			return status;		}	}	/* get _ADR. _ADR must exist if _SUN exists */	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);	if (ACPI_FAILURE(status)) {		err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);		return status;	}	dbg("acpi_shpchprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);	status = acpi_get_parent(handle, &phandle);	if (ACPI_FAILURE(status)) {		err("acpi_shpchprm:%s get_parent fail=0x%x\n", path_name, status);		return (status);	}	bus_num = pab->bus;	seg_num = pab->seg;	if (pab->bus == bus_num) {		lab = pab;	} else {		dbg("WARN: pab is not parent\n");		lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);		if (!lab) {			dbg("acpi_shpchprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);			lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);			if (!lab) {				err("acpi_shpchprm: alloc for ab fail\n");				return AE_NO_MEMORY;			}			memset(lab, 0, sizeof(struct acpi_bridge));			lab->handle = phandle;			lab->pbus = pab->bus;			lab->pdevice = (int)(padr >> 16) & 0xffff;			lab->pfunction = (int)(padr & 0xffff);			lab->bus = (int)bus_num;			lab->scanned = 0;			lab->type = BRIDGE_TYPE_P2P;			shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);		} else			dbg("acpi_shpchprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);	}	acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);	return (status);}static int shpchprm_acpi_build_php_slots(	struct acpi_bridge	*ab,	u32			depth	){	acpi_status	status;	u8		*path_name = acpi_path_name(ab->handle);	/* Walk down this pci bridge to get _SUNs if any behind P2P */	status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,				ab->handle,				depth,				shpchprm_acpi_build_php_slots_callback,				ab,				NULL );	if (ACPI_FAILURE(status)) {		dbg("acpi_shpchprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);		return -1;	}	return 0;}static void build_a_bridge(	struct acpi_bridge	*pab,	struct acpi_bridge	*ab	){	u8		*path_name = acpi_path_name(ab->handle);	shpchprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);	switch (ab->type) {	case BRIDGE_TYPE_HOST:		dbg("acpi_shpchprm: Registered PCI HOST Bridge(%02x)    on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",			ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);		break;	case BRIDGE_TYPE_P2P:		dbg("acpi_shpchprm: Registered PCI  P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",			ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);		break;	};	/* build any immediate PHP slots under this pci bridge */	shpchprm_acpi_build_php_slots(ab, 1);}static struct acpi_bridge * add_p2p_bridge(	acpi_handle handle,	struct acpi_bridge	*pab,	/* parent */	ulong	adr	){	struct acpi_bridge	*ab;	struct pci_dev	*pdev;	ulong		devnum, funcnum;	u8			*path_name = acpi_path_name(handle);	ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);	if (!ab) {		err("acpi_shpchprm: alloc for ab fail\n");		return NULL;	}	memset(ab, 0, sizeof(struct acpi_bridge));	devnum = (adr >> 16) & 0xffff;	funcnum = adr & 0xffff;	pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));	if (!pdev || !pdev->subordinate) {		err("acpi_shpchprm:%s is not a P2P Bridge\n", path_name);		kfree(ab);		return NULL;	}	ab->handle = handle;	ab->seg = pab->seg;	ab->pbus = pab->bus;		/* or pdev->bus->number */	ab->pdevice = devnum;		/* or PCI_SLOT(pdev->devfn) */	ab->pfunction = funcnum;	/* or PCI_FUNC(pdev->devfn) */	ab->bus = pdev->subordinate->number;	ab->scanned = 0;	ab->type = BRIDGE_TYPE_P2P;	dbg("acpi_shpchprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",		pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),		pab->bus, (u32)devnum, (u32)funcnum, path_name);	build_a_bridge(pab, ab);	return ab;}static acpi_status scan_p2p_bridge(	acpi_handle		handle,	u32			Level,	void			*context,	void			**retval	){	struct acpi_bridge	*pab = (struct acpi_bridge *)context;	struct acpi_bridge	*ab;	acpi_status		status;	ulong		adr = 0;	u8			*path_name = acpi_path_name(handle);	ulong		devnum, funcnum;	struct pci_dev	*pdev;	/* get device, function */	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);	if (ACPI_FAILURE(status)) {		if (status != AE_NOT_FOUND)			err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);		return AE_OK;	}	devnum = (adr >> 16) & 0xffff;	funcnum = adr & 0xffff;	pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));	if (!pdev)		return AE_OK;	if (!pdev->subordinate)		return AE_OK;	ab = add_p2p_bridge(handle, pab, adr);	if (ab) {		status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,					handle,					(u32)1,					scan_p2p_bridge,					ab,					NULL);		if (ACPI_FAILURE(status))			dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);	}	return AE_OK;}static struct acpi_bridge * add_host_bridge(	acpi_handle handle,	ulong	segnum,	ulong	busnum	){	ulong			adr = 0;	acpi_status		status;	struct acpi_bridge	*ab;	u8			*path_name = acpi_path_name(handle);	/* get device, function: host br adr is always 0000 though.  */	status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);	if (ACPI_FAILURE(status)) {		err("acpi_shpchprm:%s _ADR fail=0x%x\n", path_name, status);		return NULL;	}	dbg("acpi_shpchprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum, (u32)busnum, 		(u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);	ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);	if (!ab) {		err("acpi_shpchprm: alloc for ab fail\n");		return NULL;	}	memset(ab, 0, sizeof(struct acpi_bridge));	ab->handle = handle;	ab->seg = (int)segnum;	ab->bus = ab->pbus = (int)busnum;	ab->pdevice = (int)(adr >> 16) & 0xffff;	ab->pfunction = (int)(adr & 0xffff);	ab->scanned = 0;	ab->type = BRIDGE_TYPE_HOST;	/* get root pci bridge's current resources */	status = acpi_get_crs(ab);	if (ACPI_FAILURE(status)) {		err("acpi_shpchprm:%s evaluate _CRS fail=0x%x\n", path_name, status);		kfree(ab);		return NULL;	}	build_a_bridge(ab, ab);	return ab;}static acpi_status acpi_scan_from_root_pci_callback (	acpi_handle	handle,	u32			Level,	void		*context,	void		**retval	){	ulong		segnum = 0;	ulong		busnum = 0;	acpi_status		status;	struct acpi_bridge	*ab;	u8			*path_name = acpi_path_name(handle);	/* get bus number of this pci root bridge */	status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);	if (ACPI_FAILURE(status)) {		if (status != AE_NOT_FOUND) {			err("acpi_shpchprm:%s evaluate _SEG fail=0x%x\n", path_name, status);			return status;		}		segnum = 0;	}	/* get bus number of this pci root bridge */	status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);	if (ACPI_FAILURE(status)) {		err("acpi_shpchprm:%s evaluate _BBN fail=0x%x\n", path_name, status);		return (status);	}	ab = add_host_bridge(handle, segnum, busnum);	if (ab) {		status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,					handle,					1,					scan_p2p_bridge,					ab,					NULL);		if (ACPI_FAILURE(status))			dbg("acpi_shpchprm:%s find_p2p fail=0x%x\n", path_name, status);	}	return AE_OK;}static int shpchprm_acpi_scan_pci (void){	acpi_status	status;	/*	 * TBD: traverse LDM device tree with the help of	 *  unified ACPI augmented for php device population.	 */	status = acpi_get_devices ( PCI_ROOT_HID_STRING,				acpi_scan_from_root_pci_callback,				NULL,				NULL );	if (ACPI_FAILURE(status)) {		err("acpi_shpchprm:get_device PCI ROOT HID fail=0x%x\n", status);		return -1;	}	return 0;}int shpchprm_init(enum php_ctlr_type ctlr_type){	int	rc;	if (ctlr_type != PCI)		return -ENODEV;	dbg("shpchprm ACPI init <enter>\n");	acpi_bridges_head = NULL;	/* construct PCI bus:device tree of acpi_handles */	rc = shpchprm_acpi_scan_pci();	if (rc)		return rc;	dbg("shpchprm ACPI init %s\n", (rc)?"fail":"success");	return rc;

⌨️ 快捷键说明

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