📄 ibmphp_pci.c
字号:
/* pfmem */ debug ("PFMEM SPACE\n"); len[count] = bar[count] & 0xFFFFFFF0; len[count] = ~len[count] + 1; debug ("len[count] in PFMEM %x, count %d\n", len[count], count); pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!pfmem[count]) { err ("out of system memory\n"); return -ENOMEM; } pfmem[count]->type = PFMEM; pfmem[count]->busno = func->busno; pfmem[count]->devfunc = PCI_DEVFN(func->device, func->function); pfmem[count]->len = len[count]; pfmem[count]->fromMem = 0; if (ibmphp_check_resource (pfmem[count], 0) == 0) { ibmphp_add_resource (pfmem[count]); func->pfmem[count] = pfmem[count]; } else { mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); kfree (pfmem[count]); return -ENOMEM; } mem_tmp->type = MEM; mem_tmp->busno = pfmem[count]->busno; mem_tmp->devfunc = pfmem[count]->devfunc; mem_tmp->len = pfmem[count]->len; debug ("there's no pfmem... going into mem.\n"); if (ibmphp_check_resource (mem_tmp, 0) == 0) { ibmphp_add_resource (mem_tmp); pfmem[count]->fromMem = 1; pfmem[count]->rangeno = mem_tmp->rangeno; pfmem[count]->start = mem_tmp->start; pfmem[count]->end = mem_tmp->end; ibmphp_add_pfmem_from_mem (pfmem[count]); func->pfmem[count] = pfmem[count]; } else { err ("cannot allocate requested pfmem for bus %x, device %x, len %x\n", func->busno, func->device, len[count]); kfree (mem_tmp); kfree (pfmem[count]); return -EIO; } } pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start); /*_______________This is for debugging purposes only______________________________*/ debug ("b4 writing, start address is %x\n", func->pfmem[count]->start); pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]); debug ("after writing, start address is %x\n", bar[count]); /*_________________________________________________________________________________*/ if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ debug ("inside the mem 64 case, count %d\n", count); count += 1; /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000); } } else { /* regular memory */ debug ("REGULAR MEM SPACE\n"); len[count] = bar[count] & 0xFFFFFFF0; len[count] = ~len[count] + 1; debug ("len[count] in Mem %x, count %d\n", len[count], count); mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!mem[count]) { err ("out of system memory\n"); return -ENOMEM; } mem[count]->type = MEM; mem[count]->busno = func->busno; mem[count]->devfunc = PCI_DEVFN(func->device, func->function); mem[count]->len = len[count]; if (ibmphp_check_resource (mem[count], 0) == 0) { ibmphp_add_resource (mem[count]); func->mem[count] = mem[count]; } else { err ("cannot allocate requested mem for bus %x, device %x, len %x\n", func->busno, func->device, len[count]); kfree (mem[count]); return -EIO; } pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->mem[count]->start); /* _______________________This is for debugging purposes only _______________________*/ debug ("b4 writing, start address is %x\n", func->mem[count]->start); pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]); debug ("after writing, the address is %x\n", bar[count]); /* __________________________________________________________________________________*/ if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ debug ("inside mem 64 case, reg. mem, count %d\n", count); count += 1; /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000); } } } /* end of mem */ } /* end of for */ func->bus = 0; /* To indicate that this is not a PPB */ pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq); if ((irq > 0x00) && (irq < 0x05)) pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]); pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); return 0;}/****************************************************************************** * This routine configures a PCI-2-PCI bridge and the functions behind it * Parameters: pci_func * Returns: ******************************************************************************/static int configure_bridge (struct pci_func **func_passed, u8 slotno){ int count; int i; int rc; u8 sec_number; u8 io_base; u16 pfmem_base; u32 bar[2]; u32 len[2]; u8 flag_io = 0; u8 flag_mem = 0; u8 flag_pfmem = 0; u8 need_io_upper = 0; u8 need_pfmem_upper = 0; struct res_needed *amount_needed = NULL; struct resource_node *io = NULL; struct resource_node *bus_io[2] = {NULL, NULL}; struct resource_node *mem = NULL; struct resource_node *bus_mem[2] = {NULL, NULL}; struct resource_node *mem_tmp = NULL; struct resource_node *pfmem = NULL; struct resource_node *bus_pfmem[2] = {NULL, NULL}; struct bus_node *bus; u32 address[] = { PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, 0 }; struct pci_func *func = *func_passed; unsigned int devfn; u8 irq; int retval; debug ("%s - enter\n", __func__); devfn = PCI_DEVFN(func->function, func->device); ibmphp_pci_bus->number = func->busno; /* Configuring necessary info for the bridge so that we could see the devices * behind it */ pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, func->busno); /* _____________________For debugging purposes only __________________________ pci_bus_config_byte (ibmphp_pci_bus, devfn, PCI_PRIMARY_BUS, &pri_number); debug ("primary # written into the bridge is %x\n", pri_number); ___________________________________________________________________________*/ /* in EBDA, only get allocated 1 additional bus # per slot */ sec_number = find_sec_number (func->busno, slotno); if (sec_number == 0xff) { err ("cannot allocate secondary bus number for the bridged device\n"); return -EINVAL; } debug ("after find_sec_number, the number we got is %x\n", sec_number); debug ("AFTER FIND_SEC_NUMBER, func->busno IS %x\n", func->busno); pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, sec_number); /* __________________For debugging purposes only __________________________________ pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number); debug ("sec_number after write/read is %x\n", sec_number); ________________________________________________________________________________*/ pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, sec_number); /* __________________For debugging purposes only ____________________________________ pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sec_number); debug ("subordinate number after write/read is %x\n", sec_number); __________________________________________________________________________________*/ pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SEC_LATENCY_TIMER, LATENCY); debug ("func->busno is %x\n", func->busno); debug ("sec_number after writing is %x\n", sec_number); /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!NEED TO ADD!!! FAST BACK-TO-BACK ENABLE!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ /* First we need to allocate mem/io for the bridge itself in case it needs it */ for (count = 0; address[count]; count++) { /* for 2 BARs */ pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF); pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]); if (!bar[count]) { /* This BAR is not implemented */ debug ("so we come here then, eh?, count = %d\n", count); continue; } // tmp_bar = bar[count]; debug ("Bar %d wants %x\n", count, bar[count]); if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) { /* This is IO */ len[count] = bar[count] & 0xFFFFFFFC; len[count] = ~len[count] + 1; debug ("len[count] in IO = %x\n", len[count]); bus_io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_io[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } bus_io[count]->type = IO; bus_io[count]->busno = func->busno; bus_io[count]->devfunc = PCI_DEVFN(func->device, func->function); bus_io[count]->len = len[count]; if (ibmphp_check_resource (bus_io[count], 0) == 0) { ibmphp_add_resource (bus_io[count]); func->io[count] = bus_io[count]; } else { err ("cannot allocate requested io for bus %x, device %x, len %x\n", func->busno, func->device, len[count]); kfree (bus_io[count]); return -EIO; } pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->io[count]->start); } else { /* This is Memory */ if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) { /* pfmem */ len[count] = bar[count] & 0xFFFFFFF0; len[count] = ~len[count] + 1; debug ("len[count] in PFMEM = %x\n", len[count]); bus_pfmem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_pfmem[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } bus_pfmem[count]->type = PFMEM; bus_pfmem[count]->busno = func->busno; bus_pfmem[count]->devfunc = PCI_DEVFN(func->device, func->function); bus_pfmem[count]->len = len[count]; bus_pfmem[count]->fromMem = 0; if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) { ibmphp_add_resource (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; } else { mem_tmp = kzalloc(sizeof(*mem_tmp), GFP_KERNEL); if (!mem_tmp) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } mem_tmp->type = MEM; mem_tmp->busno = bus_pfmem[count]->busno; mem_tmp->devfunc = bus_pfmem[count]->devfunc; mem_tmp->len = bus_pfmem[count]->len; if (ibmphp_check_resource (mem_tmp, 0) == 0) { ibmphp_add_resource (mem_tmp); bus_pfmem[count]->fromMem = 1; bus_pfmem[count]->rangeno = mem_tmp->rangeno; ibmphp_add_pfmem_from_mem (bus_pfmem[count]); func->pfmem[count] = bus_pfmem[count]; } else { err ("cannot allocate requested pfmem for bus %x, device %x, len %x\n", func->busno, func->device, len[count]); kfree (mem_tmp); kfree (bus_pfmem[count]); return -EIO; } } pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start); if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ count += 1; /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000); } } else { /* regular memory */ len[count] = bar[count] & 0xFFFFFFF0; len[count] = ~len[count] + 1; debug ("len[count] in Memory is %x\n", len[count]); bus_mem[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); if (!bus_mem[count]) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } bus_mem[count]->type = MEM; bus_mem[count]->busno = func->busno; bus_mem[count]->devfunc = PCI_DEVFN(func->device, func->function); bus_mem[count]->len = len[count]; if (ibmphp_check_resource (bus_mem[count], 0) == 0) { ibmphp_add_resource (bus_mem[count]); func->mem[count] = bus_mem[count]; } else { err ("cannot allocate requested mem for bus %x, device %x, len %x\n", func->busno, func->device, len[count]); kfree (bus_mem[count]); return -EIO; } pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->mem[count]->start); if (bar[count] & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */ count += 1; /* on the 2nd dword, write all 0s, since we can't handle them n.e.ways */ pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0x00000000); } } } /* end of mem */ } /* end of for */ /* Now need to see how much space the devices behind the bridge needed */ amount_needed = scan_behind_bridge (func, sec_number); if (amount_needed == NULL) return -ENOMEM; ibmphp_pci_bus->number = func->busno; debug ("after coming back from scan_behind_bridge\n"); debug ("amount_needed->not_correct = %x\n", amount_needed->not_correct); debug ("amount_needed->io = %x\n", amount_needed->io); debug ("amount_needed->mem = %x\n", amount_needed->mem); debug ("amount_needed->pfmem = %x\n", amount_needed->pfmem); if (amount_needed->not_correct) { debug ("amount_needed is not correct\n"); for (count = 0; address[count]; count++) { /* for 2 BARs */ if (bus_io[count]) { ibmphp_remove_resource (bus_io[count]); func->io[count] = NULL; } else if (bus_pfmem[count]) { ibmphp_remove_resource (bus_pfmem[count]); func->pfmem[count] = NULL; } else if (bus_mem[count]) { ibmphp_remove_resource (bus_mem[count]); func->mem[count] = NULL; } } kfree (amount_needed); return -ENODEV; } if (!amount_needed->io) { debug ("it doesn't want IO?\n"); flag_io = 1; } else { debug ("it wants %x IO behind the bridge\n", amount_needed->io); io = kzalloc(sizeof(*io), GFP_KERNEL); if (!io) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } io->type = IO; io->busno = func->busno; io->devfunc = PCI_DEVFN(func->device, func->function); io->len = amount_needed->io; if (ibmphp_check_resource (io, 1) == 0) { debug ("were we able to add io\n"); ibmphp_add_resource (io); flag_io = 1; } } if (!amount_needed->mem) { debug ("it doesn't want n.e.memory?\n"); flag_mem = 1; } else { debug ("it wants %x memory behind the bridge\n", amount_needed->mem); mem = kzalloc(sizeof(*mem), GFP_KERNEL); if (!mem) { err ("out of system memory\n"); retval = -ENOMEM; goto error; } mem->type = MEM; mem->busno = func->busno; mem->devfunc = PCI_DEVFN(func->device, func->function); mem->len = amount_needed->mem; if (ibmphp_check_resource (mem, 1) == 0) { ibmphp_add_resource (mem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -