/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved.
 */

#include <asm/sn/types.h>
#include <asm/sn/addrs.h>
#include <asm/sn/pcidev.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/sn_sal.h>
#include "xtalk/hubdev.h"
#include <linux/acpi.h>
#include <acpi/acnamesp.h>


/*
 * The code in this file will only be executed when running with
 * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1)
 */


/*
 * This value must match the UUID the PROM uses
 * (io/acpi/defblk.c) when building a vendor descriptor.
 */
struct acpi_vendor_uuid sn_uuid = {
	.subtype = 0,
	.data	= { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
		    0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
};

struct sn_pcidev_match {
	u8 bus;
	unsigned int devfn;
	acpi_handle handle;
};

/*
 * Perform the early IO init in PROM.
 */
static s64
sal_ioif_init(u64 *result)
{
	struct ia64_sal_retval isrv = {0,0,0,0};

	SAL_CALL_NOLOCK(isrv,
			SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0);
	*result = isrv.v0;
	return isrv.status;
}

/*
 * sn_acpi_hubdev_init() - This function is called by acpi_ns_get_device_callback()
 *			   for all SGIHUB and SGITIO acpi devices defined in the
 *			   DSDT. It obtains the hubdev_info pointer from the
 *			   ACPI vendor resource, which the PROM setup, and sets up the
 *			   hubdev_info in the pda.
 */

static acpi_status __init
sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret)
{
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	u64 addr;
	struct hubdev_info *hubdev;
	struct hubdev_info *hubdev_ptr;
	int i;
	u64 nasid;
	struct acpi_resource *resource;
	acpi_status status;
	struct acpi_resource_vendor_typed *vendor;
	extern void sn_common_hubdev_init(struct hubdev_info *);

	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
					  &sn_uuid, &buffer);
	if (ACPI_FAILURE(status)) {
		printk(KERN_ERR
		       "sn_acpi_hubdev_init: acpi_get_vendor_resource() "
		       "(0x%x) failed for: ", status);
		acpi_ns_print_node_pathname(handle, NULL);
		printk("\n");
		return AE_OK;		/* Continue walking namespace */
	}

	resource = buffer.pointer;
	vendor = &resource->data.vendor_typed;
	if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
	    sizeof(struct hubdev_info *)) {
		printk(KERN_ERR
		       "sn_acpi_hubdev_init: Invalid vendor data length: %d for: ",
		        vendor->byte_length);
		acpi_ns_print_node_pathname(handle, NULL);
		printk("\n");
		goto exit;
	}

	memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *));
	hubdev_ptr = __va((struct hubdev_info *) addr);

	nasid = hubdev_ptr->hdi_nasid;
	i = nasid_to_cnodeid(nasid);
	hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
	*hubdev = *hubdev_ptr;
	sn_common_hubdev_init(hubdev);

exit:
	kfree(buffer.pointer);
	return AE_OK;		/* Continue walking namespace */
}

/*
 * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
 *			  the ACPI Vendor resource for this bus.
 */
static struct pcibus_bussoft *
sn_get_bussoft_ptr(struct pci_bus *bus)
{
	u64 addr;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	acpi_handle handle;
	struct pcibus_bussoft *prom_bussoft_ptr;
	struct acpi_resource *resource;
	acpi_status status;
	struct acpi_resource_vendor_typed *vendor;


	handle = PCI_CONTROLLER(bus)->acpi_handle;
	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
					  &sn_uuid, &buffer);
	if (ACPI_FAILURE(status)) {
		printk(KERN_ERR "%s: "
		       "acpi_get_vendor_resource() failed (0x%x) for: ",
		       __FUNCTION__, status);
		acpi_ns_print_node_pathname(handle, NULL);
		printk("\n");
		return NULL;
	}
	resource = buffer.pointer;
	vendor = &resource->data.vendor_typed;

	if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
	     sizeof(struct pcibus_bussoft *)) {
		printk(KERN_ERR
		       "%s: Invalid vendor data length %d\n",
			__FUNCTION__, vendor->byte_length);
		kfree(buffer.pointer);
		return NULL;
	}
	memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *));
	prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr);
	kfree(buffer.pointer);

	return prom_bussoft_ptr;
}

/*
 * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info
 *			    pointers from the vendor resource using the
 *			    provided acpi handle, and copy the structures
 *			    into the argument buffers.
 */
static int
sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
		    struct sn_irq_info **sn_irq_info)
{
	u64 addr;
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	struct sn_irq_info *irq_info, *irq_info_prom;
	struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr;
	struct acpi_resource *resource;
	int ret = 0;
	acpi_status status;
	struct acpi_resource_vendor_typed *vendor;

	/*
	 * The pointer to this device's pcidev_info structure in
	 * the PROM, is in the vendor resource.
	 */
	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
					  &sn_uuid, &buffer);
	if (ACPI_FAILURE(status)) {
		printk(KERN_ERR
		       "%s: acpi_get_vendor_resource() failed (0x%x) for: ",
		        __FUNCTION__, status);
		acpi_ns_print_node_pathname(handle, NULL);
		printk("\n");
		return 1;
	}

	resource = buffer.pointer;
	vendor = &resource->data.vendor_typed;
	if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
	    sizeof(struct pci_devdev_info *)) {
		printk(KERN_ERR
		       "%s: Invalid vendor data length: %d for: ",
		        __FUNCTION__, vendor->byte_length);
		acpi_ns_print_node_pathname(handle, NULL);
		printk("\n");
		ret = 1;
		goto exit;
	}

	pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
	if (!pcidev_ptr)
		panic("%s: Unable to alloc memory for pcidev_info", __FUNCTION__);

	memcpy(&addr, vendor->byte_data, sizeof(struct pcidev_info *));
	pcidev_prom_ptr = __va(addr);
	memcpy(pcidev_ptr, pcidev_prom_ptr, sizeof(struct pcidev_info));

	/* Get the IRQ info */
	irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
	if (!irq_info)
		 panic("%s: Unable to alloc memory for sn_irq_info", __FUNCTION__);

	if (pcidev_ptr->pdi_sn_irq_info) {
		irq_info_prom = __va(pcidev_ptr->pdi_sn_irq_info);
		memcpy(irq_info, irq_info_prom, sizeof(struct sn_irq_info));
	}

	*pcidev_info = pcidev_ptr;
	*sn_irq_info = irq_info;

exit:
	kfree(buffer.pointer);
	return ret;
}

static unsigned int
get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
{
	unsigned long adr;
	acpi_handle child;
	unsigned int devfn;
	int function;
	acpi_handle parent;
	int slot;
	acpi_status status;

	/*
	 * Do an upward search to find the root bus device, and
	 * obtain the host devfn from the previous child device.
	 */
	child = device_handle;
	while (child) {
		status = acpi_get_parent(child, &parent);
		if (ACPI_FAILURE(status)) {
			printk(KERN_ERR "%s: acpi_get_parent() failed "
			       "(0x%x) for: ", __FUNCTION__, status);
			acpi_ns_print_node_pathname(child, NULL);
			printk("\n");
			panic("%s: Unable to find host devfn\n", __FUNCTION__);
		}
		if (parent == rootbus_handle)
			break;
		child = parent;
	}
	if (!child) {
		printk(KERN_ERR "%s: Unable to find root bus for: ",
		       __FUNCTION__);
		acpi_ns_print_node_pathname(device_handle, NULL);
		printk("\n");
		BUG();
	}

	status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr);
	if (ACPI_FAILURE(status)) {
		printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: ",
		       __FUNCTION__, status);
		acpi_ns_print_node_pathname(child, NULL);
		printk("\n");
		panic("%s: Unable to find host devfn\n", __FUNCTION__);
	}

	slot = (adr >> 16) & 0xffff;
	function = adr & 0xffff;
	devfn = PCI_DEVFN(slot, function);
	return devfn;
}

/*
 * find_matching_device - Callback routine to find the ACPI device
 *			  that matches up with our pci_dev device.
 *			  Matching is done on bus number and devfn.
 *			  To find the bus number for a particular
 *			  ACPI device, we must look at the _BBN method
 *			  of its parent.
 */
static acpi_status
find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
{
	unsigned long bbn = -1;
	unsigned long adr;
	acpi_handle parent = NULL;
	acpi_status status;
	unsigned int devfn;
	int function;
	int slot;
	struct sn_pcidev_match *info = context;

        status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
                                       &adr);
        if (ACPI_SUCCESS(status)) {
		status = acpi_get_parent(handle, &parent);
		if (ACPI_FAILURE(status)) {
			printk(KERN_ERR
			       "%s: acpi_get_parent() failed (0x%x) for: ",
					__FUNCTION__, status);
			acpi_ns_print_node_pathname(handle, NULL);
			printk("\n");
			return AE_OK;
		}
		status = acpi_evaluate_integer(parent, METHOD_NAME__BBN,
					       NULL, &bbn);
		if (ACPI_FAILURE(status)) {
			printk(KERN_ERR
			  "%s: Failed to find _BBN in parent of: ",
					__FUNCTION__);
			acpi_ns_print_node_pathname(handle, NULL);
			printk("\n");
			return AE_OK;
		}

                slot = (adr >> 16) & 0xffff;
                function = adr & 0xffff;
                devfn = PCI_DEVFN(slot, function);
                if ((info->devfn == devfn) && (info->bus == bbn)) {
			/* We have a match! */
			info->handle = handle;
			return 1;
		}
	}
	return AE_OK;
}

/*
 * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi
 *			     device matching the specified pci_dev,
 *			     and return the pcidev info and irq info.
 */
int
sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
			struct sn_irq_info **sn_irq_info)
{
	unsigned int host_devfn;
	struct sn_pcidev_match pcidev_match;
	acpi_handle rootbus_handle;
	unsigned long segment;
	acpi_status status;

	rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle;
        status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
                                       &segment);
        if (ACPI_SUCCESS(status)) {
		if (segment != pci_domain_nr(dev)) {
			printk(KERN_ERR
			       "%s: Segment number mismatch, 0x%lx vs 0x%x for: ",
			       __FUNCTION__, segment, pci_domain_nr(dev));
			acpi_ns_print_node_pathname(rootbus_handle, NULL);
			printk("\n");
			return 1;
		}
	} else {
		printk(KERN_ERR "%s: Unable to get __SEG from: ",
		       __FUNCTION__);
		acpi_ns_print_node_pathname(rootbus_handle, NULL);
		printk("\n");
		return 1;
	}

	/*
	 * We want to search all devices in this segment/domain
	 * of the ACPI namespace for the matching ACPI device,
	 * which holds the pcidev_info pointer in its vendor resource.
	 */
	pcidev_match.bus = dev->bus->number;
	pcidev_match.devfn = dev->devfn;
	pcidev_match.handle = NULL;

	acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX,
			    find_matching_device, &pcidev_match, NULL);

	if (!pcidev_match.handle) {
		printk(KERN_ERR
		       "%s: Could not find matching ACPI device for %s.\n",
		       __FUNCTION__, pci_name(dev));
		return 1;
	}

	if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info))
		return 1;

	/* Build up the pcidev_info.pdi_slot_host_handle */
	host_devfn = get_host_devfn(pcidev_match.handle, rootbus_handle);
	(*pcidev_info)->pdi_slot_host_handle =
			((unsigned long) pci_domain_nr(dev) << 40) |
					/* bus == 0 */
					host_devfn;
	return 0;
}

/*
 * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info.
 *			Perform any SN specific slot fixup.
 *			At present there does not appear to be
 *			any generic way to handle a ROM image
 *			that has been shadowed by the PROM, so
 *			we pass a pointer to it	within the
 *			pcidev_info structure.
 */

void
sn_acpi_slot_fixup(struct pci_dev *dev)
{
	void __iomem *addr;
	struct pcidev_info *pcidev_info = NULL;
	struct sn_irq_info *sn_irq_info = NULL;
	size_t image_size, size;

	if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
		panic("%s:  Failure obtaining pcidev_info for %s\n",
		      __FUNCTION__, pci_name(dev));
	}

	if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
		/*
		 * A valid ROM image exists and has been shadowed by the
		 * PROM. Setup the pci_dev ROM resource with the address
		 * of the shadowed copy, and the actual length of the ROM image.
		 */
		size = pci_resource_len(dev, PCI_ROM_RESOURCE);
		addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
			       size);
		image_size = pci_get_rom_size(addr, size);
		dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
		dev->resource[PCI_ROM_RESOURCE].end =
					(unsigned long) addr + image_size - 1;
		dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
	}
	sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
}

EXPORT_SYMBOL(sn_acpi_slot_fixup);


/*
 * sn_acpi_bus_fixup -  Perform SN specific setup of software structs
 *			(pcibus_bussoft, pcidev_info) and hardware
 *			registers, for the specified bus and devices under it.
 */
void
sn_acpi_bus_fixup(struct pci_bus *bus)
{
	struct pci_dev *pci_dev = NULL;
	struct pcibus_bussoft *prom_bussoft_ptr;

	if (!bus->parent) {	/* If root bus */
		prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
		if (prom_bussoft_ptr == NULL) {
			printk(KERN_ERR
			       "%s: 0x%04x:0x%02x Unable to "
			       "obtain prom_bussoft_ptr\n",
			       __FUNCTION__, pci_domain_nr(bus), bus->number);
			return;
		}
		sn_common_bus_fixup(bus, prom_bussoft_ptr);
	}
	list_for_each_entry(pci_dev, &bus->devices, bus_list) {
		sn_acpi_slot_fixup(pci_dev);
	}
}

/*
 * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
 *		     nodes and root buses in the DSDT. As a result, bus scanning
 *		     will be initiated by the Linux ACPI code.
 */

void __init
sn_io_acpi_init(void)
{
	u64 result;
	s64 status;

	/* SN Altix does not follow the IOSAPIC IRQ routing model */
	acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;

	/* Setup hubdev_info for all SGIHUB/SGITIO devices */
	acpi_get_devices("SGIHUB", sn_acpi_hubdev_init, NULL, NULL);
	acpi_get_devices("SGITIO", sn_acpi_hubdev_init, NULL, NULL);

	status = sal_ioif_init(&result);
	if (status || result)
		panic("sal_ioif_init failed: [%lx] %s\n",
		      status, ia64_sal_strerror(status));
}
