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

📄 ibmphp_pci.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {					/* takes up another dword */					count += 1;				}			} else {				/* regular memory */				start_address &= PCI_BASE_ADDRESS_MEM_MASK;				debug ("start address of mem is %x\n", start_address);				if (ibmphp_find_resource (bus, start_address, &mem, MEM) < 0) {					err ("cannot find corresponding MEM resource to remove\n");					return -EIO;				}				if (mem)					debug ("mem->start = %x\n", mem->start);				ibmphp_remove_resource (mem);				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {					/* takes up another dword */					count += 1;				}			}		}	/* end of mem */	}	/* end of for */	return 0;}static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function){	int count;	int bus_no, pri_no, sub_no, sec_no = 0;	u32 start_address, tmp_address;	u8 sec_number, sub_number, pri_number;	struct resource_node *io = NULL;	struct resource_node *mem = NULL;	struct resource_node *pfmem = NULL;	struct bus_node *bus;	u32 address[] = {		PCI_BASE_ADDRESS_0,		PCI_BASE_ADDRESS_1,		0	};	unsigned int devfn;	devfn = PCI_DEVFN(device, function);	ibmphp_pci_bus->number = busno;	bus_no = (int) busno;	debug ("busno is %x\n", busno);	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number);	debug ("%s - busno = %x, primary_number = %x\n", __FUNCTION__, busno, pri_number);	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);	debug ("sec_number is %x\n", sec_number);	sec_no = (int) sec_number;	pri_no = (int) pri_number;	if (pri_no != bus_no) {		err ("primary numbers in our structures and pci config space don't match.\n");		return -EINVAL;	}	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);	sec_no = (int) sec_no;	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sub_number);	sub_no = (int) sub_number;	debug ("sub_no is %d, sec_no is %d\n", sub_no, sec_no);	if (sec_no != sub_number) {		err ("there're more buses behind this bridge.  Hot removal is not supported.  Please choose another card\n");		return -ENODEV;	}	bus = ibmphp_find_res_bus (sec_number);	debug ("bus->busno is %x\n", bus->busno);	debug ("sec_number is %x\n", sec_number);	if (!bus) {		err ("cannot find Bus structure for the bridged device\n");		return -EINVAL;	}	ibmphp_remove_bus (bus, busno);	for (count = 0; address[count]; count++) {		/* for 2 BARs */		pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &start_address);		if (!start_address) {			/* This BAR is not implemented */			continue;		}		tmp_address = start_address;		if (start_address & PCI_BASE_ADDRESS_SPACE_IO) {			/* This is IO */			start_address &= PCI_BASE_ADDRESS_IO_MASK;			if (ibmphp_find_resource (bus, start_address, &io, IO) < 0) {				err ("cannot find corresponding IO resource to remove\n");				return -EIO;			}			if (io)				debug ("io->start = %x\n", io->start);			ibmphp_remove_resource (io);			/* ????????? DO WE NEED TO WRITE ANYTHING INTO THE PCI CONFIG SPACE BACK ?????????? */		} else {			/* This is Memory */			if (start_address & PCI_BASE_ADDRESS_MEM_PREFETCH) {				/* pfmem */				start_address &= PCI_BASE_ADDRESS_MEM_MASK;				if (ibmphp_find_resource (bus, start_address, &pfmem, PFMEM) < 0) {					err ("cannot find corresponding PFMEM resource to remove\n");					return -EINVAL;				}				if (pfmem)					debug ("pfmem->start = %x\n", pfmem->start);				ibmphp_remove_resource (pfmem);				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {					/* takes up another dword */					count += 1;				}			} else {				/* regular memory */				start_address &= PCI_BASE_ADDRESS_MEM_MASK;				if (ibmphp_find_resource (bus, start_address, &mem, MEM) < 0) {					err ("cannot find corresponding MEM resource to remove\n");					return -EINVAL;				}				if (mem)					debug ("mem->start = %x\n", mem->start);				ibmphp_remove_resource (mem);				if (tmp_address & PCI_BASE_ADDRESS_MEM_TYPE_64) {					/* takes up another dword */					count += 1;				}			}		}	/* end of mem */	}	/* end of for */	debug ("%s - exiting, returning success\n", __FUNCTION__);	return 0;}static int unconfigure_boot_card (struct slot *slot_cur){	u16 vendor_id;	u32 class;	u8 hdr_type;	u8 device;	u8 busno;	u8 function;	int rc;	unsigned int devfn;	u8 valid_device = 0x00; /* To see if we are ever able to find valid device and read it */	debug ("%s - enter\n", __FUNCTION__);	device = slot_cur->device;	busno = slot_cur->bus;	debug ("b4 for loop, device is %x\n", device);	/* For every function on the card */	for (function = 0x0; function < 0x08; function++) {		devfn = PCI_DEVFN(device, function);		ibmphp_pci_bus->number = busno;		pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_VENDOR_ID, &vendor_id);		if (vendor_id != PCI_VENDOR_ID_NOTVALID) {			/* found correct device!!! */			++valid_device;			debug ("%s - found correct device\n", __FUNCTION__);			/* header: x x x x x x x x			 *         | |___________|=> 1=PPB bridge, 0=normal device, 2=CardBus Bridge			 *         |_=> 0 = single function device, 1 = multi-function device			 */			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_HEADER_TYPE, &hdr_type);			pci_bus_read_config_dword (ibmphp_pci_bus, devfn, PCI_CLASS_REVISION, &class);			debug ("hdr_type %x, class %x\n", hdr_type, class);			class >>= 8;	/* to take revision out, class = class.subclass.prog i/f */			if (class == PCI_CLASS_NOT_DEFINED_VGA) {				err ("The device %x function %x is VGA compatible and is not supported for hot removing. "				     "Please choose another device.\n", device, function);				return -ENODEV;			} else if (class == PCI_CLASS_DISPLAY_VGA) {				err ("The device %x function %x is not supported for hot removing. "				     "Please choose another device.\n", device, function);				return -ENODEV;			}			switch (hdr_type) {				case PCI_HEADER_TYPE_NORMAL:					rc = unconfigure_boot_device (busno, device, function);					if (rc) {						err ("was not able to unconfigure device %x func %x on bus %x. bailing out...\n",						     device, function, busno);						return rc;					}					function = 0x8;					break;				case PCI_HEADER_TYPE_MULTIDEVICE:					rc = unconfigure_boot_device (busno, device, function);					if (rc) {						err ("was not able to unconfigure device %x func %x on bus %x. bailing out...\n",						     device, function, busno);						return rc;					}					break;				case PCI_HEADER_TYPE_BRIDGE:					class >>= 8;					if (class != PCI_CLASS_BRIDGE_PCI) {						err ("This device %x function %x is not PCI-to-PCI bridge, "						     "and is not supported for hot-removing. "						     "Please try another card.\n", device, function);						return -ENODEV;					}					rc = unconfigure_boot_bridge (busno, device, function);					if (rc != 0) {						err ("was not able to hot-remove PPB properly.\n");						return rc;					}					function = 0x8;					break;				case PCI_HEADER_TYPE_MULTIBRIDGE:					class >>= 8;					if (class != PCI_CLASS_BRIDGE_PCI) {						err ("This device %x function %x is not PCI-to-PCI bridge, "						     "and is not supported for hot-removing. "						     "Please try another card.\n", device, function);						return -ENODEV;					}					rc = unconfigure_boot_bridge (busno, device, function);					if (rc != 0) {						err ("was not able to hot-remove PPB properly.\n");						return rc;					}					break;				default:					err ("MAJOR PROBLEM!!!! Cannot read device's header\n");					return -1;					break;			}	/* end of switch */		}	/* end of valid device */	}	/* end of for */	if (!valid_device) {		err ("Could not find device to unconfigure.  Or could not read the card.\n");		return -1;	}	return 0;}/* * free the resources of the card (multi, single, or bridged) * Parameters: slot, flag to say if this is for removing entire module or just * unconfiguring the device * TO DO:  will probably need to add some code in case there was some resource, * to remove it... this is from when we have errors in the configure_card... * 			!!!!!!!!!!!!!!!!!!!!!!!!!FOR BUSES!!!!!!!!!!!! * Returns: 0, -1, -ENODEV  */int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end){	int i;	int count;	int rc;	struct slot *sl = *slot_cur;	struct pci_func *cur_func = NULL;	struct pci_func *temp_func;	debug ("%s - enter\n", __FUNCTION__);	if (!the_end) {		/* Need to unconfigure the card */		rc = unconfigure_boot_card (sl);		if ((rc == -ENODEV) || (rc == -EIO) || (rc == -EINVAL)) {			/* In all other cases, will still need to get rid of func structure if it exists */			return rc;		}	}	if (sl->func) {		cur_func = sl->func;		while (cur_func) {			/* TO DO: WILL MOST LIKELY NEED TO GET RID OF THE BUS STRUCTURE FROM RESOURCES AS WELL */			if (cur_func->bus) {				/* in other words, it's a PPB */				count = 2;			} else {				count = 6;			}			for (i = 0; i < count; i++) {				if (cur_func->io[i]) {					debug ("io[%d] exists\n", i);					if (the_end > 0)						ibmphp_remove_resource (cur_func->io[i]);					cur_func->io[i] = NULL;				}				if (cur_func->mem[i]) {					debug ("mem[%d] exists\n", i);					if (the_end > 0)						ibmphp_remove_resource (cur_func->mem[i]);					cur_func->mem[i] = NULL;				}				if (cur_func->pfmem[i]) {					debug ("pfmem[%d] exists\n", i);					if (the_end > 0)						ibmphp_remove_resource (cur_func->pfmem[i]);					cur_func->pfmem[i] = NULL;				}			}			temp_func = cur_func->next;			kfree (cur_func);			cur_func = temp_func;		}	}	sl->func = NULL;	*slot_cur = sl;	debug ("%s - exit\n", __FUNCTION__);	return 0;}/* * add a new bus resulting from hot-plugging a PPB bridge with devices * * Input: bus and the amount of resources needed (we know we can assign those, *        since they've been checked already * Output: bus added to the correct spot *         0, -1, error  */static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct resource_node *mem, struct resource_node *pfmem, u8 parent_busno){	struct range_node *io_range = NULL;	struct range_node *mem_range = NULL;	struct range_node *pfmem_range = NULL;	struct bus_node *cur_bus = NULL;	/* Trying to find the parent bus number */	if (parent_busno != 0xFF) {		cur_bus	= ibmphp_find_res_bus (parent_busno);		if (!cur_bus) {			err ("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n");			return -ENODEV;		}			list_add (&bus->bus_list, &cur_bus->bus_list);	}	if (io) {		io_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);		if (!io_range) {			err ("out of system memory\n");			return -ENOMEM;		}		memset (io_range, 0, sizeof (struct range_node));		io_range->start = io->start;		io_range->end = io->end;		io_range->rangeno = 1;		bus->noIORanges = 1;		bus->rangeIO = io_range;	}	if (mem) {		mem_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);		if (!mem_range) {			err ("out of system memory\n");			return -ENOMEM;		}		memset (mem_range, 0, sizeof (struct range_node));		mem_range->start = mem->start;		mem_range->end = mem->end;		mem_range->rangeno = 1;		bus->noMemRanges = 1;		bus->rangeMem = mem_range;	}	if (pfmem) {		pfmem_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);		if (!pfmem_range) {				err ("out of system memory\n");			return -ENOMEM;		}		memset (pfmem_range, 0, sizeof (struct range_node));		pfmem_range->start = pfmem->start;		pfmem_range->end = pfmem->end;		pfmem_range->rangeno = 1;		bus->noPFMemRanges = 1;		bus->rangePFMem = pfmem_range;	}	return 0;}/* * find the 1st available bus number for PPB to set as its secondary bus * Parameters: bus_number of the primary bus * Returns: bus_number of the secondary bus or 0xff in case of failure */static u8 find_sec_number (u8 primary_busno, u8 slotno){	int min, max;	u8 busno;	struct bus_info *bus;	struct bus_node *bus_cur;	bus = ibmphp_find_same_bus_num (primary_busno);	if (!bus) {		err ("cannot get slot range of the bus from the BIOS\n");		return 0xff;	}	max = bus->slot_max;	min = bus->slot_min;	if ((slotno > max) || (slotno < min)) {		err ("got the wrong range\n");		return 0xff;	}	busno = (u8) (slotno - (u8) min);	busno += primary_busno + 0x01;	bus_cur = ibmphp_find_res_bus (busno);	/* either there is no such bus number, or there are no ranges, which	 * can only happen if we removed the bridged device in previous load	 * of the driver, and now only have the skeleton bus struct	 */	if ((!bus_cur) || (!(bus_cur->rangeIO) && !(bus_cur->rangeMem) && !(bus_cur->rangePFMem)))		return busno;	return 0xff;}

⌨️ 快捷键说明

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