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

📄 cpqphp_ctrl.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	if (node->length < alignment) {		kfree(node);		return(NULL);	}	if (node->base & (alignment - 1)) {		// Short circuit if adjusted size is too small		temp_dword = (node->base | (alignment-1)) + 1;		if ((node->length - (temp_dword - node->base)) < alignment) {			kfree(node);			return(NULL);		}		node->length -= (temp_dword - node->base);		node->base = temp_dword;	}	if (node->length & (alignment - 1)) {		// There's stuff in use after this node		kfree(node);		return(NULL);	}	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;	u32 temp_dword;	if (!(*head))		return(NULL);	if ( cpqhp_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 = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), 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 = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), 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. */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;	if (!(*head))		return(NULL);	if (cpqhp_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 = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), 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 = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), 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;		// 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 ( cpqhp_resource_sort_and_combine(head) )		return(NULL);	if ( sort_by_size(head) )		return(NULL);	for (node = *head; node; node = node->next) {		dbg(__FUNCTION__": req_size =%x node=%p, base=%x, length=%x\n",		    size, node, node->base, node->length);		if (node->length < size)			continue;		if (node->base & (size - 1)) {			dbg(__FUNCTION__": not aligned\n");			// 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 = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), 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(__FUNCTION__": too big\n");			// this one is longer than we need			// so we'll make a new entry and split it up			split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), 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(__FUNCTION__": 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);}/* * cpqhp_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 cpqhp_resource_sort_and_combine(struct pci_resource **head){	struct pci_resource *node1;	struct pci_resource *node2;	int out_of_order = 1;	dbg(__FUNCTION__": head = %p, *head = %p\n", 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);}void cpqhp_ctrl_intr(int IRQ, struct controller * ctrl, struct pt_regs *regs){	u8 schedule_flag = 0;	u16 misc;	u32 Diff;	u32 temp_dword;		misc = readw(ctrl->hpc_reg + MISC);	//*********************************	// Check to see if it was our interrupt	//*********************************	if (!(misc & 0x000C)) {		return;	}	if (misc & 0x0004) {		//*********************************		// Serial Output interrupt Pending		//*********************************		// Clear the interrupt		misc |= 0x0004;		writew(misc, ctrl->hpc_reg + MISC);		// Read to clear posted writes		misc = readw(ctrl->hpc_reg + MISC);		dbg (__FUNCTION__" - waking up\n");		wake_up_interruptible(&ctrl->queue);	}	if (misc & 0x0008) {		// General-interrupt-input interrupt Pending		Diff = readl(ctrl->hpc_reg + INT_INPUT_CLEAR) ^ ctrl->ctrl_int_comp;		ctrl->ctrl_int_comp = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);		// Clear the interrupt		writel(Diff, ctrl->hpc_reg + INT_INPUT_CLEAR);		// Read it back to clear any posted writes		temp_dword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);		if (!Diff) {			// Clear all interrupts			writel(0xFFFFFFFF, ctrl->hpc_reg + INT_INPUT_CLEAR);		}		schedule_flag += handle_switch_change((u8)(Diff & 0xFFL), ctrl);		schedule_flag += handle_presence_change((u16)((Diff & 0xFFFF0000L) >> 16), ctrl);		schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl);	}	if (schedule_flag) {		up(&event_semaphore);		dbg("Signal event_semaphore\n");		mark_bh(IMMEDIATE_BH);	}}/** * cpqhp_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 *cpqhp_slot_create(u8 busnumber){	struct pci_func *new_slot;	struct pci_func *next;	new_slot = (struct pci_func *) kmalloc(sizeof(struct pci_func), GFP_KERNEL);	if (new_slot == NULL) {		// I'm not dead yet!		// You will be.		return(new_slot);	}	memset(new_slot, 0, sizeof(struct pci_func));	new_slot->next = NULL;	new_slot->configured = 1;	if (cpqhp_slot_list[busnumber] == NULL) {		cpqhp_slot_list[busnumber] = new_slot;	} else {		next = cpqhp_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 = cpqhp_slot_list[old_slot->bus];	if (next == NULL) {		return(1);	}	if (next == old_slot) {		cpqhp_slot_list[old_slot->bus] = old_slot->next;		cpqhp_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;		cpqhp_destroy_board_resources(old_slot);		kfree(old_slot);		return(0);	} else

⌨️ 快捷键说明

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