/*
 * 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) 2003-2005 Silicon Graphics, Inc.  All Rights Reserved.
 */

/*
 * SGI TIOCA AGPGART routines.
 *
 */

#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
#include <asm/sn/addrs.h>
#include <asm/sn/io.h>
#include <asm/sn/pcidev.h>
#include <asm/sn/pcibus_provider_defs.h>
#include <asm/sn/tioca_provider.h>
#include "agp.h"

extern int agp_memory_reserved;
extern uint32_t tioca_gart_found;
extern struct list_head tioca_list;
static struct agp_bridge_data **sgi_tioca_agp_bridges;

/*
 * The aperature size and related information is set up at TIOCA init time.
 * Values for this table will be extracted and filled in at
 * sgi_tioca_fetch_size() time.
 */

static struct aper_size_info_fixed sgi_tioca_sizes[] = {
	{0, 0, 0},
};

static struct page *sgi_tioca_alloc_page(struct agp_bridge_data *bridge)
{
	struct page *page;
	int nid;
	struct tioca_kernel *info =
	    (struct tioca_kernel *)bridge->dev_private_data;

	nid = info->ca_closest_node;
	page = alloc_pages_node(nid, GFP_KERNEL, 0);
	if (!page)
		return NULL;

	get_page(page);
	atomic_inc(&agp_bridge->current_memory_agp);
	return page;
}

/*
 * Flush GART tlb's.  Cannot selectively flush based on memory so the mem
 * arg is ignored.
 */

static void sgi_tioca_tlbflush(struct agp_memory *mem)
{
	tioca_tlbflush(mem->bridge->dev_private_data);
}

/*
 * Given an address of a host physical page, turn it into a valid gart
 * entry.
 */
static unsigned long
sgi_tioca_mask_memory(struct agp_bridge_data *bridge,
		      struct page *page, int type)
{
	unsigned long addr = phys_to_gart(page_to_phys(page));
	return tioca_physpage_to_gart(addr);
}

static void sgi_tioca_agp_enable(struct agp_bridge_data *bridge, u32 mode)
{
	tioca_fastwrite_enable(bridge->dev_private_data);
}

/*
 * sgi_tioca_configure() doesn't have anything to do since the base CA driver
 * has alreay set up the GART.
 */

static int sgi_tioca_configure(void)
{
	return 0;
}

/*
 * Determine gfx aperature size.  This has already been determined by the
 * CA driver init, so just need to set agp_bridge values accordingly.
 */

static int sgi_tioca_fetch_size(void)
{
	struct tioca_kernel *info =
	    (struct tioca_kernel *)agp_bridge->dev_private_data;

	sgi_tioca_sizes[0].size = info->ca_gfxap_size / MB(1);
	sgi_tioca_sizes[0].num_entries = info->ca_gfxgart_entries;

	return sgi_tioca_sizes[0].size;
}

static int sgi_tioca_create_gatt_table(struct agp_bridge_data *bridge)
{
	struct tioca_kernel *info =
	    (struct tioca_kernel *)bridge->dev_private_data;

	bridge->gatt_table_real = (u32 *) info->ca_gfxgart;
	bridge->gatt_table = bridge->gatt_table_real;
	bridge->gatt_bus_addr = info->ca_gfxgart_base;

	return 0;
}

static int sgi_tioca_free_gatt_table(struct agp_bridge_data *bridge)
{
	return 0;
}

static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
				   int type)
{
	int num_entries;
	size_t i;
	off_t j;
	void *temp;
	struct agp_bridge_data *bridge;
	u64 *table;

	bridge = mem->bridge;
	if (!bridge)
		return -EINVAL;

	table = (u64 *)bridge->gatt_table;

	temp = bridge->current_size;

	switch (bridge->driver->size_type) {
	case U8_APER_SIZE:
		num_entries = A_SIZE_8(temp)->num_entries;
		break;
	case U16_APER_SIZE:
		num_entries = A_SIZE_16(temp)->num_entries;
		break;
	case U32_APER_SIZE:
		num_entries = A_SIZE_32(temp)->num_entries;
		break;
	case FIXED_APER_SIZE:
		num_entries = A_SIZE_FIX(temp)->num_entries;
		break;
	case LVL2_APER_SIZE:
		return -EINVAL;
		break;
	default:
		num_entries = 0;
		break;
	}

	num_entries -= agp_memory_reserved / PAGE_SIZE;
	if (num_entries < 0)
		num_entries = 0;

	if (type != 0 || mem->type != 0) {
		return -EINVAL;
	}

	if ((pg_start + mem->page_count) > num_entries)
		return -EINVAL;

	j = pg_start;

	while (j < (pg_start + mem->page_count)) {
		if (table[j])
			return -EBUSY;
		j++;
	}

	if (!mem->is_flushed) {
		bridge->driver->cache_flush();
		mem->is_flushed = true;
	}

	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
		table[j] =
		    bridge->driver->mask_memory(bridge, mem->pages[i],
						mem->type);
	}

	bridge->driver->tlb_flush(mem);
	return 0;
}

static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
				   int type)
{
	size_t i;
	struct agp_bridge_data *bridge;
	u64 *table;

	bridge = mem->bridge;
	if (!bridge)
		return -EINVAL;

	if (type != 0 || mem->type != 0) {
		return -EINVAL;
	}

	table = (u64 *)bridge->gatt_table;

	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
		table[i] = 0;
	}

	bridge->driver->tlb_flush(mem);
	return 0;
}

static void sgi_tioca_cache_flush(void)
{
}

/*
 * Cleanup.  Nothing to do as the CA driver owns the GART.
 */

static void sgi_tioca_cleanup(void)
{
}

static struct agp_bridge_data *sgi_tioca_find_bridge(struct pci_dev *pdev)
{
	struct agp_bridge_data *bridge;

	list_for_each_entry(bridge, &agp_bridges, list) {
		if (bridge->dev->bus == pdev->bus)
			break;
	}
	return bridge;
}

const struct agp_bridge_driver sgi_tioca_driver = {
	.owner = THIS_MODULE,
	.size_type = U16_APER_SIZE,
	.configure = sgi_tioca_configure,
	.fetch_size = sgi_tioca_fetch_size,
	.cleanup = sgi_tioca_cleanup,
	.tlb_flush = sgi_tioca_tlbflush,
	.mask_memory = sgi_tioca_mask_memory,
	.agp_enable = sgi_tioca_agp_enable,
	.cache_flush = sgi_tioca_cache_flush,
	.create_gatt_table = sgi_tioca_create_gatt_table,
	.free_gatt_table = sgi_tioca_free_gatt_table,
	.insert_memory = sgi_tioca_insert_memory,
	.remove_memory = sgi_tioca_remove_memory,
	.alloc_by_type = agp_generic_alloc_by_type,
	.free_by_type = agp_generic_free_by_type,
	.agp_alloc_page = sgi_tioca_alloc_page,
	.agp_destroy_page = agp_generic_destroy_page,
	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
	.cant_use_aperture = true,
	.needs_scratch_page = false,
	.num_aperture_sizes = 1,
};

static int __devinit agp_sgi_init(void)
{
	unsigned int j;
	struct tioca_kernel *info;
	struct pci_dev *pdev = NULL;

	if (tioca_gart_found)
		printk(KERN_INFO PFX "SGI TIO CA GART driver initialized.\n");
	else
		return 0;

	sgi_tioca_agp_bridges = kmalloc(tioca_gart_found *
					sizeof(struct agp_bridge_data *),
					GFP_KERNEL);
	if (!sgi_tioca_agp_bridges)
		return -ENOMEM;

	j = 0;
	list_for_each_entry(info, &tioca_list, ca_list) {
		struct list_head *tmp;
		if (list_empty(info->ca_devices))
			continue;
		list_for_each(tmp, info->ca_devices) {
			u8 cap_ptr;
			pdev = pci_dev_b(tmp);
			if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8))
				continue;
			cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
			if (!cap_ptr)
				continue;
		}
		sgi_tioca_agp_bridges[j] = agp_alloc_bridge();
		printk(KERN_INFO PFX "bridge %d = 0x%p\n", j,
		       sgi_tioca_agp_bridges[j]);
		if (sgi_tioca_agp_bridges[j]) {
			sgi_tioca_agp_bridges[j]->dev = pdev;
			sgi_tioca_agp_bridges[j]->dev_private_data = info;
			sgi_tioca_agp_bridges[j]->driver = &sgi_tioca_driver;
			sgi_tioca_agp_bridges[j]->gart_bus_addr =
			    info->ca_gfxap_base;
			sgi_tioca_agp_bridges[j]->mode = (0x7D << 24) |	/* 126 requests */
			    (0x1 << 9) |	/* SBA supported */
			    (0x1 << 5) |	/* 64-bit addresses supported */
			    (0x1 << 4) |	/* FW supported */
			    (0x1 << 3) |	/* AGP 3.0 mode */
			    0x2;	/* 8x transfer only */
			sgi_tioca_agp_bridges[j]->current_size =
			    sgi_tioca_agp_bridges[j]->previous_size =
			    (void *)&sgi_tioca_sizes[0];
			agp_add_bridge(sgi_tioca_agp_bridges[j]);
		}
		j++;
	}

	agp_find_bridge = &sgi_tioca_find_bridge;
	return 0;
}

static void __devexit agp_sgi_cleanup(void)
{
	kfree(sgi_tioca_agp_bridges);
	sgi_tioca_agp_bridges = NULL;
}

module_init(agp_sgi_init);
module_exit(agp_sgi_cleanup);

MODULE_LICENSE("GPL and additional rights");
