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

📄 cpqphp_pci.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			for (cloop = 0; cloop < 0x20; cloop++) {				pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), cloop << 2, (u32 *) & (new_slot-> config_space [cloop]));			}			function++;			stop_it = 0;			//  this loop skips to the next present function			//  reading in the Class Code and the Header type.			while ((function < max_functions) && (!stop_it)) {				pci_bus_read_config_dword (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_VENDOR_ID, &ID);				if (ID == 0xFFFFFFFF) {	 // nothing there.					function++;				} else {  // Something there					pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), 0x0B, &class_code);					pci_bus_read_config_byte (ctrl->pci_bus, PCI_DEVFN(new_slot->device, function), PCI_HEADER_TYPE, &header_type);					stop_it++;				}			}		} while (function < max_functions);	}			// End of IF (device in slot?)	else {		return 2;	}	return 0;}/* * cpqhp_save_base_addr_length * * Saves the length of all base address registers for the * specified slot.  this is for hot plug REPLACE * * returns 0 if success */int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func){	u8 cloop;	u8 header_type;	u8 secondary_bus;	u8 type;	int sub_bus;	u32 temp_register;	u32 base;	u32 rc;	struct pci_func *next;	int index = 0;	struct pci_bus *pci_bus = ctrl->pci_bus;	unsigned int devfn;	func = cpqhp_slot_find(func->bus, func->device, index++);	while (func != NULL) {		pci_bus->number = func->bus;		devfn = PCI_DEVFN(func->device, func->function);		// Check for Bridge		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {			// PCI-PCI Bridge			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);			sub_bus = (int) secondary_bus;			next = cpqhp_slot_list[sub_bus];			while (next != NULL) {				rc = cpqhp_save_base_addr_length(ctrl, next);				if (rc)					return rc;				next = next->next;			}			pci_bus->number = func->bus;			//FIXME: this loop is duplicated in the non-bridge case.  The two could be rolled together			// Figure out IO and memory base lengths			for (cloop = 0x10; cloop <= 0x14; cloop += 4) {				temp_register = 0xFFFFFFFF;				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);				if (base) {  // If this register is implemented					if (base & 0x01L) {						// IO base						// set base = amount of IO space requested						base = base & 0xFFFFFFFE;						base = (~base) + 1;						type = 1;					} else {						// memory base						base = base & 0xFFFFFFF0;						base = (~base) + 1;						type = 0;					}				} else {					base = 0x0L;					type = 0;				}				// Save information in slot structure				func->base_length[(cloop - 0x10) >> 2] =				base;				func->base_type[(cloop - 0x10) >> 2] = type;			}	// End of base register loop		} else if ((header_type & 0x7F) == 0x00) {	  // PCI-PCI Bridge			// Figure out IO and memory base lengths			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {				temp_register = 0xFFFFFFFF;				pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);				pci_bus_read_config_dword (pci_bus, devfn, cloop, &base);				if (base) {  // If this register is implemented					if (base & 0x01L) {						// IO base						// base = amount of IO space requested						base = base & 0xFFFFFFFE;						base = (~base) + 1;						type = 1;					} else {						// memory base						// base = amount of memory space requested						base = base & 0xFFFFFFF0;						base = (~base) + 1;						type = 0;					}				} else {					base = 0x0L;					type = 0;				}				// Save information in slot structure				func->base_length[(cloop - 0x10) >> 2] = base;				func->base_type[(cloop - 0x10) >> 2] = type;			}	// End of base register loop		} else {	  // Some other unknown header type		}		// find the next device in this slot		func = cpqhp_slot_find(func->bus, func->device, index++);	}	return(0);}/* * cpqhp_save_used_resources * * Stores used resource information for existing boards.  this is * for boards that were in the system when this driver was loaded. * this function is for hot plug ADD * * returns 0 if success */int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func){	u8 cloop;	u8 header_type;	u8 secondary_bus;	u8 temp_byte;	u8 b_base;	u8 b_length;	u16 command;	u16 save_command;	u16 w_base;	u16 w_length;	u32 temp_register;	u32 save_base;	u32 base;	int index = 0;	struct pci_resource *mem_node;	struct pci_resource *p_mem_node;	struct pci_resource *io_node;	struct pci_resource *bus_node;	struct pci_bus *pci_bus = ctrl->pci_bus;	unsigned int devfn;	func = cpqhp_slot_find(func->bus, func->device, index++);	while ((func != NULL) && func->is_a_board) {		pci_bus->number = func->bus;		devfn = PCI_DEVFN(func->device, func->function);		// Save the command register		pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);		// disable card		command = 0x00;		pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);		// Check for Bridge		pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge			// Clear Bridge Control Register			command = 0x00;			pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);			pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);			pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);			bus_node = kmalloc(sizeof(*bus_node), GFP_KERNEL);			if (!bus_node)				return -ENOMEM;			bus_node->base = secondary_bus;			bus_node->length = temp_byte - secondary_bus + 1;			bus_node->next = func->bus_head;			func->bus_head = bus_node;			// Save IO base and Limit registers			pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &b_base);			pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &b_length);			if ((b_base <= b_length) && (save_command & 0x01)) {				io_node = kmalloc(sizeof(*io_node), GFP_KERNEL);				if (!io_node)					return -ENOMEM;				io_node->base = (b_base & 0xF0) << 8;				io_node->length = (b_length - b_base + 0x10) << 8;				io_node->next = func->io_head;				func->io_head = io_node;			}			// Save memory base and Limit registers			pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);			pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);			if ((w_base <= w_length) && (save_command & 0x02)) {				mem_node = kmalloc(sizeof(*mem_node), GFP_KERNEL);				if (!mem_node)					return -ENOMEM;				mem_node->base = w_base << 16;				mem_node->length = (w_length - w_base + 0x10) << 16;				mem_node->next = func->mem_head;				func->mem_head = mem_node;			}			// Save prefetchable memory base and Limit registers			pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);			pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);			if ((w_base <= w_length) && (save_command & 0x02)) {				p_mem_node = kmalloc(sizeof(*p_mem_node), GFP_KERNEL);				if (!p_mem_node)					return -ENOMEM;				p_mem_node->base = w_base << 16;				p_mem_node->length = (w_length - w_base + 0x10) << 16;				p_mem_node->next = func->p_mem_head;				func->p_mem_head = p_mem_node;			}			// Figure out IO and memory base lengths			for (cloop = 0x10; cloop <= 0x14; cloop += 4) {				pci_bus_read_config_dword (pci_bus, devfn, cloop, &save_base);				temp_register = 0xFFFFFFFF;				pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);				pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);				temp_register = base;				if (base) {  // If this register is implemented					if (((base & 0x03L) == 0x01)					    && (save_command & 0x01)) {						// IO base						// set temp_register = amount of IO space requested						temp_register = base & 0xFFFFFFFE;						temp_register = (~temp_register) + 1;						io_node = kmalloc(sizeof(*io_node),								GFP_KERNEL);						if (!io_node)							return -ENOMEM;						io_node->base =						save_base & (~0x03L);						io_node->length = temp_register;						io_node->next = func->io_head;						func->io_head = io_node;					} else						if (((base & 0x0BL) == 0x08)						    && (save_command & 0x02)) {						// prefetchable memory base						temp_register = base & 0xFFFFFFF0;						temp_register = (~temp_register) + 1;						p_mem_node = kmalloc(sizeof(*p_mem_node),								GFP_KERNEL);						if (!p_mem_node)							return -ENOMEM;						p_mem_node->base = save_base & (~0x0FL);						p_mem_node->length = temp_register;						p_mem_node->next = func->p_mem_head;						func->p_mem_head = p_mem_node;					} else						if (((base & 0x0BL) == 0x00)						    && (save_command & 0x02)) {						// prefetchable memory base						temp_register = base & 0xFFFFFFF0;						temp_register = (~temp_register) + 1;						mem_node = kmalloc(sizeof(*mem_node),								GFP_KERNEL);						if (!mem_node)							return -ENOMEM;						mem_node->base = save_base & (~0x0FL);						mem_node->length = temp_register;						mem_node->next = func->mem_head;						func->mem_head = mem_node;					} else						return(1);				}			}	// End of base register loop		} else if ((header_type & 0x7F) == 0x00) {	  // Standard header			// Figure out IO and memory base lengths			for (cloop = 0x10; cloop <= 0x24; cloop += 4) {				pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);				temp_register = 0xFFFFFFFF;				pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);				pci_bus_read_config_dword(pci_bus, devfn, cloop, &base);				temp_register = base;				if (base) {	  // If this register is implemented					if (((base & 0x03L) == 0x01)					    && (save_command & 0x01)) {						// IO base						// set temp_register = amount of IO space requested						temp_register = base & 0xFFFFFFFE;						temp_register = (~temp_register) + 1;						io_node = kmalloc(sizeof(*io_node),								GFP_KERNEL);						if (!io_node)							return -ENOMEM;						io_node->base = save_base & (~0x01L);						io_node->length = temp_register;						io_node->next = func->io_head;						func->io_head = io_node;					} else						if (((base & 0x0BL) == 0x08)						    && (save_command & 0x02)) {						// prefetchable memory base						temp_register = base & 0xFFFFFFF0;						temp_register = (~temp_register) + 1;						p_mem_node = kmalloc(sizeof(*p_mem_node),								GFP_KERNEL);						if (!p_mem_node)							return -ENOMEM;						p_mem_node->base = save_base & (~0x0FL);						p_mem_node->length = temp_register;						p_mem_node->next = func->p_mem_head;						func->p_mem_head = p_mem_node;					} else						if (((base & 0x0BL) == 0x00)						    && (save_command & 0x02)) {						// prefetchable memory base						temp_register = base & 0xFFFFFFF0;						temp_register = (~temp_register) + 1;						mem_node = kmalloc(sizeof(*mem_node),								GFP_KERNEL);						if (!mem_node)							return -ENOMEM;						mem_node->base = save_base & (~0x0FL);						mem_node->length = temp_register;						mem_node->next = func->mem_head;						func->mem_head = mem_node;					} else						return(1);				}			}	// End of base register loop		} else {	  // Some other unknown header type		}		// find the next device in this slot		func = cpqhp_slot_find(func->bus, func->device, index++);	}	return(0);}/* * cpqhp_configure_board * * Copies saved configuration information to one slot. * this is called recursively for bridge devices. * this is for hot plug REPLACE! * * returns 0 if success */int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func){	int cloop;	u8 header_type;	u8 secondary_bus;	int sub_bus;	struct pci_func *next;	u32 temp;	u32 rc;	int index = 0;	struct pci_bus *pci_bus = ctrl->pci_bus;	unsigned int devfn;	func = cpqhp_slot_find(func->bus, func->device, index++);	while (func != NULL) {		pci_bus->number = func->bus;		devfn = PCI_DEVFN(func->device, func->function);		// Start at the top of config space so that the control		// registers are programmed last		for (cloop = 0x3C; cloop > 0; cloop -= 4) {			pci_bus_write_config_dword (pci_bus, devfn, cloop, func->config_space[cloop >> 2]);		}		pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);		// If this is a bridge device, restore subordinate devices		if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {	  // PCI-PCI Bridge			pci_bus_read_config_byte (pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);			sub_bus = (int) secondary_bus;			next = cpqhp_slot_list[sub_bus];			while (next != NULL) {				rc = cpqhp_configure_board(ctrl, next);				if (rc)					return rc;				next = next->next;			}		} else {			// Check all the base Address Registers to make sure			// they are the same.  If not, the board is different.			for (cloop = 16; cloop < 40; cloop += 4) {				pci_bus_read_config_dword (pci_bus, devfn, cloop, &temp);				if (temp != func->config_space[cloop >> 2]) {					dbg("Config space compare failure!!! offset = %x\n", cloop);					dbg("bus = %x, device = %x, function = %x\n", func->bus, func->device, func->function);					dbg("temp = %x, config space = %x\n\n", temp, func->config_space[cloop >> 2]);					return 1;				}			}		}		func->configured = 1;		func = cpqhp_slot_find(func->bus, func->device, index++);	}	return 0;}/* * cpqhp_valid_replace * * this function checks to see if a board is the same as the * one it is replacing.  this check will detect if the device's * vendor or device id's are the same * * returns 0 if the board is the same nonzero otherwise */int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func){	u8 cloop;	u8 header_type;	u8 secondary_bus;	u8 type;	u32 temp_register = 0;	u32 base;	u32 rc;	struct pci_func *next;	int index = 0;	struct pci_bus *pci_bus = ctrl->pci_bus;

⌨️ 快捷键说明

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