p); } static int titan_agp_configure(alpha_agp_info *agp) { union TPAchipPCTL pctl; titan_pachip_port *port = agp->private; pctl.pctl_q_whole = port->pctl.csr; /* Side-Band Addressing? */ pctl.pctl_r_bits.apctl_v_agp_sba_en = agp->mode.bits.sba; /* AGP Rate? */ pctl.pctl_r_bits.apctl_v_agp_rate = 0; /* 1x */ if (agp->mode.bits.rate & 2) pctl.pctl_r_bits.apctl_v_agp_rate = 1; /* 2x */ #if 0 if (agp->mode.bits.rate & 4) pctl.pctl_r_bits.apctl_v_agp_rate = 2; /* 4x */ #endif /* RQ Depth? */ pctl.pctl_r_bits.apctl_v_agp_hp_rd = 2; pctl.pctl_r_bits.apctl_v_agp_lp_rd = 7; /* * AGP Enable. */ pctl.pctl_r_bits.apctl_v_agp_en = agp->mode.bits.enable; /* Tell the user. */ printk("Enabling AGP: %dX%s\n", 1 << pctl.pctl_r_bits.apctl_v_agp_rate, pctl.pctl_r_bits.apctl_v_agp_sba_en ? " - SBA" : ""); /* Write it. */ port->pctl.csr = pctl.pctl_q_whole; /* And wait at least 5000 66MHz cycles (per Titan spec). */ udelay(100); return 0; } static int titan_agp_bind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem) { struct titan_agp_aperture *aper = agp->aperture.sysdata; return iommu_bind(aper->arena, aper->pg_start + pg_start, mem->page_count, mem->pages); } static int titan_agp_unbind_memory(alpha_agp_info *agp, off_t pg_start, struct agp_memory *mem) { struct titan_agp_aperture *aper = agp->aperture.sysdata; return iommu_unbind(aper->arena, aper->pg_start + pg_start, mem->page_count); } static unsigned long titan_agp_translate(alpha_agp_info *agp, dma_addr_t addr) { struct titan_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 titan_agp_ops = { .setup = titan_agp_setup, .cleanup = titan_agp_cleanup, .configure = titan_agp_configure, .bind = titan_agp_bind_memory, .unbind = titan_agp_unbind_memory, .translate = titan_agp_translate }; alpha_agp_info * titan_agp_info(void) { alpha_agp_info *agp; struct pci_controller *hose; titan_pachip_port *port; int hosenum = -1; union TPAchipPCTL pctl; /* * Find the AGP port. */ port = &TITAN_pachip0->a_port; if (titan_query_agp(port)) hosenum = 2; if (hosenum < 0 && titan_pchip1_present && titan_query_agp(port = &TITAN_pachip1->a_port)) hosenum = 3; /* * Find the hose the port is on. */ for (hose = hose_head; hose; hose = hose->next) if (hose->index == hosenum) break; if (!hose || !hose->sg_pci) return NULL; /* * Allocate the info structure. */ agp = kmalloc(sizeof(*agp), GFP_KERNEL); if (!agp) return NULL; /* * Fill it in. */ agp->hose = hose; agp->private = port; agp->ops = &titan_agp_ops; /* * Aperture - not configured until ops.setup(). * * FIXME - should we go ahead and allocate it here? */ agp->aperture.bus_base = 0; agp->aperture.size = 0; agp->aperture.sysdata = NULL; /* * Capabilities. */ agp->capability.lw = 0; agp->capability.bits.rate = 3; /* 2x, 1x */ agp->capability.bits.sba = 1; agp->capability.bits.rq = 7; /* 8 - 1 */ /* * Mode. */ pctl.pctl_q_whole = port->pctl.csr; agp->mode.lw = 0; agp->mode.bits.rate = 1 << pctl.pctl_r_bits.apctl_v_agp_rate; agp->mode.bits.sba = pctl.pctl_r_bits.apctl_v_agp_sba_en; agp->mode.bits.rq = 7; /* RQ Depth? */ agp->mode.bits.enable = pctl.pctl_r_bits.apctl_v_agp_en; return agp; }