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

📄 ibmphp_res.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				}			}		}		if (!res_cur->next) {			/* last device on the range */			if ((range->end != res_cur->end) && ((len_tmp = range->end - (res_cur->end + 1)) >= res->len)) {				debug ("len_tmp = %x\n", len_tmp);				if ((len_tmp < len_cur) || (len_cur == 0)) {					if (((res_cur->end + 1) % tmp_divide) == 0) {						/* just perfect, starting address is divisible by length */						flag = TRUE;						len_cur = len_tmp;						start_cur = res_cur->end + 1;					} else {						/* Needs adjusting */						tmp_start = res_cur->end + 1;						flag = FALSE;						while ((len_tmp = range->end - tmp_start) >= res->len) {							if ((tmp_start % tmp_divide) == 0) {								flag = TRUE;								len_cur = len_tmp;								start_cur = tmp_start;								break;							}							tmp_start += tmp_divide - tmp_start % tmp_divide;							if (tmp_start >= range->end)								break;						}					}					if (flag && len_cur == res->len) {						res->start = start_cur;						res->len += 1; /* To restore the balance */						res->end = res->start + res->len - 1;						return 0;					}				}			}		}		if (res_prev) {			if (res_prev->rangeno != res_cur->rangeno) {				/* 1st device on this range */				if ((res_cur->start != range->start) && 					((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {					if ((len_tmp < len_cur) || (len_cur == 0)) {						if ((range->start % tmp_divide) == 0) {								/* just perfect, starting address is divisible by length */							flag = TRUE;							len_cur = len_tmp;							start_cur = range->start;						} else {							/* Needs adjusting */							tmp_start = range->start;							flag = FALSE;							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {								if ((tmp_start % tmp_divide) == 0) {									flag = TRUE;									len_cur = len_tmp;									start_cur = tmp_start;									break;								}								tmp_start += tmp_divide - tmp_start % tmp_divide;								if (tmp_start >= res_cur->start - 1)									break;							}						}						if (flag && len_cur == res->len) {							res->start = start_cur;							res->len += 1; /* To restore the balance */							res->end = res->start + res->len - 1;							return 0;						}					}				}			} else {				/* in the same range */				if ((len_tmp = res_cur->start - 1 - res_prev->end - 1) >= res->len) {					if ((len_tmp < len_cur) || (len_cur == 0)) {						if (((res_prev->end + 1) % tmp_divide) == 0) {							/* just perfect, starting address's divisible by length */							flag = TRUE;							len_cur = len_tmp;							start_cur = res_prev->end + 1;						} else {							/* Needs adjusting */							tmp_start = res_prev->end + 1;							flag = FALSE;							while ((len_tmp = res_cur->start - 1 - tmp_start) >= res->len) {								if ((tmp_start % tmp_divide) == 0) {									flag = TRUE;									len_cur = len_tmp;									start_cur = tmp_start;									break;								}								tmp_start += tmp_divide - tmp_start % tmp_divide;								if (tmp_start >= res_cur->start - 1)									break;							}						}						if (flag && len_cur == res->len) {							res->start = start_cur;							res->len += 1; /* To restore the balance */							res->end = res->start + res->len - 1;							return 0;						}					}				}			}		}		/* end if (res_prev) */		res_prev = res_cur;		if (res_cur->next)			res_cur = res_cur->next;		else			res_cur = res_cur->nextRange;	}	/* end of while */	if (!res_prev) {		/* 1st device ever */		/* need to find appropriate range */		switch (res->type) {			case IO:				range = bus_cur->rangeIO;				break;			case MEM:				range = bus_cur->rangeMem;				break;			case PFMEM:				range = bus_cur->rangePFMem;				break;		}		while (range) {			if ((len_tmp = range->end - range->start) >= res->len) {				if ((len_tmp < len_cur) || (len_cur == 0)) {					if ((range->start % tmp_divide) == 0) {						/* just perfect, starting address's divisible by length */						flag = TRUE;						len_cur = len_tmp;						start_cur = range->start;					} else {						/* Needs adjusting */						tmp_start = range->start;						flag = FALSE;						while ((len_tmp = range->end - tmp_start) >= res->len) {							if ((tmp_start % tmp_divide) == 0) {								flag = TRUE;								len_cur = len_tmp;								start_cur = tmp_start;								break;							}							tmp_start += tmp_divide - tmp_start % tmp_divide;							if (tmp_start >= range->end)								break;						}					}					if (flag && len_cur == res->len) {						res->start = start_cur;						res->len += 1; /* To restore the balance */						res->end = res->start + res->len - 1;						return 0;					}				}			}			range = range->next;		}		/* end of while */		if ((!range) && (len_cur == 0)) {			/* have gone through the list of devices and ranges and haven't found n.e.thing */			err ("no appropriate range.. bailing out...\n");			return -EINVAL;		} else if (len_cur) {			res->start = start_cur;			res->len += 1; /* To restore the balance */			res->end = res->start + res->len - 1;			return 0;		}	}	if (!res_cur) {		debug ("prev->rangeno = %d, noranges = %d\n", res_prev->rangeno, noranges);		if (res_prev->rangeno < noranges) {			/* if there're more ranges out there to check */			switch (res->type) {				case IO:					range = bus_cur->rangeIO;					break;				case MEM:					range = bus_cur->rangeMem;					break;				case PFMEM:					range = bus_cur->rangePFMem;					break;			}			while (range) {				if ((len_tmp = range->end - range->start) >= res->len) {					if ((len_tmp < len_cur) || (len_cur == 0)) {						if ((range->start % tmp_divide) == 0) {							/* just perfect, starting address's divisible by length */							flag = TRUE;							len_cur = len_tmp;							start_cur = range->start;						} else {							/* Needs adjusting */							tmp_start = range->start;							flag = FALSE;							while ((len_tmp = range->end - tmp_start) >= res->len) {								if ((tmp_start % tmp_divide) == 0) {									flag = TRUE;									len_cur = len_tmp;									start_cur = tmp_start;									break;								}								tmp_start += tmp_divide - tmp_start % tmp_divide;								if (tmp_start >= range->end)									break;							}						}						if (flag && len_cur == res->len) {							res->start = start_cur;							res->len += 1; /* To restore the balance */							res->end = res->start + res->len - 1;							return 0;						}					}				}				range = range->next;			}	/* end of while */			if ((!range) && (len_cur == 0)) {				/* have gone through the list of devices and ranges and haven't found n.e.thing */				err ("no appropriate range.. bailing out...\n");				return -EINVAL;			} else if (len_cur) {				res->start = start_cur;				res->len += 1; /* To restore the balance */				res->end = res->start + res->len - 1;				return 0;			}		} else {			/* no more ranges to check on */			if (len_cur) {				res->start = start_cur;				res->len += 1; /* To restore the balance */				res->end = res->start + res->len - 1;				return 0;			} else {				/* have gone through the list of devices and haven't found n.e.thing */				err ("no appropriate range.. bailing out...\n");				return -EINVAL;			}		}	}	/* end if(!res_cur) */	return -EINVAL;}/******************************************************************************** * This routine is called from remove_card if the card contained PPB. * It will remove all the resources on the bus as well as the bus itself * Input: Bus * Ouput: 0, -ENODEV ********************************************************************************/int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno){	struct resource_node *res_cur;	struct resource_node *res_tmp;	struct bus_node *prev_bus;	int rc;	prev_bus = find_bus_wprev (parent_busno, NULL, 0);		if (!prev_bus) {		debug ("something terribly wrong. Cannot find parent bus to the one to remove\n");		return -ENODEV;	}	debug ("In ibmphp_remove_bus... prev_bus->busno is %x\n", prev_bus->busno);	rc = remove_ranges (bus, prev_bus);	if (rc)		return rc;	if (bus->firstIO) {		res_cur = bus->firstIO;		while (res_cur) {			res_tmp = res_cur;			if (res_cur->next)				res_cur = res_cur->next;			else				res_cur = res_cur->nextRange;			kfree (res_tmp);			res_tmp = NULL;		}		bus->firstIO = NULL;	}	if (bus->firstMem) {		res_cur = bus->firstMem;		while (res_cur) {			res_tmp = res_cur;			if (res_cur->next)				res_cur = res_cur->next;			else				res_cur = res_cur->nextRange;			kfree (res_tmp);			res_tmp = NULL;		}		bus->firstMem = NULL;	}	if (bus->firstPFMem) {		res_cur = bus->firstPFMem;		while (res_cur) {			res_tmp = res_cur;			if (res_cur->next)				res_cur = res_cur->next;			else				res_cur = res_cur->nextRange;			kfree (res_tmp);			res_tmp = NULL;		}		bus->firstPFMem = NULL;	}	if (bus->firstPFMemFromMem) {		res_cur = bus->firstPFMemFromMem;		while (res_cur) {			res_tmp = res_cur;			res_cur = res_cur->next;			kfree (res_tmp);			res_tmp = NULL;		}		bus->firstPFMemFromMem = NULL;	}	list_del (&bus->bus_list);	kfree (bus);	return 0;}/****************************************************************************** * This routine deletes the ranges from a given bus, and the entries from the  * parent's bus in the resources * Input: current bus, previous bus * Output: 0, -EINVAL ******************************************************************************/static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev){	struct range_node *range_cur;	struct range_node *range_tmp;	int i;	struct resource_node *res = NULL;	if (bus_cur->noIORanges) {		range_cur = bus_cur->rangeIO;		for (i = 0; i < bus_cur->noIORanges; i++) {			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, IO) < 0)				return -EINVAL;			ibmphp_remove_resource (res);			range_tmp = range_cur;			range_cur = range_cur->next;			kfree (range_tmp);			range_tmp = NULL;		}		bus_cur->rangeIO = NULL;	}	if (bus_cur->noMemRanges) {		range_cur = bus_cur->rangeMem;		for (i = 0; i < bus_cur->noMemRanges; i++) {			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, MEM) < 0) 				return -EINVAL;			ibmphp_remove_resource (res);			range_tmp = range_cur;			range_cur = range_cur->next;			kfree (range_tmp);			range_tmp = NULL;		}		bus_cur->rangeMem = NULL;	}	if (bus_cur->noPFMemRanges) {		range_cur = bus_cur->rangePFMem;		for (i = 0; i < bus_cur->noPFMemRanges; i++) {			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, PFMEM) < 0) 				return -EINVAL;			ibmphp_remove_resource (res);			range_tmp = range_cur;			range_cur = range_cur->next;			kfree (range_tmp);			range_tmp = NULL;		}		bus_cur->rangePFMem = NULL;	}	return 0;}/* * find the resource node in the bus  * Input: Resource needed, start address of the resource, type of resource */int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resource_node **res, int flag){	struct resource_node *res_cur = NULL;	char * type = "";	if (!bus) {		err ("The bus passed in NULL to find resource\n");		return -ENODEV;	}	switch (flag) {		case IO:			res_cur = bus->firstIO;			type = "io";			break;		case MEM:			res_cur = bus->firstMem;			type = "mem";			break;		case PFMEM:			res_cur = bus->firstPFMem;			type = "pfmem";			break;		default:			err ("wrong type of flag\n");			return -EINVAL;	}		while (res_cur) {		if (res_cur->start == start_address) {			*res = res_cur;			break;		}		if (res_cur->next)			res_cur = res_cur->next;		else			res_cur = res_cur->nextRange;	}	if (!res_cur) {		if (flag == PFMEM) {			res_cur = bus->firstPFMemFromMem;			while (res_cur) {				if (res_cur->start == start_address) {					*res = res_cur;					break;				}				res_cur = res_cur->next;			}			if (!res_cur) {				debug ("SOS...cannot find %s resource in the bus.\n", type);				return -EINVAL;			}		} else {			debug ("SOS... cannot find %s resource in the bus.\n", type);			return -EINVAL;		}	}	if (*res)		debug ("*res->start = %x\n", (*res)->start);	return 0;}/*********************************************************************** * This routine will free the resource structures used by the * system.  It is called from cleanup routine for the module * Parameters: none * Returns: none ***********************************************************************/void ibmphp_free_resources (void){	struct bus_node *bus_cur = NULL;	struct bus_node *bus_tmp;	struct range_node *range_cur;	struct range_node *range_tmp;	struct resource_node *res_cur;	struct resource_node *res_tmp;	struct list_head *tmp;	struct list_head *next;	int i = 0;	flags = 1;	list_for_each_safe (tmp, next, &gbuses) {		bus_cur = list_entry (tmp, struct bus_node, bus_list);		if (bus_cur->noIORanges) {			range_cur = bus_cur->rangeIO;			for (i = 0; i < bus_cur->noIORanges; i++) {				if (!range_cur)					break;				range_tmp = range_cur;				range_cur = range_cur->next;				kfree (range_tmp);				range_tmp = NULL;			}		}		if (bus_cur->noMemRanges) {			range_cur = bus_cur->rangeMem;			for (i = 0; i < bus_cur->noMemRanges; i++) {				if (!range_cur)					break;				range_tmp = range_cur;				range_cur = range_cur->next;				kfree (range_tmp);				range_tmp = NULL;			}		}		if (bus_cur->noPFMemRanges) {			range_cur = bus_cur->rangePFMem;			for (i = 0; i < bus_cur->noPFMemRanges; i++) {				if (!range_cur)					break;				range_tmp = range_cur;				range_cur = range_cur->next;				kfree (range_tmp);				range_tmp = NULL;			}		}		if (bus_cur->firstIO) {			res_cur = bus_cur->firstIO;			while (res_cur) {				res_tmp = res_cur;				if (res_cur->next)					res_cur = res_cur->next;				else					res_cur = res_cur->nextRange;				kfree (res_tmp);

⌨️ 快捷键说明

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