in hotplug/cpqphp_pci.c [687:938]
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) {
/* 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 this register is implemented */
if (base) {
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 */
/* Standard header */
} else if ((header_type & 0x7F) == 0x00) {
/* 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 this register is implemented */
if (base) {
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 */
}
/* find the next device in this slot */
func = cpqhp_slot_find(func->bus, func->device, index++);
}
return 0;
}