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

📄 shpchprm_acpi.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
}static void free_a_slot(struct acpi_php_slot *aps){	dbg("        free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);	free_pci_resource (aps->io_head);	free_pci_resource (aps->bus_head);	free_pci_resource (aps->mem_head);	free_pci_resource (aps->p_mem_head);	kfree(aps);}static void free_a_bridge( struct acpi_bridge	*ab){	struct acpi_php_slot	*aps, *next;	switch (ab->type) {	case BRIDGE_TYPE_HOST:		dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",			ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);		break;	case BRIDGE_TYPE_P2P:		dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",			ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);		break;	};	/* free slots first */	for (aps = ab->slots; aps; aps = next) {		next = aps->next;		free_a_slot(aps);	}	free_pci_resource (ab->io_head);	free_pci_resource (ab->tio_head);	free_pci_resource (ab->bus_head);	free_pci_resource (ab->tbus_head);	free_pci_resource (ab->mem_head);	free_pci_resource (ab->tmem_head);	free_pci_resource (ab->p_mem_head);	free_pci_resource (ab->tp_mem_head);	kfree(ab);}static void shpchprm_free_bridges ( struct acpi_bridge	*ab){	if (!ab)		return;	if (ab->child)		shpchprm_free_bridges (ab->child);	if (ab->next)		shpchprm_free_bridges (ab->next);	free_a_bridge(ab);}void shpchprm_cleanup(void){	shpchprm_free_bridges (acpi_bridges_head);}static int get_number_of_slots (	struct acpi_bridge	*ab,	int				selfonly	){	struct acpi_php_slot	*aps;	int	prev_slot = -1;	int	slot_num = 0;	for ( aps = ab->slots; aps; aps = aps->next)		if (aps->dev != prev_slot) {			prev_slot = aps->dev;			slot_num++;		}	if (ab->child)		slot_num += get_number_of_slots (ab->child, 0);	if (selfonly)		return slot_num;	if (ab->next)		slot_num += get_number_of_slots (ab->next, 0);	return slot_num;}static int print_acpi_resources (struct acpi_bridge	*ab){	struct acpi_php_slot	*aps;	int	i;	switch (ab->type) {	case BRIDGE_TYPE_HOST:		dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle));		break;	case BRIDGE_TYPE_P2P:		dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle));		break;	};	print_pci_resources (ab);	for ( i = -1, aps = ab->slots; aps; aps = aps->next) {		if (aps->dev == i)			continue;		dbg("  Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);		print_slot_resources(aps);		i = aps->dev;	}	if (ab->child)		print_acpi_resources (ab->child);	if (ab->next)		print_acpi_resources (ab->next);	return 0;}int shpchprm_print_pirt(void){	dbg("SHPCHPRM ACPI Slots\n");	if (acpi_bridges_head)		print_acpi_resources (acpi_bridges_head);	return 0;}static struct acpi_php_slot * get_acpi_slot (	struct acpi_bridge *ab,	u32 sun	){	struct acpi_php_slot	*aps = NULL;	for ( aps = ab->slots; aps; aps = aps->next)		if (aps->sun == sun)			return aps;	if (!aps && ab->child) {		aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);		if (aps)			return aps;	}	if (!aps && ab->next) {		aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);		if (aps)			return aps;	}	return aps;}#if 0static void * shpchprm_get_slot(struct slot *slot){	struct acpi_bridge	*ab = acpi_bridges_head;	struct acpi_php_slot	*aps = get_acpi_slot (ab, slot->number);	aps->slot = slot;	dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);	return (void *)aps;}#endifstatic void shpchprm_dump_func_res( struct pci_func *fun){	struct pci_func *func = fun;	if (func->bus_head) {		dbg(":    BUS Resources:\n");		print_pci_resource (func->bus_head);	}	if (func->io_head) {		dbg(":    IO Resources:\n");		print_pci_resource (func->io_head);	}	if (func->mem_head) {		dbg(":    MEM Resources:\n");		print_pci_resource (func->mem_head);	}	if (func->p_mem_head) {		dbg(":    PMEM Resources:\n");		print_pci_resource (func->p_mem_head);	}}static void shpchprm_dump_ctrl_res( struct controller *ctlr){	struct controller *ctrl = ctlr;	if (ctrl->bus_head) {		dbg(":    BUS Resources:\n");		print_pci_resource (ctrl->bus_head);	}	if (ctrl->io_head) {		dbg(":    IO Resources:\n");		print_pci_resource (ctrl->io_head);	}	if (ctrl->mem_head) {		dbg(":    MEM Resources:\n");		print_pci_resource (ctrl->mem_head);	}	if (ctrl->p_mem_head) {		dbg(":    PMEM Resources:\n");		print_pci_resource (ctrl->p_mem_head);	}}static int shpchprm_get_used_resources (	struct controller *ctrl,	struct pci_func *func	){	return shpchp_save_used_resources (ctrl, func, !DISABLE_CARD);}static int configure_existing_function(	struct controller *ctrl,	struct pci_func *func	){	int rc;	/* see how much resources the func has used. */	rc = shpchprm_get_used_resources (ctrl, func);	if (!rc) {		/* subtract the resources used by the func from ctrl resources */		rc  = shpchprm_delete_resources (&ctrl->bus_head, func->bus_head);		rc |= shpchprm_delete_resources (&ctrl->io_head, func->io_head);		rc |= shpchprm_delete_resources (&ctrl->mem_head, func->mem_head);		rc |= shpchprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);		if (rc)			warn("aCEF: cannot del used resources\n");	} else		err("aCEF: cannot get used resources\n");	return rc;}static int bind_pci_resources_to_slots ( struct controller *ctrl){	struct pci_func *func, new_func;	int busn = ctrl->slot_bus;	int devn, funn;	u32	vid;	for (devn = 0; devn < 32; devn++) {		for (funn = 0; funn < 8; funn++) {			/*			if (devn == ctrl->device && funn == ctrl->function)				continue;			*/			/* find out if this entry is for an occupied slot */			vid = 0xFFFFFFFF;			pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);			if (vid != 0xFFFFFFFF) {				func = shpchp_slot_find(busn, devn, funn);				if (!func) {					memset(&new_func, 0, sizeof(struct pci_func));					new_func.bus = busn;					new_func.device = devn;					new_func.function = funn;					new_func.is_a_board = 1;					configure_existing_function(ctrl, &new_func);					shpchprm_dump_func_res(&new_func);				} else {					configure_existing_function(ctrl, func);					shpchprm_dump_func_res(func);				}				dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);			}		}	}	return 0;}static int bind_pci_resources(	struct controller 	*ctrl,	struct acpi_bridge	*ab	){	int	status = 0;	if (ab->bus_head) {		dbg("bapr:  BUS Resources add on PCI 0x%x\n", ab->bus);		status = shpchprm_add_resources (&ctrl->bus_head, ab->bus_head);		if (shpchprm_delete_resources (&ab->bus_head, ctrl->bus_head))			warn("bapr:  cannot sub BUS Resource on PCI 0x%x\n", ab->bus);		if (status) {			err("bapr:  BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);			return status;		}	} else		info("bapr:  No BUS Resource on PCI 0x%x.\n", ab->bus);	if (ab->io_head) {		dbg("bapr:  IO Resources add on PCI 0x%x\n", ab->bus);		status = shpchprm_add_resources (&ctrl->io_head, ab->io_head);		if (shpchprm_delete_resources (&ab->io_head, ctrl->io_head))			warn("bapr:  cannot sub IO Resource on PCI 0x%x\n", ab->bus);		if (status) {			err("bapr:  IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);			return status;		}	} else		info("bapr:  No  IO Resource on PCI 0x%x.\n", ab->bus);	if (ab->mem_head) {		dbg("bapr:  MEM Resources add on PCI 0x%x\n", ab->bus);		status = shpchprm_add_resources (&ctrl->mem_head, ab->mem_head);		if (shpchprm_delete_resources (&ab->mem_head, ctrl->mem_head))			warn("bapr:  cannot sub MEM Resource on PCI 0x%x\n", ab->bus);		if (status) {			err("bapr:  MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);			return status;		}	} else		info("bapr:  No MEM Resource on PCI 0x%x.\n", ab->bus);	if (ab->p_mem_head) {		dbg("bapr:  PMEM Resources add on PCI 0x%x\n", ab->bus);		status = shpchprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);		if (shpchprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head))			warn("bapr:  cannot sub PMEM Resource on PCI 0x%x\n", ab->bus);		if (status) {			err("bapr:  PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);			return status;		}	} else		info("bapr:  No PMEM Resource on PCI 0x%x.\n", ab->bus);	return status;}static int no_pci_resources( struct acpi_bridge *ab){	return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);}static int find_pci_bridge_resources (	struct controller *ctrl,	struct acpi_bridge *ab	){	int	rc = 0;	struct pci_func func;	memset(&func, 0, sizeof(struct pci_func));	func.bus = ab->pbus;	func.device = ab->pdevice;	func.function = ab->pfunction;	func.is_a_board = 1;	/* Get used resources for this PCI bridge */	rc = shpchp_save_used_resources (ctrl, &func, !DISABLE_CARD);	ab->io_head = func.io_head;	ab->mem_head = func.mem_head;	ab->p_mem_head = func.p_mem_head;	ab->bus_head = func.bus_head;	if (ab->bus_head)		shpchprm_delete_resource(&ab->bus_head, ctrl->bus, 1);	return rc;}static int get_pci_resources_from_bridge(	struct controller *ctrl,	struct acpi_bridge *ab	){	int	rc = 0;	dbg("grfb:  Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus);	rc = find_pci_bridge_resources (ctrl, ab);	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 rc;}static int get_pci_resources(	struct controller	*ctrl,	struct acpi_bridge	*ab	){	int	rc = 0;	if (no_pci_resources(ab)) {		dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus);		rc = get_pci_resources_from_bridge(ctrl, ab);	}	return rc;}int shpchprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum){	int offset = devnum - ctrl->slot_device_offset;	dbg("%s: ctrl->slot_num_inc %d, offset %d\n", __FUNCTION__, ctrl->slot_num_inc, offset);	*sun = (u8) (ctrl->first_slot + ctrl->slot_num_inc *offset);	return 0;}/* * Get resources for this ctrl. *  1. get total resources from ACPI _CRS or bridge (this ctrl) *  2. find used resources of existing adapters *	3. subtract used resources from total resources */int shpchprm_find_available_resources( struct controller *ctrl){	int rc = 0;	struct acpi_bridge	*ab;	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number);	if (!ab) {		err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);		return -1;	}	if (no_pci_resources(ab)) {		rc = get_pci_resources(ctrl, ab);		if (rc) {			err("pfar:cannot get pci resources of PCI 0x%x.\n",ctrl->pci_dev->subordinate->number);			return -1;		}	}	rc = bind_pci_resources(ctrl, ab);	dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);	shpchprm_dump_ctrl_res(ctrl);	bind_pci_resources_to_slots (ctrl);	dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);	shpchprm_dump_ctrl_res(ctrl);	return rc;}int shpchprm_set_hpp(	struct controller *ctrl,	struct pci_func *func,	u8	card_type	){	struct acpi_bridge	*ab;	struct pci_bus lpci_bus, *pci_bus;	int				rc = 0;	unsigned int	devfn;	u8				cls= 0x08;	/* default cache line size	*/	u8				lt = 0x40;	/* default latency timer	*/	u8				ep = 0;	u8				es = 0;	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));	pci_bus = &lpci_bus;	pci_bus->number = func->bus;	devfn = PCI_DEVFN(func->device, func->function);	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);	if (ab) {		if (ab->_hpp) {			lt  = (u8)ab->_hpp->latency_timer;			cls = (u8)ab->_hpp->cache_line_size;			ep  = (u8)ab->_hpp->enable_perr;			es  = (u8)ab->_hpp->enable_serr;		} else			dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);	} else		dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);	if (card_type == PCI_HEADER_TYPE_BRIDGE) {		/* set subordinate Latency Timer */		rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);	}	/* set base Latency Timer */	rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);	dbg("  set latency timer  =0x%02x: %x\n", lt, rc);	rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);	dbg("  set cache_line_size=0x%02x: %x\n", cls, rc);	return rc;}void shpchprm_enable_card(	struct controller *ctrl,	struct pci_func *func,	u8 card_type){	u16 command, cmd, bcommand, bcmd;	struct pci_bus lpci_bus, *pci_bus;	struct acpi_bridge	*ab;	unsigned int devfn;	int rc;	memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));	pci_bus = &lpci_bus;	pci_bus->number = func->bus;	devfn = PCI_DEVFN(func->device, func->function);	rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);	if (card_type == PCI_HEADER_TYPE_BRIDGE) {		rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);	}	cmd = command  = command | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE		| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;	bcmd = bcommand  = bcommand | PCI_BRIDGE_CTL_NO_ISA;	ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);	if (ab) {		if (ab->_hpp) {			if (ab->_hpp->enable_perr) {				command |= PCI_COMMAND_PARITY;				bcommand |= PCI_BRIDGE_CTL_PARITY;			} else {				command &= ~PCI_COMMAND_PARITY;				bcommand &= ~PCI_BRIDGE_CTL_PARITY;			}			if (ab->_hpp->enable_serr) {				command |= PCI_COMMAND_SERR;				bcommand |= PCI_BRIDGE_CTL_SERR;			} else {				command &= ~PCI_COMMAND_SERR;				bcommand &= ~PCI_BRIDGE_CTL_SERR;			}		} else			dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);	} else		dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);	if (command != cmd) {		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);	}	if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {		rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);	}}

⌨️ 快捷键说明

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