in hotplug/ibmphp_pci.c [329:536]
static int configure_device(struct pci_func *func)
{
u32 bar[6];
u32 address[] = {
PCI_BASE_ADDRESS_0,
PCI_BASE_ADDRESS_1,
PCI_BASE_ADDRESS_2,
PCI_BASE_ADDRESS_3,
PCI_BASE_ADDRESS_4,
PCI_BASE_ADDRESS_5,
0
};
u8 irq;
int count;
int len[6];
struct resource_node *io[6];
struct resource_node *mem[6];
struct resource_node *mem_tmp;
struct resource_node *pfmem[6];
unsigned int devfn;
debug("%s - inside\n", __func__);
devfn = PCI_DEVFN(func->device, func->function);
ibmphp_pci_bus->number = func->busno;
for (count = 0; address[count]; count++) { /* for 6 BARs */
/* not sure if i need this. per scott, said maybe need * something like this
if devices don't adhere 100% to the spec, so don't want to write
to the reserved bits
pcibios_read_config_byte(cur_func->busno, cur_func->device,
PCI_BASE_ADDRESS_0 + 4 * count, &tmp);
if (tmp & 0x01) // IO
pcibios_write_config_dword(cur_func->busno, cur_func->device,
PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFD);
else // Memory
pcibios_write_config_dword(cur_func->busno, cur_func->device,
PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFF);
*/
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 */
continue;
debug("Device %x BAR %d wants %x\n", func->device, count, bar[count]);
if (bar[count] & PCI_BASE_ADDRESS_SPACE_IO) {
/* This is IO */
debug("inside IO SPACE\n");
len[count] = bar[count] & 0xFFFFFFFC;
len[count] = ~len[count] + 1;
debug("len[count] in IO %x, count %d\n", len[count], count);
io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL);
if (!io[count])
return -ENOMEM;
io[count]->type = IO;
io[count]->busno = func->busno;
io[count]->devfunc = PCI_DEVFN(func->device, func->function);
io[count]->len = len[count];
if (ibmphp_check_resource(io[count], 0) == 0) {
ibmphp_add_resource(io[count]);
func->io[count] = io[count];
} else {
err("cannot allocate requested io for bus %x device %x function %x len %x\n",
func->busno, func->device, func->function, len[count]);
kfree(io[count]);
return -EIO;
}
pci_bus_write_config_dword(ibmphp_pci_bus, devfn, address[count], func->io[count]->start);
/* _______________This is for debugging purposes only_____________________ */
debug("b4 writing, the IO address is %x\n", func->io[count]->start);
pci_bus_read_config_dword(ibmphp_pci_bus, devfn, address[count], &bar[count]);
debug("after writing.... the start address is %x\n", bar[count]);
/* _________________________________________________________________________*/
} else {
/* This is Memory */
if (bar[count] & PCI_BASE_ADDRESS_MEM_PREFETCH) {
/* 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])
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) {
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])
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;
}