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

📄 ibmphp_res.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				res_tmp = NULL;			}			bus_cur->firstIO = NULL;		}		if (bus_cur->firstMem) {			res_cur = bus_cur->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_cur->firstMem = NULL;		}		if (bus_cur->firstPFMem) {			res_cur = bus_cur->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_cur->firstPFMem = NULL;		}		if (bus_cur->firstPFMemFromMem) {			res_cur = bus_cur->firstPFMemFromMem;			while (res_cur) {				res_tmp = res_cur;				res_cur = res_cur->next;				kfree (res_tmp);				res_tmp = NULL;			}			bus_cur->firstPFMemFromMem = NULL;		}		bus_tmp = bus_cur;		list_del (&bus_cur->bus_list);		kfree (bus_tmp);		bus_tmp = NULL;	}}/********************************************************************************* * This function will go over the PFmem resources to check if the EBDA allocated * pfmem out of memory buckets of the bus.  If so, it will change the range numbers * and a flag to indicate that this resource is out of memory. It will also move the * Pfmem out of the pfmem resource list to the PFMemFromMem list, and will create * a new Mem node * This routine is called right after initialization *******************************************************************************/static int __init once_over (void){	struct resource_node *pfmem_cur;	struct resource_node *pfmem_prev;	struct resource_node *mem;	struct bus_node *bus_cur;	struct list_head *tmp;	list_for_each (tmp, &gbuses) {		bus_cur = list_entry (tmp, struct bus_node, bus_list);		if ((!bus_cur->rangePFMem) && (bus_cur->firstPFMem)) {			for (pfmem_cur = bus_cur->firstPFMem, pfmem_prev = NULL; pfmem_cur; pfmem_prev = pfmem_cur, pfmem_cur = pfmem_cur->next) {				pfmem_cur->fromMem = TRUE;				if (pfmem_prev)					pfmem_prev->next = pfmem_cur->next;				else					bus_cur->firstPFMem = pfmem_cur->next;				if (!bus_cur->firstPFMemFromMem)					pfmem_cur->next = NULL;				else					/* we don't need to sort PFMemFromMem since we're using mem node for					   all the real work anyways, so just insert at the beginning of the					   list					 */					pfmem_cur->next = bus_cur->firstPFMemFromMem;				bus_cur->firstPFMemFromMem = pfmem_cur;				mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);						if (!mem) {					err ("out of system memory\n");					return -ENOMEM;				}				memset (mem, 0, sizeof (struct resource_node));				mem->type = MEM;				mem->busno = pfmem_cur->busno;				mem->devfunc = pfmem_cur->devfunc;				mem->start = pfmem_cur->start;				mem->end = pfmem_cur->end;				mem->len = pfmem_cur->len;				if (ibmphp_add_resource (mem) < 0)					err ("Trouble...trouble... EBDA allocated pfmem from mem, but system doesn't display it has this space... unless not PCI device...\n");				pfmem_cur->rangeno = mem->rangeno;			}	/* end for pfmem */		}	/* end if */	}	/* end list_for_each bus */	return 0; }int ibmphp_add_pfmem_from_mem (struct resource_node *pfmem){	struct bus_node *bus_cur = find_bus_wprev (pfmem->busno, NULL, 0);	if (!bus_cur) {		err ("cannot find bus of pfmem to add...\n");		return -ENODEV;	}	if (bus_cur->firstPFMemFromMem)		pfmem->next = bus_cur->firstPFMemFromMem;	else		pfmem->next = NULL;	bus_cur->firstPFMemFromMem = pfmem;	return 0;}/* This routine just goes through the buses to see if the bus already exists. * It is called from ibmphp_find_sec_number, to find out a secondary bus number for * bridged cards * Parameters: bus_number * Returns: Bus pointer or NULL */struct bus_node *ibmphp_find_res_bus (u8 bus_number){	return find_bus_wprev (bus_number, NULL, 0);}static struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag){	struct bus_node *bus_cur;	struct list_head *tmp;	struct list_head *tmp_prev;	list_for_each (tmp, &gbuses) {		tmp_prev = tmp->prev;		bus_cur = list_entry (tmp, struct bus_node, bus_list);		if (flag) 			*prev = list_entry (tmp_prev, struct bus_node, bus_list);		if (bus_cur->busno == bus_number) 			return bus_cur;	}	return NULL;}void ibmphp_print_test (void){	int i = 0;	struct bus_node *bus_cur = NULL;	struct range_node *range;	struct resource_node *res;	struct list_head *tmp;		debug_pci ("*****************START**********************\n");	if ((!list_empty(&gbuses)) && flags) {		err ("The GBUSES is not NULL?!?!?!?!?\n");		return;	}	list_for_each (tmp, &gbuses) {		bus_cur = list_entry (tmp, struct bus_node, bus_list);		debug_pci ("This is bus # %d.  There are\n", bus_cur->busno);		debug_pci ("IORanges = %d\t", bus_cur->noIORanges);		debug_pci ("MemRanges = %d\t", bus_cur->noMemRanges);		debug_pci ("PFMemRanges = %d\n", bus_cur->noPFMemRanges);		debug_pci ("The IO Ranges are as follows:\n");		if (bus_cur->rangeIO) {			range = bus_cur->rangeIO;			for (i = 0; i < bus_cur->noIORanges; i++) {				debug_pci ("rangeno is %d\n", range->rangeno);				debug_pci ("[%x - %x]\n", range->start, range->end);				range = range->next;			}		}		debug_pci ("The Mem Ranges are as follows:\n");		if (bus_cur->rangeMem) {			range = bus_cur->rangeMem;			for (i = 0; i < bus_cur->noMemRanges; i++) {				debug_pci ("rangeno is %d\n", range->rangeno);				debug_pci ("[%x - %x]\n", range->start, range->end);				range = range->next;			}		}		debug_pci ("The PFMem Ranges are as follows:\n");		if (bus_cur->rangePFMem) {			range = bus_cur->rangePFMem;			for (i = 0; i < bus_cur->noPFMemRanges; i++) {				debug_pci ("rangeno is %d\n", range->rangeno);				debug_pci ("[%x - %x]\n", range->start, range->end);				range = range->next;			}		}		debug_pci ("The resources on this bus are as follows\n");		debug_pci ("IO...\n");		if (bus_cur->firstIO) {			res = bus_cur->firstIO;			while (res) {				debug_pci ("The range # is %d\n", res->rangeno);				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);				if (res->next)					res = res->next;				else if (res->nextRange)					res = res->nextRange;				else					break;			}		}		debug_pci ("Mem...\n");		if (bus_cur->firstMem) {			res = bus_cur->firstMem;			while (res) {				debug_pci ("The range # is %d\n", res->rangeno);				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);				if (res->next)					res = res->next;				else if (res->nextRange)					res = res->nextRange;				else					break;			}		}		debug_pci ("PFMem...\n");		if (bus_cur->firstPFMem) {			res = bus_cur->firstPFMem;			while (res) {				debug_pci ("The range # is %d\n", res->rangeno);				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);				if (res->next)					res = res->next;				else if (res->nextRange)					res = res->nextRange;				else					break;			}		}		debug_pci ("PFMemFromMem...\n");		if (bus_cur->firstPFMemFromMem) {			res = bus_cur->firstPFMemFromMem;			while (res) {				debug_pci ("The range # is %d\n", res->rangeno);				debug_pci ("The bus, devfnc is %d, %x\n", res->busno, res->devfunc);				debug_pci ("[%x - %x], len=%x\n", res->start, res->end, res->len);				res = res->next;			}		}	}	debug_pci ("***********************END***********************\n");}static int range_exists_already (struct range_node * range, struct bus_node * bus_cur, u8 type){	struct range_node * range_cur = NULL;	switch (type) {		case IO:			range_cur = bus_cur->rangeIO;			break;		case MEM:			range_cur = bus_cur->rangeMem;			break;		case PFMEM:			range_cur = bus_cur->rangePFMem;			break;		default:			err ("wrong type passed to find out if range already exists\n");			return -ENODEV;	}	while (range_cur) {		if ((range_cur->start == range->start) && (range_cur->end == range->end))			return 1;		range_cur = range_cur->next;	}		return 0;}/* This routine will read the windows for any PPB we have and update the * range info for the secondary bus, and will also input this info into * primary bus, since BIOS doesn't. This is for PPB that are in the system * on bootup.  For bridged cards that were added during previous load of the * driver, only the ranges and the bus structure are added, the devices are * added from NVRAM * Input: primary busno * Returns: none * Note: this function doesn't take into account IO restrictions etc, *	 so will only work for bridges with no video/ISA devices behind them It *	 also will not work for onboard PPB's that can have more than 1 *bus *	 behind them All these are TO DO. *	 Also need to add more error checkings... (from fnc returns etc) */static int __init update_bridge_ranges (struct bus_node **bus){	u8 sec_busno, device, function, hdr_type, start_io_address, end_io_address;	u16 vendor_id, upper_io_start, upper_io_end, start_mem_address, end_mem_address;	u32 start_address, end_address, upper_start, upper_end;	struct bus_node *bus_sec;	struct bus_node *bus_cur;	struct resource_node *io;	struct resource_node *mem;	struct resource_node *pfmem;	struct range_node *range;	unsigned int devfn;	bus_cur = *bus;	if (!bus_cur)		return -ENODEV;	ibmphp_pci_bus->number = bus_cur->busno;	debug ("inside %s\n", __FUNCTION__);	debug ("bus_cur->busno = %x\n", bus_cur->busno);	for (device = 0; device < 32; device++) {		for (function = 0x00; function < 0x08; function++) {			devfn = PCI_DEVFN(device, function);			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);			if (vendor_id != PCI_VENDOR_ID_NOTVALID) {				/* found correct device!!! */				pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);				switch (hdr_type) {					case PCI_HEADER_TYPE_NORMAL:						function = 0x8;						break;					case PCI_HEADER_TYPE_MULTIDEVICE:						break;					case PCI_HEADER_TYPE_BRIDGE:						function = 0x8;					case PCI_HEADER_TYPE_MULTIBRIDGE:						/* We assume here that only 1 bus behind the bridge 						   TO DO: add functionality for several:						   temp = secondary;						   while (temp < subordinate) {						   ...						   temp++;						   }						 */						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_busno);						bus_sec = find_bus_wprev (sec_busno, NULL, 0); 						/* this bus structure doesn't exist yet, PPB was configured during previous loading of ibmphp */						if (!bus_sec) {							bus_sec = alloc_error_bus (NULL, sec_busno, 1);							/* the rest will be populated during NVRAM call */							return 0;						}						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &start_io_address);						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, &end_io_address);						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_BASE_UPPER16, &upper_io_start);						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_IO_LIMIT_UPPER16, &upper_io_end);						start_address = (start_io_address & PCI_IO_RANGE_MASK) << 8;						start_address |= (upper_io_start << 16);						end_address = (end_io_address & PCI_IO_RANGE_MASK) << 8;						end_address |= (upper_io_end << 16);						if ((start_address) && (start_address <= end_address)) {							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);							if (!range) {								err ("out of system memory\n");								return -ENOMEM;							}							memset (range, 0, sizeof (struct range_node));							range->start = start_address;							range->end = end_address + 0xfff;							if (bus_sec->noIORanges > 0) {								if (!range_exists_already (range, bus_sec, IO)) {									add_range (IO, range, bus_sec);									++bus_sec->noIORanges;								} else {									kfree (range);									range = NULL;								}							} else {								/* 1st IO Range on the bus */								range->rangeno = 1;								bus_sec->rangeIO = range;								++bus_sec->noIORanges;							}							fix_resources (bus_sec);							if (ibmphp_find_resource (bus_cur, start_address, &io, IO)) {								io = kmalloc (sizeof (struct resource_node), GFP_KERNEL);															if (!io) {									kfree (range);									err ("out of system memory\n");									return -ENOMEM;								}								memset (io, 0, sizeof (struct resource_node));								io->type = IO;								io->busno = bus_cur->busno;								io->devfunc = ((device << 3) | (function & 0x7));								io->start = start_address;								io->end = end_address + 0xfff;								io->len = io->end - io->start + 1;								ibmphp_add_resource (io);							}						}							pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &start_mem_address);						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &end_mem_address);						start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;						end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;						if ((start_address) && (start_address <= end_address)) {							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);							if (!range) {								err ("out of system memory\n");								return -ENOMEM;							}							memset (range, 0, sizeof (struct range_node));							range->start = start_address;							range->end = end_address + 0xfffff;							if (bus_sec->noMemRanges > 0) {								if (!range_exists_already (range, bus_sec, MEM)) {									add_range (MEM, range, bus_sec);									++bus_sec->noMemRanges;								} else {									kfree (range);									range = NULL;								}							} else {								/* 1st Mem Range on the bus */								range->rangeno = 1;								bus_sec->rangeMem = range;								++bus_sec->noMemRanges;							}							fix_resources (bus_sec);							if (ibmphp_find_resource (bus_cur, start_address, &mem, MEM)) {								mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);								if (!mem) {									kfree (range);									err ("out of system memory\n");									return -ENOMEM;								}								memset (mem, 0, sizeof (struct resource_node));								mem->type = MEM;								mem->busno = bus_cur->busno;								mem->devfunc = ((device << 3) | (function & 0x7));								mem->start = start_address;								mem->end = end_address + 0xfffff;								mem->len = mem->end - mem->start + 1;								ibmphp_add_resource (mem);							}						}						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_BASE, &start_mem_address);						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &end_mem_address);						pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_BASE_UPPER32, &upper_start);						pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_PREF_LIMIT_UPPER32, &upper_end);						start_address = 0x00000000 | (start_mem_address & PCI_MEMORY_RANGE_MASK) << 16;						end_address = 0x00000000 | (end_mem_address & PCI_MEMORY_RANGE_MASK) << 16;#if BITS_PER_LONG == 64						start_address |= ((long) upper_start) << 32;						end_address |= ((long) upper_end) << 32;#endif						if ((start_address) && (start_address <= end_address)) {							range = kmalloc (sizeof (struct range_node), GFP_KERNEL);							if (!range) {								err ("out of system memory\n");								return -ENOMEM;							}							memset (range, 0, sizeof (struct range_node));							range->start = start_address;							range->end = end_address + 0xfffff;							if (bus_sec->noPFMemRanges > 0) {								if (!range_exists_already (range, bus_sec, PFMEM)) {									add_range (PFMEM, range, bus_sec);									++bus_sec->noPFMemRanges;								} else {									kfree (range);									range = NULL;								}							} else {								/* 1st PFMem Range on the bus */								range->rangeno = 1;								bus_sec->rangePFMem = range;								++bus_sec->noPFMemRanges;							}							fix_resources (bus_sec);							if (ibmphp_find_resource (bus_cur, start_address, &pfmem, PFMEM)) {								pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);								if (!pfmem) {									kfree (range);									err ("out of system memory\n");									return -ENOMEM;								}								memset (pfmem, 0, sizeof (struct resource_node));								pfmem->type = PFMEM;								pfmem->busno = bus_cur->busno;								pfmem->devfunc = ((device << 3) | (function & 0x7));								pfmem->start = start_address;								pfmem->end = end_address + 0xfffff;								pfmem->len = pfmem->end - pfmem->start + 1;								pfmem->fromMem = FALSE;								ibmphp_add_resource (pfmem);							}						}						break;				}	/* end of switch */			}	/* end if vendor */		}	/* end for function */	}	/* end for device */	bus = &bus_cur;	return 0;}

⌨️ 快捷键说明

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