1 /* 2 * Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "../i915_drv.h" 18 19 #include <drm/drm_agpsupport.h> 20 21 /* MCH IFP BARs */ 22 #define I915_IFPADDR 0x60 23 #define I965_IFPADDR 0x70 24 25 extern struct cfdriver inteldrm_cd; 26 27 #ifdef __amd64__ 28 #define membar_producer_wc() __asm __volatile("sfence":::"memory") 29 #else 30 #define membar_producer_wc() __asm __volatile(\ 31 "lock; addl $0,0(%%esp)":::"memory") 32 #endif 33 34 /* 35 * We're intel IGD, bus 0 function 0 dev 0 should be the GMCH, so it should 36 * be Intel 37 */ 38 int 39 inteldrm_gmch_match(struct pci_attach_args *pa) 40 { 41 if (pa->pa_bus == 0 && pa->pa_device == 0 && pa->pa_function == 0 && 42 PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 43 PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 44 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_HOST) 45 return (1); 46 return (0); 47 } 48 49 void 50 i915_alloc_ifp(struct inteldrm_softc *dev_priv, struct pci_attach_args *bpa) 51 { 52 bus_addr_t addr; 53 u_int32_t reg; 54 55 dev_priv->ifp.i9xx.bst = bpa->pa_memt; 56 57 reg = pci_conf_read(bpa->pa_pc, bpa->pa_tag, I915_IFPADDR); 58 if (reg & 0x1) { 59 addr = (bus_addr_t)reg; 60 addr &= ~0x1; 61 /* XXX extents ... need data on whether bioses alloc or not. */ 62 if (bus_space_map(bpa->pa_memt, addr, PAGE_SIZE, 0, 63 &dev_priv->ifp.i9xx.bsh) != 0) 64 goto nope; 65 return; 66 } else if (bpa->pa_memex == NULL || 67 extent_alloc_subregion(bpa->pa_memex, 0x100000, 0xffffffff, 68 PAGE_SIZE, PAGE_SIZE, 0, 0, 0, &addr) || 69 bus_space_map(bpa->pa_memt, addr, PAGE_SIZE, 0, 70 &dev_priv->ifp.i9xx.bsh)) 71 goto nope; 72 73 pci_conf_write(bpa->pa_pc, bpa->pa_tag, I915_IFPADDR, addr | 0x1); 74 75 return; 76 77 nope: 78 dev_priv->ifp.i9xx.bsh = 0; 79 printf("%s: no ifp\n", dev_priv->sc_dev.dv_xname); 80 } 81 82 void 83 i965_alloc_ifp(struct inteldrm_softc *dev_priv, struct pci_attach_args *bpa) 84 { 85 bus_addr_t addr; 86 u_int32_t lo, hi; 87 88 dev_priv->ifp.i9xx.bst = bpa->pa_memt; 89 90 hi = pci_conf_read(bpa->pa_pc, bpa->pa_tag, I965_IFPADDR + 4); 91 lo = pci_conf_read(bpa->pa_pc, bpa->pa_tag, I965_IFPADDR); 92 if (lo & 0x1) { 93 addr = (((u_int64_t)hi << 32) | lo); 94 addr &= ~0x1; 95 /* XXX extents ... need data on whether bioses alloc or not. */ 96 if (bus_space_map(bpa->pa_memt, addr, PAGE_SIZE, 0, 97 &dev_priv->ifp.i9xx.bsh) != 0) 98 goto nope; 99 return; 100 } else if (bpa->pa_memex == NULL || 101 extent_alloc_subregion(bpa->pa_memex, 0x100000, 0xffffffff, 102 PAGE_SIZE, PAGE_SIZE, 0, 0, 0, &addr) || 103 bus_space_map(bpa->pa_memt, addr, PAGE_SIZE, 0, 104 &dev_priv->ifp.i9xx.bsh)) 105 goto nope; 106 107 pci_conf_write(bpa->pa_pc, bpa->pa_tag, I965_IFPADDR + 4, 108 upper_32_bits(addr)); 109 pci_conf_write(bpa->pa_pc, bpa->pa_tag, I965_IFPADDR, 110 (addr & 0xffffffff) | 0x1); 111 112 return; 113 114 nope: 115 dev_priv->ifp.i9xx.bsh = 0; 116 printf("%s: no ifp\n", dev_priv->sc_dev.dv_xname); 117 } 118 119 void 120 intel_gtt_chipset_setup(struct drm_device *dev) 121 { 122 struct inteldrm_softc *dev_priv = dev->dev_private; 123 struct pci_attach_args bpa; 124 125 if (INTEL_GEN(dev_priv) >= 6) 126 return; 127 128 if (pci_find_device(&bpa, inteldrm_gmch_match) == 0) { 129 printf("%s: can't find GMCH\n", 130 dev_priv->sc_dev.dv_xname); 131 return; 132 } 133 134 /* Set up the IFP for chipset flushing */ 135 if (INTEL_GEN(dev_priv) >= 4 || IS_G33(dev_priv)) { 136 i965_alloc_ifp(dev_priv, &bpa); 137 } else if (INTEL_GEN(dev_priv) == 3) { 138 i915_alloc_ifp(dev_priv, &bpa); 139 } else { 140 int nsegs; 141 /* 142 * I8XX has no flush page mechanism, we fake it by writing until 143 * the cache is empty. allocate a page to scribble on 144 */ 145 dev_priv->ifp.i8xx.kva = NULL; 146 if (bus_dmamem_alloc(dev_priv->dmat, PAGE_SIZE, 0, 0, 147 &dev_priv->ifp.i8xx.seg, 1, &nsegs, BUS_DMA_WAITOK) == 0) { 148 if (bus_dmamem_map(dev_priv->dmat, &dev_priv->ifp.i8xx.seg, 149 1, PAGE_SIZE, &dev_priv->ifp.i8xx.kva, 0) != 0) { 150 bus_dmamem_free(dev_priv->dmat, 151 &dev_priv->ifp.i8xx.seg, nsegs); 152 dev_priv->ifp.i8xx.kva = NULL; 153 } 154 } 155 } 156 } 157 158 int 159 intel_enable_gtt(void) 160 { 161 struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0]; 162 163 intel_gtt_chipset_setup(&dev_priv->drm); 164 return 1; 165 } 166 167 int 168 intel_gmch_probe(struct pci_dev *bridge_dev, struct pci_dev *gpu_pdev, 169 void *bridge) 170 { 171 return 1; 172 } 173 174 void 175 intel_gtt_get(u64 *gtt_total, 176 phys_addr_t *mappable_base, resource_size_t *mappable_end) 177 { 178 struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0]; 179 struct agp_info *ai = &dev_priv->drm.agp->info; 180 181 *gtt_total = ai->ai_aperture_size; 182 *mappable_base = ai->ai_aperture_base; 183 *mappable_end = ai->ai_aperture_size; 184 } 185 186 void 187 intel_gtt_chipset_flush(void) 188 { 189 struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0]; 190 191 /* 192 * Write to this flush page flushes the chipset write cache. 193 * The write will return when it is done. 194 */ 195 if (INTEL_GEN(dev_priv) >= 3) { 196 if (dev_priv->ifp.i9xx.bsh != 0) 197 bus_space_write_4(dev_priv->ifp.i9xx.bst, 198 dev_priv->ifp.i9xx.bsh, 0, 1); 199 } else { 200 int i; 201 #define I830_HIC 0x70 202 i915_reg_t hic = _MMIO(I830_HIC); 203 204 wbinvd_on_all_cpus(); 205 206 I915_WRITE(hic, (I915_READ(hic) | (1<<31))); 207 for (i = 1000; i; i--) { 208 if (!(I915_READ(hic) & (1<<31))) 209 break; 210 delay(100); 211 } 212 213 } 214 } 215 216 void 217 intel_gmch_remove(void) 218 { 219 } 220 221 void 222 intel_gtt_insert_sg_entries(struct sg_table *pages, unsigned int pg_start, 223 unsigned int flags) 224 { 225 struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0]; 226 struct agp_softc *sc = dev_priv->drm.agp->agpdev; 227 bus_addr_t addr = sc->sc_apaddr + pg_start * PAGE_SIZE; 228 struct sg_page_iter sg_iter; 229 230 for_each_sg_page(pages->sgl, &sg_iter, pages->nents, 0) { 231 sc->sc_methods->bind_page(sc->sc_chipc, addr, 232 sg_page_iter_dma_address(&sg_iter), flags); 233 addr += PAGE_SIZE; 234 } 235 membar_producer_wc(); 236 intel_gtt_chipset_flush(); 237 } 238 239 void 240 intel_gtt_insert_page(dma_addr_t addr, unsigned int pg, 241 unsigned int flags) 242 { 243 struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0]; 244 struct agp_softc *sc = dev_priv->drm.agp->agpdev; 245 bus_addr_t apaddr = sc->sc_apaddr + (pg * PAGE_SIZE); 246 sc->sc_methods->bind_page(sc->sc_chipc, apaddr, addr, flags); 247 intel_gtt_chipset_flush(); 248 } 249 250 void 251 intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) 252 { 253 struct inteldrm_softc *dev_priv = (void *)inteldrm_cd.cd_devs[0]; 254 struct agp_softc *sc = dev_priv->drm.agp->agpdev; 255 bus_addr_t addr = sc->sc_apaddr + first_entry * PAGE_SIZE; 256 int i; 257 258 for (i = 0; i < num_entries; i++) { 259 sc->sc_methods->unbind_page(sc->sc_chipc, addr); 260 addr += PAGE_SIZE; 261 } 262 membar_producer_wc(); 263 } 264