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

📄 cpqphp_ctrl.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
		node->base = temp_dword;	}	if (node->length & (alignment - 1))		/* There's stuff in use after this node */		goto error;	return node;error:	kfree(node);	return NULL;}/** * get_io_resource: find first node of given size not in ISA aliasing window. * @head: list to search * @size: size of node to find, must be a power of two. * * Description: this function sorts the resource list by size and then returns * 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. * */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 = 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 and break */		if (*head == node) {			*head = node->next;		} else {			prevnode = *head;			while (prevnode->next != node)				prevnode = prevnode->next;			prevnode->next = node->next;		}		node->next = NULL;		break;	}	return node;}/** * get_max_resource: get largest node which has at least the given size. * @head: the list to search the node in * @size: the minimum size of the node to find * * Description: 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 (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 = 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;			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;			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 = *head;		if (temp == max) {			*head = max->next;		} else {			while (temp && temp->next != max) {				temp = temp->next;			}			temp->next = max->next;		}		max->next = NULL;		break;	}	return max;}/** * get_resource: find resource of given size and split up larger ones. * @head: the list to search for resources * @size: the size limit to use * * Description: 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 (cpqhp_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, 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;			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;		break;	}	return node;}/** * cpqhp_resource_sort_and_combine: sort nodes by base addresses and clean up. * @head: the list to sort and clean up * * Description: 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("%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;}irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data, struct pt_regs *regs){	struct controller *ctrl = data;	u8 schedule_flag = 0;	u8 reset;	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 IRQ_NONE;	}	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 ("%s - waking up\n", __FUNCTION__);		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);	}	reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);	if (reset & 0x40) {		/* Bus reset has completed */		reset &= 0xCF;		writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE);		reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);		wake_up_interruptible(&ctrl->queue);	}	if (schedule_flag) {		up(&event_semaphore);		dbg("Signal event_semaphore\n");	}	return IRQ_HANDLED;}/** * 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 = kmalloc(sizeof(*new_slot), 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		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;

⌨️ 快捷键说明

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