/*
 * 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 void *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_address(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,
		      unsigned long addr, int type)
{
	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 == FALSE) {
		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->memory[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 = 1,
	.needs_scratch_page = 0,
	.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");
