static int configure_device()

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;
}