/*
 * 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/slab.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, dma_addr_t 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;
	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,
						page_to_phys(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 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_array(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) {
		if (list_empty(info->ca_devices))
			continue;
		list_for_each_entry(pdev, info->ca_devices, bus_list) {
			u8 cap_ptr;

			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 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");
