addr <= last; 
		    baddr += PAGE_SIZE, vaddr += PAGE_SIZE) {
			pfn = ptes[baddr >> PAGE_SHIFT];
			if (!(pfn & 1)) {
				printk("ioremap failed... pte not valid...\n");
				vfree(area->addr);
				return NULL;
			}
			pfn >>= 1;	/* make it a true pfn */
			
			if (__alpha_remap_area_pages(vaddr,
						     pfn << PAGE_SHIFT, 
						     PAGE_SIZE, 0)) {
				printk("FAILED to map...\n");
				vfree(area->addr);
				return NULL;
			}
		}

		flush_tlb_all();

		vaddr = (unsigned long)area->addr + (addr & ~PAGE_MASK);

		return (void __iomem *) vaddr;
	}

	/* Assume it was already a reasonable address */
	vaddr = baddr + hose->mem_space->start;
	return (void __iomem *) vaddr;
}

void
marvel_iounmap(volatile void __iomem *xaddr)
{
	unsigned long addr = (unsigned long) xaddr;
	if (addr >= VMALLOC_START)
		vfree((void *)(PAGE_MASK & addr)); 
}

int
marvel_is_mmio(const volatile void __iomem *xaddr)
{
	unsigned long addr = (unsigned long) xaddr;

	if (addr >= VMALLOC_START)
		return 1;
	else
		return (addr & 0xFF000000UL) == 0;
}

#define __marvel_is_port_kbd(a)	(((a) == 0x60) || ((a) == 0x64))
#define __marvel_is_port_rtc(a)	(((a) == 0x70) || ((a) == 0x71))

void __iomem *marvel_ioportmap (unsigned long addr)
{
	FIXUP_IOADDR_VGA(addr);
	return (void __iomem *)addr;
}

u8
marvel_ioread8(const void __iomem *xaddr)
{
	unsigned long addr = (unsigned long) xaddr;
	if (__marvel_is_port_kbd(addr))
		return 0;
	else if (__marvel_is_port_rtc(addr))
		return __marvel_rtc_io(0, addr, 0);
	else if (marvel_is_ioaddr(addr))
		return __kernel_ldbu(*(vucp)addr);
	else
		/* this should catch other legacy addresses
		   that would normally fail on MARVEL,
		   because there really is nothing there...
		*/
		return ~0;
}

void
marvel_iowrite8(u8 b, void __iomem *xaddr)
{
	unsigned long addr = (unsigned long) xaddr;
	if (__marvel_is_port_kbd(addr))
		return;
	else if (__marvel_is_port_rtc(addr)) 
		__marvel_rtc_io(b, addr, 1);
	else if (marvel_is_ioaddr(addr))
		__kernel_stb(b, *(vucp)addr);
}

#ifndef CONFIG_ALPHA_GENERIC
EXPORT_SYMBOL(marvel_ioremap);
EXPORT_SYMBOL(marvel_iounmap);
EXPORT_SYMBOL(marvel_is_mmio);
EXPORT_SYMBOL(marvel_ioportmap);
EXPORT_SYMBOL(marvel_ioread8);
EXPORT_SYMBOL(marvel_iowrite8);
#endif

/*
 * AGP GART Support.
 */
#include <linux/agp_backend.h>
#include <asm/agp_backend.h>
#include <linux/slab.h>
#include <linux/delay.h>

struct marvel_agp_aperture {
	struct pci_iommu_arena *arena;
	long pg_start;
	long pg_count;
};

static int
marvel_agp_setup(alpha_agp_info *agp)
{
	struct marvel_agp_aperture *aper;

	if (!alpha_agpgart_size)
		return -ENOMEM;

	aper = kmalloc(sizeof(*aper), GFP_KERNEL);
	if (aper == NULL) return -ENOMEM;

	aper->arena = agp->hose->sg_pci;
	aper->pg_count = alpha_agpgart_size / PAGE_SIZE;
	aper->pg_start = iommu_reserve(aper->arena, aper->pg_count,
				       aper->pg_count - 1);

	if (aper->pg_start < 0) {
		printk(KERN_ERR "Failed to reserve AGP memory\n");
		kfree(aper);
		return -ENOMEM;
	}

	agp->aperture.bus_base = 
		aper->arena->dma_base + aper->pg_start * PAGE_SIZE;
	agp->aperture.size = aper->pg_count * PAGE_SIZE;
	agp->aperture.sysdata = aper;

	return 0;
}

static void
marvel_agp_cleanup(alpha_agp_info *agp)
{
	struct marvel_agp_aperture *aper = agp->aperture.sysdata;
	int status;

	status = iommu_release(aper->arena, aper->pg_start, aper->pg_count);
	if (status == -EBUSY) {
		printk(KERN_WARNING
		       "Attempted to release bound AGP memory - unbinding\n");
		iommu_unbind(aper->arena, aper->pg_start, aper->pg_count);
		status = iommu_release(aper->arena, aper->pg_start, 
				       aper->pg_count);
	}
	if (status < 0)
		printk(KERN_ERR "Failed to release AGP memory\n");

	kfree(aper);
	kfree(agp);
}

static int
marvel_agp_configure(alpha_agp_info *agp)
{
	io7_ioport_csrs *csrs = ((struct io7_port *)agp->hose->sysdata)->csrs;
	struct io7 *io7 = ((struct io7_port *)agp->hose->sysdata)->io7;
	unsigned int new_rate = 0;
	unsigned long agp_pll;

	/*
	 * Check the requested mode against the PLL setting.
	 * The agpgart_be code has not programmed the card yet,
	 * so we can still tweak mode here.
	 */
	agp_pll = io7->csrs->POx_RST[IO7_AGP_PORT].csr;
	switch(IO7_PLL_RNGB(agp_pll)) {
	case 0x4:				/* 2x only */
		/* 
		 * The PLL is only programmed for 2x, so adjust the
		 * rate to 2x, if necessary.
		 */
		if (agp->mode.bits.rate != 2) 
			new_rate = 2;
		break;

	case 0x6:				/* 1x / 4x */
		/*
		 * The PLL is programmed for 1x or 4x.  Don't go faster
		 * than requested, so if the requested rate is 2x, use 1x.
		 */
		if (agp->mode.bits.rate == 2) 
			new_rate = 1;
		break;

	default:				/* ??????? */
		/*
		 * Don't know what this PLL setting is, take the requested
		 * rate, but warn the user.
		 */
		printk("%s: unknown PLL setting RNGB=%lx (PLL6_CTL=%016lx)\n",
		       __func__, IO7_PLL_RNGB(agp_pll), agp_pll);
		break;
	}

	/*
	 * Set the new rate, if necessary.
	 */
	if (new_rate) {
		printk("Requested AGP Rate %dX not compatible "
		       "with PLL setting - using %dX\n",
		       agp->mode.bits.rate,
		       new_rate);

		agp->mode.bits.rate = new_rate;
	}
		
	printk("Enabling AGP on hose %d: %dX%s RQ %d\n", 
	       agp->hose->index, agp->mode.bits.rate, 
	       agp->mode.bits.sba ? " - SBA" : "", agp->mode.bits.rq);

	csrs->AGP_CMD.csr = agp->mode.lw;

	return 0;
}

static int 
marvel_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
{
	struct marvel_agp_aperture *aper = agp->aperture.sysdata;
	return iommu_bind(aper->arena, aper->pg_start + pg_start, 
			  mem->page_count, mem->pages);
}

static int 
marvel_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem)
{
	struct marvel_agp_aperture *aper = agp->aperture.sysdata;
	return iommu_unbind(aper->arena, aper->pg_start + pg_start,
			    mem->page_count);
}

static unsigned long
marvel_agp_translate(alpha_agp_info *agp, dma_addr_t addr)
{
	struct marvel_agp_aperture *aper = agp->aperture.sysdata;
	unsigned long baddr = addr - aper->arena->dma_base;
	unsigned long pte;

	if (addr < agp->aperture.bus_base ||
	    addr >= agp->aperture.bus_base + agp->aperture.size) {
		printk("%s: addr out of range\n", __func__);
		return -EINVAL;
	}

	pte = aper->arena->ptes[baddr >> PAGE_SHIFT];
	if (!(pte & 1)) {
		printk("%s: pte not valid\n", __func__);
		return -EINVAL;
	} 
	return (pte >> 1) << PAGE_SHIFT;
}

struct alpha_agp_ops marvel_agp_ops =
{
	.setup		= marvel_agp_setup,
	.cleanup	= marvel_agp_cleanup,
	.configure	= marvel_agp_configure,
	.bind		= marvel_agp_bind_memory,
	.unbind		= marvel_agp_unbind_memory,
	.translate	= marvel_agp_translate
};

alpha_agp_info *
marvel_agp_info(void)
{
	struct pci_controller *hose;
	io7_ioport_csrs *csrs;
	alpha_agp_info *agp;
	struct io7 *io7;

	/*
	 * Find the first IO7 with an AGP card.
	 *
	 * FIXME -- there should be a better way (we want to be able to
	 * specify and what if the agp card is not video???)
	 */
	hose = NULL;
	for (io7 = NULL; (io7 = marvel_next_io7(io7)) != NULL; ) {
		struct pci_controller *h;
		vuip addr;

		if (!io7->ports[IO7_AGP_PORT].enabled)
			continue;

		h = io7->ports[IO7_AGP_PORT].hose;
		addr = (vuip)build_conf_addr(h, 0, PCI_DEVFN(5, 0), 0);

		if (*addr != 0xffffffffu) {
			hose = h;
			break;
		}
	}

	if (!hose || !hose->sg_pci)
		return NULL;

	printk("MARVEL - using hose %d as AGP\n", hose->index);

	/* 
	 * Get the csrs from the hose.
	 */
	csrs = ((struct io7_port *)hose->sysdata)->csrs;

	/*
	 * Allocate the info structure.
	 */
	agp = kmalloc(sizeof(*agp), GFP_KERNEL);
	if (!agp)
		return NULL;

	/*
	 * Fill it in.
	 */
	agp->hose = hose;
	agp->private = NULL;
	agp->ops = &marvel_agp_ops;

	/*
	 * Aperture - not configured until ops.setup().
	 */
	agp->aperture.bus_base = 0;
	agp->aperture.size = 0;
	agp->aperture.sysdata = NULL;

	/*
	 * Capabilities.
	 *
	 * NOTE: IO7 reports through AGP_STAT that it can support a read queue
	 *       depth of 17 (rq = 0x10). It actually only supports a depth of
	 * 	 16 (rq = 0xf).
	 */
	agp->capability.lw = csrs->AGP_STAT.csr;
	agp->capability.bits.rq = 0xf;
	
	/*
	 * Mode.
	 */
	agp->mode.lw = csrs->AGP_CMD.csr;

	return agp;
}
