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

📄 shpchp_ctrl.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	return(node);}/* * get_io_resource * * this function sorts the resource list by size and then * returns the first node of "size" length that is not in the * ISA aliasing window.  If it finds a node larger than "size" * it will split it up. * * size must be a power of two. */static struct pci_resource *get_io_resource (struct pci_resource **head, u32 size){	struct pci_resource *prevnode;	struct pci_resource *node;	struct pci_resource *split_node = NULL;	u32 temp_dword;	if (!(*head))		return(NULL);	if ( shpchp_resource_sort_and_combine(head) )		return(NULL);	if ( sort_by_size(head) )		return(NULL);	for (node = *head; node; node = node->next) {		if (node->length < size)			continue;		if (node->base & (size - 1)) {			/* This one isn't base aligned properly			   so we'll make a new entry and split it up */			temp_dword = (node->base | (size-1)) + 1;			/*/ Short circuit if adjusted size is too small */			if ((node->length - (temp_dword - node->base)) < size)				continue;			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);			if (!split_node)				return(NULL);			split_node->base = node->base;			split_node->length = temp_dword - node->base;			node->base = temp_dword;			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) {			/* This one is longer than we need			   so we'll make a new entry and split it up */			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);			if (!split_node)				return(NULL);			split_node->base = node->base + size;			split_node->length = node->length - size;			node->length = size;			/* Put it in the list */			split_node->next = node->next;			node->next = split_node;		}  /* End of too big on top end */		/* For IO make sure it's not in the ISA aliasing space */		if (node->base & 0x300L)			continue;		/* 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_max_resource * * Gets the largest node that is at least "size" big from the * list pointed to by head.  It aligns the node on top and bottom * to "size" alignment before returning it. * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M *  This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot. */static struct pci_resource *get_max_resource (struct pci_resource **head, u32 size){	struct pci_resource *max;	struct pci_resource *temp;	struct pci_resource *split_node;	u32 temp_dword;	u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 };	int i;	if (!(*head))		return(NULL);	if (shpchp_resource_sort_and_combine(head))		return(NULL);	if (sort_by_max_size(head))		return(NULL);	for (max = *head;max; max = max->next) {		/* If not big enough we could probably just bail, 		   instead we'll continue to the next. */		if (max->length < size)			continue;		if (max->base & (size - 1)) {			/* This one isn't base aligned properly			   so we'll make a new entry and split it up */			temp_dword = (max->base | (size-1)) + 1;			/* Short circuit if adjusted size is too small */			if ((max->length - (temp_dword - max->base)) < size)				continue;			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);			if (!split_node)				return(NULL);			split_node->base = max->base;			split_node->length = temp_dword - max->base;			max->base = temp_dword;			max->length -= split_node->length;			/* Put it next in the list */			split_node->next = max->next;			max->next = split_node;		}		if ((max->base + max->length) & (size - 1)) {			/* This one isn't end aligned properly at the top			   so we'll make a new entry and split it up */			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);			if (!split_node)				return(NULL);			temp_dword = ((max->base + max->length) & ~(size - 1));			split_node->base = temp_dword;			split_node->length = max->length + max->base					     - split_node->base;			max->length -= split_node->length;			/* Put it in the list */			split_node->next = max->next;			max->next = split_node;		}		/* Make sure it didn't shrink too much when we aligned it */		if (max->length < size)			continue;		for ( i = 0; max_size[i] > size; i++) {			if (max->length > max_size[i]) {				split_node = kmalloc(sizeof(*split_node),							GFP_KERNEL);				if (!split_node)					break;	/* return (NULL); */				split_node->base = max->base + max_size[i];				split_node->length = max->length - max_size[i];				max->length = max_size[i];				/* Put it next in the list */				split_node->next = max->next;				max->next = split_node;				break;			}		}		/* Now take it out of the list */		temp = (struct pci_resource*) *head;		if (temp == max) {			*head = max->next;		} else {			while (temp && temp->next != max) {				temp = temp->next;			}			temp->next = max->next;		}		max->next = NULL;		return(max);	}	/* If we get here, we couldn't find one */	return(NULL);}/* * get_resource * * this function sorts the resource list by size and then * returns the first node of "size" length.  If it finds a node * larger than "size" it will split it up. * * size must be a power of two. */static struct pci_resource *get_resource (struct pci_resource **head, u32 size){	struct pci_resource *prevnode;	struct pci_resource *node;	struct pci_resource *split_node;	u32 temp_dword;	if (!(*head))		return(NULL);	if ( shpchp_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 =0x%x node=%p, base=0x%x, length=0x%x\n",		    __FUNCTION__, size, node, 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_dword = (node->base | (size-1)) + 1;			/* Short circuit if adjusted size is too small */			if ((node->length - (temp_dword - node->base)) < size)				continue;			split_node = kmalloc(sizeof(*split_node), GFP_KERNEL);			if (!split_node)				return(NULL);			split_node->base = node->base;			split_node->length = temp_dword - node->base;			node->base = temp_dword;			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 = kmalloc(sizeof(*split_node), GFP_KERNEL);			if (!split_node)				return(NULL);			split_node->base = node->base + size;			split_node->length = node->length - size;			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);}/* * shpchp_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 shpchp_resource_sort_and_combine(struct pci_resource **head){	struct pci_resource *node1;	struct pci_resource *node2;	int out_of_order = 1;	dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);	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",(*head)->base);	dbg("*head->next->base = 0x%x\n",(*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);}/** * shpchp_slot_create - Creates a node and adds it to the proper bus. * @busnumber - bus where new node is to be located * * Returns pointer to the new node or NULL if unsuccessful */struct pci_func *shpchp_slot_create(u8 busnumber){	struct pci_func *new_slot;	struct pci_func *next;	new_slot = kmalloc(sizeof(*new_slot), GFP_KERNEL);	if (new_slot == NULL) {		return(new_slot);	}	memset(new_slot, 0, sizeof(struct pci_func));	new_slot->next = NULL;	new_slot->configured = 1;	if (shpchp_slot_list[busnumber] == NULL) {		shpchp_slot_list[busnumber] = new_slot;	} else {		next = shpchp_slot_list[busnumber];		while (next->next != NULL)			next = next->next;		next->next = new_slot;	}	return(new_slot);}/* * slot_remove - Removes a node from the linked list of slots. * @old_slot: slot to remove * * Returns 0 if successful, !0 otherwise. */static int slot_remove(struct pci_func * old_slot){	struct pci_func *next;	if (old_slot == NULL)		return(1);	next = shpchp_slot_list[old_slot->bus];	if (next == NULL) {		return(1);	}	if (next == old_slot) {		shpchp_slot_list[old_slot->bus] = old_slot->next;		shpchp_destroy_board_resources(old_slot);		kfree(old_slot);		return(0);	}	while ((next->next != old_slot) && (next->next != NULL)) {		next = next->next;	}	if (next->next == old_slot) {		next->next = old_slot->next;		shpchp_destroy_board_resources(old_slot);		kfree(old_slot);		return(0);	} else		return(2);}/** * bridge_slot_remove - Removes a node from the linked list of slots. * @bridge: bridge to remove * * Returns 0 if successful, !0 otherwise. */static int bridge_slot_remove(struct pci_func *bridge){	u8 subordinateBus, secondaryBus;	u8 tempBus;	struct pci_func *next;	if (bridge == NULL)		return(1);	secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;	subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;	for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {		next = shpchp_slot_list[tempBus];		while (!slot_remove(next)) {			next = shpchp_slot_list[tempBus];		}	}	next = shpchp_slot_list[bridge->bus];	if (next == NULL) {		return(1);	}

⌨️ 快捷键说明

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