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

📄 acpiphp_res.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
 * larger than "size" it will split it up. * * size must be a power of two. * */struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size){	struct pci_resource *prevnode;	struct pci_resource *node;	struct pci_resource *split_node;	u64 temp_qword;	if (!(*head))		return NULL;	if (acpiphp_resource_sort_and_combine(head))		return NULL;	if (sort_by_size(head))		return NULL;	for (node = *head; node; node = node->next) {		dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",		    __FUNCTION__, size, node, (u32)node->base, node->length);		if (node->length < size)			continue;		if (node->base & (size - 1)) {			dbg("%s: not aligned\n", __FUNCTION__);			/* this one isn't base aligned properly			   so we'll make a new entry and split it up */			temp_qword = (node->base | (size-1)) + 1;			/* Short circuit if adjusted size is too small */			if ((node->length - (temp_qword - node->base)) < size)				continue;			split_node = acpiphp_make_resource(node->base, temp_qword - node->base);			if (!split_node)				return NULL;			node->base = temp_qword;			node->length -= split_node->length;			/* Put it in the list */			split_node->next = node->next;			node->next = split_node;		} /* End of non-aligned base */		/* Don't need to check if too small since we already did */		if (node->length > size) {			dbg("%s: too big\n", __FUNCTION__);			/* this one is longer than we need			   so we'll make a new entry and split it up */			split_node = acpiphp_make_resource(node->base + size, node->length - size);			if (!split_node)				return NULL;			node->length = size;			/* Put it in the list */			split_node->next = node->next;			node->next = split_node;		}  /* End of too big on top end */		dbg("%s: got one!!!\n", __FUNCTION__);		/* If we got here, then it is the right size		   Now take it out of the list */		if (*head == node) {			*head = node->next;		} else {			prevnode = *head;			while (prevnode->next != node)				prevnode = prevnode->next;			prevnode->next = node->next;		}		node->next = NULL;		/* Stop looping */		break;	}	return node;}/** * get_resource_with_base - get resource with specific base address * * this function * returns the first node of "size" length located at specified base address. * If it finds a node larger than "size" it will split it up. * * size must be a power of two. * */struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size){	struct pci_resource *prevnode;	struct pci_resource *node;	struct pci_resource *split_node;	u64 temp_qword;	if (!(*head))		return NULL;	if (acpiphp_resource_sort_and_combine(head))		return NULL;	for (node = *head; node; node = node->next) {		dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n",		    (u32)base, size, node, (u32)node->base, node->length);		if (node->base > base)			continue;		if ((node->base + node->length) < (base + size))			continue;		if (node->base < base) {			dbg(": split 1\n");			/* this one isn't base aligned properly			   so we'll make a new entry and split it up */			temp_qword = base;			/* Short circuit if adjusted size is too small */			if ((node->length - (temp_qword - node->base)) < size)				continue;			split_node = acpiphp_make_resource(node->base, temp_qword - node->base);			if (!split_node)				return NULL;			node->base = temp_qword;			node->length -= split_node->length;			/* Put it in the list */			split_node->next = node->next;			node->next = split_node;		}		dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x\n",		    (u32)base, size, node, (u32)node->base, node->length);		/* Don't need to check if too small since we already did */		if (node->length > size) {			dbg(": split 2\n");			/* this one is longer than we need			   so we'll make a new entry and split it up */			split_node = acpiphp_make_resource(node->base + size, node->length - size);			if (!split_node)				return NULL;			node->length = size;			/* Put it in the list */			split_node->next = node->next;			node->next = split_node;		}  /* End of too big on top end */		dbg(": got one!!!\n");		/* If we got here, then it is the right size		   Now take it out of the list */		if (*head == node) {			*head = node->next;		} else {			prevnode = *head;			while (prevnode->next != node)				prevnode = prevnode->next;			prevnode->next = node->next;		}		node->next = NULL;		/* Stop looping */		break;	}	return node;}/** * acpiphp_resource_sort_and_combine * * Sorts all of the nodes in the list in ascending order by * their base addresses.  Also does garbage collection by * combining adjacent nodes. * * returns 0 if success */int acpiphp_resource_sort_and_combine (struct pci_resource **head){	struct pci_resource *node1;	struct pci_resource *node2;	int out_of_order = 1;	if (!(*head))		return 1;	dbg("*head->next = %p\n",(*head)->next);	if (!(*head)->next)		return 0;	/* only one item on the list, already sorted! */	dbg("*head->base = 0x%x\n",(u32)(*head)->base);	dbg("*head->next->base = 0x%x\n", (u32)(*head)->next->base);	while (out_of_order) {		out_of_order = 0;		/* Special case for swapping list head */		if (((*head)->next) &&		    ((*head)->base > (*head)->next->base)) {			node1 = *head;			(*head) = (*head)->next;			node1->next = (*head)->next;			(*head)->next = node1;			out_of_order++;		}		node1 = (*head);		while (node1->next && node1->next->next) {			if (node1->next->base > node1->next->next->base) {				out_of_order++;				node2 = node1->next;				node1->next = node1->next->next;				node1 = node1->next;				node2->next = node1->next;				node1->next = node2;			} else				node1 = node1->next;		}	}  /* End of out_of_order loop */	node1 = *head;	while (node1 && node1->next) {		if ((node1->base + node1->length) == node1->next->base) {			/* Combine */			dbg("8..\n");			node1->length += node1->next->length;			node2 = node1->next;			node1->next = node1->next->next;			kfree(node2);		} else			node1 = node1->next;	}	return 0;}/** * acpiphp_make_resource - make resource structure * @base: base address of a resource * @length: length of a resource */struct pci_resource *acpiphp_make_resource (u64 base, u32 length){	struct pci_resource *res;	res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);	if (res) {		memset(res, 0, sizeof(struct pci_resource));		res->base = base;		res->length = length;	}	return res;}/** * acpiphp_move_resource - move linked resources from one to another * @from: head of linked resource list * @to: head of linked resource list */void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to){	struct pci_resource *tmp;	while (*from) {		tmp = (*from)->next;		(*from)->next = *to;		*to = *from;		*from = tmp;	}	/* *from = NULL is guaranteed */}/** * acpiphp_free_resource - free all linked resources * @res: head of linked resource list */void acpiphp_free_resource (struct pci_resource **res){	struct pci_resource *tmp;	while (*res) {		tmp = (*res)->next;		kfree(*res);		*res = tmp;	}	/* *res = NULL is guaranteed */}/* debug support functions;  will go away sometime :) */static void dump_resource(struct pci_resource *head){	struct pci_resource *p;	int cnt;	p = head;	cnt = 0;	while (p) {		dbg("[%02d] %08x - %08x\n",		    cnt++, (u32)p->base, (u32)p->base + p->length - 1);		p = p->next;	}}void acpiphp_dump_resource(struct acpiphp_bridge *bridge){	dbg("I/O resource:\n");	dump_resource(bridge->io_head);	dbg("MEM resource:\n");	dump_resource(bridge->mem_head);	dbg("PMEM resource:\n");	dump_resource(bridge->p_mem_head);	dbg("BUS resource:\n");	dump_resource(bridge->bus_head);}void acpiphp_dump_func_resource(struct acpiphp_func *func){	dbg("I/O resource:\n");	dump_resource(func->io_head);	dbg("MEM resource:\n");	dump_resource(func->mem_head);	dbg("PMEM resource:\n");	dump_resource(func->p_mem_head);	dbg("BUS resource:\n");	dump_resource(func->bus_head);}

⌨️ 快捷键说明

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