1 /* $OpenBSD: agp_intel.c,v 1.15 2009/05/10 16:57:44 oga Exp $ */ 2 /* $NetBSD: agp_intel.c,v 1.3 2001/09/15 00:25:00 thorpej Exp $ */ 3 4 /*- 5 * Copyright (c) 2000 Doug Rabson 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: src/sys/pci/agp_intel.c,v 1.4 2001/07/05 21:28:47 jhb Exp $ 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/malloc.h> 35 #include <sys/kernel.h> 36 #include <sys/lock.h> 37 #include <sys/proc.h> 38 #include <sys/agpio.h> 39 #include <sys/device.h> 40 #include <sys/agpio.h> 41 42 #include <dev/pci/pcivar.h> 43 #include <dev/pci/pcireg.h> 44 #include <dev/pci/pcidevs.h> 45 #include <dev/pci/agpvar.h> 46 #include <dev/pci/agpreg.h> 47 48 #include <machine/bus.h> 49 50 struct agp_intel_softc { 51 struct device dev; 52 struct agp_softc *agpdev; 53 struct agp_gatt *gatt; 54 pci_chipset_tag_t isc_pc; 55 pcitag_t isc_tag; 56 bus_addr_t isc_apaddr; 57 bus_size_t isc_apsize; 58 u_int aperture_mask; 59 enum { 60 CHIP_INTEL, 61 CHIP_I443, 62 CHIP_I840, 63 CHIP_I845, 64 CHIP_I850, 65 CHIP_I865 66 } chiptype; 67 }; 68 69 70 void agp_intel_attach(struct device *, struct device *, void *); 71 int agp_intel_probe(struct device *, void *, void *); 72 bus_size_t agp_intel_get_aperture(void *); 73 int agp_intel_set_aperture(void *, bus_size_t); 74 void agp_intel_bind_page(void *, bus_addr_t, paddr_t, int); 75 void agp_intel_unbind_page(void *, bus_addr_t); 76 void agp_intel_flush_tlb(void *); 77 78 struct cfattach intelagp_ca = { 79 sizeof(struct agp_intel_softc), agp_intel_probe, agp_intel_attach 80 }; 81 82 struct cfdriver intelagp_cd = { 83 NULL, "intelagp", DV_DULL 84 }; 85 86 const struct agp_methods agp_intel_methods = { 87 agp_intel_bind_page, 88 agp_intel_unbind_page, 89 agp_intel_flush_tlb, 90 /* default enable and memory routines */ 91 }; 92 93 int 94 agp_intel_probe(struct device *parent, void *match, void *aux) 95 { 96 struct agp_attach_args *aa = aux; 97 struct pci_attach_args *pa = aa->aa_pa; 98 99 /* Must be a pchb */ 100 if (agpbus_probe(aa) == 0) 101 return (0); 102 103 switch (PCI_PRODUCT(pa->pa_id)) { 104 case PCI_PRODUCT_INTEL_82443LX: 105 case PCI_PRODUCT_INTEL_82443BX: 106 case PCI_PRODUCT_INTEL_82440BX: 107 case PCI_PRODUCT_INTEL_82440BX_AGP: 108 case PCI_PRODUCT_INTEL_82815_HB: 109 case PCI_PRODUCT_INTEL_82820_HB: 110 case PCI_PRODUCT_INTEL_82830M_HB: 111 case PCI_PRODUCT_INTEL_82840_HB: 112 case PCI_PRODUCT_INTEL_82845_HB: 113 case PCI_PRODUCT_INTEL_82845G_HB: 114 case PCI_PRODUCT_INTEL_82850_HB: 115 case PCI_PRODUCT_INTEL_82855PM_HB: 116 case PCI_PRODUCT_INTEL_82855GM_HB: 117 case PCI_PRODUCT_INTEL_82860_HB: 118 case PCI_PRODUCT_INTEL_82865G_HB: 119 case PCI_PRODUCT_INTEL_82875P_HB: 120 return (1); 121 } 122 123 return (0); 124 } 125 126 void 127 agp_intel_attach(struct device *parent, struct device *self, void *aux) 128 { 129 struct agp_intel_softc *isc = (struct agp_intel_softc *)self; 130 struct agp_attach_args *aa = aux; 131 struct pci_attach_args *pa = aa->aa_pa; 132 struct agp_gatt *gatt; 133 pcireg_t reg; 134 u_int32_t value; 135 136 isc->isc_pc = pa->pa_pc; 137 isc->isc_tag = pa->pa_tag; 138 139 switch (PCI_PRODUCT(pa->pa_id)) { 140 case PCI_PRODUCT_INTEL_82443LX: 141 case PCI_PRODUCT_INTEL_82443BX: 142 case PCI_PRODUCT_INTEL_82440BX: 143 case PCI_PRODUCT_INTEL_82440BX_AGP: 144 isc->chiptype = CHIP_I443; 145 break; 146 case PCI_PRODUCT_INTEL_82830M_HB: 147 case PCI_PRODUCT_INTEL_82840_HB: 148 isc->chiptype = CHIP_I840; 149 break; 150 case PCI_PRODUCT_INTEL_82845_HB: 151 case PCI_PRODUCT_INTEL_82845G_HB: 152 case PCI_PRODUCT_INTEL_82855PM_HB: 153 isc->chiptype = CHIP_I845; 154 break; 155 case PCI_PRODUCT_INTEL_82850_HB: 156 isc->chiptype = CHIP_I850; 157 break; 158 case PCI_PRODUCT_INTEL_82865G_HB: 159 case PCI_PRODUCT_INTEL_82875P_HB: 160 isc->chiptype = CHIP_I865; 161 break; 162 default: 163 isc->chiptype = CHIP_INTEL; 164 } 165 166 if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, AGP_APBASE, 167 PCI_MAPREG_TYPE_MEM, &isc->isc_apaddr, NULL, NULL) != 0) { 168 printf(": can't get aperture info\n"); 169 return; 170 } 171 172 /* Determine maximum supported aperture size. */ 173 value = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE); 174 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE, APSIZE_MASK); 175 isc->aperture_mask = pci_conf_read(pa->pa_pc, pa->pa_tag, 176 AGP_INTEL_APSIZE) & APSIZE_MASK; 177 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE, value); 178 isc->isc_apsize = agp_intel_get_aperture(isc); 179 180 for (;;) { 181 gatt = agp_alloc_gatt(pa->pa_dmat, isc->isc_apsize); 182 if (gatt != NULL) 183 break; 184 185 /* 186 * almost certainly error allocating contigious dma memory 187 * so reduce aperture so that the gatt size reduces. 188 */ 189 isc->isc_apsize /= 2; 190 if (agp_intel_set_aperture(isc, isc->isc_apsize)) { 191 printf(": failed to set aperture\n"); 192 return; 193 } 194 } 195 isc->gatt = gatt; 196 197 /* Install the gatt. */ 198 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_ATTBASE, 199 gatt->ag_physical); 200 201 /* Enable the GLTB and setup the control register. */ 202 switch (isc->chiptype) { 203 case CHIP_I443: 204 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 205 AGPCTRL_AGPRSE | AGPCTRL_GTLB); 206 break; 207 default: 208 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 209 pci_conf_read(isc->isc_pc, isc->isc_tag, 210 AGP_INTEL_AGPCTRL) | AGPCTRL_GTLB); 211 } 212 213 /* Enable things, clear errors etc. */ 214 switch (isc->chiptype) { 215 case CHIP_I845: 216 case CHIP_I865: 217 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG); 218 reg |= MCHCFG_AAGN; 219 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG, reg); 220 break; 221 case CHIP_I840: 222 case CHIP_I850: 223 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_AGPCMD); 224 reg |= AGPCMD_AGPEN; 225 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_AGPCMD, 226 reg); 227 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG); 228 reg |= MCHCFG_AAGN; 229 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG, 230 reg); 231 break; 232 default: 233 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_NBXCFG); 234 reg &= ~NBXCFG_APAE; 235 reg |= NBXCFG_AAGN; 236 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_NBXCFG, reg); 237 } 238 239 /* Clear Error status */ 240 switch (isc->chiptype) { 241 case CHIP_I840: 242 pci_conf_write(pa->pa_pc, pa->pa_tag, 243 AGP_INTEL_I8XX_ERRSTS, 0xc000); 244 break; 245 case CHIP_I845: 246 case CHIP_I850: 247 case CHIP_I865: 248 pci_conf_write(isc->isc_pc, isc->isc_tag, 249 AGP_INTEL_I8XX_ERRSTS, 0x00ff); 250 break; 251 252 default: 253 pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_ERRSTS, 0x70); 254 } 255 256 isc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &agp_intel_methods, 257 isc->isc_apaddr, isc->isc_apsize, &isc->dev); 258 return; 259 } 260 261 #if 0 262 int 263 agp_intel_detach(struct agp_softc *sc) 264 { 265 int error; 266 pcireg_t reg; 267 struct agp_intel_softc *isc = sc->sc_chipc; 268 269 error = agp_generic_detach(sc); 270 if (error) 271 return (error); 272 273 /* XXX i845/i855PM/i840/i850E */ 274 reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG); 275 reg &= ~(1 << 9); 276 printf("%s: set NBXCFG to %x\n", __FUNCTION__, reg); 277 pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG, reg); 278 pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_ATTBASE, 0); 279 AGP_SET_APERTURE(sc, isc->initial_aperture); 280 agp_free_gatt(sc, isc->gatt); 281 282 return (0); 283 } 284 #endif 285 286 bus_size_t 287 agp_intel_get_aperture(void *sc) 288 { 289 struct agp_intel_softc *isc = sc; 290 bus_size_t apsize; 291 292 apsize = pci_conf_read(isc->isc_pc, isc->isc_tag, 293 AGP_INTEL_APSIZE) & isc->aperture_mask; 294 295 /* 296 * The size is determined by the number of low bits of 297 * register APBASE which are forced to zero. The low 22 bits 298 * are always forced to zero and each zero bit in the apsize 299 * field just read forces the corresponding bit in the 27:22 300 * to be zero. We calculate the aperture size accordingly. 301 */ 302 return ((((apsize ^ isc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1); 303 } 304 305 int 306 agp_intel_set_aperture(void *sc, bus_size_t aperture) 307 { 308 struct agp_intel_softc *isc = sc; 309 bus_size_t apsize; 310 311 /* 312 * Reverse the magic from get_aperture. 313 */ 314 apsize = ((aperture - 1) >> 22) ^ isc->aperture_mask; 315 316 /* 317 * Double check for sanity. 318 */ 319 if ((((apsize ^ isc->aperture_mask) << 22) | 320 ((1 << 22) - 1)) + 1 != aperture) 321 return (EINVAL); 322 323 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_APSIZE, apsize); 324 325 return (0); 326 } 327 328 void 329 agp_intel_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags) 330 { 331 struct agp_intel_softc *isc = sc; 332 333 isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 334 physical | 0x17; 335 } 336 337 void 338 agp_intel_unbind_page(void *sc, bus_size_t offset) 339 { 340 struct agp_intel_softc *isc = sc; 341 342 isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 0; 343 } 344 345 void 346 agp_intel_flush_tlb(void *sc) 347 { 348 struct agp_intel_softc *isc = sc; 349 pcireg_t reg; 350 351 switch (isc->chiptype) { 352 case CHIP_I865: 353 case CHIP_I850: 354 case CHIP_I845: 355 case CHIP_I840: 356 case CHIP_I443: 357 reg = pci_conf_read(isc->isc_pc, isc->isc_tag, 358 AGP_INTEL_AGPCTRL); 359 reg &= ~AGPCTRL_GTLB; 360 pci_conf_write(isc->isc_pc, isc->isc_tag, 361 AGP_INTEL_AGPCTRL, reg); 362 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 363 reg | AGPCTRL_GTLB); 364 break; 365 default: /* XXX */ 366 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 367 0x2200); 368 pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL, 369 0x2280); 370 } 371 } 372